OpenGL中的延迟渲染?

3
我有一个关于延迟着色实现的奇怪问题。我通过MRT将所需信息渲染到FBO中,目前是世界空间中的漫反射、位置和法线,看起来像这样:

enter image description here

对于所有三个纹理,都使用以下设置完成:
diffuse = std::shared_ptr<bb::Texture>(new bb::Texture(GL_TEXTURE_2D)); // generates texture ID
diffuse->bind();
diffuse->texture2D(0, GL_RGB, width, height, 0, GL_RGB, GL_FLOAT, 0); // glTexture2D
diffuse->parameterf(GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
diffuse->parameterf(GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
diffuse->parameterf(GL_TEXTURE_MIN_FILTER, GL_LINEAR);
diffuse->parameterf(GL_TEXTURE_MAG_FILTER, GL_LINEAR);
diffuse->unbind();
texture2D(GL_COLOR_ATTACHMENT0+1, diffuse->getID(), 0);

接着在我的绘图阶段中使用它们:

dsShader->bind();
dsShader->enableVertexAttribArrays();

ds->diffuse->bind(GL_TEXTURE0); // "ds" is an FBO containing the textures
ds->position->bind(GL_TEXTURE0+1);
ds->normal->bind(GL_TEXTURE0+2);

dsShader->sendUniform("diffuse", 0);
dsShader->sendUniform("position", 1);
dsShader->sendUniform("normal", 2);

dsShader->sendUniform("camera", camera3D->position.x, camera3D->position.y, camera3D->position.z);

dsOut->indexBuffer->bind();
dsOut->vertex2Buffer->bind();
dsOut->vertex2Buffer->vertexAttribPointer(dsShader->getAttribLocation("vertex0"), 2, GL_FLOAT, false, 0, 0);

glDrawElements(GL_TRIANGLES, dsOut->indexBuffer->size(), GL_UNSIGNED_INT, 0);

ds->diffuse->unbind();
ds->position->unbind();
ds->normal->unbind();

dsShader->disableVertexAttribArrays();
dsShader->unbind();

使用以下着色器(只需要必要的部分,光源是硬编码):

struct DirLight{
    vec3 direction;
    vec4 diffuse, specular;
};

uniform sampler2D diffuse;
uniform sampler2D position;
uniform sampler2D normal;

uniform vec3 camera;

DirLight light0 = DirLight(vec3(1, 1, 0), vec4(0.3), vec4(0.1));

in vec2 vertex;

void main(){
    vec4 color = texture(diffuse, vertex)*0.5;
    vec3 p = vec3(texture(position, vertex));
    vec3 n = normalize(vec3(texture(normal, vertex)));

    float ndotl = max(dot(n, normalize(light0.direction)), 0.0); // simple phong

    if(ndotl > 0.0){
        color += ndotl*light0.diffuse;
    }

    gl_FragColor = color;
}

奇怪的是,如果我将光源的方向设置为负值,比如说:
DirLight light0 = DirLight(vec3(-1, 0, 0), vec4(0.3), vec4(0.1));

最终结果没有着色。对于正值(或多或少)看起来正确。 这是输出的图片:

enter image description here

而且法线也可能存在问题,标记在红色区域。

听起来像是法线的问题。你尝试过不使用延迟渲染来渲染场景吗? - Gurgadurgen
是的,我尝试过了,没有问题。您可以在第一张图片中看到所有树纹理的输出。我忘记提到的是我的z轴是上轴。 - Kugel
看起来你的法线反了,在第一个里面。我建议先尝试修复它,然后再回来测试负值。 - Gurgadurgen
1
你们的普通G-Buffer格式是什么?在你们附加的截图中,你们忽略了将法线缩放和偏移到可见颜色范围内...也就是说,任何具有负值的法线在默认帧缓冲区上显示时都会被GL裁剪为黑色。如果你们试图将法线存储在像GL_RGB这样的格式中,那么G-Buffer本身也会有这种行为。你们可以使用类似于GL_RGB8_SNORM的东西,或者手动缩放到[0,1]并使用* 2.0 - 1.0技巧来缩放回[-1,1]。 - Andon M. Coleman
1
@AndonM.Coleman,你的解决方案似乎已经为OP解决了问题。你应该考虑将其发布为答案。 - Jason C
显示剩余4条评论
1个回答

2

好的,Andon M. Coleman提供的解决方案可行,我将内部格式切换为GL_RGB8_SNORM。 感谢您的帮助 :)


3
由于这个出现在旗帜审查队列中,这里有一个提示给审核者:这实际上是一个答案,而不是“谢谢”。目前没有其他回答发布在这个问题下。这个答案是在问题评论中提出的,而且OP已经很好地总结了答案。@user3476897:如果Andon决定发表答案,请建议接受他的答案。 - Jason C

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接