Jump to content
  • Advertisement
Sign in to follow this  

XNA Framerate issue when using Spotlights

This topic is 3775 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

I have a XNA application that’s fairly simple. Basically I draw a room with a few models inside. There are 4 spot lights in the room casting basic shadows. I have normal first person shooter controls that allow the camera to move around the room. Once I added multiple passes to the spot light technique the frame rate really dropped off. the additional passes are to replicate the spot light four times. I have alpha blending enabled for all the passes after the first one. I can't tell what the exact FPS is because when I draw the spritebatch objects disappear. I have a feeling it is due to the alpha blending... but that’s not my main concern now. What is the best way to analyze where the bottle neck is? I'm very new to all of this 3d rendering. What are some ways to improve frame rate? Is there anything that I'm doing that jumps out as being a big "No No" in game programming? EDIT: I used PIX for Windows and it appears my FPS is around 8. Here is the code I'm using to render room and lights:
        protected override void Draw(GameTime gameTime)


            Matrix rotationMatrix = Matrix.CreateRotationY(cameraYaw);

            Vector3 headOffset = Vector3.Transform(avatarHeadOffset, rotationMatrix);

            Vector3 cameraPosition = avatarPosition + headOffset;

            Vector3 transformedReference = Vector3.Transform(cameraReference, rotationMatrix);

            Vector3 cameraLookat = transformedReference + cameraPosition;

            Matrix slookAt = Matrix.CreateLookAt(cameraPosition, cameraLookat, Vector3.Up);
            graphics.GraphicsDevice.Clear(ClearOptions.Target | ClearOptions.DepthBuffer, Color.Blue, 1.0f, 0);

            DrawObejcts("ShadowedScene", slookAt, buildingModel, Matrix.Identity, llookAt, lProjection);




        void DrawObejcts(string techniqueName, Matrix lookAt, Model model, Matrix world, Matrix[] lView, Matrix lProjection)
            Matrix[] transforms = new Matrix[model.Bones.Count];

            roomLighting.CurrentTechnique = roomLighting.Techniques[techniqueName];
            roomLighting.Parameters["Projection"].SetValue(Matrix.CreatePerspectiveFieldOfView(MathHelper.ToRadians(45.0f), graphics.GraphicsDevice.Viewport.AspectRatio, 0.1f, 5000f));

            int i = 0;
            foreach (ModelMesh mesh in model.Meshes)
                roomLighting.Parameters["World"].SetValue(transforms[mesh.ParentBone.Index] * world);
                graphics.GraphicsDevice.Indices = mesh.IndexBuffer;

                if (techniqueName.Equals("SpotLight") || techniqueName.Equals("ShadowedScene"))

                    foreach (Effect b in mesh.Effects)

                foreach (ModelMeshPart meshPart in mesh.MeshParts)
                    graphics.GraphicsDevice.Vertices[0].SetSource(mesh.VertexBuffer, meshPart.StreamOffset, meshPart.VertexStride);
                    graphics.GraphicsDevice.VertexDeclaration = meshPart.VertexDeclaration;

                    foreach (EffectPass pass in roomLighting.CurrentTechnique.Passes)
                        graphics.GraphicsDevice.DrawIndexedPrimitives(PrimitiveType.TriangleList, meshPart.BaseVertex, 0, meshPart.NumVertices, meshPart.StartIndex, meshPart.PrimitiveCount);


float4x4 World;
float4x4 View;
float4x4 Projection;
float4x4 LightView[4];
float4x4 LightProjection;

float3 lightPosition[4];
float3 lightDirection;
float phi;
float theta;
float dimFactor;
bool lightsOn; 

float cphi;
float ctheta;

// for shadows
float maxDepth;
texture modelTexture;
texture shadowMap0;
texture shadowMap1;
texture shadowMap2;
texture shadowMap3;

sampler ColoredTextureSampler = 
	sampler_state { texture = <modelTexture> ; magfilter = LINEAR; minfilter = LINEAR; mipfilter=LINEAR;AddressU = wrap; AddressV = wrap;};
