PDA

View Full Version : Help with SpotLight and NVidia Cg Language



Easy Architect 3D
11-16-2007, 11:44 AM
Hi, I'm trying to write a vertex shader that emulates the fixed function pipeline but using phong lighting.

The problem is in the code that computes the "Spot Attenuation". I use an ATI 9600 card and Don't know if is my error or a driver error.

Please Help !!!

P.S. Search "!!!!! COMPUTE SPOT ATTENUATION !!!!!!!"

Here is the code:

================================================== =========


#define MAX_LIGHT 2

float4 Ambient;
float4 Diffuse;
float4 Specular;


// -----------------------------------
// Light Model : Lambert Phong
// -----------------------------------

float PhongSize;

void DoLight(in int i,
in float3 Eye,
in float3 Position,
in float3 Normal)
{
float LdotN; // normal . light direction
float RdotE; // normal . light half vector
float SpotDot; //
float pf; // power factor
float Att = 1.0; // computed attenuation factor
float SpottAtt; // computed spot attenuation factor
float Dist; // distance from surface to light source
float3 LightVector; // direction from surface to light position
float3 VertexToEye;
float3 Reflection ;


// Get the vector from the eye to the vertex in object space
VertexToEye = normalize(Eye - Position);

// Compute vector from surface to light position
LightVector = glstate.light[i].position.xyz - Position;

if(glstate.light[i].attenuation.x < 1.0) // Attenuation is on
{
// Compute distance between surface and light position
Dist = length(LightVector);

// Compute attenuation
Att = 1.0 / (glstate.light[i].attenuation.x + glstate.light[i].attenuation.y * Dist + glstate.light[i].attenuation.z * Dist * Dist);
}

LightVector = normalize(LightVector);

// !!!!! COMPUTE SPOT ATTENUATION !!!!!!!
if( glstate.light[i].spot.direction.w > -1.0 ) // Spot Light
{
// Spot Attenuation
SpotDot = dot(-LightVector, normalize(glstate.light[i].spot.direction.xyz));

if (SpotDot > glstate.light[i].spot.direction.w)
{
SpottAtt = pow(SpotDot, glstate.light[i].attenuation.w); // spot light exponent

Att *= SpottAtt;
}
else
{
return;
}
}
// !!!!! COMPUTE SPOT ATTENUATION !!!!!!!

// Compute Ambient
Ambient += glstate.light[i].ambient * Att;

// Compute Diffuse
if(glstate.light[i].position.w < 0.5)
{
// Directiona Light
LdotN = max(0.0, dot(Normal, glstate.light[i].position.xyz));
}
else
{
// Point or Spot Light
LdotN = max(0.0, dot(Normal, LightVector));
}
Diffuse += glstate.light[i].diffuse * LdotN * Att;

// Compute Specular
if( (glstate.material.front.shininess.x < 128.0) && (LdotN > 0.0)) // Specular is ON
{
Reflection = normalize(2.0 * Normal * dot(Normal, LightVector) - LightVector);

RdotE = max(0.0, dot(Reflection, VertexToEye));

pf = pow(RdotE, PhongSize);

Specular += glstate.light[i].specular * pf * Att;
}
}

// -----------------------------------
// Common Runtime
// -----------------------------------

float4 SphereMap(in float3 normal, in float3 ecPosition3)
{
float m;
float3 r,u;

u = normalize(ecPosition3);
r = reflect(u, normal);
m = 2.0 * sqrt(r.x * r.x + r.y * r.y + (r.z + 1.0) * (r.z + 1.0));

return float4 (r.x / m + 0.5, r.y / m + 0.5, 0.0, 1.0);
}

void DoLighting(in int Count,
in float3 Eye,
in float3 PositionEye,
in float3 NormalEye,
out float4 PrimaryColor,
out float4 SecondaryColor)
{
int i;

// Reset values
Ambient = float4(0,0,0,1);
Diffuse = float4(0,0,0,1);
Specular = float4(0,0,0,1);

for(i=0;i<MAX_LIGHT;i++)
{
if(i<Count)
{
DoLight(i,Eye,PositionEye,NormalEye);
}
}

PrimaryColor = clamp(glstate.lightmodel.scenecolor + glstate.material.front.ambient * Ambient + glstate.material.front.diffuse * Diffuse, 0.0, 1.0);

SecondaryColor = clamp(glstate.material.front.specular * Specular,0.0,1.0);
}

struct app_Data
{
// OpenGL Standard
float4 Position : POSITION;
float4 Normal : NORMAL;
float4 Color0 : COLOR0;
float4 Color1 : COLOR1;
float2 TextureCoord0 : TEXCOORD0;
float2 TextureCoord1 : TEXCOORD1;
// Program defined
int LightsCount;
float PhongSize;
};

struct v2f_Data
{
float4 Position : POSITION;
float4 Color0 : COLOR0;
float4 Color1 : COLOR1;
float2 TextureCoord0 : TEXCOORD0;
float2 TextureCoord1 : TEXCOORD1;
};


v2f_Data main(app_Data IN)
{
// Vertex Program Output
v2f_Data OUT;
// Colors
float4 PrimaryColor;
float4 SecondaryColor;
// Positions and Normals
float3 PositionEye;
float4 Position;
float3 NormalEye;
float3 Eye = float3(0.0, 0.0, 1.0); // Distant Viewer Light Model

// Transform Positions and Normals
NormalEye = mul(glstate.matrix.invtrans.modelview[0],IN.Normal).xyz;
NormalEye = normalize(NormalEye);
Position = mul(glstate.matrix.modelview[0],IN.Position);
PositionEye = Position.xyz;
Eye = -normalize(PositionEye); // Local Viewer Light Model

PhongSize = IN.PhongSize;

// Compute Vertex Color
DoLighting(int(IN.LightsCount),Eye,PositionEye,Nor malEye,PrimaryColor,SecondaryColor);

// Assign Colors
OUT.Color0.rgb = PrimaryColor.rgb;
OUT.Color0.a = IN.Color0.a;
OUT.Color1.rgb = SecondaryColor.rgb;
OUT.Color1.a = IN.Color0.a;

// Texture coordinates
// UV Mapping
OUT.TextureCoord0 = mul(glstate.matrix.texture[0],float4(IN.TextureCoord0.xy,0,0)).xy;
// UV Mapping
OUT.TextureCoord1 = mul(glstate.matrix.texture[1],float4(IN.TextureCoord1.xy,0,0)).xy;

// Transform output position
OUT.Position = mul( glstate.matrix.mvp, IN.Position );

return OUT;
}