Overlay: Edit Mesh: Add anti-alising on normal lines #119146

Open
sac.aiden wants to merge 7 commits from sac.aiden/blender:normal-antialiasing into main

When changing the target branch, be careful to rebase the branch in your fork to match. See documentation.
8 changed files with 302 additions and 8 deletions

View File

@ -787,6 +787,9 @@ set(GLSL_SRC
engines/overlay/shaders/overlay_edit_mesh_frag.glsl
engines/overlay/shaders/overlay_edit_mesh_geom.glsl
engines/overlay/shaders/overlay_edit_mesh_normal_vert.glsl
engines/overlay/shaders/overlay_edit_mesh_normal_vert_no_geom.glsl
engines/overlay/shaders/overlay_edit_mesh_normal_geom.glsl
engines/overlay/shaders/overlay_edit_mesh_normal_frag.glsl
engines/overlay/shaders/overlay_edit_mesh_skin_root_vert.glsl
engines/overlay/shaders/overlay_edit_mesh_vert.glsl
engines/overlay/shaders/overlay_edit_mesh_vert_no_geom.glsl

View File

@ -112,7 +112,7 @@ void OVERLAY_edit_mesh_cache_init(OVERLAY_Data *vedata)
{
/* Normals */
state = DRW_STATE_WRITE_DEPTH | DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_LESS_EQUAL |
(pd->edit_mesh.do_zbufclip ? DRW_STATE_BLEND_ALPHA : DRWState(0));
DRW_STATE_BLEND_ALPHA;
DRW_PASS_CREATE(psl->edit_mesh_normals_ps, state | pd->clipping_state);
sh = OVERLAY_shader_edit_mesh_normal();

View File

@ -8,6 +8,10 @@ GPU_SHADER_INTERFACE_INFO(overlay_edit_flat_color_iface, "").flat(Type::VEC4, "f
GPU_SHADER_INTERFACE_INFO(overlay_edit_smooth_color_iface, "").smooth(Type::VEC4, "finalColor");
GPU_SHADER_INTERFACE_INFO(overlay_edit_nopersp_color_iface, "")
.no_perspective(Type::VEC4, "finalColor");
GPU_SHADER_INTERFACE_INFO(overlay_edit_mesh_normale_iface, "interp")
.smooth(Type::VEC4, "final_color");
GPU_SHADER_INTERFACE_INFO(overlay_edit_mesh_normal_noperspective_iface, "interp_noperspective")
.no_perspective(Type::FLOAT, "smoothline");
/* -------------------------------------------------------------------- */
/** \name Edit Mesh
@ -150,6 +154,8 @@ GPU_SHADER_CREATE_INFO(overlay_edit_mesh_facedot)
GPU_SHADER_CREATE_INFO(overlay_edit_mesh_normal)
.do_static_compilation(true)
.define("LINE_WIDTH", "1")
.define("SMOOTH_WIDTH", "1")
.vertex_in(0, Type::VEC3, "pos")
.vertex_in(1, Type::VEC4, "lnor")
.vertex_in(2, Type::VEC4, "vnor")
@ -159,12 +165,38 @@ GPU_SHADER_CREATE_INFO(overlay_edit_mesh_normal)
.push_constant(Type::FLOAT, "normalScreenSize")
.push_constant(Type::FLOAT, "alpha")
.push_constant(Type::BOOL, "isConstantScreenSizeNormals")
.vertex_out(overlay_edit_flat_color_iface)
.vertex_out(overlay_edit_mesh_normale_iface)
.geometry_layout(PrimitiveIn::LINES, PrimitiveOut::TRIANGLE_STRIP, 4)
.geometry_out(overlay_edit_mesh_normale_iface)
.geometry_out(overlay_edit_mesh_normal_noperspective_iface)
.fragment_out(0, Type::VEC4, "fragColor")
.vertex_source("overlay_edit_mesh_normal_vert.glsl")
.fragment_source("overlay_varying_color.glsl")
.geometry_source("overlay_edit_mesh_normal_geom.glsl")
.fragment_source("overlay_edit_mesh_normal_frag.glsl")
.additional_info("draw_modelmat_instanced_attr", "draw_globals");
#ifdef WITH_METAL_BACKEND
GPU_SHADER_CREATE_INFO(overlay_edit_mesh_normal_no_geom)
.do_static_compilation(true)
.define("LINE_WIDTH", "1")
.define("SMOOTH_WIDTH", "1")
.vertex_in(0, Type::VEC3, "pos")
.vertex_in(1, Type::VEC4, "lnor")
.vertex_in(2, Type::VEC4, "vnor")
.vertex_in(3, Type::VEC4, "norAndFlag")
.sampler(0, ImageType::DEPTH_2D, "depthTex")
.push_constant(Type::FLOAT, "normalSize")
.push_constant(Type::FLOAT, "normalScreenSize")
.push_constant(Type::FLOAT, "alpha")
.push_constant(Type::BOOL, "isConstantScreenSizeNormals")
.vertex_out(overlay_edit_mesh_normale_iface)
.vertex_out(overlay_edit_mesh_normal_noperspective_iface)
.fragment_out(0, Type::VEC4, "fragColor")
.vertex_source("overlay_edit_mesh_normal_vert_no_geom.glsl")
.fragment_source("overlay_edit_mesh_normal_frag.glsl")
.additional_info("draw_modelmat_instanced_attr", "draw_globals");
#endif
GPU_SHADER_INTERFACE_INFO(overlay_edit_mesh_analysis_iface, "").smooth(Type::VEC4, "weightColor");
GPU_SHADER_CREATE_INFO(overlay_edit_mesh_analysis)

View File

@ -0,0 +1,10 @@
/* SPDX-FileCopyrightText: 2024 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
void main()
{
fragColor = interp.final_color;
fragColor.a *= clamp(
(LINE_WIDTH + SMOOTH_WIDTH) * 0.5 - abs(interp_noperspective.smoothline), 0.0, 1.0);
}

View File

@ -0,0 +1,57 @@
/* SPDX-FileCopyrightText: 2020-2024 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/* Almost a copy of blender/source/blender/gpu/shaders/gpu_shader_3D_polyline_geom.glsl */
/* Clips point to near clip plane before perspective divide. */
vec4 clip_line_point_homogeneous_space(vec4 p, vec4 q)
{
if (p.z < -p.w) {
/* Just solves p + (q - p) * A; for A when p.z / p.w = -1.0. */
float denom = q.z - p.z + q.w - p.w;
if (denom == 0.0) {
/* No solution. */
return p;
}
float A = (-p.z - p.w) / denom;
p = p + (q - p) * A;
}
return p;
}
void do_vertex(const int i, vec4 pos, vec2 ofs)
{
interp_out.final_color = interp_in[1].final_color;
interp_noperspective.smoothline = (LINE_WIDTH + SMOOTH_WIDTH) * 0.5;
gl_Position = pos;
gl_Position.xy += ofs * pos.w;
gpu_EmitVertex();
interp_noperspective.smoothline = -(LINE_WIDTH + SMOOTH_WIDTH) * 0.5;
gl_Position = pos;
gl_Position.xy -= ofs * pos.w;
gpu_EmitVertex();
}
void main(void)
{
vec4 p0 = clip_line_point_homogeneous_space(gl_in[0].gl_Position, gl_in[1].gl_Position);
vec4 p1 = clip_line_point_homogeneous_space(gl_in[1].gl_Position, gl_in[0].gl_Position);
vec2 e = normalize(((p1.xy / p1.w) - (p0.xy / p0.w)) * sizeViewport.xy);
#if 0 /* Hard turn when line direction changes quadrant. */
e = abs(e);
vec2 ofs = (e.x > e.y) ? vec2(0.0, 1.0 / e.x) : vec2(1.0 / e.y, 0.0);
#else /* Use perpendicular direction. */
vec2 ofs = vec2(-e.y, e.x);
#endif
ofs /= sizeViewport.xy;
ofs *= LINE_WIDTH + SMOOTH_WIDTH;
do_vertex(0, p0, ofs);
do_vertex(1, p1, ofs);
EndPrimitive();
}

View File

@ -16,7 +16,7 @@ void main()
GPU_INTEL_VERTEX_SHADER_WORKAROUND
/* Avoid undefined behavior after return. */
finalColor = vec4(0.0);
interp.final_color = vec4(0.0);
gl_Position = vec4(0.0);
vec3 nor;
@ -26,21 +26,21 @@ void main()
return;
}
nor = lnor.xyz;
finalColor = colorLNormal;
interp.final_color = colorLNormal;
}
else if (!all(equal(vnor.xyz, vec3(0)))) {
if (vnor.w < 0.0) {
return;
}
nor = vnor.xyz;
finalColor = colorVNormal;
interp.final_color = colorVNormal;
}
else {
nor = norAndFlag.xyz;
if (all(equal(nor, vec3(0)))) {
return;
}
finalColor = colorNormal;
interp.final_color = colorNormal;
}
vec3 n = normalize(normal_object_to_world(nor));
@ -66,7 +66,7 @@ void main()
gl_Position = point_world_to_ndc(world_pos);
finalColor.a *= (test_occlusion()) ? alpha : 1.0;
interp.final_color.a *= (test_occlusion()) ? alpha : 1.0;
view_clipping_distances(world_pos);
}

