Single Pass Wireframe Shading

Hi All,

I am trying to draw solid wireframe over mesh.
And trying to look for a lot of sources but still can’t build proper shader yet.

#shader vertex
#version 430 core

layout (location = 0) in vec3 geo_Pos;

/* Global information sent by the engine */
layout (std140) uniform UBO {
    mat4    ubo_Model;
    mat4    ubo_View;
    mat4    ubo_Projection;
    vec3    ubo_ViewPos;
    float   ubo_Time;
};

/* Information passed to the fragment shader */
out VS_OUT {
    vec3        FragPos;
    vec3        Normal;
    vec2        TexCoords;
    mat3        TBN;
    flat vec3   TangentViewPos;
    vec3        TangentFragPos;
} vs_out;

out vec2 vPosition;

vec4 og_ClipToWindowCoordinates(vec4 v, mat4 viewportTransformationMatrix) {
    v.xyz /= v.w;                                                  // normalized device coordinates
    v.xyz = (viewportTransformationMatrix * vec4(v.xyz, 1.0)).xyz; // window coordinates
    return v;
}

void main() {
    gl_Position = ubo_Projection * ubo_View * ubo_Model * vec4(geo_Pos, 1.0);
    vPosition = og_ClipToWindowCoordinates(gl_Position, ubo_View * ubo_Projection).xy;
}

#shader geometry
#version 430 core

layout(triangles) in;
layout(triangle_strip, max_vertices = 3) out;

in vec2 vPosition[];
noperspective out vec3 distanceToEdges;

float og_distanceToLine(vec2 f, vec2 p0, vec2 p1) {
    vec2 l = f - p0;
    vec2 d = p1 - p0;

    vec2 p = p0 + (d * (dot(l, d) / dot(d, d)));
    return distance(f, p);
}

void main() {
    vec2 p0 = vPosition[0];
    vec2 p1 = vPosition[1];
    vec2 p2 = vPosition[2];

    // Alternate between using the first and last vertex as the one opposite the
    // interior edge based on primitive ID.
    bool strip_flip = (bool (gl_PrimitiveIDIn & 1));

    gl_Position = gl_in[0].gl_Position;
    if (strip_flip)
      distanceToEdges = vec3(og_distanceToLine(p0, p1, p2), 0.0, 0.0);
    
	else
      distanceToEdges = vec3(og_distanceToLine(p0, p1, p2), 0.0, 1.0);
    EmitVertex();

    gl_Position = gl_in[1].gl_Position;
    if (strip_flip)
      distanceToEdges = vec3(1.0, og_distanceToLine(p1, p2, p0), 0.0);
    
	else
      distanceToEdges = vec3(0.0,     og_distanceToLine(p1, p2, p0), 1.0);
    EmitVertex();

    gl_Position = gl_in[2].gl_Position;
	if (strip_flip)
      distanceToEdges = vec3(1.0, 0.0, og_distanceToLine(p2, p0, p1));
    
	else
      distanceToEdges = vec3(    0.0, 0.0, og_distanceToLine(p2, p0, p1));
    
	EmitVertex();
}

#shader fragment
#version 430 core

/* Global information sent by the engine */
layout (std140) uniform UBO {
    mat4    ubo_Model;
    mat4    ubo_View;
    mat4    ubo_Projection;
    vec3    ubo_ViewPos;
    float   ubo_Time;
};

/* Information passed from the fragment shader */
in VS_OUT {
    vec3        FragPos;
    vec3        Normal;
    vec2        TexCoords;
    mat3        TBN;
    flat vec3   TangentViewPos;
    vec3        TangentFragPos;
} fs_in;

uniform float u_halfLineWidth;
uniform vec3 u_color;

noperspective in vec3 distanceToEdges;
out vec4 fragmentColor;

void main() {
    float d = min(distanceToEdges.x, min(distanceToEdges.y, distanceToEdges.z));

    if (d > u_halfLineWidth + 1.0) {
        fragmentColor = vec4(0.0, 0.0, 0.0, 1.0);
		return;
    }

    d = clamp(d - (u_halfLineWidth - 1.0), 0.0, 2.0);
	
    fragmentColor = vec4(u_color, exp2(-2.0 * d * d));
}

As you can see above that the meshes are shown up with color specified by u_color but I don’t see any wireframe, can you please let me know what’s the problem I have and how to fix it?

Thanks,

#shader vertex
#version 430 core

#extension GL_EXT_gpu_shader4 : enable

layout (location = 0) in vec3 VertexPosition;
layout (location = 1) in vec3 VertexNormal;

out vec3 VNormal;
out vec3 VPosition;

/* Global information sent by the engine */
layout (std140) uniform Engine {
    mat4    ubo_Model;
    mat4    ubo_View;
    mat4    ubo_Projection;
    vec3    ubo_ViewPos;
    float   ubo_Time;
};

mat3 mat3_emu(mat4 m4) {
	return mat3(
		m4[0][0], m4[0][1], m4[0][2],
		m4[1][0], m4[1][1], m4[1][2],
		m4[2][0], m4[2][1], m4[2][2]);
}

void main() {
	mat3 NormalMatrix = mat3_emu(transpose(inverse(ubo_Model)));
    VNormal = normalize(NormalMatrix * VertexNormal);
    VPosition = vec3(ubo_Projection * vec4(VertexPosition, 1.0));
	
	mat4 MVP = ubo_Projection * ubo_View;
    gl_Position = MVP * vec4(VertexPosition,1.0);
}

#shader geometry
#version 430 core

#extension GL_EXT_geometry_shader : enable
#extension GL_EXT_gpu_shader4 : enable
uniform vec2 Scale;
noperspective out vec3 dist;

layout (triangles) in;
layout (triangle_strip, max_vertices = 3) out;

void main() {
	vec2 p0 = Scale * gl_PositionIn[0].xy / gl_PositionIn[0].w;
	vec2 p1 = Scale * gl_PositionIn[1].xy / gl_PositionIn[1].w;
	vec2 p2 = Scale * gl_PositionIn[2].xy / gl_PositionIn[2].w;
	
	vec2 v0 = p2 - p1;
	vec2 v1 = p2 - p0;
	vec2 v2 = p1 - p0;
	
	float area = abs(v1.x * v2.y - v1.y * v2.x);
	
	dist = vec3(area / length(v0), 0, 0);
	gl_Position = gl_PositionIn[0]; EmitVertex();
	
	dist = vec3(0, area / length(v1), 0);
	gl_Position = gl_PositionIn[1]; EmitVertex();
	
	dist = vec3(0, 0, area / length(v2));
	gl_Position = gl_PositionIn[2]; EmitVertex();
	
	EndPrimitive();
}

#shader fragment
#version 430 core

#extension GL_EXT_gpu_shader4 : enable
noperspective in vec3 dist;

uniform struct LineInfo {
  float Width;
  vec4 Color;
} Line;

uniform vec4 MeshColor;
out vec4 FragColor;

void main() {
	float d = min(dist.x, min(dist.y, dist.z));
	float I = exp2(-2 * d * d);
	
	FragColor = I * Line.Color + (1.0 - I) * MeshColor;
}

I think I’ve solved the problem with above, although I want the quads but not triangles.
Should look for altenatives…

image

These should not go together. Either you’re using the core 3.2+ geometry shader feature, or you’re using GL_EXT_geometry_shader. You can’t use both, and they don’t expose the functionality in the same way. Your code looks like the EXT stuff (gl_PositionIn is not a valid input in 3.2).

Can you suggest one better? :slight_smile:

I can confirm that I can remove below from it

#extension GL_EXT_gpu_shader4 : enable