4

Me and a friend are developing an editor (CAD-like) to use in our future game. We are using the Qt framework and OpenGL. The problem we are encountering is that on his laptop with an integrated nVidia card, the shading is working as expected and renders well. On my laptop with an integrated ATI card, as well as on my desktop with Radeon HD5850, the phong lighting is behaving slightly differently. There are more bright spots and dark spots and the image doesn't look good. Also, we are using a toon shader to draw a silhouette around the edges and to limit the amount of shades a color can have.

The toon shader uses 2-pass rendering - first pass renders the object in black, slightly larger than original (shifting each vertex in its normals direction slightly) to make the silhouette and then the second pass renders the object normally (only limiting the shade spectrum, so it looks more comic-like).

The images are of the same thing on our 2 computers. The first difference I mentioned above, the second is that the silhouette is stretched out as it should be on my friends computer, so it makes an even silhouette around the object, but is moved slightly up on my computer, making a thick line on the top and no line on the bottom.

The other thing is the phong lighting, illuminating the cube within which the object is edited. Again, rendering well on my friends computer, but being almost all-black or all-white on mine.

First image (nVidia card):

  Monkey1

Second image (ATI cards):

  Monkey2

I understand that the code is long and maybe the problem lays in some Qt settings, not in the shaders, but if you see anything that strikes you as bad practice, please answer.

Code for the phong shading follows

    #version 400

    in vec4 aVertex;
    in vec4 aNormal;
    in vec2 aTexCoord;

    uniform mat4 uPVM;
    uniform mat4 uViewModel;
    uniform mat4 uNormal;
    uniform int  uLightsOn;

    out vec2 vTexCoord;
    out vec3 vNormal;
    flat out vec3 mEye;
    flat out vec3 mLightDirection;

    flat out vec4 mAxisColor;

    void main(void)
    {
        if(uLightsOn == 1) {
            mEye = (uViewModel * aVertex).xyz;
            mLightDirection = vec4(2.0,-2.0,1.0,0.0).xyz;
            vNormal = (uNormal * aNormal).xyz;
        }

        gl_Position = uPVM * aVertex;
        vTexCoord = aTexCoord;
        mAxisColor = aNormal;
    }

The phong fragment shader :

    #version 400

    uniform sampler2D uTexture0;
    uniform int  uLightsOn;
    uniform vec3 uHighlightColor;
    uniform int uTextured;
    uniform int uAxisRender;

    in vec2 vTexCoord;
    in vec3 vNormal;
    flat in vec3 mEye;
    flat in vec3 mLightDirection;

    out vec4 fragColor;

    flat in vec4 mAxisColor;

    struct TMaterial {
        vec4 diffuse;
        vec4 ambient;
        vec4 specular;
        float shininess;
    };

    TMaterial material;

    void setup() {
        // setupMaterials

        material.ambient = vec4(0.4);
        material.diffuse = vec4(0.9);
        material.specular = vec4(0.0);
        material.shininess = 0.3;

    }

    void main(void)
    {
        setup();

        vec3 finalHighlightColor = uHighlightColor;

        if(finalHighlightColor.x <= 0.0) finalHighlightColor.x = 0.1;
        if(finalHighlightColor.y <= 0.0) finalHighlightColor.y = 0.1;
        if(finalHighlightColor.z <= 0.0) finalHighlightColor.z = 0.1;

        if(uLightsOn == 0) {
            if(uAxisRender == 1) fragColor = mAxisColor;
            else fragColor = vec4(finalHighlightColor,1.0);
            return;
        }

        vec4 diffuse;
        vec4 spec = vec4(0.0);
        vec4 ambient;

        vec3 L = normalize(mLightDirection - mEye);
        vec3 E = normalize(-mEye);
        vec3 R = normalize(reflect(-L,vNormal));

        ambient = material.ambient;

        float intens = max(dot(vNormal,L), 0.0);

        diffuse = clamp( material.diffuse * intens  , 0.0, 1.0 );
        if(intens > 0.0) spec = clamp ( material.specular * pow(max(dot(R,E),0.0),material.shininess) , 0.0, 1.0 );

        if(uTextured == 1) fragColor = (ambient + diffuse + spec) * texture(uTexture0,vTexCoord);
        else fragColor = (ambient + diffuse + spec) * vec4(finalHighlightColor,1.0);

    }

And the toon shaders :

    #version 400

    in vec4 aVertex;
    in vec4 aNormal;
    in vec2 aTexCoord;

    uniform mat4 uPV;
    uniform mat4 uM;
    uniform mat4 uN;
    uniform vec3 uLightPosition;
    uniform vec3 uCameraPosition;
    uniform int  uSilhouetteMode;
    uniform float uOffset;
    // if this uniform is passed, all the toon rendering is going off and only simple axis are rendered
    // last data in aNormal are colors of those axis if everything was ser properly.
    uniform int  uAxisRendering;
    flat out vec4 fAxisColor;

    out vec4 vNormal;
    out vec2 vTexCoord;
    out vec3 vDirectionToCamera;
    out vec3 vDirectionToLight;


    void silhouetteMode() {
        gl_Position = uPV * uM * vec4(aVertex.xyz + aNormal.xyz * uOffset,1.0f);
    }

    void toonMode() {
        vec4 worldPosition = uM * aVertex;

        vDirectionToCamera = uCameraPosition - worldPosition.xyz;
        vDirectionToLight = uLightPosition - worldPosition.xyz;
        vNormal = uN * aNormal;

        gl_Position = uPV * worldPosition;
    }

    void axisMode() {
        fAxisColor = aNormal;

        gl_Position = uPV * uM * aVertex;
    }

    void main(void)
    {
        vTexCoord = aTexCoord;

        if(uSilhouetteMode == 1) {
            silhouetteMode();
        } else {
            if(uAxisRendering == 1) axisMode();
            else toonMode();
        }
    }

