Пример #1
0
        protected override void Initialise()
        {
            //draw target camera.
            Camera3D 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));



            Vector2 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(this, camera);
            drawToScreen.ClearBuffer.ClearColour = Color.CornflowerBlue;

            //add the helper element to the screen
            drawToScreen.Add(displayElement);
        }
Пример #2
0
        protected override void Initialise()
        {
            //draw targets usually need a camera.
            Camera3D 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.
            drawToScreen = new DrawTargetScreen(this, camera);
            drawToScreen.ClearBuffer.ClearColour = Color.CornflowerBlue;

            //create the sphere
            SphereDrawer sphere = new SphereDrawer(Vector3.Zero);


            //before adding the sphere, add a rect over half the background to show blending is active

            //element covers half the screen
            SolidColourElement element = new SolidColourElement(Color.DarkGray, new Vector2(0.5f, 1), true);

            //element is added before the sphere (so it draws first)
            drawToScreen.Add(element);

            //add it to be drawn to the screen
            drawToScreen.Add(sphere);
        }
Пример #3
0
        protected override void Initialise()
        {
            Resource.EnableResourceTracking();


            Camera3D camera = new Camera3D();

            camera.LookAt(Vector3.Zero, new Vector3(0, 0, 5), Vector3.UnitY);

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



            //create a shader to display the geometry (this is the same as tutorial 02)
            Vector3        lightDirection = new Vector3(1.0f, 0.5f, 0.5f);
            MaterialShader material       = new MaterialShader(new MaterialLightCollection());

            material.UsePerPixelSpecular       = true;
            material.Lights.AmbientLightColour = Color.CornflowerBlue.ToVector3() * 0.5f;               //set the ambient
            material.Lights.AddDirectionalLight(true, lightDirection, Color.Gray);                      //add the first of two light sources
            material.Lights.AddDirectionalLight(true, -lightDirection, Color.DarkSlateBlue);
            material.SpecularColour = Color.LightYellow.ToVector3();                                    //give the material a nice sheen

            //create a simpler shader to display the wireframe (and also used for the bounding cube)
            Xen.Ex.Shaders.FillSolidColour simpleShader = new Xen.Ex.Shaders.FillSolidColour();
            simpleShader.FillColour = Vector4.One * 0.01f;


            Vector3 sphereSize = new Vector3(0.5f, 0.5f, 0.5f);

            //create the complex sphere, this will have ~100k triangles.
            //pass in a shader for wireframe rendering
            sphere = new GeometryDrawer(new Xen.Ex.Geometry.Sphere(sphereSize, 200), material, simpleShader);

            //create the bounding cube
            sphereBoundingBox = new GeometryDrawer(new Xen.Ex.Geometry.Cube(sphereSize), simpleShader, null);

            //create the occluding cube, and position it close to the camera
            cube          = new GeometryDrawer(new Xen.Ex.Geometry.Cube(Vector3.One), material, null);
            cube.position = new Vector3(0, 0, 2.75f);


            //add the cube first (so it can draw first, potentially occluding the sphere)
            //if the cube was added second, it would have no effect, as it would draw after the sphere
            drawToScreen.Add(cube);


            //create the predicate, passing in the sphere and bounding box
            Xen.Ex.Scene.DrawPredicate predicate = new Xen.Ex.Scene.DrawPredicate(sphere, sphereBoundingBox);

            //add the DrawPredicate (the DrawPredicate draws it's children)
            drawToScreen.Add(predicate);


            //statistic overlay
            statOverlay = new Xen.Ex.Graphics2D.Statistics.DrawStatisticsDisplay(this.UpdateManager);
            drawToScreen.Add(statOverlay);
        }
Пример #4
0
        //NEW CODE
        protected override void Initialise()
        {
            //draw targets usually need a camera.
            Camera3D 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)
            Tutorial_03.SphereDrawer sphere = new Tutorial_03.SphereDrawer(Vector3.Zero);

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


            //now, create the drawToScreen object..

            //The same camera is being used, although it doesn't have to be.
            //The 2D element helper class that will be used will automatically push it's own 2D Camera when
            //drawing, to keep itself consistent.
            drawToScreen = new DrawTargetScreen(this, camera);
            drawToScreen.ClearBuffer.ClearColour = Color.CornflowerBlue;


            Vector2 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 texture parameter.
            //This saves some effort here.

            //drawToTexture's Texture2D can be accessed with drawToTexture.GetTexture(),
            //in a similar way to XNA render targets.

            //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.
            displayTexture = new TexturedElement(drawToTexture, sizeInPixels);

            //add it to the screen
            drawToScreen.Add(displayTexture);
        }
Пример #5
0
        protected override void Initialise()
        {
            //create the draw target.
            drawToScreen = new DrawTargetScreen(this, new Camera3D());

            //create the image displayer, passing in a reference
            //to the ContentRegister for this Application instance
            ImageDisplayer imageDisplayer = new ImageDisplayer(this.Content);

            //add it to the screen
            drawToScreen.Add(imageDisplayer);
        }
Пример #6
0
        //This method gets called just before the window is shown, and the device is created
        protected override void Initialise()
        {
            //draw targets usually need a camera.
            //create a 3D camera with default parameters
            Camera3D camera = new Camera3D();

            //create the draw target.
            drawToScreen = new DrawTargetScreen(this, camera);

            //Set the screen clear colour to blue
            //(Draw targets have a built in ClearBuffer object)
            drawToScreen.ClearBuffer.ClearColour = Color.CornflowerBlue;
        }