sampler ShadowMapSamplers[4] = {
	sampler_state { texture = <shadowMap0> ; magfilter = LINEAR; minfilter = LINEAR; mipfilter=LINEAR;AddressU = clamp; AddressV = clamp;},
	sampler_state { texture = <shadowMap1> ; magfilter = LINEAR; minfilter = LINEAR; mipfilter=LINEAR;AddressU = clamp; AddressV = clamp;},	
	sampler_state { texture = <shadowMap2> ; magfilter = LINEAR; minfilter = LINEAR; mipfilter=LINEAR;AddressU = clamp; AddressV = clamp;},
	sampler_state { texture = <shadowMap3> ; magfilter = LINEAR; minfilter = LINEAR; mipfilter=LINEAR;AddressU = clamp; AddressV = clamp;},

struct SSceneVertexToPixel
    float4 Position             : POSITION;
    float4 ShadowMapSamplingPos : TEXCOORD0;    
    float4 RealDistance			: TEXCOORD1;
	float2 TexCoords            : TEXCOORD2;
	float3 Normal				: TEXCOORD3;
	float3 Position3D           : TEXCOORD4;
	float3 interPos				: TEXCOORD5;

struct SScenePixelToFrame
    float4 Color				: COLOR0;

struct SSceneVertexInput
	float4 inPos				: POSITION;
	float2 inTexCoords			: TEXCOORD0;
	float3 inNormal				: NORMAL;
SSceneVertexToPixel ShadowedSceneVertexShader(SSceneVertexInput input, uniform int currentLight)
    SSceneVertexToPixel Output = (SSceneVertexToPixel)0;
    float4x4 wvp =  mul(mul(World, View), Projection);
    Output.Position = mul(input.inPos, wvp);

	float4x4 lwvp =  mul(mul(World, LightView[currentLight]), LightProjection);
	Output.ShadowMapSamplingPos = mul(input.inPos,lwvp );
	Output.RealDistance = Output.ShadowMapSamplingPos.z/maxDepth; 
    Output.Normal = normalize(mul(input.inNormal, (float3x3)World));
    Output.Position3D = mul(input.inPos, World);

    Output.TexCoords = input.inTexCoords;

    return Output;    

SScenePixelToFrame ShadowedScenePixelShader(SSceneVertexToPixel PSIn, uniform int currentLight)
    SScenePixelToFrame Output = (SScenePixelToFrame)0;

	float3 lightDir= normalize(lightDirection);
	float4 FinalColor = {0.0f,0.0f,0.0f,1.0f};
		Output.Color = FinalColor;

		float2 ProjectedTexCoords;

		ProjectedTexCoords[0] = PSIn.ShadowMapSamplingPos.x/PSIn.ShadowMapSamplingPos.w/2.0f +0.5f;
		ProjectedTexCoords[1] = -PSIn.ShadowMapSamplingPos.y/PSIn.ShadowMapSamplingPos.w/2.0f +0.5f;
		if ((saturate(ProjectedTexCoords.x) == ProjectedTexCoords.x) && (saturate(ProjectedTexCoords.y) == ProjectedTexCoords.y))
			float StoredDepthInShadowMap = tex2D(ShadowMapSamplers[currentLight], ProjectedTexCoords).x;    
			if ((PSIn.RealDistance.x - 1.0f/100.0f) <= StoredDepthInShadowMap)    
				float4 ColorComponent = tex2D(ColoredTextureSampler, PSIn.TexCoords);	

				float3 lightVec = lightPosition[currentLight] - PSIn.Position3D.xyz;
				lightVec= normalize(lightVec);	
				float diffuse = dot(PSIn.Normal, lightVec);
				float cAlpha = dot(-lightDirection,lightVec);	
				if (cAlpha >= cphi && cAlpha <= ctheta)
					FinalColor = CalculateFallOff(cAlpha) * ColorComponent;
				else if (cAlpha >= ctheta)
					FinalColor =  ColorComponent;
				Output.Color = FinalColor * diffuse;     

	Output.Color.a = 1.0f;  
    return Output;

technique ShadowedScene
    pass Pass0
        VertexShader = compile vs_2_0 ShadowedSceneVertexShader(0);
        PixelShader = compile ps_2_0 ShadowedScenePixelShader(0);
    pass Pass1
		SRCBLEND = one;
		DESTBLEND = one;
        VertexShader = compile vs_2_0 ShadowedSceneVertexShader(1);
        PixelShader = compile ps_2_0 ShadowedScenePixelShader(1);
	 pass Pass2
        VertexShader = compile vs_2_0 ShadowedSceneVertexShader(2);
        PixelShader = compile ps_2_0 ShadowedScenePixelShader(2);
    pass Pass3
        VertexShader = compile vs_2_0 ShadowedSceneVertexShader(3);
        PixelShader = compile ps_2_0 ShadowedScenePixelShader(3);

[Edited by - ddamicoAVI on February 22, 2008 10:57:49 AM]

Share this post

Link to post
Share on other sites
Depending on your hardware, you can probably look into using NVPerfHUD to dig into the performance characteristics. PIX isn't bad at this, but I've found it to be a better debugger than performance profiler in the past...

Having said that, you can use PIX to determine how much state-changing occurs per frame. Re-ordering the render sequence may well improve this and give you a more efficient API usage. For example, try ordering it by effect/pass rather than by model/modelpart.


Share this post

Link to post
Share on other sites
Sign in to follow this  

  • Advertisement

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

Participate in the game development conversation and more when you create an account on GameDev.net!

Sign me up!