and the fragment shader

    #version 400

    uniform sampler2D uTexture;
    uniform vec3 uBaseColor;
    uniform float uNumShades;
    uniform int  uSilhouetteMode;

    uniform int  uAxisRendering;
    flat in vec4 fAxisColor;

    in vec4 vNormal;
    in vec2 vTexCoord;
    in vec3 vDirectionToCamera;
    in vec3 vDirectionToLight;

    out vec4 outFragColor;

    void main(void)
    {

        if(uSilhouetteMode == 1) {
            outFragColor = vec4(uBaseColor,1.0);
            return;
        }

        if(uAxisRendering == 1) {
            outFragColor = fAxisColor;
            return;
        }

        float l_ambient = 0.1;
        float l_diffuse = clamp(dot(vDirectionToLight,vNormal.xyz),0.0,1.0);
        float l_specular;
        vec3 halfVector = normalize(vDirectionToCamera + vDirectionToLight);

        if(dot(vDirectionToLight,vNormal.xyz) > 0.0) {
            l_specular = pow(clamp(dot(halfVector,vNormal.xyz),0.0,1.0),64.0);
        } else {
            l_specular = 0.0;
        }

        float intensity = l_ambient + l_diffuse + l_specular;
        float shadeIntesity = ceil(intensity * uNumShades)/ uNumShades;

        outFragColor = vec4(texture(uTexture,vTexCoord).xyz * shadeIntesity * uBaseColor,1.0);
    }

And finally, our OpenGLWindow initialization (in Qt)

    OpenGLWindow::OpenGLWindow(QWindow *parent) :
        QWindow(parent),m_animating(false), m_initialized(false), m_animationTimer(NULL)
    {
        setSurfaceType(QWindow::OpenGLSurface);

        QSurfaceFormat format;
        format.setDepthBufferSize( 24 );
        format.setMajorVersion( 4 );
        format.setMinorVersion( 0 );
        format.setSamples( 4 );
        format.setProfile( QSurfaceFormat::CoreProfile );
        setFormat( format );
        create();

        if(!m_context) {
            m_context = new QOpenGLContext(this);
            m_context->setFormat(requestedFormat());
            m_context->create();
            m_context->makeCurrent(this);

            initializeOpenGLFunctions();
        }

        m_animationTimer = new QTimer(this);
        connect(m_animationTimer, SIGNAL(timeout()), this, SLOT(renderer()));
        m_animationTimer->setInterval(16);
    }
Gob
  • 73
  • 2
  • 6
  • 2
    You really should not mix and match `in` / `out` with `attribute` and `varying`. This is a GLSL 4.00 shader, you should avoid the latter deprecated language features. Likewise, `texture2D (...)` was replaced with an overload of `texture (...)` in GLSL 1.30. – Andon M. Coleman May 01 '14 at 22:24
  • Thanks for the tip, but I've changed all varyings and attributes to in/out respectively and texture2D to texture to no avail. The result is still the same. Do you know if there is any good source for actual GLSL standards ? – Gob May 01 '14 at 22:42
  • http://www.opengl.org/registry/ is the best source for any OpenGL-related standard. Reading the specification is not going to be easy though, it is a lot of information to digest. You would be better off buying a book like the OpenGL Super Bible for learning non-deprecated features, and referring to the spec. only when you have a specific concern. Furthermore, knowing which things are deprecated and particularly what and when they were replaced with is not something you will easily find by reading the latest spec., that comes with years of experience. – Andon M. Coleman May 01 '14 at 23:17
  • Yes I know. Im now just a little lost because we had great courses that were about modern opengl methods and before I understood the basics, learned how OpenGL really works and how to use it I was on my own to learn it. Now Im a little futher but still not very experienced and to find something related to modern methods on the internet is nearly impossible. I will be happy for any tips, thank you for your interest. – Gob May 02 '14 at 00:13
  • 3
    Well, if a little self promotion is ok, I wrote an article about porting code to the core profile on my personal web site: http://retokoradi.com/2014/03/30/opengl-transition-to-core-profile/. It's not intended to be a complete list of deprecated features, but should cover some of the main areas. – Reto Koradi May 02 '14 at 03:00
  • Thanks! This helped me to sort things out. – Gob May 02 '14 at 13:54
  • By "helped me sort things out", do you mean that the problem has been solved? – Andon M. Coleman May 02 '14 at 23:57
  • Unfortunately not. But it clarified me whats deprecated. Not everything but most of functionality Im using. – Gob May 03 '14 at 00:42

1 Answers1

0

To my eyes the nVidia image seems to be using alpha whereas the AMD one is not. I also can't see a

format.setAlpha(true);

in your Qt setup so may be that.

user2746401
  • 3,157
  • 2
  • 21
  • 46