编辑:更改片段着色器,以便每次运行只有一个光可以解决我的第一个问题。我的第二个问题仍然存在。
提前感谢您提供的任何帮助。几周以来,我一直在为我的 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_RGBA32f
或GL_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 时,重影变得不那么明显,但仍然存在,所以我认为这意味着片段着色器的一次运行会导致这些重影。
感谢任何人对这两个问题的任何帮助,非常感谢。如果您有任何问题要问我,尽管我可能需要一些时间才能回复您,但我会尽快回复您。
编辑对不起,我忘记了我的着色器代码: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;
}