一.shadow2DProjEXT函数需要传入一张深度纹理和一个点的坐标(4维)
1.这里首先注意的是这张纹理必须使用采样器类型为sampler2DShadow才可以,直接使用sampler2D是不行的,会出错。
2.深度纹理必须设置正确的格式GL_DEPTH_COMPONENT,另外要指定相应的比较函数,可以通过glTexParameteri来设置GL_TEXTURE_COMPARE_FUNC_EXT为GL_LEQUAL,GL_TEXTURE_COMPARE_MODE_EXT为GL_COMPARE_REF_TO_TEXTURE_EXT
3.传入的坐标是4维的(x,y,z,w),shadow2DProjEXT函数内部会这样做
shadow2DProjEXT(depthTexture, shadowCoord);其实是分两步,第一步会取出真正的纹理坐标即shadowCoord.xy / shadowCoord.w并存depthTexture中对应位置取出相应的深度值,相当于执行float depth = texture2D(depthTexture,shadowCoord.xy/shadowCoord.w)。第二步则是对纹理中的深度值与坐标中的深度值进行比较纹理中的深度值就是depth,而坐标中的深度值要通过计算:float
depth1 = shadowCoord.z / shadowCoord.w,然后将depth 与depth1做比较。
4.返回值问题,此函数的返回值为0或者1,若depth < depth1 则返回0表示深度测试未通过,反之为1表示深度测试通过。
二、上面计算时有一点需要注意,就是第三步的时候,在进行纹理坐标计算和坐标中的深度值计算时要注意shadowCoord是经过转换后的坐标,这里的转换后的意思是必须将shadowCoord的x,y,z由[-1,1]转换到[0,1],所以通常在实现的时候直接在mvp矩阵的前面乘上一个偏移矩阵,
bias = 0.5, 0.0, 0.0, 0.5
0.0,0.5, 0.0,0.5
0.0, 0.0,0.5,0.5
0.0, 0.0,0.0,1.0
这样bias * (x,y,z,w),然后在除掉第四个分量之后就是(x +1)*0.5,(y+1)*0.5,(z+1)*0.5,这样就实现了转换。
但是由于opengl的矩阵是列优先的,所以我们在进行矩阵设置的时候要把矩阵进行转置才可以,
bias =
0.5, 0.0, 0.0, 0.0
0.0,0.5, 0.0,0.0
0.0, 0.0,0.5,0.0
0.5, 0.5,0.5,1.0
这样就ok了。
在通常的过程中我们唔需要考虑行列主序的问题,因为我们计算得到的矩阵(比如通过lookAt,或者glm的相关函数得到的矩阵)与shader中需要的格式是一致的,所以我们传入就可以使用,只有一种情况下我们需要考虑矩阵的列主序或者行主序关系,那就是将GLSL矩阵放入自定义的内存块是,当将矩阵传递到uniform块中式,就需要考虑这个问题,例如上面,我们自己写了一个矩阵存储在自定义的内存块中,所以我们向shader中传递的时候就要进行行列转置,这样才能正确的使用矩阵。