/* Solid Wirefram implementation * Mike Erwin, Clément Foucault */ uniform float faceAlphaMod; uniform float edgeScale; flat in vec3 edgesCrease; flat in vec3 edgesBweight; flat in vec4 faceColor; flat in ivec3 flag; #ifdef VERTEX_SELECTION in vec3 vertexColor; #endif #ifdef EDGE_FIX flat in vec2 ssPos[3]; #else in vec3 barycentric; #endif #ifdef VERTEX_FACING in float facing; #endif out vec4 FragColor; /* Vertex flag is shifted and combined with the edge flag */ #define FACE_ACTIVE_ (FACE_ACTIVE << 8) #define LARGE_EDGE_SIZE 3.0 /* Style Parameters in pixel */ void distToEdgesAndPoints(out vec3 edges, out vec3 points) { #ifdef EDGE_FIX vec2 e0 = normalize(ssPos[1] - ssPos[0] + 1e-8); vec2 e1 = normalize(ssPos[2] - ssPos[1] + 1e-8); vec2 e2 = normalize(ssPos[0] - ssPos[2] + 1e-8); e0 = vec2(-e0.y, e0.x); e1 = vec2(-e1.y, e1.x); e2 = vec2(-e2.y, e2.x); vec2 p0 = gl_FragCoord.xy - ssPos[0]; vec2 p1 = gl_FragCoord.xy - ssPos[1]; vec2 p2 = gl_FragCoord.xy - ssPos[2]; edges.z = abs(dot(e0, p0)); edges.x = abs(dot(e1, p1)); edges.y = abs(dot(e2, p2)); #else vec3 dx = dFdx(barycentric); vec3 dy = dFdy(barycentric); /* per component derivative */ vec2 d0 = vec2(dx.x, dy.x); vec2 d1 = vec2(dx.y, dy.y); vec2 d2 = vec2(dx.z, dy.z); vec3 d = vec3(length(d0), length(d1), length(d2)); edges = abs(vec3(barycentric / d)); #endif #if defined(VERTEX_SELECTION) && defined(EDGE_FIX) points.x = dot(p0, p0); points.y = dot(p1, p1); points.z = dot(p2, p2); points = sqrt(points); #else points = vec3(1e10); #endif } void colorDist(vec4 color, float dist) { FragColor = (dist < 0) ? color : FragColor; } #ifdef ANTI_ALIASING void colorDistEdge(vec4 color, float dist) { FragColor.rgb *= FragColor.a; FragColor = mix(color, FragColor, clamp(dist, 0.0, 1.0)); FragColor.rgb /= max(1e-8, FragColor.a); } #else #define colorDistEdge colorDist #endif void main() { vec3 e, p; distToEdgesAndPoints(e, p); /* Face */ FragColor = faceColor; FragColor.a *= faceAlphaMod; /* Edges */ float sizeEdgeFinal = sizeEdge * edgeScale; for (int v = 0; v < 3; ++v) { if ((flag[v] & EDGE_EXISTS) != 0) { /* Outer large edge */ float largeEdge = e[v] - sizeEdgeFinal * LARGE_EDGE_SIZE; vec4 large_edge_color = EDIT_MESH_edge_color_outer(flag[v], (flag[0] & FACE_ACTIVE_) != 0, edgesCrease[v], edgesBweight[v]); if (large_edge_color.a != 0.0) { colorDistEdge(large_edge_color, largeEdge); } /* Inner thin edge */ float innerEdge = e[v] - sizeEdgeFinal; #ifdef ANTI_ALIASING innerEdge += 0.4; #endif #ifdef VERTEX_SELECTION colorDistEdge(vec4(vertexColor, 1.0), innerEdge); #else vec4 inner_edge_color = EDIT_MESH_edge_color_inner(flag[v], (flag[0] & FACE_ACTIVE_) != 0); colorDistEdge(inner_edge_color, innerEdge); #endif } } #if defined(VERTEX_SELECTION) && defined(EDGE_FIX) /* Points */ for (int v = 0; v < 3; ++v) { if ((flag[v] & EDGE_VERTEX_EXISTS) == 0) { /* Leave as-is, no vertex. */ } else { float size = p[v] - sizeVertex; vec4 point_color = colorVertex; point_color = ((flag[v] & EDGE_VERTEX_SELECTED) != 0) ? colorVertexSelect : point_color; point_color = ((flag[v] & EDGE_VERTEX_ACTIVE) != 0) ? vec4(colorEditMeshActive.xyz, 1.0) : point_color; colorDist(point_color, size); } } #endif #ifdef VERTEX_FACING FragColor.a *= 1.0 - abs(facing) * 0.4; #endif /* don't write depth if not opaque */ if (FragColor.a == 0.0) discard; }