Search code examples
javaopenglglslshader

This "Single - pass wire frame shader "opengl shader worked on my old machine with amd integrated graphics but it dose not my new nvidea pc


I created this shader from following this tutorial on single pass wireframe rendering: http://codeflow.org/entries/2012/aug/02/easy-wireframe-display-with-barycentric-coordinates/

Fragment:

#version 450
layout (location = 0) out vec4 outColor;
in vec3 vBC;
const float lineWidth = 0.5;
const vec3 color = vec3(0.7, 0.7, 0.7);
float edgeFactor(){
    vec3 d = fwidth(vBC);
    vec3 a3 = smoothstep(vec3(0.0), d*1.5, vBC);
    return min(min(a3.x, a3.y), a3.z);
}
void main(){
    outColor = vec4(min(vec3(edgeFactor()), color), 1.0);
}

Vertex:

#version 450
layout (location = 0) in vec3 position;
layout (location = 1) in vec3 baryCentric;
out vec3 vBC;
uniform mat4 T_MVP;
void main() {
  //texCoord0 = texCoord;    
  gl_Position = T_MVP * vec4(position, 1.0);
  vBC = baryCentric;
}

And here is the gl prep before rendering:

wir.bind();
wir.updateUniforms(super.getTransform(), mat, engine);
GL45.glEnable(GL45.GL_SAMPLE_ALPHA_TO_COVERAGE);
GL45.glEnable(GL45.GL_BLEND);
GL45.glBlendFunc(GL45.GL_SRC_ALPHA, GL45.GL_ONE_MINUS_SRC_ALPHA);
mesh.draw("baryCentric", GL15.GL_TRIANGLES);

And here is how i bind the vertex atrribs; java show

The shader worked perfectly fine on my old amd integrated graphics card. But it dosnt on my rtx 2060 super. Shader and Gl version on old: OpenGL version: 4.5.13399 Compatibility Profile Context 15.200.1062.1004 on new: 4.6.0 NVIDIA 445.87


Solution

  • First of all I dont know what causes this but i think its the model files.

    How i solved this was instead of pre processing the Bary centric coords i would calculate them or rather assign them in a geometry shader like so:

        vBC = vec3(1, 0, 0);
        gl_Position = gl_in[0].gl_Position;
        EmitVertex();
    
        vBC = vec3(0, 1, 0);
        gl_Position = gl_in[1].gl_Position;
        EmitVertex();
    
        vBC = vec3(0, 0, 1);
        gl_Position = gl_in[2].gl_Position;
        EmitVertex();
    

    and nothing else just pass them onto the fragment shader and it would do the rest:

    #version 400
    precision mediump float;
    layout (location = 0) out vec4 outColor;
    in vec3 vBC;
    const float lineWidth = 0.5;
    const vec3 lineColor = vec3(0.7, 0.7, 0.7);
    
    float edgeFactor() {
      vec3 d = fwidth(vBC);
      vec3 f = step(d * lineWidth, vBC);
      return min(min(f.x, f.y), f.z);
    }
    
    void main(){
        outColor = vec4(255, 191, 0.0, (1.0-edgeFactor())*0.95);        
    }
    

    The vertex shader only defines the positions nothing else the most basic.

    Here is the full geometry shader if any one needs it:

    #version 400
    layout(triangles) in;
    layout(triangle_strip, max_vertices = 3) out;
    out vec3 vBC;
    void main()
    {
    
        vBC = vec3(1, 0, 0);
        gl_Position = gl_in[0].gl_Position;
        EmitVertex();
    
        vBC = vec3(0, 1, 0);
        gl_Position = gl_in[1].gl_Position;
        EmitVertex();
    
        vBC = vec3(0, 0, 1);
        gl_Position = gl_in[2].gl_Position;
        EmitVertex();
    
     }
    

    Here are some pictures: wireframe As you can see its working with transparency which is done using: code

    Here is the articles i looked at: https://tchayen.github.io/wireframes-with-barycentric-coordinates/ http://codeflow.org/entries/2012/aug/02/easy-wireframe-display-with-barycentric-coordinates/

    And a cool book that helped me a lot: https://people.inf.elte.hu/plisaai/pdf/David%20Wolff%20-%20OpenGL%204.0%20Shading%20Language%20Cookbook%20(2).pdf

    Just in case here is the Vertex shader:

    #version 400
    precision mediump int;
    precision mediump float;
    layout (location = 0) in vec3 position;
    
    uniform mat4 T_MVP;
    
    void main() {
      gl_Position = T_MVP * vec4(position, 1.0);
    }