Пример #7
0
        protected override void Initialise()
        {
            //create the draw target.
            drawToScreen = new DrawTargetScreen(this, new Camera2D());

            //create the logo
            this.xenLogo = new Xen.Logo.XenLogo(this);

            //test xenLogo.EffectFinished to determine if the effect has completed.

            //add it to the screen
            this.drawToScreen.Add(xenLogo);
        }
Пример #8
0
        protected override void Initialise()
        {
            Camera3D camera = new Camera3D();

            camera.LookAt(new Vector3(0, 0, 4), new Vector3(3, 4, 4), new Vector3(0, 0, 1));

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

            //NEW CODE
            //create the actor instance
            drawToScreen.Add(new Actor(this.Content));
        }
Пример #9
0
        protected override void Initialise()
        {
            Camera3D camera = new Camera3D();

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

            //NEW CODE
            //create the CameraOrbit object..
            //pass in the application update manager
            cameraOrbit = new CameraOrbit(camera, this.UpdateManager);

            //create the actor instance from Tutorial_10
            drawToScreen.Add(new Tutorial_10.Actor(this.Content, Vector3.Zero));
        }
Пример #10
0
        protected override void Initialise()
        {
            Camera3D camera = new Camera3D();

            camera.LookAt(Vector3.Zero, new Vector3(0, 0, 4), Vector3.UnitY);

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

            //create the sphere
            SphereDrawer sphere = new SphereDrawer(Vector3.Zero);

            //add it to be drawn to the screen
            drawToScreen.Add(sphere);
        }
Пример #11
0
        protected override void Initialise()
        {
            //draw targets usually need a camera.
            Camera3D camera = new Camera3D();

            //look at the sphere, which will be at 0,0,0. Look from 0,0,4
            camera.LookAt(Vector3.Zero, new Vector3(0, 0, 4), Vector3.UnitY);

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

            //create the sphere at 0,0,0
            SphereDrawer sphere = new SphereDrawer(Vector3.Zero);

            //add it to be drawn to the screen
            drawToScreen.Add(sphere);
        }
Пример #12
0
        protected override void Initialise()
        {
            Resource.EnableResourceTracking();

            //create the draw target.
            drawToScreen = new DrawTargetScreen(this, new Camera2D());
            drawToScreen.ClearBuffer.ClearColour = Color.CornflowerBlue;

            //create the GameStateManager
            GameStateManager manager = new GameStateManager(this);

            //add it to the screen, and to be updated
            this.drawToScreen.Add(manager);
            this.UpdateManager.Add(manager);

            stats = new Xen.Ex.Graphics2D.Statistics.DrawStatisticsDisplay(this.UpdateManager);
            this.drawToScreen.Add(stats);
        }
Пример #13
0
        protected override void Initialise()
        {
            Camera2D camera = new Camera2D();

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


            // uncomment this to force theparticle system to run on the CPU
            // Note: This property is not available on the xbox.

            //ParticleSystem.ForceUseCpuParticleSystem = true;

            // Use ParticleSystem.SystemSupportsGpuParticles to determine if the particle
            // system will be run on the GPU
            //
            // NOTE: When running on the GPU, the particle system will be processed in 16bit floating point
            // The CPU particle system is not supported on the Xbox.



            //NEW CODE
            //create the particle system
            this.particles = new ParticleSystem(this.UpdateManager);

            //Like ModelInstance, the ParticleSystem content must be assigned before it can be drawn

            //create the particle drawer,
            //In this case, use a VelocityBillboardParticles2DElement.
            //This is a special particle drawer that will 'stretch' particles in the direction they are
            //travelling - giving them a streaky look.
            //
            particleDrawer = new Xen.Ex.Graphics.Display.VelocityBillboardParticles2DElement(this.particles, true);

            //align the drawer to the bottom centre of the screen
            particleDrawer.VerticalAlignment   = VerticalAlignment.Bottom;
            particleDrawer.HorizontalAlignment = HorizontalAlignment.Centre;

            //add it to ths screen
            drawToScreen.Add(particleDrawer);
        }
Пример #14
0
        protected override void Initialise()
        {
            Camera3D camera = new Camera3D();

            camera.LookAt(new Vector3(0, 0, 4), new Vector3(3, 4, 4), new Vector3(0, 0, 1));

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

            //create the actor
            actor = new Actor(this.Content, this.UpdateManager);

            drawToScreen.Add(actor);

            text          = new TextElement();
            text.Position = new Vector2(30, -30);             // text is aligned to the top left by default

            drawToScreen.Add(text);
        }
Пример #15
0
        protected override void Initialise()
        {
            Camera3D camera = new Camera3D();

            camera.LookAt(new Vector3(0, 1, 0), new Vector3(0.5f, 1, -1), new Vector3(0, 1, 0));
            camera.Projection.NearClip = 0.1f;

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

            //create the avatar instance
            drawToScreen.Add(new Avatar(this.Content, this.UpdateManager));

#if XBOX
            text = new TextElement(@"Press 'A' to display a new Avatar" + Environment.NewLine + "Press 'B' to play the 'Cheer' animation.");
#else
            text = new TextElement(@"Unfortunately, avatars are only supported on the XBOX...." + Environment.NewLine + "AvatarInstance will display a wireframe of an avatar skeleton, using any FBX imported animations." + Environment.NewLine + "XNA preset animations cannot be displayed in this wireframe mode.");
#endif
            text.Position = new Vector2(50, -50);
            drawToScreen.Add(text);
        }