View File

@ -0,0 +1,191 @@
/* SPDX-FileCopyrightText: 2019-2022 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
#pragma USE_SSBO_VERTEX_FETCH(TriangleList, 6)
#pragma BLENDER_REQUIRE(common_view_clipping_lib.glsl)
#pragma BLENDER_REQUIRE(common_view_lib.glsl)
/* "geometry" shader area */
/* Clips point to near clip plane before perspective divide. */
vec4 clip_line_point_homogeneous_space(vec4 p, vec4 q)
{
if (p.z < -p.w) {
/* Just solves p + (q - p) * A; for A when p.z / p.w = -1.0. */
float denom = q.z - p.z + q.w - p.w;
if (denom == 0.0) {
/* No solution. */
return p;
}
float A = (-p.z - p.w) / denom;
p = p + (q - p) * A;
}
return p;
}
void do_vertex(uint index, vec4 pos, vec2 ofs, float flip)
{
interp_noperspective.smoothline = flip * (LINE_WIDTH + SMOOTH_WIDTH) * 0.5;
gl_Position = pos;
gl_Position.xy += flip * ofs * pos.w;
}
/* "veretex" shader area */
bool test_occlusion()
{
vec3 ndc = (gl_Position.xyz / gl_Position.w) * 0.5 + 0.5;
return (ndc.z - 0.00035) > texture(depthTex, ndc.xy).r;
}
vec4 vertex_main(uint src_index, vec3 in_pos, vec4 in_lnor, vec4 in_vnor, vec4 in_norAndFlag)
{
/* Avoid undefined behavior after return. */
interp.final_color = vec4(0.0);
gl_Position = vec4(0.0);
vec3 nor;
/* Select the right normal by checking if the generic attribute is used. */
if (!all(equal(in_lnor.xyz, vec3(0)))) {
if (in_lnor.w < 0.0) {
return vec4(0, 0, 0, 0);
}
nor = in_lnor.xyz;
interp.final_color = colorLNormal;
}
else if (!all(equal(in_vnor.xyz, vec3(0)))) {
if (in_vnor.w < 0.0) {
return vec4(0, 0, 0, 0);
}
nor = in_vnor.xyz;
interp.final_color = colorVNormal;
}
else {
nor = in_norAndFlag.xyz;
if (all(equal(nor, vec3(0)))) {
return vec4(0, 0, 0, 0);
}
interp.final_color = colorNormal;
}
vec3 n = normalize(normal_object_to_world(nor));
vec3 world_pos = point_object_to_world(in_pos);
if (src_index == 0) {
if (isConstantScreenSizeNormals) {
bool is_persp = (drw_view.winmat[3][3] == 0.0);
if (is_persp) {
float dist_fac = length(cameraPos - world_pos);
float cos_fac = dot(cameraForward, cameraVec(world_pos));
world_pos += n * normalScreenSize * dist_fac * cos_fac * pixelFac * sizePixel;
}
else {
float frustrum_fac = mul_project_m4_v3_zfac(n) * sizePixel;
world_pos += n * normalScreenSize * frustrum_fac;
}
}
else {
world_pos += n * normalSize;
}
}
interp.final_color.a *= (test_occlusion()) ? alpha : 1.0;
view_clipping_distances(world_pos);
return point_world_to_ndc(world_pos);
}
/* Real main */
#ifndef INT16_MAX
# define INT16_MAX 32767
#endif
typedef struct GPUPackedNormal {
int x : 10;
int y : 10;
int z : 10;
int w : 2;
} GPUPackedNormal;
#define nor_to_vec4(index, in_data, out_vec) \
{ \
if (vertex_fetch_get_attr_type(in_data) == GPU_SHADER_ATTR_TYPE_SHORT) { \
out_vec = (vec4)vertex_fetch_attribute(index, in_data, short4) / vec4(INT16_MAX); \
} \
else if (vertex_fetch_get_attr_type(in_data) == GPU_SHADER_ATTR_TYPE_INT1010102_NORM) { \
GPUPackedNormal data = *(constant GPUPackedNormal *)(&vertex_fetch_attribute( \
index, in_data, vec3_1010102_Inorm)); \
out_vec.x = float(data.x) / 511.0; \
out_vec.y = float(data.y) / 511.0; \
out_vec.z = float(data.z) / 511.0; \
out_vec.w = float(data.w); \
} \
else { \
out_vec = vertex_fetch_attribute(index, in_data, vec4); \
} \
}
void main()
{
/* Index of the quad primitive. Each quad corresponds to one line in the input primitive. */
int quad_id = gl_VertexID / 6;
/* Determine vertex ID. */
int quad_vertex_id = gl_VertexID % 6;
/* Get current point attributes. */
uint src_index_a = quad_id * 2;
uint src_index_b = quad_id * 2 + 1;
vec3 in_pos[2];
in_pos[0] = vertex_fetch_attribute(src_index_a, pos, vec3);
in_pos[1] = vertex_fetch_attribute(src_index_b, pos, vec3);
vec4 in_lnor[2];
nor_to_vec4(src_index_a, lnor, in_lnor[0]);
nor_to_vec4(src_index_b, lnor, in_lnor[1]);
vec4 in_vnor[2];
nor_to_vec4(src_index_a, vnor, in_vnor[0]);
nor_to_vec4(src_index_b, vnor, in_vnor[1]);
vec4 in_norAndFlag[2];
nor_to_vec4(src_index_a, norAndFlag, in_norAndFlag[0]);
nor_to_vec4(src_index_b, norAndFlag, in_norAndFlag[1]);
/* Convert to ndc space. Vertex shader main area. */
vec4 out_pos[2];
out_pos[0] = vertex_main(src_index_a, in_pos[0], in_lnor[0], in_vnor[0], in_norAndFlag[0]);
out_pos[1] = vertex_main(src_index_b, in_pos[1], in_lnor[1], in_vnor[1], in_norAndFlag[1]);
/* Geometry shader main area. */
vec4 clippedP[2];
clippedP[0] = clip_line_point_homogeneous_space(out_pos[0], out_pos[1]);
clippedP[1] = clip_line_point_homogeneous_space(out_pos[1], out_pos[0]);
vec2 e = normalize(((clippedP[1].xy / clippedP[1].w) - (clippedP[0].xy / clippedP[0].w)) *
sizeViewport.xy);
#if 0 /* Hard turn when line direction changes quadrant. */
e = abs(e);
vec2 ofs = (e.x > e.y) ? vec2(0.0, 1.0 / e.x) : vec2(1.0 / e.y, 0.0);
#else /* Use perpendicular direction. */
vec2 ofs = vec2(-e.y, e.x);
#endif
ofs /= sizeViewport.xy;
ofs *= LINE_WIDTH + SMOOTH_WIDTH;
if (quad_vertex_id == 0) {
do_vertex(0, clippedP[0], ofs, 1.0);
}
else if (quad_vertex_id == 1 || quad_vertex_id == 3) {
do_vertex(0, clippedP[0], ofs, -1.0);
}
else if (quad_vertex_id == 2 || quad_vertex_id == 5) {
do_vertex(1, clippedP[1], ofs, 1.0);
}
else if (quad_vertex_id == 4) {
do_vertex(1, clippedP[1], ofs, -1.0);
}
}

View File

@ -494,6 +494,7 @@ void gpu_shader_create_info_init()
overlay_edit_mesh_edge_flat = overlay_edit_mesh_edge_flat_no_geom;
overlay_edit_mesh_edge_clipped = overlay_edit_mesh_edge_clipped_no_geom;
overlay_edit_mesh_edge_flat_clipped = overlay_edit_mesh_edge_flat_clipped_no_geom;
overlay_edit_mesh_normal = overlay_edit_mesh_normal_no_geom;
overlay_edit_curve_handle = overlay_edit_curve_handle_no_geom;
overlay_edit_curve_handle_clipped = overlay_edit_curve_handle_clipped_no_geom;