For shader debugging purposes, I’m trying to pass flags into a thin instance shader… and failing. If line 52 is uncommented, the circles no longer render. (No errors on console.) Clues?
I do have an error in the console (Chrome):
[.WebGL-0000368E00A54E00] GL_INVALID_OPERATION: Vertex shader input type does not match the type of the bound vertex attribute.
That’s because thinInstanceSetBuffer
only supports Float32Array
as buffers. You can use a float instead of an uint in your shader (GPUs are bad with integers anyway):
Thanks. In operation: https://playground.babylonjs.com/#D2SV4S#5
(Chrome seems to filter errors by type at a certain point. I had cleared the console after the errors and before the last run.)
@Evgeni_Popov Hi Evgeni, do you think there might be a precision issue with floating-point numbers if the value of the thin instance attribute goes too large? For example, if I want to calculate UV coordinates based on the instance index (as a thin instance attribute), would the UV coordinates become less precise when the value of the index is very large due to the limitations of floating-point representation?
BTW Three.js does support setting integers as thin instance attribtute, it would be great if Babylon could do the same
You shouldn’t have problems with float precision, as 32 bits float can exactly represents integer numbers up to 16,777,217 (2^ 24 + 1).
I created an internal task for us to support attributes other than floats for thin instances!
For anyone encountering the precision limit (larger than 16,777,216) of float attributes before integer attributes are supported, you can try using an int proxy to store the thin instance attribute as a workaround.
Let’s assume that initially you are using float instance attributes like this:
// your glsl vertex shader
const vertexShader = `
attribute float sampleAttribute; // the instance attribute
void main() {
int result = int(sampleAttribute) * 10 + 12345; // sample usages of the instance attribute
// ...
}
`
// ...
const sampleAttributesArray = new Float32Array(10000000);
for (let i = 0; i < sampleAttributesArray.length(); ++i) {
sampleAttributesArray[i] = i;
}
sampleInstanceMesh.thinInstanceSetBuffer("sampleAttribute", sampleAttributesArray , 1);
// ...
If you want to increase the instance number to larger than 20,000,000 and encounter precision issues with floats, you can create an int proxy to set the data, but use a float array to set the buffer. Then, interpret the float attribute as an int within your shader. It would look something like this:
// your glsl vertex shader
const vertexShader = `
attribute float sampleAttribute; // the instance attribute
void main() {
int result = floatBitsToInt(sampleAttribute) * 10 + 123; // interprets float bits as int
// ...
}
`
// ...
const sampleAttributesArray = new Int32Array(20000000); // exceeds precision limits of float
const sampleAttributesArrayProxy = new Float32Array(sampleAttributesArray.data);
for (let i = 0; i < sampleAttributesArray.length(); ++i) {
sampleAttributesArray[i] = i; // set value to int array
}
sampleInstanceMesh.thinInstanceSetBuffer("sampleAttribute", sampleAttributesArrayProxy, 1); // set buffer with the float proxy array
This way, the instance attributes store integer bits. Only during the buffer setting process, we treat them as floats, but in the shader, we interpret them as integer bits.