MadMarx Tutorial 9 - Part 2         Render A Texture To Itself

Foreword.

If you prefer tutorials that come with a framework => check the other wiki tutorial series.
If you prefer tutorials that go step by step without a framework => this page should be ok.

I assume you know C++. If not, this tutorial will probably be hard to understand !

This tutorial presents only a few elements of Ogre3D.

You can download the code and media for this tutorial at the bottom of this wiki page.
This little tutorial is an extract of a bigger project which contains more tutorials & helper classes.
This bigger project is avaible there :
https://sourceforge.net/projects/so3dtools/

Also, make sure you read these tutorials in order!

Tutorial Description

In this program, I create a texture, in which I will render the scene.
I create a material that uses this texture, and I apply it on a mesh.
This technique is called a Render-To-Texture (RTT).
Please note that depending on your video card driver, you might get very different results.
For example, on my nvidia Geforce 9600M, RTT fails with 'FBO'.
So I modified the SimpleOgreInit.cpp (at the 'step 3'), so that it uses "Copy" instead of FBO.

Before root initialisation

¤				const Ogre::RenderSystemList& lRenderSystemList = mRoot->getAvailableRenderers();
				if( lRenderSystemList.size() == 0 )
				{
					MWARNING("Sorry, no rendersystem was found.");
					return result;
				}

				Ogre::RenderSystem *lRenderSystem = lRenderSystemList.at(0);

In order to have a working RTT, I check if I can select another mode than "FBO".
I suppose that the 'Copy' mode works for everyone under opengl.

¤				Ogre::ConfigOptionMap& lConfigMap = lRenderSystem->getConfigOptions();
				if(lConfigMap.find("RTT Preferred Mode") != lConfigMap.end())
				{
					lRenderSystem->setConfigOption("RTT Preferred Mode","Copy");

¤				}

				mRoot->setRenderSystem(lRenderSystem);

Don't forget the includes

¤#include "OGRE/OgreRoot.h"
#include "OGRE/OgreRenderSystem.h"
#include "OGRE/OgreRenderWindow.h"
#include "OGRE/OgreWindowEventUtilities.h"
#include "OGRE/OgreManualObject.h"
#include "OGRE/OgreEntity.h"
#include "OGRE/OgreMaterialManager.h"
#include "OGRE/OgreHardwarePixelBuffer.h"

After resource loading & viewport creation

Now I create a special texture. This texture allows to do what is called a
'render to texture'. Which means that you can render your scene into
it, and then use this texture as any other in a material.
In order to keep a good framerate, I set its number of mipmaps to 0.

¤	Ogre::TextureManager& lTextureManager = Ogre::TextureManager::getSingleton();
	Ogre::String lTextureName = "MyFirstRtt";
	bool lGammaCorrection = false;
	unsigned int lAntiAliasing = 0;
	unsigned int lNumMipmaps = 0;
	Ogre::TexturePtr lTextureWithRtt = lTextureManager.createManual(lTextureName, lNameOfResourceGroup, 
		Ogre::TEX_TYPE_2D, 512, 512, lNumMipmaps,
		Ogre::PF_R8G8B8, Ogre::TU_RENDERTARGET, 0, lGammaCorrection, lAntiAliasing);

now I will link this texture to a camera, by creating a viewport in the texture.

¤	Ogre::RenderTexture* lRenderTarget = NULL;
	{
		Ogre::HardwarePixelBufferSharedPtr lRttBuffer = lTextureWithRtt->getBuffer();
		lRenderTarget = lRttBuffer->getRenderTarget();
		lRenderTarget->setAutoUpdated(true);

I create a camera so that it has a beautiful '1' aspect ratio.

¤		Ogre::Camera * lRttCamera = lScene->createCamera("RttCamera");
		lRttCamera->setNearClipDistance(1.5f);
		lRttCamera->setFarClipDistance(3000.0f); 
		lRttCamera->setAspectRatio(1.0f);

I attach this camera to the same node than main camera.

¤		lCameraNode->attachObject(lRttCamera);

In the texture I will draw first a Big Blue Viewport.

¤		Ogre::Viewport* lRttViewport1 = lRenderTarget->addViewport(lRttCamera, 50, 0.00f, 0.00f, 1.0f, 1.0f);
		lRttViewport1->setAutoUpdated(true);
		Ogre::ColourValue lBgColor1(1.0,0.0,0.0,1.0);
		lRttViewport1->setBackgroundColour(lBgColor1);

In the texture I will draw then a more little red Viewport.
The previous viewport with the ZOrder at 50 will be drawn first (50 < 100).

¤		Ogre::Viewport* lRttViewport2 = lRenderTarget->addViewport(lRttCamera, 100, 0.05f, 0.05f, 0.9f, 0.9f);
		lRttViewport2->setAutoUpdated(true);
		Ogre::ColourValue lBgColor2(0.0,0.0,1.0,1.0);
		lRttViewport2->setBackgroundColour(lBgColor2);

This will draw a scene, within a scene, within a scene etc...
Because the quad that will be drawn is contained 'inside' the texture!

¤	}

