• Advertisement
Sign in to follow this  

need per pixel attenuation shader help[Solved]

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

If you intended to correct an error in the post then please contact us.

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
	// 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);
	
	
}


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 this post


Link to post
Share on other sites
Advertisement
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 this post


Link to post
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);


}


Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement