Help With Shaders and Lighting (Solved)

Hey there guys. Firstly, I’m a total beginner when it comes to this.

I made a shader to apply both ambient and point lights to a scene…but for some reason, the background color affects the output.

Here’s my Shader code:

#if OPENGL
#define SV_POSITION POSITION
#define VS_SHADERMODEL vs_3_0
#define PS_SHADERMODEL ps_3_0
#else
#define VS_SHADERMODEL vs_4_0_level_9_1
#define PS_SHADERMODEL ps_4_0_level_9_1
#endif
float3 LightDirection;
float3 LightColor = 1.5;
float3 AmbientColor = 0;
float AmbientStrength = 1;
float3 LightPosition = float3(0, 32, 20);
float Radius = 128;
float3 PointColor = float3(0.5, 0.8, 1.0);
float PointStrength = 1;
static float BrightnessMultiplier = 0.25;
Texture2D Texture : register(t0);
Texture2D NormalTexture : register(t1);
sampler TextureSampler : register(s0)
{
Texture = (Texture);
};
sampler NormalSampler : register(s1)
{
Texture = (NormalTexture);
};
struct VertexShaderOutput
{
float4 Position : SV_POSITION;
float4 Color : COLOR0;
float2 TextureCoordinates : TEXCOORD0;
};
float4 PointPS(float4 pos : SV_POSITION, float4 color : COLOR0, float2 texCoord : TEXCOORD0) : SV_TARGET0
{
float3 dir = LightPosition - float3(texCoord, 0);
float attenuation = max(1.0 - length(dir) / Radius, 0.0);
float3 normal = 2 * tex2D(NormalSampler, texCoord) - 1;
float lighting = (dot(normalize(normal), normalize(dir)) * 0.5 + 0.5) * attenuation * PointStrength;
return color * tex2D(TextureSampler, texCoord) * float4(lighting * PointColor, 1.0);
}
float4 AmbientPS(VertexShaderOutput input) : COLOR
{
float4 tex = tex2D(TextureSampler, input.TextureCoordinates);
float3 normal = 2 * tex2D(NormalSampler, input.TextureCoordinates) - 1;
float lightAmount = max(dot(normal, LightDirection), 0);
input.Color.rgb *= (AmbientColor + lightAmount * LightColor * AmbientStrength);
input.Color += PointPS(input.Position, input.Color, input.TextureCoordinates);
return input.Color * tex * BrightnessMultiplier;
}
technique SpriteDrawing
{
pass P0
{
PixelShader = compile PS_SHADERMODEL AmbientPS();
}
};

And here’s my Draw function :

protected override void Draw(GameTime gameTime)
{
GraphicsDevice.Clear(Color.Black);
Vector2 dir = Mouse.GetState().Position.ToVector2();
Vector3 lightDirection = new Vector3(dir.X, dir.Y, 5f);
lightDirection.Normalize();
Console.WriteLine(lightDirection);
spriteBatch.Begin(effect : combinedLight);
combinedLight.Parameters["NormalTexture"].SetValue(normal);
combinedLight.Parameters["LightDirection"].SetValue(lightDirection);
combinedLight.Parameters["LightColor"].SetValue(new Vector3(0.5f));
combinedLight.Parameters["AmbientColor"].SetValue(new Vector3(0.75f));
combinedLight.Parameters["AmbientStrength"].SetValue(10f);
combinedLight.Parameters["LightPosition"].SetValue(pointPosition);
combinedLight.Parameters["PointColor"].SetValue(new Vector3(1, 0.717f, 0.058f));
combinedLight.Parameters["Radius"].SetValue(0.25f);
combinedLight.Parameters["PointStrength"].SetValue(20f);
spriteBatch.Draw(wall, Vector2.Zero, Color.White);
spriteBatch.End();
base.Draw(gameTime);
}

It works fine when the background is black, but it seems to have an overlay of the color of the background when I set it to something else other than black.

Any help or suggestions are welcome, I’m probably making many stupid errors in this ^^’

Sounds like you are not adjusting your blend states before you render them. Meaning that whatever the base image colder is will be lended though to your new light render.

`//Blending states
private BlendState lightBlendState;
private BlendState linierBlendState;

lightBlendState = new BlendState
{
AlphaSourceBlend = Blend.One,
ColorSourceBlend = Blend.One,
ColorDestinationBlend = Blend.One,
AlphaDestinationBlend = Blend.One
};

        linierBlendState = new BlendState
        {
            AlphaSourceBlend = Blend.BlendFactor,
            ColorSourceBlend = Blend.BlendFactor,
            ColorDestinationBlend = Blend.BlendFactor,
            AlphaDestinationBlend = Blend.BlendFactor,
            BlendFactor = new Color(0.5f, 0.5f, 0.5f, 0.5f)
        };

Then later just call the following before you draw the Lights. Or just use the default built in states.

graphics.BlendState = linierBlendState;