OpenGL3.3_C++_Windows(25)

  • 阴影失真:阴影的不真实感

条纹样式:

  • 首先理解采样原理:同光的视角下,渲染一张深度图,每个像素,存储同一射线下的深度值(不断更新深度缓冲的结果),即最近片段的深度。
  • 接着,每个片段,T变换到光的视角下,从对应的深度贴图采样,比较自身的深度值,和深度贴图的深度值,、这便是阴影计算的过程
  • 但是,深度贴图受限于分辨率,在距离光源比较远的情况下,多个片段可能从深度贴图的同一个值中去采样,
  • 由于每个像素的深度值,为映射到同一像素范围内片段的中心点,那么映射到同一像素范围内的,某些Fragment.z > 中心点的z,就会被判断为阴影中,而某些Fragment.z < 中心点的z,判断为非阴影,所以,同一个映射范围的片段,有暗有亮,产生不合理的效果
  • 解决:偏移:可以让 表面的深度 / 深度贴图 应用一个偏移量(0.005f),这样同一范围的z深度,计算比较后的结果都是一致的,
  • 但是,这仅针对大部分情况,有些表面坡度很大,仍然会产生阴影失真
  • 原因:当光线和片段的法线 角度比较大,Fragment.z的值也会比较大,我们将z值偏移0.005f,并不能使它的z>中心点的z,
  • 解决:应用更大的偏移量:float bias = max(0.005 * (1.0 - dot(normal, lightDir)), 0.005);
  • 这行代码根据光线和片段的法线 角度,决定具体的偏移值

???悬浮Peter panning:

悬浮
  • 当使用阴影偏移,我们会发现阴影处于不正确的位置显示(虽然没有了条纹),对于原本应处于阴影的区域,却被判定为非阴影,不再计算阴影,
  • 原因:应用了偏移bias,虽然几乎可以保证同一映射范围的,片段判定一致,但是假如原本应处于阴影中,也就是深度贴图有更近的深度值,bias后片段的z深度,其实有一定可能比这个深度贴图的z深度还要小了,所以判定为非阴影
  • 书中的解决方案:当渲染深度图时候使用正面剔除(front face culling):也就是对深度贴图的深度值做了偏移(更远,值更大)
  • ???深度贴图深度值更大,不是越容易z - bias 小于<深度值(更高了)
  • 我认为这不是正确的解决方案,在我应用了面剔除,真的几乎没有阴影渲染了,并且源码中也没有用glCullFace(GL_FRONT);
  • 限制:只对内部不会对外开口 / 非单独平面  的实体物体有效,因为仅一个平面,剔除会完全移除它

采样过多

  • 我们发现地面上有一大块的阴影,超出光的视锥的投影坐标比1.0大,这样采样的深度纹理就会超出他默认的0到1的范围
  • 这是因为:超出光的视锥(和相机视锥不同)的片段一律被认为是处于阴影中,不管它真的处于阴影之中
  • 解决:让所有超出深度贴图的坐标的深度值是1.0,储存一个边框颜色,纹理环绕方式设置GL_CLAMP_TO_BORDER(当纹理坐标的值超出[0, 1]范围时,OpenGL会使用边框颜色作为纹理的颜色。)
  • 仍有一部分是黑暗区域,那里的坐标超出了光的正交视锥的远平面
  • 解决:强制将shadow的值强制设为0.0非阴影

PCF

  • 放大看阴影,会看到明显的锯齿状
  • 原因:深度贴图有一个固定的分辨率,多个片段对应于一个纹理像素,那么这几个片段便得到的是同一个阴影,而非各自的阴影,这就会产生锯齿边。
  • 方案:增加深度贴图的分辨率 / 尝试尽可能的让光的视锥接近场景(像素从一定范围的片段映射,当越接近,可映射范围就小,所以原本的某部分片段,产生了更多的采样坐标) / PCF
  • PCF(percentage-closer filtering):深度贴图中多次采样,所有的次生结果接着结合在一起,进行平均化,我们就得到了柔和阴影。
  • 根据textureSize(纹理对象,mipmap级别)(0:具有最高的分辨率和最多的细节),返回给定采样器纹理的mipmap级别的宽和高,再用1除以它返回一个单独纹理像素的大小
  • 37
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值