-
-
Notifications
You must be signed in to change notification settings - Fork 36k
Closed
Description
Description
When creating Uniform Nodes for WebGPU, the default uniform type in the shader is float. If you want to use integer values in the shader, fp32 is capable of every integer value up to 2^24=16777216, after which fp32 precision breaks down. For better precision, you can set the nodetype of the uniform nodes to create, for example, uniforms of type uint. However, when setting the value of the integer uniform node, the value still gets uploaded to the GPU as a float, but is interpreted by the shader as an uint, which causes nonsense values. Right now you can only use integer uniforms with a little hack to interpret the value as float before uploading to the GPU (see attached jsfiddle)
Reproduction steps
- Create a uniform with type uint: uniform(value, "uint")
- Use a compute shader to write the value to an output buffer of type uint
- Read the output and compare
Code
import * as THREE from 'three';
import { Fn, uniform, storage } from 'three/tsl';
const renderer = new THREE.WebGPURenderer();
const outputNode = document.createElement("div");
document.body.appendChild(outputNode);
const int2float_hack = (x) => {
return new Float32Array(new Uint32Array([x]).buffer)[0];
};
const run = async () => {
const buffer = new THREE.StorageBufferAttribute(new Uint32Array(3), 1, Uint32Array);
const outputStorage = storage(buffer, "uint", 3);
const value = 16777217;
const u0 = uniform(value);
const u1 = uniform(value, "uint");
const u2 = uniform(int2float_hack(value), "uint");
const kernel = Fn(()=>{
outputStorage.element(0).assign(u0);
outputStorage.element(1).assign(u1);
outputStorage.element(2).assign(u2);
})().compute(3);
await renderer.computeAsync(kernel);
const result = new Uint32Array(await renderer.getArrayBufferAsync(buffer));
outputNode.innerText += "input value: " + value + "\n\n";
outputNode.innerText += "Element 0 (float uniform): " + result[0] + "\n";
outputNode.innerText += "Element 1 (uint uniform): " + result[1] + "\n";
outputNode.innerText += "Element 2 (uint uniform with hack): " + result[2] + "\n";
}
run();
Live example
Screenshots
Version
r171-dev
Device
No response
Browser
No response
OS
No response