OpenGL之ShadowMap
流程:先创建一个RenderTexture,然后用灯光的视口渲染。
然后切换到正常相机,进行渲染,使用RenderTexture中的深度或者颜色纹理,然后还原当前顶点在灯光中的深度,两者对比,比缓存中的大,则为阴影,两个相等则可以直接光照计算。两者都可以不过有一些区别:
1.使用ColorTexture,Shader中需要使用Sampler2D,在灯光的视图中需要对深度进行编码,即颜色等于深度,当然有一个转换关系。 vec3 color = EncodeDepth(depthj);
2.使用DepthTexture,Shader中使用的是Smapler2DShadow,这里通过texture2DProj,获取到的是一个float的值,即深度值。当然DepthTexture需要做以下设置,特别是GL_Compare_MODE和GL_NEARST
glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, w, h, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_BYTE, NULL); 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_COMPARE_MODE, GL_COMPARE_REF_TO_TEXTURE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC, GL_LESS); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
切换到正常相机渲染的时候需要注意:
如果你用的是BIAS矩阵,那么从刚才灯光生成的纹理中取值,需要的坐标是 B*P*V*M
如果用的是Shadow Matrix,那么坐标值为: 坐标: S*P*V*M;
其中ShadowMatrix的值,如下
0.5 0 0 0.5 0 0.5 0 0.5 0 0 0.5 0.5 0 0 0 1
需要注意的是Shader中的Shadow2D在400版本已经不能使用了,只能用textureProj。
以上来自于自我总结,书中的例子也不是很完善,但是根据理论应该是这样子的,
扩展:基于PCF的阴影或者柔化阴影,还有基于模板的阴影都有待探索。
---------------------------------《3D绘图程序设计 使用Direct3D和OpenGL》 (使用了gl_TextureMatrix,用的shader比较早)
--------------------------------- 《OpenGL Shading Language 3rd Edith》 (提出ShadowMatrix理论,但是例子很糟糕)
----------------------------------《OpenGL Shading Language 4th Edith》 (例子不够完善)