完整资源:
前情提要:
从0开始编写minecraft光影包(0)GLSL,坐标系,光影包结构介绍
前言
上次提到泛光的开销过大,减少高斯模糊的半径可以减小开销,但是并且不能取得很好的效果。今天通过两种优化方案来提升泛光特效的品质。
模糊的拆分
模糊操作可以被拆成横向和纵向的两次模糊,我们通过这种方式来提升性能。
原理
还记得上一篇博客提到的模糊算法(均值滤波)吗?
我们直接使用两重 for 循环,对一个像素计算其周围像素的均值。所以每次渲染的复杂度是 O(n平方)。比如 3x3 的模糊,我们需要采样9个点。
而如果我们先执行一次横向的模糊,我们会得到一张被 “横向拉伸” 的图,对该图再执行一次纵向的模糊,那么会获得同样的效果:
于是渲染的复杂度从 O(n方) 降低到 O(n),还可以接受。
(注:其实这么理解是有点问题的,真要证明害得看数学。其实本文的模糊并未使用高斯分布函数作为权重。。
图片引自:https://blog.csdn.net/qq_36359022/article/details/80188873
渲染流程
于是我们需要两个着色器,分别是composite1.fsh 和 composite2.fsh ,他们负责对筛选出来的高亮原图像分别进行横向和纵向的模糊。
在此之前,我们需要修改 composite.fsh ,将高亮原图像存入 1 号颜色缓冲区。
gl_FragData[1] = getBloomOriginColor(color);
其中 getBloomOriginColor 是亮色提取函数,会返回图像中亮的部分。此外,别忘了修改 DRAWBUFFER
/* DRAWBUFFERS: 01 */
那么composite将基色存到0号缓冲区,将高亮颜色存储到1号缓冲区。接下来我们需要编写三个着色器,分别是
- composite1.fsh 负责对1号缓冲区中的高亮原图 O 做横向的模糊,得到图像 A 并且写入1号缓冲区
- composite1.fsh 负责对1号缓冲区中的 A 图像做纵向的模糊,得到图像 B 并且写入1号缓冲区
- final.fsh 中负责对 0 和 1 号缓冲区中的图像做叠加,并且输出
注:为啥不使用 composite3 对图像叠加合成呢?是因为 final 的渲染发生在 composite 文件处理之后。而今后如果需要继续加特效,可能会用到 composite3。所以为了避免冲突,直接在final最后一个着色器中进行叠加合成的操作。
附:图像在缓冲区中的流动过程