Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

Simulating Mirror in a Managed DirectX Application

0.00/5 (No votes)
14 Jul 2006 1  
Simulating Mirror in a Managed DirectX Application
Sample Image - DirectXMirror.gif

Introduction

This article explains how to simulate a mirror in a Managed DirectX application. This technique has many uses, but the best one I can think of right now is to make a rear-view mirror in a driving simulation.

Using the Code

The Mirror effect is achieved by rendering the same scene (generally with a different camera angle) into a texture, and then applying this texture to a triangle(s) or simply to a sprite. I am going to apply it to a sprite.

Rendering Into Surface

First of all, we need to declare these variables :

private Texture renderTexture = null;
private Surface renderSurface = null;
private RenderToSurface rts = null;
private const int renderSurfaceSize = 128;
  • renderTexture is the texture we will be rendering to.
  • renderSurface is the surface which we get from the texture. Technically we will be rendering to this surface.
  • rts is an object of type RenderToSurface, which is a helper class used to, yes you guessed right, render to the surface.
  • renderSurfaceSize is the length of the side of my square mirror (You can easily create a rectangular mirror, as you will see later.)

Now we initialize the mirror variables. This initialization should be done after the device creation and before Application.Run(). Here is the code:

rts = new RenderToSurface(device, RenderSurfaceSize, RenderSurfaceSize,
    Format.X8R8G8B8, true, DepthFormat.D16);
renderTexture = new Texture(device, RenderSurfaceSize, RenderSurfaceSize, 
    1,Usage.RenderTarget, Format.X8R8G8B8, Pool.Default);
renderSurface = renderTexture.GetSurfaceLevel(0);

First we create the object rts of the helper class. Note that the arguments used in its creation are similar to the arguments used in device creation. Then we create our texture and then the actual surface from the texture.

Assume that the only object to render is a Mesh, mesh. So the code for this is mesh.DrawSubset(0);

Here is the code for rendering into the surface :

private void RenderIntoSurface()
{
    // Render to this surface
    Viewport view = new Viewport();
    view.Width = RenderSurfaceSize;
    view.Height = RenderSurfaceSize;
    view.MaxZ = 1.0f;
    
    rts.BeginScene(renderSurface, view);

    device.Clear(ClearFlags.Target | ClearFlags.ZBuffer, Color.DarkBlue, 1.0f,
        0);
    device.Transform.Projection = Matrix.PerspectiveFovLH((float)Math.PI / 4,
        this.Width / this.Height, 1.0f, 100.0f);

    device.Transform.View = Matrix.LookAtLH(new Vector3(0,0, -3.0f),
        new Vector3(0,0,0), new Vector3(0, 1,0));

    mesh.DrawSubset(0);

    rts.EndScene(Filter.None);
}

Note that this code is very similar to our normal rendering method. There is a begin call, an end call, camera transforms, and the Mesh rendering. The view matrix specified here is the actual view angle of the mirror.

Rendering the Sprite

We will want to render to the surface before rendering to our main window, hence add this line as the first statement in your OnPaint method.

RenderIntoSurface()

Now we need to render the sprite. Given below is the code to render the sprite using the surface. This code is to be added in between the device.BeginScene() and device.EndScene() call.

using (Sprite s = new Sprite(device))
{
    s.Begin(SpriteFlags.None);
    s.Draw(renderTexture, new Rectangle(0, 0, RenderSurfaceSize,
         RenderSurfaceSize),  new Vector3(0, 0, 0), new Vector3(0, 0, 1.0f),
        Color.White);
    s.End();
}

Just to clear the confusion, I will give the full OnPaint code:

protected override void OnPaint(System.Windows.Forms.PaintEventArgs e)
{
    //This renders into the mirror
    RenderIntoSurface();
    device.Clear(ClearFlags.Target| ClearFlags.ZBuffer, 
                 System.Drawing.Color.CornflowerBlue, 1.0f, 0);
            
    device.BeginScene();            
    SetupCamera();
    mesh.DrawSubset(0);
    using (Sprite s = new Sprite(device))
    {
        s.Begin(SpriteFlags.None);
        s.Draw(renderTexture, new Rectangle(0, 0, RenderSurfaceSize,
            RenderSurfaceSize),  new Vector3(0, 0, 0), 
            new Vector3(82, 5, 1.0f), Color.White);
        s.End();
    }
    device.EndScene();
            
    device.Present();
    this.Invalidate();
}

References

I would like to mention that I have referred to the book "Managed DirectX 9 Kick Start: Graphics and Game Programming" for writing this article.

History

  • 14th July, 2006: Initial post

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here