108 lines
3.1 KiB
Plaintext
108 lines
3.1 KiB
Plaintext
CCEffect %{
|
|
techniques:
|
|
- passes:
|
|
- vert: rainbow-water-vs
|
|
frag: rainbow-water-fs
|
|
blendState:
|
|
targets:
|
|
- blend: true
|
|
blendSrc: src_alpha
|
|
blendDst: one_minus_src_alpha
|
|
rasterizerState:
|
|
cullMode: none
|
|
depthStencilState:
|
|
depthTest: false
|
|
depthWrite: false
|
|
properties:
|
|
texture: { value: white }
|
|
uvRect: { value: [0, 0, 1, 1] }
|
|
uvRotated: { value: 0 }
|
|
water: { value: [1, 0, 0.024, 0.006] }
|
|
}%
|
|
|
|
CCProgram rainbow-water-vs %{
|
|
precision highp float;
|
|
#include <cc-global>
|
|
#include <cc-local>
|
|
in vec3 a_position;
|
|
in vec4 a_color;
|
|
in vec2 a_uv0;
|
|
out vec4 v_color;
|
|
out vec2 v_uv0;
|
|
|
|
void main () {
|
|
vec4 pos = vec4(a_position, 1.0);
|
|
#if CC_USE_MODEL
|
|
pos = cc_matViewProj * cc_matWorld * pos;
|
|
#else
|
|
pos = cc_matViewProj * pos;
|
|
#endif
|
|
gl_Position = pos;
|
|
v_color = a_color;
|
|
v_uv0 = a_uv0;
|
|
}
|
|
}%
|
|
|
|
CCProgram rainbow-water-fs %{
|
|
#if CC_SUPPORT_standard_derivatives
|
|
#extension GL_OES_standard_derivatives : enable
|
|
#endif
|
|
precision highp float;
|
|
#include <texture>
|
|
in vec4 v_color;
|
|
in vec2 v_uv0;
|
|
uniform sampler2D texture;
|
|
uniform WaterProperties {
|
|
vec4 uvRect;
|
|
vec4 water;
|
|
float uvRotated;
|
|
};
|
|
|
|
void main () {
|
|
vec2 uv = (v_uv0 - uvRect.xy) / max(uvRect.zw, vec2(0.00001));
|
|
if (uvRotated > 0.5) uv = vec2(uv.y, 1.0 - uv.x);
|
|
vec4 base = vec4(1.0);
|
|
{
|
|
CCTexture(texture, v_uv0, base);
|
|
}
|
|
|
|
// 固定波形从左向右平移,瓶内颜色跟随同一波列,不在中途叠出新的凸起。
|
|
float phase = uv.x * 7.5 - water.y * 1.8;
|
|
float envelope = 4.0 * uv.y * (1.0 - uv.y);
|
|
vec2 drift = vec2(0.0, 0.75 * sin(phase + uv.y * 3.0));
|
|
vec2 flowingUV = clamp(uv + drift * water.z * envelope, vec2(0.001), vec2(0.999));
|
|
if (uvRotated > 0.5) flowingUV = vec2(1.0 - flowingUV.y, flowingUV.x);
|
|
vec4 flowing = vec4(1.0);
|
|
{
|
|
CCTexture(texture, uvRect.xy + flowingUV * uvRect.zw, flowing);
|
|
}
|
|
vec4 color = vec4(mix(base.rgb, flowing.rgb, flowing.a), base.a);
|
|
|
|
// 液面沿同一方向连续推进;空瓶不残留,满瓶保持完整。
|
|
float amplitude = water.z * smoothstep(0.0, 0.08, water.x)
|
|
* smoothstep(0.0, 0.08, 1.0 - water.x);
|
|
float wave = amplitude * sin(phase);
|
|
float surface = water.x + wave;
|
|
float height = 1.0 - uv.y;
|
|
float distanceToSurface = height - surface;
|
|
float feather = water.w;
|
|
#if CC_SUPPORT_standard_derivatives
|
|
// 按实际屏幕像素抗锯齿,缩小瓶子后液面仍能平滑跨过像素边界。
|
|
feather = max(0.75 * fwidth(distanceToSurface), 0.00001);
|
|
#endif
|
|
if (water.x <= 0.0) {
|
|
color.a = 0.0;
|
|
} else if (water.x < 1.0) {
|
|
color.a *= 1.0 - smoothstep(-feather, feather, distanceToSurface);
|
|
float rim = 1.0 - smoothstep(0.0, feather, abs(distanceToSurface));
|
|
color.rgb = mix(color.rgb, vec3(1.0, 0.98, 0.88), rim * 0.08);
|
|
}
|
|
color *= v_color;
|
|
#if USE_BGRA
|
|
gl_FragColor = color.bgra;
|
|
#else
|
|
gl_FragColor = color;
|
|
#endif
|
|
}
|
|
}%
|