Reflective bump mapping

Hi, i’ve done a reflective bump mapping demo but i think there’s something wrong in the code because if i move around the reflective object it reflects always rhe same part of enviroment. Please help me.

Here’s the code:

VERTEX SHADER

struct vpin
{
float4 Position;
float3 Tangent;
float3 Binormal;
float3 Normal;
float2 TexCoord;
};

struct vpout
{
float4 Position : POSITION;
float2 TexCoord0 : TEXCOORD0;
float4 TexCoord1 : TEXCOORD1;
float4 TexCoord2 : TEXCOORD2;
float4 TexCoord3 : TEXCOORD3;
};

vpout main ( vpin IN,
uniform float4x4 ModelViewProj,
uniform float4x4 ModelView,
uniform float4x4 ModelViewIT,
uniform float4 EyePos,
uniform float BumpScale )
{
vpout OUT;

OUT.Position = mul( ModelViewProj, IN.Position );

float4 WSPosition = mul( ModelView, IN.Position );

float4 EyeVector = -WSPosition;

float3x3 TangentMatrix;
TangentMatrix[0] = IN.Tangent;
TangentMatrix[1] = IN.Binormal;
TangentMatrix[2] = IN.Normal;

OUT.TexCoord0 = IN.TexCoord;

OUT.TexCoord1.xyz = mul( TangentMatrix, ModelViewIT[0].xyz );
OUT.TexCoord2.xyz = mul( TangentMatrix, ModelViewIT[1].xyz );
OUT.TexCoord3.xyz = mul( TangentMatrix, ModelViewIT[2].xyz );

OUT.TexCoord1.w = EyeVector.x;
OUT.TexCoord2.w = EyeVector.y;
OUT.TexCoord3.w = EyeVector.z;

return OUT;
}

PIXEL SHADER

struct fpin
{
float2 TexCoord0 : TEXCOORD0;
float4 TexCoord1 : TEXCOORD1;
float4 TexCoord2 : TEXCOORD2;
float4 TexCoord3 : TEXCOORD3;
};

struct fpout
{
float3 Color : COLOR;
};

fpout main ( fpin IN,
uniform sampler2D NormalMap,
uniform samplerCUBE CubeMap,
uniform float4 Color )
{
fpout OUT;

float4 NormalTex = tex2D( NormalMap, IN.TexCoord0 ) * 2.0 - 1.0;

float3 EyeVector = float3( IN.TexCoord1.w, IN.TexCoord2.w, IN.TexCoord3.w );

float3 Normal = float3( dot( IN.TexCoord1.xyz, NormalTex.xyz ),
dot( IN.TexCoord2.xyz, NormalTex.xyz ),
dot( IN.TexCoord3.xyz, NormalTex.xyz ) );

float3 CubeTex = texCUBE( CubeMap, reflect( -EyeVector, Normal ) );

OUT.Color = CubeTex;

return OUT;
}

Without even looking at your shader code…

You have to apply your camera rotation to your texture matrix (for the TU that is calculating your reflection coords). Something like…

glMatrixMode(GL_TEXTURE);
glPushMatrix();
glLoadIdentity();
glRotatef(utilGlobal.activecamera->rotation.y, 0.0f, 1.0f, 0.0f);
glRotatef(utilGlobal.activecamera->rotation.x, 1.0f, 0.0f, 0.0f);
glMatrixMode(GL_MODELVIEW);

You will have to change the rotations to suit your situation. In mine I only rotate the camera on two axis so x/y rotations work for me.

It doesn’t work.

Here’s the code:

cgGLEnableTextureParameter( ReflectMap );

glMatrixMode( GL_TEXTURE );
glPushMatrix();
glLoadIdentity();
glRotatef( camera.AngleYaw, 0.0, 1.0, 0.0 );
glRotatef( camera.AnglePitch, 1.0, 0.0, 0.0 );
glPopMatrix();
glMatrixMode( GL_MODELVIEW );

Originally posted by ^DaNiEl^:
It doesn’t work.

And I wouldn’t expect that to work since you are using a vertex shader to calculate the texture coords and there exists no reference to the texture matrix in your shader. What you could try though is find out how to get access to the texture matrix inside the shader and multiply it with what you are right now assigning to OUT.TexCoordx.xyz.

Now I may be wrong, but would passing your eye vector into the w components of the texture coords be causing a problem?

-SirKnight

Another way to approach this problem is from the model’s perspective. Since you are bouncing rays of the model into a cubemap, presumably oriented with the world axes, the trick is to orient your model’s normals, light to vertex vector, and eye to vertex vector in the same space. You can begin this for the normals by multiplying by the inverse transpose of the matrix used to position the model in world space to begin with:

main( Vertex v, … ) {

pos = mul( modelMat, v.pos );
N = mul( modelMatIT, v.normal );

lightVec = lightPosInWorldSpace - pos;
// or if directional light
lightVec = lightPosInWorldSpace; // where w=0.

eyeVec = eyePosInWorldSpace - pos;

}

Keep in mind this is not necessarily the ModelView matrix, but just the matrix used to transform the model. In OpenGL, you can use GL_MATRIXi_ARB for this on a per-object basis, very handy indeed.

Now, you want to transform your other basis vectors, that is, the tangent and binormal, with the same matrix:
T = mul( modelMatIT, v.tangent );
B = mul( modelMatIT, v.binormal );

// A fragment structure with plenty of texCoords
Fragment f;

// At this point, you could move the light vec into tangent space, and use the half angle vector method. But personally, I think the H vector method leaves something to be desired, so we’ll just store the world lightVec, as this is the cube space we want anyway.
(the tex coord numbers are arbitrary)
f.texCoord3 = lightVec;

// store rotation matrix in tex coords,
// eye to vertex in w if short on tex coords,
// which I always am
f.texCoord4 = float4( T.x, B.x, N.x, eyeVec.x );
f.texCoord5 = float4( T.y, B.y, N.y, eyeVec.y );
f.texCoord6 = float4( T.z, B.z, N.z, eyeVec.z );

In the fragment program you will need to grab your bump:
bump = tex2D(bumpMap,f.texCoord1)*2-1;

then rotate the bump back into world(cube) space:
N = float3( dot(bump,f.texCoord4.xyz),
dot(bump,f.texCoord5.xyz),
dot(bump,f.texCoord6.xyz));

Now you have a bump normal in cube space to reflect about, or whatever.
L = f.texCoord3; // lightVec
diffuseDot = dot( L, N );
reflectedL = 2*(dot(L,N)/dot(N,N))*N - L;
and so on…

Now, the meaning of lightVec depends on whether you’re using a point light, in which case you’ll have to deal with attenuation, and so on. For a directional “sun” light you’re good to go.

This might help you
http://www.opengl.org/discussion_boards/cgi_directory/ultimatebb.cgi?ubb=get_topic;f=11;t=000135
Check my last post :slight_smile:

Ok but i need the world matrix ( model matrix ) to compute enviroment bump mapping, how can i calculate it ?

Depending what space you’re in the ‘world’ matrix or the matrix to transform you to world space varies. If you’re in object space the matrix to get you into world space is the model matrix, if you’re in eye space then it’s the inverse viewing matrix. You should know what these are since you multiplied them on the modelview stack at some point in your application.

If you have just the viewing matrix on the modelview stack then you’re in world space, (positions sent to the pipe are in world space). i.e. object space == world space.

I read that the model matrix is the multiplication of the rotation matrix and the translation matrix. The water plane have no rotation or translation so i set the matrix in this way:

Matrix4x4 ModelMatrix, Rx, Ry, Rz, Trans;
Rx.SetRotationX( 0.0 );
Ry.SetRotationY( 0.0 );
Rz.SetRotationZ( 0.0 );
Trans = MatrixTranslation( Trans, 0.0, 0.0, 0.0 );
ModelMatrix = Rx * Ry * Rz * Trans;

cgGLSetMatrixParameterfr( Model, ModelMatrix );

It doesn’t work because the reflection moves horizontally with the player. Why ? Please Help me.

Here’s yhe Cg code:

// VERTEX PROGRAM

struct vpin
{
float4 Position;
float3 Tangent;
float3 Binormal;
float3 Normal;
float2 TexCoord;
};

struct vpout
{
float4 Position : POSITION;
float2 TexCoord0 : TEXCOORD0;
float4 TexCoord1 : TEXCOORD1;
float4 TexCoord2 : TEXCOORD2;
float4 TexCoord3 : TEXCOORD3;
};

