我终于让我的GBuffer工作了(不是真的),但现在我有一些奇怪的问题,我找不到原因。
当我将普通纹理绘制到屏幕时,法线总是向我显示(蓝色始终指向相机)。我不知道如何正确解释,所以这里有一些屏幕:
(我认为这就是为什么我的灯光通过看起来很奇怪的问题)
以下是我创建GBuffer的方法:
glGenFramebuffers(1, &fbo);
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo);
// generate texture object
glGenTextures(GBUFFER_NUM_TEXTURES, textures);
for (unsigned int i = 0; i < 4; i++)
{
glBindTexture(GL_TEXTURE_2D, textures[i]);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16F, width, height, 0, GL_RGBA, GL_FLOAT, 0);
glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + i, GL_TEXTURE_2D, textures[i], 0);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
}
// generate depth texture object
glGenTextures(1, &depthStencilTexture);
glBindTexture(GL_TEXTURE_2D, depthStencilTexture);
glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT32, width, height, 0, GL_DEPTH_COMPONENT, GL_FLOAT,NULL);
glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, depthStencilTexture, 0);
// generate output texture object
glGenTextures(1, &outputTexture);
glBindTexture(GL_TEXTURE_2D, outputTexture);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB32F, width, height, 0, GL_RGB, GL_FLOAT, NULL);
glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT4, GL_TEXTURE_2D, outputTexture, 0);
GLenum Status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
assert(Status == GL_FRAMEBUFFER_COMPLETE);
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
这里是Geometry Pass:
glEnable(GL_DEPTH_TEST);
glDepthMask(true);
glCullFace(GL_BACK);
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo);
GLenum DrawBuffers[] = {GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1, GL_COLOR_ATTACHMENT2, GL_COLOR_ATTACHMENT3};
glDrawBuffers(GBUFFER_NUM_TEXTURES, DrawBuffers);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity();
camera.Render();
geoProgram->Use();
GLfloat mat[16];
glPushMatrix();
glTranslatef(0,0,-20);
glRotatef(rot, 1.0, 0, 0);
glGetFloatv(GL_MODELVIEW_MATRIX,mat);
glUniformMatrix4fv(worldMatrixLocation, 1, GL_FALSE, mat);
glutSolidCube(5);
glPopMatrix();
glPushMatrix();
glTranslatef(0,0,0);
glGetFloatv(GL_MODELVIEW_MATRIX,mat);
glUniformMatrix4fv(worldMatrixLocation, 1, GL_FALSE, mat);
gluSphere(sphere, 3.0, 20, 20);
glPopMatrix();
glDepthMask(false);
glDisable(GL_DEPTH_TEST);
这里是几何传递着色器:
[Vertex]
varying vec3 normal;
varying vec4 position;
uniform mat4 worldMatrix;
void main( void )
{
gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
position = worldMatrix * gl_Vertex;
normal = (worldMatrix * vec4(gl_Normal, 0.0)).xyz;
gl_TexCoord[0]=gl_MultiTexCoord0;
}
[Fragment]
varying vec3 normal;
varying vec4 position;
void main( void )
{
gl_FragData[0] = vec4(0.5, 0.5, 0.5, 1);//gl_Color;
gl_FragData[1] = position;
gl_FragData[2] = vec4(normalize(normal),0);
gl_FragData[3] = vec4(gl_TexCoord[0].st, 0, 0);
}
对于长问题/代码片段感到抱歉,但我不知道下一步该做什么,我用其他GBuffer实现检查了所有内容但是找不到错误。
//编辑:
好吧,看来你是对的,问题不是gbuffer,而是照明传递。我已经玩了很多,但不能让它工作:(
这是照明通行证:
[vs]
void main( void )
{
gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
}
[fs]
uniform sampler2D colorMap;
uniform sampler2D positionMap;
uniform sampler2D normalMap;
uniform sampler2D texcoordMap;
uniform vec2 screenSize;
uniform vec3 pointLightPostion;
uniform vec3 pointLightColor;
uniform float pointLightRadius;
void main( void )
{
float lightDiffuse = 0.5;
float lightSpecular = 0.7;
vec3 lightAttenuation = vec3(1.4, 0.045, 0.00075);
vec2 TexCoord = gl_FragCoord.xy / screenSize.xy;
vec3 WorldPos = texture2D(positionMap, TexCoord).xyz;
vec3 Color = texture(colorMap, TexCoord).xyz;
vec3 normal = texture(normalMap, TexCoord).xyz;
normal = normalize(normal);
vec3 lightVector = WorldPos - pointLightPostion;
float dist = length(lightVector);
lightVector = normalize(lightVector);
float nDotL = max(dot(normal, lightVector), 0.0);
vec3 halfVector = normalize(lightVector - WorldPos);
float nDotHV = max(dot(normal, halfVector), 0.0);
vec3 lightColor = pointLightColor;
vec3 diffuse = lightDiffuse * nDotL;
vec3 specular = lightSpecular * pow(nDotHV, 1.0) * nDotL;
lightColor += diffuse + specular;
float attenuation = clamp(1.0 / (lightAttenuation.x + lightAttenuation.y * dist + lightAttenuation.z * dist * dist), 0.0, 1.0);
gl_FragColor = vec4(vec3(Color * lightColor * attenuation), 1.0);
}
如果有必要,我还可以发布sencil通行证和/或所有其他处理。
答案 0 :(得分:5)
我知道这有点老了但我想让你知道经过多次研究后我得到了一切! 我只想在这里发帖,如果有人遇到类似/相同的问题。
实际上位置图是完全错误的(我的照明模型也是如此,但那是另一个故事:))。正如您已经说过的,我正在使用固定管道功能(这真的很愚蠢)。 实际的失败是我得到了“模型矩阵”
glGetFloatv(GL_MODELVIEW_MATRIX,mat);
glUniformMatrix4fv(worldMatrixLocation, 1, GL_FALSE, mat);
实际上是modelmatrix *固定管道中的viewmatrix。所以我将所有内容都改为自定义模型计算,瞧,位置图是正确的。 (您也可以使用固定功能管道并设置具有匹配值的自定义模型矩阵,并将其作为模型矩阵输入到着色器中,但这只是脏的)。 多亏了你,我得到了正确的方法,并设法理解矩阵计算和着色器等更多!
顺便说一下:gbuffer现在看起来像这样(纹理位置实际上是不必要的:)):
答案 1 :(得分:2)
从你在评论中发布的链接看你的解决方案,首先引起我注意的是: 在照明传递顶点着色器中,你做
viewSpace = gl_ModelViewMatrix * gl_Vertex;
然后在片段着色器中执行
vec3 lightPos = pointLightPostion * viewSpace;
vec3 WorldPos = texture2D(positionMap, TexCoord) * viewSpace;
vec3 normal = texture2D(normalMap, TexCoord) * viewSpace;
这完全没有意义。
现在,你正在进行延迟着色,这是一种典型的现代openGL(3.2+)技术,它不能很好地运行古老的硬件,我认为你使用了this tutorial形式的东西,它也是现代的openGL,那你为什么要用glPushMatrix
和那种旧东西?太糟糕了,我从来没有学过旧的openGL,所以我并不总是确定我能正确理解你的代码
顺便说一下,回到几何传递。在顶点着色器中,您可以
position = gl_ModelViewMatrix * gl_Vertex;
normal = (modelMatrix * vec4(gl_Normal,0.0)).xyz;
但是你在视图空间中的位置和模型空间中的正常位置。 (如果传递给着色器的modelMatrix实际上是模型矩阵,因为从屏幕截图中,法线似乎在视图空间中)。
另外,请注意,如果法线不在视图空间中,但在模型空间中,则必须偏向并缩放法线normal = 0.5f*(modelMatrix * vec4(gl_Normal,0.0)).xyz +1.0f;
。我只是去找
position = gl_ModelViewMatrix * gl_Vertex;
normal = (gl_ModelViewMatrix * vec4(gl_Normal,0.0)).xyz;
请记住,重要的是你在同一个空间同时拥有位置和法线。您可以使用世界空间或视图空间,但随后坚持您的选择。 在照明通道中,只需执行
vec3 WorldPos = texture2D(positionMap, TexCoord).rgb;
vec3 normal = texture2D(normalMap, TexCoord).rgb;
vec3 lightVector = WorldPos - pointLightPostion;
并确保pointLightPostion
与您决定的空间相同,通过在应用程序中转换它,在CPU端,然后将其传递给已经转换的openGL。
另外,我不明白你为什么这么做
lightColor += diffuse + specular;
不是
lightColor *= diffuse + specular;
通过这种方式,您的灯光中会有一个发光组件,其中包含灯光的颜色以及没有它的漫反射和镜面反射。它似乎不是一个不错的选择,特别是在延迟着色中,您可以轻松地在整个帧上执行环境传递。
希望我能帮到你。太糟糕了,我不使用过剩,我无法建立你的代码。 修改强>
要将pointLightPostion
(我假设已经在世界空间中)转换为视图空间,只需执行
pointLightPostion = (ViewMatrix * glm::vec4(pointLightPostion,1.0f)).xyz;