Help with basic lighting shader in opengles

  • Follow


Hi everybody.

I'm learning lighting in opengles, and I'm posting here because I want to be 
sure that I pass to the shader the correct uniform matrices and other 
parameters.
So far I've got in my C++ code (I use the glm math header only library):

glm::mat4    projectionMatrix;    // the camera projection matrix
glm::mat4    modelviewMatrix;    //the camera modelview (i.e. 
gluLookAt(...))

glm::mat4   modelMatrix;            // this is my object's modelview matrix 
(i.e. I can render my object without lighting if I pass to a basic vertex 
shader the single matrix:  "mp = projectionMatrix * modelviewMatrix * 
modelMatrix")

glm::vec3    lightPosInWorldSpace;

OK, this is what I got in my C++ code.
Now my lighting shader needs these uniforms (I will use the leading u_ 
notation here):

mat4 u_projectionMatrix;    // some versions get the full 
modelviewprojectionMatrix here...
mat4 u_modelviewMatrix;
mat3 u_normalMatrix;
vec3 u_lightPosInEyeSpace;

From now on I'm not 100% sure of what I'm doing; please check CAREFULLY if 
it's correct:
-----------------------------------------------------------------------------
C++                              ->                                  VERTEX 
SHADER
------------------------------------------------------------------------------
projectionMatrix    ->    u_projectionMatrix    (or in some versions: 
projectionMatrix * modelviewMatrix * modelMatrix -> 
modelviewprojectionMatrix )
modelviewMatrix*modelMatrix    ->    u_modelviewMatrix
((modelviewMatrix*modelMatrix )inverse)transpose    ->    u_normalMatrix
vec3((modelviewMatrix*modelMatrix)*vec4(lightPosInWorldSpace,0.0))    -> 
u_lightPosInEyeSpace

My questions:
1) Is this correct ? I've read a lot of articles (and a book) about it, and 
none of them showed  how to assign the shader uniforms in a clear and 
concise way.

Now I got two more questions:
2) when using a directional light (glm::vec3 lightDirInWorldSpace) how do I 
transform it in eye space ? My guess:
((modelviewMatrix*modelMatrix )inverse)transpose    * 
ghtDirInWorldSpace    -> u_lightDirInEyeSpace    (provided the assignments 
above are correct, which I'm not too sure of)
3) I've read that when u_modelviewMatrix  has no scaling at all inside it, 
or just uniform scaling, it can be: u_normalMatrix = 
mat3(u_modelviewMatrix ) (I don't know if this compiles
in the shader, it does in C++ with glm).
Furthermore if no scaling at all  is present, the normalization used in the 
vertex shader for lighting calculation can be avoided.
So I ask: is it possible to pass such a scaling (or better its inverse) as a 
vec3 uniform to the vertex shader and to apply it later (i.e. always using 
u_normalMatrix = mat3(u_modelviewMatrix ) and
no normalization at all)?
Most likely the answer should be negative, otherwise this faster procedure 
would have become a standard already...

Thanks in advance for your answers/contributions
 

0
Reply writeme7597 (2) 8/15/2012 7:54:13 AM

Just to say that I've changed my mind about how to calculate 
u_lightPosInEyeSpace: it should be:
vec3((cameraModelviewMatrix)*vec4(lightPosInWorldSpace,0.0))    -> 
u_lightPosInEyeSpace,
so that it's not object-dependent.

I've also found on the web 
(http://www.learnopengles.com/android-lesson-two-ambient-and-diffuse-lighting/) 
a well commented vertex shader,
that I have further modified in this way (the fragment shader is trivial):

uniform mat4 u_MVPMatrix;      // A constant representing the combined 
model/view/projection matrix.
uniform mat4 u_MVMatrix;       // A constant representing the combined 
model/view matrix.
uniform vec3 u_MVMatrixScaleInverse;	// To be tested. default (1,1,1). Note 
that the scale usually refers to the model matrix only, since the view 
matrix is usually orthonormal (gluLookAt(...) and similiar are OK)
uniform vec3 u_LightPos;       // The position of the light in eye space 
(vec3(view matrix * vec4(lightPosInWorldSpace,0) AFAIK).
uniform float u_LightAttenuationFactor;	// Maybe it can be inglobed into 
u_LightPos.w. default 0.25 (or simply 0.0 = no attenuation)

attribute vec4 a_Position;     // Per-vertex position information we will 
pass in.
attribute vec4 a_Color;        // Per-vertex color information we will pass 
in.
attribute vec3 a_Normal;       // Per-vertex normal information we will pass 
in.

varying vec4 v_Color;          // This will be passed into the fragment 
shader.

void main()                    // The entry point for our vertex shader.
{

   vec3 modelViewVertex = vec3(u_MVMatrix * a_Position);  					// Transform 
the vertex into eye space.
   vec3 modelViewNormal = vec3(u_MVMatrix * vec4(a_Normal, 
0.0))*u_MVMatrixScaleInverse;     	// Transform the normal's orientation 
into eye space and (to be tested) correct scaling errors.
   float distance = length(u_LightPos - modelViewVertex);   		// Will be 
used for attenuation.	(slow IMO: refactor code using length2 if available, 
since "distance * distance" is used)
   vec3 lightVector = normalize(u_LightPos - modelViewVertex);    	// Get a 
lighting direction vector from the light to the vertex.

	// Calculate the dot product of the light vector and vertex normal. If the 
normal and light vector are
	// pointing in the same direction then it will get max illumination.
   float diffuse = max(dot(modelViewNormal, lightVector), 0.1);
   diffuse = diffuse * (1.0 / (1.0 + (u_LightAttenuationFactor * distance * 
distance)));  	// Attenuate the light based on distance.

   v_Color = a_Color * diffuse;          				// Multiply the color by the 
illumination level. It will be interpolated across the triangle.
	// gl_Position is a special variable used to store the final position.
	// Multiply the vertex by the matrix to get the final point in normalized 
screen coordinates.
   gl_Position = u_MVPMatrix * a_Position;  	// Some versions of this shader 
replace u_MVPMatrix with u_ProjectionMatrix, and multiply it with a vec4 
modelViewVertex (see first line of the shader).
						// This could be faster, because u_MVPMatrix does not need to be 
calculated in the C++ code anymore...
}

I still have to test it: hope it works.
Feel free to post comments/suggestions about it... 

0
Reply writeme7597 (2) 8/15/2012 2:04:27 PM


1 Replies
59 Views

(page loaded in 0.07 seconds)


Reply: