Inverse model view matrix question

A simple question…maybe: all shaders that i’ve tried (taken by Rendermonkey or Shader Designer) are usefull only if use it on a mesh without translating and rotating it (object space=world space), if a make a rotation or a translation illumination is not correctly calculated. The problem, i think, is that i have to multiply lightPosition by the inverse model view matrix but i’ve tried in all way without results. This is a simple shader that is correct only when object and world space are equal, someone knows what i have to add to obtain correct illumination?

 
[VERTEX SHADER]

//
// Simple vertex shader for wood
//
// Author: John Kessenich
//
// Copyright (c) 2002-2004 3Dlabs Inc. Ltd.
//
// See 3Dlabs-License.txt for license information
//

varying float lightIntensity;
varying vec3 Position;
uniform vec3 lightPosition0;
uniform float Scale;

void main(void)
{
	vec4 pos = gl_ModelViewMatrix * gl_Vertex;
	Position = vec3(gl_Vertex) * Scale;
	vec3 tnorm = normalize(gl_NormalMatrix * gl_Normal);
	lightIntensity = max(dot(normalize(lightPosition0 - vec3(pos)), tnorm), 0.0) * 1.5;
	gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
}
[FRAGMENT SHADER]

//
// Simple fragment shader for wood
//
// Author: John Kessenich
//
// Copyright (c) 2002-2004 3Dlabs Inc. Ltd.
//
// See 3Dlabs-License.txt for license information
//

uniform float GrainSizeRecip;
uniform vec3  DarkColor;
uniform vec3  spread;

varying float lightIntensity; 
varying vec3 Position;

void main (void)
{
    //
    // cheap noise
    //
    vec3 location = Position;
    vec3 floorvec = vec3(floor(10.0 * Position.x), 0.0, floor(10.0 * Position.z));
    vec3 noise = Position * 10.0 - floorvec - 0.5;
    noise *= noise;
    location += noise * 0.12;

    //
    // distance from axis
    //
    float dist = location.x * location.x + location.z * location.z;
    float grain = dist * GrainSizeRecip;

    //
    // grain effects as function of distance
    //
    float brightness = fract(grain);
    if (brightness > 0.5) 
        brightness = (1.0 - brightness);
    vec3 color = DarkColor + brightness * spread;
    
    brightness = fract(grain * 7.0);    
    if (brightness > 0.5) 
        brightness = 1.0 - brightness;
    color -= brightness * spread;

    //
    // also as a function of lines parallel to the axis
    //
    brightness = fract(grain * 47.0) * 0.60;
    float line = fract(Position.z + Position.x);
    float snap = floor(line * 20.0) * (1.0/20.0);
    if (line < snap + 0.006)
        color -= brightness * spread;

    //
    // apply lighting effects from vertex processor
    //
    color = clamp(color * lightIntensity, 0.0, 1.0); 

    gl_FragColor = vec4(color, 1.0);
}



 

In my shaders I pass the accumulated rotations as a 4 components Uniform quaternion (same with the translation) and then convert them to matrices and apply em to the vertex position and normal to get the correct position in world space.
You could also pass the whole accumulated transform matrix as 16 components uniform (pretty heavy)

  <VERTEX_SHADER>

    <Uniform name = "cameraPosition" size = " 4" type = "float"/>

    <Uniform name = "transform3D"    size = "16" type = "float"/>

    <Uniform name = "bumpScale"      size = "1"  type = "float"/>



    <RawData>

      uniform vec4  cameraPosition;

      varying mat3  normalMatrix;

      uniform mat4  transform3D;

      uniform float bumpScale;



      void main(void)

      {

        mat3 rotations  = mat3(transform3D[0].xyz,

                               transform3D[1].xyz,

                               transform3D[2].xyz);



        vec3 firstRow   = rotations*gl_MultiTexCoord1.xyz;

             firstRow  *= bumpScale;

        

        vec3 secondRow  = rotations*gl_MultiTexCoord2.xyz;

             secondRow *= bumpScale;



        vec3 thirdRow   = rotations*gl_Normal;



        normalMatrix    = mat3(firstRow, secondRow, thirdRow);

        

        gl_TexCoord[0]  = gl_MultiTexCoord0;

        gl_TexCoord[1]  = cameraPosition  -  (transform3D*gl_Vertex);

        gl_Position     = ftransform();

      }

    </RawData>

  </VERTEX_SHADER>

