在OpenGL中渲染纹理深度时的奇怪结果

时间:2014-01-05 05:54:30

标签: c++ opengl game-engine

我正在处理图形引擎的纹理组件的渲染。我花了几个小时在DX上实现它,它按预期工作,我花了几天时间在OpenGL实现上,但它拒绝工作。

当将深度缓冲区渲染到纹理时,我获得了一些预期的结果,但是图像完全是奇怪的伪像(颜色目标工作正常)。我玩了各种深度和模板位配置,不同的绑定方法,但我没有在哪里。

我会发布我的结果以及我所拥有的相关代码导致“最接近”正确结果。

场景是大量的大炮,大炮前面的摄像机位置,在摄像机前面有一架飞机。飞机的纹理是围绕大炮旋转的第二个摄像机的渲染结果。我希望飞机大部分是红色的,有一些较暗的红色区域,物体靠近第二个摄像机。

以下是我在DX中得到的结果(这是我的预期):[1]:http://i.imgur.com/Zfchzq3.png“结果好”

以下是我从GL获得的结果:[2]:http://i.imgur.com/vH9u1bq.png“奇怪的结果”

我不知道黑色部分来自哪里。通过一些着色器调试我可以看出,未渲染的区域保持为1.0(深度清晰值),非黑色区域接近1.0但从未达到它(正如我所料)。黑色区域是......随机的。

我用来创建纹理的代码是:

glGenTextures(1, &textureID);
dim = GL_TEXTURE_2D;
wth = width;
hgt = height;
iFormat = _glTranslateFormat(fmt, format, type);
glBindTexture(dim, textureID);
glTexStorage2D(dim, 1, iFormat, width, height);

_glTranslateFormat将原生格式转换为GL格式,这将返回GL_DEPTH_COMPONENT16 atm。我尝试了其他格式,它们甚至给出了更奇怪的结果。 32和32F允许采样的值远远超出0和1的范围(如高于1000000000),基于模板也会导致各种问题(即使我更改代码以考虑模板)。

我用来将它绑定到帧缓冲区的代码是:

glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, d->_exposeTexture()->_exposeAPI(), 0);

_exposeAPI返回纹理的ID。每次代码要求深度缓冲区绑定到不同的帧缓冲区时都会发生这种情况(帧缓冲区将在手边绑定)。

我已经尝试过将渲染目标绑定到帧缓冲区的各种方法,但是没有,但问题似乎永远不会消失。任何帮助将不胜感激。现在我将不得不放弃引擎的OpenGL组件并使用DX,直到找到解决此问题的方法。

编辑:根据要求我添加了负责从纹理中采样的着色器,文件末尾的内容只是调试我玩过的代码。深度纹理作为漫反射纹理进入。

    #version 430

    struct Light
       {
       vec4 diffuse;
       vec4 specular;
       vec4 attenuation;
       vec3 spot;
       uint nID;
       uint type;
       };

    layout (std140, binding = 9) uniform singleLight
       {
       Light light;
       };

    struct BasicFSInput
       {
       vec4 position;
       vec3 normal;
       vec2 uv;
       vec4 fragPos;
       vec3 toLight;
       };

    layout(binding = 1) uniform sampler2D diff1;
    layout(binding = 2) uniform sampler2D amb1;
    layout(binding = 3) uniform sampler2D spec1;

    layout (location = 0) in BasicFSInput fin;
    layout (location = 0) out vec4 color;

    layout(std140, binding = 10) uniform material
       {
       float specular;
       float shininess;
       };

    void BasicFragmentShader()
       {
       vec4 dTexel = texture(diff1, fin.uv).rgba;
       vec4 aTexel = texture(amb1, fin.uv).rgba;
       vec4 sTexel = texture(spec1,fin.uv).rgba;

       vec3 lightDir = normalize(fin.toLight);
       vec3 n = normalize(fin.normal);
       float NdotL = max(dot(n, lightDir),0.0);
       vec4 col = NdotL * light.diffuse;
       vec4 ambContrib = aTexel;
       vec4 diffContrib = dTexel * col;

       vec3 refl = 2.0 * NdotL * n + lightDir;
       float NdotR = max(dot(normalize(refl), normalize(-fin.fragPos.xyz)),0.0);
       float specContrib = sTexel * specular * pow(NdotR, shininess);

       color = ambContrib + diffContrib + specContrib;/*
       if(dTexel.r < -1.0)
          color.r = 1.0f;
       if(dTexel.r > 1.0)
          color.b = 1.0f;
       if(dTexel.r == 1.0f)
          color.g = 1.0f;*/
       //color.r = dTexel.r;

       /*if(dTexel.r < 0.5f)
          color.b = 1.0f;
       if(dTexel.r > 0.5f)
          color.r = 1.0f;*/
       /*if(dTexel.r < -10000000.0f)
          color.g = 1.0f;*/
       //color.a = 1.0f;
       }

1 个答案:

答案 0 :(得分:1)

不要快速放弃OpenGL :)

您确定要将深度缓冲区渲染到纹理而不是纹理的颜色缓冲区吗?

也许下面可能会有所帮助(如果您已经知道这一点,请道歉)。 (它取自OpenGL Superbible第6版。)

设置帧缓冲区

    glGenFramebuffers(1, &fbo);
glBindFramebuffer(GL_FRAMEBUFFER, fbo);
    //texture for the colour buffer
glGenTextures(1, &colourTexture);
glBindTexture(GL_TEXTURE_2D, colourTexture);
glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, width, height);

glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    //texture for the depth buffer
glGenTextures(1, &depthTexture);
glBindTexture(GL_TEXTURE_2D, depthTexture);
glTexStorage2D(GL_TEXTURE_2D, 1, GL_DEPTH_COMPONENT32F, width, hwight);

glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, colourTexture, 0);
glFramebufferTexture(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, depthTexture, 0);

const GLenum drawBuffers[] = { GL_COLOR_ATTACHMENT0 };
glDrawBuffers(1, drawBuffers);

然后在调用glDrawArrays / Elements绑定到framebuffer

之前
    glBindFramebuffer(GL_FRAMEBUFFER, fbo);

稍后,当您想要将纹理渲染到屏幕时绑定纹理

     glBindTexture(GL_TEXTURE_2D, colourTexture);

在渲染纹理时片段内部需要一个采样器。

#version 430 core 
uniform sampler2D tex;  
in VS_OUT
{ 
    vec2 texcoord;
} fs_in;
out vec4 color;
void main(void)
{
color = texture(tex, fs_in.texcoord);
}