Deferred Rendering Pipeline Not Working On Laptop Graphics Cards, and Odd "Model Ghosting" Problems (glBlendFunc)

358 Views Asked by At

EDIT: Changing the fragment shader so only one light per-run was possible solved my first problem. My second problem still stands.

thanks in advance for any help you can offer. I have been working on a deferred shading pipeline for my LWJGL rendering engine for a couple weeks now. I though I had managed to get everything to work as I would expected, but after distributing the program to a few people I know, I began encountering problems. I'll try to keep this as short as possible. Thanks for staying with me.

I'll start with the first of the two problems in my title. On my machine (AMD Phenom II 965 and Nvidia GTX 480) the final product of my renderer was exactly as expected. (I was going to post a link to an image, but seeing as I am a new user, I was unable to post more than 3 hyperlinks. But it is sufficient to say, it looked like it should have.)

This is exactly what I intended so I though the renderer was working fine. I sent it off to a friend (who was using a GT 440) and they had the same results.

Soon after this I gave a build of the engine to a friend of mine who has a laptop (with a GT 540M). This was what the renderer produced (ignore the FPS counter, it doesn't work):

https://i.stack.imgur.com/KKeck.png

Obviously this is not at all the results I expected. I experienced the same results on every other mobile graphics card I was able to test on. After more than a week of banging my head on my desk, I was able to narrow the problem down to the lighting pass, where glBlendFunc is called. My code is as follows:

    glBindFramebuffer(GL_FRAMEBUFFER, 0);
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    List<Float[]>[] listArray = LightData.getInstance().updateLights();
    List<Float[]> lightsColor = listArray[1];
    List<Float[]> lightsPos = listArray[0];
    viewMatrix.setViewMatrix(camera.getTranslation(), camera.getRotation());


    glDisable(GL_DEPTH_TEST);
    glUseProgram(0);
    glCallList(quadList);
    FBO.useShader();
    FBO.passTextures(); //Just sets the shader uniform values to the correct textures
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    glEnable(GL_BLEND);
    glLoadIdentity();
    glBlendFunc(GL_ONE, GL_ONE) ; //using GL_ONE and GL_ONE_MINUS_SRC_ALPHA have the same effect
    for (int i = 0; i < lightsPos.size(); i++) {
        glClear(GL_DEPTH_BUFFER_BIT);
        int uniformLightPosition = glGetUniformLocation(FBO.getShaderID(), "uniformLightPosition");
        int uniformLightColor = glGetUniformLocation(FBO.getShaderID(), "uniformLightColor");
        int uniformViewMatrix = glGetUniformLocation(FBO.getShaderID(), "uniformViewMatrix");
        int uniformAmbient = glGetUniformLocation(FBO.getShaderID(), "uniformAmbient");
        glUniform1(uniformLightPosition, Tools.asFloatBuffer(lightsPos.get(i)));
        glUniform1(uniformLightColor, Tools.asFloatBuffer(lightsColor.get(i)));
        glUniform1f(uniformAmbient, 0.01f);
        glUniformMatrix4(uniformViewMatrix, true, viewMatrix.asFloatBuffer());

        glCallList(quadList); //is just a display list for a fullscreen quad (using GL_QUADS)
    } 
    glDisable(GL_BLEND);
    glEnable(GL_DEPTH_TEST);

This first thing that you might notice is the fact that I draw a quad and then clear the depth and color buffers. That will be a addressed in my next question, although I wouldn't be surprised if the problem in my next question was closely related to the one in this question. I am almost sure (99%) that the problem is in this method because when testing with an older build of the engine that only supported one light but was still using the deferred pipeline I was able to get perfect results on every computer I tested on. Once again, the renderer works on every desktop graphics card I have tested, but not on any laptop graphics cards. I have ruled out almost everything except this method. It might be worth noting that I have had no success using a texture with an internal format that is not GL_RGBA32f or GL_RGBA16f as a render target. Has anyone seen this before, or can anyone offer assistance? I would love if anyone even had any idea where to start looking for problems at this point, because I've got nothing. I've been complete unable to find a solution by myself.

Then moving on to the second problem and second question. In the beginning of the last code block I had a few line of codes that created a quad on the screen with no shader:

glDisable(GL_DEPTH_TEST);
    glUseProgram(0);
    glCallList(quadList);
    FBO.useShader();
    FBO.passTextures(); //Just sets the shader uniform values to the correct textures
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    glEnable(GL_BLEND);

As far as I can tell, this code should do absolutely nothing. But when I remove the drawing of the quad, The window displays this:

https://i.stack.imgur.com/WwCYN.png

I didn't know what else to call this besides "ghosting" because it is like a ghost image (at least that how it seems to me). When I rotate the MV matrix it distorts in the direction I rotate, and the first set of lights (I use an array of 7) light it, but then the rest light the actual model. I can't explain why this happens because the code that generates this image is exactly like the code above without the glCallList(quadList); which means the depth and color buffers are still cleared right before I enter the loop. I can't explain this problem at all. Does anyone have any idea what's wrong and how to fix it, or at least an idea about what's wrong?

EDIT I have found that this only happens to models that have texture coordinates. I don't know why.

EDIT It looks like when I limit the amount of lights allowed in each shader to 1, the ghosting gets much less noticeable, but is still there, So I assume this means that one run of the fragment shader results in these ghosts.

Thanks for ANY help anyone has with either of these two problems, it is greatly appreciated. If you have any questions for me just ask, although it might take me some time to get back to you, I'll try to get back as fast as possible.

EDIT Sory, I forgot my shader code: GeometryPass vertex:

uniform sampler2D tex;

varying vec3 surfaceNormal;
varying vec3 varyingVertex;

void main() {
    vec4 color = vec4(texture2D(tex, gl_TexCoord[1].st));
    gl_FragColor = color;

}

GeometryPass fragment:

uniform sampler2D tex;

varying vec3 surfaceNormal;
varying vec3 varyingVertex;

uniform float materialValue;
uniform float specValue; 

void main() {
    vec4 color = vec4(texture2D(tex, gl_TexCoord[1].st)) ;//vec4(0.25,0.25,0.25,1);
    vec4 vertex = vec4(varyingVertex, materialValue);
    vec4 normal = vec4(surfaceNormal, specValue);
    gl_FragData[0] = color;
    gl_FragData[1] = vertex;
    gl_FragData[2] = normal;

}

LightPass Phong vertex:

void main() {
    gl_TexCoord[0] = gl_MultiTexCoord0;
    gl_Position = gl_ModelViewMatrix * gl_Vertex;
}

LightPass Phong Fragment

uniform sampler2D location;
uniform sampler2D normal;
uniform sampler2D color;

uniform float uniformLightPosition[21];
uniform mat4 uniformViewMatrix;
uniform float uniformLightColor[28];


void main() {
    vec4 color = texture2D(color, gl_TexCoord[0].st);
    vec4 locationAndMat = texture2D(location, gl_TexCoord[0].st);
    vec4 normalAndSpec = texture2D(normal, gl_TexCoord[0].st);  

    vec3 vertexPosition = locationAndMat.xyz;
    vec3 surfaceNormal = normalAndSpec.xyz;
    float spec = normalAndSpec.a;
    float specA = locationAndMat.a;

    vec4 lightColor[7];
    int iterator = 0;
    for (int i = 0; i<28; i = i+4) {
        lightColor[iterator] = vec4(uniformLightColor[i], uniformLightColor[i+1], uniformLightColor[i+2], uniformLightColor[i+3]);
        iterator = iterator + 1;
    }
    vec3 lightPos[7];
    iterator = 0;
    for (int i = 0; i<21; i = i+3) {
        lightPos[iterator] = vec3(uniformLightPosition[i], uniformLightPosition[i+1], uniformLightPosition[i+2]);
        lightPos[iterator] =  (uniformViewMatrix * vec4(lightPos[iterator],1)).xyz ;
        iterator = iterator + 1;
    }

    vec4 fragData[7];
    vec4 endColor;
    for (int i = 0; i<7 ; i++) {
        if (lightColor[i] != vec4(0,0,0,0) && color != vec4(0,0,0,0)) {
            vec3 lightDistance = lightPos[i]-vertexPosition;
            float distance = pow((pow(lightDistance.x, 2) + pow(lightDistance.y, 2) + pow(lightDistance.z, 2)), 0.5);
            if (distance < lightColor[i].a) { 
                float att = 1/((-3/800*(lightColor[i].a) + 0.225)*pow(distance, 2));
                vec3 lightDirection = normalize(lightDistance);    

                float diffuseLightIntensity = max(0.0, dot(surfaceNormal, lightDirection));
                fragData[i] += (vec4(diffuseLightIntensity,diffuseLightIntensity,diffuseLightIntensity,1));    

                vec3 reflectionDirection = normalize(reflect(-lightDirection, surfaceNormal));

                float specular = max(0.0, dot(reflectionDirection,  -normalize(vertexPosition)));

                if (diffuseLightIntensity != 0) {
                    float fspecular = pow(specular, spec);
                    vec4 fspec = vec4(fspecular*specA, fspecular*specA, fspecular*specA,1);
                    fragData[i] += fspec;
                }
                fragData[i] *= lightColor[i]; 
                fragData[i] *= 0.1;
                fragData[i].a = 0;
                fragData[i] *= att;
                endColor += fragData[i];
            }
        }  

    } 

    gl_FragData[0] = endColor * color;

}
1

There are 1 best solutions below

0
On

I solved the primary problem! This was good enough for me. It appears the problem I was having was that I had to many instructions per fragment shader (because of the for loop). When I adjusted the shader to only allow one light it worked as expected! I just use blending to take care of everything as I used to, but run the shader more. The downside is It requires more filtrate, but the upside is it works on older hardware and laptops.

I still can't figure out what's causing the ghosting, but it is less important to me, as I have a poor fix for that.