now I create a material using this texture.

¤	Ogre::String lMaterialName = "MyRttMaterial";
	{

I get a reference on the material manager, which is a singleton.

¤		Ogre::MaterialManager& lMaterialManager = Ogre::MaterialManager::getSingleton();
		Ogre::MaterialPtr lMaterial = lMaterialManager.create(lMaterialName, lNameOfResourceGroup);
		Ogre::Technique * lTechnique = lMaterial->getTechnique(0);
		Ogre::Pass* lPass = lTechnique->getPass(0);
		Ogre::TextureUnitState* lTextureUnit = lPass->createTextureUnitState();
		lTextureUnit->setTextureName(lTextureName);

I use no mipmap, and I just use some bilinear filtering on the result.

¤		lTextureUnit->setNumMipmaps(0);
		lTextureUnit->setTextureFiltering(Ogre::TFO_BILINEAR);

I make the texture rotate.
The material can handle 'special effects' on the texture coordinates.
Here I rotate the texture coordinates.

¤		float lRotateSpeed = 0.01f;
		lTextureUnit->setRotateAnimation(lRotateSpeed);

Uncomment the following line to see something funnier. :-D.
lTextureUnit->setTransformAnimation(Ogre::TextureUnitState::TT_SCALE_U, Ogre::WFT_SINE, 0.9f, 0.5f, 0.0f, 0.2f);

¤	}

Now I will create a manualobject quad, and convert it to a mesh...

¤	Ogre::String lNameOfTheMesh = "MyQuad";
	{
		Ogre::ManualObject * lManualObject = NULL;
		Ogre::String lManualObjectName = "SomeQuad";
		lManualObject = lScene->createManualObject(lManualObjectName);

Always tell if you want to update the 3D (vertex/index) later or not.

¤		bool lDoIWantToUpdateItLater = false;
		lManualObject->setDynamic(lDoIWantToUpdateItLater);

BaseWhiteNoLighting is the name of a material that already exist inside Ogre.
Ogre::RenderOperation::OT_TRIANGLE_LIST is a kind of primitive.

¤		float lSize = 0.7f;
		lManualObject->begin("BaseWhiteNoLighting", Ogre::RenderOperation::OT_TRIANGLE_LIST);
		{
			float cp = 1.0f * lSize ;
			float cm = -1.0f * lSize;
			float lNumberOfTiles = 1.0f;

			lManualObject->position(cm, cp, 0.0f);// a vertex
			lManualObject->textureCoord(0.0f, 0.0f);

			lManualObject->position(cp, cp, 0.0f);// a vertex
			lManualObject->textureCoord(lNumberOfTiles, 0.0f);

			lManualObject->position(cp, cm, 0.0f);// a vertex
			lManualObject->textureCoord(lNumberOfTiles, lNumberOfTiles);

			lManualObject->position(cm, cm, 0.0f);// a vertex
			lManualObject->textureCoord(0.0, lNumberOfTiles);

			lManualObject->triangle(2,1,0);
			lManualObject->triangle(0,3,2);
		}
		lManualObject->end();
		lManualObject->convertToMesh(lNameOfTheMesh);
		lScene->destroyManualObject(lManualObject);
	}

Now I will create the corresponding entity, and its scenenode.