Пример #16
0
        protected override void Initialise()
        {
            Resource.EnableResourceTracking();

            //draw targets usually need a camera.
            Xen.Ex.Camera.FirstPersonControlledCamera3D camera = new Xen.Ex.Camera.FirstPersonControlledCamera3D(this.UpdateManager);

            //don't allow the camera to move
            camera.MovementSensitivity *= 0;
            camera.Position             = new Vector3(0, 5, 0);

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


            //create the particle system
            this.particles = new ParticleSystem(this.UpdateManager);

            //the snow particles will be drawn as velocity particles
            this.snowDrawer = new Xen.Ex.Graphics.Display.VelocityBillboardParticles3D(this.particles, false, 0.1f);

            //the fog particles will be drawn as normal billboards
            this.fogDrawer = new Xen.Ex.Graphics.Display.BillboardParticles3D(this.particles);

            //add a ground plane to show the horizon
            drawToScreen.Add(new DarkGroundPlane(new Vector4(0.225f, 0.225f, 0.225f, 1f)));

            //add the particles
            drawToScreen.Add(fogDrawer);
            drawToScreen.Add(snowDrawer);

            //Note: The particle drawers are masked in the LoadContent method

            //add draw stats
            stats = new Xen.Ex.Graphics2D.Statistics.DrawStatisticsDisplay(this.UpdateManager);
            drawToScreen.Add(stats);
        }
Пример #17
0
        protected override void Initialise()
        {
            //create the draw target.
            drawToScreen = new DrawTargetScreen(this, new Camera3D());

            //this element will display some help text
            helpDisplay          = new TextElement();
            helpDisplay.Position = new Vector2(100, -100);


#if XBOX360
            helpDisplay.Text.SetText("Use a chatpad to input text!");
#else
            helpDisplay.Text.SetText("Use the keyboard to input text!");
#endif

            //add it to the screen
            drawToScreen.Add(helpDisplay);



            //create the text
            this.textElement        = new TextElementRect(new Vector2(400, 200));
            this.textElement.Colour = Color.Yellow;


            //align the element to the bottom centre of the screen
            this.textElement.VerticalAlignment   = VerticalAlignment.Bottom;
            this.textElement.HorizontalAlignment = HorizontalAlignment.Centre;

            //centre align the text
            this.textElement.TextHorizontalAlignment = TextHorizontalAlignment.Centre;
            //centre the text in the middle of the 400x200 area of the element
            this.textElement.TextVerticalAlignment = VerticalAlignment.Centre;

            //add it to the screen
            drawToScreen.Add(textElement);
        }
Пример #18
0
        protected override void Initialise()
        {
            Resource.EnableResourceTracking();

            Camera3D camera = new Xen.Ex.Camera.FirstPersonControlledCamera3D(this.UpdateManager, Vector3.Zero, true);

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

            //NEW CODE
            //create a BatchModel, this class stores the ModelData and will draw BatchModelInstances
            this.batchModel = new BatchModel();

            //NEW CODE
            //create a large number of actors (1600)
            for (float x = -20; x < 20; x++)
            {
                for (float y = -20; y < 20; y++)
                {
                    drawToScreen.Add(new Actor(this.batchModel, new Vector3(x * 5, y * 5, -5)));
                }
            }

            //this is the most important bit...
            //always add the BatchModel itself to the draw target,
            //this should be added *after* all BatchModelInstances have been added

            //Note: each time a BatchModelInstance is drawn, it will store it's world matrix in the BatchModel
            //If the BatchModel is not drawn, the buffer storing these matrices will not be emptied, and will
            //eventually throw an OutOfMemoryException exception.

            this.drawToScreen.Add(batchModel);

            statistics = new Xen.Ex.Graphics2D.Statistics.DrawStatisticsDisplay(this.UpdateManager);
            this.drawToScreen.Add(statistics);
        }
Пример #19
0
        protected override void Initialise()
        {
            //create the camera
            Xen.Ex.Camera.FirstPersonControlledCamera3D camera =
                new Xen.Ex.Camera.FirstPersonControlledCamera3D(this.UpdateManager, Vector3.Zero);
            camera.Projection.FarClip *= 10;

            this.camera = camera;


            //create the draw target.
            drawToScreen = new DrawTargetScreen(this, camera);

            //25,000 instances
            const int   instanceCount = 25000;
            const float areaRadius    = 500;


            //create the mesh instance drawer, (but add it to the screen later)
            InstancedMeshGeometry meshDrawer = new InstancedMeshGeometry(instanceCount);

            //the instances are added to a StaticBinaryTreePartition, which sorts the items
            //into a binary tree, for more efficient culling.
            //This class assumes it's children do not move (ie they are static)

            Xen.Ex.Scene.StaticBinaryTreePartition sceneTree = new Xen.Ex.Scene.StaticBinaryTreePartition();

            //add it to the screen
            drawToScreen.Add(sceneTree);


            //create the instances
            Random random = new Random();

            for (int i = 0; i < instanceCount; i++)
            {
                //create a random position in a sphere
                Vector3 position = new Vector3((float)(random.NextDouble() - .5),
                                               (float)(random.NextDouble() - .5),
                                               (float)(random.NextDouble() - .5));
                position.Normalize();
                position *= (float)Math.Sqrt(random.NextDouble()) * areaRadius;


                //create the instance
                MeshInstance instance = new MeshInstance(meshDrawer, position);

                //add the instance to the StaticBinaryTreePartition
                sceneTree.Add(instance);
            }

            //now add the drawer (instances will be drawn by the StaticBinaryPartition, before the drawer)
            drawToScreen.Add(meshDrawer);

            //Note that if the StaticBinaryTreePartition was not used, then
            //in each frame, every single instance would perform a CullTest to the screen
            //CullTests, despite their simplicity can be very costly in large numbers.
            //The StaticBinaryTreePartition will usually perform a maximum number of CullTests
            //that is approximately ~30% the number of children. (in this case, ~8000 tests)
            //At it's best, when it's entirely off or on screen, it will perform only 1 or 2 CullTests.

            //The number of cull tests performed will be displayed in debug builds of this tutorial:

            //add some statusText to display on screen to show the stats
            statusText          = new TextElement();
            statusText.Position = new Vector2(50, -50);
            drawToScreen.Add(statusText);
        }
