Skip to content

WebGPURenderer: Images with color-specific metadata produces different results in both backends. #31132

Open
@steve-o

Description

@steve-o

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

  1. In one window: https://miffy.dsbunny.com/apps/webgpu/play/webgl.html
  2. 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

Image
Image

Version

176

Device

Desktop

Browser

Chrome

OS

Windows

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions