Object Mode Outline: Changed algorithm a bit.
First pass find outline pixel. Second pass expand it by 1px in each direction. Subsequent passes fade the occluded outlines inward.
This commit is contained in:
@@ -54,11 +54,13 @@ typedef struct OBJECT_PassList {
|
||||
struct DRWPass *non_meshes;
|
||||
struct DRWPass *ob_center;
|
||||
struct DRWPass *outlines;
|
||||
struct DRWPass *outlines_search;
|
||||
struct DRWPass *outlines_expand;
|
||||
struct DRWPass *outlines_blur1;
|
||||
struct DRWPass *outlines_blur2;
|
||||
struct DRWPass *outlines_blur3;
|
||||
struct DRWPass *outlines_blur4;
|
||||
struct DRWPass *outlines_fade1;
|
||||
struct DRWPass *outlines_fade2;
|
||||
struct DRWPass *outlines_fade3;
|
||||
struct DRWPass *outlines_fade4;
|
||||
struct DRWPass *outlines_fade5;
|
||||
struct DRWPass *outlines_resolve;
|
||||
struct DRWPass *bone_solid;
|
||||
struct DRWPass *bone_wire;
|
||||
@@ -149,7 +151,7 @@ static struct {
|
||||
|
||||
static struct {
|
||||
struct GPUShader *outline_resolve_sh;
|
||||
struct GPUShader *outline_expand_sh;
|
||||
struct GPUShader *outline_detect_sh;
|
||||
struct GPUShader *outline_fade_sh;
|
||||
} e_data = {NULL}; /* Engine data */
|
||||
|
||||
@@ -178,8 +180,8 @@ static void OBJECT_engine_init(void)
|
||||
e_data.outline_resolve_sh = DRW_shader_create_fullscreen(datatoc_object_outline_resolve_frag_glsl, NULL);
|
||||
}
|
||||
|
||||
if (!e_data.outline_expand_sh) {
|
||||
e_data.outline_expand_sh = DRW_shader_create_fullscreen(datatoc_object_outline_detect_frag_glsl, NULL);
|
||||
if (!e_data.outline_detect_sh) {
|
||||
e_data.outline_detect_sh = DRW_shader_create_fullscreen(datatoc_object_outline_detect_frag_glsl, NULL);
|
||||
}
|
||||
|
||||
if (!e_data.outline_fade_sh) {
|
||||
@@ -191,8 +193,8 @@ static void OBJECT_engine_free(void)
|
||||
{
|
||||
if (e_data.outline_resolve_sh)
|
||||
DRW_shader_free(e_data.outline_resolve_sh);
|
||||
if (e_data.outline_expand_sh)
|
||||
DRW_shader_free(e_data.outline_expand_sh);
|
||||
if (e_data.outline_detect_sh)
|
||||
DRW_shader_free(e_data.outline_detect_sh);
|
||||
if (e_data.outline_fade_sh)
|
||||
DRW_shader_free(e_data.outline_fade_sh);
|
||||
}
|
||||
@@ -233,46 +235,79 @@ static void OBJECT_cache_init(void)
|
||||
|
||||
{
|
||||
DRWState state = DRW_STATE_WRITE_COLOR;
|
||||
psl->outlines_expand = DRW_pass_create("Outlines Expand Pass", state);
|
||||
|
||||
struct Batch *quad = DRW_cache_fullscreen_quad_get();
|
||||
static float alphaOcclu = 0.35f;
|
||||
static float alphaNear = 0.75f;
|
||||
static float alphaFar = 0.5f;
|
||||
static float one = 1.0f;
|
||||
static float alpha1 = 5.0f / 6.0f;
|
||||
static float alpha2 = 4.0f / 5.0f;
|
||||
static float alpha3 = 3.0f / 4.0f;
|
||||
static float alpha4 = 2.0f / 3.0f;
|
||||
static float alpha5 = 1.0f / 2.0f;
|
||||
static bool bTrue = true;
|
||||
static bool bFalse = false;
|
||||
|
||||
DRWShadingGroup *grp = DRW_shgroup_create(e_data.outline_expand_sh, psl->outlines_expand);
|
||||
psl->outlines_search = DRW_pass_create("Outlines Expand Pass", state);
|
||||
|
||||
DRWShadingGroup *grp = DRW_shgroup_create(e_data.outline_detect_sh, psl->outlines_search);
|
||||
DRW_shgroup_uniform_buffer(grp, "outlineColor", &txl->outlines_color_tx, 0);
|
||||
DRW_shgroup_uniform_buffer(grp, "outlineDepth", &txl->outlines_depth_tx, 1);
|
||||
DRW_shgroup_uniform_buffer(grp, "sceneDepth", &dtxl->depth, 2);
|
||||
DRW_shgroup_uniform_float(grp, "alphaOcclu", &alphaOcclu, 1);
|
||||
DRW_shgroup_uniform_vec2(grp, "viewportSize", DRW_viewport_size_get(), 1);
|
||||
DRW_shgroup_call_add(grp, quad, NULL);
|
||||
|
||||
psl->outlines_blur1 = DRW_pass_create("Outlines Blur 1 Pass", state);
|
||||
psl->outlines_expand = DRW_pass_create("Outlines Expand Pass", state);
|
||||
|
||||
grp = DRW_shgroup_create(e_data.outline_fade_sh, psl->outlines_blur1);
|
||||
grp = DRW_shgroup_create(e_data.outline_fade_sh, psl->outlines_expand);
|
||||
DRW_shgroup_uniform_buffer(grp, "outlineColor", &txl->outlines_blur_tx, 0);
|
||||
DRW_shgroup_uniform_float(grp, "alpha", &alphaNear, 1);
|
||||
DRW_shgroup_uniform_buffer(grp, "outlineDepth", &txl->outlines_depth_tx, 1);
|
||||
DRW_shgroup_uniform_float(grp, "alpha", &one, 1);
|
||||
DRW_shgroup_uniform_bool(grp, "doExpand", &bTrue, 1);
|
||||
DRW_shgroup_call_add(grp, quad, NULL);
|
||||
|
||||
psl->outlines_blur2 = DRW_pass_create("Outlines Blur 2 Pass", state);
|
||||
psl->outlines_fade1 = DRW_pass_create("Outlines Fade 1 Pass", state);
|
||||
|
||||
grp = DRW_shgroup_create(e_data.outline_fade_sh, psl->outlines_blur2);
|
||||
grp = DRW_shgroup_create(e_data.outline_fade_sh, psl->outlines_fade1);
|
||||
DRW_shgroup_uniform_buffer(grp, "outlineColor", &txl->outlines_color_tx, 0);
|
||||
DRW_shgroup_uniform_float(grp, "alpha", &alphaNear, 1);
|
||||
DRW_shgroup_uniform_buffer(grp, "outlineDepth", &txl->outlines_depth_tx, 1);
|
||||
DRW_shgroup_uniform_float(grp, "alpha", &alpha1, 1);
|
||||
DRW_shgroup_uniform_bool(grp, "doExpand", &bFalse, 1);
|
||||
DRW_shgroup_call_add(grp, quad, NULL);
|
||||
|
||||
psl->outlines_blur3 = DRW_pass_create("Outlines Blur 3 Pass", state);
|
||||
psl->outlines_fade2 = DRW_pass_create("Outlines Fade 2 Pass", state);
|
||||
|
||||
grp = DRW_shgroup_create(e_data.outline_fade_sh, psl->outlines_blur3);
|
||||
grp = DRW_shgroup_create(e_data.outline_fade_sh, psl->outlines_fade2);
|
||||
DRW_shgroup_uniform_buffer(grp, "outlineColor", &txl->outlines_blur_tx, 0);
|
||||
DRW_shgroup_uniform_float(grp, "alpha", &alphaFar, 1);
|
||||
DRW_shgroup_uniform_buffer(grp, "outlineDepth", &txl->outlines_depth_tx, 1);
|
||||
DRW_shgroup_uniform_float(grp, "alpha", &alpha2, 1);
|
||||
DRW_shgroup_uniform_bool(grp, "doExpand", &bFalse, 1);
|
||||
DRW_shgroup_call_add(grp, quad, NULL);
|
||||
|
||||
psl->outlines_blur4 = DRW_pass_create("Outlines Blur 4 Pass", state);
|
||||
psl->outlines_fade3 = DRW_pass_create("Outlines Fade 3 Pass", state);
|
||||
|
||||
grp = DRW_shgroup_create(e_data.outline_fade_sh, psl->outlines_blur4);
|
||||
grp = DRW_shgroup_create(e_data.outline_fade_sh, psl->outlines_fade3);
|
||||
DRW_shgroup_uniform_buffer(grp, "outlineColor", &txl->outlines_color_tx, 0);
|
||||
DRW_shgroup_uniform_float(grp, "alpha", &alphaFar, 1);
|
||||
DRW_shgroup_uniform_buffer(grp, "outlineDepth", &txl->outlines_depth_tx, 1);
|
||||
DRW_shgroup_uniform_float(grp, "alpha", &alpha3, 1);
|
||||
DRW_shgroup_uniform_bool(grp, "doExpand", &bFalse, 1);
|
||||
DRW_shgroup_call_add(grp, quad, NULL);
|
||||
|
||||
psl->outlines_fade4 = DRW_pass_create("Outlines Fade 4 Pass", state);
|
||||
|
||||
grp = DRW_shgroup_create(e_data.outline_fade_sh, psl->outlines_fade4);
|
||||
DRW_shgroup_uniform_buffer(grp, "outlineColor", &txl->outlines_blur_tx, 0);
|
||||
DRW_shgroup_uniform_buffer(grp, "outlineDepth", &txl->outlines_depth_tx, 1);
|
||||
DRW_shgroup_uniform_float(grp, "alpha", &alpha4, 1);
|
||||
DRW_shgroup_uniform_bool(grp, "doExpand", &bFalse, 1);
|
||||
DRW_shgroup_call_add(grp, quad, NULL);
|
||||
|
||||
psl->outlines_fade5 = DRW_pass_create("Outlines Fade 5 Pass", state);
|
||||
|
||||
grp = DRW_shgroup_create(e_data.outline_fade_sh, psl->outlines_fade5);
|
||||
DRW_shgroup_uniform_buffer(grp, "outlineColor", &txl->outlines_color_tx, 0);
|
||||
DRW_shgroup_uniform_buffer(grp, "outlineDepth", &txl->outlines_depth_tx, 1);
|
||||
DRW_shgroup_uniform_float(grp, "alpha", &alpha5, 1);
|
||||
DRW_shgroup_uniform_bool(grp, "doExpand", &bFalse, 1);
|
||||
DRW_shgroup_call_add(grp, quad, NULL);
|
||||
}
|
||||
|
||||
@@ -284,7 +319,6 @@ static void OBJECT_cache_init(void)
|
||||
|
||||
DRWShadingGroup *grp = DRW_shgroup_create(e_data.outline_resolve_sh, psl->outlines_resolve);
|
||||
DRW_shgroup_uniform_buffer(grp, "outlineBluredColor", &txl->outlines_blur_tx, 0);
|
||||
DRW_shgroup_uniform_buffer(grp, "outlineDepth", &txl->outlines_depth_tx, 1);
|
||||
DRW_shgroup_call_add(grp, quad, NULL);
|
||||
}
|
||||
|
||||
@@ -743,39 +777,53 @@ static void OBJECT_draw_scene(void)
|
||||
OBJECT_Data *ved = DRW_viewport_engine_data_get("ObjectMode");
|
||||
OBJECT_PassList *psl = ved->psl;
|
||||
OBJECT_FramebufferList *fbl = ved->fbl;
|
||||
OBJECT_TextureList *txl = ved->txl;
|
||||
DefaultFramebufferList *dfbl = DRW_viewport_framebuffer_list_get();
|
||||
float clearcol[4] = {0.0f, 0.0f, 0.0f, 0.0f};
|
||||
|
||||
DRW_draw_pass(psl->bone_wire);
|
||||
DRW_draw_pass(psl->bone_solid);
|
||||
DRW_draw_pass(psl->non_meshes);
|
||||
DRW_draw_pass(psl->ob_center);
|
||||
|
||||
/* Render filled polygon on a separate framebuffer */
|
||||
DRW_framebuffer_bind(fbl->outlines);
|
||||
DRW_framebuffer_clear(true, true, false, clearcol, 1.0f);
|
||||
DRW_draw_pass(psl->outlines);
|
||||
|
||||
/* Expand filled color by 1px and modulate if occluded */
|
||||
/* detach textures */
|
||||
DRW_framebuffer_texture_detach(txl->outlines_depth_tx);
|
||||
|
||||
/* Search outline pixels */
|
||||
DRW_framebuffer_bind(fbl->blur);
|
||||
DRW_draw_pass(psl->outlines_expand);
|
||||
DRW_draw_pass(psl->outlines_search);
|
||||
|
||||
/* Expand and fade gradually */
|
||||
DRW_framebuffer_bind(fbl->outlines);
|
||||
DRW_draw_pass(psl->outlines_blur1);
|
||||
DRW_draw_pass(psl->outlines_expand);
|
||||
|
||||
DRW_framebuffer_bind(fbl->blur);
|
||||
DRW_draw_pass(psl->outlines_blur2);
|
||||
DRW_draw_pass(psl->outlines_fade1);
|
||||
|
||||
// DRW_framebuffer_bind(fbl->outlines);
|
||||
// DRW_draw_pass(psl->outlines_blur3);
|
||||
DRW_framebuffer_bind(fbl->outlines);
|
||||
DRW_draw_pass(psl->outlines_fade2);
|
||||
|
||||
// DRW_framebuffer_bind(fbl->blur);
|
||||
// DRW_draw_pass(psl->outlines_blur4);
|
||||
DRW_framebuffer_bind(fbl->blur);
|
||||
DRW_draw_pass(psl->outlines_fade3);
|
||||
|
||||
DRW_framebuffer_bind(fbl->outlines);
|
||||
DRW_draw_pass(psl->outlines_fade4);
|
||||
|
||||
DRW_framebuffer_bind(fbl->blur);
|
||||
DRW_draw_pass(psl->outlines_fade5);
|
||||
|
||||
/* reattach */
|
||||
DRW_framebuffer_texture_attach(fbl->outlines, txl->outlines_depth_tx, 0);
|
||||
|
||||
/* Combine with scene buffer */
|
||||
DRW_framebuffer_bind(dfbl->default_fb);
|
||||
DRW_draw_pass(psl->outlines_resolve);
|
||||
|
||||
/* This needs to be drawn after the oultine */
|
||||
DRW_draw_pass(psl->bone_wire);
|
||||
DRW_draw_pass(psl->bone_solid);
|
||||
DRW_draw_pass(psl->non_meshes);
|
||||
DRW_draw_pass(psl->ob_center);
|
||||
}
|
||||
|
||||
void OBJECT_collection_settings_create(CollectionEngineSettings *ces)
|
||||
|
||||
@@ -8,14 +8,24 @@ uniform sampler2D outlineDepth;
|
||||
uniform sampler2D sceneDepth;
|
||||
|
||||
uniform float alphaOcclu;
|
||||
uniform vec2 viewportSize;
|
||||
|
||||
void search_outline(ivec2 uv, ivec2 offset, vec4 ref_col, inout bool outline)
|
||||
void search_outline(ivec2 uv, ivec2 offset, vec4 ref_col, inout bool ref_occlu, inout bool outline)
|
||||
{
|
||||
if (!outline) {
|
||||
vec4 color = texelFetchOffset(outlineColor, uv, 0, offset).rgba;
|
||||
if (color != ref_col) {
|
||||
outline = true;
|
||||
}
|
||||
else {
|
||||
float depth = texelFetchOffset(outlineDepth, uv, 0, offset).r;
|
||||
float scene_depth = texelFetchOffset(sceneDepth, uv, 0, offset).r;
|
||||
bool occlu = (depth > scene_depth);
|
||||
|
||||
if (occlu != ref_occlu && !ref_occlu) {
|
||||
outline = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,25 +34,35 @@ void main()
|
||||
ivec2 uv = ivec2(gl_FragCoord.xy);
|
||||
vec4 ref_col = texelFetch(outlineColor, uv, 0).rgba;
|
||||
|
||||
float depth = texelFetch(outlineDepth, uv, 0).r;
|
||||
/* Modulate color if occluded */
|
||||
float scene_depth = texelFetch(sceneDepth, uv, 0).r;
|
||||
|
||||
bool ref_occlu = (depth > scene_depth);
|
||||
|
||||
bool outline = false;
|
||||
|
||||
search_outline(uv, ivec2( 1, 0), ref_col, outline);
|
||||
search_outline(uv, ivec2( 0, 1), ref_col, outline);
|
||||
search_outline(uv, ivec2(-1, 0), ref_col, outline);
|
||||
search_outline(uv, ivec2( 0, -1), ref_col, outline);
|
||||
if (float(uv.x) < viewportSize.x - 1.0)
|
||||
search_outline(uv, ivec2( 1, 0), ref_col, ref_occlu, outline);
|
||||
|
||||
if (float(uv.y) < viewportSize.x - 1.0)
|
||||
search_outline(uv, ivec2( 0, 1), ref_col, ref_occlu, outline);
|
||||
|
||||
if (float(uv.x) > 0)
|
||||
search_outline(uv, ivec2(-1, 0), ref_col, ref_occlu, outline);
|
||||
|
||||
if (float(uv.y) > 0)
|
||||
search_outline(uv, ivec2( 0, -1), ref_col, ref_occlu, outline);
|
||||
|
||||
FragColor = ref_col;
|
||||
|
||||
/* We Hit something ! */
|
||||
if (outline) {
|
||||
FragColor = ref_col;
|
||||
/* Modulate color if occluded */
|
||||
float depth = texelFetch(outlineDepth, uv, 0).r;
|
||||
float scene_depth = texelFetch(sceneDepth, uv, 0).r;
|
||||
/* TODO bias in linear depth not exponential */
|
||||
if (depth > scene_depth) {
|
||||
if (ref_occlu) {
|
||||
FragColor.a *= alphaOcclu;
|
||||
}
|
||||
}
|
||||
else {
|
||||
FragColor = vec4(0.0);
|
||||
FragColor.a = 0.0;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,66 +4,42 @@ in vec4 uvcoordsvar;
|
||||
out vec4 FragColor;
|
||||
|
||||
uniform sampler2D outlineColor;
|
||||
#ifdef DEPTH_TEST
|
||||
uniform sampler2D outlineDepth;
|
||||
uniform sampler2D sceneDepth;
|
||||
#endif
|
||||
|
||||
uniform float alpha;
|
||||
uniform bool doExpand;
|
||||
|
||||
#define ALPHA_OCCLU 0.4
|
||||
|
||||
void search_outline(ivec2 uv, ivec2 offset, inout float weight, inout vec4 col_accum)
|
||||
void search_outline(ivec2 uv, ivec2 offset, inout bool found_edge)
|
||||
{
|
||||
vec4 color = texelFetchOffset(outlineColor, uv, 0, offset).rgba;
|
||||
if (color.a != 0.0) {
|
||||
#ifdef DEPTH_TEST
|
||||
/* Modulate color if occluded */
|
||||
/* TODO bias in linear depth not exponential */
|
||||
float depth = texelFetchOffset(outlineDepth, uv, 0, offset).r;
|
||||
float scene_depth = texelFetchOffset(sceneDepth, uv, 0, offset).r;
|
||||
if (depth > scene_depth) {
|
||||
color *= ALPHA_OCCLU;
|
||||
if (!found_edge) {
|
||||
vec4 color = texelFetchOffset(outlineColor, uv, 0, offset).rgba;
|
||||
if (color.a != 0.0) {
|
||||
if (doExpand || color.a != 1.0) {
|
||||
FragColor = color;
|
||||
found_edge = true;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
col_accum += color;
|
||||
weight += 1.0;
|
||||
}
|
||||
}
|
||||
|
||||
void main()
|
||||
{
|
||||
ivec2 uv = ivec2(gl_FragCoord.xy);
|
||||
// vec2 uv = uvcoordsvar.xy + 0.5 / viewportSize;
|
||||
FragColor = texelFetch(outlineColor, uv, 0).rgba;
|
||||
float depth = texelFetch(outlineDepth, uv, 0).r;
|
||||
|
||||
if (FragColor.a != 0.0){
|
||||
#ifdef DEPTH_TEST
|
||||
/* Modulate color if occluded */
|
||||
float depth = texelFetch(outlineDepth, uv, 0).r;
|
||||
float scene_depth = texelFetch(sceneDepth, uv, 0).r;
|
||||
/* TODO bias in linear depth not exponential */
|
||||
if (depth > scene_depth) {
|
||||
FragColor *= ALPHA_OCCLU;
|
||||
}
|
||||
#endif
|
||||
if (FragColor.a != 0.0 || (depth == 1.0 && !doExpand))
|
||||
return;
|
||||
}
|
||||
|
||||
float weight = 0.0;
|
||||
vec4 col = vec4(0.0);
|
||||
|
||||
search_outline(uv, ivec2( 1, 0), weight, col);
|
||||
search_outline(uv, ivec2( 0, 1), weight, col);
|
||||
search_outline(uv, ivec2(-1, 0), weight, col);
|
||||
search_outline(uv, ivec2( 0, -1), weight, col);
|
||||
bool found_edge = false;
|
||||
search_outline(uv, ivec2( 1, 0), found_edge);
|
||||
search_outline(uv, ivec2( 0, 1), found_edge);
|
||||
search_outline(uv, ivec2(-1, 0), found_edge);
|
||||
search_outline(uv, ivec2( 0, -1), found_edge);
|
||||
|
||||
/* We Hit something ! */
|
||||
if (weight != 0.0) {
|
||||
FragColor = col / weight;
|
||||
if (found_edge) {
|
||||
/* only change alpha */
|
||||
FragColor.a *= alpha;
|
||||
}
|
||||
else {
|
||||
FragColor = vec4(0.0);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,14 +4,8 @@ in vec4 uvcoordsvar;
|
||||
out vec4 FragColor;
|
||||
|
||||
uniform sampler2D outlineBluredColor;
|
||||
uniform sampler2D outlineDepth;
|
||||
|
||||
void main()
|
||||
{
|
||||
FragColor = texture(outlineBluredColor, uvcoordsvar.st).rgba;
|
||||
|
||||
/* Modulate fill color */
|
||||
// float depth = texture(outlineDepth, uvcoordsvar.st).r;
|
||||
// if (depth != 1.0)
|
||||
// FragColor.a *= 0.1;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user