Пример #20
0
        protected override void Initialise()
        {
            Resource.EnableResourceTracking();

            //draw targets usually need a camera.
            Xen.Ex.Camera.FirstPersonControlledCamera3D camera = new Xen.Ex.Camera.FirstPersonControlledCamera3D(this.UpdateManager, Vector3.Zero, false);

            //don't allow the camera to move too fast
            camera.MovementSensitivity *= 0.1f;
            camera.LookAt(new Vector3(0, 3, 0), new Vector3(1, 5, 10), new Vector3(0, 1, 0));

            //create the draw target.
            drawToScreen = new DrawTargetScreen(this, camera);
            drawToScreen.ClearBuffer.ClearColour = new Color(45, 50, 60);


            //create the fire and smoke particle system
            this.fireParticleSystem  = new ParticleSystem(this.UpdateManager);
            this.smokeParticleSystem = new ParticleSystem(this.UpdateManager);

            //IMPORTANT
            //The following flags are FALSE by default.
            //For looping effects, such as the fire and smoke, it's highly
            //recommended to enable this flag. Otherwise, while the effect
            //is offscreen, the particle system will continue to process.
            this.fireParticleSystem.PauseUpdatingWhileCulled  = true;
            this.smokeParticleSystem.PauseUpdatingWhileCulled = true;


            this.drawSorted   = new Xen.Ex.Scene.DepthDrawSorter(Xen.Ex.Scene.DepthSortMode.BackToFront);
            this.drawUnsorted = new DrawList();

            Xen.Ex.Graphics.Display.ParticleDrawer3D fireDrawer  = new Xen.Ex.Graphics.Display.VelocityBillboardParticles3D(this.fireParticleSystem, true);
            Xen.Ex.Graphics.Display.ParticleDrawer3D smokeDrawer = new Xen.Ex.Graphics.Display.BillboardParticles3D(this.smokeParticleSystem);

            for (int i = 0; i < 10; i++)
            {
                Vector3 position = new Vector3((float)Math.Cos(i * Math.PI / 5.0) * 6.0f, 0, (float)Math.Sin(i * Math.PI / 5.0) * 6.0f);

                CullableParticleWrapper fireEffect, smokeEffect;

                fireEffect  = new CullableParticleWrapper(fireDrawer, position, new Vector3(0, 2, 0), 4);
                smokeEffect = new CullableParticleWrapper(smokeDrawer, position, new Vector3(0, 6, 0), 5);

                this.drawSorted.Add(fireEffect);
                this.drawSorted.Add(smokeEffect);

                this.drawUnsorted.Add(fireEffect);
                this.drawUnsorted.Add(smokeEffect);

                GroundLightDisk light = new GroundLightDisk(position);
                this.drawSorted.Add(light);
                this.drawUnsorted.Add(light);
            }


            //setup the burst effect
            this.burstParticleSystem = new ParticleSystem(this.UpdateManager);

            //for this case, PauseUpdatingWhileCulled is not set to true.
            //The particle emitting is culled when offscreen. If set to true,
            //Any particles left offscreen could 'pause', when they naturally
            //wouldn't be emitted anyway.
            //(The particle system will use very few resources when it has no
            //active particles)

            this.burstSources = new BurstSource[20];
            Random rand = new Random();

            for (int i = 0; i < this.burstSources.Length; i++)
            {
                //create the bursts out in the distance
                Vector3 position = new Vector3((float)i * 5.0f - this.burstSources.Length * 2.5f, 0, -20);
                float   radius   = 10;             // with a decent radius

                //give them a random starting time
                this.burstSources[i] = new BurstSource(position, radius, (float)rand.NextDouble() * 2);

                this.drawSorted.Add(this.burstSources[i]);
                this.drawUnsorted.Add(this.burstSources[i]);
            }

            //the bursts need to be drawn as a group..
            ParticleDrawer3D burstDrawer = new Xen.Ex.Graphics.Display.VelocityBillboardParticles3D(this.burstParticleSystem, false, 0.5f);

            this.drawSorted.Add(burstDrawer);
            this.drawUnsorted.Add(burstDrawer);

            //Use all the burst sources to cull the drawer (may not be ideal if there were many sources...)
            //Use the particle drawer CullProxy to do it
            burstDrawer.CullProxy = new BurstCullProxy(this.burstSources);



            //add a ground plane to show the horizon
            drawToScreen.Add(new Tutorial_22.DarkGroundPlane(new Vector4(0.125f, 0.15f, 0.135f, 1)));

            //add the sorted and unsorted lists
            drawToScreen.Add(drawSorted);
            drawToScreen.Add(drawUnsorted);


            //finally, create a CullTestVisualizer, which will visually show the cull tests performed
            cullTestVisualizer = new Xen.Ex.Scene.CullTestVisualizer(this.drawToScreen.Camera);

            //the visualizer is added as a draw modifier
            this.drawToScreen.AddModifier(cullTestVisualizer);

            //add help text
            this.text = new TextElement();
            this.text.VerticalAlignment = VerticalAlignment.Bottom;
            this.text.Position          = new Vector2(50, 100);
            drawToScreen.Add(this.text);

            //add draw stats
            stats = new Xen.Ex.Graphics2D.Statistics.DrawStatisticsDisplay(this.UpdateManager);
            drawToScreen.Add(stats);
        }
