本节介绍的是阴影贴图(shadow map),或称为深度贴图(depth map)。改方法具有较好的表现里,在多种计算机图形学的场合,甚至电影特效中都有所使用。
如何实现阴影
基本思想:
太阳看不见阴影。
如果在光源处放置一位观察者,其实现方向与光线一致,那么观察者也看不到阴影。他看到的每一处都在光的照射下,而那些背后的,他没有看到的物体则处在阴影中。
这里需要用到光源与物体之间的距离(实际上也就是物体在光源坐标系下的深度z值)来决定物体是否可见。
需要两对着色器来实现阴影:
- 一对着色器来计算光源到物体的距离。
- 另一对着色器根据1中计算出的距离绘制场景。
使用一张纹理图像把(1)的结果传入(2)中,这纹理图像就被称为阴影贴图(shadow map) ,而通过阴影贴图实现的方法就被称为阴影映射(shadow mapping)。
阴影映射的过程:
- 将视点移到光源的位置处,并运行(1)中的着色器。这时,那些“将要被绘制出”的片元都是被光照射到的,即落在这个像素上的各个偏远中最前面的。我们并不实际绘制出片元的颜色,而是将片元的z值写入到阴影贴图中。
- 将视点移回到原来的位置,运行(2)中的着色器绘制场景。此时,我们计算出每个片元在光源坐标系(即(1)中的视点坐标系)下的坐标,并与阴影贴图中纪录的z值比较,如果前者大于后者,就说面当前片元处在阴影中,用较深暗的颜色绘制。
gl_FragCood
gl_FragCoord的内置变量是vec4类型的,用来表示片元的坐标。gl_FragCoord.x和gl_FragCoord.y是片元在屏幕上的坐标,而gl_FragCoord.z是深度值。他们是通过(gl_Position.xyz / gl_Position.y)/2.0 + 0.5算出来的,都被归一化到[0.0, 1.0]区间。如果gl_FragCoord.z是0.0 表示改片元类近裁面上,如果是1.0则表示改片元在远裁面上。