Alternative code; 2 x vec4 uniforms instead of a single mat4.

<Shaders 
   linkProcessors    = "true" 
   vertexProcessor   = "VERTEX_SHADER"
   fragmentProcessor = "FRAGMENT_SHADER">

  <VERTEX_SHADER>
    <Uniform name = "cameraPosition" size = "4" type = "float"/>
    <Uniform name = "rotationsQuat"  size = "4" type = "float"/>
    <Uniform name = "translations"   size = "4" type = "float"/>
    <Uniform name = "bumpScale"      size = "1" type = "float"/>

    <RawData>
      uniform vec4  cameraPosition;
      uniform vec4  rotationsQuat;
      uniform vec4  translations;
      varying mat3  normalMatrix;
      uniform float bumpScale;

      void main(void)
      {
        vec4 firstRow  = vec4(1.0 - 2.0 * (rotationsQuat.y * rotationsQuat.y + rotationsQuat.z * rotationsQuat.z), 
                              2.0 * (rotationsQuat.x * rotationsQuat.y + rotationsQuat.z * rotationsQuat.w),
                              2.0 * (rotationsQuat.x * rotationsQuat.z - rotationsQuat.y * rotationsQuat.w),
                              0.0);  

        vec4 secondRow = vec4(2.0 * (rotationsQuat.x * rotationsQuat.y - rotationsQuat.z * rotationsQuat.w),  
                              1.0 - 2.0 * (rotationsQuat.x * rotationsQuat.x + rotationsQuat.z * rotationsQuat.z), 
                              2.0 * (rotationsQuat.z * rotationsQuat.y + rotationsQuat.x * rotationsQuat.w),  
                              0.0);  

        vec4 thirdRow  = vec4(2.0 * (rotationsQuat.x * rotationsQuat.z + rotationsQuat.y * rotationsQuat.w),
                              2.0 * (rotationsQuat.y * rotationsQuat.z - rotationsQuat.x * rotationsQuat.w),
                              1.0 - 2.0 * (rotationsQuat.x * rotationsQuat.x + rotationsQuat.y * rotationsQuat.y),  
                              0.0);  
        
        mat3 rotations   = mat3(firstRow.xyz, secondRow.xyz, thirdRow.xyz);

        normalMatrix[0]  = rotations*gl_MultiTexCoord1.xyz;
        normalMatrix[0] *= bumpScale;
        
        normalMatrix[1]  = rotations*gl_MultiTexCoord2.xyz;
        normalMatrix[1] *= bumpScale;

        normalMatrix[2]  = rotations*gl_Normal;

        vec4 worldSpaceVertexPos = vec4(dot(firstRow, gl_Vertex), dot(secondRow   , gl_Vertex),
                                        dot(thirdRow, gl_Vertex), dot(translations, gl_Vertex));
       
        gl_TexCoord[0]  = gl_MultiTexCoord0;
        gl_TexCoord[1]  = cameraPosition  -  worldSpaceVertexPos;
        gl_Position     = ftransform();
      }
    </RawData>
  </VERTEX_SHADER>
</Shaders>

Nothing goes right, all i want to do is a simple operation, i want to pass light position and camera position in object space, this is the shader:

 
[VERTEX SHADER]

uniform vec3 cameraPosition;
uniform vec3 lightPosition0;
uniform vec4 lightDir;

varying vec2 vTexCoord;
varying vec3 vLightVec;
varying vec3 vLightDir;
varying vec3 vViewVec;