Пример #21
0
        protected override void Initialise()
        {
            //setup ambient lighting
            this.ambientLight               = new MaterialLightCollection();
            ambientLight.LightingEnabled    = true;
            ambientLight.AmbientLightColour = new Vector3(0.25f, 0.25f, 0.25f);
            ambientLight.AddDirectionalLight(false, new Vector3(-1, -1, 0), new Vector3(2, 2, 2));           // add some backlighting

            //setup the shadow render camera
            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)
            SurfaceFormat textureFormat = SurfaceFormat.Color;
            const int     resolution    = 512;

            //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;

#if !XBOX360
            //not required on the xbox if the render target is small enough to fit in EDRAM in one tile
            blurIntermediate = new DrawTargetTexture2D(shadowCamera, resolution, resolution, textureFormat);
#endif
            //create a blur filter
            shadowDepthBlurFilter = new Xen.Ex.Filters.BlurFilter(Xen.Ex.Filters.BlurFilterFormat.SevenSampleBlur, 1.0f, drawShadowDepth, blurIntermediate);

            //create the scene camera
            Camera3D 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(this, 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.1f, 4 - x * 2 - y));
                    }
                }
            }

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


            //setup the draw targets...


            //create the shader provider
            ShadowOutputShaderProvider 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);

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

            //add a nice faded background
            Tutorial_20.BackgroundGradient background = new Tutorial_20.BackgroundGradient(Color.WhiteSmoke, Color.Black);
            background.DrawAtMaxZDepth = true;
            drawToScreen.Add(background);


            //create a textured element that will display the shadow map texture
            TexturedElement shadowDepthDisplay = new TexturedElement(drawShadowDepth, new Vector2(256, 256));
            shadowDepthDisplay.VerticalAlignment = VerticalAlignment.Top;
            this.drawToScreen.Add(shadowDepthDisplay);
        }
