在OpenGL中使用颜色立方体贴图进行阴影贴图

时间:2017-10-19 16:15:31

标签: c++ opengl shadow-mapping

我正在尝试在OpenGL中制作一个全方位阴影贴图(来自点光源)。为了避免在世界空间和光照空间之间传递大量矩阵并使用深度图,我想我可能能够使用颜色纹理并将距离(在世界空间中)编码到其中。我发现了其他一些stackoverflow响应,说这就是现在通常做的,但实际上并没有详细说明这个过程。

在大多数情况下,我正在学习本教程:http://ogldev.atspace.co.uk/www/tutorial43/tutorial43.html

这是我的初始化函数:

glGenFramebuffers(1, &depthBuffer);

glGenTextures(1, &shadowMap);
glBindTexture(GL_TEXTURE_CUBE_MAP, shadowMap);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);

for (uint i = 0 ; i < 6 ; i++) {
    glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, GL_R32F, 1024, 1024, 0, GL_RED, GL_FLOAT, NULL);
}

glBindFramebuffer(GL_FRAMEBUFFER, depthBuffer);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_CUBE_MAP_POSITIVE_X, shadowMap, 0);

glGenRenderbuffers(1, &renderBuffer);
glBindRenderbuffer(GL_RENDERBUFFER, renderBuffer);
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT24, 1024, 1024);

glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, renderBuffer);

这是我的第一个渲染过程:

struct CameraDirection {
    GLenum CubemapFace;
    glm::vec3 Target;
    glm::vec3 up;
};

CameraDirection gCameraDirections[6] =
        {
                { GL_TEXTURE_CUBE_MAP_POSITIVE_X, glm::vec3(1.0f, 0.0f, 0.0f),  glm::vec3(0.0f, 1.0f, 0.0f) },
                { GL_TEXTURE_CUBE_MAP_NEGATIVE_X, glm::vec3(-1.0f, 0.0f, 0.0f), glm::vec3(0.0f, 1.0f, 0.0f) },
                { GL_TEXTURE_CUBE_MAP_POSITIVE_Y, glm::vec3(0.0f, 1.0f, 0.0f),  glm::vec3(0.0f, 0.0f, -1.0f) },
                { GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, glm::vec3(0.0f, -1.0f, 0.0f), glm::vec3(0.0f, 0.0f, 1.0f) },
                { GL_TEXTURE_CUBE_MAP_POSITIVE_Z, glm::vec3(0.0f, 0.0f, 1.0f),  glm::vec3(0.0f, 1.0f, 0.0f) },
                { GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, glm::vec3(0.0f, 0.0f, -1.0f), glm::vec3(0.0f, 1.0f, 0.0f) }
        };

shadowShader->Enable();

glCullFace(GL_FRONT);

glBindFramebuffer(GL_FRAMEBUFFER, depthBuffer);
glViewport(0,0,1024,1024);

glm::mat4 oldView = view;
glm::mat4 oldProj = projection;

glm::vec3 offset = *Object::globalOffset;
offset *= -1;

projection = glm::perspective(45.0f, 1.0f, .1f, 1000000.0f);

glClearColor(FLT_MAX, FLT_MAX, FLT_MAX, FLT_MAX);
for (auto& gCameraDirection : gCameraDirections) {
    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, gCameraDirection.CubemapFace, shadowMap, 0);
    glDrawBuffer(GL_COLOR_ATTACHMENT0);
    glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);

    view = glm::lookAt(offset, offset + gCameraDirection.Target, gCameraDirection.up);

    renderScene();
}

view = oldView;
projection = oldProj;
glViewport(0, 0, windowWidth, windowHeight);

我的影子着色器:

#version 330

layout (location = 0) in vec3 positionM;

uniform mat4 modelViewProjectionMatrix;
uniform mat4 modelMatrix;

out vec3 worldPos;

void main(void) {
    gl_Position = modelViewProjectionMatrix * vec4(positionM, 1.0);
    worldPos = (modelMatrix * vec4(positionM, 1.0)).xyz;
}

片段:

#version 330 core

in vec3 worldPos;

uniform vec3 lightW3;

layout (location = 0) out float fragDepth;

void main(void) {
    fragDepth = length(worldPos - lightW3);
}

在我的普通渲染片段着色器中,我对立方体贴图进行了采样:

...

uniform samplerCube gShadowMap;

void main(void) {

    float distance = length(lightW3 - positionW);

    if(texture(gShadowMap, positionW - lightW3).x - distance >= 0.01 ) {
        frag_color.rgba = vec4(1.0, 0.0, 0.0, 1.0);
    } else {
        frag_color.rgba = vec4(0.0, 0.0, 0.0, 1.0);
    }
}

我现在正在渲染一个球体,所以我期待面向光线的球体侧面是红色的,面朝外的一面是黑色的,但是整个球体都是红色的,这让我相信我的阴影传递实际上没有正确地绘制到纹理,并将所有内容保留为默认FLT_MAX。我做错了什么?

编辑:根据@ Rabbid76的建议添加了渲染缓冲区

0 个答案:

没有答案