1 /*
2 -----------------------------------------------------------------------------
3 This source file is part of OGRE
4     (Object-oriented Graphics Rendering Engine)
5 For the latest info, see http://www.ogre3d.org/
6 
7 Copyright (c) 2000-2013 Torus Knot Software Ltd
8 Also see acknowledgements in Readme.html
9 
10 You may use this sample code for anything you like, it is not covered by the
11 same license as the rest of the engine.
12 -----------------------------------------------------------------------------
13 */
14 
15 #ifndef _CompositorDemo_H_
16 #define _CompositorDemo_H_
17 
18 #include "OgreConfigFile.h"
19 #include "OgreStringConverter.h"
20 #include "OgreException.h"
21 
22 #include "SdkSample.h"
23 #include "SamplePlugin.h"
24 
25 using namespace Ogre;
26 using namespace OgreBites;
27 
28 #define COMPOSITORS_PER_PAGE 8
29 
30 class _OgreSampleClassExport Sample_Compositor : public SdkSample
31 {
32 public:
33 	Sample_Compositor();
34 
35     void setupContent(void);
36     void cleanupContent(void);
37     StringVector getRequiredPlugins();
38 
39 	bool frameRenderingQueued(const FrameEvent& evt);
40 
41 	void checkBoxToggled(OgreBites::CheckBox * box);
42 	void buttonHit(OgreBites::Button* button);
43 	void itemSelected(OgreBites::SelectMenu* menu);
44 
45 protected:
46 
47 	void setupView(void);
48 	void setupControls(void);
49     void setupScene(void);
50     void createEffects(void);
51 	void createTextures(void);
52 
53 	void registerCompositors();
54 	void changePage(size_t pageNum);
55 
56 	SceneNode * mSpinny;
57 	StringVector mCompositorNames;
58 	size_t mActiveCompositorPage;
59 	size_t mNumCompositorPages;
60 
61 	//Used to unregister compositor logics and free memory
62 	typedef map<String, CompositorLogic*>::type CompositorLogicMap;
63 	CompositorLogicMap mCompositorLogics;
64 
65 	String mDebugCompositorName;
66 	SelectMenu* mDebugTextureSelectMenu;
67 	TextureUnitState* mDebugTextureTUS;
68 
69 };
70 
71 /**
72     @file
73         Compositor.cpp
74     @brief
75         Shows OGRE's Compositor feature
76 	@author
77 		W.J. :wumpus: van der Laan
78 			Ogre compositor framework
79 		Manuel Bua
80 			Postfilter ideas and original out-of-core implementation
81         Jeff (nfz) Doyle
82             added gui framework to demo
83 */
84 
85 #include <Ogre.h>
86 
87 #include "HelperLogics.h"
88 
89 /*************************************************************************
90 	                    Sample_Compositor Methods
91 *************************************************************************/
Sample_Compositor()92 Sample_Compositor::Sample_Compositor()
93 {
94 	mInfo["Title"] = "Compositor";
95 	mInfo["Description"] = "A demo of Ogre's post-processing framework.";
96 	mInfo["Thumbnail"] = "thumb_comp.png";
97 	mInfo["Category"] = "Effects";
98 }
99 //--------------------------------------------------------------------------
setupView()100 void Sample_Compositor::setupView()
101 {
102 	SdkSample::setupView();
103     mCamera->setPosition(Ogre::Vector3(0,0,0));
104     mCamera->lookAt(Ogre::Vector3(0,0,-300));
105     mCamera->setNearClipDistance(1);
106 }
107 //-----------------------------------------------------------------------------------
setupContent(void)108 void Sample_Compositor::setupContent(void)
109 {
110 	// Register the compositor logics
111 	// See comment in beginning of HelperLogics.h for explanation
112 	Ogre::CompositorManager& compMgr = Ogre::CompositorManager::getSingleton();
113 	mCompositorLogics["GaussianBlur"]	= new GaussianBlurLogic;
114 	mCompositorLogics["HDR"]			= new HDRLogic;
115 	mCompositorLogics["HeatVision"]		= new HeatVisionLogic;
116 	compMgr.registerCompositorLogic("GaussianBlur", mCompositorLogics["GaussianBlur"]);
117 	compMgr.registerCompositorLogic("HDR", mCompositorLogics["HDR"]);
118 	compMgr.registerCompositorLogic("HeatVision", mCompositorLogics["HeatVision"]);
119 
120 	createTextures();
121     /// Create a couple of hard coded postfilter effects as an example of how to do it
122 	/// but the preferred method is to use compositor scripts.
123 	createEffects();
124 
125 	setupScene();
126 
127 	registerCompositors();
128 
129 	setupControls();
130 
131 #if OGRE_PLATFORM != OGRE_PLATFORM_APPLE_IOS
132 	setDragLook(true);
133 #endif
134 }
getRequiredPlugins()135 StringVector Sample_Compositor::getRequiredPlugins()
136 {
137     StringVector names;
138     if (!GpuProgramManager::getSingleton().isSyntaxSupported("glsles") && !GpuProgramManager::getSingleton().isSyntaxSupported("glsl150"))
139         names.push_back("Cg Program Manager");
140     return names;
141 }
142 //-----------------------------------------------------------------------------------
registerCompositors(void)143 void Sample_Compositor::registerCompositors(void)
144 {
145 	Ogre::Viewport *vp = mViewport;
146 
147     //iterate through Compositor Managers resources and add name keys to menu
148     Ogre::CompositorManager::ResourceMapIterator resourceIterator =
149         Ogre::CompositorManager::getSingleton().getResourceIterator();
150 
151     // add all compositor resources to the view container
152     while (resourceIterator.hasMoreElements())
153     {
154         Ogre::ResourcePtr resource = resourceIterator.getNext();
155         const Ogre::String& compositorName = resource->getName();
156         // Don't add base Ogre/Scene compositor to view
157         if (Ogre::StringUtil::startsWith(compositorName, "Ogre/Scene/", false))
158             continue;
159 		// Don't add the deferred shading compositors, thats a different demo.
160 		if (Ogre::StringUtil::startsWith(compositorName, "DeferredShading", false))
161 			continue;
162 		// Don't add the SSAO compositors, thats a different demo.
163 		if (Ogre::StringUtil::startsWith(compositorName, "SSAO", false))
164 			continue;
165 		// Don't add the TestMRT compositor, it needs extra scene setup so doesn't currently work.
166 		if (Ogre::StringUtil::startsWith(compositorName, "TestMRT", false))
167 			continue;
168 
169 		mCompositorNames.push_back(compositorName);
170 		int addPosition = -1;
171 		if (compositorName == "HDR")
172 		{
173 			// HDR must be first in the chain
174 			addPosition = 0;
175 		}
176 		try
177 		{
178 			Ogre::CompositorManager::getSingleton().addCompositor(vp, compositorName, addPosition);
179 			Ogre::CompositorManager::getSingleton().setCompositorEnabled(vp, compositorName, false);
180 		} catch (...) {
181 			/// Warn user
182 			LogManager::getSingleton().logMessage("Could not load compositor " + compositorName, LML_CRITICAL);
183 		}
184     }
185 
186 	mNumCompositorPages = (mCompositorNames.size() / COMPOSITORS_PER_PAGE) +
187 		((mCompositorNames.size() % COMPOSITORS_PER_PAGE == 0) ? 0 : 1);
188 }
189 //-----------------------------------------------------------------------------------
changePage(size_t pageNum)190 void Sample_Compositor::changePage(size_t pageNum)
191 {
192 	assert(pageNum < mNumCompositorPages);
193 
194 	mActiveCompositorPage = pageNum;
195 	size_t maxCompositorsInPage = mCompositorNames.size() - (pageNum * COMPOSITORS_PER_PAGE);
196 	for (size_t i=0; i < COMPOSITORS_PER_PAGE; i++)
197 	{
198 		String checkBoxName = "Compositor_" + Ogre::StringConverter::toString(i);
199 		CheckBox* cb = static_cast<CheckBox*>(mTrayMgr->getWidget(TL_TOPLEFT, checkBoxName));
200 		if (i < maxCompositorsInPage)
201 		{
202 			String compositorName = mCompositorNames[pageNum * COMPOSITORS_PER_PAGE + i];
203 			CompositorInstance *tmpCompo = CompositorManager::getSingleton().getCompositorChain(mViewport)
204 				->getCompositor(compositorName);
205 
206 			cb->setCaption(compositorName);
207 
208 			if( tmpCompo )
209 			{
210 				cb->setChecked( tmpCompo->getEnabled(), false );
211 				cb->show();
212 			}
213 			else
214 			{
215 				cb->setChecked( false, false );
216 				cb->hide();
217 			}
218 
219 		}
220 		else
221 		{
222 			cb->hide();
223 		}
224 	}
225 
226 	OgreBites::Button* pageButton = static_cast<OgreBites::Button*>(mTrayMgr->getWidget(TL_TOPLEFT, "PageButton"));
227 	Ogre::StringStream ss;
228 	ss << "Compositors " << pageNum + 1 << "/" << mNumCompositorPages;
229 	pageButton->setCaption(ss.str());
230 }
231 //-----------------------------------------------------------------------------------
cleanupContent(void)232 void Sample_Compositor::cleanupContent(void)
233 {
234 	mDebugTextureTUS->setContentType(TextureUnitState::CONTENT_NAMED);
235 	CompositorManager::getSingleton().removeCompositorChain(mViewport);
236 	mCompositorNames.clear();
237 
238     TextureManager::getSingleton().remove("DitherTex");
239     TextureManager::getSingleton().remove("HalftoneVolume");
240 
241 	Ogre::CompositorManager& compMgr = Ogre::CompositorManager::getSingleton();
242 	CompositorLogicMap::const_iterator itor = mCompositorLogics.begin();
243 	CompositorLogicMap::const_iterator end  = mCompositorLogics.end();
244 	while( itor != end )
245 	{
246 		compMgr.unregisterCompositorLogic( itor->first );
247 		delete itor->second;
248 		++itor;
249 	}
250 	mCompositorLogics.clear();
251     MeshManager::getSingleton().remove("Myplane");
252 }
253 //-----------------------------------------------------------------------------------
setupControls(void)254 void Sample_Compositor::setupControls(void)
255 {
256 	mTrayMgr->createButton(TL_TOPLEFT, "PageButton", "Compositors", 175);
257 
258 	for (size_t i=0; i < COMPOSITORS_PER_PAGE; i++)
259 	{
260 		String checkBoxName = "Compositor_" + Ogre::StringConverter::toString(i);
261 		CheckBox* cb = mTrayMgr->createCheckBox(TL_TOPLEFT, checkBoxName, "Compositor", 175);
262 		cb->hide();
263 	}
264 
265 	changePage(0);
266 
267 	mDebugTextureSelectMenu = mTrayMgr->createThickSelectMenu(TL_TOPRIGHT, "DebugRTTSelectMenu", "Debug RTT", 180, 5);
268 	mDebugTextureSelectMenu->addItem("None");
269 
270 	mTrayMgr->createSeparator(TL_TOPRIGHT, "DebugRTTSep1");  // this is a hack to give the debug RTT a bit more room
271 
272 	DecorWidget* debugRTTPanel = mTrayMgr->createDecorWidget(TL_NONE, "DebugRTTPanel", "SdkTrays/Picture");
273 	OverlayContainer* debugRTTContainer = (OverlayContainer*)debugRTTPanel->getOverlayElement();
274 	mDebugTextureTUS = debugRTTContainer->getMaterial()->getBestTechnique()->getPass(0)->getTextureUnitState(0);
275 	//mDebugTextureTUS->setTextureName("CompositorDemo/DebugView");
276 	debugRTTContainer->setDimensions(128, 128);
277 	debugRTTContainer->getChild("DebugRTTPanel/PictureFrame")->setDimensions(144, 144);
278 	debugRTTPanel->hide();
279 
280 	mTrayMgr->createSeparator(TL_TOPRIGHT, "DebugRTTSep2");  // this is a hack to give the debug RTT a bit more room
281 
282 	mTrayMgr->showCursor();
283 	mTrayMgr->showLogo(TL_BOTTOMLEFT);
284 	mTrayMgr->toggleAdvancedFrameStats();
285 }
286 //-----------------------------------------------------------------------------------
checkBoxToggled(OgreBites::CheckBox * box)287 void Sample_Compositor::checkBoxToggled(OgreBites::CheckBox * box)
288 {
289 	if (Ogre::StringUtil::startsWith(box->getName(), "Compositor_", false))
290 	{
291 		String compositorName = box->getCaption();
292 
293 		String activeTex = mDebugTextureSelectMenu->getSelectedItem();
294 
295 		if (!box->isChecked())
296 		{
297 			//Remove the items from the debug menu and remove debug texture if from disabled compositor
298 			bool debuggingRemovedTex = StringUtil::startsWith(activeTex, compositorName, false);
299 			if (debuggingRemovedTex)
300 			{
301 				mDebugTextureTUS->setContentType(TextureUnitState::CONTENT_NAMED);
302 				mDebugTextureSelectMenu->selectItem(0, true);
303 			}
304 			for (unsigned int i = 1; i < mDebugTextureSelectMenu->getNumItems(); i++)
305 			{
306 				if (StringUtil::startsWith(mDebugTextureSelectMenu->getItems()[i], compositorName, false))
307 				{
308 					mDebugTextureSelectMenu->removeItem(i);
309 					i--;
310 				}
311 			}
312 			if (!debuggingRemovedTex)
313 			{
314 				//Selection clears itself when removing items. Restore.
315 				mDebugTextureSelectMenu->selectItem(activeTex, false);
316 			}
317 		}
318 
319 		CompositorManager::getSingleton().setCompositorEnabled(mViewport, compositorName, box->isChecked());
320 
321 
322 		if (box->isChecked())
323 		{
324 			//Add the items to the selectable texture menu
325 			CompositorInstance* instance = CompositorManager::getSingleton().getCompositorChain(mViewport)->getCompositor(compositorName);
326 			if (instance)
327 			{
328 				CompositionTechnique::TextureDefinitionIterator it = instance->getTechnique()->getTextureDefinitionIterator();
329 				while (it.hasMoreElements())
330 				{
331 					CompositionTechnique::TextureDefinition* texDef = it.getNext();
332 					size_t numTextures = texDef->formatList.size();
333 					if (numTextures > 1)
334 					{
335 						for (size_t i=0; i<numTextures; i++)
336 						{
337 							//Dirty string composition. NOT ROBUST!
338 							mDebugTextureSelectMenu->addItem(compositorName + ";" + texDef->name + ";" +
339 								Ogre::StringConverter::toString((Ogre::uint32)i));
340 						}
341 					}
342 					else
343 					{
344 						mDebugTextureSelectMenu->addItem(compositorName + ";" + texDef->name);
345 					}
346 				}
347 				mDebugTextureSelectMenu->selectItem(activeTex, false);
348 			}
349 		}
350 	}
351 }
352 //-----------------------------------------------------------------------------------
buttonHit(OgreBites::Button * button)353 void Sample_Compositor::buttonHit(OgreBites::Button* button)
354 {
355 	size_t nextPage = (mActiveCompositorPage + 1) % mNumCompositorPages;
356 	changePage(nextPage);
357 }
358 //-----------------------------------------------------------------------------------
itemSelected(OgreBites::SelectMenu * menu)359 void Sample_Compositor::itemSelected(OgreBites::SelectMenu* menu)
360 {
361 	if (menu->getSelectionIndex() == 0)
362 	{
363 		mDebugTextureTUS->setContentType(TextureUnitState::CONTENT_NAMED);
364 		mTrayMgr->getWidget("DebugRTTPanel")->hide();
365 		mTrayMgr->removeWidgetFromTray("DebugRTTPanel");
366 		return;
367 	}
368 
369 	mTrayMgr->getWidget("DebugRTTPanel")->show();
370 	mTrayMgr->moveWidgetToTray("DebugRTTPanel", TL_TOPRIGHT, static_cast<unsigned int>(mTrayMgr->getNumWidgets(TL_TOPRIGHT) - 1));
371 	StringVector parts = StringUtil::split(menu->getSelectedItem(), ";");
372 	mDebugTextureTUS->setContentType(TextureUnitState::CONTENT_COMPOSITOR);
373 
374 	if (parts.size() == 2)
375 	{
376 		mDebugTextureTUS->setCompositorReference(parts[0], parts[1]);
377 	}
378 	else
379 	{
380 		mDebugTextureTUS->setCompositorReference(parts[0], parts[1],
381 			StringConverter::parseUnsignedInt(parts[2]));
382 	}
383 }
384 //-----------------------------------------------------------------------------------
setupScene(void)385 void Sample_Compositor::setupScene(void)
386 {
387 	mSceneMgr->setShadowTechnique(Ogre::SHADOWTYPE_TEXTURE_MODULATIVE);
388 	mSceneMgr->setShadowFarDistance(1000);
389 
390 	Ogre::MovableObject::setDefaultVisibilityFlags(0x00000001);
391 
392 	// Set ambient light
393 	mSceneMgr->setAmbientLight(Ogre::ColourValue(0.3, 0.3, 0.2));
394 
395 	Ogre::Light* l = mSceneMgr->createLight("Light2");
396 	Ogre::Vector3 dir(-1,-1,0);
397 	dir.normalise();
398 	l->setType(Ogre::Light::LT_DIRECTIONAL);
399 	l->setDirection(dir);
400 	l->setDiffuseColour(1, 1, 0.8);
401 	l->setSpecularColour(1, 1, 1);
402 
403 
404 	Ogre::Entity* pEnt;
405 
406 	// House
407 	pEnt = mSceneMgr->createEntity( "1", "tudorhouse.mesh" );
408 	Ogre::SceneNode* n1 = mSceneMgr->getRootSceneNode()->createChildSceneNode(Ogre::Vector3(350, 450, -200));
409 	n1->attachObject( pEnt );
410 
411 	pEnt = mSceneMgr->createEntity( "2", "tudorhouse.mesh" );
412 	Ogre::SceneNode* n2 = mSceneMgr->getRootSceneNode()->createChildSceneNode(Ogre::Vector3(-350, 450, -200));
413 	n2->attachObject( pEnt );
414 
415 	pEnt = mSceneMgr->createEntity( "3", "knot.mesh" );
416 	mSpinny = mSceneMgr->getRootSceneNode()->createChildSceneNode(Ogre::Vector3(0, 0, 300));
417 	mSpinny->attachObject( pEnt );
418 	pEnt->setMaterialName("Examples/MorningCubeMap");
419 
420 	mSceneMgr->setSkyBox(true, "Examples/MorningSkyBox");
421 
422 
423 	Ogre::Plane plane;
424 	plane.normal = Ogre::Vector3::UNIT_Y;
425 	plane.d = 100;
426 	Ogre::MeshManager::getSingleton().createPlane("Myplane",
427 		Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, plane,
428 		1500, 1500, 10, 10, true, 1, 5, 5, Ogre::Vector3::UNIT_Z);
429 	Ogre::Entity* pPlaneEnt = mSceneMgr->createEntity( "plane", "Myplane" );
430 	pPlaneEnt->setMaterialName("Examples/Rockwall");
431 	pPlaneEnt->setCastShadows(false);
432 	mSceneMgr->getRootSceneNode()->createChildSceneNode()->attachObject(pPlaneEnt);
433 
434 	mCamera->setPosition(-400, 50, 900);
435 	mCamera->lookAt(0,80,0);
436 }
437 //-----------------------------------------------------------------------------------
frameRenderingQueued(const FrameEvent & evt)438 bool Sample_Compositor::frameRenderingQueued(const FrameEvent& evt)
439 {
440 	mSpinny->yaw(Ogre::Degree(10 * evt.timeSinceLastFrame));
441 	return SdkSample::frameRenderingQueued(evt);
442 }
443 //-----------------------------------------------------------------------------------
444 /// Create the hard coded postfilter effects
createEffects(void)445 void Sample_Compositor::createEffects(void)
446 {
447 	    // Bloom compositor is loaded from script but here is the hard coded equivalent
448 //		CompositorPtr comp = CompositorManager::getSingleton().create(
449 //				"Bloom", ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME
450 //			);
451 //		{
452 //			CompositionTechnique *t = comp->createTechnique();
453 //			{
454 //				CompositionTechnique::TextureDefinition *def = t->createTextureDefinition("rt0");
455 //				def->width = 128;
456 //				def->height = 128;
457 //				def->format = PF_A8R8G8B8;
458 //			}
459 //			{
460 //				CompositionTechnique::TextureDefinition *def = t->createTextureDefinition("rt1");
461 //				def->width = 128;
462 //				def->height = 128;
463 //				def->format = PF_A8R8G8B8;
464 //			}
465 //			{
466 //				CompositionTargetPass *tp = t->createTargetPass();
467 //				tp->setInputMode(CompositionTargetPass::IM_PREVIOUS);
468 //				tp->setOutputName("rt1");
469 //			}
470 //			{
471 //				CompositionTargetPass *tp = t->createTargetPass();
472 //				tp->setInputMode(CompositionTargetPass::IM_NONE);
473 //				tp->setOutputName("rt0");
474 //				CompositionPass *pass = tp->createPass();
475 //				pass->setType(CompositionPass::PT_RENDERQUAD);
476 //				pass->setMaterialName("Ogre/Compositor/Blur0");
477 //				pass->setInput(0, "rt1");
478 //			}
479 //			{
480 //				CompositionTargetPass *tp = t->createTargetPass();
481 //				tp->setInputMode(CompositionTargetPass::IM_NONE);
482 //				tp->setOutputName("rt1");
483 //				CompositionPass *pass = tp->createPass();
484 //				pass->setType(CompositionPass::PT_RENDERQUAD);
485 //				pass->setMaterialName("Ogre/Compositor/Blur1");
486 //				pass->setInput(0, "rt0");
487 //			}
488 //			{
489 //				CompositionTargetPass *tp = t->getOutputTargetPass();
490 //				tp->setInputMode(CompositionTargetPass::IM_PREVIOUS);
491 //				{ CompositionPass *pass = tp->createPass();
492 //				pass->setType(CompositionPass::PT_RENDERQUAD);
493 //				pass->setMaterialName("Ogre/Compositor/BloomBlend");
494 //				pass->setInput(0, "rt1");
495 //				}
496 //			}
497 //		}
498 	    // Glass compositor is loaded from script but here is the hard coded equivalent
499 		/// Glass effect
500 //		CompositorPtr comp2 = CompositorManager::getSingleton().create(
501 //				"Glass", ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME
502 //			);
503 //		{
504 //			CompositionTechnique *t = comp2->createTechnique();
505 //			{
506 //				CompositionTechnique::TextureDefinition *def = t->createTextureDefinition("rt0");
507 //				def->width = 0;
508 //				def->height = 0;
509 //				def->format = PF_R8G8B8;
510 //			}
511 //			{
512 //				CompositionTargetPass *tp = t->createTargetPass();
513 //				tp->setInputMode(CompositionTargetPass::IM_PREVIOUS);
514 //				tp->setOutputName("rt0");
515 //			}
516 //			{
517 //				CompositionTargetPass *tp = t->getOutputTargetPass();
518 //				tp->setInputMode(CompositionTargetPass::IM_NONE);
519 //				{ CompositionPass *pass = tp->createPass();
520 //				pass->setType(CompositionPass::PT_RENDERQUAD);
521 //				pass->setMaterialName("Ogre/Compositor/GlassPass");
522 //				pass->setInput(0, "rt0");
523 //				}
524 //			}
525 //		}
526 		/// Motion blur effect
527 	Ogre::CompositorPtr comp3 = Ogre::CompositorManager::getSingleton().create(
528 			"Motion Blur", Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME
529 		);
530 	{
531 		Ogre::CompositionTechnique *t = comp3->createTechnique();
532 		{
533 			Ogre::CompositionTechnique::TextureDefinition *def = t->createTextureDefinition("scene");
534 			def->width = 0;
535 			def->height = 0;
536 			def->formatList.push_back(Ogre::PF_R8G8B8);
537 		}
538 		{
539 			Ogre::CompositionTechnique::TextureDefinition *def = t->createTextureDefinition("sum");
540 			def->width = 0;
541 			def->height = 0;
542 			def->formatList.push_back(Ogre::PF_R8G8B8);
543 		}
544 		{
545 			Ogre::CompositionTechnique::TextureDefinition *def = t->createTextureDefinition("temp");
546 			def->width = 0;
547 			def->height = 0;
548 			def->formatList.push_back(Ogre::PF_R8G8B8);
549 		}
550 		/// Render scene
551 		{
552 			Ogre::CompositionTargetPass *tp = t->createTargetPass();
553 			tp->setInputMode(Ogre::CompositionTargetPass::IM_PREVIOUS);
554 			tp->setOutputName("scene");
555 		}
556 		/// Initialisation pass for sum texture
557 		{
558 			Ogre::CompositionTargetPass *tp = t->createTargetPass();
559 			tp->setInputMode(Ogre::CompositionTargetPass::IM_PREVIOUS);
560 			tp->setOutputName("sum");
561 			tp->setOnlyInitial(true);
562 		}
563 		/// Do the motion blur
564 		{
565 			Ogre::CompositionTargetPass *tp = t->createTargetPass();
566 			tp->setInputMode(Ogre::CompositionTargetPass::IM_NONE);
567 			tp->setOutputName("temp");
568 			{ Ogre::CompositionPass *pass = tp->createPass();
569 			pass->setType(Ogre::CompositionPass::PT_RENDERQUAD);
570 			pass->setMaterialName("Ogre/Compositor/Combine");
571 			pass->setInput(0, "scene");
572 			pass->setInput(1, "sum");
573 			}
574 		}
575 		/// Copy back sum texture
576 		{
577 			Ogre::CompositionTargetPass *tp = t->createTargetPass();
578 			tp->setInputMode(Ogre::CompositionTargetPass::IM_NONE);
579 			tp->setOutputName("sum");
580 			{ Ogre::CompositionPass *pass = tp->createPass();
581 			pass->setType(Ogre::CompositionPass::PT_RENDERQUAD);
582 			pass->setMaterialName("Ogre/Compositor/Copyback");
583 			pass->setInput(0, "temp");
584 			}
585 		}
586 		/// Display result
587 		{
588 			Ogre::CompositionTargetPass *tp = t->getOutputTargetPass();
589 			tp->setInputMode(Ogre::CompositionTargetPass::IM_NONE);
590 			{ Ogre::CompositionPass *pass = tp->createPass();
591 			pass->setType(Ogre::CompositionPass::PT_RENDERQUAD);
592 			pass->setMaterialName("Ogre/Compositor/MotionBlur");
593 			pass->setInput(0, "sum");
594 			}
595 		}
596 	}
597 	/// Heat vision effect
598 	Ogre::CompositorPtr comp4 = Ogre::CompositorManager::getSingleton().create(
599 			"Heat Vision", Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME
600 		);
601 	{
602 		Ogre::CompositionTechnique *t = comp4->createTechnique();
603 		t->setCompositorLogicName("HeatVision");
604 		{
605 			Ogre::CompositionTechnique::TextureDefinition *def = t->createTextureDefinition("scene");
606 			def->width = 256;
607 			def->height = 256;
608 			def->formatList.push_back(Ogre::PF_R8G8B8);
609 		}
610 		{
611 			Ogre::CompositionTechnique::TextureDefinition *def = t->createTextureDefinition("temp");
612 			def->width = 256;
613 			def->height = 256;
614 			def->formatList.push_back(Ogre::PF_R8G8B8);
615 		}
616 		/// Render scene
617 		{
618 			Ogre::CompositionTargetPass *tp = t->createTargetPass();
619 			tp->setInputMode(Ogre::CompositionTargetPass::IM_PREVIOUS);
620 			tp->setOutputName("scene");
621 		}
622 		/// Light to heat pass
623 		{
624 			Ogre::CompositionTargetPass *tp = t->createTargetPass();
625 			tp->setInputMode(Ogre::CompositionTargetPass::IM_NONE);
626 			tp->setOutputName("temp");
627 			{
628 				Ogre::CompositionPass *pass = tp->createPass();
629 				pass->setType(Ogre::CompositionPass::PT_RENDERQUAD);
630 				pass->setIdentifier(0xDEADBABE); /// Identify pass for use in listener
631 				pass->setMaterialName("Fury/HeatVision/LightToHeat");
632 				pass->setInput(0, "scene");
633 			}
634 		}
635 		/// Display result
636 		{
637 			Ogre::CompositionTargetPass *tp = t->getOutputTargetPass();
638 			tp->setInputMode(Ogre::CompositionTargetPass::IM_NONE);
639 			{
640 				Ogre::CompositionPass *pass = tp->createPass();
641 				pass->setType(Ogre::CompositionPass::PT_RENDERQUAD);
642 				pass->setMaterialName("Fury/HeatVision/Blur");
643 				pass->setInput(0, "temp");
644 			}
645 		}
646 	}
647 }
648 //--------------------------------------------------------------------------
createTextures(void)649 void Sample_Compositor::createTextures(void)
650 {
651 	using namespace Ogre;
652 
653 	TexturePtr tex = TextureManager::getSingleton().createManual(
654 		"HalftoneVolume",
655 		"General",
656 		TEX_TYPE_3D,
657 		64,64,64,
658 		0,
659 		PF_L8,
660 		TU_DYNAMIC_WRITE_ONLY
661 	);
662 
663     if(!tex.isNull())
664     {
665         HardwarePixelBufferSharedPtr ptr = tex->getBuffer(0,0);
666         ptr->lock(HardwareBuffer::HBL_DISCARD);
667         const PixelBox &pb = ptr->getCurrentLock();
668         Ogre::uint8 *data = static_cast<Ogre::uint8*>(pb.data);
669 
670         size_t height = pb.getHeight();
671         size_t width = pb.getWidth();
672         size_t depth = pb.getDepth();
673         size_t rowPitch = pb.rowPitch;
674         size_t slicePitch = pb.slicePitch;
675 
676         for (size_t z = 0; z < depth; ++z)
677         {
678             for (size_t y = 0; y < height; ++y)
679             {
680                 for(size_t x = 0; x < width; ++x)
681                 {
682                     float fx = 32-(float)x+0.5f;
683                     float fy = 32-(float)y+0.5f;
684                     float fz = 32-((float)z)/3+0.5f;
685                     float distanceSquare = fx*fx+fy*fy+fz*fz;
686                     data[slicePitch*z + rowPitch*y + x] =  0x00;
687                     if (distanceSquare < 1024.0f)
688                         data[slicePitch*z + rowPitch*y + x] +=  0xFF;
689                 }
690             }
691         }
692         ptr->unlock();
693     }
694 	Ogre::Viewport *vp = mWindow->getViewport(0);
695 
696 	TexturePtr tex2 = TextureManager::getSingleton().createManual(
697 		"DitherTex",
698 		"General",
699 		TEX_TYPE_2D,
700 		vp->getActualWidth(),vp->getActualHeight(),1,
701 		0,
702 		PF_L8,
703         TU_DYNAMIC_WRITE_ONLY
704 	);
705 
706 	HardwarePixelBufferSharedPtr ptr2 = tex2->getBuffer(0,0);
707 	ptr2->lock(HardwareBuffer::HBL_DISCARD);
708 	const PixelBox &pb2 = ptr2->getCurrentLock();
709 	Ogre::uint8 *data2 = static_cast<Ogre::uint8*>(pb2.data);
710 
711 	size_t height2 = pb2.getHeight();
712 	size_t width2 = pb2.getWidth();
713 	size_t rowPitch2 = pb2.rowPitch;
714 
715 	for (size_t y = 0; y < height2; ++y)
716 	{
717 		for(size_t x = 0; x < width2; ++x)
718 		{
719 			data2[rowPitch2*y + x] = Ogre::Math::RangeRandom(64.0,192);
720 		}
721 	}
722 
723 	ptr2->unlock();
724 }
725 
726 #endif	// end _CompositorDemo_H_
727