Пример #22
0
        protected override void Initialise()
        {
            Resource.EnableResourceTracking();

            camera = new Camera3D();
            camera.Projection.FarClip      = 300;
            camera.Projection.NearClip     = 10;
            camera.Projection.FieldOfView *= 0.55f;
            //create the draw target.
            drawToScreen = new DrawTargetScreen(this, camera);

            //no need to clear the colour buffer, as a special background will be drawn
            drawToScreen.ClearBuffer.ClearColourEnabled = false;

            //create the light collection first
            lights = new MaterialLightCollection();

            // In this example, the rendering order has been manually optimized to reduce the number of pixels drawn
            //
            // In xen, rendering is usually explicit. This means, when a call to Draw() is made, the draw order is
            // respected, and internally the object will be drawn using the graphics API.
            // Objects added to the screen will have Draw() called in the order they were added.
            //
            // However, the draw order can also cause performance problems.
            // In general, it's best to draw front to back, this means draw the objects closest to the screen first.
            //
            // This way, the objects at the back will be drawing behind the objects already drawn.
            // Modern video cards can quickly discard pixels if they are 'behind' what is already drawn.
            // Without front-to-back, the objects at the front could be drawing *over* objects already drawn.
            //
            // This is known as overdraw, a case where an object is drawn, only to be 'overdrawn' later in the frame.
            // Reducing overdraw can help performance, especially when complex shaders are used.
            //
            // In this example, the sample is usually vertex-limited (that is, the bottleneck is vertex processing)
            // However, it can demonstrate how optimizing for overdraw can significantly reduce the number of pixels
            // that are shaded.
            //
            // In debug builds, the DrawStatisticsDisplay class will show the number of pixels drawn in the frame.
            //
            // With overdraw optimized draw order, ~1,000,000 pixels are drawn per frame. Without, upto 2,100,000
            // pixels are drawn per frame (usually ~1,800,000). (A 1280x720 display has 921,600 pixels)
            //
            // This means that without an overdraw optimized draw order, on average, each pixel is being drawn
            // twice. With an optimized draw order, this number is closer to 1.1, which is very close to the
            // optimal value of 1.0 (where each pixel is only drawn once).
            //
            // Note that the number of pixels reported by the DrawStatisticsDisplay is for the entire frame, including
            // every render target. Some PCs may not support this value, and display -1.
            //
            // One last point....
            // This sample is an extreme test of a GPU's ability to push triangles onto the screen (vertex/triangle rate).
            // However, observation will show the number of triangles drawn is often over 3,300,000!
            // Assuming half the triangles are back-face culled (an accurate approximation), this still means
            // there are around 1,650,000 triangles that are visible at any time.
            // (But remember, the vertex shader still runs for back facing triangles!)
            //
            // Assuming approximatly half of these triangles are depth occluded (very approximate), still
            // results in a huge number of visible triangles.
            // This all means that the average triangle is drawing a *very* small number of pixels, in this case,
            // the average for the actors is probably *less than 1 pixel per triangle!*.
            //
            // Triangles averaging less than 1 pixel are known as subpixel triangles.
            // For a number of reasons, subpixel triangles are very inefficent.
            // For example, if a single pixel is drawn, due to the way a video card works, the pixel shader will always
            // run in multiples of 4 pixels, so a single pixel triangle will still run the pixel shader 4 times.
            //
            // This makes this sample a perfect candidate for level of detail optimization, where a lower resolution
            // model is used as an actor gets further away from the screen.
            //
            // The vertex shader is also very expensive, and for each triangle, it will be run upto 3 times.
            // This means the vertex shader is quite possibly running more often than the pixel shader.
            // This hypothesis can be confirmed; setting the lights to per-vertex, instead of per-pixel, results
            // in a significantly *lower* frame rate!
            //
            //
            //

            bool optimizeForOverdraw = true;

            //create a list of actors to added to the screen
            List <Actor> actors = new List <Actor>(500);

            //create 500 actors!
            for (int i = 0; i < 500; i++)
            {
                Actor actor = new Actor(this.Content, this.UpdateManager, lights, diskRadius);
                actors.Add(actor);
            }


            //create the lights, similar to Tutorial 14
            lights.AmbientLightColour = new Vector3(0.45f, 0.45f, 0.5f);

            Vector3[] lightPositions = new Vector3[]
            {
                new Vector3(0, 30, 12),
                new Vector3(0, -30, 12)
            };

            //setup the two lights in the scene
            IDraw lightGeometry     = null;
            IDraw lightPoleGeometry = null;
            //create geometry to display the lights
            List <IDraw> lightSourceGeometry = new List <IDraw>();

            //setup the lights, and create the light globe geometry
            for (int i = 0; i < lightPositions.Length; i++)
            {
                Vector3 colour = new Vector3(5, 5, 5);

                IMaterialPointLight light = lights.AddPointLight(i < 2, lightPositions[i], 8, colour, colour);

                light.ConstantAttenuation  = 0.25f;                // make the ligh falloff curve a lot sharper (brighter at the centre)
                light.LinearAttenuation    = 0;
                light.QuadraticAttenuation = 0.075f;               //approximate inverse distance in which the brightness of the light will halve

                if (lightGeometry == null)
                {
                    lightGeometry     = new Xen.Ex.Geometry.Sphere(Vector3.One, 8, true, false, false);
                    lightPoleGeometry = new Xen.Ex.Geometry.Cube(new Vector3(0.4f, 0.4f, lightPositions[i].Z * 0.5f));
                }

                //visually show the light
                //create the light sphere geometry from tutorial 14.
                Vector3 position = lightPositions[i];
                lightSourceGeometry.Add(new Tutorial_14.LightSourceDrawer(position, lightGeometry, Color.LightYellow));
                position.Z *= 0.5f;
                lightSourceGeometry.Add(new Tutorial_14.LightSourceDrawer(position, lightPoleGeometry, new Color(40, 40, 70)));
            }

            //create the ground plane, also from tutorial 14
            Tutorial_14.GroundDisk ground = new Tutorial_14.GroundDisk(this.Content, lights, diskRadius);


            //this is a special background element,
            //it draws a gradient over the entire screen, fading from dark at the bottom to light at the top.
            Color darkBlue  = new Color(40, 40, 50);
            Color lightBlue = new Color(100, 100, 110);
            BackgroundGradient background = new BackgroundGradient(lightBlue, darkBlue);


            if (optimizeForOverdraw == false)
            {
                //add all the objects in a naive order

                //first add the background (fills the entire screen, draws to every pixel, but is very fast)
                drawToScreen.Add(background);

                //then add the ground plane (all the actors will appear on top of the ground plane, overdrawing it)
                drawToScreen.Add(ground);

                //then add the lights (which are on top of the ground, overdrawing it)
                foreach (IDraw geometry in lightSourceGeometry)
                {
                    drawToScreen.Add(geometry);
                }

                //then finally add the actors, in the order they were created
                foreach (Actor actor in actors)
                {
                    drawToScreen.Add(actor);
                }
            }
            else
            {
                //or, add the objects in a order optimized for overdraw

#if !XBOX360
                //first, add the actors. Because they are almost always closest to the screen
                //however, use a depth sorter so the actors are sorted into a front to back draw order,
                //this sorting is based on the centre point of the cull tests they perform.

                Xen.Ex.Scene.DepthDrawSorter sorter = new Xen.Ex.Scene.DepthDrawSorter(Xen.Ex.Scene.DepthSortMode.FrontToBack);

                //Remember, the objects placed in the sorter *must* perform a valid CullTest,
                //if the CullTest simply returns true/false, no sorting will occur.
                //(Note the Actor.CullTest method)

                //to ease the CPU load, have the sorter only sort the actors every few frames...
                sorter.SortDelayFrameCount = 5;

                foreach (Actor actor in actors)
                {
                    sorter.Add(actor);                     // add the actors to the sorter (not the screen)
                }
                //the sorter itself must be added to the screen!
                drawToScreen.Add(sorter);                 // the sorter will then draw the actors in a sorted order
#else
                //In this case (on the Xbox), because the application is heavily vertex limited
                //and already heavily CPU stretched by the animation system, the cost of
                //sorting the actors actually causes a larger performance hit on the CPU than
                //the time saved on the GPU. This inballance causes a frame rate drop.
                //
                //However, the reason for this may be unexpected.
                //The framerate drop is not caused by the overhead of sorting the actors.
                //
                //Any 3D API calls made are doubly expensive on the XBOX, so in order to
                //maintain 20fps in this sample, the primary (rendering) thread must not
                //block, or switch to task processing.
                //If it does so, valuable rendering time is lost.
                //
                //When using a sorter, the actors are drawn in an order that is constantly changing.
                //However, they always have Update() called in a consistent order.
                //
                //During Update() the actors animation controllers will spawn thread tasks to
                //process their animation.
                //
                //These tasks are processed on the three spare xbox hardware threads, they are
                //processed in the order they were added.
                //Processing the animation usually completes before the rendering finishes.
                //(the rendering is not delayed waiting for the animation to finish).
                //
                //However, when sorting the actors get drawn in an unpredictable order,
                //this means the last actor added could be the first actor to draw,
                //in such a case, the chances of it's animation processing having completed
                //is *very* low. When this happens, the rendering thread has to switch to
                //processing animations, delaying rendering.
                //
                //So, for the xbox, it's best just to draw in the update order.

                foreach (Actor actor in actors)
                {
                    drawToScreen.Add(actor);
                }
#endif

                //add the light source geometry, as they are usually below the actors, but above the ground
                foreach (IDraw geometry in lightSourceGeometry)
                {
                    drawToScreen.Add(geometry);
                }

                //then add the ground plane, which is usually below the actors and lights.
                drawToScreen.Add(ground);

                //finally, enable a special feature of ElementRect.
                //This makes the element draw at the maximum possible Z distance
                //(behind anything else that has been drawn)
                background.DrawAtMaxZDepth = true;

                //add it to the screen
                drawToScreen.Add(background);
            }

            //finally,
            //create the draw statistics display
            stats = new Xen.Ex.Graphics2D.Statistics.DrawStatisticsDisplay(this.UpdateManager);
            drawToScreen.Add(stats);
        }
