# 前言
相信当年VR刚出的时候大家都体验过吧?这里就用 cocos 的后处理来实现 VR 效果
从其他的 VR 应用可以看出来,手机 VR 画面是由 左右两个相同的类似老电视机画面组成 的(其实是我没找到关于手机 VR 展示的资料…)
那么就从这里入手,去逛了下 shadertoy,果然找到一个类似的 效果,然后搬到了 creator 里面,接下来我们看看是 VR 效果具体如何实现的
# 实现
1. 把屏幕分成两块
uv 坐标范围:0-1
这里我们需要对 uv 进行处理,思路很简单,我们把半块屏幕当作 uv 的实际坐标范围,也就是 (0 ~ 0.5) 和 (0.5 ~ 1.0)
一句代码搞定
vec2 v_uv2 = mod(v_uv * 2.0, 1.0);
效果:
看到了输出结果,这句代码不仅把左右分成了两边,上下也是,那么我们怎么处理呢?
也很简单
- uv.y 坐标移动到中间,也就是 +0.25
- 过滤掉多余画面
// uv 居中
vec2 v_uv2 = vec2(v_uv.x, v_uv.y + 0.25);
// uv 分块
vec2 v_uv3 = mod(v_uv2 * 2.0, 1.0);
// 过滤画面
if (v_uv2.y < 0.5 || v_uv2.y > 1.0 || v_uv3.x < 0.0 || v_uv3.x > 1.0 || v_uv3.y < 0.0 || v_uv3.y > 1.0) {
discard;
}
效果:
不戳不戳有那味了~
2. 添加 CRT 老电视效果
如果红色框是我们最开始界面,那我们的需求是:
- uv.x 在(0 ~ 0.5)从大到小递增,在(0.5 ~ 1.0)从小到大递减
- uv.y 在(0 ~ 0.5)从大到小递增,在(0.5 ~ 1.0)从小到大递减
上
vec2 post_process_crt(vec2 uv_pos_v2_, float bend_f_) {
// -1.0 ~ 1.0
uv_pos_v2_ = (uv_pos_v2_ - 0.5) * 2.0;
// 缩放 uv,增加差异范围
uv_pos_v2_ *= 1.5;
// uv 变形
// 由于 uv_pos_v2_.y 范围在(-1.0,1.0),所以 abs(uv_pos_v2_.y)越大则结果越大,0 为分界线
// pow((abs(uv_pos_v2_.y) / bend_f_), 2.0) 的结果由于 abs(uv_pos_v2_.y)不会超过 1.0,所以 uv_pos_v2_.x 不会超过自己2倍
uv_pos_v2_.x *= 1.0 + pow((abs(uv_pos_v2_.y) / bend_f_), 2.0);
uv_pos_v2_.y *= 1.0 + pow((abs(uv_pos_v2_.x) / bend_f_), 2.0);
// 转换回 0.0 - 1.0 空间
uv_pos_v2_ = (uv_pos_v2_ / 2.0) + 0.5;
return uv_pos_v2_;
}
参考图:
-
x 为 递增的 vec2, t 为递增的 number
-
固定 y 后的 x 值
-
固定 x 后的 y 值
3. 最终输出
至此完成我们的目标, 下班前赶稿,写的不好见谅
# 结语
demo: github链接
打开项目后请在 项目-> 项目设置 -> 项目数据 -> 更换渲染管线为 builtin-deferred2.rpp
由于目前 cocos 版本渲染管线对后处理的支持并不好, 我是修改的 web 端渲染管线实现的,所以更加推荐通过 renderTexture 方式实现。可以参考另外一篇帖子