Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Noise algorithm in WebGPURenderer - performance concerns #29830

Open
Makio64 opened this issue Nov 7, 2024 · 2 comments
Open

Noise algorithm in WebGPURenderer - performance concerns #29830

Makio64 opened this issue Nov 7, 2024 · 2 comments

Comments

@Makio64
Copy link
Contributor

Makio64 commented Nov 7, 2024

Description

I like to use different kind of noise in my projects and i optimized them a lot for this purpose like ashima snoise : https://www.shadertoy.com/view/4sdGD8

When I translate it to tsl using the tsl-translator ( https://threejs.org/examples/?q=tsl%20to#webgpu_tsl_editor ) it give me something like :

// Three.js Transpiler r170

import { vec3, mod, Fn, vec2, floor, step, float, sub, int, dot, max, fract, abs, pow, mul } from 'three/tsl';

export const permute = /*#__PURE__*/ Fn( ( [ x_immutable ] ) => {

	const x = vec3( x_immutable ).toVar();

	return mod( x.mul( 34. ).add( 1. ).mul( x ), 289. );

} ).setLayout( {
	name: 'permute',
	type: 'vec3',
	inputs: [
		{ name: 'x', type: 'vec3', qualifier: 'in' }
	]
} );

export const snoise = /*#__PURE__*/ Fn( ( [ v_immutable ] ) => {

	const v = vec2( v_immutable ).toVar();
	const i = vec2( floor( v.x.add( v.y ).mul( .36602540378443 ).add( v ) ) ).toVar(), x0 = vec2( i.x.add( i.y ).mul( .211324865405187 ).add( v.sub( i ) ) ).toVar();
	const s = float( step( x0.x, x0.y ) ).toVar();
	const j = vec2( sub( 1.0, s ), s ).toVar(), x1 = vec2( x0.sub( j ).add( .211324865405187 ) ).toVar(), x3 = vec2( x0.sub( .577350269189626 ) ).toVar();
	i.assign( mod( i, 289. ) );
	const p = vec3( permute( permute( i.y.add( vec3( int( 0 ), j.y, int( 1 ) ) ) ).add( i.x ).add( vec3( int( 0 ), j.x, int( 1 ) ) ) ) ).toVar(), m = vec3( max( .5.sub( vec3( dot( x0, x0 ), dot( x1, x1 ), dot( x3, x3 ) ) ), 0. ) ).toVar(), x = vec3( fract( p.mul( .024390243902439 ) ).mul( 2. ).sub( 1. ) ).toVar(), h = vec3( abs( x ).sub( .5 ) ).toVar(), a0 = vec3( x.sub( floor( x.add( .5 ) ) ) ).toVar();

	return .5.add( mul( 65., dot( pow( m, vec3( 4. ) ).mul( - 0.85373472095314.mul( a0.mul( a0 ).add( h.mul( h ) ) ).add( 1.79284291400159 ) ), a0.mul( vec3( x0.x, x1.x, x3.x ) ).add( h.mul( vec3( x0.y, x1.y, x3.y ) ) ) ) ) );

} ).setLayout( {
	name: 'snoise',
	type: 'float',
	inputs: [
		{ name: 'v', type: 'vec2', qualifier: 'in' }
	]
} );

Solution

I was wondering if this seems ok to you in terms of performance ?

Also I was wondering if Three have a current system to check the output of the shaders ?

Alternatives

RawShaderNodeMaterial( gslVertexShader, gslFragmentShader, wgslVertexShader, wgslFragmentShader )

Additional context

No response

@Mugen87
Copy link
Collaborator

Mugen87 commented Nov 7, 2024

Also I was wondering if Three have a current system to check the output of the shaders ?

For a given mesh, you can query vertex and fragment shader like so:

console.log( await renderer.debug.getShaderAsync( scene, camera, mesh ) );

getShaderAsync() gives you an object holding the vertex and fragment shader string for the current configured backend. If you want to force GLSL output, you have to create the renderer via forceWebGL: true. Or use a browser that does not support WebGPU yet.

You might want to use the dev branch since there is a minor bug in r170 that breaks the method, see #29832.

@Mugen87
Copy link
Collaborator

Mugen87 commented Nov 8, 2024

I was wondering if this seems ok to you in terms of performance ?

I don't see an obvious flaw.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants