# need per pixel attenuation shader help[Solved]

This topic is 4002 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

## Recommended Posts

I'm trying to get per-pixel attenuation to work and I've only been somewhat successful. I could use some help getting it working completely Here's my vert shader(mostly done by the author of OGRE)
void atten_vp(float4 position : POSITION,
float3 normal		: NORMAL,
float2 uv			: TEXCOORD0,
float3 tangent     : TANGENT0,
// outputs
out float4 oPosition : POSITION,
out float2 oUv			 : TEXCOORD0,
out float3 oTSLightDir	 : TEXCOORD1,
out float4 olVec : TEXCOORD2,
// parameters
uniform float4 lightPosition,
uniform float4x4 worldViewProj,
uniform float4x4 world,
uniform float4x4 worldIT
)
{
// calculate output position

oPosition = mul(worldViewProj, position);

float4 worldloc = mul(world, position);

olVec = lightPosition - worldloc;

// pass the main uvs straight through unchanged
oUv = uv;

// calculate tangent space light vector
// Get object space light direction
// Non-normalised since we'll do that in the fragment program anyway
float3 lightDir = lightPosition.xyz -  (position * lightPosition.w);

// Calculate the binormal (NB we assume both normal and tangent are
// NB looks like nvidia cross params are BACKWARDS to what you'd expect
// this equates to NxT, not TxN
float3 binormal = cross(tangent, normal);

// Form a rotation matrix out of the vectors
float3x3 rotation = float3x3(tangent, binormal, normal);

// Transform the light vector according to this matrix
oTSLightDir = mul(rotation, lightDir);

}


Notice how the out light vec is light position - the vertex world position... This code doesn't work right. When I make olVec = lightPosition - oPosition the per pixel attenuation only works when the camera is moved within the light radius of a surface. Here's my pixel shader:
void atten_fp(
float2 uv			: TEXCOORD0,
float3 TSlightDir : TEXCOORD1,
float4 lpos : TEXCOORD2,

out float4 colour	: COLOR,

uniform float4 lightDiffuse,
uniform float4 lightAttenuation,
uniform sampler2D   normalMap : register(s0),
uniform samplerCUBE normalCubeMap : register(s1) )
{

float dist = length(lpos);
float att = saturate( (1.0f - saturate(  ( dist * dist ) / ( lightAttenuation.x * lightAttenuation.x ) ) ) );

float att2 = att * att;

// retrieve normalised light vector, expand from range-compressed
float3 lightVec = expand(texCUBE(normalCubeMap, TSlightDir).xyz);

// get bump map vector, again expand from range-compressed
float3 bumpVec = expand(tex2D(normalMap, uv).xyz);

// Calculate dot product
colour = att2 * (lightDiffuse * dot(bumpVec, lightVec));
}


I'm not really good at graphics programming but I think my lights should cutoff when I make olVec = lightPosition - worldloc but it looks like I'm wrong. This shader is being used in the ogre engine... Anyone know what I'm doing wrong? [Edited by - etsuja on February 9, 2008 11:37:14 PM]

##### Share on other sites
For some reaons I'm not getting the same results as I was last night when I set olVec = lightPosition - oPosition, but it wasn't working right anyway so I guess it doesn't matter that much.

##### Share on other sites
I found a solution, I was sending a mistransformed world position to my pixel shader.

Here's my final point light attenuation shaders

VS:
void atten_vp(float4 position : POSITION,			 float4 normal		: NORMAL,			 float2 uv			: TEXCOORD0,			 float3 tangent     : TANGENT0,			 // outputs			 out float4 oPosition : POSITION,			 out float2 oUv			 : TEXCOORD0,			 out float3 oTSLightDir	 : TEXCOORD1,			 out float4 oworldPos : TEXCOORD2,			 // parameters			 uniform float4 lightPosition,			 uniform float4x4 worldViewProj,			 uniform float4x4 world,			 uniform float4x4 worldIT			 ){	// calculate output position	oPosition = mul(worldViewProj, position);	oworldPos = position;	oworldPos.w = 1.0f;	// pass the main uvs straight through unchanged	oUv = uv;	// calculate tangent space light vector	// Get object space light direction	// Non-normalised since we'll do that in the fragment program anyway	float3 lightDir = lightPosition.xyz -  (position * lightPosition.w);	// Calculate the binormal (NB we assume both normal and tangent are	// already normalised)	// NB looks like nvidia cross params are BACKWARDS to what you'd expect	// this equates to NxT, not TxN	float3 binormal = cross(tangent, normal);		// Form a rotation matrix out of the vectors	float3x3 rotation = float3x3(tangent, binormal, normal);		// Transform the light vector according to this matrix	oTSLightDir = mul(rotation, lightDir);		}

PS:
void atten_fp( 		 	  float2 uv			: TEXCOORD0,			  float3 TSlightDir : TEXCOORD1,			  float3 wpos : TEXCOORD2,			  out float4 colour	: COLOR0,			  uniform float4 lightDiffuse,			  uniform float4 lightAttenuation,			  uniform float4 lightPos,			  uniform sampler2D   normalMap : register(s0),			  uniform samplerCUBE normalCubeMap : register(s1) ){	float dist = distance(lightPos,  wpos );	float att = saturate( 1.0f - saturate(  ( dist * dist ) / ( lightAttenuation.x * lightAttenuation.x ) ) );	float att2 = att * att;		// retrieve normalised light vector, expand from range-compressed	float3 lightVec = expand(texCUBE(normalCubeMap, TSlightDir).xyz);	// get bump map vector, again expand from range-compressed	float3 bumpVec = expand(tex2D(normalMap, uv).xyz);	// Calculate dot product	colour = lightDiffuse * att2 * dot(lightVec, bumpVec);	}

• ### What is your GameDev Story?

In 2019 we are celebrating 20 years of GameDev.net! Share your GameDev Story with us.

• 13
• 12
• 15
• 11
• 12
• ### Forum Statistics

• Total Topics
634152
• Total Posts
3015843
×