Open
Description
Description
REF: https://www.vantajs.com/?effect=clouds2
Taking the popular Vanta clouds2 demo and porting to TSL I can reproduce the visual output with forceWebGL: true
, however when using WebGPU the clouds are significantly less fluffy. I really not sure how to start debugging this.
Reproduction steps
- In one window: https://miffy.dsbunny.com/apps/webgpu/play/webgl.html
- In another: https://miffy.dsbunny.com/apps/webgpu/play/webgpu.html
Code
const cloudShader = /*@__PURE__*/ Fn( ({
resolution,
time,
speed,
skyColor,
cloudColor,
lightColor,
cloudTexture,
}) => {
const coord = vec2(
screenCoordinate.x,
screenCoordinate.y,
).toVar();
// Base direction vector (0.8, 0, coord/resolution.y - 0.35)
const d = vec4(
float(0.8),
float(0),
coord.div(resolution.y).sub(float(0.35)),
).toVar();
// Sky gradient based on height (skyColor - d.w)
let outColor = skyColor.sub(d.w).toVar();
// Initial value for ray marching (200.0 + sin(dot(coord,coord)))
let t = float(200.0).add(sin(dot(coord, coord))).toVar();
// Ray marching loop
const MAX_ITER = float(100.0);
Loop({ start: float(1.0), end: MAX_ITER, type: 'float', condition: '<=' }, () => {
// Decrease t by 2.0 for each step
t.assign(t.sub(float(2.0)));
// Break if t < 0
If(t.lessThan(float(0.0)), () => { Break(); });
// p = 0.05 * t * d
let p = d.mul(t).mul(float(0.05)).toVar();
// Apply movement through space
// p.xz += time * 0.5 * speed
p.xz.assign(p.xz.add(time.mul(float(0.5)).mul(speed)));
// p.x += sin(time * 0.25 * speed) * 0.25
p.x.assign(p.x.add(sin(time.mul(float(0.25)).mul(speed)).mul(float(0.25))));
// Start with s = 2.0
let s = float(2.0).toVar();
// Initialize f value for cloud density
// Note: In GLSL we have p.w + 1.0 - T - T - T - T
let f = p.w.add(float(1.0)).toVar();
// Emulate -T -T -T -T
Loop(4, () => {
// Calculate texture coordinates for sampling
// fract((s*p.zw + ceil(s*p.x)) / 200.0)
const p_zw = p.zw;
const s_p_zw = s.mul(p_zw);
const s_p_x = s.mul(p.x);
const texCoord = fract(s_p_zw.add(ceil(s_p_x)).div(float(200.0)));
const sampleY = texture(cloudTexture, texCoord).y.div(s.assign(s.add(s)));
const T = sampleY.mul(float(4.0));
// Subtract T from f (f -= T)
f.assign(f.sub(T));
});
// Check if inside a cloud (f < 0.0)
If(f.lessThan(float(0.0)), () => {
// Calculate cloud color with shading
// mix(lightColor, cloudColor, -f)
const shaded = mix(lightColor, cloudColor, f.negate());
// Blend with the sky color
// mix(out1, cloudColorShading, -f * 0.4)
const mixed = mix(outColor, shaded, f.negate().mul(float(0.4)));
outColor.assign(mixed);
});
});
// Return final color with alpha = 1.0
return vec4(outColor, float(1.0));
} );
Live example
Screenshots
Version
176
Device
Desktop
Browser
Chrome
OS
Windows