实现效果
烟雾是动态的,因为gif录制不清楚,所有就截个图
代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>造型函数</title>
</head>
<body>
<script src="https://unpkg.com/gl-renderer/dist/gl-renderer.js"></script>
<canvas width="640" height="360"></canvas>
<script>
const vertex = `
attribute vec2 a_vertexPosition;
attribute vec2 uv;
uniform vec2 translation;
varying vec2 vUv;
mat3 transformMatrix = mat3(
1, 0, 0,
0, 1, 0,
translation, 1
);
void main() {
gl_PointSize = 1.0;
vUv = uv;
vec3 pos = vec3(a_vertexPosition, 1);
gl_Position = vec4(pos, 1);
}
`;
const fragment = `
#ifdef GL_ES
precision highp float;
#endif
varying vec2 vUv;
uniform sampler2D tMap;
uniform sampler2D tPic;
uniform float uTime;
uniform vec2 resolution;
float random(float x) {
return fract(sin(x) * 10000.);
}
float noise(vec2 p) {
return random(p.x + p.y * 10000.);
}
vec2 sw(vec2 p) { return vec2(floor(p.x), floor(p.y)); }
vec2 se(vec2 p) { return vec2(ceil(p.x), floor(p.y)); }
vec2 nw(vec2 p) { return vec2(floor(p.x), ceil(p.y)); }
vec2 ne(vec2 p) { return vec2(ceil(p.x), ceil(p.y)); }
float smoothNoise(vec2 p) {
vec2 interp = smoothstep(0., 1., fract(p));
float s = mix(noise(sw(p)), noise(se(p)), interp.x);
float n = mix(noise(nw(p)), noise(ne(p)), interp.x);
return mix(s, n, interp.y);
}
float fractalNoise(vec2 p) {
float n = 0.;
n += smoothNoise(p);
n += smoothNoise(p * 2.) / 2.;
n += smoothNoise(p * 4.) / 4.;
n += smoothNoise(p * 8.) / 8.;
n += smoothNoise(p * 16.) / 16.;
n /= 1. + 1./2. + 1./4. + 1./8. + 1./16.;
return n;
}
void main() {
vec2 st = gl_FragCoord.xy / resolution;
vec2 nuv = vec2(st.x - uTime / 6., st.y);
st *= vec2(1., -1.);
float x = fractalNoise(nuv * 1.5);
vec3 final = mix(vec3(x), texture2D(tPic, vUv).xyz, pow(abs(st.y),.9));
gl_FragColor = vec4(final, 1.);
}
`;
(async function () {
const canvas = document.querySelector("canvas");
const renderer = new GlRenderer(canvas);
const program = renderer.compileSync(fragment, vertex);
renderer.useProgram(program);
const picture = await renderer.loadTexture(
"https://p1.ssl.qhimg.com/t01cca5849c98837396.jpg"
)
renderer.setMeshData([
{
positions: [
[-1, -1],
[-1, 1],
[1, 1],
[1, -1],
],
attributes: {
uv: [
[0, 0],
[0, 1],
[1, 1],
[1, 0],
],
},
cells: [
[0, 1, 2],
[2, 0, 3],
],
},
]);
function update(t) {
renderer.uniforms.uTime = t / 1000;
renderer.uniforms.resolution = [640, 360];
renderer.uniforms.tPic = picture;
renderer.render();
requestAnimationFrame(update);
}
update(0);
})();
</script>
</body>
</html>
tips
更多知识 参考 跟月影学可视化 还有 www.shadertoy.com/