PDA

View Full Version : Inverse model view matrix question



capedica
04-14-2005, 06:59 AM
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);
}

Java Cool Dude
04-14-2005, 09:06 AM
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>

Java Cool Dude
04-14-2005, 07:05 PM
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>

capedica
04-15-2005, 02:22 AM
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_p os);
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.