vpout main ( vpin IN,
uniform float4x4 ModelViewProj,
uniform float4x4 ModelViewIT,
uniform float4x4 ModelView,
uniform float4x4 Model,
uniform float4 EyePos )
{
vpout OUT;

OUT.Position = mul( ModelViewProj, IN.Position );

float4 WSPosition = mul( Model, IN.Position );

float4 EyeVector = EyePos - WSPosition;

float3x3 TangentMatrix;
TangentMatrix[0] = IN.Tangent;
TangentMatrix[1] = IN.Binormal;
TangentMatrix[2] = IN.Normal;

OUT.TexCoord0 = IN.TexCoord;

OUT.TexCoord1.xyz = mul( TangentMatrix, Model[0].xyz );
OUT.TexCoord2.xyz = mul( TangentMatrix, Model[1].xyz );
OUT.TexCoord3.xyz = mul( TangentMatrix, Model[2].xyz );

OUT.TexCoord1.w = EyeVector.x;
OUT.TexCoord2.w = EyeVector.y;
OUT.TexCoord3.w = EyeVector.z;

return OUT;

}

// FRAGMENT PROGRAM

struct fpin
{
float2 TexCoord0 : TEXCOORD0;
float4 TexCoord1 : TEXCOORD1;
float4 TexCoord2 : TEXCOORD2;
float4 TexCoord3 : TEXCOORD3;
float3 TexCoord4 : TEXCOORD4;
};

struct fpout
{
float3 Color : COLOR;
};

fpout main ( fpin IN,
uniform sampler2D NormalMap,
uniform samplerCUBE ReflectMap )
{
fpout OUT;

float4 NormalTex = tex2D( NormalMap, IN.TexCoord0 ) * 2.0 - 1.0;

NormalTex.z = sqrt( 1.0 - NormalTex.x * NormalTex.x - NormalTex.y * NormalTex.y );

float3 E = float3( IN.TexCoord1.w, IN.TexCoord2.w, IN.TexCoord3.w );

float3 N = float3( dot( IN.TexCoord1.xyz, NormalTex.xyz ),
	               dot( IN.TexCoord2.xyz, NormalTex.xyz ),
				   dot( IN.TexCoord3.xyz, NormalTex.xyz ) );

float3 ReflectTex = texCUBE( ReflectMap, 2 * dot( N, E ) * N - E );

OUT.Color = ReflectTex;

return OUT;

}

This is one of your problems right here:

float4 WSPosition = mul( Model, IN.Position );
float4 EyeVector = EyePos - WSPosition;

Think about what you’re doing here. Your taking your eye position, presumably in world space, and subtracting from it a point in homogeneous projection space. This point will follow you to the end of time, because it’s always eye relative. What you want is a point in world space, the same space as the eye. To get this world space position, you need to transform the vertex position with the matrix that transforms the water, appearently the identity matrix, from what I could glean from your code:

Matrix4x4 ModelMatrix, Rx, Ry, Rz, Trans;
Rx.SetRotationX( 0.0 );
Ry.SetRotationY( 0.0 );
Rz.SetRotationZ( 0.0 );
Trans = MatrixTranslation( Trans, 0.0, 0.0, 0.0 );
ModelMatrix = Rx * Ry * Rz * Trans;

This is just the identity matrix, right?

Just keep in mind the the mvp matrix transforms points into homogeneous projection space, not world space:

mvp = ProjectionMatrices * CameraMatrices * ModelMatrices.

You want only the ModelMatrices.

Another problem is this area here:

float3x3 TangentMatrix;
TangentMatrix[0] = IN.Tangent;
TangentMatrix[1] = IN.Binormal;
TangentMatrix[2] = IN.Normal;

OUT.TexCoord0 = IN.TexCoord;

OUT.TexCoord1.xyz = mul( TangentMatrix, Model[0].xyz );
OUT.TexCoord2.xyz = mul( TangentMatrix, Model[1].xyz );
OUT.TexCoord3.xyz = mul( TangentMatrix, Model[2].xyz );

I’m not sure what you’re trying to do here. If you have the vertex tangent basis, then just transform that with the inverse transpose of the model matrix. It looks like you’re transforming your model matrix with the tangent basis! I don’t think that will get you where you want to be. You want the opposite of this.