Hi Gamedev! I've coded little shader code for my small game to handle lights on my moving rectangles. It work and I'm quite happy with the visual result. Unfortunately it's badly implemented and the number of lights I can have on screen at same time is not enough. Changing pixelshader to use ps_3_0 instead of ps_2_0 made it possible to use 18 lights instead of 3. I know this is a bad solution and what I've to do is lower the number of instructions that is made on the pixel shader.
I would love any help I could get to optimize my code, by moving some parts to the vertex shader or change instructions on pixel shader.
//-----------------------------------------------------------------------------
// Texture sampler
//-----------------------------------------------------------------------------
uniform const texture BasicTexture;
uniform const sampler TextureSampler : register(s0) = sampler_state
{
Texture = (BasicTexture);
MipFilter = Linear;
MinFilter = Linear;
MagFilter = Linear;
};
//-----------------------------------------------------------------------------
// Material settings
//-----------------------------------------------------------------------------
uniform const float3 DiffuseColor : register(c0) = 1;
uniform const float Alpha : register(c1) = 1;
//-----------------------------------------------------------------------------
// Matrices
//-----------------------------------------------------------------------------
uniform const float4x4 World : register(vs, c2);
uniform const float4x4 View : register(vs, c6);
uniform const float4x4 Projection : register(vs, c10);
//-----------------------------------------------------------------------------
// Structure definitions
//-----------------------------------------------------------------------------
struct CommonVSOutput
{
float4 Pos_ws;
float4 Pos_ps;
float4 Diffuse;
};
//-----------------------------------------------------------------------------
// Vertex shader inputs
//-----------------------------------------------------------------------------
struct VSInputTx
{
float4 Position : POSITION;
float2 TexCoord : TEXCOORD0;
};
//-----------------------------------------------------------------------------
// Vertex shader outputs
//-----------------------------------------------------------------------------
struct VertexLightingVSOutputTx
{
float4 PositionPS : POSITION; // Position in projection space
float4 Diffuse : COLOR0;
float2 TexCoord : TEXCOORD0;
};
//-----------------------------------------------------------------------------
// Pixel shader inputs
//-----------------------------------------------------------------------------
struct VertexLightingPSInputTx
{
float4 Diffuse : COLOR0;
float2 TexCoord : TEXCOORD0;
};
CommonVSOutput ComputeCommonVSOutput(float4 position)
{
CommonVSOutput vout;
float4 pos_ws = mul(position, World);
float4 pos_vs = mul(pos_ws, View);
float4 pos_ps = mul(pos_vs, Projection);
vout.Pos_ws = pos_ws;
vout.Pos_ps = pos_ps;
vout.Diffuse = float4(DiffuseColor, Alpha);
return vout;
}
VertexLightingVSOutputTx VSBasicTx(VSInputTx vin)
{
VertexLightingVSOutputTx vout;
CommonVSOutput cout = ComputeCommonVSOutput(vin.Position);
vout.PositionPS = cout.Pos_ps;
vout.Diffuse = cout.Diffuse;
vout.TexCoord = vin.TexCoord;
return vout;
}
//-----------------------------------------------------------------------------
// Pixel shaders
//-----------------------------------------------------------------------------
#define MAX_LIGHTS 18
float2 lightPos[MAX_LIGHTS];
float lightRadius[MAX_LIGHTS];
float lightIntensity[MAX_LIGHTS];
float4 lightColor[MAX_LIGHTS];
float objectWidth;
float objectHeight;
float2 objectPosition;
float grayScaleIntensity = 1.0f;
float4 PSBasicTx(VertexLightingPSInputTx pin) : COLOR
{
float4 texCol = tex2D(TextureSampler, pin.TexCoord);
float4 color = texCol * pin.Diffuse;
//color.a = texCol.a;
//Pixel position
float2 pixelPos = pin.TexCoord.xy * float2(objectWidth, objectHeight) + objectPosition.xy;
//Grayscale
float4 grayScale = texCol;
grayScale.rgb = dot(texCol.rgb, float3(0.3, 0.59, 0.11));
for(int i = 0; i < MAX_LIGHTS; i++){
float dist = distance(lightPos, pixelPos);
float distanceFactor = saturate((lightRadius-dist) / lightRadius);
grayScale.rgb = lerp(grayScale, texCol, distanceFactor * grayScaleIntensity);
color += saturate(distanceFactor * lightIntensity) * (grayScale * lightColor);
}
//fix overlaping lights
color.r = min(color.r, texCol.r);
color.b = min(color.b, texCol.b);
color.g = min(color.g, texCol.g);
return color;
}
float4 PSBasicTxNoLight(VertexLightingPSInputTx pin) : COLOR
{
float4 texCol = tex2D(TextureSampler, pin.TexCoord);
float4 color = texCol * pin.Diffuse;
return color;
}
//-----------------------------------------------------------------------------
// Shader and technique definitions
//-----------------------------------------------------------------------------
int ShaderIndex = 0;
VertexShader VSArray[2] =
{
compile vs_3_0 VSBasicTx(),
compile vs_3_0 VSBasicTx(),
};
PixelShader PSArray[2] =
{
compile ps_3_0 PSBasicTx(),
compile ps_3_0 PSBasicTxNoLight(),
};
Technique BasicEffect
{
Pass
{
VertexShader = (VSArray[ShaderIndex]);
PixelShader = (PSArray[ShaderIndex]);
}
}