If I write attribute mat2/3/4 in shader and upload data like this
// glsl
attribute mat4 matrix;
// js
geometry.addAttribute( 'matrix', new THREE.BufferAttribute( data, 16 ) );
It fails because the second argument of gl.vertexAttribPointer() (= attribute.itemSize) takes only 1, 2, 3, or 4.
GL ERROR :GL_INVALID_VALUE : glVertexAttribPointer: size GL_INVALID_VALUE
I needed to break it up to columns to use them on Three.js.
// glsl
attribute vec4 column0;
attribute vec4 column1;
attribute vec4 column2;
attribute vec4 column3;
void main() {
mat4 matrix = mat4( column0, column1, column2, column3 );
}
// js
geometry.addAttribute( 'column0', new THREE.BufferAttribute( data0, 4 ) );
geometry.addAttribute( 'column1', new THREE.BufferAttribute( data1, 4 ) );
geometry.addAttribute( 'column2', new THREE.BufferAttribute( data2, 4 ) );
geometry.addAttribute( 'column3', new THREE.BufferAttribute( data3, 4 ) );
So we can't practically use mat2/3/4 attribute in shader on Three.js because renderer doesn't handle them correctly. But I think allowing them may be useful.
To handle them we need to update WebGLRenderer to call enableAttribute and vertexAttribPointer multiple times for mat2/3/4.
https://stackoverflow.com/questions/38853096/webgl-how-to-bind-values-to-a-mat4-attribute
// glsl
attribute mat4 matrix;
// js
geometry.addAttribute( 'matrix', new THREE.BufferAttribute( data, 16 ) );
// js in renderer
state.enableAttribute( programAttribute.location );
state.enableAttribute( programAttribute.location + 1 );
state.enableAttribute( programAttribute.location + 2 );
state.enableAttribute( programAttribute.location + 3 );
_gl.vertexAttribPointer( programAttribute.location, 4, type, normalized, 64, 0 );
_gl.vertexAttribPointer( programAttribute.location + 1, 4, type, normalized, 64, 16 );
_gl.vertexAttribPointer( programAttribute.location + 2, 4, type, normalized, 64, 32 );
_gl.vertexAttribPointer( programAttribute.location + 3, 4, type, normalized, 64, 48 );
But I think enabling attribute mat2/3/4 may be useful.
What is your use case?
And why do we need to support something WegGL does not?
Users pass vectors or quaternions instead, in this case, I expect. More efficient.
My use case is geometry instancing. I want to pass local model matrix for each instance.
Position + quaternion (and univariate scale factor if needed) is more efficient than a Matrix4 -- at least as far as passing the data is concerned.
I think your use case is sufficiently-compelling, however.
Given you want to support something WebGL does not, I suggest you at least consider the alternatives.
Given you want to support something WebGL does not, I suggest you at least consider the alternatives.
WebGL support mat2/3/4 attribute in vertex shader.
I think we can add some simple utility functions in three like this:
// pseudocode
state.enableAttribute = function(){
if (gl.getActiveAttrib(program, i).type === gl.FLOAT_MAT2) {
for(let i = 0;i < Math.sqrt(matSize);i ++) {
gl.enableAttribute(location + i);
}
}
};
Yes, I think WebGL GLSL supports mat2/3/4 attributes. So @WestLangley could you explain what "WebGL doesn't support mat2/3/4 attribues" means here for me?
@takahirox Sorry, I'm not sure what I was thinking... :/
No problem. I think because I wrote the issue comment poorly then you misunderstood something. I updated the comment a bit. I hope the issue is clearer now.
Most helpful comment
My use case is geometry instancing. I want to pass local model matrix for each instance.
https://github.com/takahirox/three.js/blob/PhysicsInstancing/examples/webgl_physics_instancing.html#L247