本篇教程转载自 Cocos 中文社区,作者:regocxy。通过本篇教程你将学到如何做风格化水体的渲染,包含的知识点有如何使用天空立方体贴图作反射,如何巧用噪声贴图作纹理扰动并顺便做出浮沫效果,如何巧用uv做出边沿雾效果。
水体渲染
是游戏中比较有挑战的一种效果,实现难度也有深有浅,这里笔者希望使用一种简单高效的方法实现一个简单美观的风格化水体效果,最终实现效果如下,性能非常优秀,对移动设备非常友好。
下面是实现过程:
1、天空反射
天空的反射需要:
环境立方体贴图
噪声贴图
菲涅尔反射
1.1 环境立方体贴图
想要做出水体流动的感觉有非常多的方法,其中使用 uv 偏移
是最简单并且性能最好的方法,该方案绝大多数的做法都是对一张法线贴图作 uv 缩放和偏移,并作光影计算从而表现出流动的水面。
该方案的确能做出相当不错的风格化水体效果,但是笔者这次不想这么做,因为法线贴图的采样还原在笔者看来还是不够精简,甚至水体对光源的明暗变化笔者也不想计算。
笔者选择了直接对环境立方体贴图做采样,表现一个简单的水面反射效果。
代码如下:
vec3 v = normalize(v_view);
vec3 r = -v;
vec3 reflectColor = texture(envTexture, r).rgb;
以上代码中,笔者对反射做了一个计算优化
,直接对视角向量取反,即 r = -v
。
常规做法是 r = reflect(v, n)
,其中 reflect(v, n) = v - 2.0 * dot(n, v) * n
。
由 reflect
表达式就能看出笔者的写法效率要远高于常规做法,少了 2 次的乘法计算和 1 次点成计算。
而笔者的计算优化成立的原因是对于天空的反射,如果仅仅让视觉上看起来像反射,我们其实可以不用关心反射方向的正确性,读者可以自己作个图细品下。
完整代码如下:
vec4 frag () {
vec3 n = normalize(v_normal);
vec3 v = normalize(v_view);
vec3 r = -v;
vec3 reflectColor = texture(envTexture, r).rgb;
return vec4(reflectColor, mainColor.a);
}
此时读者应该能得到一个镜子一般的水面,毫无美感,并且丝毫也感受不出这是水。