My point lights seem to have problems when the camera is far away… is it the depth map? Anyway i'll show you the code
Here is my GBUffer fx :
float4x4 World;
float4x4 View;
float4x4 Projection;
float specularIntensity = 0.8f;
float specularPower = 0.5f;
texture Texture;
sampler diffuseSampler = sampler_state
{
Texture = (Texture);
MAGFILTER = LINEAR;
MINFILTER = LINEAR;
MIPFILTER = LINEAR;
AddressU = Wrap;
AddressV = Wrap;
};
struct VertexShaderInput
{
float4 Position : POSITION0;
float3 Normal : NORMAL0;
float2 TexCoord : TEXCOORD0;
};
struct VertexShaderOutput
{
float4 Position : POSITION0;
float2 TexCoord : TEXCOORD0;
float3 Normal : TEXCOORD1;
float2 Depth : TEXCOORD2;
};
VertexShaderOutput VertexShaderFunction(VertexShaderInput input)
{
VertexShaderOutput output;
float4 worldPosition = mul(input.Position, World);
float4 viewPosition = mul(worldPosition, View);
output.Position = mul(viewPosition, Projection);
output.TexCoord = input.TexCoord; //pass the texture coordinates further
float4 worldNormal = float4(mul(input.Normal, (float3x3)World), 1);
output.Normal = worldNormal;
output.Depth.xy = output.Position.zw;
return output;
}
struct PixelShaderOutput
{
half4 Color : COLOR0;
half4 Normal : COLOR1;
half4 Depth : COlOR2;
};
PixelShaderOutput PixelShaderFunction(VertexShaderOutput input)
{
PixelShaderOutput output;
output.Color = tex2D(diffuseSampler, input.TexCoord); //output Color
output.Color.a = specularIntensity; //output SpecularIntensity //output SpecularPower
output.Normal.rgb = 0.5f * (normalize(input.Normal) + 1.0f);// normalize(mul(input.Normal, (float3x3)World));
output.Normal.a = specularPower;
float exp = (input.Depth.x / input.Depth.y);
/*float exp2 =
log(128 * input.Depth.x + 1) /
(log(128 * 1000 + 1) * input.Depth.y);
output.Depth = exp2 * 10;*/
output.Depth = exp;
return output;
}
technique Technique1
{
pass Pass1
{
VertexShader = compile vs_2_0 VertexShaderFunction();
PixelShader = compile ps_2_0 PixelShaderFunction();
}
}
Here is my PointLight fx
float4x4 World;
float4x4 View;
float4x4 Projection;
//color of the light
float3 Color;
//position of the camera, for specular light
float3 cameraPosition;
//this is used to compute the world-position
float4x4 InvertViewProjection;
//this is the position of the light
float3 lightPosition;
//how far does this light reach
float lightRadius;
//control the brightness of the light
float lightIntensity = 1.0f;
// diffuse color, and specularIntensity in the alpha channel
texture colorMap;
// normals, and specularPower in the alpha channel
texture normalMap;
//depth
texture depthMap;
sampler colorSampler = sampler_state
{
Texture = (colorMap);
AddressU = CLAMP;
AddressV = CLAMP;
MagFilter = LINEAR;
MinFilter = LINEAR;
Mipfilter = LINEAR;
};
sampler depthSampler = sampler_state
{
Texture = (depthMap);
AddressU = CLAMP;
AddressV = CLAMP;
MagFilter = POINT;
MinFilter = POINT;
Mipfilter = POINT;
};
sampler normalSampler = sampler_state
{
Texture = (normalMap);
AddressU = CLAMP;
AddressV = CLAMP;
MagFilter = POINT;
MinFilter = POINT;
Mipfilter = POINT;
};
struct VertexShaderInput
{
float3 Position : POSITION0;
};
struct VertexShaderOutput
{
float4 Position : POSITION0;
float4 ScreenPosition : TEXCOORD0;
};
VertexShaderOutput VertexShaderFunction(VertexShaderInput input)
{
VertexShaderOutput output;
//processing geometry coordinates
float4 worldPosition = mul(float4(input.Position,1), World);
float4 viewPosition = mul(worldPosition, View);
output.Position = mul(viewPosition, Projection);
output.ScreenPosition = output.Position;
return output;
}
float2 halfPixel;
float4 PixelShaderFunction(VertexShaderOutput input) : COLOR0
{
//obtain screen position
input.ScreenPosition.xy /= input.ScreenPosition.w;
//obtain textureCoordinates corresponding to the current pixel
//the screen coordinates are in [-1,1]*[1,-1]
//the texture coordinates need to be in [0,1]*[0,1]
float2 texCoord = 0.5f *(float2(input.ScreenPosition.x,-input.ScreenPosition.y) + 1);
//allign texels to pixels
texCoord -=halfPixel;
//get normal data from the normalMap
float4 normalData = tex2D(normalSampler,texCoord);
//tranform normal back into [-1,1] range
float3 normal = 2.0f * normalData.xyz - 1.0f;
//get specular power
float specularPower = normalData.a * 255;
//get specular intensity from the colorMap
float specularIntensity = tex2D(colorSampler, texCoord).a;
//read depth
float depthVal = tex2D(depthSampler,texCoord).r;
//compute screen-space position
float4 position;
position.xy = input.ScreenPosition.xy;
position.z = depthVal;
position.w = 1.0f;
//transform to world space
position = mul(position, InvertViewProjection);
position /= position.w;
//surface-to-light vector
float3 lightVector = (lightPosition - position);
//compute attenuation based on distance - linear attenuation
float attenuation = saturate(1.0f - max(0, length(lightVector)) / (lightRadius));
//normalize light vector
lightVector = normalize(lightVector);
//compute diffuse light
float NdL = max(0, dot(normal, lightVector));
float3 diffuseLight = NdL * Color.rgb;
//reflection vector
float3 reflectionVector = normalize(reflect(-lightVector, normal));
//camera-to-surface vector
float3 directionToCamera = normalize(cameraPosition - position);
//compute specular light
float specularLight = specularIntensity *
pow(saturate(dot(reflectionVector, -directionToCamera)), specularPower);
//take into account attenuation and lightIntensity.
return attenuation * lightIntensity * float4(diffuseLight.rgb, specularLight);
}
technique Technique1
{
pass Pass1
{
VertexShader = compile vs_2_0 VertexShaderFunction();
PixelShader = compile ps_2_0 PixelShaderFunction();
}
}
Here's how i'm setting it up:
colorRT = new RenderTarget2D(
Device,
Graphics.PreferredBackBufferWidth,
Graphics.PreferredBackBufferHeight,
false,
SurfaceFormat.Color,
DepthFormat.Depth24Stencil8);
normalRT = new RenderTarget2D(
Device,
Graphics.PreferredBackBufferWidth,
Graphics.PreferredBackBufferHeight,
false,
SurfaceFormat.Color,
DepthFormat.Depth24Stencil8);
depthRT = new RenderTarget2D(
Device,
Graphics.PreferredBackBufferWidth,
Graphics.PreferredBackBufferHeight,
false,
SurfaceFormat.Single,
DepthFormat.Depth24Stencil8);
lightRT = new RenderTarget2D(
Device,
Graphics.PreferredBackBufferWidth,
Graphics.PreferredBackBufferHeight,
false,
SurfaceFormat.Color,
DepthFormat.Depth24Stencil8);
halfPixel = new Microsoft.Xna.Framework.
Vector2(0.5f / (float)Graphics.PreferredBackBufferWidth,
0.5f / (float)Graphics.PreferredBackBufferHeight);
private void DrawPointLight(ICamera camera, PointLight pointLight, Matrix projection)
{
//set the G-Buffer parameters
pointLightEffect.Parameters["colorMap"].
SetValue(colorRT);
pointLightEffect.Parameters["normalMap"].
SetValue(normalRT);
pointLightEffect.Parameters["depthMap"].
SetValue(depthRT);
//compute the light world matrix
//scale according to light radius, and translate it to light position
Matrix sphereWorldMatrix = Matrix.CreateScale(pointLight.Radius) *
Matrix.CreateTranslation(pointLight.GameObject.Transform.Position);
pointLightEffect.Parameters["World"].
SetValue(sphereWorldMatrix);
pointLightEffect.Parameters["View"].
SetValue(GameWindow.Singleton.Effect.View);
pointLightEffect.Parameters["Projection"].
SetValue(projection);
//light position
pointLightEffect.Parameters["lightPosition"].
SetValue(pointLight.GameObject.Transform.Position);
//set the color, radius and Intensity
pointLightEffect.Parameters["Color"].
SetValue(
new Vector3(
pointLight.Color.R,
pointLight.Color.G,
pointLight.Color.B));
pointLightEffect.Parameters["lightRadius"].
SetValue(pointLight.Radius / 2);
pointLightEffect.Parameters["lightIntensity"].
SetValue(pointLight.Intensity);
//parameters for specular computations
pointLightEffect.Parameters["cameraPosition"].
SetValue(camera.Transform.Position);
pointLightEffect.Parameters["InvertViewProjection"].
SetValue(
Matrix.Invert(
GameWindow.Singleton.Effect.View *
GameWindow.Singleton.Effect.Projection));
//size of a halfpixel, for texture coordinates alignment
pointLightEffect.Parameters["halfPixel"].
SetValue(halfPixel);
//calculate the distance between the camera and light center
float cameraToCenter =
Vector3.Distance(
camera.Transform.Position,
pointLight.GameObject.Transform.Position);
//if we are inside the light volume, draw the sphere's inside face
if (cameraToCenter < pointLight.Radius)
Device.RasterizerState =
RasterizerState.CullClockwise;
else
Device.RasterizerState =
RasterizerState.CullCounterClockwise;
pointLightEffect.Techniques[0].Passes[0].Apply();
foreach (ModelMesh mesh in sphereModel.Meshes)
{
foreach (ModelMeshPart meshPart in mesh.MeshParts)
{
Device.SetVertexBuffer(meshPart.VertexBuffer);
Device.Indices = meshPart.IndexBuffer;
Device.DrawIndexedPrimitives(
PrimitiveType.TriangleList,
meshPart.VertexOffset,
meshPart.StartIndex,
meshPart.PrimitiveCount);
}
}
Device.RasterizerState =
RasterizerState.CullCounterClockwise;
}
This is how it looks when the camera is near :
This is how it looks when the camera is far away :
in the seconds image The light gets "spotty" as the camera gos furhter away from it.
How can I solve this? Is there an error in my code?

