◰GL-阴影贴图核心步骤

Posted itzyjr

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了◰GL-阴影贴图核心步骤相关的知识,希望对你有一定的参考价值。

第一轮:在光源视角渲染场景
1.创建自定义帧缓冲区

glGenFramebuffers(1, &shadowBuffer);

2.创建并绑定阴影纹理,设置阴影贴图及参数

glGenTextures(1, &shadowTex);
glBindTexture(GL_TEXTURE_2D, shadowTex);
// specify a two-dimensional texture image
glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT32,
		     screenW, screenH, 0, GL_DEPTH_COMPONENT, GL_FLOAT, 0);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_REF_TO_TEXTURE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC, GL_LEQUAL);
// may reduce shadow border artifacts
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);

3.绑定帧缓冲区

glBindFramebuffer(GL_FRAMEBUFFER, shadowBuffer);

4.将深度信息附加到帧缓冲区的阴影纹理附件上
如果纹理对象的图像被附加到帧缓冲区,OpenGL将执行“渲染到纹理”,即深度信息都在阴影纹理中了,这样就可用纹理中的深度信息来判断点是否在阴影里。

// attach a level of a texture object as a logical buffer of a framebuffer object
glFramebufferTexture(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, shadowTex, 0);

5.禁用颜色缓冲(即禁用颜色输出)

// GL_NONE:No color buffers are written
glDrawBuffer(GL_NONE);

6.启用深度测试

glEnable(GL_DEPTH_TEST);

7.在光照空间绘制两物体(一个遮挡另一个)

glDrawArrays(..one.);
glDrawArrays(..two.);

8.顶点着色器Ⅰ:正常输出经光照空间MVP矩阵变换后的坐标。
 片段着色器Ⅰ:什么也不做。
因为深度测试是在片段着色器之后进行,Alpha测试->模板测试->深度测试。所以必须正常输出经MVP矩阵变换后的坐标。因为不需要上色,所以片段着色器1什么也不用做。

// 顶点着色器Ⅰ
gl_Position = shadowMVP * vec4(vertPos, 1.0);

// 片段着色器Ⅰ
void main(void) 

第二轮:在相机视角渲染场景
1.中断帧缓冲
由于我们的帧缓冲不是默认帧缓冲,渲染指令将不会对窗口的视觉输出有任何影响。出于这个原因,渲染到一个不同的帧缓冲被叫做离屏渲染(Off-screen Rendering)。要保证所有的渲染操作在主窗口中有视觉效果,我们需要再次激活[默认帧缓冲],将它绑定到0。

// 切换回默认帧缓冲
glBindFramebuffer(GL_FRAMEBUFFER, 0);

2.激活#0纹理单元并绑定阴影纹理
此时就将带有深度信息的纹理复制到阴影纹理单元了。

glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, shadowTex);

3.启用颜色缓冲区(即启用颜色输出)

// GL_FRONT:Only the front left and front right color buffers are written
glDrawBuffer(GL_FRONT);

4.构建两个MVP矩阵作为统一变量:一个是相机空间MVP矩阵,一个光照空间BMVP矩阵。
5.在相机空间绘制两物体(一个遮挡另一个)
6.顶点着色器Ⅱ:

[out] shadow_coord = shadowBMVP * vec4(vertPos, 1.0);
[out] gl_Position = proj_matrix * mv_matrix * vec4(vertPos, 1.0);

片段着色器Ⅱ:

in vec4 shadow_coord;
layout(binding = 0) uniform sampler2DShadow shadowTex;
main() 
	// 0:在阴影里,1:不在阴影里
	float inShadow = textureProj(shadowTex, shadow_coord);

以上是关于◰GL-阴影贴图核心步骤的主要内容,如果未能解决你的问题,请参考以下文章

使用带有延迟渲染 Opengl 3.3 的阴影贴图的问题

如何在 OpenGL 中使用立方体贴图数组来渲染带有阴影贴图的多个点光源?

OpenGL阴影映射几乎可以工作

OpenGL 阴影贴图

阴影贴图未正确投影

Linux OpenGL 实践篇-11-shadow