Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorClément Foucault <foucault.clem@gmail.com>2019-12-04 03:31:36 +0300
committerClément Foucault <foucault.clem@gmail.com>2019-12-05 00:32:17 +0300
commit6d3eb85f66ae93d9d4859ef3264f1a1b2ae4fa36 (patch)
treea18be546ae0daee539de83bcddea7ee4e2195e24 /source/blender/draw/engines
parente203f69bc3eb0c3c77820d54821c2e71469f36d1 (diff)
Overlay Engine: Simplify outline rendering by using the antialiasing pass
This use the overlay AA pass to antialias the selection outlines. This also do all search and expand in one pass and reduce the computation time and memory used (2 x 32bit/pixel buffer less). Note that the aliasing is a bit worse than the old FXAA that we used to have.
Diffstat (limited to 'source/blender/draw/engines')
-rw-r--r--source/blender/draw/engines/overlay/overlay_antialiasing.c6
-rw-r--r--source/blender/draw/engines/overlay/overlay_engine.c35
-rw-r--r--source/blender/draw/engines/overlay/overlay_outline.c84
-rw-r--r--source/blender/draw/engines/overlay/overlay_private.h14
-rw-r--r--source/blender/draw/engines/overlay/overlay_shader.c58
-rw-r--r--source/blender/draw/engines/overlay/shaders/antialiasing_frag.glsl4
-rw-r--r--source/blender/draw/engines/overlay/shaders/outline_detect_frag.glsl349
-rw-r--r--source/blender/draw/engines/overlay/shaders/outline_expand_frag.glsl51
-rw-r--r--source/blender/draw/engines/overlay/shaders/outline_resolve_frag.glsl21
9 files changed, 346 insertions, 276 deletions
diff --git a/source/blender/draw/engines/overlay/overlay_antialiasing.c b/source/blender/draw/engines/overlay/overlay_antialiasing.c
index 569d47bf3a2..8f357d37768 100644
--- a/source/blender/draw/engines/overlay/overlay_antialiasing.c
+++ b/source/blender/draw/engines/overlay/overlay_antialiasing.c
@@ -60,12 +60,6 @@
#include "overlay_private.h"
-void OVERLAY_antialiasing_reset(OVERLAY_Data *vedata)
-{
- OVERLAY_PrivateData *pd = vedata->stl->pd;
- pd->antialiasing.sample = 0;
-}
-
void OVERLAY_antialiasing_init(OVERLAY_Data *vedata)
{
OVERLAY_FramebufferList *fbl = vedata->fbl;
diff --git a/source/blender/draw/engines/overlay/overlay_engine.c b/source/blender/draw/engines/overlay/overlay_engine.c
index e83a5c04eaf..24e2c4441e3 100644
--- a/source/blender/draw/engines/overlay/overlay_engine.c
+++ b/source/blender/draw/engines/overlay/overlay_engine.c
@@ -50,37 +50,27 @@ static void OVERLAY_engine_init(void *vedata)
}
OVERLAY_PrivateData *pd = stl->pd;
- View3DOverlay overlay;
- short v3d_flag, v3d_gridflag;
pd->hide_overlays = (v3d->flag2 & V3D_HIDE_OVERLAYS) != 0;
pd->ctx_mode = CTX_data_mode_enum_ex(
draw_ctx->object_edit, draw_ctx->obact, draw_ctx->object_mode);
if (!pd->hide_overlays) {
- overlay = v3d->overlay;
- v3d_flag = v3d->flag;
- v3d_gridflag = v3d->gridflag;
+ pd->overlay = v3d->overlay;
+ pd->v3d_flag = v3d->flag;
+ pd->v3d_gridflag = v3d->gridflag;
}
else {
- memset(&overlay, 0, sizeof(overlay));
- v3d_flag = 0;
- v3d_gridflag = 0;
- overlay.flag = V3D_OVERLAY_HIDE_TEXT | V3D_OVERLAY_HIDE_MOTION_PATHS | V3D_OVERLAY_HIDE_BONES |
- V3D_OVERLAY_HIDE_OBJECT_XTRAS | V3D_OVERLAY_HIDE_OBJECT_ORIGINS;
+ memset(&pd->overlay, 0, sizeof(pd->overlay));
+ pd->v3d_flag = 0;
+ pd->v3d_gridflag = 0;
+ pd->overlay.flag = V3D_OVERLAY_HIDE_TEXT | V3D_OVERLAY_HIDE_MOTION_PATHS |
+ V3D_OVERLAY_HIDE_BONES | V3D_OVERLAY_HIDE_OBJECT_XTRAS |
+ V3D_OVERLAY_HIDE_OBJECT_ORIGINS;
}
if (v3d->shading.type == OB_WIRE) {
- overlay.flag |= V3D_OVERLAY_WIREFRAMES;
- }
-
- /* Check if anything changed, and if so, reset AA. */
- if (v3d_flag != pd->v3d_flag || pd->v3d_gridflag != v3d_gridflag ||
- memcmp(&pd->overlay, &overlay, sizeof(overlay))) {
- pd->overlay = overlay;
- pd->v3d_flag = v3d_flag;
- pd->v3d_gridflag = v3d_gridflag;
- OVERLAY_antialiasing_reset(vedata);
+ pd->overlay.flag |= V3D_OVERLAY_WIREFRAMES;
}
pd->wireframe_mode = (v3d->shading.type == OB_WIRE);
@@ -376,6 +366,9 @@ static void OVERLAY_draw_scene(void *vedata)
OVERLAY_antialiasing_start(vedata);
+ DRW_view_set_active(NULL);
+ OVERLAY_outline_draw(vedata);
+
DRW_view_set_active(pd->view_default);
OVERLAY_image_draw(vedata);
@@ -387,9 +380,7 @@ static void OVERLAY_draw_scene(void *vedata)
OVERLAY_extra_draw(vedata);
DRW_view_set_active(NULL);
-
OVERLAY_grid_draw(vedata);
- OVERLAY_outline_draw(vedata);
DRW_view_set_active(pd->view_default);
diff --git a/source/blender/draw/engines/overlay/overlay_outline.c b/source/blender/draw/engines/overlay/overlay_outline.c
index cb5344630c3..706dcc95288 100644
--- a/source/blender/draw/engines/overlay/overlay_outline.c
+++ b/source/blender/draw/engines/overlay/overlay_outline.c
@@ -32,23 +32,28 @@ void OVERLAY_outline_init(OVERLAY_Data *vedata)
{
OVERLAY_FramebufferList *fbl = vedata->fbl;
OVERLAY_TextureList *txl = vedata->txl;
+ OVERLAY_PrivateData *pd = vedata->stl->pd;
+ DefaultTextureList *dtxl = DRW_viewport_texture_list_get();
if (DRW_state_is_fbo()) {
/* TODO only alloc if needed. */
- /* XXX TODO GPU_R16UI can overflow, it would cause no harm
- * (only bad colored or missing outlines) but we should
- * use 32bits only if the scene have that many objects */
DRW_texture_ensure_fullscreen_2d(&txl->temp_depth_tx, GPU_DEPTH24_STENCIL8, 0);
DRW_texture_ensure_fullscreen_2d(&txl->outlines_id_tx, GPU_R16UI, 0);
+
GPU_framebuffer_ensure_config(
&fbl->outlines_prepass_fb,
{GPU_ATTACHMENT_TEXTURE(txl->temp_depth_tx), GPU_ATTACHMENT_TEXTURE(txl->outlines_id_tx)});
- for (int i = 0; i < 2; i++) {
- DRW_texture_ensure_fullscreen_2d(&txl->outlines_color_tx[i], GPU_RGBA8, DRW_TEX_FILTER);
+ if (pd->antialiasing.enabled) {
+ GPU_framebuffer_ensure_config(&fbl->outlines_resolve_fb,
+ {GPU_ATTACHMENT_NONE,
+ GPU_ATTACHMENT_TEXTURE(txl->overlay_color_tx),
+ GPU_ATTACHMENT_TEXTURE(txl->overlay_line_tx)});
+ }
+ else {
GPU_framebuffer_ensure_config(
- &fbl->outlines_process_fb[i],
- {GPU_ATTACHMENT_NONE, GPU_ATTACHMENT_TEXTURE(txl->outlines_color_tx[i])});
+ &fbl->outlines_resolve_fb,
+ {GPU_ATTACHMENT_TEXTURE(txl->temp_depth_tx), GPU_ATTACHMENT_TEXTURE(dtxl->color)});
}
}
}
@@ -133,9 +138,8 @@ void OVERLAY_outline_cache_init(OVERLAY_Data *vedata)
DRWShadingGroup *grp = NULL;
const float outline_width = UI_GetThemeValuef(TH_OUTLINE_WIDTH);
- const bool do_outline_expand = (U.pixelsize > 1.0) || (outline_width > 2.0f);
- const bool do_large_expand = ((U.pixelsize > 1.0) && (outline_width > 2.0f)) ||
- (outline_width > 4.0f);
+ const bool do_expand = (U.pixelsize > 1.0) || (outline_width > 2.0f);
+
{
DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL;
DRW_PASS_CREATE(psl->outlines_prepass_ps, state | pd->clipping_state);
@@ -164,50 +168,22 @@ void OVERLAY_outline_cache_init(OVERLAY_Data *vedata)
}
{
- DRW_PASS_CREATE(psl->outlines_detect_ps, DRW_STATE_WRITE_COLOR);
- DRW_PASS_CREATE(psl->outlines_expand_ps, DRW_STATE_WRITE_COLOR);
- DRW_PASS_CREATE(psl->outlines_bleed_ps, DRW_STATE_WRITE_COLOR);
- DRW_PASS_CREATE(psl->outlines_resolve_ps, DRW_STATE_WRITE_COLOR | DRW_STATE_BLEND_ALPHA);
+ /* We can only do alpha blending with lineOutput just after clearing the buffer. */
+ DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_BLEND_ALPHA_PREMUL;
+ DRW_PASS_CREATE(psl->outlines_detect_ps, state);
- GPUShader *sh = OVERLAY_shader_outline_detect(pd->xray_enabled_and_not_wire);
+ GPUShader *sh = OVERLAY_shader_outline_detect();
grp = DRW_shgroup_create(sh, psl->outlines_detect_ps);
/* Don't occlude the "outline" detection pass if in xray mode (too much flickering). */
- DRW_shgroup_uniform_float_copy(grp, "alphaOcclu", (pd->xray_enabled) ? 1.0f : 0.35f);
+ DRW_shgroup_uniform_float_copy(grp, "alphaOcclu", (pd->xray_enabled) ? 1.0f : 0.125f);
+ DRW_shgroup_uniform_bool_copy(grp, "doThickOutlines", do_expand);
+ DRW_shgroup_uniform_bool_copy(grp, "isXrayWires", pd->xray_enabled_and_not_wire);
DRW_shgroup_uniform_texture_ref(grp, "outlineId", &txl->outlines_id_tx);
- DRW_shgroup_uniform_texture_ref(grp, "outlineDepth", &txl->temp_depth_tx);
DRW_shgroup_uniform_texture_ref(grp, "sceneDepth", &dtxl->depth);
+ DRW_shgroup_uniform_texture_ref(grp, "outlineDepth", &txl->temp_depth_tx);
DRW_shgroup_uniform_block(grp, "globalsBlock", G_draw.block_ubo);
DRW_shgroup_call_procedural_triangles(grp, NULL, 1);
-
- if (do_outline_expand) {
- sh = OVERLAY_shader_outline_expand(do_large_expand);
- grp = DRW_shgroup_create(sh, psl->outlines_expand_ps);
- DRW_shgroup_uniform_texture_ref(grp, "outlineColor", &txl->outlines_color_tx[0]);
- DRW_shgroup_uniform_bool_copy(grp, "doExpand", true);
- DRW_shgroup_call_procedural_triangles(grp, NULL, 1);
-
- sh = OVERLAY_shader_outline_expand(false);
- grp = DRW_shgroup_create(sh, psl->outlines_bleed_ps);
- DRW_shgroup_uniform_texture_ref(grp, "outlineColor", &txl->outlines_color_tx[1]);
- DRW_shgroup_uniform_bool_copy(grp, "doExpand", false);
- DRW_shgroup_call_procedural_triangles(grp, NULL, 1);
- }
- else {
- sh = OVERLAY_shader_outline_expand(false);
- grp = DRW_shgroup_create(sh, psl->outlines_expand_ps);
- DRW_shgroup_uniform_texture_ref(grp, "outlineColor", &txl->outlines_color_tx[0]);
- DRW_shgroup_uniform_bool_copy(grp, "doExpand", false);
- DRW_shgroup_call_procedural_triangles(grp, NULL, 1);
- }
-
- GPUTexture **outline_tx = &txl->outlines_color_tx[do_outline_expand ? 0 : 1];
- sh = OVERLAY_shader_outline_resolve();
-
- grp = DRW_shgroup_create(sh, psl->outlines_resolve_ps);
- DRW_shgroup_uniform_texture_ref(grp, "outlineBluredColor", outline_tx);
- DRW_shgroup_uniform_vec2_copy(grp, "rcpDimensions", DRW_viewport_invert_size_get());
- DRW_shgroup_call_procedural_triangles(grp, NULL, 1);
}
}
@@ -331,25 +307,13 @@ void OVERLAY_outline_draw(OVERLAY_Data *vedata)
/* Render filled polygon on a separate framebuffer */
GPU_framebuffer_bind(fbl->outlines_prepass_fb);
- GPU_framebuffer_clear_color_depth(fbl->outlines_prepass_fb, clearcol, 1.0f);
+ GPU_framebuffer_clear_color_depth_stencil(fbl->outlines_prepass_fb, clearcol, 1.0f, 0x00);
DRW_draw_pass(psl->outlines_prepass_ps);
/* Search outline pixels */
- GPU_framebuffer_bind(fbl->outlines_process_fb[0]);
+ GPU_framebuffer_bind(fbl->outlines_resolve_fb);
DRW_draw_pass(psl->outlines_detect_ps);
- /* Expand outline to form a 3px wide line */
- GPU_framebuffer_bind(fbl->outlines_process_fb[1]);
- DRW_draw_pass(psl->outlines_expand_ps);
-
- /* Bleed color so the AA can do it's stuff */
- GPU_framebuffer_bind(fbl->outlines_process_fb[0]);
- DRW_draw_pass(psl->outlines_bleed_ps);
-
- /* restore main framebuffer */
- GPU_framebuffer_bind(fbl->overlay_default_fb);
- DRW_draw_pass(psl->outlines_resolve_ps);
-
DRW_stats_group_end();
}
else if (DRW_state_is_select()) {
diff --git a/source/blender/draw/engines/overlay/overlay_private.h b/source/blender/draw/engines/overlay/overlay_private.h
index 6b030b65ac0..5b25a473528 100644
--- a/source/blender/draw/engines/overlay/overlay_private.h
+++ b/source/blender/draw/engines/overlay/overlay_private.h
@@ -35,16 +35,14 @@ typedef struct OVERLAY_FramebufferList {
struct GPUFrameBuffer *overlay_color_only_fb;
struct GPUFrameBuffer *overlay_in_front_fb;
struct GPUFrameBuffer *outlines_prepass_fb;
- struct GPUFrameBuffer *outlines_process_fb[2];
+ struct GPUFrameBuffer *outlines_resolve_fb;
} OVERLAY_FramebufferList;
typedef struct OVERLAY_TextureList {
struct GPUTexture *temp_depth_tx;
struct GPUTexture *dummy_depth_tx;
struct GPUTexture *outlines_id_tx;
- struct GPUTexture *outlines_color_tx[2];
struct GPUTexture *overlay_color_tx;
- struct GPUTexture *overlay_color_history_tx;
struct GPUTexture *overlay_line_tx;
struct GPUTexture *edit_mesh_occlude_wire_tx;
} OVERLAY_TextureList;
@@ -87,8 +85,6 @@ typedef struct OVERLAY_PassList {
DRWPass *motion_paths_ps;
DRWPass *outlines_prepass_ps;
DRWPass *outlines_detect_ps;
- DRWPass *outlines_expand_ps;
- DRWPass *outlines_bleed_ps;
DRWPass *outlines_resolve_ps;
DRWPass *paint_color_ps;
DRWPass *paint_overlay_ps;
@@ -278,9 +274,6 @@ typedef struct OVERLAY_PrivateData {
OVERLAY_ShadingData shdata;
struct {
- short sample;
- short target_sample;
- float prev_persmat[4][4];
bool enabled;
} antialiasing;
struct {
@@ -388,7 +381,6 @@ BLI_INLINE void pack_fl_in_mat4(float rmat[4][4], const float mat[4][4], float a
rmat[3][3] = a;
}
-void OVERLAY_antialiasing_reset(OVERLAY_Data *vedata);
void OVERLAY_antialiasing_init(OVERLAY_Data *vedata);
void OVERLAY_antialiasing_cache_init(OVERLAY_Data *vedata);
void OVERLAY_antialiasing_cache_finish(OVERLAY_Data *vedata);
@@ -562,9 +554,7 @@ GPUShader *OVERLAY_shader_motion_path_vert(void);
GPUShader *OVERLAY_shader_uniform_color(void);
GPUShader *OVERLAY_shader_outline_prepass(bool use_wire);
GPUShader *OVERLAY_shader_outline_prepass_grid(void);
-GPUShader *OVERLAY_shader_outline_resolve(void);
-GPUShader *OVERLAY_shader_outline_expand(bool high_dpi);
-GPUShader *OVERLAY_shader_outline_detect(bool use_wire);
+GPUShader *OVERLAY_shader_outline_detect(void);
GPUShader *OVERLAY_shader_paint_face(void);
GPUShader *OVERLAY_shader_paint_point(void);
GPUShader *OVERLAY_shader_paint_texture(void);
diff --git a/source/blender/draw/engines/overlay/overlay_shader.c b/source/blender/draw/engines/overlay/overlay_shader.c
index 3f702a00bcd..db1d97544c0 100644
--- a/source/blender/draw/engines/overlay/overlay_shader.c
+++ b/source/blender/draw/engines/overlay/overlay_shader.c
@@ -80,12 +80,10 @@ extern char datatoc_motion_path_line_vert_glsl[];
extern char datatoc_motion_path_line_geom_glsl[];
extern char datatoc_motion_path_point_vert_glsl[];
extern char datatoc_outline_detect_frag_glsl[];
-extern char datatoc_outline_expand_frag_glsl[];
extern char datatoc_outline_prepass_frag_glsl[];
extern char datatoc_outline_prepass_geom_glsl[];
extern char datatoc_outline_prepass_vert_glsl[];
extern char datatoc_outline_lightprobe_grid_vert_glsl[];
-extern char datatoc_outline_resolve_frag_glsl[];
extern char datatoc_paint_face_vert_glsl[];
extern char datatoc_paint_point_vert_glsl[];
extern char datatoc_paint_texture_frag_glsl[];
@@ -159,11 +157,7 @@ typedef struct OVERLAY_Shaders {
GPUShader *outline_prepass;
GPUShader *outline_prepass_wire;
GPUShader *outline_prepass_lightprobe_grid;
- GPUShader *outline_resolve;
- GPUShader *outline_fade;
- GPUShader *outline_fade_large;
GPUShader *outline_detect;
- GPUShader *outline_detect_wire;
GPUShader *paint_face;
GPUShader *paint_point;
GPUShader *paint_texture;
@@ -941,51 +935,19 @@ GPUShader *OVERLAY_shader_outline_prepass_grid(void)
return sh_data->outline_prepass_lightprobe_grid;
}
-GPUShader *OVERLAY_shader_outline_resolve(void)
+GPUShader *OVERLAY_shader_outline_detect(void)
{
OVERLAY_Shaders *sh_data = &e_data.sh_data[0];
- if (!sh_data->outline_resolve) {
- sh_data->outline_resolve = DRW_shader_create_with_lib(datatoc_common_fullscreen_vert_glsl,
- NULL,
- datatoc_outline_resolve_frag_glsl,
- datatoc_common_fxaa_lib_glsl,
- "#define FXAA_ALPHA\n"
- "#define USE_FXAA\n");
- }
- return sh_data->outline_resolve;
-}
-
-GPUShader *OVERLAY_shader_outline_expand(bool high_dpi)
-{
- OVERLAY_Shaders *sh_data = &e_data.sh_data[0];
- if (high_dpi && !sh_data->outline_fade_large) {
- sh_data->outline_fade_large = DRW_shader_create_fullscreen(datatoc_outline_expand_frag_glsl,
- "#define LARGE_OUTLINE\n");
- }
- else if (!sh_data->outline_fade) {
- sh_data->outline_fade = DRW_shader_create_fullscreen(datatoc_outline_expand_frag_glsl, NULL);
- }
- return (high_dpi) ? sh_data->outline_fade_large : sh_data->outline_fade;
-}
-
-GPUShader *OVERLAY_shader_outline_detect(bool use_wire)
-{
- OVERLAY_Shaders *sh_data = &e_data.sh_data[0];
- if (use_wire && !sh_data->outline_detect_wire) {
- sh_data->outline_detect_wire = DRW_shader_create_with_lib(datatoc_common_fullscreen_vert_glsl,
- NULL,
- datatoc_outline_detect_frag_glsl,
- datatoc_common_globals_lib_glsl,
- "#define WIRE\n");
- }
- else if (!sh_data->outline_detect) {
- sh_data->outline_detect = DRW_shader_create_with_lib(datatoc_common_fullscreen_vert_glsl,
- NULL,
- datatoc_outline_detect_frag_glsl,
- datatoc_common_globals_lib_glsl,
- NULL);
+ if (!sh_data->outline_detect) {
+ sh_data->outline_detect = GPU_shader_create_from_arrays({
+ .vert = (const char *[]){datatoc_common_fullscreen_vert_glsl, NULL},
+ .frag = (const char *[]){datatoc_common_view_lib_glsl,
+ datatoc_common_globals_lib_glsl,
+ datatoc_outline_detect_frag_glsl,
+ NULL},
+ });
}
- return (use_wire) ? sh_data->outline_detect_wire : sh_data->outline_detect;
+ return sh_data->outline_detect;
}
GPUShader *OVERLAY_shader_paint_face(void)
diff --git a/source/blender/draw/engines/overlay/shaders/antialiasing_frag.glsl b/source/blender/draw/engines/overlay/shaders/antialiasing_frag.glsl
index 46a2afc42fd..386e6d9e141 100644
--- a/source/blender/draw/engines/overlay/shaders/antialiasing_frag.glsl
+++ b/source/blender/draw/engines/overlay/shaders/antialiasing_frag.glsl
@@ -96,6 +96,8 @@ void main()
fragColor = texelFetch(colorTex, center_texel, 0);
+ bool original_col_has_alpha = fragColor.a < 1.0;
+
float depth = texelFetch(depthTex, center_texel, 0).r;
float dist_raw = texelFetch(lineTex, center_texel, 0).b;
@@ -138,7 +140,7 @@ void main()
#if 1
/* Fix aliasing issue with really dense meshes and 1 pixel sized lines. */
- if (dist_raw > 0.0 && line_kernel < 0.45) {
+ if (!original_col_has_alpha && dist_raw > 0.0 && line_kernel < 0.45) {
vec4 lines = vec4(neightbor_line0.z, neightbor_line1.z, neightbor_line2.z, neightbor_line3.z);
/* Count number of line neighbors. */
float blend = dot(vec4(0.25), step(0.001, lines));
diff --git a/source/blender/draw/engines/overlay/shaders/outline_detect_frag.glsl b/source/blender/draw/engines/overlay/shaders/outline_detect_frag.glsl
index 79c970adfe0..6b4d424c700 100644
--- a/source/blender/draw/engines/overlay/shaders/outline_detect_frag.glsl
+++ b/source/blender/draw/engines/overlay/shaders/outline_detect_frag.glsl
@@ -1,86 +1,325 @@
-in vec4 uvcoordsvar;
-
-out vec4 FragColor;
-
+uniform float alphaOcclu;
+uniform bool isXrayWires;
+uniform bool doThickOutlines;
uniform usampler2D outlineId;
uniform sampler2D outlineDepth;
uniform sampler2D sceneDepth;
-uniform float alphaOcclu;
+in vec4 uvcoordsvar;
-void main()
-{
- ivec2 texel = ivec2(gl_FragCoord.xy);
+layout(location = 0) out vec4 fragColor;
+layout(location = 1) out vec4 lineOutput;
-#ifdef GPU_ARB_texture_gather
- vec2 texel_size = 1.0 / vec2(textureSize(outlineId, 0).xy);
- vec2 uv = ceil(gl_FragCoord.xy) * texel_size;
+#define XPOS 1
+#define XNEG 2
+#define YPOS 4
+#define YNEG 8
+
+#define ALL (XPOS | XNEG | YPOS | YNEG)
+#define NONE 0
+
+#define DIAG_XNEG_YPOS (XNEG | YPOS)
+#define DIAG_XPOS_YPOS (XPOS | YPOS)
+#define DIAG_XPOS_YNEG (XPOS | YNEG)
+#define DIAG_XNEG_YNEG (XNEG | YNEG)
- /* Samples order is CW starting from top left. */
- uvec4 tmp1 = textureGather(outlineId, uv - texel_size);
- uvec4 tmp2 = textureGather(outlineId, uv);
+#define APEX_XPOS (ALL & (~XPOS))
+#define APEX_XNEG (ALL & (~XNEG))
+#define APEX_YPOS (ALL & (~YPOS))
+#define APEX_YNEG (ALL & (~YNEG))
- uint ref_id = tmp1.y;
- uvec4 id = uvec4(tmp1.xz, tmp2.xz);
+bool has_edge(uint id, vec2 uv, uint ref, inout uint ref_col, inout vec2 depth_uv)
+{
+ if (ref_col == 0u) {
+ /* Make outline bleed on the background. */
+ ref_col = id;
+ depth_uv = uv;
+ }
+ return (id != ref);
+}
+
+/* A gather4 + check against ref. */
+bvec4 gather_edges(vec2 uv, uint ref)
+{
+ uvec4 ids;
+#ifdef GPU_ARB_texture_gather
+ ids = textureGather(outlineId, uv);
#else
- uvec4 id;
- uint ref_id = texelFetch(outlineId, texel, 0).r;
- id.x = texelFetchOffset(outlineId, texel, 0, ivec2(-1, 0)).r;
- id.y = texelFetchOffset(outlineId, texel, 0, ivec2(0, -1)).r;
- id.z = texelFetchOffset(outlineId, texel, 0, ivec2(0, 1)).r;
- id.w = texelFetchOffset(outlineId, texel, 0, ivec2(1, 0)).r;
+ vec3 ofs = vec3(0.5, 0.5, -0.5) * sizeViewportInv.xyy;
+ ids.x = textureLod(outlineId, uv - ofs.xz, 0.0).r;
+ ids.y = textureLod(outlineId, uv + ofs.xy, 0.0).r;
+ ids.z = textureLod(outlineId, uv + ofs.xz, 0.0).r;
+ ids.w = textureLod(outlineId, uv - ofs.xy, 0.0).r;
#endif
-#ifdef WIRE
- /* We want only 2px outlines. */
- /* TODO optimize, don't sample if we don't need to. */
- id.xy = uvec2(ref_id);
-#endif
+ return notEqual(ids, uvec4(ref));
+}
+
+/* Apply offset to line endpoint based on surrounding edges infos. */
+bool line_offset(bvec2 edges, vec2 ofs, inout vec2 line_point)
+{
+ if (all(edges.xy)) {
+ line_point.y -= ofs.y;
+ }
+ else if (!edges.x) {
+ line_point.y += ofs.y;
+ }
+ else /* !edges.y */ {
+ line_point.x += ofs.x;
+ return true;
+ }
+ return false;
+}
+
+/* Changes Antialiasing pattern and makes line thicker. 0.0 is thin. */
+#define PROXIMITY_OFS -0.35
+
+/* Use surrounding edges to approximate the outline direction to create smooth lines. */
+void straight_line_dir(bvec4 edges1, bvec4 edges2, out vec2 line_start, out vec2 line_end)
+{
+ line_end = vec2(1.5, 0.5 + PROXIMITY_OFS);
+ line_start = vec2(-line_end.x, line_end.y);
+
+ vec2 line_ofs = vec2(1.0, 0.5);
+ if (line_offset(edges1.xw, line_ofs, line_end)) {
+ line_offset(edges1.yz, line_ofs, line_end);
+ }
+ line_ofs = vec2(-line_ofs.x, line_ofs.y);
+ if (line_offset(edges2.yz, line_ofs, line_start)) {
+ line_offset(edges2.xw, line_ofs, line_start);
+ }
+}
+
+/* Compute line direction vector from the bottom left corner. */
+void diag_dir(bvec4 edges, out vec2 line_start, out vec2 line_end)
+{
+ /* TODO Improve diagonal antialiasing. */
+ if (all(edges.wz)) {
+ line_start = vec2(-3.0, -0.5 + PROXIMITY_OFS);
+ line_end = vec2(3.0, 0.5 + PROXIMITY_OFS);
+ }
+ else if (all(not(edges.xw))) {
+ line_start = vec2(-0.5 - PROXIMITY_OFS, -3.0);
+ line_end = vec2(0.5 - PROXIMITY_OFS, 3.0);
+ }
+ else if (edges.w) {
+ line_start = vec2(-1.0, -0.5 - PROXIMITY_OFS);
+ line_end = vec2(2.0, 0.5 - PROXIMITY_OFS);
+ }
+ else {
+ line_start = vec2(-0.6, -0.5 + PROXIMITY_OFS);
+ line_end = vec2(0.6 - PROXIMITY_OFS, 0.5);
+ }
+}
+/* Clockwise */
+vec2 rotate_90(vec2 v)
+{
+ return vec2(v.y, -v.x);
+}
+vec2 rotate_180(vec2 v)
+{
+ return vec2(-v.x, -v.y);
+}
+vec2 rotate_270(vec2 v)
+{
+ return vec2(-v.y, v.x);
+}
- bool outline = any(notEqual(id, uvec4(ref_id)));
+/* Counter-Clockwise */
+bvec4 rotate_90(bvec4 v)
+{
+ return v.yzwx;
+}
+bvec4 rotate_180(bvec4 v)
+{
+ return v.zwxy;
+}
+bvec4 rotate_270(bvec4 v)
+{
+ return v.wxyz;
+}
- ivec2 depth_texel = texel;
- /* If texel is an outline but has no valid id ...
- * replace id and depth texel by a valid one.
- * This keeps the outline thickness consistent everywhere. */
- if (ref_id == 0u && outline) {
- depth_texel = (id.x != 0u) ? texel + ivec2(-1, 0) : depth_texel;
- depth_texel = (id.y != 0u) ? texel + ivec2(0, -1) : depth_texel;
- depth_texel = (id.z != 0u) ? texel + ivec2(0, 1) : depth_texel;
- depth_texel = (id.w != 0u) ? texel + ivec2(1, 0) : depth_texel;
+void main()
+{
+ uint ref = textureLod(outlineId, uvcoordsvar.st, 0.0).r;
+ uint ref_col = ref;
+
+ vec2 uvs = gl_FragCoord.xy * sizeViewportInv.xy;
+ vec3 ofs = vec3(1.0, 1.0, 0.0) * sizeViewportInv.xyy;
- ref_id = (id.x != 0u) ? id.x : ref_id;
- ref_id = (id.y != 0u) ? id.y : ref_id;
- ref_id = (id.z != 0u) ? id.z : ref_id;
- ref_id = (id.w != 0u) ? id.w : ref_id;
+ vec2 depth_uv = uvs;
+
+ uvec4 ids;
+#ifdef GPU_ARB_texture_gather
+ /* Reminder: Samples order is CW starting from top left. */
+ uvec2 tmp1, tmp2, tmp3, tmp4;
+ if (doThickOutlines) {
+ tmp1 = textureGather(outlineId, uvs + ofs.xy * vec2(1.5, -0.5)).xy;
+ tmp2 = textureGather(outlineId, uvs + ofs.xy * vec2(-1.5, -0.5)).yx;
+ tmp3 = textureGather(outlineId, uvs + ofs.xy * vec2(0.5, 1.5)).wx;
+ tmp4 = textureGather(outlineId, uvs + ofs.xy * vec2(0.5, -1.5)).xw;
+ ids.x = tmp1.x;
+ ids.y = tmp2.x;
+ ids.z = tmp3.x;
+ ids.w = tmp4.x;
}
+ else {
+ ids.xz = textureGather(outlineId, uvs + ofs.xy * 0.5).zx;
+ ids.yw = textureGather(outlineId, uvs - ofs.xy * 0.5).xz;
+ }
+#else
+ ids.x = textureLod(outlineId, uvs + ofs.xz, 0.0).r;
+ ids.y = textureLod(outlineId, uvs - ofs.xz, 0.0).r;
+ ids.z = textureLod(outlineId, uvs + ofs.zy, 0.0).r;
+ ids.w = textureLod(outlineId, uvs - ofs.zy, 0.0).r;
+#endif
- float ref_depth = texelFetch(outlineDepth, depth_texel, 0).r;
- float scene_depth = texelFetch(sceneDepth, depth_texel, 0).r;
+ bool has_edge_pos_x = has_edge(ids.x, uvs + ofs.xz, ref, ref_col, depth_uv);
+ bool has_edge_neg_x = has_edge(ids.y, uvs - ofs.xz, ref, ref_col, depth_uv);
+ bool has_edge_pos_y = has_edge(ids.z, uvs + ofs.zy, ref, ref_col, depth_uv);
+ bool has_edge_neg_y = has_edge(ids.w, uvs - ofs.zy, ref, ref_col, depth_uv);
- /* Avoid bad cases of zfighting for occlusion only. */
- const float epsilon = 3.0 / 8388608.0;
- bool occluded = (ref_depth > scene_depth + epsilon);
+ if (doThickOutlines) {
+ if (!any(bvec4(has_edge_pos_x, has_edge_neg_x, has_edge_pos_y, has_edge_neg_y))) {
+#ifdef GPU_ARB_texture_gather
+ ids.x = tmp1.y;
+ ids.y = tmp2.y;
+ ids.z = tmp3.y;
+ ids.w = tmp4.y;
+#else
+ ids.x = textureLod(outlineId, uvs + 2.0 * ofs.xz, 0.0).r;
+ ids.y = textureLod(outlineId, uvs - 2.0 * ofs.xz, 0.0).r;
+ ids.z = textureLod(outlineId, uvs + 2.0 * ofs.zy, 0.0).r;
+ ids.w = textureLod(outlineId, uvs - 2.0 * ofs.zy, 0.0).r;
+#endif
+
+ has_edge_pos_x = has_edge(ids.x, uvs + 2.0 * ofs.xz, ref, ref_col, depth_uv);
+ has_edge_neg_x = has_edge(ids.y, uvs - 2.0 * ofs.xz, ref, ref_col, depth_uv);
+ has_edge_pos_y = has_edge(ids.z, uvs + 2.0 * ofs.zy, ref, ref_col, depth_uv);
+ has_edge_neg_y = has_edge(ids.w, uvs - 2.0 * ofs.zy, ref, ref_col, depth_uv);
+ }
+ }
+
+ if (isXrayWires) {
+ /* Don't inflate the wire outlines too much. */
+ has_edge_neg_x = has_edge_neg_y = false;
+ }
/* WATCH: Keep in sync with outlineId of the prepass. */
- uint color_id = ref_id >> 14u;
- if (ref_id == 0u) {
- FragColor = vec4(0.0);
+ uint color_id = ref_col >> 14u;
+ if (ref_col == 0u) {
+ fragColor = vec4(0.0);
}
else if (color_id == 1u) {
- FragColor = colorSelect;
+ fragColor = colorSelect;
}
else if (color_id == 2u) {
- FragColor = colorDupliSelect;
+ fragColor = colorDupliSelect;
}
else if (color_id == 3u) {
- FragColor = colorActive;
+ fragColor = colorActive;
}
else {
- FragColor = colorTransform;
+ fragColor = colorTransform;
+ }
+
+ float ref_depth = textureLod(outlineDepth, depth_uv, 0.0).r;
+ float scene_depth = textureLod(sceneDepth, depth_uv, 0.0).r;
+
+ /* Avoid bad cases of zfighting for occlusion only. */
+ const float epsilon = 3.0 / 8388608.0;
+ bool occluded = (ref_depth > scene_depth + epsilon);
+
+ /* NOTE: We never set alpha to 1.0 to avoid Antialiasing destroying the line. */
+ fragColor *= (occluded) ? alphaOcclu : (254.0 / 255.0);
+
+ float edge_case = 0.0;
+ edge_case += float(has_edge_pos_x) * 1.0;
+ edge_case += float(has_edge_neg_x) * 2.0;
+ edge_case += float(has_edge_pos_y) * 4.0;
+ edge_case += float(has_edge_neg_y) * 8.0;
+
+ vec2 line_start, line_end;
+ vec2 line_ofs;
+ bvec4 extra_edges, extra_edges2;
+ /* TODO simplify this branching hell. */
+ switch (int(edge_case)) {
+ /* Straight lines. */
+ case YPOS:
+ extra_edges = gather_edges(uvs + sizeViewportInv.xy * vec2(2.5, 0.5), ref);
+ extra_edges2 = gather_edges(uvs + sizeViewportInv.xy * vec2(-2.5, 0.5), ref);
+ straight_line_dir(extra_edges, extra_edges2, line_start, line_end);
+ break;
+ case YNEG:
+ extra_edges = gather_edges(uvs + sizeViewportInv.xy * vec2(-2.5, -0.5), ref);
+ extra_edges2 = gather_edges(uvs + sizeViewportInv.xy * vec2(2.5, -0.5), ref);
+ extra_edges = rotate_180(extra_edges);
+ extra_edges2 = rotate_180(extra_edges2);
+ straight_line_dir(extra_edges, extra_edges2, line_start, line_end);
+ line_start = rotate_180(line_start);
+ line_end = rotate_180(line_end);
+ break;
+ case XPOS:
+ extra_edges = gather_edges(uvs + sizeViewportInv.xy * vec2(0.5, 2.5), ref);
+ extra_edges2 = gather_edges(uvs + sizeViewportInv.xy * vec2(0.5, -2.5), ref);
+ extra_edges = rotate_90(extra_edges);
+ extra_edges2 = rotate_90(extra_edges2);
+ straight_line_dir(extra_edges, extra_edges2, line_start, line_end);
+ line_start = rotate_90(line_start);
+ line_end = rotate_90(line_end);
+ break;
+ case XNEG:
+ extra_edges = gather_edges(uvs + sizeViewportInv.xy * vec2(-0.5, 2.5), ref);
+ extra_edges2 = gather_edges(uvs + sizeViewportInv.xy * vec2(-0.5, -2.5), ref);
+ extra_edges = rotate_270(extra_edges);
+ extra_edges2 = rotate_270(extra_edges2);
+ straight_line_dir(extra_edges, extra_edges2, line_start, line_end);
+ line_start = rotate_270(line_start);
+ line_end = rotate_270(line_end);
+ break;
+
+ /* Diagonal */
+ case DIAG_XNEG_YPOS:
+ extra_edges = gather_edges(uvs + ofs.xy * vec2(1.5), ref);
+ diag_dir(extra_edges, line_start, line_end);
+ break;
+ case DIAG_XPOS_YNEG:
+ extra_edges = gather_edges(uvs - ofs.xy * vec2(1.5), ref);
+ extra_edges = rotate_180(extra_edges);
+ diag_dir(extra_edges, line_start, line_end);
+ line_start = rotate_180(line_start);
+ line_end = rotate_180(line_end);
+ break;
+ case DIAG_XPOS_YPOS:
+ extra_edges = gather_edges(uvs + ofs.xy * vec2(1.5, -1.5), ref);
+ extra_edges = rotate_90(extra_edges);
+ diag_dir(extra_edges, line_start, line_end);
+ line_start = rotate_90(line_start);
+ line_end = rotate_90(line_end);
+ break;
+ case DIAG_XNEG_YNEG:
+ extra_edges = gather_edges(uvs - ofs.xy * vec2(1.5, -1.5), ref);
+ extra_edges = rotate_270(extra_edges);
+ diag_dir(extra_edges, line_start, line_end);
+ line_start = rotate_270(line_start);
+ line_end = rotate_270(line_end);
+ break;
+
+ /* Apex */
+ case APEX_XPOS:
+ case APEX_XNEG:
+ line_start = vec2(-0.5, 0.0);
+ line_end = vec2(0.5, 0.0);
+ break;
+ case APEX_YPOS:
+ case APEX_YNEG:
+ line_start = vec2(0.0, -0.5);
+ line_end = vec2(0.0, 0.5);
+ break;
+ default:
+ discard;
}
- FragColor.a *= (occluded) ? alphaOcclu : 1.0;
- FragColor.a = (outline) ? FragColor.a : 0.0;
+ lineOutput = pack_line_data(vec2(0.0), line_start, line_end);
}
diff --git a/source/blender/draw/engines/overlay/shaders/outline_expand_frag.glsl b/source/blender/draw/engines/overlay/shaders/outline_expand_frag.glsl
deleted file mode 100644
index cb9fe0e7c36..00000000000
--- a/source/blender/draw/engines/overlay/shaders/outline_expand_frag.glsl
+++ /dev/null
@@ -1,51 +0,0 @@
-
-in vec4 uvcoordsvar;
-
-out vec4 FragColor;
-
-uniform sampler2D outlineColor;
-
-uniform float alpha;
-uniform bool doExpand;
-
-void main()
-{
- ivec2 uv = ivec2(gl_FragCoord.xy);
- FragColor = texelFetch(outlineColor, uv, 0).rgba;
-
- vec4 color[4];
- color[0] = texelFetchOffset(outlineColor, uv, 0, ivec2(1, 0)).rgba;
- color[1] = texelFetchOffset(outlineColor, uv, 0, ivec2(0, 1)).rgba;
- color[2] = texelFetchOffset(outlineColor, uv, 0, ivec2(-1, 0)).rgba;
- color[3] = texelFetchOffset(outlineColor, uv, 0, ivec2(0, -1)).rgba;
-
- vec4 values = vec4(color[0].a, color[1].a, color[2].a, color[3].a);
-
- vec4 tests = step(vec4(1e-6), values); /* (color.a != 0.0) */
- bvec4 btests = equal(tests, vec4(1.0));
-
- if (FragColor.a != 0.0) {
- return;
- }
-
-#ifdef LARGE_OUTLINE
- if (!any(btests)) {
- color[0] = texelFetchOffset(outlineColor, uv, 0, ivec2(2, 0)).rgba;
- color[1] = texelFetchOffset(outlineColor, uv, 0, ivec2(0, 2)).rgba;
- color[2] = texelFetchOffset(outlineColor, uv, 0, ivec2(-2, 0)).rgba;
- color[3] = texelFetchOffset(outlineColor, uv, 0, ivec2(0, -2)).rgba;
-
- values = vec4(color[0].a, color[1].a, color[2].a, color[3].a);
-
- tests = step(vec4(1e-6), values); /* (color.a != 0.0) */
- btests = equal(tests, vec4(1.0));
- }
-#endif
-
- FragColor = (btests.x) ? color[0] : FragColor;
- FragColor = (btests.y) ? color[1] : FragColor;
- FragColor = (btests.z) ? color[2] : FragColor;
- FragColor = (btests.w) ? color[3] : FragColor;
-
- FragColor.a *= (!doExpand) ? 0.0 : 1.0;
-}
diff --git a/source/blender/draw/engines/overlay/shaders/outline_resolve_frag.glsl b/source/blender/draw/engines/overlay/shaders/outline_resolve_frag.glsl
deleted file mode 100644
index ba5d073a9c2..00000000000
--- a/source/blender/draw/engines/overlay/shaders/outline_resolve_frag.glsl
+++ /dev/null
@@ -1,21 +0,0 @@
-
-in vec4 uvcoordsvar;
-
-out vec4 FragColor;
-
-uniform sampler2D outlineBluredColor;
-uniform vec2 rcpDimensions;
-
-void main()
-{
-#ifdef USE_FXAA
- float aa_alpha =
- FxaaPixelShader(uvcoordsvar.st, outlineBluredColor, rcpDimensions, 1.0, 0.166, 0.0833).r;
-#endif
-
- FragColor = texture(outlineBluredColor, uvcoordsvar.st).rgba;
-
-#ifdef USE_FXAA
- FragColor.a = aa_alpha;
-#endif
-}