[.net] XNA Per-Pixel Lighting - *MULTIPLE* Lights

Started by
1 comment, last by ferr 16 years, 9 months ago
I've been messing with Riemer's PPL tutorial and have found great success with rendering ONE light. But what about multiple? I've been googling for hours now and all I can find are MDX/HLSL tutorials such as Riemer's which make use of methods that XNA has no equivalent for (i.e. Matrix.LookAtLH and a couple of others). I've tried modifying Riemer's PPL HLSL file by using similar concepts to the MDX tutorials with no success. Here is my most recent version of trying to get it to work properly:
struct VertexToPixel
{
    float4 Position     : POSITION;
    float2 TexCoords        : TEXCOORD0;


     float3 Normal        : TEXCOORD1;
     float3 Position3D        : TEXCOORD2;


};

struct PixelToFrame
{
    float4 Color        : COLOR0;
};

float4x4 xWorldViewProjection;


 float4x4 xWorld;
 float4 xLightPos[2];
 float xLightPower;


bool xUseBrownInsteadOfTextures;

Texture xColoredTexture;

sampler ColoredTextureSampler = sampler_state { texture = <xColoredTexture> ; magfilter = LINEAR; minfilter = LINEAR; mipfilter=LINEAR; AddressU = mirror; AddressV = mirror;};



 VertexToPixel SimplestVertexShader( float4 inPos : POSITION0, float3 inNormal: NORMAL0, float2 inTexCoords : TEXCOORD0, uniform int CurrentLight)


{
    VertexToPixel Output = (VertexToPixel)0;

    Output.Position = mul(inPos, xWorldViewProjection);


     Output.Normal = normalize(mul(inNormal, (float3x3)xWorld));
     Output.Position3D = mul(inPos, xWorld);


    Output.TexCoords = inTexCoords;

    if (xUseBrownInsteadOfTextures)
        Output.TexCoords = (0,0);

    return Output;
}



 float DotProduct(float3 LightPos, float3 Pos3D, float3 Normal)
 {
     float3 LightDir = normalize(LightPos - Pos3D);
     return dot(LightDir, Normal);
 }



PixelToFrame OurFirstPixelShader(VertexToPixel PSIn, uniform int CurrentLight)
{
    PixelToFrame Output = (PixelToFrame)0;

     float DiffuseLightingFactor = DotProduct(xLightPos[CurrentLight], PSIn.Position3D, PSIn.Normal);
     Output.Color = tex2D(ColoredTextureSampler, PSIn.TexCoords)*DiffuseLightingFactor*xLightPower;

    return Output;
}

technique Simplest
{
    pass Pass0
    {
         VertexShader = compile vs_2_0 SimplestVertexShader(0);
         PixelShader = compile ps_2_0 OurFirstPixelShader(0);
    }
    pass Pass1
    {    
         VertexShader = compile vs_2_0 SimplestVertexShader(1);
         PixelShader = compile ps_2_0 OurFirstPixelShader(1);
    }
}
All that seems to happen is the Pass1 PixelShader overwrites the Pass0 PixelShader (the second light is the only one rendered). The main difference in my code and Riemer's MDX version is in the Vertex Shader where he makes use of a xLightViewProjection array which is made up of the MDX exclusive Matrix methods. This is how he creates one of the LightViewProjections in MDX:
LightViewProjection[0] = Matrix.LookAtLH(LightPos[0], new Vector3(2, 10, -3), new Vector3(0, 0, 1)) * Matrix.PerspectiveFovLH((float)Math.PI / 2, this.Width / this.Height, 1f, 100f);
Advertisement
Why not do all of the lights in one pass?
Quote:Original post by smitty1276
Why not do all of the lights in one pass?


Wow, that worked. I tried something very similar earlier but I must have formed the Output differently somehow. Here is the solution:

PixelToFrame OurFirstPixelShader(VertexToPixel PSIn, uniform int CurrentLight){    PixelToFrame Output = (PixelToFrame)0;     float DiffuseLightingFactor = DotProduct(xLightPos[0], PSIn.Position3D, PSIn.Normal);     float DiffuseLightingFactor2 = DotProduct(xLightPos[1], PSIn.Position3D, PSIn.Normal);          Output.Color = tex2D(ColoredTextureSampler, PSIn.TexCoords) 					* (DiffuseLightingFactor + DiffuseLightingFactor2)					* xLightPower;    return Output;}

This topic is closed to new replies.

Advertisement