很早就想看阴影映射,一直拖到了现在,今天终于看了单方向的阴影映射,然后搭了个场景看了一下效果(每次搭场景感觉有点麻烦)。
阴影映射的大体过程:
// 1. 首选渲染深度贴图 glViewport(0, 0, SHADOW_WIDTH, SHADOW_HEIGHT); glBindFramebuffer(GL_FRAMEBUFFER, depthMapFBO); glClear(GL_DEPTH_BUFFER_BIT); ConfigureShaderAndMatrices(); RenderScene(); glBindFramebuffer(GL_FRAMEBUFFER, 0); // 2. 像往常一样渲染场景,但这次使用深度贴图 glViewport(0, 0, SCR_WIDTH, SCR_HEIGHT); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); ConfigureShaderAndMatrices(); glBindTexture(GL_TEXTURE_2D, depthMap); RenderScene();
思路:
1、渲染深度贴图
以光源的位置为相机位置进行一遍渲染,当然了得使用GBuffer(延迟着色)进行离屏渲染,这样可以将深度存入一张纹理。之后可以通过平面贴图的方式展示深度贴图的模样,方便检验深度贴图的正确性。
2、渲染阴影
这一步和正常渲染一样,只是要加入深度判断。对于当前的片元,将其位置转换到光源的视图下的坐标,这样可以从深度图中采样对应其的深度贴图中的坐标,深度贴图中表示对应片元射线下的最近片元的深度值,将当前的片元的深度值与从depth texture中采样的深度值进行比较,大于采样的深度值则表示片元位于阴影中。
看起来有点不对,深度纹理采用了循环采样的设置,一些不该有阴影的地方出现了阴影。更改深度纹理的属性设置。
GLuint WKS::Texture::GenDepthTexture(GLuint width, GLuint height) { glGenTextures(1, &this->textureID); glBindTexture(GL_TEXTURE_2D, this->textureID); glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, width, height, 0, GL_DEPTH_COMPONENT, GL_FLOAT, NULL); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_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 borderColor[] = { 1.0, 1.0, 1.0, 1.0 }; glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, borderColor); glBindTexture(GL_TEXTURE_2D, 0); return this->textureID; }
好多了。
当然了,这样的阴影范围有限,要获取完整的阴影需要使用点阴影的方式,对六个方向获取深度纹理。(见下节)