Skip to main content

History: MadMarx Tutorial 9 - Part 3

Source of version: 7 (current)

Copy to clipboard
            !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!

{maketoc}

!!Tutorial Description
This program is mainly the same as the previous RenderToTexture tutorial,
but this time I use 'FBO' (frame buffer object).
To be able to use 'FBO' kind of render to ((-Texture|texture)), I am not allowed to
make a ((-Texture|texture)) render to itself (on my graphic card at least...).
As a consequence : I create here an intermediate ((-Texture|texture)), that will receive the result
of the render to ((-Texture|texture)). So, in this program we see how to copy content from one ((-Texture|texture))
to another ((-Texture|texture)), directly on the GPU.

Conclusion : don't trust too much your graphic card's pilot.

!!During GL render system configuration, before root initialisation

{CODE(wrap="1",colors="c++")} 
¤					lRenderSystem->setConfigOption("RTT Preferred Mode","FBO");
{CODE} 
!! After viewport creation & resource loading
Now I create a special ((-Texture|texture)). This ((-Texture|texture)) allows to do what is called a
'render to ((-Texture|texture))'. Which means that you can render your scene into
it, and then use this ((-Texture|texture)) as any other in a ((-Material|material)).
In order to keep a good framerate, I set its number of mipmaps to 0.

{CODE(wrap="1",colors="c++")} 
¤	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);
{CODE} 
I create an intermediate ((-Texture|texture)), that will receive a copy of the rtt ((-Texture|texture)).
Since I will dynamically write in this ((-Texture|texture)), I have chosen the ((-Texture|texture)) usage Ogre::TU_DYNAMIC_WRITE_ONLY.
There are very detailed informations on ((-Texture|texture)) usage & hardware buffers in the ogre3D manual.

{CODE(wrap="1",colors="c++")} 
¤	Ogre::String lIntermediateTextureName = "IntermediateTexture";
	Ogre::TexturePtr lIntermediateTexture = lTextureManager.createManual(lIntermediateTextureName, lNameOfResourceGroup, 
		Ogre::TEX_TYPE_2D, 512, 512, lNumMipmaps,
		Ogre::PF_R8G8B8, Ogre::TU_DYNAMIC_WRITE_ONLY, 0, lGammaCorrection, lAntiAliasing);
{CODE} 
now I will link this ((-Texture|texture)) to a ((-Camera|camera)), by creating a ((-Viewport|viewport)) in the ((-Texture|texture)).

{CODE(wrap="1",colors="c++")} 
¤	Ogre::RenderTexture* lRenderTarget = NULL;
	{
		Ogre::HardwarePixelBufferSharedPtr lRttBuffer = lTextureWithRtt->getBuffer();
		lRenderTarget = lRttBuffer->getRenderTarget();
		lRenderTarget->setAutoUpdated(false);
{CODE} 
I create a ((-Camera|camera)) so that it has a beautiful '1' aspect ratio.

{CODE(wrap="1",colors="c++")} 
¤		Ogre::Camera * lRttCamera = lScene->createCamera("RttCamera");
		lRttCamera->setNearClipDistance(1.5f);
		lRttCamera->setFarClipDistance(3000.0f); 
		lRttCamera->setAspectRatio(1.0f);
{CODE} 
I attach this ((-Camera|camera)) to the same node than main ((-Camera|camera)).

{CODE(wrap="1",colors="c++")} 
¤		lCameraNode->attachObject(lRttCamera);
{CODE} 
In the ((-Texture|texture)) I will draw first a Big Blue ((-Viewport|Viewport)).

{CODE(wrap="1",colors="c++")} 
¤		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);
{CODE} 
In the ((-Texture|texture)) I will draw then a more little red ((-Viewport|Viewport)).
The previous ((-Viewport|viewport)) with the ZOrder at 50 will be drawn first (50 < 100).

{CODE(wrap="1",colors="c++")} 
¤		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);
	}
{CODE} 
This ((-Material|material)) will use the intermediate ((-Texture|texture)).

