When writing a specific scene in webgl, the usual procedure of transforming an object would be to define the original vertex position data and pass it to the vertex shader, where the vertices are multiplied with matrices, that hold the informations about perspective, translations, rotations and scale, so that the corresponding vertex shader code - for example - would look like this:
gl_Position = projectionMatrix * modelviewMatrix * vec4(vertexPosition, 1.0);
The modelviewMatrix itself is then the result of the multiplication of the viewMatrix with the modelMatrix, which again are the results of successive matrix manipulations to translate, rotate and scale.
What I'd like to know now is, how this last link in the chain of multiplications works - the multiplication of a mat4 with a vector array of arbitrary length.
someMatrix * vec4(vertexPosition, 1.0);
That is because I'm writing on a webgl editor and I want to be able to save the vertex position data of the created and transformed 3D-objects without the need of adding information about matrix transformations but as raw position data, simply as {x, y, z, x, y, z, x, y, z, etc.}, just like the original array of vertices.
As a basic example, let's say we have the following vertices for a simple triangle:
var vertices = [0.0, 1.0, 0.0, -1.0, -1.0, 0.0, 1.0, -1.0, 0.0];
Then I create a mat4 and translate it by [2, 0, 0]
.
The function I need would then take this translated mat4 and the vertices array as parameters, would multiply both and return an array of translated vertices like:
var translatedVertices = [2.0, 1.0, 0.0, 1.0, -1.0, 0.0, 3.0, -1.0, 0.0];
It seems obvious, that for multiplying a 4x4 matrix with a vector array, there has to be added a fourth value to it, so the first step should be to split the original vec3 array and insert for each triple of values an additional 1.0
, to make it a vec4 array, [x, y, z] --> [x, y, z, 1]
, but apart from that, I have absolutely no idea how this JavaScript function should look like.
attribute vec4 vertexPosition;
and still only pass 3 values per vertex withgl.vertexAttribPointer(vertexPositionLoc, 3, gl.FLOAT, false, 0, 0);
.w
defaults to 1 if not provided for an attribute so thissomeMatrix * vec4(vertexPosition, 1.0);
can be simplified tosomeMatrix * vertexPosition;
– gmangl.vertexAttribPointer
. - Nice little trick! Thank you, gman! – user4512363