I want to calculate the new normal vector and in GLSL 1.4 you can use this formula: normal = mat3(transpose(inverse(modelview))) * in_Normal; But my version of GLSL is 1.3 and the function inverse is not available in this version. Do you know if there is an alternative to this without coding the entire function to inverse a matrix ?
Asked
Active
Viewed 1,887 times
1
-
2I suggest to calculate the inverse on CPU side (e.g. [glm](https://glm.g-truc.net/0.9.9/index.html) has this function) and then pass it as an uniform to the shader. – Ripi2 Nov 19 '18 at 16:22
-
1If the matrix is an [Orthogonal matrix](https://en.wikipedia.org/wiki/Orthogonal_matrix) (which may be the case for the model view matrix), then the inverse matrix is equal the transposed matrix and the term can be simplified: `normal = mat3(modelview) * in_Normal;` – Rabbid76 Nov 19 '18 at 16:36
-
1I agree with @Ripi. Furthermore, check if you really need the inverse transpose. For a huge number of cases (when the model view matrix is just a rigid body transform), you don't need to do this. – Nico Schertler Nov 19 '18 at 16:36
-
see [Pseudo inverse matrix](https://stackoverflow.com/a/42293434/2521214) it is very easy to implement even in GLSL – Spektre Nov 21 '18 at 10:16
-
@Rabbid76 that is true only for rotational transform matrix... with homogenous transform matrix you need to correct the position afterwards... – Spektre Nov 21 '18 at 21:34
1 Answers
0
Assuming the last row of your matrix is [ 0 0 0 1 ]
(if you use only rotations, scaling and translation, it should), you can simplify your calculations.
Instead of:
normal = mat3(transpose(inverse(modelview))) * in_Normal
use:
normal = transpose(inverse(mat3(modelview))) * in_Normal
Then:
mat3 transpose(mat3 matrix) {
vec3 row0 = matrix[0];
vec3 row1 = matrix[1];
vec3 row2 = matrix[2];
mat3 result = mat3(
vec3(row0.x, row1.x, row2.x),
vec3(row0.y, row1.y, row2.y),
vec3(row0.z, row1.z, row2.z)
);
return result;
}
float det(mat2 matrix) {
return matrix[0].x * matrix[1].y - matrix[0].y * matrix[1].x;
}
mat3 inverse(mat3 matrix) {
vec3 row0 = matrix[0];
vec3 row1 = matrix[1];
vec3 row2 = matrix[2];
vec3 minors0 = vec3(
det(mat2(row1.y, row1.z, row2.y, row2.z)),
det(mat2(row1.z, row1.x, row2.z, row2.x)),
det(mat2(row1.x, row1.y, row2.x, row2.y))
);
vec3 minors1 = vec3(
det(mat2(row2.y, row2.z, row0.y, row0.z)),
det(mat2(row2.z, row2.x, row0.z, row0.x)),
det(mat2(row2.x, row2.y, row0.x, row0.y))
);
vec3 minors2 = vec3(
det(mat2(row0.y, row0.z, row1.y, row1.z)),
det(mat2(row0.z, row0.x, row1.z, row1.x)),
det(mat2(row0.x, row0.y, row1.x, row1.y))
);
mat3 adj = transpose(mat3(minors0, minors1, minors2));
return (1.0 / dot(row0, minors0)) * adj;
}

Slav
- 786
- 1
- 13
- 25
-
not working for me: in vertex: ` void main() { v_uv = uv; vec3 pos = position; rotate2d(pos.xz, t * .4); pos += offset; mat3 newNorm = transpose(inverse( toMat3(modelViewMatrix) )); v_normal = normalize( normal * newNorm); fragPos = vec3(modelViewMatrix * vec4(pos, 1.0)); gl_Position = projectionMatrix * modelViewMatrix * vec4(pos, 1.0); }` Light still appears to rotate with the geometry – Mr.Coder Aug 17 '23 at 06:50