mrdoob / three.js

JavaScript 3D Library.
https://threejs.org/
MIT License
102.69k stars 35.37k forks source link

TSL: Avoid naming collision when using `label()` or `toVar()`. #29813

Open Mugen87 opened 1 week ago

Mugen87 commented 1 week ago

Description

When using label() or toVar() to give variables a name, collisions can occur when the name is already reserved for internal entities like uniforms or varyings.

If you now redefine a variable on app level, a shader error occurs. In WGSL for example:

Error while parsing WGSL: :40:2 error: redefinition of 'cameraNear'

Solution

It would be nice if the node material could automatically detect such name collisions and modify the custom names e.g. with a suffix.

Alternatives

Leave it as it is and ask developers to pick unique names.

Additional context

29810

ligaofeng0901 commented 6 days ago

I have the following thoughts/ideas:

  1. .label() is used for uniforms, the names should be detected in shader level. Any uniform generated from a unique node should have a unique name
  2. toVar() is used for variables in shader. any variable in a Fn should be visible only in this Fn. Becasue all vars are defined on the top of main function, the name of any variable in a Fn should not collide with any other variables in any other Fns. So far, one situation I meet is
    
    const fn1 = Fn(([param1]) => {
     const var1 = vec3().toVar('var1');
     .....
     return var1;
    });

this.colorNode = Fn(() => { const var1 = vec3().toVar('var1'); const a = fn1(1); const b = fn1(2); ..... return mix(a, b, var1); });


After shader building, the logic of the shader is totally different from what I want. The builder thinks all `var1` is the same variable, the value of different `var1` will be affected by others.