{CODE(wrap="1",colors="c++")} 
¤	Ogre::String lMaterialName = "MyRttMaterial";
	{
{CODE} 
I get a reference on the ((-Material|material)) manager, which is a ((-Singleton|singleton)).

{CODE(wrap="1",colors="c++")} 
¤		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(lIntermediateTextureName);
{CODE} 
I use no mipmap, and I just use some bilinear filtering on the result.

{CODE(wrap="1",colors="c++")} 
¤		lTextureUnit->setNumMipmaps(0);
		lTextureUnit->setTextureFiltering(Ogre::TFO_BILINEAR);
{CODE} 
I make the ((-Texture|texture)) rotate.
The ((-Material|material)) can handle 'special effects' on the ((-Texture|texture)) coordinates.
Here I rotate the ((-Texture|texture)) coordinates.

{CODE(wrap="1",colors="c++")} 
¤		float lRotateSpeed = 0.01f;
		lTextureUnit->setRotateAnimation(lRotateSpeed);
{CODE} 
!!Entity creation
Now I will create the corresponding ((-Entity|entity)), and its scenenode.

{CODE(wrap="1",colors="c++")} 
¤	{
		Ogre::Entity* lEntity = lScene->createEntity(lNameOfTheMesh);
		lEntity->setMaterialName(lMaterialName);
{CODE} 
Now I attach it to a scenenode, so that it becomes present in the scene.

{CODE(wrap="1",colors="c++")} 
¤		Ogre::SceneNode* lNodeWithEntity = lNodeWithEntity = lRootSceneNode->createChildSceneNode();
		lNodeWithEntity->attachObject(lEntity);
{CODE} 
I move the ((-SceneNode|SceneNode)) so that it is visible to the ((-Camera|camera)).

{CODE(wrap="1",colors="c++")} 
¤		lNodeWithEntity->setPosition(0.0f, 0.0f, -1.8f);
	}
{CODE} 
!!Full while() loop

{CODE(wrap="1",colors="c++")} 
¤	while(!lOgreInit.mWindow->isClosed())
	{
{CODE} 
Drawings

First I update the rendertarget, and then I make the copy of its content.
I show 2 versions of the copying.

{CODE(wrap="1",colors="c++")} 
¤		lRenderTarget->update();
		int lCopyingVersion = 1;
		if(0 == lCopyingVersion)
		{
{CODE} 
this version resizes the ((-Texture|texture)) if needed.

{CODE(wrap="1",colors="c++")} 
¤			lTextureWithRtt->copyToTexture(lIntermediateTexture);
		}else if(1 == lCopyingVersion)
		{
{CODE} 
This version crop a part of the image to the other part.
Since I use the ((-Texture|texture)) same size there is no problem.
The HardwarePixelBuffer is a pixel buffer, there is at least one per ((-Texture|texture)).
I will copy the content from the RTT-buffer to the intermediate ((-Texture|texture))-buffer.

{CODE(wrap="1",colors="c++")} 
¤			Ogre::HardwarePixelBufferSharedPtr lBufferRtt = lTextureWithRtt->getBuffer(0,0);
			Ogre::HardwarePixelBufferSharedPtr lBufferIntermediate = lIntermediateTexture->getBuffer(0,0);
			size_t left = 0;
			size_t top = 0;
			size_t right = 511;
			size_t bottom = 511;
			Ogre::Image::Box lSourceBox(left, top, right, bottom);
			Ogre::Image::Box lDestinationBox(left, top, right, bottom);

			lBufferIntermediate->blit(lBufferRtt, lSourceBox, lDestinationBox);
		}
{CODE} 
the window update its content.
each ((-Viewport|viewport)) that is 'autoupdated' will be redrawn now,
in order given by its z-order.

{CODE(wrap="1",colors="c++")} 
¤		lWindow->update(false);
{CODE} 
The drawn surface is then shown on the screen
(google "double buffering" if you want more details).
I always use vertical synchro.

{CODE(wrap="1",colors="c++")} 
¤		bool lVerticalSynchro = true;
		lWindow->swapBuffers(lVerticalSynchro);	
{CODE} 
This update some internal counters and listeners.
Each render surface (window/rtt/mrt) that is 'auto-updated' has got its 'update' function called.

{CODE(wrap="1",colors="c++")} 
¤		lRoot->renderOneFrame();

		Ogre::WindowEventUtilities::messagePump();
	}
{CODE} 

! main.cpp , main.cs
{VERSIONS(nav="y",default="c++")}
{CODE(wrap="1",colors="c++")} 
// This program is mainly the same as the previous RenderToTexture tutorial,
// but this time I use 'FBO' (frame buffer object).
// To be able to use 'FBO' kind of render to texture, I am not allowed to 
// make a texture render to itself (on my graphic card at least...).
// As a consequence : I create here an intermediate texture, that will receive the result
// of the render to texture. So, in this program we see how to copy content from one texture 
// to another texture, directly on the GPU.
//
// Conclusion : don't trust too much your graphic card's pilot.

// I will use std::auto_ptr so I need to include 'memory'. 
// If you don't know std::auto_ptr, you should check some C++ tutorials/lesson on this matter.
#include <memory>
// I will check for std::exception. If you don't know what exception/try/catch means, you should learn C++ first.
#include <exception>

// These are some files that we need to include to use Ogre3D. Note that you can at the beginnings use directly "Ogre.h", to include lots of commonly used classes.
#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"

//Here I include my other files, like the one for SimpleOgreInit...
#include "SimpleOgreInit.h"

#include "EasyDefines.h"

// 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.
void AnOgreApplication()
{
	// I construct my object that will allow me to initialise Ogre easily.
	OgreEasy::SimpleOgreInit lOgreInit;

	if(!lOgreInit.initOgre())
	{
		std::cout<<"Impossible to init Ogre correctly."<<std::endl;
		return;
	}

	//I prefer to be able to access my variables directly.
	Ogre::Root* lRoot = lOgreInit.mRoot.get();
	Ogre::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).
	Ogre::SceneManager* lScene = lRoot->createSceneManager(Ogre::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.
	Ogre::SceneNode* lRootSceneNode = lScene->getRootSceneNode();

	// I create a camera. It represent a 'point of view' in the scene.
	Ogre::Camera* lCamera = lScene->createCamera("MyFirstCamera");

	// I attach the camera to a new SceneNode. It will be easier then to move it in the scene.
	Ogre::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.
	unsigned short lMainViewportZOrder = 100;
	Ogre::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->setBackgroundColour(Ogre::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 = float(vp->getActualWidth()) / float(vp->getActualHeight());
	lCamera->setAspectRatio(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->setNearClipDistance(1.5f);
	lCamera->setFarClipDistance(3000.0f); 

	// I want my window to be active
	lWindow->setActive(true);

	// I want to update myself the content of the window, not automatically.
	lWindow->setAutoUpdated(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.
	Ogre::String lNameOfResourceGroup = "Mission 1 : Deliver Tom";
	{
		Ogre::ResourceGroupManager& lRgMgr = Ogre::ResourceGroupManager::getSingleton();
		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.
	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);
	
	// I create an intermediate texture, that will receive a copy of the rtt texture.
	// Since I will dynamically write in this texture, I have chosen the texture usage Ogre::TU_DYNAMIC_WRITE_ONLY.
	// There are very detailed informations on texture usage & hardware buffers in the ogre3D manual.
	Ogre::String lIntermediateTextureName = "IntermediateTexture";
	Ogre::TexturePtr lIntermediateTexture = lTextureManager.createManual(lIntermediateTextureName, lNameOfResourceGroup, 
		Ogre::TEX_TYPE_2D, 512, 512, lNumMipmaps,
		Ogre::PF_R8G8B8, Ogre::TU_DYNAMIC_WRITE_ONLY, 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(false);

		// 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 material will use the intermediate 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(lIntermediateTextureName);
		//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);
	}

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

		// First I update the rendertarget, and then I make the copy of its content.
		// I show 2 versions of the copying.
		lRenderTarget->update();
		int lCopyingVersion = 1;
		if(0 == lCopyingVersion)
		{
			// this version resizes the texture if needed.
			lTextureWithRtt->copyToTexture(lIntermediateTexture);
		}else if(1 == lCopyingVersion)
		{
			// This version crop a part of the image to the other part.
			// Since I use the texture same size there is no problem.
			// The HardwarePixelBuffer is a pixel buffer, there is at least one per texture.
			// I will copy the content from the RTT-buffer to the intermediate texture-buffer.
			Ogre::HardwarePixelBufferSharedPtr lBufferRtt = lTextureWithRtt->getBuffer(0,0);
			Ogre::HardwarePixelBufferSharedPtr lBufferIntermediate = lIntermediateTexture->getBuffer(0,0);
			size_t left = 0;
			size_t top = 0;
			size_t right = 511;
			size_t bottom = 511;
			Ogre::Image::Box lSourceBox(left, top, right, bottom);
			Ogre::Image::Box lDestinationBox(left, top, right, bottom);

			lBufferIntermediate->blit(lBufferRtt, lSourceBox, lDestinationBox);
		}

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

		Ogre::WindowEventUtilities::messagePump();
	}

	// Let's cleanup!
	{
		lWindow->removeAllViewports();
	}
	{
		lScene->destroyAllCameras();
		lScene->destroyAllManualObjects();
		lScene->destroyAllEntities();
		lScene->destroyAllLights();
		lRootSceneNode->removeAndDestroyAllChildren();
	}
	{
		Ogre::RenderSystem* lRenderSystem = lRoot->getRenderSystem();
		lRenderSystem->destroyRenderTarget(lTextureName);
	}
	{
		Ogre::ResourceGroupManager& lRgMgr = Ogre::ResourceGroupManager::getSingleton();
		lRgMgr.destroyResourceGroup(lNameOfResourceGroup);
	}

	return;
}

int main()
{
	try
	{
		AnOgreApplication();
		std::cout<<"end of the program"<<std::endl;
	}catch(Ogre::Exception &e)
	{
		MWARNING("!!!!Ogre::Exception!!!!\n"<<e.what());
	}catch(std::exception &e)
	{
		MWARNING("!!!!std::exception!!!!\n"<<e.what());
	}
	return 0;
}

{CODE} 
Full program sources :
http://sourceforge.net/projects/so3dtools/files/Ogre3DWiki/09_RenderToTexture2.7z/download

---(C#)---
__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 [http://www.ogre3d.org/addonforums/viewforum.php?f=8|MOGRE Forum].

{CODE(wrap="1", colors="c#")}
//NOTE This program is similar to previous tutorial. You may use merge (e.g. WinMerge) to view difference

//TODO Dispose correctly without accessViolation error. Surround  prt with using(){} does not fix this

using System;
using System.Windows.Forms;
using Mogre;
using System.Collections.Generic;

public static class GlobalMembersMain
{
    // This program is mainly the same as the previous RenderToTexture tutorial,
    // but this time I use 'FBO' (frame buffer object).
    // To be able to use 'FBO' kind of render to texture, I am not allowed to 
    // make a texture render to itself (on my graphic card at least...).
    // As a consequence : I create here an intermediate texture, that will receive the result
    // of the render to texture. So, in this program we see how to copy content from one texture 
    // to another texture, directly on the GPU.
    //
    // Conclusion : don't trust too much your graphic card's pilot.

    // 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())
        {
            MessageBox.Show("Impossible to init Ogre correctly.");
            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);

        // I create an intermediate texture, that will receive a copy of the rtt texture.
        // Since I will dynamically write in this texture, I have chosen the texture usage TextureUsage.TU_DYNAMIC_WRITE_ONLY.
        // There are very detailed informations on texture usage & hardware buffers in the ogre3D manual.
        string lIntermediateTextureName = "IntermediateTexture";
        TexturePtr lIntermediateTexture = lTextureManager.CreateManual(lIntermediateTextureName, lNameOfResourceGroup, TextureType.TEX_TYPE_2D, 512, 512, lNumMipmaps, PixelFormat.PF_R8G8B8, (int)TextureUsage.TU_DYNAMIC_WRITE_ONLY, null, lGammaCorrection, lAntiAliasing);


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

            // 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 material will use the intermediate 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(lIntermediateTextureName);
            //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.
            // 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::OperationTypes.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

            // First I update the rendertarget, and then I make the copy of its content.
            // I show 2 versions of the copying.
            lRenderTarget.Update();
            int lCopyingVersion = 1;
            if (0 == lCopyingVersion)
            {
                // this version resizes the texture if needed.
                lTextureWithRtt.CopyToTexture(lIntermediateTexture);
            }
            else if (1 == lCopyingVersion)
            {
                // This version crop a part of the image to the other part.
                // Since I use the texture same size there is no problem.
                // The HardwarePixelBuffer is a pixel buffer, there is at least one per texture.
                // I will copy the content from the RTT-buffer to the intermediate texture-buffer.
                HardwarePixelBufferSharedPtr lBufferRtt = lTextureWithRtt.GetBuffer(0, 0);
                HardwarePixelBufferSharedPtr lBufferIntermediate = lIntermediateTexture.GetBuffer(0, 0);
                uint left = 0;
                uint top = 0;
                uint right = 511;
                uint bottom = 511;

                Box lSourceBox = new Box(left, top, right, bottom);
                Box lDestinationBox = new Box(left, top, right, bottom);

                lBufferIntermediate.Blit(lBufferRtt, lSourceBox, lDestinationBox);
            }

            // 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)
                MessageBox.Show(OgreException.LastException.FullDescription, "An exception has occured!", MessageBoxButtons.OK, MessageBoxIcon.Error);
        }
    }
}



{CODE} 
{VERSIONS}