public void renderScene() { Renderables.Triangle triangle = new Renderables.Triangle(); while (true) { DeviceManager dm = DeviceManager.Instance; dm.context.ClearRenderTargetView(dm.renderTarget, new Color4(0.25f, 0.75f, 0.25f)); triangle.render(); dm.swapChain.Present(0, PresentFlags.None); } }
The Renderable Class
But what you usually want to do is add and remove objects to render dynamically. So we have to have a data structure to hold all our render objects. For the sake of simplicity lets start with a list. To be able to iterate through the List, all renderable objects have to inherit from a base class called Renderable.
So this is the bare minimum we need:
public abstract class Renderable { public abstract void render(); }
Now let us derive our Triangle Class from this abstract class override our render method:
class Triangle : Renderable { ShaderSignature inputSignature; VertexShader vertexShader; PixelShader pixelShader; . . .
public override void render() { // configure the Input Assembler portion of the pipeline with the vertex data DeviceManager.Instance.context.InputAssembler.InputLayout = layout; DeviceManager.Instance.context.InputAssembler.PrimitiveTopology = PrimitiveTopology.TriangleList; DeviceManager.Instance.context.InputAssembler.SetVertexBuffers(0, new VertexBufferBinding(vertexBuffer, 12, 0)); // set the shaders DeviceManager.Instance.context.VertexShader.Set(vertexShader); DeviceManager.Instance.context.PixelShader.Set(pixelShader); // render the triangle DeviceManager.Instance.context.Draw(3, 0); }
The Scene Class
Now lets add a Singleton Class called Scene. This holds a List of Renderables, a method to add Renderables, a method to remove Renderables and a method to iterate our List to render the objects.To prevent altering the List while the render-loop is calling the render method, I use the lock Statement.
using System; using System.Collections.Generic; using System.Linq; using System.Text; using Apparat.Renderables; namespace Apparat { public class Scene { #region Singleton Pattern private static Scene instance = null; public static Scene Instance { get { if (instance == null) { instance = new Scene(); } return instance; } } #endregion #region Constructor private Scene() { } #endregion List<Renderable> RenderObjects = new List<Renderable>(); public void addRenderObject(Renderable renderObject) { lock (RenderObjects) { RenderObjects.Add(renderObject); } } public void removeRenderObject(Renderable renderObject) { lock (RenderObjects) { if( RenderObjects.Contains( renderObject )) { RenderObjects.Remove( renderObject ); } } } public void render() { lock (RenderObjects) { foreach (Renderable renderable in RenderObjects) { renderable.render(); } } } } }
Using the Scene
Now we can change the code in our renderScene method in our RenderManager to call the render method of our Scene (compare with the first method at the top):
public void renderScene() { while (true) { DeviceManager dm = DeviceManager.Instance; dm.context.ClearRenderTargetView(dm.renderTarget, new Color4(0.25f, 0.75f, 0.25f)); Scene.Instance.render(); dm.swapChain.Present(0, PresentFlags.None); } }
While we created the triangle at first in our renderScene method, we are now able to add and remove Renderables from our Application!
For example:
You can download the code to this project here:
http://apparat.codeplex.com/SourceControl/changeset/changes/ba452d5587ac
For example:
public Form1() { InitializeComponent(); DeviceManager.Instance.createDeviceAndSwapChain(this); RenderManager.Instance.init(); Triangle triangle = new Triangle(); Scene.Instance.addRenderObject(triangle); }
You can download the code to this project here:
http://apparat.codeplex.com/SourceControl/changeset/changes/ba452d5587ac