//constructor, including shaders
		//This constructor is called from the LoadContent method, the ContentManager is passed in.
		public CharacterShaderProvider(Shaders.Character shader, Xen.Ex.Graphics.Content.ModelData model, ContentManager manager, string assetLocation)
		{
			//Generate a list of SOF textures for this model
			List<Texture2D> textures = new List<Texture2D>();

			assetLocation = assetLocation ?? "";
			if (assetLocation.Length > 0)
				assetLocation += "/";

			//loop through all the geometries in the model
			foreach (Xen.Ex.Graphics.Content.MeshData mesh in model.Meshes)
			{
				foreach (Xen.Ex.Graphics.Content.GeometryData geom in mesh.Geometry)
				{
					//take the existing texture file name and add 'SOF' on the end, to find the skin/occlusion/face+skin texture

					//Normally, XNA would add '_0' to the end of every texture asset, so each model has a unique copy of the
					//asset (incase a model sets up different processing options for the asset).

					//Xen supports the ability to set 'Manual Texture Import' property to true.
					//When this is set to true, the model will not directly process the textures, it
					//will simply assume they are processed. This requires each texture is manually added to the project.
					//When this is true, the textures are not renamed.

					//Try and load a texture with 'SOF' on the end.
					Texture2D texture = manager.Load<Texture2D>(assetLocation + geom.MaterialData.TextureFileName + "SOF");
					textures.Add(texture);
				}
			}

			//store the textures
			this.SofTextures = textures.ToArray();

			this.shader = shader;
		}
		protected override void Initialise()
		{
			//setup the view camera first
			//--------------------------------------

			viewCamera = new Xen.Camera.FirstPersonControlledCamera3D(this.UpdateManager);
			viewCamera.Projection.FieldOfView *= 0.65f;
			viewCamera.MovementSensitivity *= 0.05f;
			viewCamera.LookAt(new Vector3(-3, 4, 2), new Vector3(6, 6, 2), new Vector3(0, 1, 0));
			viewCamera.Projection.NearClip = 0.1f;

			//shadow map setup:
			//--------------------------------------

			const float shadowArea = 4;
			const int shadowMapResolution = 1024;

			//setup the shadow map rendering camera
			shadowCamera = new Camera3D();

			//setup the shadow map projection to roughly cover the character
			shadowCamera.Projection.Orthographic = true;
			shadowCamera.Projection.NearClip = shadowArea * 2;
			shadowCamera.Projection.FarClip = -shadowArea * 2;
			shadowCamera.Projection.Region = new Vector4(1, -1.8f, -1, 0.2f) * shadowArea;

			//setup the shadow map draw target

			//create the shadow map
			shadowMap = new DrawTargetTexture2D(shadowCamera, shadowMapResolution, shadowMapResolution, SurfaceFormat.HalfSingle, DepthFormat.Depth24);
			shadowMap.ClearBuffer.ClearColour = Color.White;

			//setup the shadow map drawer..
			shadowDrawer = new Tutorial_25.ShadowMapDrawer(null, new Tutorial_25.ShadowOutputShaderProvider());
			this.shadowMap.Add(shadowDrawer);



			//create the main draw targets.
			//--------------------------------------

			drawToScreen = new DrawTargetScreen(new Camera2D());
			drawToScreen.ClearBuffer.ClearColourEnabled = false;

			drawToRenderTarget = new DrawTargetTexture2D(viewCamera, this.WindowWidth, this.WindowHeight, SurfaceFormat.Color, DepthFormat.Depth24Stencil8, false, PreferredMultiSampleLevel.FourSamples, RenderTargetUsage.PlatformContents);
			drawToRenderTarget.ClearBuffer.ClearColourEnabled = false;

			//setup the bloom draw targets
			//--------------------------------------

			//scale to reduce the size of the bloom target, compared to main render target
			const int bloomDownsample = 8;	//eight times smaller

			bloomRenderTarget = new DrawTargetTexture2D(new Camera2D(), Math.Max(1, drawToRenderTarget.Width / bloomDownsample), Math.Max(1, drawToRenderTarget.Height / bloomDownsample), SurfaceFormat.Color, DepthFormat.None);
			bloomRenderTarget.ClearBuffer.ClearColourEnabled = false;

			bloomIntermediateRenderTarget = null;

			//the bloom intermediate target is not needed on the xbox, as the full bloom target fits in EDRAM
			bloomIntermediateRenderTarget = new DrawTargetTexture2D(viewCamera, bloomRenderTarget.Width, bloomRenderTarget.Height, SurfaceFormat.Color, DepthFormat.None);
			bloomIntermediateRenderTarget.ClearBuffer.ClearColourEnabled = false;

			//setup the blur filter, with a large 31 sample radius.
			bloomBlurPass = new Xen.Ex.Filters.BlurFilter(Xen.Ex.Filters.BlurFilterFormat.ThirtyOneSampleBlur_FilteredTextureFormat, 1.0f, bloomRenderTarget, bloomIntermediateRenderTarget);


			//setup the character model
			this.model = new ModelInstance();	//(the model is setup in LoadContent)
			this.modelRotation = new DrawRotated(model);
			this.modelRotation.RotationAngle = 3;

			//add the model to be drawn
			drawToRenderTarget.Add(modelRotation);

			//setup the shaders
			this.characterRenderShader = new Shaders.Character();

			//setup the output and bloom shaders
			outputShader = new Shaders.RgbmDecode();
			drawToScreen.Add(new ShaderElement(outputShader, new Vector2(1, 1), true));

			bloomPassShader = new Shaders.RgbmDecodeBloomPass();
			bloomRenderTarget.Add(new ShaderElement(bloomPassShader, new Vector2(1, 1), true));

			//add a background to be drawn
			drawToRenderTarget.Add(new BackgroundDrawer());


			//setup the debug image displays
			//--------------------------------------

			this.rgmbTextureAlphaShader = new Shaders.AlphaWrite();
			this.bloomTextureDisplay = new TexturedElement(this.bloomRenderTarget, new Vector2(0.2f, 0.2f), true);
			this.rgbmTextureDisplay = new TexturedElement(this.drawToRenderTarget, new Vector2(0.2f, 0.2f), true);
			this.rgbmTextureAlphaDisplay = new ShaderElement(this.rgmbTextureAlphaShader, new Vector2(0.2f, 0.2f), true);

			this.rgbmTextureAlphaDisplay.Position = new Vector2(0.7f, 0.2f);
			this.rgbmTextureDisplay.Position = new Vector2(0.7f, 0.4f);
			this.bloomTextureDisplay.Position = new Vector2(0.7f, 0.6f);

			this.drawToScreen.Add(this.rgbmTextureDisplay);
			this.drawToScreen.Add(this.rgbmTextureAlphaDisplay);
			this.drawToScreen.Add(this.bloomTextureDisplay);

			//setup the render config
			this.configEditor = new RenderConfigEditor(this.Content);

			this.drawToScreen.Add(configEditor);
			this.UpdateManager.Add(configEditor);


			//add a statistics overlay.
			drawStats = new Xen.Ex.Graphics2D.Statistics.DrawStatisticsDisplay(this.UpdateManager);
			drawToScreen.Add(drawStats);
			
		}