从光源透视图中渲染场景,并对最近的深度值进行采样,决定片段是否在阴影中
首先需要一张深度贴图,来计算阴影,将结果存储在纹理中
GLuint depthMapFBO;
glGenFramebuffers(1, &depthMapFBO);
然后创建一个2D纹理,作为帧缓冲的深度缓冲
使用正交投影矩阵
GLfloat near_plane = 1.0f, far_plane = 7.5f;
glm::mat4 lightProjection = glm::ortho(-10.0f, 10.0f, -10.0f, 10.0f, near_plane, far_plane);
创建一个视图矩阵来变换物体,使用glm::lookAt
glm::mat4 lightView = glm::lookAt(glm::vec3(-2.0f, 4.0f, -1.0f), glm::vec3(0.0f, 0.0f, 0.0f), glm::vec3(0.0f, 1.0f, 0.0f));
结合提供逛空间的变换矩阵
接着使用着色器将变换到光空间中,然后将深度贴图渲染到片段着色器上
片段着色器中,在阴影中时是1.0,在阴影外是0.0,然后用diffuse和specular乘以阴影元素,还要把逛空间片段位置转换为NDC空间,并进行透视除法,检查currentDepth是否高于closetDepth,判断片段是否在阴影中
当产生阴影偏移时,对表面的深度进行微小偏移
当产生悬浮时,进行正面剔除
glCullFace(GL_FRONT);
RenderSceneToDepthMap();
glCullFace(GL_BACK);
当采样过多时,将所有超出深度贴图的范围设为1.0,并将环绕模式设置为GL_CLAMP_TO_BORDER,投影z坐标大于1.0时,将shadow值设为0.0
PCF:在深度贴图中多次采样,产生柔和阴影