¤	{
		Ogre::Entity* lEntity = lScene->createEntity(lNameOfTheMesh);
		lEntity->setMaterialName(lMaterialName);

Now I attach it to a scenenode, so that it becomes present in the scene.

¤		Ogre::SceneNode* lNodeWithEntity = lNodeWithEntity = lRootSceneNode->createChildSceneNode();
		lNodeWithEntity->attachObject(lEntity);

I move the SceneNode so that it is visible to the camera.

¤		lNodeWithEntity->setPosition(0.0f, 0.0f, -1.8f);
	}

main.cpp , main.cs

NOTE This is a quick semiautomatic convert from C++ and it works with MOGRE SDK 1.7.1 r72
Any problems you encounter while working with MOGRE should be posted to the MOGRE Forum.

//TODO Fix accessViolation error on close window (Dispose correctly). Surround  prt with using(){} does not fix this

using System;
using Mogre;
using System.Collections.Generic;

namespace OgreTutorials
{
    public static class GlobalMembersMain
    {
        // In this program, I create a texture, in which I will render the scene.
        // I create a material that uses this texture, and I apply it on a mesh.
        // This technique is called a Render-To-Texture (RTT).
        // Please note that depending on your video card driver, you might get very different results.
        // For example, on my nvidia Geforce 9600M, RTT fails with 'FBO'.
        // So I modified the SimpleOgreInit.cpp (at the 'step 3'), so that it uses "Copy" instead of FBO.