varying vec3 vTangent;
varying vec3 vBinormal;
varying vec3 vNormal;

void main(void)
{
vec3 vr_tangent = vec3(gl_MultiTexCoord3[0],gl_MultiTexCoord3[1],gl_MultiTexCoord3[2]);
   vec3 vr_bitangent = vec3(gl_MultiTexCoord4[0],gl_MultiTexCoord4[1],gl_MultiTexCoord4[2]);
   gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;

   // construct a tangent space matrix from tan/binorm/norm   
   mat3 tanSpace = mat3( vr_tangent, gl_Normal,vr_bitangent);
   
   vec3 tangent  = vec3( vr_tangent.x,  vr_tangent.y,  vr_tangent.z);
   vec3 normal   = vec3(  gl_Normal.x,   gl_Normal.y,   gl_Normal.z);
   vec3 binormal = vec3(vr_bitangent.x, vr_bitangent.y, vr_bitangent.z);
   
    // find lightvec and xform it to tanspace.
   vec3 tempVec = lightPosition0.xyz - gl_Vertex.xyz;
   vLightVec.x = dot(tangent,  tempVec);
   vLightVec.y = dot(binormal, tempVec);
   vLightVec.z = dot(normal,   tempVec);
   
   // xform lightdir to tanspace.
   tempVec = vec3(lightDir.x, lightDir.y, lightDir.z);
   vLightDir.x = dot(tangent,  tempVec);
   vLightDir.y = dot(binormal, tempVec);
   vLightDir.z = dot(normal,   tempVec);
   
   // find viewvec and xform it to tanspace.
   tempVec  = cameraPosition.xyz - gl_Vertex.xyz;
   vViewVec.x = dot(tangent,  tempVec);
   vViewVec.y = dot(binormal, tempVec);
   vViewVec.z = dot(normal,   tempVec);
   
   // load texcoords.
   vTexCoord = vec2(gl_MultiTexCoord0);
   
   vTangent   = vr_tangent;
   vBinormal  = vr_bitangent;
   vNormal    = gl_Normal;  
}


[FRAGMENT SHADER]

uniform float spread;
uniform float sharpness;
uniform sampler2D BumpMap;
uniform sampler2D BaseMap;

varying vec2 vTexCoord;
varying vec3 vLightVec;
varying vec3 vLightDir;
varying vec3 vViewVec;

varying vec3 vTangent;
varying vec3 vBinormal;
varying vec3 vNormal;

float saturate( float inValue)
{
   return clamp(inValue, 0.0, 1.0);
}
void main(void)
{
   vec4 base = texture2D(BaseMap, vTexCoord);
   vec3 bump = texture2D(BumpMap, vTexCoord).xyz * 2.0 - 1.0;
   
   // Standard lighting
   vec3  lVec     = normalize(vLightVec);

   float diffuse  = saturate(dot(lVec, bump));
   float specular = pow(saturate(dot(reflect(normalize(-vViewVec), bump), lVec)), 16.0);

   // The angle between light vector and spotlight direction
   // defines the spot.
   float spot     = saturate(sharpness * pow(saturate(dot(lVec, -vLightDir)), spread));
   
   gl_FragColor = (diffuse * base + specular) * spot + 0.25 * base;
}



 

in my code i do:

Start Drawing a mesh applying translation and rotation…
…Activate shader…
glGetFloatv(GL_MODELVIEW_MATRIX, modelMatrix);
InvertMatrix4x4(modelMatrix);
MatrixVectorMultiply(modelMatrix,cam_pos,cam_pos);
MatrixVectorMultiply(modelMatrix,light_pos,light_pos);
and then i pass cam_pos and light_pos as uniform.
Is this right?
For testing i draw a light rotating in circle on a plane (painted with this shader). With this code all goes right until i rotate camera, when i rotate it illumination is bad calculated.
Thank you for helping me.

This topic was automatically closed 183 days after the last reply. New replies are no longer allowed.