一、创建深度纹理并连接到帧缓冲区
int InitShadowMap ( ESContext *esContext )
{
UserData *userData = esContext->userData;
GLenum none = GL_NONE;
GLint defaultFramebuffer = 0;
// 使用1024*1024的深度纹理
userData->shadowMapTextureWidth = userData->shadowMapTextureHeight = 1024;
//生成并绑定纹理对象到GL_TEXTURE_2D
glGenTextures ( 1, &userData->shadowMapTextureId );
glBindTexture ( GL_TEXTURE_2D, userData->shadowMapTextureId );
//放大过滤,使用GL_LINEAR,将从纹理坐标附近的纹理中取得一个双线性样本(4个样本的平均值)
//如果使用GL_NEAREST,则将最靠近从纹理坐标的纹理中取得单点样本
glTexParameteri ( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
//缩小过滤,使用GL_LINEAR,从最靠近纹理坐标的纹理中获得一个双线性样本
//如果使用GL_NEAREST,则从最靠近纹理坐标的纹理中获得一个单点样本
glTexParameteri ( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
//沿S,T方向上,GL_CLAMP_TO_EDGE限定读取纹理边缘
//GL_REPRAT重复纹理;GL_MIRRORED_REPEAT重复纹理和镜像,这部分网上很多资料可自行搜索
glTexParameteri ( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE );
glTexParameteri ( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE );
// 设置硬件比较
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_REF_TO_TEXTURE );
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC, GL_LEQUAL );
//注意pixels为NULL,我们将渲染到整个纹理区域,所以没有理由指定任何输入数据
glTexImage2D ( GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT24,
userData->shadowMapTextureWidth, userData->shadowMapTextureHeight,
0, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, NULL );
glBindTexture ( GL_TEXTURE_2D, 0 );
//检查是否支持帧缓冲区
glGetIntegerv ( GL_FRAMEBUFFER_BINDING, &defaultFramebuffer );
// setup fbo
glGenFramebuffers ( 1, &userData->shadowMapBufferId );
glBindFramebuffer ( GL_FRAMEBUFFER, userData->shadowMapBufferId );
//指定要绘制到的颜色缓冲区列表
glDrawBuffers ( 1, &none );
//将2D纹理连接到帧缓冲区附着点
glFramebufferTexture2D ( GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, userData->shadowMapTextureId, 0 );
glActiveTexture ( GL_TEXTURE0 );
glBindTexture ( GL_TEXTURE_2D, userData->shadowMapTextureId );
if ( GL_FRAMEBUFFER_COMPLETE != glCheckFramebufferStatus ( GL_FRAMEBUFFER ) )
{
return FALSE;
}
glBindFramebuffer ( GL_FRAMEBUFFER, defaultFramebuffer );
return TRUE;
}
上述的
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_REF_TO_TEXTURE );
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC, GL_LEQUAL );
该代码主要是为了实现深度纹理的阴影特效,为了实现这个特效,在片段着色器中需要比较片段和纹理的深度值,以此判断该片段位于阴影内还是外;在这段代码之前,我们使用了GL_LINEAR方式去过滤,原因就是双线性过滤可以使得阴影的边缘可以平滑过滤;那么这里加上硬件比较的原因就是确保将采样的深度和参考值深度比较之后,平均该结果,实现百分比渐进过滤(PCF)功能,如果不加硬件比较,则可能导致过滤发生在采样比较之前发生,这样的话就不能得到正确的结果。
GL_TEXTURE_COMPARE_MODE的默认值是GL_NONE,但是当它被设置为GL_COMPARE_REF_TO_TEXTURE时,纹理坐标(s, t, r)的r分量用来和深度纹理的值做比较,比较结果会成为阴影纹理读取的结果(可能为0或者1,如果开启了纹理过滤则是这些值的平均值)。比较函数用GL_TEXTURE_COMPARE_FUNC设置,GL_LEQUAL:深度小于或等于的时候渲染;GL_LESS:深度小于时渲染。
以上部分参考于https://www.jianshu.com/p/b54f77569855
深度纹理格式:
内部格式后面的数字代表深度
内部格式 格式 类型
GL_DEPTH_COMPONENT16 GL_DEPTH_COMPONENT GL_UNSIGNED_SHORT
GL_DEPTH_COMPONENT16 GL_DEPTH_COMPONENT GL_UNSIGNED_INT
GL_DEPTH_COMPONENT24 GL_DEPTH_COMPONENT GL_UNSIGNED_INT
GL_DEPTH_COMPONENT32F GL_DEPTH_COMPONENT GL_FLOAT
void glDrawBuffers(