java - 延迟渲染管道无法在笔记本电脑图形卡上运行,以及奇怪的“模型重影”问题(glBlendFunc)

标签 java opengl lwjgl glblendfunc deferred-rendering

编辑:更改片段着色器,以便每次运行只能有一个光源解决了我的第一个问题。我的第二个问题仍然存在。

在此先感谢您提供的任何帮助。我已经为我的LWJGL渲染引擎开发了一个延迟着色管道,现在已经有几个星期了。尽管我设法按预期完成了所有工作,但是在将程序分发给一些我认识的人之后,我开始遇到问题。我会尽量保持简短。谢谢你陪我

我将从标题中的两个问题中的第一个开始。在我的机器(AMD Phenom II 965和Nvidia GTX 480)上,渲染器的最终产品完全符合预期。 (我打算发布指向图像的链接,但是由于我是新用户,因此我无法发布3个以上的超链接。但是可以说,它看起来应该是应该的。)

这正是我想要的,因此尽管渲染器工作正常。我将其发送给一个朋友(使用GT 440),他们得到了相同的结果。

此后不久,我将发动机的构造交给了我的一个有笔记本电脑(配有GT 540M)的朋友。这就是渲染器产生的(忽略FPS计数器,它不起作用):

http://i.imgur.com/DxxFEpy.png

显然,这根本不是我期望的结果。在我可以测试的其他所有移动图形卡上,我也得到了相同的结果。经过一个多星期的敲打,我的头才得以解决,直到照明通行证被称为glBlendFunc为止。我的代码如下:

    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);


您可能会注意到的第一件事是我绘制了一个四边形,然后清除了深度和颜色缓冲区。这将在我的下一个问题中得到解决,但是如果我的下一个问题与该问题密切相关,我不会感到惊讶。我几乎可以肯定(99%),问题出在这种方法上,因为在使用仅支持一盏灯但仍使用延迟管线的较旧版本的引擎进行测试时,我能够在测试的每台计算机上获得完美的结果。渲染器再次适用于我测试过的每个台式机图形卡,但不适用于任何笔记本电脑图形卡。除了这种方法,我几乎排除了所有其他方法。可能值得注意的是,我使用内部格式不是GL_RGBA32fGL_RGBA16f的纹理作为渲染目标并没有成功。有人看过这个吗,或者有人可以提供帮助吗?如果有人甚至不知道从哪里开始寻找问题,我将很乐意,因为我什么都没有。我已经完全无法自己找到解决方案。

然后转到第二个问题和第二个问题。在最后一个代码块的开头,我有几行代码在没有着色器的情况下在屏幕上创建了一个四边形:

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);


据我所知,此代码绝对不做任何事情。但是,当我删除四边形的图形时,窗口将显示以下内容:

http://i.imgur.com/mkMsP0F.png

除了“重影”外,我不知道该怎么称呼它,因为它就像一个鬼像(至少在我看来是这样)。当我旋转MV矩阵时,它会沿旋转的方向扭曲,第一组灯光(我使用7的数组)将其照亮,但其余部分将照亮实际模型。我无法解释为什么会发生这种情况,因为生成此图像的代码与上面的代码完全一样,但没有glCallList(quadList);,这意味着在进入循环之前,仍会清除深度和颜色缓冲区。我根本无法解释这个问题。是否有人知道什么地方出了问题以及如何解决,或者至少有什么地方出了错?

编辑我发现这仅发生在具有纹理坐标的模型上。我不知道为什么

编辑看起来当我将每个着色器中允许的灯光数量限制为1时,重影变得不那么明显了,但是仍然存在,所以我认为这意味着片段着色器的一次运行会导致这些重影。

感谢任何人对这两个问题有任何帮助,非常感谢。如果您有任何问题想问我,尽管可能要花点时间与您联系,但我会尽力尽快回复您。

编辑Sory,我忘记了我的着色器代码:
GeometryPass顶点:

uniform sampler2D tex;

varying vec3 surfaceNormal;
varying vec3 varyingVertex;

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

}


GeometryPass片段:

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顶点:

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


LightPass Phong片段

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;

}

最佳答案

我解决了主要问题!这对我来说足够好了。看来我遇到的问题是每个片段着色器必须有很多指令(由于for循环)。当我将着色器调整为仅允许一个光源时,它按预期工作!我只是像以前那样使用混合来处理所有事情,但是要多运行着色器。缺点是需要更多的滤液,但缺点是可以在较旧的硬件和笔记本电脑上使用。

我仍然不知道是什么导致了重影,但这对我来说并不重要,因为我对此不满意。

关于java - 延迟渲染管道无法在笔记本电脑图形卡上运行,以及奇怪的“模型重影”问题(glBlendFunc),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14533782/

相关文章:

opengl - opengl中的背面多边形

c++ - 在 OpenGL 中使用 imageStore 写入图像

rendering - LWJGL(裸)使用软件渲染还是硬件渲染?

java - LWJGL显示和java swing

java - 第一人称相机在移动眼睛时有奇怪的行为

java - 每个语言环境的 JSF 2 中的不同 facelets(用于模板)

Java 日历返回错误的月份

java - 为 Java 创建一个在输入/输出后不会关闭的循环回文程序

java - 无法打开 JPA EntityManager 进行交易;嵌套异常是 javax.persistence.PersistenceException

opengl - 使用 GLUT 和不使用 GLUT 的 OpenGL 编程有什么区别