OPENGL ES 3.0 shadow示例代码详解(阴影纹理、MVP矩阵等)

本文详细介绍了OpenGL ES 3.0中如何通过创建深度纹理和帧缓冲区来实现阴影效果,包括设置GL_TEXTURE_COMPARE_MODE和GL_TEXTURE_COMPARE_FUNC以进行深度比较,以及使用正交投影和MVP矩阵生成视图。此外,还讨论了片段着色器中的PCF过滤和消除多边形缝隙的技巧,如启用Polygon Offset。
摘要由CSDN通过智能技术生成

一、创建深度纹理并连接到帧缓冲区

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(
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值