Sign in to follow this  

Multi-Shader

This topic is 3462 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've got two seperate shader files, an ambient light shader and a point light shader. I'd like to use both of them in a scene together so I've decided to combine them into one file using multiple passes (not sure if this is possible) but all it seems to do is render the second pass without taking into account the first pass. How would I go about doing this? Shader:
float4x4 matWorldViewProj;	//World*View*Projection Matrix
float4x4 matWorld;		//World Space Matrix
texture modelTexture;		//Texture of models in scene

float4 lightPosition = {0.0f, 0.0f, 0.0f, 0.0f};	//Position of the Light
float4 lightColor = {1.0f, 1.0f, 1.0f, 1.0f};		//Color of the Light
float4 matColor = {1.0f, 1.0f, 1.0f, 1.0f};		//Material Color
float falloff = 10.0f;		//Light Falloff
float brightness = 1.0f;	//Brightness of Ambient Light


float4 ambientColor = {1.0f, 1.0f, 1.0f, 1.0f};		//Color of Ambient Light
float ambientbrightness = 1.0f;	//Brightness of Ambient Light

sampler TextureSampler = sampler_state
{
	Texture = (modelTexture);
	MinFilter = LINEAR;
	MagFilter = LINEAR;
	MipFilter = LINEAR;
};

struct ambientA2V
{
	float4 Pos: POSITION;
	float2 TexCoord: TEXCOORD0;
};

struct ambientV2P
{
	float4 Pos: POSITION;
	float2 TexCoord: TEXCOORD0;
};

struct A2V
{
	float4 Pos: POSITION;
	float3 Normal : NORMAL;
	float2 TexCoord: TEXCOORD0;
};

struct V2P
{
	float4 Pos : POSITION;
	float4 WorldPos : TEXCOORD0;
	float3 WorldNormal : TEXCOORD1;
	float2 TexCoord : TEXCOORD2;
	float4 Diffuse : TEXCOORD3;
	float3 LightDir : TEXCOORD4;
};

void VS(in A2V IN, out V2P OUT)
{
	//Transform from view space to projection space
	OUT.Pos = mul(IN.Pos, matWorldViewProj);
	
	//Find World Position
	OUT.WorldPos = mul(IN.Pos, matWorld);
	
	//Calculate Light Direction
	OUT.LightDir = lightPosition - OUT.WorldPos;
	
	//Calculate world normal
	OUT.WorldNormal = normalize( mul(IN.Normal, (float3x3)matWorld));
	
	//Obtain Diffuse of Material
	OUT.Diffuse = matColor * lightColor;
	
	//Texture coordinates
	OUT.TexCoord = IN.TexCoord;
}

float4 PS(in V2P IN) : COLOR0
{
	//Pixel to light
	float LenSq = dot(IN.LightDir, IN.LightDir);
	IN.LightDir = normalize(IN.LightDir);

	//Determine Attenuation of light
	float Attn = min((falloff*falloff) / LenSq, 1.0f);
	
	//Calculate lighting amount
	float4 I = saturate(dot(normalize(IN.WorldNormal), IN.LightDir)) * IN.Diffuse * Attn;
	
	//Get Texture	
	float4 Color = tex2D(TextureSampler, IN.TexCoord);
	
	return Color * (I * brightness);
}

void ambientVS(in ambientA2V IN, out ambientV2P OUT)
{
	//Transform from view space to projection Space
	OUT.Pos = mul(IN.Pos, matWorldViewProj);
	
	//Grab texture coordinates
	OUT.TexCoord = IN.TexCoord;
}

float4 ambientPS(in ambientV2P IN) : COLOR
{
	//Get texture
	float4 Color = tex2D(TextureSampler, IN.TexCoord);
	
	//Return texture * color * ambientbrightness
	return Color * (ambientColor * ambientbrightness);
}

technique PointLight
{
	pass P0
	{
		vertexshader = compile vs_2_0 VS();
		pixelshader = compile ps_2_0 PS();
	}
	
	pass P1
	{
		vertexshader = compile vs_2_0 ambientVS();
		pixelshader = compile ps_2_0 ambientPS();
	}
}

Share this post


Link to post
Share on other sites
Don't forget that you need to also set blending states for this to work. If you leave everything at default, alpha blending will be disabled and the results of the second pass will wipe out and replace the results of the first pass. For multi-pass lighting, you'll want to use additive blending as this sums the result of the second pass with the result of the first (you always sum the contributions from different light sources). Setting the appropriate effect states would look like this:


technique PointLight
{
pass P0
{
AlphaBlendEnable = FALSE;
ZEnable = TRUE;
ZWriteEnable = TRUE;

vertexshader = compile vs_2_0 VS();
pixelshader = compile ps_2_0 PS();
}

pass P1
{
AlphaBlendEnable = TRUE;
SrcBlend = ONE;
DestBlend = ONE;
BlendOp = ADD;
ZEnable = TRUE;
ZWriteEnable = FALSE;

vertexshader = compile vs_2_0 ambientVS();
pixelshader = compile ps_2_0 ambientPS();
}
}


Also note that this will disable z-writes on the second pass...there's no need to do z-writes since you're be rendering to the exact same spot as the first pass.

[Edited by - MJP on June 23, 2008 8:39:47 PM]

Share this post


Link to post
Share on other sites
Thanks! For anyone reading though, make sure you have semi-colons after those lines. I've read a bunch on shaders but never found anything about that stuff, do you happen to know of any sites that talk about that? If not, thats cool.

Share this post


Link to post
Share on other sites
Quote:
Original post by programmermattc
Thanks! For anyone reading though, make sure you have semi-colons after those lines. I've read a bunch on shaders but never found anything about that stuff, do you happen to know of any sites that talk about that? If not, thats cool.


Err...the missing semi-colons were a test of how observant you are. [grin]

Anyway as far as setting effect states, you can check out the documentation for those right here. Not sure where I first learned about blending with multiple passes, it might have been just something I figured out. Or I may have just learned it from hanging out here!




Share this post


Link to post
Share on other sites

This topic is 3462 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.

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this