        // I declare a function in which I will make my whole application.
        // This is easy then to add more things later in that function.
        // The main will call this function and take care of the global try/catch.
        public static void AnOgreApplication()
        {
            // I construct my object that will allow me to initialise Ogre easily.
            OgreEasy.SimpleOgreInit lOgreInit = new OgreEasy.SimpleOgreInit();

            if (!lOgreInit.initOgre())
            {
                Console.Write("Impossible to init Ogre correctly.");
                Console.Write("\n");
                return;
            }

            //I prefer to be able to access my variables directly.
            Root lRoot = lOgreInit.mRoot;
            RenderWindow lWindow = lOgreInit.mWindow;

            // I create a scenemanager. This is like a 'Scene', in which I can put lights, 3d objects, etc...
            // The scenemanager contains an arborescent graph of 'SceneNodes'. To manage elements of the scene,
            // I will create SceneNodes in the SceneManager, and attach the elements to the scenenodes.
            // First parameter : I select a kind of SceneManager. This may have a huge impact on performance.
            // Depending on your scene, some are better than other. The default one does no optimization at all.
            // Second parameter : I give a name to the scenemanager.
            // Note : It is easy to have more than one scenemanager (If you got 2 different scenes for example).
            SceneManager lScene = lRoot.CreateSceneManager(SceneType.ST_GENERIC, "MyFirstSceneManager");

            // The 'root SceneNode' is the only scenenode at the beginning in the SceneManager.
            // The SceneNodes can be seen as 'transformation' containers <=> it contains scale/position/rotation
            // of the objects. There is only 1 root scenenode, and all other scenenode are
            // its direct or indirect children.
            SceneNode lRootSceneNode = lScene.RootSceneNode;

            // I create a camera. It represent a 'point of view' in the scene.
            Camera lCamera = lScene.CreateCamera("MyFirstCamera");

            // I attach the camera to a new SceneNode. It will be easier then to move it in the scene.
            SceneNode lCameraNode = lRootSceneNode.CreateChildSceneNode("MyFirstCameraNode");
            lCameraNode.AttachObject(lCamera);

            // We create a viewport on a part of the window.
            // A viewport is the link between 1 camera and 1 drawing surface (here the window).
            // I can then call 'update();' on it to make it draw the Scene from the camera.
            // You can have several viewports on 1 window.
            // Check API for details on parameters.
            ushort lMainViewportZOrder = 100;
            Viewport vp = lWindow.AddViewport(lCamera, lMainViewportZOrder);

            // I want the viewport to draw the scene automatically
            // when I will call lWindow->update();
            vp.SetAutoUpdated(true);

            // I choose a color for this viewport.
            // I prefer to have a bright color, to detect holes in geometry etc...
            vp.BackgroundColour = new ColourValue(1, 0, 1);

            // I choose the visual ratio of the camera. To make it looks real, I want it the same as the viewport.
            float ratio = vp.ActualWidth / vp.ActualHeight;
            lCamera.AspectRatio = ratio;

            // I choose the clipping far& near planes. if far/near>2000, you can get z buffer problem.
            // eg : far/near = 10000/5 = 2000 . it's ok.
            // If (far/near)>2000 then you will likely get 'z fighting' issues.
            lCamera.NearClipDistance = 1.5f;
            lCamera.FarClipDistance = 3000.0f;

            // I want my window to be active
            lWindow.IsActive = true;

            // I want to update myself the content of the window, not automatically.
            lWindow.IsAutoUpdated = false;

            // Here I choose a name for a resource group. Then I create it.
            // Often, a resourcegroup is a good way to store the data corresponding
            // to a level in a game.
            string lNameOfResourceGroup = "Mission 1 : Deliver Tom";
            {
                ResourceGroupManager lRgMgr = ResourceGroupManager.Singleton;
                lRgMgr.CreateResourceGroup(lNameOfResourceGroup);

                // The function 'initialiseResourceGroup' parses scripts if any in the locations.
                lRgMgr.InitialiseResourceGroup(lNameOfResourceGroup);

                // Files that can be loaded are loaded.
                lRgMgr.LoadResourceGroup(lNameOfResourceGroup);
            }

            // Now I create a special texture. This texture allows to do what is called a
            // 'render to texture'. Which means that you can render your scene into
            // it, and then use this texture as any other in a material.
            // In order to keep a good framerate, I set its number of mipmaps to 0.
            TextureManager lTextureManager = TextureManager.Singleton;
            string lTextureName = "MyFirstRtt";
            bool lGammaCorrection = false;
            uint lAntiAliasing = 0;
            int lNumMipmaps = 0;

            TexturePtr lTextureWithRtt = lTextureManager.CreateManual(lTextureName, lNameOfResourceGroup, TextureType.TEX_TYPE_2D, 512, 512, lNumMipmaps, PixelFormat.PF_R8G8B8, (int)TextureUsage.TU_RENDERTARGET, null, lGammaCorrection, lAntiAliasing);

            // now I will link this texture to a camera, by creating a viewport in the texture.
            RenderTexture lRenderTarget = null;
            {
                HardwarePixelBufferSharedPtr lRttBuffer = lTextureWithRtt.GetBuffer();
                lRenderTarget = lRttBuffer.GetRenderTarget();
                lRenderTarget.IsAutoUpdated = true;

                // I create a camera so that it has a beautiful '1' aspect ratio.
                Camera lRttCamera = lScene.CreateCamera("RttCamera");
                lRttCamera.NearClipDistance = 1.5f;
                lRttCamera.FarClipDistance = 3000.0f;
                lRttCamera.AspectRatio = 1.0f;

                // I attach this camera to the same node than main camera.
                lCameraNode.AttachObject(lRttCamera);

                // In the texture I will draw first a Big Blue Viewport.
                Viewport lRttViewport1 = lRenderTarget.AddViewport(lRttCamera, 50, 0.00f, 0.00f, 1.0f, 1.0f);
                lRttViewport1.SetAutoUpdated(true);
                lRttViewport1.BackgroundColour = new ColourValue(1.0f, 0.0f, 0.0f, 1.0f);

                // In the texture I will draw then a more little red Viewport.
                // The previous viewport with the ZOrder at 50 will be drawn first (50 < 100).
                Viewport lRttViewport2 = lRenderTarget.AddViewport(lRttCamera, 100, 0.05f, 0.05f, 0.9f, 0.9f);
                lRttViewport2.SetAutoUpdated(true);
                lRttViewport2.BackgroundColour = new ColourValue(0.0f, 0.0f, 1.0f, 1.0f);

                // This will draw a scene, within a scene, within a scene etc...
                // Because the quad that will be drawn is contained 'inside' the texture!
            }

            // now I create a material using this texture.
            string lMaterialName = "MyRttMaterial";
            {
                // I get a reference on the material manager, which is a singleton.
                MaterialManager lMaterialManager = MaterialManager.Singleton;
                MaterialPtr lMaterial = lMaterialManager.Create(lMaterialName, lNameOfResourceGroup);
                Technique lTechnique = lMaterial.GetTechnique(0);
                Pass lPass = lTechnique.GetPass(0);
                TextureUnitState lTextureUnit = lPass.CreateTextureUnitState();
                lTextureUnit.SetTextureName(lTextureName);
                //I use no mipmap, and I just use some bilinear filtering on the result.
                lTextureUnit.NumMipmaps = 0;
                lTextureUnit.SetTextureFiltering(TextureFilterOptions.TFO_BILINEAR);

                // I make the texture rotate.
                // The material can handle 'special effects' on the texture coordinates.
                // Here I rotate the texture coordinates.
                float lRotateSpeed = 0.01f;
                lTextureUnit.SetRotateAnimation(lRotateSpeed);
                // Uncomment the following line to see something funnier. :-D.
                //NOTE lTextureUnit.SetTransformAnimation(TextureUnitState.TextureTransformType.TT_SCALE_U,WaveformType.WFT_SINE, 0.9f, 0.5f, 0.0f, 0.2f);
            }

            // Now I will create a manualobject quad, and convert it to a mesh...
            string lNameOfTheMesh = "MyQuad";
            {
                ManualObject lManualObject = null;
                string lManualObjectName = "SomeQuad";
                lManualObject = lScene.CreateManualObject(lManualObjectName);

                // Always tell if you want to update the 3D (vertex/index) later or not.
                bool lDoIWantToUpdateItLater = false;
                lManualObject.Dynamic = lDoIWantToUpdateItLater;

                // BaseWhiteNoLighting is the name of a material that already exist inside
                // Ogre::RenderOperation::OT_TRIANGLE_LIST is a kind of primitive.
                float lSize = 0.7f;
                lManualObject.Begin("BaseWhiteNoLighting", RenderOperation.OperationTypes.OT_TRIANGLE_LIST);
                {
                    float cp = 1.0f * lSize;
                    float cm = -1.0f * lSize;
                    float lNumberOfTiles = 1.0f;

                    lManualObject.Position(cm, cp, 0.0f); // a vertex
                    lManualObject.TextureCoord(0.0f, 0.0f);

                    lManualObject.Position(cp, cp, 0.0f); // a vertex
                    lManualObject.TextureCoord(lNumberOfTiles, 0.0f);

                    lManualObject.Position(cp, cm, 0.0f); // a vertex
                    lManualObject.TextureCoord(lNumberOfTiles, lNumberOfTiles);

                    lManualObject.Position(cm, cm, 0.0f); // a vertex
                    lManualObject.TextureCoord(0.0f, lNumberOfTiles);

                    lManualObject.Triangle(2, 1, 0);
                    lManualObject.Triangle(0, 3, 2);
                }
                lManualObject.End();
                lManualObject.ConvertToMesh(lNameOfTheMesh);
                lScene.DestroyManualObject(lManualObject);
            }

            // Now I will create the corresponding entity, and its scenenode.
            {
                Entity lEntity = lScene.CreateEntity(lNameOfTheMesh);
                lEntity.SetMaterialName(lMaterialName);
                // Now I attach it to a scenenode, so that it becomes present in the scene.
                SceneNode lNodeWithEntity = lRootSceneNode.CreateChildSceneNode();
                lNodeWithEntity.AttachObject(lEntity);
                // I move the SceneNode so that it is visible to the camera.
                lNodeWithEntity.Position = new Vector3(0.0f, 0.0f, -1.8f);
            }

            // cleaning of windows events managed by Ogre::WindowEventUtilities::...
            // I call it after a 'pause in window updating', in order to maintain smoothness.
            // Explanation : if you clicked 2000 times when the windows was being created, there are
            // at least 2000 messages created by the OS to listen to. This is made to clean them.
            lRoot.ClearEventTimes();

            // I wait until the window is closed.
            // The "message pump" thing is something you will see in most GUI application.
            // It allow the binding of messages between the application and the OS.
            // These messages are most of the time : keystroke, mouse moved, ... or window closed.
            // If I don't do this, the message are never caught, and the window won't close.
            while (!lOgreInit.mWindow.IsClosed)
            {
                // Drawings
                // the window update its content.
                // each viewport that is 'autoupdated' will be redrawn now,
                // in order given by its z-order.
                lWindow.Update(false);

                // The drawn surface is then shown on the screen
                // (google "double buffering" if you want more details).
                // I always use vertical synchro.
                bool lVerticalSynchro = true;
                lWindow.SwapBuffers(lVerticalSynchro);

                // This update some internal counters and listeners.
                // Each render surface (window/rtt/mrt) that is 'auto-updated' has got its 'update' function called.
                lRoot.RenderOneFrame();

                WindowEventUtilities.MessagePump();
            }

            // Let's cleanup!
            {
                lWindow.RemoveAllViewports();
            }
            {
                lScene.DestroyAllCameras();
                lScene.DestroyAllManualObjects();
                lScene.DestroyAllEntities();
                lScene.DestroyAllLights();
                lRootSceneNode.RemoveAndDestroyAllChildren();
            }
            {
                RenderSystem lRenderSystem = lRoot.RenderSystem;
                lRenderSystem.DestroyRenderTarget(lTextureName);
            }
            {
                ResourceGroupManager lRgMgr = ResourceGroupManager.Singleton;
                lRgMgr.DestroyResourceGroup(lNameOfResourceGroup);
            }

            return;
        }

