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:
-rw-r--r--source/blender/draw/CMakeLists.txt2
-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
10 files changed, 346 insertions, 278 deletions
diff --git a/source/blender/draw/CMakeLists.txt b/source/blender/draw/CMakeLists.txt
index ea52d8e8f1f..88caafb0c00 100644
--- a/source/blender/draw/CMakeLists.txt
+++ b/source/blender/draw/CMakeLists.txt
@@ -360,12 +360,10 @@ data_to_c_simple(engines/overlay/shaders/motion_path_line_geom.glsl SRC)
data_to_c_simple(engines/overlay/shaders/motion_path_line_vert.glsl SRC)
data_to_c_simple(engines/overlay/shaders/motion_path_point_vert.glsl SRC)
data_to_c_simple(engines/overlay/shaders/outline_detect_frag.glsl SRC)
-data_to_c_simple(engines/overlay/shaders/outline_expand_frag.glsl SRC)
data_to_c_simple(engines/overlay/shaders/outline_prepass_frag.glsl SRC)
data_to_c_simple(engines/overlay/shaders/outline_prepass_geom.glsl SRC)
data_to_c_simple(engines/overlay/shaders/outline_prepass_vert.glsl SRC)
data_to_c_simple(engines/overlay/shaders/outline_lightprobe_grid_vert.glsl SRC)
-data_to_c_simple(engines/overlay/shaders/outline_resolve_frag.glsl SRC)
data_to_c_simple(engines/overlay/shaders/paint_face_vert.glsl SRC)
data_to_c_simple(engines/overlay/shaders/paint_point_vert.glsl SRC)
data_to_c_simple(engines/overlay/shaders/paint_texture_frag.glsl SRC)
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
-}