gl_NormalMatrix equivalent in shaders?

openframeworks passes the following uniforms by default.

uniform mat4 modelViewMatrix;
uniform mat4 projectionMatrix;
uniform mat4 textureMatrix;
uniform mat4 modelViewProjectionMatrix;

Is there any equivalent for the gl_NormalMatrix which is deprecated in version 150?

Rg,

Arnaud

The GLSL definition for “gl_NormalMatrix” is “the transpose of the inverse of the gl_ModelViewMatrix.” We might need to add this into the Programmable Renderer as a default. It should be really simple as you just have to invert and transpose the modelViewMatrix. Thoughts @arturo?

Hi,

the answer interests me as well. :blush:

Using the programmable pipeline (OpenGL 3.3), I’ve been able to do something like this so far :

void ofApp::draw() {
cam.begin();
ofMatrix4x4 normalMatrix = ofMatrix4x4::getTransposedOf(cam.getModelViewMatrix().getInverse());
shader.setUniformMatrix4f("normalMatrix", normalMatrix);
shader.begin();
// etc...
shader.end();
cam.end();

and it seems to work fine for what I do (lighting).

My understanding is that’s useless to recompute it every time in a shader, so I compute it once and pass it as a uniform.

But that may be suboptimal, so I’m interested on what you would have to say about it, if there’s a better solution.

in the version in master there’s 2 functions that give useful matrices to work with lighting.

ofGetCurrentNormalMatrix();
ofGetCurrentViewMatrix();

the view matrix is the transformation of the camera and is uploaded by default to the shaders as the uniform viewMatrix you probably want that instead of the modelViewMatrix to do light calculations. the normal matrix is not uploaded unless there’s a material binded but can be recovered with the function ofGetCurrentNormalMatrix() and uploaded to your own shaders or you can implement ofBaseMaterial which already uploads the normal matrix as the uniform normalMatrix when it’s binded.

btw, the normal matrix is not always uploaded because it implies calculating a matrix inverse which is relatively expensive and is not needed in most basic cases. so materials upload it themselves in the base class method uploadMatrices which can be overriden and you can get it through a function call and upload it manually to a plain shader if you prefer

Awesome arturo !

I didn’t know about ofGetCurrentNormalMatrix but that may be because I still use a rather old version of OF (and it doesn’t seem to be in the documentation yet).

If it works my use of the normal matrix will be much simpler. Thanks :smile:

yes it’s probably only in the current version in master not in 0.8.4 but not 100% sure

@Pando Using of_v0.8.4 The code you posted above works for me in terms of converting from OpenGL coordinates to OF coordinates, but when I light the object it’s clearly using its local normals. For example, using this vertex shader:

#version 120

uniform vec3 lightDir;
uniform mat4 normalMatrix;

varying vec3 normal;

void main(){

    normal = normalize (mat3(normalMatrix) * gl_Normal);
    gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
    gl_TexCoord[0] = gl_MultiTexCoord0;
}

and this in the cpp file:

pointLight.setGlobalOrientation(ofQuaternion(0.0,0.0,-1.0,1.0));
cam.setupPerspective();

lightShader.load("normalLighting");
lightShader.begin();

ofVec3f dir = pointLight.getOrientationEuler().normalized();
lightShader.setUniform3fv("lightDir",  dir.getPtr());
lightShader.setUniformMatrix4f("normalMatrix", ofMatrix4x4::getTransposedOf(cam.getModelViewMatrix().getInverse()));
lightShader.end();

my object is very clearly lit up on its local z-axis, even as it spins. How can I get the normals in world coordinates?