Edit Mesh: Rework new implementation and use geometry shader to draw lines

This make it (theoriticaly) compatible with all supported hardware with
consistent results.

Also we now draw the lines with analytic anti-aliasing instead of relying
on MSAA (which offers less benefits in our case).

The remaining aliasing comes from edges cut in half by the mesh which is
not rendered with MSAA. Hopefully this is not too much distracting and only
happen if the face is almost parallel to the view.
This commit is contained in:
2019-02-07 16:30:08 +01:00
parent 9b774dfa3b
commit a710af2b25
5 changed files with 110 additions and 150 deletions

View File

@@ -11,7 +11,7 @@ vec4 EDIT_MESH_edge_color_outer(int edge_flag, int face_flag, float crease, floa
color = ((edge_flag & EDGE_SEAM) != 0) ? colorEdgeSeam : color;
if ((face_flag & FACE_ACTIVE) != 0) {
color = colorEditMeshActive;
color = vec4(colorEditMeshActive.rgb, 1.0);
}
return color;
}

View File

@@ -1,23 +1,36 @@
#ifdef FLAT
flat in vec4 finalColor;
#else
in vec4 finalColor;
# ifdef EDGE
flat in int selectOveride;
# endif
#endif
#define M_1_SQRTPI 0.5641895835477563 /* 1/sqrt(pi) */
/**
* We want to know how much a pixel is covered by a line.
* We replace the square pixel with acircle of the same area and try to find the intersection area.
* The area we search is the circular segment. https://en.wikipedia.org/wiki/Circular_segment
* The formula for the area uses inverse trig function and is quite complexe.
* Instead, we approximate it by using the smoothstep function and a 1.05 factor to the disc radius.
**/
#define DISC_RADIUS (M_1_SQRTPI * 1.05)
#define GRID_LINE_SMOOTH_START (0.5 - DISC_RADIUS)
#define GRID_LINE_SMOOTH_END (0.5 + DISC_RADIUS)
uniform float edgeScale;
flat in vec4 finalColorOuter_f;
in vec4 finalColor_f;
in float edgeCoord_f;
out vec4 FragColor;
void main()
{
#if defined(EDGE) && !defined(FLAT)
vec4 prim_col = mix(colorEditMeshMiddle, colorEdgeSelect, finalColor.a);
prim_col = (selectOveride != 0) ? prim_col : finalColor;
prim_col.a = 1.0;
float dist = abs(edgeCoord_f) - max(sizeEdge * edgeScale - 0.5, 0.0);
float dist_outer = dist - max(sizeEdge * edgeScale, 1.0);
#if 1
float mix_w = smoothstep(GRID_LINE_SMOOTH_START, GRID_LINE_SMOOTH_END, dist);
float mix_w_outer = smoothstep(GRID_LINE_SMOOTH_START, GRID_LINE_SMOOTH_END, dist_outer);
#else
# define prim_col finalColor
float mix_w = step(0.5, dist);
float mix_w_outer = step(0.5, dist_outer);
#endif
FragColor = prim_col;
FragColor = mix(finalColorOuter_f, finalColor_f, 1.0 - mix_w * finalColorOuter_f.a);
FragColor.a *= 1.0 - (finalColorOuter_f.a > 0.0 ? mix_w_outer : mix_w);
}

View File

@@ -4,33 +4,23 @@ layout(triangle_strip, max_vertices = 4) out;
uniform vec2 viewportSize;
uniform vec2 viewportSizeInv;
uniform float edgeScale;
in VertexData {
vec4 finalColor;
#if defined(EDGE) && !defined(FLAT)
int selectOveride;
#endif
} v[];
in vec4 finalColor[2];
in vec4 finalColorOuter[2];
in int selectOveride[2];
#ifdef FLAT
# define interp_col flat
#else
# define interp_col
#endif
flat out vec4 finalColorOuter_f;
out vec4 finalColor_f;
out float edgeCoord_f;
interp_col out vec4 finalColor;
#if defined(EDGE) && !defined(FLAT)
flat out int selectOveride;
#endif
void do_vertex(const int i, vec2 offset)
void do_vertex(const int i, float coord, vec2 offset)
{
finalColor = v[i].finalColor;
#if defined(EDGE) && !defined(FLAT)
selectOveride = v[0].selectOveride;
#endif
finalColor_f = (selectOveride[0] == 0) ? finalColor[i] : finalColor[0];
edgeCoord_f = coord;
gl_Position = gl_in[i].gl_Position;
gl_Position.xy += offset * gl_Position.w;
/* Multiply offset by 2 because gl_Position range is [-1..1]. */
gl_Position.xy += offset * 2.0 * gl_Position.w;
EmitVertex();
}
@@ -41,25 +31,24 @@ void main()
ss_pos[1] = gl_in[1].gl_Position.xy / gl_in[1].gl_Position.w;
vec2 line = ss_pos[0] - ss_pos[1];
line *= viewportSize;
line = abs(line) * viewportSize;
vec3 edge_ofs = sizeEdge * 2.0 * viewportSizeInv.xyy * vec3(1.0, 1.0, 0.0);
finalColorOuter_f = finalColorOuter[0];
float half_size = sizeEdge * edgeScale;
/* Enlarge edge for flag display. */
half_size += (finalColorOuter_f.a > 0.0) ? max(sizeEdge * edgeScale, 1.0) : 0.0;
/* Add 1 px for AA */
half_size += 0.5;
#ifdef EDGE_DECORATION
edge_ofs *= 3.0;
vec3 edge_ofs = half_size * viewportSizeInv.xyy * vec3(1.0, 1.0, 0.0);
if (finalColor.a == 0.0) {
return;
}
#endif
bool horizontal = abs(line.x) > abs(line.y);
bool horizontal = line.x > line.y;
edge_ofs = (horizontal) ? edge_ofs.zyz : edge_ofs.xzz;
do_vertex(0, edge_ofs.xy);
do_vertex(0, -edge_ofs.xy);
do_vertex(1, edge_ofs.xy);
do_vertex(1, -edge_ofs.xy);
do_vertex(0, half_size, edge_ofs.xy);
do_vertex(0, -half_size, -edge_ofs.xy);
do_vertex(1, half_size, edge_ofs.xy);
do_vertex(1, -half_size, -edge_ofs.xy);
EndPrimitive();
}

