我正在尝试在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的建议添加了渲染缓冲区