mabu
January 25, 2022, 4:10pm
1
How do I set the following shader uniform:
uniform mat4 matrix_object_face_to_world[6];
material.setParameter seems to only take data of type number, number[] and Texture according to the docs
1 Like
Hi @mabu ,
Check this post on how to pass an array to a shader:
I apologize for reviving an older thread, I had trouble myself sending an array to a shader. I was able to resolve my issue, posting my findings since there were a lot unanswered threads on the subject, in case it’s of help (@mvaligursky do step in if I got something wrong).
To make sure an array uniform is created:
You need to add [0] to your uniform name, at the end.
Passing Float32Array and dynamic JS arrays is supported. I think the exact length of the array is what specifies the type of …
1 Like
mabu
January 26, 2022, 1:46pm
3
I’m not getting it to work so far.
I see that https://github.com/playcanvas/engine/blob/bb5aa65caa880ab546ce9de456ef5bc195533f74/src/graphics/shader-input.js
only seems to account for vector arrays but not matrix arrays. How is that type deducted by the engine?
I assume gl.getActiveAttrib returns gl.FLOAT_MAT4 for a matrix array, but it seems that https://github.com/playcanvas/engine/blob/bb5aa65caa880ab546ce9de456ef5bc195533f74/src/graphics/constants.js would need to add a UNIFORMTYPE_MAT4ARRAY type (and same for other matrix dimensions) to support setting matrix arrays by adding “[0]” to the variable name. Or am I missing something?
1 Like
as an example, here’s how we use skinning matrices (in case uniforms are used to supply them to vertex shaders)
export default /* glsl */`
attribute vec4 vertex_boneWeights;
attribute vec4 vertex_boneIndices;
uniform vec4 matrix_pose[BONE_LIMIT * 3];
void getBoneMatrix(const in float i, out vec4 v1, out vec4 v2, out vec4 v3) {
// read 4x3 matrix
v1 = matrix_pose[int(3.0 * i)];
v2 = matrix_pose[int(3.0 * i + 1.0)];
v3 = matrix_pose[int(3.0 * i + 2.0)];
}
mat4 getSkinMatrix(const in vec4 indices, const in vec4 weights) {
// get 4 bone matrices
and this is how JS is setting those up:
this._skinDrawCalls++;
if (device.supportsBoneTextures) {
boneTexture = meshInstance.skinInstance.boneTexture;
this.boneTextureId.setValue(boneTexture);
boneTextureSize[0] = boneTexture.width;
boneTextureSize[1] = boneTexture.height;
boneTextureSize[2] = 1.0 / boneTexture.width;
boneTextureSize[3] = 1.0 / boneTexture.height;
this.boneTextureSizeId.setValue(boneTextureSize);
} else {
this.poseMatrixId.setValue(meshInstance.skinInstance.matrixPalette);
}
}
}
// returns number of extra draw calls to skip - used to skip auto instanced meshes draw calls. by default return 0 to not skip any additional draw calls
drawInstance(device, meshInstance, mesh, style, normal) {
DebugGraphics.pushGpuMarker(device, meshInstance.node.name);
instancingData = meshInstance.instancingData;
data are allocated this way
format: PIXELFORMAT_RGBA32F,
mipmaps: false,
minFilter: FILTER_NEAREST,
magFilter: FILTER_NEAREST
});
this.boneTexture.name = 'skin';
this.matrixPalette = this.boneTexture.lock();
} else {
this.matrixPalette = new Float32Array(numBones * 12);
}
}
destroy() {
if (this.boneTexture) {
this.boneTexture.destroy();
this.boneTexture = null;
}
}
I think maybe sth related to 16 elements, because of matrix4x4, precisely dont sure
mabu
January 26, 2022, 2:25pm
7
It looks like you’re using a vec4 array rather than a mat4 array and then assemble a mat4 in the shader. Does that mean it’s not possible to use mat4 array uniforms directly?
it works for matrix as well, for example shadow cascade matrixes in code
code += "uniform mat4 light" + i + "_shadowMatrixPalette[4];\n";
this.shadowMatrixPaletteId[i] = scope.resolve(light + "_shadowMatrixPalette[0]");
this._shadowMatrixPalette = new Float32Array(4 * 16); // always 4
this.shadowMatrixPaletteId[cnt].setValue(directional._shadowMatrixPalette);
1 Like