候使用阴影贴图比较着色器,进行阴影渲染.
有一点要说明一下,阴影贴图中的片段深度信息都是在纹理坐标系内的点,那么进行正常渲染的时候我们传入渲染阴影贴图时候用的视图矩阵与投影矩阵,然后进行以下变换:
模型空间->世界空间->阴影视图空间->阴影投影空间->规范化设备空间->阴影贴图纹理空间
那么接下来向着色器传递以下矩阵:
?//Calculate texture matrix for projection
?//This matrix takes us from eye space to the light's clip space
?//It is postmultiplied by the inverse of the current view matrix when specifying texgen
?static MATRIX4X4 biasMatrix(0.5f, 0.0f, 0.0f, 0.0f,
? ? ? ? ?0.0f, 0.5f, 0.0f, 0.0f,
? ? ? ? ?0.0f, 0.0f, 0.5f, 0.0f,
? ? ? ? ?0.5f, 0.5f, 0.5f, 1.0f);?//bias from [-1, 1] to [0, 1]
?shadowMatrix=biasMatrix*lightProjectionMatrixLeft*lightViewMatrixLeft;
所以顶点着色器可以这么写:
uniform mat4 viewMatrix,modelMatrix,normalMatrix;
uniform mat4 shadowLeftMatrix,shadowRightMatrix;
varying vec4 shadowVertLeft,shadowVertRight;
......
......
? shadowVertLeft = shadowLeftMatrix * modelMatrix * gl_Vertex;
? ? ?shadowVertRight = shadowRightMatrix * modelMatrix * gl_Vertex;
?
? viewVertex = vec3(viewMatrix * modelMatrix * gl_Vertex);
? ? ?gl_Position = gl_ProjectionMatrix * viewMatrix * modelMatrix * gl_Vertex;?
然后在片段着色器当中将传入的shadowVertLeft和shadowVertRight都除以它们的w坐标值就能得到正常渲染的片元在阴影贴图坐标系内的坐标值了,之后把这个坐标值的深度(也就是z值)与阴影贴图内的深度值用shadow2D做比较,这边我偷了个懒,用shadow2DProj做,使用proj函数可以实现齐次除法,也就是顶点值除以w.
片段着色器这么写:
uniform sampler2DShadow texShadowLeft,texShadowRight;
varying vec4 shadowVertLeft,shadowVertRight;
......
......
?vec4 texcoordOffset = shadowVertLeft;
? ? if(texcoordOffset.x >= 0.0 && texcoordOffset.y >= 0.0 &&
? ? ? texcoordOffset.x <= 1.0 && texcoordOffset.y <= 1.0 ) {
? ? ?
? texcoordOffset.z+=bias;
? ? ?float depth = shadow2DProj(texShadowLeft, texcoordOffset).z;
? ? ?if(depth<1.0 && factor>=0.2)
? ?factor-= 0.1;
? if(factor<0.4)
? ?factor=0.4;
?}
片段的z坐标要加上一个偏移量,原因如图所示:

最后返回的factor值即为阴影值,把它与环境颜色相乘就能够输出片段了.
最终效果如下:

还能够在渲染阴影贴图的那一步使用着色器对深度纹理进行过滤产生半影区,这边我使用了pcf法对阴影进行处理.