c++ - 带有聚光灯的 OpenGL 中的阴影映射会产生不寻常的效果

标签 c++ opengl glsl shadow-mapping

我一直在尝试实现阴影映射。虽然我认为我现在已经接近了,但我遇到了一个奇怪的效果(如下图所示):
Shadow Mapping
如您所见,阴影区域显得太小。对立方体本身也有不寻常的影响。
正在渲染的几何体是尺寸为 100.0 的正方形平面上尺寸为 1.0 的立方体。该场景包含一个角度(从一侧到另一侧)为 0.5 弧度且范围为 100.0 的聚光灯。此聚光灯围绕 y 轴运行并调整其旋转以查看原点。
我设置了帧缓冲区和深度纹理 (512 x 512),如下所示:

// Create and configure the depth texture.
glGenTextures(1, &m_depthTexture);
glBindTexture(GL_TEXTURE_2D, m_depthTexture);

glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);

glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER);

GLfloat border[] = { 1.0f, 1.0f, 1.0f, 1.0f };
glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, border);

glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_NONE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC, GL_LEQUAL);

glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT32, width, height, 0, GL_DEPTH_COMPONENT, GL_FLOAT, (void*)0);

// Assign the depth texture to texture channel 0.
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, m_depthTexture);

// Create and configure the framebuffer.
glGenFramebuffers(1, &m_framebuffer);
glBindFramebuffer(GL_FRAMEBUFFER, m_framebuffer);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, m_depthTexture, 0);
GLenum drawBuffers[] = { GL_NONE };
glDrawBuffers(1, drawBuffers);
然后我从聚光灯的角度将场景渲染到阴影贴图帧缓冲区。这似乎有效。使用 OpenGL 调试工具检查深度纹理显示以下内容:
Depth Texture
场景被第二次渲染,在那里我为深度纹理和阴影矩阵设置了统一:
glActiveTexture(GL_TEXTURE0 + 1);
glBindTexture(GL_TEXTURE_2D, shadowMap.depthTexture());
program->uniform("shadowMap", 1);

const M3D::Matrix4 lightViewMatrix = lightTransformComponent->transformationMatrix().inverse();

const float invTanHalfFov = 1.0f / std::tan(coneAngle * 0.5f);
const float nearClipPlane = 0.3f;
const float farClipPlane = lightLightComponent->range();
const float zRange = nearClipPlane - farClipPlane;
const Matrix4 lightProjectionMatrix(
    invTanHalfFov, 0.0f, 0.0f, 0.0f,
    0.0f, invTanHalfFov, 0.0f, 0.0f,
    0.0f, 0.0f, -(nearClipPlane + farClipPlane) / zRange, 2.0f * nearClipPlane * farClipPlane / zRange,
    0.0f, 0.0f, 1.0f, 0.0f
);

const Matrix4 shadowMatrix = lightProjectionMatrix * lightViewMatrix * modelMatrix;
program->uniform("shadowMatrix", shadowMatrix);
我在顶点着色器中计算阴影坐标:
f_shadowCoordinate = shadowMatrix * vec4(v_position, 1.0f);
然后,在片段着色器中,我投影该坐标并将其偏置到区间 [0, 1] 内的范围内。
vec2 projectedShadowCoordinates = (f_shadowCoordinate.xy / f_shadowCoordinate.w) * 0.5f + vec2(0.5f, 0.5f);
float shadowDistance = texture(shadowMap, projectedShadowCoordinates).x;
return vec4(1.0f) * shadowDistance;

最佳答案

该问题是由于在渲染到阴影帧缓冲区时错误地将投影矩阵设置为与相机的投影矩阵(而不是灯光的投影矩阵)一致。

关于c++ - 带有聚光灯的 OpenGL 中的阴影映射会产生不寻常的效果,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24645409/

相关文章:

C++(标准)异常和 Unicode

c++ - 如何在我的 Qt 应用程序中存储密码?

java - 我在哪里可以找到包 javax.media.opengl?

glsl - GLSL中的printf?

opengl - 有没有办法在 OpenGL 着色器中丢弃几何体、顶点或片段?

c++ - OpenGL 代码在一台计算机上运行缓慢(但在其他计算机上则不然)

c++ - 如何让你的程序重复递增,直到在 switch 语句中按下另一个键

Java Final 关键字 vs C++ 常量指针 vs C++ 引用

c - Opengl 在 3d 场景问题上绘制 2d 叠加

opengl - 带有 gl_ModelViewProjectionMatrix 的 GLSL 4.1