//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法对阴影进行处理.
Ubuntu 13.04 安装 OpenGL