Help With Multiple Lights

I am currently working on a project where i am using hlsl shaders for the first time. What i want to do is get more than a single light in the scene at once.

I have a point light shader. It works fine, and casts light as it should. What i was hoping to be able to do was essentially call the shader more than once with different values for colour, position etc and that would render a second light when applied to the same objects again. Ofcourse when i tried this it didn't work. Only the last light shader called is seen to have an effect on the screen. Is there a way of getting them to render one on top of the other so they both light the scene.

I know there are ways to create loops withing the shaders to call multiple values out of a struct, but i have no idea how to do that.

Here is the shader i am using:

// PerPixelSpecular
// Calculates Per pixel
// Pass 0
//These Values passed into the shader from the main program
//Global variable, these values are sent to the effect
//using the various Set functions of the effect object
uniform extern float4x4 g_matView : View;
uniform extern float4x4 g_matProjection : Projection;
uniform extern float4x4 g_matWorld : World;

//Ambient Colour
float4 g_AmbientLightColour;
float g_AmbientLightIntensity;
//Diffuse Light Colour
float4 g_DiffuseLightColour;
float g_DiffuseLightIntensity;
//Light Position
float4 g_LightPosition;
float4 g_SpecularLightColour;
float g_SpecularLightIntensity;
//Eye Position
float3 g_EyePosition;
float3 g_AttenuationFactor;

//Material Colour
float4 g_AmbientColour;
float4 g_DiffuseColour;
float4 g_SpecularColour;

//Struct that holds the Input to the Vetex Shader
//HLSL language shares the same synatx as C, so a Shader can have structs,
//functions, loops etc.
struct VS_INPUT
//a Float4 that represents the untransfomed position of a vertex, POSITION0 is
//a semantic this tells the Shader that the variable hold postional values of a
float4 Position : POSITION0;
//vertex normal
float3 Normal :NORMAL0;
float2 TexCoords:TEXCOORD0;

//Struct that holds the output from the Vertex Shader
struct VS_OUTPUT
//Float4 Represents the position
float4 Position : POSITION0;
float2 TexCoords:TEXCOORD0;
//light Direction
float3 LightDirection:TEXCOORD1;
float3 Norm :TEXCOORD2;
float3 View :TEXCOORD3;
float attenuation:TEXCOORD4;

//The Vertex Shader entry point
//This recieves VS_INPUT structure as an Input and it returns a VS_OUTPUT
VS_OUTPUT vs_main( VS_INPUT Input )
//Declare a VS_OUTPUT structure
float4x4 matViewProjection=mul(g_matView,g_matProjection);
float4x4 matWorldViewProjection=mul(g_matWorld,matViewProjection);

Output.Position = mul(Input.Position , matWorldViewProjection);
//sets the ouput light direction to the global light direction
float d=length(lightDir);
//sets the output normal to the value of input normal multiplied by the world
//matrix. Normalize - this normalizes the normals so that the length of the
//vector is equal to 1
//return the Output structure. if there is a pixel shader then the Pixel Shader
//is called.
float4 worldPos=mul(Input.Position,g_matWorld);
return( Output );

//PS_INPUT structure
//holds the inputs to the pixel shader
struct PS_INPUT
float2 TexCoords:TEXCOORD0;
float3 LightDirection:TEXCOORD1;
float3 Norm :TEXCOORD2;
float3 View :TEXCOORD3;
float attenuation:TEXCOORD4;

Texture diffuseMap;
Texture specularMap;

sampler diffuseSampler= sampler_state

sampler specularSampler= sampler_state

//Entry point for the Pixel Shader
//this recieves a PS_INPUT structure as input, this value comes from the
//Vertex Shader.
//The pixel shader returns float4 that represents a colour of a pixel, the COLOR0
//semantic indicates
float4 ps_main(PS_INPUT input) : COLOR0
float3 Normal = normalize(input.Norm);
float3 LightDir = normalize(input.LightDirection);
float4 diffuseColour=tex2D(diffuseSampler,input.TexCoords)*g_DiffuseColour;
float4 specularColour=tex2D(specularSampler,input.TexCoords)*g_SpecularColour;

//float4 to hold the final colour this is set to the ambinet colour contained
//in the PS_INPUT structure
float4 ambientComponent=g_AmbientLightColour*g_AmbientLightIntensity;

float nDotL=saturate(dot(Normal,LightDir));
float4 diffuseComponent=g_DiffuseLightColour*g_DiffuseLightIntensity*nDotL;

float3 HalfVec=normalize(LightDir+normalize(input.View));
float specularPower=pow(saturate(dot(Normal,HalfVec)),25);
float4 specularComponent=g_SpecularLightColour*g_SpecularLightIntensity*specularPower;

float4 finalColour=((g_AmbientColour*ambientComponent)+((diffuseColour*diffuseComponent)+(specularColour*specularComponent))/input.attenuation);
//returns the final colour
return finalColour;

// Technique Section for PerPixelSpecular
technique PointLight
pass Pass_0
VertexShader = compile vs_2_0 vs_main();
PixelShader = compile ps_2_0 ps_main();


If someone could tell me how i would go about getting shaders to blend together their effects that would be great. If the only way is shader modification and someone can be bothered to work it out, it would be much apreciated if someone could tell me how to make the shader render more than one light.

Sign In or Register to comment.

Howdy, Stranger!

It looks like you're new here. If you want to get involved, click one of these buttons!