        public static void Main()
        {
            try
            {
                AnOgreApplication();
            }
            catch (Exception e)
            {
                OgreEasy.SimpleOgreInit.ShowOgreException();
            }
        }
    }
}



// The classes of this tutorial are put in a namespace called OgreEasy.
// So that it can be reused without difficulty.
namespace OgreEasy
{
    /// \brief This class contains a function that help to initialise Ogre3d in one go.
    /// the code of this function is inspired by the first tutorial of OgreEasy.
    /// It was written for tutorial purpose.
    public class SimpleOgreInit
    {
        // The constructor does nothing but initialisation to NULL or empty values.
        // the constructor uses the initialisation list to have a proper state.
        public SimpleOgreInit()
        {
            mRoot = null;
            mWindow = null;
        }

        // the destructor frees memory allocated by the class.
        //public void Dispose() //TODO
        //{
        //    mRoot.Dispose();
        //    mRoot = null;
        //    mWindow = null;
        //    //mRoot.Reset(); // I was not obliged to do that...
        //}

        ///\brief  This function will create 1 ogre root and 1 window and store them in its members mRoot and mWindow.
        ///\return false if an error occurs, true otherwise.
        public bool initOgre()
        {
            bool result = false;
            // This try/catch will catch potential exception launched by ogre or by my program.
            // Ogre can launch 'Ogre::Exception' for example.
            try
            {
                // STEP 1/ First, we will need to create the Ogre::Root object.
                // It is an object that must be created to use ogre correctly, and delete once we are finished using

                // This is the name of an optionnal textual configuration file for the rendersystem.
                // I won't use it.
                string lConfigFileName = "";
                // This is the name of an optionnal textual configuration file, which lists the available plugins.
                // I won't use it.
                string lPluginsFileName = "";
                // This is the name of the log file. A log file is a file in which you can write things during the program execution.
                // Ogre use it to display general informations about the rendersystem.
                // You are not obliged to generate one, and ogre can even transmit the log data to you own class if you want.
                // Here we only ask the root to create the file.
                string lLogFileName = "Ogre.log";

                mRoot = new Root(lConfigFileName, lPluginsFileName, lLogFileName);

                // STEP 2/ Then we need to load plugins. It means that there are functions that are stored inside dynamic libraries.
                // These libraries are .dll or .so files. Most projects Ogre Project do not need all functions to be usable.
                // That way, only a subset of all function can be loaded. It also means you can create your own plugins if you want.
                // If you want to know more on the subject, you 'll need to dig into a C++ tutorial.
                // Anyway, for our use, we will need to load at least a 'RenderSystem' plugin, which means something to drive opengl or directx.
                // The basic plugins you are the most likely to use are the RenderSystems, the particle FX and the Cgprogram.
                {
                    // Here I list all the plugins I want to load.
                    // I let those I don't want to use in comments.
                    // Opengl rendersystem is supposed to work everywhere.
                    // But in reality a rendersystem may fail on your computer.
                    // It is likely do to bad/old graphic card driver/installation,
                    // or too old directx version on windows (try update).
                    // Often, when one rendersystem fail, the other at least kind-a-work.
                    // I put them in a std::vector, because then I can factorise operations and calls (do a 'for').
                    List<string> lPluginNames = new List<string>
					                                {
					                                    "RenderSystem_GL",
					                                    //"RenderSystem_Direct3D9",
					                                    "Plugin_ParticleFX",
					                                    "Plugin_CgProgramManager",
					                                    //"Plugin_PCZSceneManager",
					                                    //"Plugin_OctreeZone",
					                                    "Plugin_OctreeSceneManager",
					                                    //"Plugin_BSPSceneManager"
					                                };

                    {
                        foreach (var lPluginName in lPluginNames)
                        {
                            //TODO if (OGRE_DEBUG_MODE)  lPluginName + "_d"
                            mRoot.LoadPlugin(lPluginName);
                        }
                    }
                }

                // STEP 3/ Then, we can select from the loaded plugins the unique RenderSystem we want to use.
                {
                    // the root provide a method if you want to select
                    // the rendersystem and its options visually (lRoot->showConfigDialog()).
                    // in that case, you don't need to set the render system manually
                    Const_RenderSystemList lRenderSystemList = mRoot.GetAvailableRenderers();
                    if (lRenderSystemList.Count == 0)
                    {
                        System.Windows.Forms.MessageBox.Show("Sorry, no rendersystem was found.");
                        return result;
                    }

                    RenderSystem lRenderSystem = lRenderSystemList[0];

                    // In order to have a working RTT, I check if I can select another mode than "FBO".
                    // I suppose that the 'Copy' mode works for everyone under opengl.
                    ConfigOptionMap lConfigMap = lRenderSystem.GetConfigOptions();
                    if (lConfigMap.Find("RTT Preferred Mode") != lConfigMap.End())
                    {
                        lRenderSystem.SetConfigOption("RTT Preferred Mode", "Copy");
                        //lRenderSystem.SetConfigOption("RTT Preferred Mode","PBuffer");
                        //lRenderSystem.SetConfigOption("RTT Preferred Mode","FBO");
                    }

                    mRoot.RenderSystem = lRenderSystem;
                }

                // STEP 4/ When the RenderSystem is selected, we can initialise the Root. The root can be initialised only when a rendersystem has been selected.
                {
                    // I can create a window automatically, but I won't do it.
                    bool lCreateAWindowAutomatically = false;
                    // name of the automatically generated window. empty for me.
                    string lWindowTitle = "";
                    // custom capabilities of the rendersystem. It's a feature for advanced use.
                    string lCustomCapacities = "";
                    mRoot.Initialise(lCreateAWindowAutomatically, lWindowTitle, lCustomCapacities);
                }

                // STEP 5/ Then we can ask to the RenderSystem to create a window.
                {
                    string lWindowTitle = "Hello Ogre World";
                    uint lSizeX = 800;
                    uint lSizeY = 600;
                    //I don't want to use fullscreen during development.
                    bool lFullscreen = false;
                    // This is just an example of parameters that we can put. Check the API for more details.
                    NameValuePairList lParams = new NameValuePairList();
                    // fullscreen antialiasing. (check wikipedia if needed).
                    lParams["FSAA"] = "0";
                    // vertical synchronisation will prevent some image-tearing, but also
                    // will provide smooth framerate in windowed mode.(check wikipedia if needed).
                    lParams["vsync"] = "true";
                    mWindow = mRoot.CreateRenderWindow(lWindowTitle, lSizeX, lSizeY, lFullscreen, lParams);
                }
                result = true;
            }
            catch (Exception e) //TODO
            {
                ShowOgreException();
                result = false;
            }

            return result;
        }

        // I put the member in public because there is no need to put them private in these tutorials.
        // It will allow very simple access to these useful members.
        ///\brief the root of ogre will be contained in this member.
        /// it will be initialised in initOgre().
        public Root mRoot = new Root();
        ///\brief the window created in the initOgre(). NULL otherwise.
        /// This is just a handle, not a real aggregation.
        /// The destruction of the Root will imply its destruction.
        public RenderWindow mWindow;

        public static void ShowOgreException()
        {
            if (OgreException.IsThrown)
                System.Windows.Forms.MessageBox.Show(OgreException.LastException.FullDescription, "An exception has occured!", System.Windows.Forms.MessageBoxButtons.OK, System.Windows.Forms.MessageBoxIcon.Error);
        }
    }
}