OpenGL - 无法写入帧缓冲区(或正确读取)

时间:2016-11-26 08:43:57

标签: opengl framebuffer shadow-mapping

所以我一直试图让阴影映射工作,但我没有成功,我现在试图简单地将任何东西写入帧缓冲区,然后将其渲染为四边形作为纹理。我一直在看这段小代码10个小时,所以我觉得最后可能是时候寻求帮助了。如果您需要更多信息或有些不清楚的地方,请告诉我。

我开始关注此tutorial。完成它两次后,直接复制粘贴第三次我放弃了,并开始寻找其他地方的信息。我目前的代码有点混乱,但我试图提取什么是至关重要的

以下是我如何使用TEXTURE2D设置我的FBO(_shadowMap和_shadowMapFBO是作为主程序的类中的私有变量):

glGenTextures(1, &_shadowMap);
glBindTexture(GL_TEXTURE_2D, _shadowMap);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT32, SHADOW_WIDTH, SHADOW_HEIGHT, 0, GL_DEPTH_COMPONENT, GL_FLOAT, NULL);

glGenFramebuffers(1, &_shadowMapFBO);
glBindFramebuffer(GL_FRAMEBUFFER, _shadowMapFBO);
glDrawBuffer(GL_NONE);
glReadBuffer(GL_NONE);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, _shadowMap, 0);
GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) 
{
    std::cout << "Frame buffer failed" << std::endl;
    system("pause");
    exit(1);
}
glBindFramebuffer(GL_FRAMEBUFFER, 0);

然后我在主循环中执行第一个渲染过程:

glViewport(0, 0, SHADOW_WIDTH, SHADOW_HEIGHT);
glBindFramebuffer(GL_FRAMEBUFFER, _shadowMapFBO);
glClear(GL_DEPTH_BUFFER_BIT);
_shadowShader.bind();
glBindVertexArray(_cubeVAO);
glDrawElements(GL_TRIANGLES, _numberOfIndicesCube, GL_UNSIGNED_SHORT, 0);
glBindVertexArray(_planeVAO);
glDrawElements(GL_TRIANGLES, _numberOfIndicesPlane, GL_UNSIGNED_SHORT, 0);
glBindFramebuffer(GL_FRAMEBUFFER, 0);
glDrawBuffer(GL_BACK);
glReadBuffer(GL_BACK);

最初我想创建一个阴影贴图,但此时我只是尝试使用以下着色器对(_shadowShader使用的那个)将附加到帧缓冲区的整个纹理写入显式值

顶点

#version 450

in layout(location=0) vec3 position;

uniform mat4 mvp;

void main()
{
    gl_Position = mvp * vec4(position, 1.0f);
}

片段

#version 450

out float depth;

void main()
{
    depth = 0.0f;
}

然后我尝试在四边形上显示纹理来完成:

glViewport(0, 0, _screenWidth, _screenHeight);
glClearColor(0.7f, 0.5f, 0.0f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
_testShader.bind();
glBindTexture(GL_TEXTURE_2D, _shadowMap);
glBindVertexArray(_quadVAO);
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, 0);

以下是quad的片段着色器:

#version 450

in vec2 textureCoordinates;

uniform sampler2D _shadowMap;

out vec4 color;

void main()
{
    float depth = texture2D(_shadowMap, textureCoordinates).r;
    color = texture2D(_shadowMap, textureCoordinates);
}

但令我持续沮丧的是,虽然我从片段着色器输出0.0f(黑色),但四边形看起来是白色的......我知道四边形能够显示纹理,因为我已经能够呈现正常的纹理在其上显示.jpg。所以,这就是我现在所处的位置;任何想法,指针,想法,动机词等?

编辑I:所以经过一段时间后,我至少发现纹理已正确加载并且我能够从中读取。我是通过在初始化期间将图像实际加载到它上然后不写入它来实现的。然后四边形正确显示纹理。所以我写作的方式肯定有问题。

编辑二:所以我得到了它的工作;我坐下来用TA和复制粘贴代码(是的,我知道......并没有比那更好)现在它可以工作了。谢谢Bart:)

1 个答案:

答案 0 :(得分:0)

你的阴影传递片段着色器是错误的:

#version 450

out float depth;

void main()
{
    depth = 0.0f;
}

这只是声明一个单一通道颜色输出,它将被写入颜色附件(你没有)。由于您要写入FBO的深度附件,因此必须使用内置gl_FragDepth输出变量。如果你不这样做,GL会将线性插值窗口空间深度值写入深度缓冲区。

请注意,通常情况下,将深度缓冲区清除为1.0,当使用典型的透视投影时,对象看起来非常接近1.0,比如0.99something,作为深度值,因此很可能转换为只有8位灰度的结果看起来都是白色的。