compressing the light vector?

This is something I have been wanting to ask for quite a while now but i’m just now getting around to doing it. Ok anyway i have noticed something kind of wierd. First let me ask, when I compute the surface to light vector and then trasnform it to tangent space, do I have to compress it to fit in the combiners ie. multiply by 0.5 and add 0.5 before putting it in a texture unit? I made a simple demo demonstrating bump mapping using Cg and I have noticed that if I dont mul by .5 and add .5 then my light circles around the center of my quad like its supposed to. But if I do mul by .5 and add .5 then my light circles around the top right vertex of my quad. :stuck_out_tongue:

Just for the heck of it here is some code:

Here is the Cg vertex shader:

#include “shader_defs.h”

#pragma bind vtxData.position = VERTEX_POSITION
#pragma bind vtxData.normal = VERTEX_NORMAL
#pragma bind vtxData.color = VERTEX_COLOR
#pragma bind vtxData.color2 = VERTEX_COLOR2
#pragma bind vtxData.texture0 = VERTEX_TEXTURE0
#pragma bind vtxData.texture1 = VERTEX_TEXTURE1
#pragma bind vtxData.texture2 = VERTEX_TEXTURE2

struct vtxData : application2vertex
{
float4 position;
float4 color;
float4 color2;

float4 colorBright;

float3 normal;

float4 texture0;
float4 texture1;
float4 texture2;

// Tangent space stuff
float4 T;
float4 B;
float4 N;

float4 LightVector;
float4 LightBrightness;
};

#pragma bind vtxOut.HPosition = HPOS
#pragma bind vtxOut.Color0 = COL0
#pragma bind vtxOut.Color1 = COL1
#pragma bind vtxOut.Texture0 = TEX0
#pragma bind vtxOut.Texture1 = TEX1
#pragma bind vtxOut.Texture2 = TEX2

struct vtxOut : vertex2fragment
{
float4 HPosition;
float4 Color0;
float4 Color1;
float4 Texture0;
float4 Texture1;
float4 Texture2;
};

// Do this to support glTrackMatrixNV(…)
#pragma bind main.ModelViewProj = C 0
#pragma bind main.ModelViewInv = C 4

vtxOut main( vtxData IN, uniform float4x4 ModelViewProj,
uniform float4x4 ModelViewInv
)
{
vtxOut OUT;

float3 TangentLight;

OUT.HPosition = mul( ModelViewProj, IN.position );

float4 ObjSpaceLight = mul( ModelViewInv, IN.LightVector );
float4 SurfaceToLight = ObjSpaceLight - IN.position;

float4x4 TangentMatrix;

//TangentMatrix[0] = IN.T;
//TangentMatrix[1] = IN.B;
//TangentMatrix[2] = IN.N;

// Doing it this way instead of using mul is one less ASM instruction
TangentLight.x = dot( SurfaceToLight, IN.T );
TangentLight.y = dot( SurfaceToLight, IN.B );
TangentLight.z = dot( SurfaceToLight, IN.N );

//TangentLight.xyz = mul( TangentMatrix, SurfaceToLight ).xyz;

OUT.Color0.xyz = IN.color.xyz;
OUT.Color0.w = 1.0;

OUT.Color1 = IN.colorBright;

OUT.Texture0.xyz = TangentLight.xyz;// * 0.5 + 0.5;
OUT.Texture1.xy = IN.texture1.xy;
OUT.Texture2.xy = IN.texture2.xy;

return OUT;
}

Here is the combiner code:

nvparse(
"!!RC1.0
"
"{
"
" rgb
"
" {
"
" spare0 = expand( tex0 ) . expand( tex1 );
"
" }
"
"}
"
"{
"
" rgb
"
" {
"
" spare0 = spare0 * tex2;
"
" }
"
"}
"
"out.rgb = spare0;
"
"out.a = one;
"
);

-SirKnight

[This message has been edited by SirKnight (edited 07-25-2002).]

If you are using a Cube Map Normalizer, you only have to “unpack” it in the combiners (because the cube map isn’t signed), the input texture UVW vector doesn’t need to be “packed”.

The only time you should need to scale and bias the vector is if you are using color interpolators. Other wise you only have to scale and bias (expand) in the combiners (unless you use texture coords as interpolators, but you don’t have to worry about that, because AFAIK the register combiners can’t use those).

Ok thanks, I kinda figured I didnt need to ‘compress’ it since I do use a normalization cubemap and I saw it worked correctly when i didnt ‘compress’ but I just wanted verification from someone who is ‘In The Know™.’ heh heh

Well good, this answers that question that has been bugging me for quite a while.

Thanks!

-SirKnight

Sure, no problem! That’s what I’m here for