From c584597165ab16a66135695d30dd7c727363948a Mon Sep 17 00:00:00 2001 From: Jason Fielder Date: Tue, 19 Mar 2024 13:49:47 +0000 Subject: [PATCH] Fix #109363: Resolve GPencil fill in Metal Resolves an issue with stroke rendering in Metal using the geometry shader fallback path. Stroke rendering now matches OpenGL which should enable the GPencil fill tool to function correctly at all zoom levels. Authored by Apple: Michael Parkin-White Pull Request: https://projects.blender.org/blender/blender/pulls/119660 --- .../gpu_shader_gpencil_stroke_frag.glsl | 2 +- ...pu_shader_gpencil_stroke_vert_no_geom.glsl | 29 ++++++++++++++----- .../infos/gpu_shader_gpencil_stroke_info.hh | 1 + 3 files changed, 23 insertions(+), 9 deletions(-) diff --git a/source/blender/gpu/shaders/gpu_shader_gpencil_stroke_frag.glsl b/source/blender/gpu/shaders/gpu_shader_gpencil_stroke_frag.glsl index 3402ef19c58..f0c12ca25a7 100644 --- a/source/blender/gpu/shaders/gpu_shader_gpencil_stroke_frag.glsl +++ b/source/blender/gpu/shaders/gpu_shader_gpencil_stroke_frag.glsl @@ -2,7 +2,7 @@ * * SPDX-License-Identifier: GPL-2.0-or-later */ -#ifdef USE_GEOMETRY_SHADER +#if defined(USE_GEOMETRY_SHADER) || defined(USE_GEOMETRY_IFACE_COLOR) vec4 fragment_in_color() { return geometry_out.mColor; diff --git a/source/blender/gpu/shaders/gpu_shader_gpencil_stroke_vert_no_geom.glsl b/source/blender/gpu/shaders/gpu_shader_gpencil_stroke_vert_no_geom.glsl index 8ff8ed1fa43..d524d1d862d 100644 --- a/source/blender/gpu/shaders/gpu_shader_gpencil_stroke_vert_no_geom.glsl +++ b/source/blender/gpu/shaders/gpu_shader_gpencil_stroke_vert_no_geom.glsl @@ -97,13 +97,13 @@ bool is_equal(vec4 p1, vec4 p2) geometry_out.mTexCoord = vec2(0, 0); \ geometry_out.mColor = finalColor[1]; \ gl_Position = vec4( \ - (sp1 + finalThickness[2] * n0) / gpencil_stroke_data.viewport, getZdepth(P1), 1.0); + (sp1 + finalThickness[1] * n0) / gpencil_stroke_data.viewport, getZdepth(P1), 1.0); #define V1_a \ geometry_out.mTexCoord = vec2(0, 0); \ geometry_out.mColor = finalColor[1]; \ gl_Position = vec4( \ - (sp1 + finalThickness[2] * n1) / gpencil_stroke_data.viewport, getZdepth(P1), 1.0); + (sp1 + finalThickness[1] * n1) / gpencil_stroke_data.viewport, getZdepth(P1), 1.0); #define V2_a \ geometry_out.mTexCoord = vec2(0, 0.5); \ @@ -114,12 +114,12 @@ bool is_equal(vec4 p1, vec4 p2) geometry_out.mTexCoord = vec2(0, 1); \ geometry_out.mColor = finalColor[1]; \ gl_Position = vec4( \ - (sp1 - finalThickness[2] * n1) / gpencil_stroke_data.viewport, getZdepth(P1), 1.0); + (sp1 - finalThickness[1] * n1) / gpencil_stroke_data.viewport, getZdepth(P1), 1.0); #define V1_b \ geometry_out.mTexCoord = vec2(0, 1); \ geometry_out.mColor = finalColor[1]; \ gl_Position = vec4( \ - (sp1 - finalThickness[2] * n0) / gpencil_stroke_data.viewport, getZdepth(P1), 1.0); + (sp1 - finalThickness[1] * n0) / gpencil_stroke_data.viewport, getZdepth(P1), 1.0); #define V2_b \ geometry_out.mTexCoord = vec2(0, 0.5); \ @@ -197,6 +197,11 @@ bool is_equal(vec4 p1, vec4 p2) vec2 svn2 = normalize(sp2 - sp1) * length_b * 4.0 * extend; \ gl_Position = vec4((sp2 + svn2) / gpencil_stroke_data.viewport, getZdepth(P2), 1.0); +vec4 uchar4_to_normalized_vec4(uchar4 udata) +{ + return vec4(udata) / vec4(255.0f); +} + void main(void) { /* Determine output geometry IDs. */ @@ -215,7 +220,9 @@ void main(void) for (int i = 0; i < 4; i++) { finalPos[i] = ModelViewProjectionMatrix * vec4(vertex_fetch_attribute(input_prim_id + i, pos, vec3).xyz, 1.0); - finalColor[i] = vertex_fetch_attribute(input_prim_id + i, color, vec4); + /* Color attribute uses GPU_FETCH_INT_TO_FLOAT_UNIT with GPU_COMP_U8. */ + finalColor[i] = uchar4_to_normalized_vec4( + vertex_fetch_attribute(input_prim_id + i, color, uchar4)); float in_thickness = vertex_fetch_attribute(input_prim_id + i, thickness, float); if (gpencil_stroke_data.keep_size) { @@ -223,7 +230,7 @@ void main(void) } else { float size = (ProjectionMatrix[3][3] == 0.0) ? - (in_thickness / (gl_Position.z * defaultpixsize)) : + (in_thickness / (finalPos[i].z * defaultpixsize)) : (in_thickness / defaultpixsize); finalThickness[i] = max(size * gpencil_stroke_data.objscale, 1.0); } @@ -296,8 +303,14 @@ void main(void) } /** Geometry output. */ - /* First triangle (T0). prevent excessively long miters at sharp - * corners */ + + /* prevent excessively long miters at sharp corners */ + if (dot(v0, v1) < -MiterLimit) { + miter_a = n1; + length_a = finalThickness[1]; + } + + /* First triangle (T0). */ if (output_prim_triangle_id == 0) { if (dot(v0, v1) < -MiterLimit) { if (dot(v0, n1) > 0) { diff --git a/source/blender/gpu/shaders/infos/gpu_shader_gpencil_stroke_info.hh b/source/blender/gpu/shaders/infos/gpu_shader_gpencil_stroke_info.hh index af4fdb19a0c..131e2bfd45c 100644 --- a/source/blender/gpu/shaders/infos/gpu_shader_gpencil_stroke_info.hh +++ b/source/blender/gpu/shaders/infos/gpu_shader_gpencil_stroke_info.hh @@ -39,6 +39,7 @@ GPU_SHADER_CREATE_INFO(gpu_shader_gpencil_stroke) GPU_SHADER_CREATE_INFO(gpu_shader_gpencil_stroke_no_geom) .metal_backend_only(true) + .define("USE_GEOMETRY_IFACE_COLOR") .additional_info("gpu_shader_gpencil_stroke_base") .vertex_out(gpencil_stroke_geom_iface) .vertex_source("gpu_shader_gpencil_stroke_vert_no_geom.glsl")