coffee smoke shader
· 阅读需 3 分钟
这个 vertex.glsl 代码好难理解
vertex.glsl
varying vec2 vUv;
uniform float uTime;
uniform sampler2D uPerlinTexture;
vec2 rotate2D(vec2 value, float angle) {
float s = sin(angle);
float c = cos(angle);
mat2 m = mat2(c, s, -s, c);
return m * value;
}
void main() {
vec3 newPosition = position;
float twistPerlin = texture(uPerlinTexture, vec2(0.5, uv.y * 0.2 - uTime * 0.005)).r;
float angle = twistPerlin * 10.0;
newPosition.xz = rotate2D(newPosition.xz, angle);
vec2 windOffset = vec2(
texture(uPerlinTexture, vec2(0.25, uTime * 0.01)).r - 0.5,
texture(uPerlinTexture, vec2(0.75, uTime * 0.01)).r - 0.5);
windOffset *= pow(uv.y, 2.0) * 10.0;
newPosition.xz += windOffset;
// Final position
gl_Position = projectionMatrix * modelViewMatrix * vec4(newPosition, 1.0);
vUv = uv;
}
主要效果实现(main函数)
- 扭曲效果
float twistPerlin = texture(uPerlinTexture, vec2(0.5, uv.y * 0.2 - uTime * 0.005)).r;
float angle = twistPerlin * 10.0;
newPosition.xz = rotate2D(newPosition.xz, angle);
- 使用柏林噪声纹理创建扭曲效果
- 根据y坐标和时间采样噪声
- 将采样结果用于旋转xz平面
- 风力效果
vec2 windOffset = vec2(
texture(uPerlinTexture, vec2(0.25, uTime * 0.01)).r - 0.5,
texture(uPerlinTexture, vec2(0.75, uTime * 0.01)).r - 0.5);
windOffset *= pow(uv.y, 2.0) * 10.0;
newPosition.xz += windOffset;
- 使用两个不同位置的噪声采样创建风力偏移
- 风力效果随高度(y坐标)增强
- 应用到xz平面上
效果说明
这个着色器主要用于创建咖啡烟雾的效果:
- 通过柏林噪声创建自然的扭曲运动
- 使用时间变量使效果随时间变化
- 风力效果随高度增强,模拟真实烟雾上升时的扩散
- 整体效果结合了旋转和偏移,创造出流动的烟雾效果
- 这个着色器很可能是用于粒子系统或者平面网格,用来模拟上升的烟雾效果。通过柏林噪声的使用,可以创建出非常自然的随机运动效果。
fragment.glsl
uniform sampler2D uPerlinTexture;
varying vec2 vUv;
uniform float uTime;
void main() {
// scale
vec2 smokeUv = vUv;
smokeUv.x *= .5;
smokeUv.y *= .3;
smokeUv.y -= uTime * .03;
float smoke = texture(uPerlinTexture, smokeUv).r;
smoke = smoothstep(0.4, 1.0, smoke);
smoke *= smoothstep(0.0, 0.1, vUv.x);
smoke *= smoothstep(0.0, 0.1, 1.0 - vUv.x);
smoke *= smoothstep(1.0, .4, vUv.y);
smoke *= smoothstep(.0, .1, vUv.y);
gl_FragColor = vec4(.6, .3, .2, smoke);
// gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);
#include <tonemapping_fragment>
#include <colorspace_fragment>
}