I’m noticing some weird issues I can’t explain other than TSL not having precision control ??
In a glsl I have a shader working with things like:
precision mediump float;
precision mediump sampler2D;
But when making the TSL port of it, something is off. Testing arround I’ve noticed that for example decimals are ignored after the first one. So 0.01 = 0 Let’s say If I wanted to scroll the UV by vec2(0.01,0) it wont move at all…
My tests show Three.js TSL is innocent. A texture shift of 0.01 is visible:
3 Likes
I’m going nuts here… do you see why this might fail? Same settings on both…
GLSL
precision highp float;
precision highp sampler2D;
varying vec2 vUv;
uniform sampler2D uVelocity;
uniform sampler2D uSource;
uniform vec2 texelSize;
uniform vec2 dyeTexelSize;
uniform float dt;
uniform float dissipation;
uniform bool sourceIsVelocity;
void main () {
vec2 coord = vUv - dt * texture2D(uVelocity, vUv).gb * texelSize;
vec4 result = texture2D(uSource, coord);
float decay = 1.0 + dissipation * dt;
result /= decay;
if( sourceIsVelocity )
{
vec4 data = texture2D(uVelocity, vUv);
gl_FragColor = vec4( data.r, result.g, result.b, data.a);
}
else
{
gl_FragColor = result;
}
}
But in TSL
type Sampler2D = ShaderNodeObject<TextureNode>;
class AdvectShader extends MeshBasicNodeMaterial {
readonly sourceIsVelocity = uniform(0);
readonly delta = uniform(0);
readonly dissipation = uniform(0.2);
readonly uSource:Sampler2D = texture(placeholderTexture);
constructor( uVelocity:Sampler2D, textelSize:UniformVec2 ) {
super();
this.colorNode = Fn(()=>{
const velocity = uVelocity.sample(uv()).gb ;
const coord = uv().sub( this.delta.mul( velocity ).mul( textelSize ) );
const result = this.uSource.sample( coord ).toVar();
const decay = add( 1.0, this.dissipation.mul( this.delta ) );
result.divAssign( decay );
If( this.sourceIsVelocity , ()=>
{
const original = uVelocity.sample( uv() );
result.assign(vec4(
original.r,
result.gb,
original.a
));
} ) ;
return result;
})();
}
}
There’s an issue with the precision…
If on a TSL node you set a pixel with a value like vec4(0,0,0,123)
Then that 123 is lost and clamped to a value of 1…
And if another material needs to re-use this data, the pixel sampled at .a will equal 1 not 123…
Chatgpt says : By default, WebGPU render targets might use RGBA8Unorm (0–1 range).
That might be a clue…
How to make it use precision highp float ?
Went into a rabbit hole, but it is solved… the problem was a miss-interpretation on my part… I was setting the material.colorNode assuming I had control over the alpha channel but apparently only the RGB is controled by that node.
Solution → material.fragmentNode
Time wasted: 2 days.
Headaches: innumerable.
1 Like