Пример #23
0
        protected override void Initialise()
        {
            camera = new Camera3D();

            //create the draw target.
            drawToScreen = new DrawTargetScreen(this, camera);
            //clear to dark blue
            drawToScreen.ClearBuffer.ClearColour = new Color(20, 20, 40);

            //create the light collection
            lights = new MaterialLightCollection();
            //set a dark blue ambient colour
            lights.AmbientLightColour = new Color(40, 40, 80).ToVector3();

            //positions for two lights
            Vector3[] lightPositions = new Vector3[]
            {
                new Vector3(0, 30, 2),
                new Vector3(0, -30, 2)
            };

            //geometry for a light (shared for each light)
            IDraw lightGeometry = null;

            for (int i = 0; i < lightPositions.Length; i++)
            {
                float lightHalfFalloffDistance = 15;
                Color lightColor          = Color.LightYellow;
                Color lightSpecularColour = Color.WhiteSmoke;
                bool  perPixel            = i < 2;    //first two lights are per-pixel

                //interface to the light about to be created
                IMaterialPointLight light = null;

                //create the point light
                light = lights.AddPointLight(perPixel, lightPositions[i], lightHalfFalloffDistance, lightColor, lightSpecularColour);

                //adjust the lighting attenuation model, the constant defaults to 1, which prevents the light being brighter than 1.0 in the falloff equation
                //set to 0.25, the light will get really bright in close (up to 4)
                //(see light.QuadraticAttenuation remarks for an explanation of the falloff model)
                light.ConstantAttenuation = 0.25f;

                //create the light geometry (a sphere)
                if (lightGeometry == null)
                {
                    lightGeometry = new Xen.Ex.Geometry.Sphere(Vector3.One, 8, true, false, false);
                }

                //visually show the light with a light drawer
                IDraw lightSourceDrawer = new LightSourceDrawer(lightPositions[i], lightGeometry, lightColor);

                //add the light geometry to the screen
                drawToScreen.Add(lightSourceDrawer);
            }

            //create the ground disk
            GroundDisk ground = new GroundDisk(this.Content, lights, diskRadius);

            //then add it to the screen
            drawToScreen.Add(ground);
        }
