0
votes

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.

1
FYI: You can make your shader have attribute vec4 vertexPosition; and still only pass 3 values per vertex with gl.vertexAttribPointer(vertexPositionLoc, 3, gl.FLOAT, false, 0, 0);. w defaults to 1 if not provided for an attribute so this someMatrix * vec4(vertexPosition, 1.0); can be simplified to someMatrix * vertexPosition;gman
Wow, I always thought, the data type of the attribute has to be equal to the item size of the corresponding buffer, noted as second argument for gl.vertexAttribPointer. - Nice little trick! Thank you, gman!user4512363

1 Answers

0
votes

When you say

someMatrix * vec4(vertexPosition, 1.0);

someMatrix is a 4x4 matrix and vertexPosition is ALWAYS a 3x1 matrix that is converted to a 4x1 matrix with the addition of the 1.0. So a 4x4 matrix multiplied by a 4x1 matrix will produce again a valid 4x1 matrix (i.e. the gl_Position). Note that a 4x1 matrix is a vec4.

So you never multiply with a vector of "arbitrary" length. When you pass the data down (i.e. your vertices variable) the system breaks them down into triplets, adds the 1.0 and does the 4x4 by 4x1 multiplication.