前言
昨天刚办完离职手续,今天闲来无事,就分享一篇关于cocos shader中的扭曲(水波纹)特效的实现吧,话不多说,直接步入正题。
在这里打个广告,本人刚离职,坐标深圳,有没有游戏公司正在招聘U3D的(cocos 3D手游的也可以),麻烦帮忙推荐一下呗,感谢。(ps:我U3D项目经验较少,但是我非常热爱U3D游戏开发,平时也自己花时间去研究,不嫌弃的可以帮忙推荐一下呗,谢谢!可以留言或者私信我,wx: CharlieLi_Wechat)
CocosCreator版本:2.4.2
效果
这个效果原理非常简单,就是对 texture 随机采样,当然,这个随机会有一定的约束,不能太随机,在当前uv坐标附近随机即可。也就是说对uv进行随机偏移。
在shader中没有内置的随机函数,要么自己写一个随机函数,要么通过采样噪声图拿到随机值。这里我们就采用第二种方法,简单而且性能也好。(在shader中严格说来应该叫噪声,有兴趣的可以自己去查阅相关的资料)
首先我们需要一张的噪声图:
在shader中添加noisetex 属性,用来接收噪声纹理,并在拖拽图片到属性面板:
有了噪声图,我们就可以轻松的得到所谓的随机值了,代码如下:
vec4 noise = vec4(1);
CCTexture(noisetex, v_uv0.xy, noise);
此时我们得到了噪声值,然后我们对 uv坐标进行偏移,最后在采样,代码如下:
vec2 uv_temp = v_uv0;
uv_temp += noise.xy;
vec4 o = vec4(1);
CCTexture(texture, uv_temp, o);
此时效果大致如下:
现在是一个静态的,然后我们怎么让它动起来呢?很简单,在采样噪声图的时候加上一个时间变量就可以了。如下:
CCTexture(noisetex, v_uv0.xy + v_time.x * speedFactor , noise);
v_time 是从顶点着色器 传递到 片元着色器的,内置变量为:cc_time,随着游戏运行不断增长。
此时我们就得到了一个动态的噪声值。
==注意:纹理 Wrap Mode 需要设置为平铺模式 Repeat==
此时运行游戏,我们就能看到一个动态扭曲的特效了。
至此完毕,最后附上完整shader源码
// Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd.
/**
扭曲 特效
author: lichanglong
create time:2020.8.11
**/
CCEffect %{
techniques:
- passes:
- vert: vs
frag: fs
blendState:
targets:
- blend: true
rasterizerState:
cullMode: none
properties:
texture: { value: white }
alphaThreshold: { value: 0.5 }
# 噪声纹理
noisetex: { value: white }
speedFactor: {
value: 0.1,
editor: {
tooltip: "速度",
range: [0.0, 1.0],
}
}
strengthFactor: {
value: 0.1,
editor: {
tooltip: "强度",
range: [-0.5, 0.5],
}
}
isHorizontal: {
value: 0,
editor: {
tooltip: "横向扭曲",
range: [0.0, 1.0],
}
}
isVertical: {
value: 0,
editor: {
tooltip: "纵向扭曲",
range: [0.0, 1.0],
}
}
}%
CCProgram vs %{
precision highp float;
#include <cc-global>
#include <cc-local>
in vec3 a_position;
in vec4 a_color;
out vec4 v_color;
#if USE_TEXTURE
in vec2 a_uv0;
out vec2 v_uv0;
#endif
out vec4 v_time;
void main () {
vec4 pos = vec4(a_position, 1);
#if CC_USE_MODEL
pos = cc_matViewProj * cc_matWorld * pos;
#else
pos = cc_matViewProj * pos;
#endif
#if USE_TEXTURE
v_uv0 = a_uv0;
#endif
v_color = a_color;
v_time = cc_time;
gl_Position = pos;
}
}%
CCProgram fs %{
precision highp float;
#include <alpha-test>
#include <texture>
in vec4 v_color;
#if USE_TEXTURE
in vec2 v_uv0;
uniform sampler2D texture;
#endif
#if USE_NOISETEX
uniform sampler2D noisetex;
#endif
uniform Factor {
float speedFactor;
float strengthFactor;
float isHorizontal;
float isVertical;
};
in vec4 v_time;
void main () {
vec4 o = vec4(1);
vec4 noise = vec4(1);
vec2 uv_temp = v_uv0;
// 采样噪声纹理
#if USE_NOISETEX
CCTexture(noisetex, v_uv0.xy + v_time.x * speedFactor , noise);
#endif
// 偏移uv
// uv_temp += noise.xy * strengthFactor;
float isH = step(0.1, isHorizontal);
float isV = step(0.1, isVertical);
uv_temp.x += noise.x * strengthFactor * isH;
uv_temp.y += noise.x * strengthFactor * isV;
#if USE_TEXTURE
CCTexture(texture, uv_temp, o);
#endif
o *= v_color;
ALPHA_TEST(o);
gl_FragColor = o;
}
}%
最后
以上可能需要稍微懂点shader的同学才能理解,项目源码在我的 GitHub 能找到,不只是cocos中shader,还有关于Unity 和 WebGL相关的工程,喜欢的可以给个star,谢谢!
更多关于Shader 特效的可以来我的博客逛逛,喜欢的可以素质三连,嘿嘿