I've implemented deferred lighting and I tried to put about 20-26 lights on the viewable space of my map, and it brings down the FPS from 61 to 28-31. It also makes my VGA temperature to go from 68°C to 72-73°C.
I feel this a bit weird, because it's just 2D, and I don't think my implementation should be so expensive as to halve my FPS. Is there a problem with my code and how I've implemented it? Or is there any other method for good lighting which costs much less then this?
My code is:
Texture_Lights = RenderTargetBase.GetTexture(); for (int i = 0; i < LightRef.Count; i++) { //Draw lights for (int techniqueindex = 0; techniqueindex < LightRef[i].Parent.effect.Techniques.Count; techniqueindex++) { LightRef[i].Parent.effect.CurrentTechnique = LightRef[i].Parent.effect.Techniques[techniqueindex]; LightRef[i].Parent.effect.Parameters["time"].SetValue(((float)timer.Elapsed.TotalSeconds) * 0.0000158f); LightRef[i].Parent.effect.Parameters["GameTime"].SetValue(timer.Elapsed.Seconds); LightRef[i].Parent.effect.Parameters["lightPosition"].SetValue( new Vector3( (LightRef[i].Position.X-CameraX)/(1.0f/ZoomFloat), (LightRef[i].Position.Y-CameraY)/(1.0f/ZoomFloat), 0 )); LightRef[i].Parent.effect.Parameters["screenWidth"].SetValue(this.Width); LightRef[i].Parent.effect.Parameters["screenHeight"].SetValue(this.Height); for (int cx = 0; cx < LightRef[i].Parent.SelfTextures.Count; cx++) { LightRef[i].Parent.effect.Parameters[LightRef[i].Parent.SelfTextures[cx]].SetValue(RenderTargetBase.GetTexture()); } foreach (EffectPass pass in LightRef[i].Parent.effect.CurrentTechnique.Passes) { GraphicsDevice.SetRenderTarget(0, RenderTargetLights); GraphicsDevice.Clear(ClearColor); spriteBatch.Begin(SpriteBlendMode.AlphaBlend, SpriteSortMode.Immediate, SaveStateMode.None); LightRef[i].Parent.effect.Begin(); LightRef[i].Parent.effect.GraphicsDevice.RenderState.AlphaBlendEnable = true; pass.Begin(); spriteBatch.Draw( Texture_Lights, new Vector2(0,0), new Rectangle(0, 0, Texture_Lights.Width, Texture_Lights.Height), Color.White, 0, new Vector2(0, 0), 1.0f, SpriteEffects.None, 0); spriteBatch.End(); pass.End(); LightRef[i].Parent.effect.End(); GraphicsDevice.SetRenderTarget(0, null); GraphicsDevice.Clear(ClearColor); Texture_Lights = RenderTargetLights.GetTexture(); } } } GraphicsDevice.SetRenderTarget(0, null); GraphicsDevice.Clear(ClearColor); //Draw the Lightings #2 if (Texture_Lights != null) { spriteBatch.Begin(SpriteBlendMode.AlphaBlend, SpriteSortMode.Immediate, SaveStateMode.None); spriteBatch.Draw( Texture_Lights, new Vector2(0, 0), new Rectangle(0, 0, Texture_Lights.Width, Texture_Lights.Height), Color.White, 0, new Vector2(0, 0), this.ZoomFloat, SpriteEffects.None, 0); spriteBatch.End(); } And my shader:
float GameTime; float time; texture2D colortexture; texture2D normaltexture; float ambient = 1.00; float4 ambientColor = (1, 1, 1, 1); float3 lightPosition = (230,230,0); float4 lightColor = (120,120,120,120); float lightPower = 0.27; float screenWidth = 1000; float screenHeight = 600; sampler ColorMap = sampler_state { Texture = <colortexture>; }; sampler NormalMap = sampler_state { Texture = <normaltexture>; }; float4 DeferredNormalPS(float2 texCoords : TEXCOORD0) : COLOR { float4 base = tex2D(ColorMap, texCoords); float3 normal = tex2D(NormalMap, texCoords); float3 pixelPosition = float3(screenWidth * texCoords.x, screenHeight * texCoords.y,0); float3 direction = lightPosition - pixelPosition; float distance = 1 / length(lightPosition - pixelPosition) * lightPower; float amount = max(dot(base + normal, normalize(distance)), 0); lightColor *= lightPower; float4 finalColor = (base * ambientColor * ambient) + (base * distance * amount * lightColor * ambient); finalColor.a = base.a; return finalColor; } technique Deferred { pass Pass1 { PixelShader = compile ps_3_0 DeferredNormalPS(); } }