View File

@@ -17,32 +17,10 @@ in vec4 norAndFlag;
# define vnor norAndFlag.xyz
#endif
out vec4 finalColor;
out vec4 finalColorOuter;
#ifdef USE_GEOM_SHADER
# define qual_col
# define qual_sel
#else
# ifdef FLAT
# define qual_col flat out
# else
# define qual_col out
# endif
# define qual_sel flat out
#endif
#ifdef USE_GEOM_SHADER
out VertexData {
#endif
qual_col vec4 finalColor;
#if defined(EDGE) && !defined(FLAT)
qual_sel int selectOveride;
#endif
#ifdef USE_GEOM_SHADER
} v;
# define v(a) v.a
#else
# define v(a) a
out int selectOveride;
#endif
void main()
@@ -60,7 +38,7 @@ void main()
ivec4 m_data = data & dataMask;
#if defined(VERT)
v(finalColor) = EDIT_MESH_vertex_color(m_data.y);
finalColor = EDIT_MESH_vertex_color(m_data.y);
gl_PointSize = sizeVertex * 2.0;
gl_Position.z -= 3e-5 * ((ProjectionMatrix[3][3] == 0.0) ? 1.0 : 0.0);
/* Make selected and active vertex always on top. */
@@ -73,23 +51,23 @@ void main()
#elif defined(EDGE)
# ifdef FLAT
v(finalColor) = EDIT_MESH_edge_color_inner(m_data.y);
finalColor = EDIT_MESH_edge_color_inner(m_data.y);
selectOveride = 1;
# else
v(finalColor) = EDIT_MESH_edge_vertex_color(m_data.y);
v(selectOveride) = (m_data.y & EDGE_SELECTED);
finalColor = EDIT_MESH_edge_vertex_color(m_data.y);
selectOveride = (m_data.y & EDGE_SELECTED);
# endif
#elif defined(EDGE_DECORATION)
float crease = float(m_data.z) / 255.0;
float bweight = float(m_data.w) / 255.0;
v(finalColor) = EDIT_MESH_edge_color_outer(m_data.y, m_data.x, crease, bweight);
finalColorOuter = EDIT_MESH_edge_color_outer(m_data.y, m_data.x, crease, bweight);
#elif defined(FACE)
v(finalColor) = EDIT_MESH_face_color(m_data.x);
v(finalColor).a *= faceAlphaMod;
finalColor = EDIT_MESH_face_color(m_data.x);
finalColor.a *= faceAlphaMod;
#elif defined(FACEDOT)
v(finalColor) = EDIT_MESH_facedot_color(norAndFlag.w);
finalColor = EDIT_MESH_facedot_color(norAndFlag.w);
/* Bias Facedot Z position in clipspace. */
gl_Position.z -= 0.00035;
gl_PointSize = sizeFaceDot;
@@ -106,12 +84,12 @@ void main()
float facing = dot(view_vec, view_normal);
facing = 1.0 - abs(facing) * 0.3;
v(finalColor) = mix(colorEditMeshMiddle, v(finalColor), facing);
v(finalColor).a = 1.0;
finalColor = mix(colorEditMeshMiddle, finalColor, facing);
finalColor.a = 1.0;
# if defined(EDGE) && !defined(FLAT)
/* Hack to blend color in pixel shader in case of overide. */
v(finalColor).a = facing;
finalColor.a = facing;
# endif
#endif