Пример #24
0
        protected override void Initialise()
        {
            Resource.EnableResourceTracking();

            //setup the view camera first
            //--------------------------------------

            viewCamera = new Xen.Ex.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

            //find a desirable format for the shadow map,
            SurfaceFormat format = SurfaceFormat.Color;

            //ideally use a high precision format, but only if it's supported. Avoid full 32bit float
            if (DrawTargetTexture2D.SupportsFormat(SurfaceFormat.Rg32))
            {
                format = SurfaceFormat.Rg32;                                                                                                            //ushort * 2
            }
            else if (DrawTargetTexture2D.SupportsFormat(SurfaceFormat.HalfVector2))
            {
                format = SurfaceFormat.HalfVector2;                                                                                     //fp16 * 2
            }
            else if (DrawTargetTexture2D.SupportsFormat(SurfaceFormat.HalfVector4))
            {
                format = SurfaceFormat.HalfVector4;                                                                                 //fp16 * 4
            }
            //create the shadow map
            shadowMap = new DrawTargetTexture2D(shadowCamera, shadowMapResolution, shadowMapResolution, format, 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(this, new Camera2D());
            drawToScreen.ClearBuffer.ClearColourEnabled = false;

            drawToRenderTarget = new DrawTargetTexture2D(viewCamera, this.WindowWidth, this.WindowHeight, SurfaceFormat.Color, DepthFormat.Depth24Stencil8, false, MultiSampleType.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);
            bloomRenderTarget.ClearBuffer.ClearColourEnabled = false;

            bloomIntermediateRenderTarget = null;
#if WINDOWS
            //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);
            bloomIntermediateRenderTarget.ClearBuffer.ClearColourEnabled = false;
#endif
            //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();
            this.characterBlendRenderShader = new Shaders.CharacterBlend();

            //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);
        }
Пример #25
0
        protected override void Initialise()
        {
            //DrawStatisticsDisplay requires that resource tracking is enabled
            Resource.EnableResourceTracking();


            //Xen.Ex provides a very useful Camera3D called 'FirstPersonControlledCamera3D'.
            //This camera uses player input to act as a simple first-person style flythrough camera
            Xen.Ex.Camera.FirstPersonControlledCamera3D camera = null;

            //it uses player input, so the UpdateManager must be passed in
            camera = new Xen.Ex.Camera.FirstPersonControlledCamera3D(this.UpdateManager);

            //in this case, we want the z-axis to be the up/down axis (otherwise it's the Y-axis)
            camera.ZAxisUp = true;
            //also it's default is a bit too fast moving
            camera.MovementSensitivity *= 0.1f;
            camera.LookAt(new Vector3(1, 0, 0), new Vector3(), new Vector3(0, 0, 1));

            this.camera = camera;

            //create the draw target.
            drawToScreen = new DrawTargetScreen(this, camera);


            //create a large number of actor instance from tutorial 10..
            for (int n = 0; n <= 16; n++)
            {
                //create in a half circle
                float   angle    = (n / 16.0f) * MathHelper.Pi;
                Vector3 position = new Vector3((float)Math.Sin(angle), (float)Math.Cos(angle), 0);

                //not too close together
                position *= 10;

                drawToScreen.Add(new Tutorial_10.Actor(this.Content, position));
            }


            //this element will display the camera position
            positionDisplay = new TextElement();

            //TextElement (unlike other Elements) defaults to Top Left alignment
            //So, in order to bring it closer to the centre of the screen (due to potential overscan)
            //it's position needs to be set 'right' and 'down' from 'top left'
            //(this is just an example, see XNA docs for correct overscan compensation behaviour)
            positionDisplay.Position = new Vector2(40, -40);             //offset from top left corner alignment

            //add it to the screen
            drawToScreen.Add(positionDisplay);



            Vector2 sizeInPixels = new Vector2(400, 200);

            //create the main block of yellow text
            this.yellowElement        = new TextElementRect(sizeInPixels);
            this.yellowElement.Colour = Color.Yellow;

            //first line of text... this will have a flashing 2D element embedded
            string embeddedText  = @"This is a text box with a large amount of custom text! It also includes an embedded 2D element: , which is a 16x16 SolidColourElement";
            uint   insertAtIndex = 96;           // Hard coded to insert a 2D element at character index 96               which is about here: ^

            //add a bunch of text...
            this.yellowElement.Text.AppendLine(embeddedText);
            this.yellowElement.Text.AppendLine();
            this.yellowElement.Text.AppendLine(@"This class is:");
            this.yellowElement.Text.AppendLine(this.GetType().FullName);
            this.yellowElement.Text.AppendLine(@"It is located in assembly:");
            this.yellowElement.Text.AppendLine(this.GetType().Assembly.FullName);
            this.yellowElement.Text.AppendLine();

            //add an embedded 2D element within the text
            //create it..
            this.embeddedElement = new SolidColourElement(Color.Red, new Vector2(16, 16));             // quite small
            this.embeddedElement.AlphaBlendState = AlphaBlendState.Alpha;
            //add it.
            this.yellowElement.AddInline(this.embeddedElement, insertAtIndex);


#if XBOX360
            this.yellowElement.Text.AppendLine(@"Press and hold both thumbsticks to show the debug overlay");
#else
            this.yellowElement.Text.AppendLine(@"Press F12 to show the debug overlay");
#endif


            //align the element rectangle to the bottom centre of the screen
            this.yellowElement.VerticalAlignment   = VerticalAlignment.Bottom;
            this.yellowElement.HorizontalAlignment = HorizontalAlignment.Centre;

            //centre align the text
            this.yellowElement.TextHorizontalAlignment = TextHorizontalAlignment.Centre;
            //centre the text in the middle of the 400x200 area of the element rectangle
            this.yellowElement.TextVerticalAlignment = VerticalAlignment.Centre;

            //add it to the screen
            drawToScreen.Add(yellowElement);



            //create the statistics display
            //this class will query the DrawState for the previous frames DrawStatistics structure.
            //this structure provides a large number of statistics for the drawn frame.
            //The DrawStatisticsDisplay displays some of the more important statistics. It will also
            //display thread activity on the xbox.

            //DrawStatistics are only available in DEBUG xen builds
            //They can be accessed at runtime with DrawState GetPreviousFrameStatistics()

            //at runtime, pressing 'F12' will toggle the overlay (or holding both thumbsticks on x360)
            this.statisticsOverlay = new Xen.Ex.Graphics2D.Statistics.DrawStatisticsDisplay(this.UpdateManager);

            //As of xen 1.5, by default the DrawStatisticsDisplay displays a significantly reduced number of graphs.
            //To display the full set of graphs (which generally takes up the entire screen), set the following
            //property to 'true':
            //this.statisticsOverlay.DisplayFullGraphList = true;


            //then add it to the screen
            drawToScreen.Add(statisticsOverlay);
        }