[OpenGL] Bloom自发光效果

              

        之前在看Unreal的材质时,发现里面有一个自发光效果(unreal自发光),就暂且猜测它使用bloom后期处理做的吧。不过它这个自发光还能照亮周围场景,估计这套照亮的系统和自发光的泛光效果是独立的,只是将其作为了一个物体光源。

基本思路

          首先,本处要做的是对单个物体控制自发光效果,而不是一个全屏泛光效果,所以我们需要做一些特别的控制。

         我使用的第一个方案是在延迟渲染的框架中,在GBuffer中,留一个通道设置一些渲染状态量,按位存储,如果这些状态量并非互斥的话,那么32位浮点数的就能设置32个状态量了(差不多也够用了吧)。其中一位控制是否开启bloom效果。

         然后就可以直接从利用GBuffer中的存储基本颜色(albedo)的纹理,按位掩码得到一张仅包含需要bloom效果的物体颜色的纹理。

         接着对这张纹理做亮色提取,得到一张仅包含物体亮色部分的新的纹理,再对新的纹理做模糊处理。之后,按照用户设定的比例叠加到原场景纹理上。

           以上描述是为了能够更好理解算法,但实际上这一系列操作都是在后处理一个pass中完成的,也就是我们没有办法生成多个中间纹理。实际的实现应该为:在后处理中,对全屏场景做一次模糊处理,在模糊采样中,只采样那些颜色比较明亮并且标记了开启bloom的像素。

 

         这样的做法比较简单,但是我们能够控制的地方就比较少了。最终我使用的方案是,单独增加了一个pass,然后写入需要bloom效果的颜色,再在后处理中直接做普通的模糊(不需要判断是否需要采样像素了),然后叠加到原场景纹理上。

         其中要注意的是,虽然有些物体是不需要bloom效果的,但是在这一写入颜色的过程中,依然需要进行drawcall调用,只不过其写入纹理的颜色应该是黑色的。否则深度遮挡将会失效(然后意外地收获X射线的效果)。

         此处,因为后期反正也是要模糊处理的,所以可以做降采样,比如使用屏幕宽高都为1/2的分辨率。具体的实现是生成的纹理为半分辨率大小,并且把视口大小也设置为半分辨率大小(glViewport),不做后一步的话采样的结果就是错的。

         此时我们就能做点别的了,比如控制自发光颜色,比较好的做法是让美术输入自发光的颜色,然后直接在该物体写入颜色纹理时把这一指定颜色写入,而不是放在后处理过程中下所示:

         

        放在后处理中处理颜色的话,我们的做法是:

        叠加颜色 = 模糊后物体颜色 * 自发光颜色 * 自发光系数

        那么如果我们的自发光是红色(rgb(1,0,0)),而物体颜色的r分量值很小,我们就得把系数调的非常高才能看到效果,如果原物体颜色的r通道为0,那么就完全无法发出红光了。但是如果我们单独做一张额外的自发光颜色纹理,就不会有这种问题。

   

        另一个问题在于,提取物体的亮色是一个比较摸棱两可的概念。我们如果想要对不同物体做不同的亮色阈值控制,就意味着我们又需要引入新的参数控制,在后处理中引入新的参数控制就意味着需要占用额外的GBuffer通道。

        引入遮罩纹理是一张比较好的让美术控制自发光位置的方法,我们认为这是一个二值图,1表示发光,而0表示不发光。

 

         到目前为止我使用的是高斯模糊,从邻域采样进行混合,在邻域采样的间隔变大时(或者镜头拉远时,此时物体变小,而采样间隔不变,那么它相对物体也变大了),会出现如下的错位效果:

         

      这一问题可以使用物体到相机的距离(即GBuffer中存储的物体的深度)来选取合适的模糊采样间隔来解决。

 

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值