/// <summary>
		/// Construct the element, using a <see cref="DrawTargetTexture2D"/> as the texture source
		/// </summary>
		/// <param name="sizeInPixels"></param>
		/// <param name="textureSource"></param>
		public TexturedElement(DrawTargetTexture2D textureSource, Vector2 sizeInPixels) : base(sizeInPixels)
		{
			if (textureSource == null)
				throw new ArgumentNullException();

			this.texture = textureSource.GetTexture();
			this.textureSource = textureSource;
		}
		//NEW CODE
		protected override void Initialise()
		{
			//draw targets usually need a camera.
			var camera = new Camera3D();
			//look at the sphere, which will be at 0,0,0
			camera.LookAt(Vector3.Zero, new Vector3(0, 0, 4), Vector3.UnitY);


			//create the draw target texture in the same way the DrawSphere sample created the draw target screen
			//creates a 128x128 texture (the pixelation should be visible)
			drawToTexture = new DrawTargetTexture2D(camera, 128, 128, SurfaceFormat.Color, DepthFormat.Depth24Stencil8);

			//make the texture clear colour different from the screen, so it's more obvious
			drawToTexture.ClearBuffer.ClearColour = Color.WhiteSmoke;

			//create the sphere (reused from Tutorial_03)
			var sphere = new Tutorial_03.SphereDrawer(Vector3.Zero);

			//Note, the sphere is added to the texture, not the screen
			drawToTexture.Add(sphere);


			//now, create the drawToScreen object..

			//The same camera is being used, although it doesn't have to be.
			drawToScreen = new DrawTargetScreen(camera);
			drawToScreen.ClearBuffer.ClearColour = Color.CornflowerBlue;


			var sizeInPixels = new Vector2(512,512);

			//Now create a 2D helper element that will display the texture on screen

			Xen.Ex.Graphics2D.TexturedElement displayTexture = null;

			//this helper class can directly take a DrawTargetTexture2D as a constructor parameter.

			//drawToTexture's Texture2D can be accessed with drawToTexture.GetTexture(),

			//However, at this point, drawToTexture.GetTexture() will be null - as the draw
			//target has yet to be drawn to.

			//drawToTexture.Warm() can be called, which will create the resources now.
			//However calling Warm() doesn't totally solve the problem because the texture 
			//will change when content needs reloading (this happens after a device reset, etc)

			//The 2D helper element takes care of this itself.
			//Content loading/reloading and dealing with GetTexture() will be covered in the next example.
			//for now, the helper class will handle things.

			//create the 2D helper element, which will display the texture on the screen.
			displayTexture = new TexturedElement(drawToTexture, sizeInPixels);

			//add it to the screen
			drawToScreen.Add(displayTexture);
		}
示例#3
0
		protected override void Initialise()
		{
			var tutorials = new Dictionary<string, Type>();
			Program.FindTutorials(tutorials);
			
			Camera3D camera = new Camera3D();

			drawToScreen = new DrawTargetScreen(camera);
			
			backgroundParticles = new ParticleSystem(this.UpdateManager);
			backgroundParticles.GlobalValues[0] = ArrowXOffset;
			backgroundParticles.GlobalValues[2] = (float)this.WindowWidth;
			backgroundParticles.GlobalValues[3] = (float)this.WindowHeight;

			particlesTarget = new DrawTargetTexture2D(camera, this.WindowWidth, this.WindowHeight, SurfaceFormat.Color, DepthFormat.None);
			particlesBlurred = new DrawTargetTexture2D(camera, this.WindowWidth / 2, this.WindowHeight / 2, SurfaceFormat.Color, DepthFormat.None);

			DrawTargetTexture2D inter0 = null, inter1 = null;
			quaterDownsample = new TextureDownsample(particlesTarget, particlesBlurred, ref inter0, ref inter1, particlesBlurred.Width, particlesBlurred.Height);

			inter0 = new DrawTargetTexture2D(camera, particlesBlurred.Width, particlesBlurred.Height, SurfaceFormat.Color, DepthFormat.None);
			blurFilter = new BlurFilter(BlurFilterFormat.SevenSampleBlur, 1, particlesBlurred, inter0);

			backroundDrawer = new VelocityBillboardParticles2DElement(backgroundParticles, false);
			particlesTarget.Add(backroundDrawer);

			//draw the resolved particles to the screen
			drawToScreen.Add(new TexturedElement(particlesTarget, new Vector2(1, 1), true));

			//background block other elements are inserted into. invisible
			var selectionBlock = new Xen.Ex.Graphics2D.SolidColourElement(new Color(0, 0, 0, 0), new Vector2(ElementWidth, tutorials.Count * ElementSeparation));
			selectionBlock.AlphaBlendState = AlphaBlendState.Alpha;
			selectionBlock.VerticalAlignment = VerticalAlignment.Top;

			this.menuBlock = selectionBlock;

			int y_pos = 0;
			foreach (var tutorial in tutorials)
			{
				var tut_item = new TutorialSelection(tutorial.Key, y_pos, this.Content, selectionBlock, this.UpdateManager, tutorial.Value);

				y_pos -= ElementSeparation;
				buttons.Add(tut_item);
			}

			drawToScreen.Add(selectionBlock);	

			var bloom = new TexturedElement(particlesBlurred, new Vector2(1, 1), true);
			bloom.AlphaBlendState = AlphaBlendState.AdditiveSaturate;
			drawToScreen.Add(bloom);

			this.logo = new TexturedElement(new Vector2(282,100));
			this.logo.VerticalAlignment = VerticalAlignment.Top;
			this.logo.HorizontalAlignment = HorizontalAlignment.Centre;
			this.logo.Position = new Vector2(0, -50);

			this.helperText = new TextElementRect(new Vector2(800,100),"Use the DPAD to select an item, press 'A' to run the example\nWhen running an example, press 'back' to return to this menu");
			this.helperText.VerticalAlignment = VerticalAlignment.Bottom;
			this.helperText.HorizontalAlignment = HorizontalAlignment.Centre;
			this.helperText.TextHorizontalAlignment = TextHorizontalAlignment.Centre;
			this.helperText.TextVerticalAlignment = VerticalAlignment.Centre;
			this.helperText.Colour = Color.Gray;

			drawToScreen.Add(logo);
			drawToScreen.Add(helperText);
		}
		DrawTargetTexture2D PickRT(ref DrawTargetTexture2D int1, ref DrawTargetTexture2D int2, DrawTargetTexture2D source, int w, int h, Microsoft.Xna.Framework.Graphics.SurfaceFormat targetFormat)
		{
			DrawTargetTexture2D target = null;
			if (int1 != null && int1.Equals(source))
				target = int2;
			else
				if (int2 != null && int2.Equals(source))
					target = int1;

			if (target == null)
			{
				int tw = ((w + 15) / 16) * 16;
				int th = ((h + 15) / 16) * 16;

				target = new DrawTargetTexture2D(source.Camera, tw, th, targetFormat, Microsoft.Xna.Framework.Graphics.DepthFormat.None);
			}
			else
			{
				if (target.Width < w ||
					target.Height < h)
				{
					string from = "intermediate";
					if (target == int2)
						from += "2";

					throw new ArgumentException(string.Format("'{0}' draw target is too small, minimum required size for '{1}' in the current context is {2}x{3}", from, from, w, h));
				}
			}

			if (int1 == null)
			{
				int1 = target;
			}
			else
			{
				if (int2 == null  &&
					target != int1)
				{
					int2 = target;
				}
			}

			return target.Clone(false, false, false);
		}
		/// <summary>
		/// Construct the texture downsampler
		/// </summary>
		/// <param name="source">Source texture to read</param>
		/// <param name="target">Target texture to write to</param>
		/// <param name="intermediate">Intermediate texture (if null, will be created as required)</param>
		/// <param name="intermediate2">Second intermediate texture (if null, will be created as required)</param>
		/// <param name="targetWidth">target width to downsample to</param>
		/// <param name="targetHeight">target height to downsample to</param>
		/// <param name="shaderProvider">Optional provider for downsample shaders</param>
		public TextureDownsample(DrawTargetTexture2D source, DrawTargetTexture2D target, ref DrawTargetTexture2D intermediate, ref DrawTargetTexture2D intermediate2, int targetWidth, int targetHeight,
					IDownsampleShaderProvider shaderProvider)
		{
			if (source == null ||
				target == null)
				throw new ArgumentNullException();

			if (targetWidth <= 0 ||
				targetHeight <= 0)
				throw new ArgumentException("Invalid target size");

			if (DrawTarget.FormatChannels(source.SurfaceFormat) != DrawTarget.FormatChannels(target.SurfaceFormat))
			    throw new ArgumentException("source.SurfaceFormat has a different number of channels than target.SurfaceFormat");

			if (targetWidth > target.Width ||
				targetHeight > target.Height)
				throw new ArgumentException("Size is larger than target");

			if (targetWidth > source.Width ||
				targetHeight > source.Height)
				throw new ArgumentException("Size is larger than source");

			if (intermediate != null)
			{
				if (target.SurfaceFormat != intermediate.SurfaceFormat)
					throw new ArgumentException("target.SurfaceFormat != intermediate.SurfaceFormat");
				if (intermediate == intermediate2)
					throw new ArgumentException("intermediate == intermediate2");
			}
			if (intermediate2 != null)
			{
				if (target.SurfaceFormat != intermediate2.SurfaceFormat)
					throw new ArgumentException("target.SurfaceFormat != intermediate2.SurfaceFormat");
			}

			int w = source.Width;
			int h = source.Height;

			int targetMultipleWidth = targetWidth;
			int targetMultipleHeight = targetHeight;

			while (targetMultipleWidth * 2 <= w)
				targetMultipleWidth *= 2;
			while (targetMultipleHeight * 2 <= h)
				targetMultipleHeight *= 2;

			DrawTargetTexture2D current = null;
			Rectangle sRegion = new Rectangle(0,0,0,0);

			//first pass may require that the source is sized down to a multiple of the target size

			if ((double)targetWidth / (double)w <= 0.5 &&
				(double)targetHeight / (double)h <= 0.5 &&
				(targetMultipleWidth != w || targetMultipleHeight != h))
			{
				DrawTargetTexture2D go = this.PickRT(ref intermediate, ref intermediate2, source, targetMultipleWidth, targetMultipleHeight,target.SurfaceFormat);

				Vector2 size = new Vector2((float)targetMultipleWidth, (float)targetMultipleHeight);

				TexturedElement te = new TexturedElement(source, size, false);
				te.TextureCrop = new Rectangle(0,0,w,h);

				go.Add(te);
				passes.Add(go);
				current = go;
				w = targetMultipleWidth;
				h = targetMultipleHeight;
			}

			//downsample on the larger axis, either 2x, 4x or 8x downsampling, until reached the target size

			while (target.Equals(current) == false)
			{
				DrawTargetTexture2D localSource = current ?? source;

				double difW = (double)targetWidth / (double)w;
				double difH = (double)targetHeight / (double)h;

				sRegion.Width = w;
				sRegion.Height = h;
				sRegion.Y = localSource.Height - h;

				//both width/height difference are less than 50% smaller, so a linear interpolation will do fine
				if (difW > 0.5 &&
					difH > 0.5)
				{
					//write directly to the target
					DrawTargetTexture2D go = target.Clone(false, false, false);
					Vector2 te_size = new Vector2((float)targetWidth, (float)targetHeight);
					TexturedElement te = new TexturedElement(localSource, te_size, false);

					go.AddModifier(new ScissorModifier(0, go.Height - targetHeight, targetWidth, go.Height, go));
					te.TextureCrop = sRegion;

					go.Add(te);
					passes.Add(go);
					current = go;

					continue;
				}

				bool horizontal = difW < difH;
				double dif = Math.Min(difW, difH);
				int size = horizontal ? w : h;

				Vector2 dir = new Vector2(0,0);
				if (horizontal)
					dir.X = 1.0f / localSource.Width;
				else
					dir.Y = 1.0f / localSource.Height;

				if (dif > 0.25) // cutoff for using 2 samples
				{
					DrawTargetTexture2D go;
					int new_width = w;
					int new_height = h;
					if (horizontal)
						new_width /= 2;
					else
						new_height /= 2;

					if (new_width == targetWidth && new_height == targetHeight)
						go = target.Clone(false, false, false);
					else
						go = PickRT(ref intermediate, ref intermediate2, localSource, new_width, new_height, target.SurfaceFormat);

					Vector2 se_size = new Vector2((float)new_width, (float)new_height);
					ShaderElement se = new ShaderElement((shaderProvider ?? this).DownsampleShader2, se_size, false);

					go.AddModifier(new ScissorModifier(0, go.Height - new_height, new_width, go.Height, go));

					se.TextureCrop = sRegion;

					go.Add(new Drawer(dir,se,localSource));
					passes.Add(go);

					w = new_width;
					h = new_height;

					current = go;
					continue;
				}

				if (dif > 0.125) // cutoff for using 4 samples
				{
					DrawTargetTexture2D go;
					int new_width = w;
					int new_height = h;
					if (horizontal)
						new_width /= 4;
					else
						new_height /= 4;

					if (new_width == targetWidth && new_height == targetHeight)
						go = target.Clone(false, false, false);
					else
						go = PickRT(ref intermediate, ref intermediate2, localSource, new_width, new_height, target.SurfaceFormat);

					Vector2 se_size = new Vector2((float)new_width, (float)new_height);
					ShaderElement se = new ShaderElement((shaderProvider ?? this).DownsampleShader4, se_size, false);

					go.AddModifier(new ScissorModifier(0, go.Height - new_height, new_width, go.Height, go));

					se.TextureCrop = sRegion;

					go.Add(new Drawer(dir, se, localSource));
					passes.Add(go);

					w = new_width;
					h = new_height;

					current = go;
					continue;
				}

				// cutoff for using 8 samples
				{
					DrawTargetTexture2D go;
					int new_width = w;
					int new_height = h;
					if (horizontal)
						new_width /= 8;
					else
						new_height /= 8;
					
					if (new_width == targetWidth && new_height == targetHeight)
						go = target.Clone(false, false, false);
					else
						go = PickRT(ref intermediate, ref intermediate2, localSource, new_width, new_height, target.SurfaceFormat);

					Vector2 se_size = new Vector2((float)new_width, (float)new_height);
					ShaderElement se = new ShaderElement((shaderProvider ?? this).DownsampleShader8, se_size, false);

					go.AddModifier(new ScissorModifier(0, go.Height - new_height, new_width, go.Height, go));

					se.TextureCrop = sRegion;

					go.Add(new Drawer(dir, se, localSource));
					passes.Add(go);

					w = new_width;
					h = new_height;

					current = go;
					continue;
				}
			}
		}
		/// <summary>
		/// Construct the texture downsampler
		/// </summary>
		/// <param name="source">Source texture to read</param>
		/// <param name="target">Target texture to write to</param>
		/// <param name="intermediate">Intermediate texture (if null, will be created as required)</param>
		/// <param name="intermediate2">Second intermediate texture (if null, will be created as required)</param>
		/// <param name="targetWidth">target width to downsample to</param>
		/// <param name="targetHeight">target height to downsample to</param>
		public TextureDownsample(DrawTargetTexture2D source, DrawTargetTexture2D target, ref DrawTargetTexture2D intermediate, ref DrawTargetTexture2D intermediate2, int targetWidth, int targetHeight)
			: this(source, target, ref intermediate, ref intermediate2, targetWidth, targetHeight, null)
		{
		}
		/// <summary>
		/// Blur the source horizontally to the <paramref name="intermediate"/> target, then blur vertically to <paramref name="target"/>.
		/// </summary>
		/// <param name="source"></param>
		/// <param name="filterFormat">format of the blur filter</param>
		/// <param name="intermediate">draw target to use as a temporary, intermediate target for blurring</param>
		/// <param name="target"></param>
		/// <param name="bellCurveExponent">
		/// <para>A scale value to infulence the bell curve used to generate the filter kernel.</para>
		/// <para>A value of 1.0 generates a standard blur filter kernels. Larger values will produce a tighter curve, and less blur.</para>
		/// <para>Smaller values will produce a wider curve, and a larger blur - but may produce a visible edge as the curve more rapidly ends.</para>
		/// </param>
		public BlurFilter(BlurFilterFormat filterFormat, float bellCurveExponent, DrawTargetTexture2D source, DrawTargetTexture2D intermediate, DrawTargetTexture2D target)
		{
			if (target == null || source == null)
				throw new ArgumentNullException();

			if (intermediate != null && source.SurfaceFormat != intermediate.SurfaceFormat)
				throw new ArgumentException("source.SurfaceFormat != intermediate.SurfaceFormat");
			if (intermediate != null && target.SurfaceFormat != intermediate.SurfaceFormat)
				throw new ArgumentException("target.SurfaceFormat != intermediate.SurfaceFormat");

			this.source = source;

			this.filterV = new SinglePassTextureFilter(source, intermediate);
			this.filterH = new SinglePassTextureFilter(intermediate, target);

			SetFilterFormat(filterFormat, bellCurveExponent);
		}
		/// <summary>
		/// Blur the source horizontally to the <paramref name="intermediate"/> target, then blur vertically back to <paramref name="source"/>.
		/// </summary>
		/// <param name="source"></param>
		/// <param name="filterFormat">format of the blur filter</param>
		/// <param name="intermediate">draw target to use as a temporary, intermediate target for blurring</param>
		/// <param name="bellCurveExponent">
		/// <para>A scale value to infulence the bell curve used to generate the filter kernel.</para>
		/// <para>A value of 1.0 generates a standard blur filter kernels. Larger values will produce a tighter curve, and less blur.</para>
		/// <para>Smaller values will produce a wider curve, and a larger blur - but may produce a visible edge as the curve more rapidly ends.</para>
		/// </param>
		public BlurFilter(BlurFilterFormat filterFormat, float bellCurveExponent, DrawTargetTexture2D source, DrawTargetTexture2D intermediate) :
			this(filterFormat, bellCurveExponent, source, intermediate, source)
		{
		}
		internal SinglePassTextureFilter(DrawTargetTexture2D source, DrawTargetTexture2D target)
		{
			if (source == null || target == null)
				throw new ArgumentNullException();
			if (source.SurfaceFormat != target.SurfaceFormat)
				throw new ArgumentException("source.SurfaceFormat != target.SurfaceFormat");
			if (source == target)
				throw new ArgumentException("source == target is invalid");
			if (source.Width > target.Width ||
				source.Height > target.Height)
				throw new ArgumentException("source is larger than target");

			this.source = source;
			this.targetClone = target.Clone(false,false,false);

			this.targetClone.ClearBuffer.Enabled = false;

			this.element = new ShaderElement(null, source.Width, source.Height,new Vector2(1,1),true);
			this.targetClone.Add(element);

			if (target.Width != source.Width ||
				target.Height != source.Height)
			{
				this.targetClone.AddModifier(new Xen.Graphics.Modifier.ScissorModifier(0, 0, Math.Min(1, (source.Width) / target.Width), Math.Min(1, (source.Height) / target.Height)));
				this.element.TextureCrop = new Rectangle(0, 0, Math.Min(this.source.Width, this.targetClone.Width), Math.Min(this.source.Height, this.targetClone.Height));
			}
		}
		/// <summary>
		/// Creates a single pass 2 sample filter
		/// </summary>
		/// <param name="source">soure texture to filter</param>
		/// <param name="target">target to filter</param>
		/// <param name="filter">Filter to apply</param>
		public SinglePassTextureFilter(DrawTargetTexture2D source, DrawTargetTexture2D target, Filter2Sample filter)
			: this(source, target)
		{
			SetFilter(ref filter);
		}
			public Drawer(Vector2 direction, ShaderElement drawable, DrawTargetTexture2D source)
			{
				drawable.SetTextureSize(source.Width, source.Height);
				this.drawable = drawable;
				this.source = source;
				this.direction = direction;
			}
		/// <summary>
		/// Construct the element, using a <see cref="DrawTargetTexture2D"/> as the texture source
		/// </summary>
		/// <param name="textureSource"></param>
		/// <param name="size">If Normalised, the position and size are stored as [0,1] range. Otherwise the position and size are measured in pixels</param>
		/// <param name="normalised"></param>
		public TexturedElement(DrawTargetTexture2D textureSource, Vector2 size, bool normalised) : base(size,normalised)
		{
			if (textureSource == null)
				throw new ArgumentNullException();

			this.texture = textureSource.GetTexture();
			this.textureSource = textureSource;
		}
		protected override void Initialise()
		{
			//setup ambient lighting
			this.ambientLight = new MaterialLightCollection();
			ambientLight.LightingEnabled = true;
			ambientLight.AmbientLightColour = new Vector3(0.4f, 0.2f, 0.1f);
			ambientLight.CreateDirectionalLight(new Vector3(-1, -1, 0), new Vector3(3,2,1)); // add some backlighting
			ambientLight.SphericalHarmonic.AddLight(new Vector3(2, 0.5f, 0.25f), new Vector3(0, 0, 1), 0.2f);

			//the camera for the shadows point of view, represents the direction of the light.
			Camera3D shadowCamera = new Camera3D();
			shadowCamera.LookAt(new Vector3(1, 1, 3), new Vector3(-15, 20, 20), new Vector3(0, 0, 1));

			//set the clip plane distances
			shadowCamera.Projection.FarClip = 40;
			shadowCamera.Projection.NearClip = 20;
			shadowCamera.Projection.FieldOfView *= 0.25f;


			//8bit is actually enough accuracy for this sample (given the limited range of the shadow)
			var textureFormat = SurfaceFormat.Color;
			const int resolution = 256;

			//create the shadow map texture:
			drawShadowDepth = new DrawTargetTexture2D(shadowCamera, resolution, resolution, textureFormat, DepthFormat.Depth24);
			drawShadowDepth.ClearBuffer.ClearColour = Color.White;

			//for the shadow technique used, the shadow buffer is blurred.
			//this requires an intermediate render target on the PC
			DrawTargetTexture2D blurIntermediate = null;

			//technically not required on the xbox if the render target is small enough to fit in EDRAM in one tile, but xna insists
			blurIntermediate = new DrawTargetTexture2D(shadowCamera, resolution, resolution, textureFormat, DepthFormat.None);

			//create a blur filter
			shadowDepthBlurFilter = new Xen.Ex.Filters.BlurFilter(Xen.Ex.Filters.BlurFilterFormat.SevenSampleBlur,1.0f, drawShadowDepth, blurIntermediate);

			//create the scene camera
			var camera = new Camera3D();
			camera.LookAt(new Vector3(0, 0, 3), new Vector3(10, 10, 6), new Vector3(0, 0, 1));
			camera.Projection.FieldOfView *= 0.55f;

			//create the draw target.
			drawToScreen = new DrawTargetScreen(camera);
			drawToScreen.ClearBuffer.ClearColour = Color.Black;

			//the 'scene'
			//A DrawList from Tutorial 23 is used here, this stores the 'scene', 
			//which is just a set of actors and the ground
			Tutorials.Tutorial_23.DrawList scene = new Tutorials.Tutorial_23.DrawList();

			for (int x = 0; x < 2; x++)
			for (int y = 0; y < 2; y++)
			{
				//create the actor instances
				if (x != 0 || y != 0)
					scene.Add(new Actor(this.Content, new Vector3(x*6-3, y*6-3, 0), (x + y*2 + 1) * 0.2f, 4-x*2-y));
			}

			//add the ground
			var ground = new GroundDisk(this.Content, 10, ambientLight);
			scene.Add(ground);


			//setup the draw targets...


			//create the shader provider
			var shadowOutputShaderProvider = new ShadowOutputShaderProvider();

			//add a ShadowMapDrawer to the shadow map texture
			drawShadowDepth.Add(new ShadowMapDrawer(scene, shadowOutputShaderProvider));

			//setup the scene to be drawn to the screen
			//draw the scene normally (no shadow, just ambient)
			drawToScreen.Add(scene);

			Vector3 lightColour = new Vector3(2, 1.5f, 1);

			//then draw the scene with a shadow (blended on top)
			drawToScreen.Add(new ShadowedSceneDrawer(scene, shadowOutputShaderProvider, drawShadowDepth, lightColour));

			//add a nice faded background
			Tutorial_20.BackgroundGradient background = new Tutorial_20.BackgroundGradient(new Color(1, 0.5f, 0.3f), new Color(0.2f, 0.1f, 0.2f));
			background.DrawAtMaxZDepth = true;
			drawToScreen.Add(background);


			//create a textured element that will display the shadow map texture
			var shadowDepthDisplay = new TexturedElement(drawShadowDepth, new Vector2(256, 256));
			shadowDepthDisplay.VerticalAlignment = VerticalAlignment.Top;
			this.drawToScreen.Add(shadowDepthDisplay);
		}
		public ShadowedSceneDrawer(IDraw scene, ShadowOutputShaderProvider shaderProvider, DrawTargetTexture2D shadowMapTarget, Vector3 lightColour)
		{
			this.scene = scene;
			this.shaderProvider = shaderProvider;
			this.shadowMapTarget = shadowMapTarget;
			this.lightColour = lightColour;
		}
		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);
			
		}
		protected override void Initialise()
		{
			//draw target camera.
			var camera = new Camera3D();
			camera.LookAt(Vector3.Zero, new Vector3(0, 0, 4), Vector3.UnitY);


			//create the draw target texture
			//actual graphics resources are not created yet...
			drawToTexture = new DrawTargetTexture2D(camera, 128, 128, SurfaceFormat.Color, DepthFormat.Depth24Stencil8);

			//make the texture clear colour different from the screen, so it's more obvious
			drawToTexture.ClearBuffer.ClearColour = Color.WhiteSmoke;

			//add a sphere from tutorial 03 to the texture
			drawToTexture.Add(new Tutorial_03.SphereDrawer(Vector3.Zero));



			var sizeInPixels = new Vector2(512,512);

			//NEW CODE
			//create the helper element, but don't give it a texture yet..
			displayElement = new TexturedElement(sizeInPixels);



			//create the drawToScreen object..
			drawToScreen = new DrawTargetScreen(camera);
			drawToScreen.ClearBuffer.ClearColour = Color.CornflowerBlue;

			//add the helper element to the screen
			drawToScreen.Add(displayElement);
		}