Obtaining normal Matrix for 1.3+ shader

Hello.

I am porting code to work with GLSL >=1.3 shaders.
The gl_NormalMatrix built-in uniform, among others, is deprecated and unsupported in GLSL 1.3 and above.
However, OGL, to my understand, still calculates matrices when using the traditional functions such as glTransformf(), glPushMatrix(), etc.

I have the following code to get these and inject them to my uniforms, but there is no GL definition for normal matrix. Why is this missing, or is it called differently?

	void setUniforms() {
		
		GLfloat m[16];

		glGetFloatv(GL_MODELVIEW_MATRIX, &m[0]);
		glUniformMatrix4fv(modelViewMatrixLoc, 1, GL_FALSE, &m[0]);

		glGetFloatv(GL_PROJECTION_MATRIX, &m[0]);
		glUniformMatrix4fv(projectionMatrixLoc, 1, GL_FALSE, &m[0]);
		
		// Error: GL_NORMAL_MATRIX is not a thing. :-(
		glGetFloatv(GL_NORMAL_MATRIX, 1, GL_FALSE, &m[0]);
		glUniformMatrix4fv(normalMatrixLoc, 1, GL_FALSE, &m[0]);
	}

So yeah, must I really calculate this by myself now?

Thanks in advance!

Hey,

Yes, you have to “calculate” the normal matrix by your own. But this is really easy.
The model matrix a 4x4 matrix. All you have to do now is just convert the Model matrix to a simple 3x3 matrix.
This is because the normals do not need a translation or a scale factor. All they need is the models rotation.

Model matrix e.g.:


1 0 0 0
0 1 0 0
0 0 1 0
0 0 0 1

this will become:


1 0 0
0 1 0
0 0 1

That’s all, hope this will help you :wink:

  • Daniel

I don’t get why they pretty much force people to implement their own matrix stack now, rofl.

Anyway, I can see truncating the translation column, but scale matrices can affect more than just the bottom row, as far as I know at least. Also scales will (can) affect normals, but in a different manner.

I don’t use scales, so thank God.

	void setUniforms() {
		
		GLfloat m[16];
		
		glGetFloatv(GL_PROJECTION_MATRIX, &m[0]);
		glUniformMatrix4fv(projectionMatrixLoc, 1, GL_FALSE, &m[0]);

		glGetFloatv(GL_MODELVIEW_MATRIX, &m[0]);
		glUniformMatrix4fv(modelViewMatrixLoc, 1, GL_FALSE, &m[0]);

		// Error: GL_NORMAL_MATRIX is not a thing. :-(
		//glGetFloatv(GL_NORMAL_MATRIX, 1, GL_FALSE, &m[0]);

		// HACKHACK: As long as we don't do scale transformations (which we don't) we will be fine doing just this.
		m[12] = 0;
		m[13] = 0;
		m[14] = 0;
		glUniformMatrix4fv(normalMatrixLoc, 1, GL_FALSE, &m[0]);
	}

I hope I will get away with doing just that. Only other geometric data I will have to transform manually are light positions, so I should be fine for now.

In any case, thanks for letting me know.

The idea is to separate actual graphics related stuff (i.e. lights, transformations, fog, etc) from the API, so you are just dealing with the data. That way, how you format and use your data is totally up to you, and you write your code and shaders accordingly.

On another note, check out the GLM library to replace the matrix math functions that have been deprecated, and check out the Unofficial OpenGL SDK, where you can find a matrix stack implementation if you must use one.

There’s no need to do an inverse transpose all the time. The website you linked to mentions they are using non-uniform scaling and rotations. He mentions this on the same page:

A rotation is certainly orthogonal. By mathematical induction, the product of any finite number of orthogonal matrices is again orthogonal–so rotations are not really a problem. As the author says, a non-uniform scale will require the inverse-transpose so there’s nothing we can do about those.

A uniform scale, however, won’t require the inverse-transpose. To see this, note that a uniform scale is not orthogonal. Consider this: is the transpose of a uniform scale equal to its inverse? No, unless it is the identity matrix. So it appears that we may need to compute the inverse-transpose for this case after all. Since the scale is uniform, however, the transform only affects the magnitude of the normal vectors but not the direction. So re-normalizing the normals will work in this special case and so we avoid computing the inverse-transpose.