【openGL】阴影映射问题:shadow acne(阴影失真)和peter panning(阴影悬浮)
1.《Learn Opengl》第35章中提到,一般在按照光线投射产生深度贴图
的做法做阴影映射时,会出现摩尔纹
,这种现象叫shadow acne(阴影失真)
,会出现阴影失真的根本原因
是所生成的深度贴图的分辨率是有限的,就会造成在fragment位置处取深度图中的值发生采样就会出现问题。
- 如图:以四个格子为四个fragment为例,由于深度图分辨率有限四个格子会采样同一个深度值(由于纹理参数设置的是临近GL_NEAREST,设置线性也会有这个问题)。
3、如图假设采样这个四方格的正中心,假设这个深度值为10。
4、这四个fragment分别取名a,b,c,d,由于光源的位置会导致求得的四个距离会不一样,先求a到光源的距离假设为9.8<10,b到光源的距离是11.6 >10,c到光源的距离12.1>10,c到光源的距离9.5<10,。就会导致a和d亮,b和c暗,他们本来应该都是亮的才对。然后整个光源视椎体下各个片段都会出现这个问题,就会出现上面的明暗交错的条纹。
5、在《Learn Opengl》第35章中的图示如下,当然,这个看不懂就算了,毕竟画得比较抽象
6、《Learn Opengl》中说的解决方法是将fragment到光源的距离适当的缩小bias,就会避免这个问题,但是这种解决方法会带来另外一个问题,那就是peter panning(阴影悬浮)(名字应该取自彼得潘),bias越大悬浮的越厉害。
7、peter panning的一个解决方法是使用正面剔除
。
glCullFace(GL_FRONT);
使用正面剔除来生成深度贴图可以解决正面的阴影失真,也就是说只有物体背面才会产生深度信息,向地板这种只有一个面的物体不会产生深度信息,这也是合理的,但是这也只能在封闭的物体上这么做。
8、即使这样物体的背面还是会出现阴影悬浮,这时候可以用glPolygonOffset
来解决这个问题,将深度图中的值稍微减小一点而不是片段到光源的距离,两者结合就可以解决大部分问题。
9、结果: