c++ - GLSL - 从阴影立方体贴图检索值时的结果不正确

标签 c++ opengl glsl shadow

当使用立方体贴图时,我在我的着色器中得到的结果与我的程序不一致。

出于测试目的,我编写了一个测试程序,它只创建一个深度立方体贴图纹理并将“1”写入它的所有面:

unsigned int frameBuffer;
glGenFramebuffers(1,&frameBuffer);

unsigned int texture;
glGenTextures(1,&texture);

glBindFramebuffer(GL_FRAMEBUFFER,frameBuffer);
glBindTexture(GL_TEXTURE_CUBE_MAP,texture);
glDrawBuffer(GL_NONE);
glReadBuffer(GL_NONE);

glTexParameteri(GL_TEXTURE_CUBE_MAP,GL_DEPTH_TEXTURE_MODE,GL_LUMINANCE);
glTexParameteri(GL_TEXTURE_CUBE_MAP,GL_TEXTURE_COMPARE_FUNC,GL_LEQUAL);
glTexParameteri(GL_TEXTURE_CUBE_MAP,GL_TEXTURE_COMPARE_MODE,GL_COMPARE_R_TO_TEXTURE);

unsigned int width = 512;
unsigned int height = 512;
for(unsigned int i=0;i<6;i++)
{
    glTexImage2D(
        GL_TEXTURE_CUBE_MAP_POSITIVE_X +i,
        0,
        GL_DEPTH_COMPONENT16,
        width,height,
        0,GL_DEPTH_COMPONENT,
        GL_FLOAT,
        0
    );
    glFramebufferTexture2D(GL_FRAMEBUFFER,GL_DEPTH_ATTACHMENT,GL_TEXTURE_CUBE_MAP_POSITIVE_X +i,texture,0);
}
unsigned int status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
if(status != GL_FRAMEBUFFER_COMPLETE)
    return;
float *data = new float[width *height];
for(unsigned long long i=0;i<(width *height);i++)
    data[i] = 1.f;
for(unsigned int i=0;i<6;i++)
{
    glTexSubImage2D(
        GL_TEXTURE_CUBE_MAP_POSITIVE_X +i,
        0,
        0,
        0,
        width,height,
        GL_DEPTH_COMPONENT,
        GL_FLOAT,
        &data[0]
    );
}
delete[] data;

// Check to see if data has been written correctly
data = new float[width *height];
for(unsigned int i=0;i<6;i++)
{
    glFramebufferTexture2D(GL_READ_FRAMEBUFFER,GL_DEPTH_ATTACHMENT,GL_TEXTURE_CUBE_MAP_POSITIVE_X +i,texture,0);
    glReadPixels(0,0,width,height,GL_DEPTH_COMPONENT,GL_FLOAT,&data[0]);
    for(unsigned long long j=0;j<(width *height);j++)
    {
        if(data[j] != 1.f)
            return;
    }
}
delete[] data;
// Check end    

渲染:

float screenVerts[18] = {
    -1.f,-1.f,0.f,
    1.f,-1.f,0.f,
    -1.f,1.f,0.f,
    -1.f,1.f,0.f,
    1.f,-1.f,0.f,
    1.f,1.f,0.f
};
unsigned int vertexBuffer;
glGenBuffers(1,&vertexBuffer);
glBindBuffer(GL_ARRAY_BUFFER,vertexBuffer);
glBufferData(GL_ARRAY_BUFFER,sizeof(float) *18,&screenVerts[0],GL_STATIC_DRAW);

glUseProgram(shader);
glBindTexture(GL_TEXTURE_CUBE_MAP,texture);
glEnableVertexAttribArray(0);
glBindBuffer(GL_ARRAY_BUFFER,vertexBuffer);
glVertexAttribPointer(0,3,GL_FLOAT,GL_FALSE,0,(void*)0);
    glDrawArrays(GL_TRIANGLES,0,6);
glDisableVertexAttribArray(0);

顶点着色器:

#version 330 core

layout(location = 0) in vec3 vertPos;

out vec2 UV;

void main()
{
    gl_Position =  vec4(vertPos,1);
    UV = (vertPos.xy +vec2(1,1)) /2.0;
}

片段着色器:

#version 330 core

in vec2 UV;

out vec3 color;

uniform samplerCubeShadow testShadow;

void main()
{
    color.r = texture(testShadow,vec4(0,0,1,1)); 
    // Just grab the value from a random direction and put it out as red color
}

(我已经从另一种语言移植了 C++ 代码,所以如果您发现其中有一些语法错误,请不要介意,它们不在实际代码中)

glGetError() 不返回任何错误。

ReadPixels 证明写入过程有效,但结果是黑屏。这意味着着色器内部的纹理调用返回 0,这应该是不可能的,无论我使用什么作为方向 vector 。

我错过了什么?

最佳答案

您始终将 glBind*() 调用的参数颠倒过来。它们都将目标作为第一个参数,将对象 ID(又名名称)作为第二个参数。而不是这个:

glBindFramebuffer(frameBuffer,GL_FRAMEBUFFER);
glBindTexture(texture,GL_TEXTURE_CUBE_MAP);
glBindBuffer(vertexBuffer,GL_ARRAY_BUFFER);

应该是这样的:

glBindFramebuffer(GL_FRAMEBUFFER, frameBuffer);
glBindTexture(GL_TEXTURE_CUBE_MAP, texture);
glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);

代码中有其中一些实例的多个实例,因此请确保捕获所有实例。

除此之外,如果这是完整的代码,您就不会渲染到屏幕上。您有一个没有颜色附件绑定(bind)的 FBO,因此输出无处可去。如果你想渲染到屏幕上,你需要解除绑定(bind) FBO:

glBindFramebuffer(GL_FRAMEBUFFER, 0);

您还将未定义片段输出的 gb 组件,因为您只写入 r

关于c++ - GLSL - 从阴影立方体贴图检索值时的结果不正确,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24893101/

相关文章:

opengl - GLSL 宏扩展可以做到这一点吗?

java - Libgdx 的 Matrix4#translate() 无法按预期工作

c - 从C中的堆栈中删除字符串

iphone - 有没有办法在 iPhone 上使用汇编手工编码着色器而不是使用 GLSL?

opengl - OpenGL/GLSL 着色器中的统一位置之间是否存在间隙是否重要?

c++ - 什么是 ATOMIC_FLAG_INIT 以及它应该如何使用?

windows - 在 Windows 上,OpenGL 与 DirectX 有何不同?

c++ - 类模板的动态实例化被认为是显式的还是隐式的?

c++ - 如何在标题中添加文件夹以及 .a 是如何工作的?

android - 使用任意 Boost 库进行奇怪的 NDK 编译