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 #include "SdkSample.h"
16 
17 #ifndef __SSAO_H__
18 #define __SSAO_H__
19 
20 using namespace Ogre;
21 using namespace OgreBites;
22 
23 #define SSAO_GUI_WIDTH 250
24 #define SSAO_GUI_TRACK_WIDTH 100
25 #define SSAO_GUI_VALUE_BOX_WIDTH 50
26 
27 #define SSAO_OBJECT_MENU_NAME "ObjectType"
28 #define SSAO_CAMERA_MENU_NAME "Camera"
29 
30 #define SSAO_COMPOSITOR_MENU_NAME "Compositor"
31 #define SSAO_POST_MENU_NAME "Post"
32 #define SSAO_CREASE_MINIMUM_NAME "CreaseMinimum"
33 #define SSAO_CREASE_RANGE_NAME "mCreaseRange"
34 #define SSAO_CREASE_BIAS_NAME "mCreaseBias"
35 #define SSAO_CREASE_AVERAGER_NAME "mCreaseAverager"
36 #define SSAO_CREASE_KERNELSIZE_NAME "mCreaseKernelsize"
37 
38 #define SSAO_MODUALTE "mdoulate"
39 #define SSAO_SAMPLE_SPACE_NAME "sampleSpace"
40 #define SSAO_SAMPLE_LENGTH_SCREENSPACE "sampleScreenSpace"
41 #define SSAO_SAMPLE_LENGTH_WORLDSPACE "sampleWorldSpace"
42 #define SSAO_SAMPLE_LENGTH_EXPONENT_NAME "sampleLengthExponent"
43 
44 #define SSAO_ANGLE_BIAS_NAME "angleBias"
45 
46 #define SSAO_CRYTEK_OFFSET_SCALE_NAME "offsetScale"
47 #define SSAO_CRYTEK_EDGE_HIGHLIGHT_NAME "edgeHighlight"
48 #define SSAO_CRYTEK_DEFAULT_ACCESSIBILITY_NAME "defaultOcclusion"
49 
50 #define SSAO_UNSHARP_KERNEL_BIAS_NAME "kernelBias"
51 #define SSAO_UNSHARP_LAMBDA_NAME "lambda"
52 
53 #define SSAO_BILATERAL_PHOTOMETRIC_EXPONENT "photometricExponent"
54 
55 #define SSAO_USER_CAMERA_ITEM "User Camera"
56 #define SSAO_CAMERA_SIBENIK "Sibenik"
57 #define SSAO_CAMERA_CORNELL "Cornell Box"
58 
59 /** Class for handling materials who did not specify techniques for rendering
60  *  themselves into the GBuffer.
61  */
62 class _OgreSampleClassExport SSAOGBufferSchemeHandler : public Ogre::MaterialManager::Listener
63 {
64 public:
SSAOGBufferSchemeHandler()65 	SSAOGBufferSchemeHandler()
66 	{
67 		mGBufRefMat = Ogre::MaterialManager::getSingleton().getByName("SSAO/GBuffer");
68 	}
69 
~SSAOGBufferSchemeHandler()70 	virtual ~SSAOGBufferSchemeHandler()
71 	{
72 		mGBufRefMat.setNull();
73 	}
74 
75 	/** @copydoc MaterialManager::Listener::handleSchemeNotFound */
handleSchemeNotFound(unsigned short schemeIndex,const Ogre::String & schemeName,Ogre::Material * originalMaterial,unsigned short lodIndex,const Ogre::Renderable * rend)76 	virtual Ogre::Technique* handleSchemeNotFound(unsigned short schemeIndex,
77 		const Ogre::String& schemeName, Ogre::Material* originalMaterial, unsigned short lodIndex,
78 		const Ogre::Renderable* rend)
79 	{
80 			Technique* gBufferTech = originalMaterial->createTechnique();
81 			gBufferTech->setSchemeName(schemeName);
82 			Ogre::Pass* gbufPass = gBufferTech->createPass();
83 			*gbufPass = *mGBufRefMat->getTechnique(0)->getPass(0);
84 			return gBufferTech;
85 	}
86 private:
87 	Ogre::MaterialPtr mGBufRefMat;
88 };
89 
90 class _OgreSampleClassExport Sample_SSAO : public SdkSample
91 {
92 private:
93 	std::vector<String> mMeshNames;
94 	std::vector<Entity*> mMeshes;
95 	int mCurrentMeshIndex;
96 
97 	std::vector<String> mCompositorNames;
98 	String mCurrentCompositor;
99 
100 	std::vector<String> mPostNames;
101 	String mCurrentPost;
102 	String mCurrentModulateScheme;
103 
104 	SSAOGBufferSchemeHandler* mGBufSchemeHandler;
105     Light* mLight;
106 
107 public:
Sample_SSAO()108 	Sample_SSAO()
109     {
110         mInfo["Title"] = "SSAO Techniques";
111         mInfo["Description"] = "A demo of several Screen Space Ambient Occlusion (SSAO) shading techniques using compositors.";
112         mInfo["Thumbnail"] = "thumb_ssao.png";
113         mInfo["Category"] = "Lighting";
114 
115         mMeshNames.push_back("sibenik");
116         mMeshNames.push_back("cornell");
117 
118         mCompositorNames.push_back("SSAO/HemisphereMC");
119         mCompositorNames.push_back("SSAO/Volumetric");
120         mCompositorNames.push_back("SSAO/HorizonBased");
121         mCompositorNames.push_back("SSAO/Crytek");
122         mCompositorNames.push_back("SSAO/CreaseShading");
123         mCompositorNames.push_back("SSAO/UnsharpMask");
124         mCompositorNames.push_back("SSAO/ShowDepth");
125         mCompositorNames.push_back("SSAO/ShowNormals");
126         mCompositorNames.push_back("SSAO/ShowViewPos");
127 
128         mPostNames.push_back("SSAO/Post/NoFilter");
129         mPostNames.push_back("SSAO/Post/CrossBilateralFilter");
130         mPostNames.push_back("SSAO/Post/SmartBoxFilter");
131         mPostNames.push_back("SSAO/Post/BoxFilter");
132 
133         mCurrentCompositor = mCompositorNames[0];
134         mCurrentPost = mPostNames[0];
135 
136 		mGBufSchemeHandler = NULL;
137 		mLight = NULL;
138     }
139 
cleanupContent()140     void cleanupContent()
141     {
142 		MaterialManager::getSingleton().removeListener(mGBufSchemeHandler, "GBuffer");
143 		delete mGBufSchemeHandler;
144 		mGBufSchemeHandler = NULL;
145 
146         CompositorManager::getSingleton().setCompositorEnabled(mViewport, mCurrentCompositor, false);
147         CompositorManager::getSingleton().setCompositorEnabled(mViewport, mCurrentPost, false);
148 
149         CompositorManager::getSingleton().setCompositorEnabled(mViewport, "SSAO/GBuffer", false);
150         CompositorManager::getSingleton().removeCompositor(mViewport, "SSAO/GBuffer");
151 
152         for (unsigned int i = 0; i < mCompositorNames.size(); i++)
153         {
154             CompositorManager::getSingleton().setCompositorEnabled(mViewport, mCompositorNames[i], false);
155             CompositorManager::getSingleton().removeCompositor(mViewport, mCompositorNames[i]);
156         }
157 
158         for (unsigned int i = 0; i < mPostNames.size(); i++)
159         {
160             CompositorManager::getSingleton().setCompositorEnabled(mViewport, mPostNames[i], false);
161             CompositorManager::getSingleton().removeCompositor(mViewport, mPostNames[i]);
162         }
163 
164         MeshManager::getSingleton().remove("sibenik");
165         MeshManager::getSingleton().remove("cornell");
166 
167         mMeshes.clear();
168     }
169 
getRequiredPlugins()170     StringVector getRequiredPlugins()
171     {
172         return StringVector();
173     }
174 
testCapabilities(const RenderSystemCapabilities * caps)175     void testCapabilities(const RenderSystemCapabilities* caps)
176     {
177         if (!caps->hasCapability(RSC_VERTEX_PROGRAM) || !caps->hasCapability(RSC_FRAGMENT_PROGRAM))
178         {
179             OGRE_EXCEPT(Exception::ERR_NOT_IMPLEMENTED, "Your graphics card does not support vertex and fragment"
180                         " programs, so you cannot run this sample. Sorry!", "Sample_SSAO::testCapabilities");
181         }
182 		if (!(caps->getRenderSystemName() == "OpenGL Rendering Subsystem" || caps->getRenderSystemName() == "Direct3D9 Rendering Subsystem" ||
183 			caps->getRenderSystemName() == "Direct3D11 Rendering Subsystem"))
184 		{
185 			OGRE_EXCEPT(Exception::ERR_INVALID_STATE, "This demo currently only supports OpenGL and DirectX9. Sorry!",
186 				"Sample_SSAO:testCapabilities");
187 		}
188     }
189 
190 protected:
191 	/**
192 	 * Setup the compositors to be used.
193 	 */
setupCompositors()194     void setupCompositors()
195     {
196 
197         if (CompositorManager::getSingleton().addCompositor(mViewport, "SSAO/GBuffer"))
198             CompositorManager::getSingleton().setCompositorEnabled(mViewport, "SSAO/GBuffer", true);
199         else
200             LogManager::getSingleton().logMessage("Sample_SSAO: Failed to add GBuffer compositor\n");
201 
202         for (unsigned int i = 0; i < mCompositorNames.size(); i++)
203         {
204             if (CompositorManager::getSingleton().addCompositor(mViewport, mCompositorNames[i]))
205                 CompositorManager::getSingleton().setCompositorEnabled(mViewport, mCompositorNames[i], false);
206             else
207                 LogManager::getSingleton().logMessage("Sample_SSAO: Failed to add compositor: " + mCompositorNames[i] + "\n");
208         }
209 
210         for (unsigned int i = 0; i < mPostNames.size(); i++)
211         {
212 
213             if (CompositorManager::getSingleton().addCompositor(mViewport, mPostNames[i]))
214                 CompositorManager::getSingleton().setCompositorEnabled(mViewport, mPostNames[i], false);
215             else
216                 LogManager::getSingleton().logMessage("Sample_SSAO: Failed to add " + mPostNames[i] + " compositor\n");
217         }
218 
219         CompositorManager::getSingleton().setCompositorEnabled(mViewport, mCurrentCompositor, true);
220         CompositorManager::getSingleton().setCompositorEnabled(mViewport, mCurrentPost, true);
221     }
222 
223 	/**
224 	 * Setup the controls, ie. the gui elements.
225 	 */
setupControls(void)226     void setupControls(void)
227     {
228         // --- select mesh menu ---
229         SelectMenu* objectType = mTrayMgr->createThickSelectMenu(TL_TOPLEFT, SSAO_OBJECT_MENU_NAME, "Object: ", SSAO_GUI_WIDTH, 16);
230         for (unsigned int i = 0; i < mMeshNames.size(); i++)
231             objectType->addItem(mMeshNames[i]);
232 
233         // --- select camera menu ---
234         SelectMenu* cameraMenu = mTrayMgr->createThickSelectMenu(TL_TOPLEFT, SSAO_CAMERA_MENU_NAME, "Camera Position", SSAO_GUI_WIDTH, 16);
235         cameraMenu->addItem(SSAO_USER_CAMERA_ITEM);
236         cameraMenu->addItem(SSAO_CAMERA_CORNELL);
237         cameraMenu->addItem(SSAO_CAMERA_SIBENIK);
238 
239         // --- select compositor menu ---
240         SelectMenu* compositor = mTrayMgr->createThickSelectMenu(TL_TOPLEFT, SSAO_COMPOSITOR_MENU_NAME, "Compositor: ", SSAO_GUI_WIDTH, 16);
241         for (unsigned int i = 0; i < mCompositorNames.size(); i++)
242             compositor->addItem(mCompositorNames[i]);
243 
244         // --- select post filter menu ---
245         SelectMenu * post = mTrayMgr->createThickSelectMenu(TL_TOPLEFT, SSAO_POST_MENU_NAME, "Post Filter: ", SSAO_GUI_WIDTH, 16);
246         for (unsigned int i = 0; i < mPostNames.size(); i++)
247             post->addItem(mPostNames[i]);
248 
249         // --- hemisphere MC sample length exponent --- //
250         mTrayMgr->createThickSlider(TL_TOPLEFT,
251                                     SSAO_SAMPLE_LENGTH_EXPONENT_NAME,
252                                     "Sample Length Exponent",
253                                     SSAO_GUI_WIDTH,
254                                     SSAO_GUI_VALUE_BOX_WIDTH,
255                                     0,
256                                     5,
257                                     501); // snaps ???
258 
259 
260         // --- bilateral photometric exponent ---
261         mTrayMgr->createThickSlider(TL_TOPLEFT,
262                                     SSAO_BILATERAL_PHOTOMETRIC_EXPONENT,
263                                     "Photometric Exponent",
264                                     SSAO_GUI_WIDTH,
265                                     SSAO_GUI_VALUE_BOX_WIDTH,
266                                     0,
267                                     50,
268                                     501); // snaps ???
269 
270         // --- crease shading options ---
271         mTrayMgr->createThickSlider(TL_TOPLEFT,
272                                     SSAO_CREASE_MINIMUM_NAME,
273                                     "Minimum Crease",
274                                     SSAO_GUI_WIDTH,
275                                     SSAO_GUI_VALUE_BOX_WIDTH,
276                                     0,
277                                     1,
278                                     101); // snaps ???
279         mTrayMgr->createThickSlider(TL_TOPLEFT,
280                                     SSAO_CREASE_RANGE_NAME,
281                                     "Crease Range",
282                                     SSAO_GUI_WIDTH,
283                                     SSAO_GUI_VALUE_BOX_WIDTH,
284                                     0,
285                                     10,
286                                     101); // snaps ???
287         mTrayMgr->createThickSlider(TL_TOPLEFT,
288                                     SSAO_CREASE_BIAS_NAME,
289                                     "Bias",
290                                     SSAO_GUI_WIDTH,
291                                     SSAO_GUI_VALUE_BOX_WIDTH,
292                                     0,
293                                     2,
294                                     101); // snaps ???
295         mTrayMgr->createThickSlider(TL_TOPLEFT,
296                                     SSAO_CREASE_AVERAGER_NAME,
297                                     "Averager",
298                                     SSAO_GUI_WIDTH,
299                                     SSAO_GUI_VALUE_BOX_WIDTH,
300                                     0,
301                                     100,
302                                     101); // snaps ???
303 
304         mTrayMgr->createThickSlider(TL_TOPLEFT,
305                                     SSAO_CREASE_KERNELSIZE_NAME,
306                                     "Kernel Size Bias",
307                                     SSAO_GUI_WIDTH,
308                                     SSAO_GUI_VALUE_BOX_WIDTH,
309                                     0,
310                                     10,
311                                     101); // snaps ???
312         // --- sample length parameter ---
313 		mTrayMgr->createSeparator(TL_TOPLEFT, "sep");
314 
315 		mTrayMgr->createCheckBox(TL_TOPLEFT, SSAO_MODUALTE, "Modulate with scene", SSAO_GUI_WIDTH);
316 
317         // --- sample length parameter ---
318         mTrayMgr->createSeparator(TL_TOPLEFT, "sep2");
319         mTrayMgr->createCheckBox(TL_TOPLEFT, SSAO_SAMPLE_SPACE_NAME, "Sample in Screen Space", SSAO_GUI_WIDTH);
320         mTrayMgr->createThickSlider(TL_TOPLEFT,
321                                     SSAO_SAMPLE_LENGTH_SCREENSPACE,
322                                     "Screen space length (in %)",
323                                     SSAO_GUI_WIDTH,
324                                     SSAO_GUI_VALUE_BOX_WIDTH,
325                                     0,
326                                     100,
327                                     10001);
328 
329         mTrayMgr->createThickSlider(TL_TOPLEFT,
330                                     SSAO_SAMPLE_LENGTH_WORLDSPACE,
331                                     "World Space Length (units)",
332                                     SSAO_GUI_WIDTH,
333                                     SSAO_GUI_VALUE_BOX_WIDTH,
334                                     0,
335                                     10,
336                                     10001);
337 
338         // --- angle bias ---
339         mTrayMgr->createThickSlider(TL_TOPLEFT,
340                                     SSAO_ANGLE_BIAS_NAME,
341                                     "Angle Bias (radians)",
342                                     SSAO_GUI_WIDTH,
343                                     SSAO_GUI_VALUE_BOX_WIDTH,
344                                     0,
345                                     Math::HALF_PI,
346                                     1001);
347 
348         // --- offset length ---
349         mTrayMgr->createThickSlider(TL_TOPLEFT,
350                                     SSAO_CRYTEK_OFFSET_SCALE_NAME,
351                                     "Offset Scale (% of sample length)",
352                                     SSAO_GUI_WIDTH,
353                                     SSAO_GUI_VALUE_BOX_WIDTH,
354                                     0,
355                                     100,
356                                     10001);
357 
358         // --- crytek edge highlight ---
359         mTrayMgr->createThickSlider(TL_TOPLEFT,
360                                     SSAO_CRYTEK_EDGE_HIGHLIGHT_NAME,
361                                     "Edge Highlight Factor",
362                                     SSAO_GUI_WIDTH,
363                                     SSAO_GUI_VALUE_BOX_WIDTH,
364                                     0,
365                                     1,
366                                     101);
367 
368         // --- crytek default accesibility value for invalid samples ---
369         mTrayMgr->createThickSlider(TL_TOPLEFT,
370                                     SSAO_CRYTEK_DEFAULT_ACCESSIBILITY_NAME,
371                                     "Default Accessibility",
372                                     SSAO_GUI_WIDTH,
373                                     SSAO_GUI_VALUE_BOX_WIDTH,
374                                     0,
375                                     1,
376                                     101);
377 
378         // --- unsharp mask kernel bias ---
379         mTrayMgr->createThickSlider(TL_TOPLEFT,
380                                     SSAO_UNSHARP_KERNEL_BIAS_NAME,
381                                     "Kernel Size Bias",
382                                     SSAO_GUI_WIDTH,
383                                     SSAO_GUI_VALUE_BOX_WIDTH,
384                                     0,
385                                     10,
386                                     101); // snaps ???
387         // --- unsharp mask lambda ---
388         mTrayMgr->createThickSlider(TL_TOPLEFT,
389                                     SSAO_UNSHARP_LAMBDA_NAME,
390                                     "Unsharp Lambda",
391                                     SSAO_GUI_WIDTH,
392                                     SSAO_GUI_VALUE_BOX_WIDTH,
393                                     0,
394                                     10,
395                                     101); // snaps ???
396 
397         // setup values
398         static_cast<Slider*>(mTrayMgr->getWidget(SSAO_CREASE_MINIMUM_NAME))->setValue(0.2f);
399         static_cast<Slider*>(mTrayMgr->getWidget(SSAO_CREASE_RANGE_NAME))->setValue(1.0f);
400         static_cast<Slider*>(mTrayMgr->getWidget(SSAO_CREASE_BIAS_NAME))->setValue(1.0f);
401         static_cast<Slider*>(mTrayMgr->getWidget(SSAO_CREASE_AVERAGER_NAME))->setValue(24);
402         static_cast<Slider*>(mTrayMgr->getWidget(SSAO_CREASE_KERNELSIZE_NAME))->setValue(3.0f);
403 
404         static_cast<CheckBox*>(mTrayMgr->getWidget(SSAO_SAMPLE_SPACE_NAME))->setChecked(false);
405         static_cast<Slider*>(mTrayMgr->getWidget(SSAO_SAMPLE_LENGTH_SCREENSPACE))->setValue(6.0f);
406         static_cast<Slider*>(mTrayMgr->getWidget(SSAO_SAMPLE_LENGTH_WORLDSPACE))->setValue(2.0f);
407         static_cast<Slider*>(mTrayMgr->getWidget(SSAO_ANGLE_BIAS_NAME))->setValue(0.2f);
408         static_cast<Slider*>(mTrayMgr->getWidget(SSAO_CRYTEK_OFFSET_SCALE_NAME))->setValue(1.0f);
409         static_cast<Slider*>(mTrayMgr->getWidget(SSAO_CRYTEK_EDGE_HIGHLIGHT_NAME))->setValue(0.0f);
410         static_cast<Slider*>(mTrayMgr->getWidget(SSAO_CRYTEK_DEFAULT_ACCESSIBILITY_NAME))->setValue(0.5f);
411 
412         static_cast<Slider*>(mTrayMgr->getWidget(SSAO_UNSHARP_KERNEL_BIAS_NAME))->setValue(1.0f);
413         static_cast<Slider*>(mTrayMgr->getWidget(SSAO_UNSHARP_LAMBDA_NAME))->setValue(5.0f);
414 
415         static_cast<Slider*>(mTrayMgr->getWidget(SSAO_BILATERAL_PHOTOMETRIC_EXPONENT))->setValue(10.0f);
416 
417         static_cast<Slider*>(mTrayMgr->getWidget(SSAO_SAMPLE_LENGTH_EXPONENT_NAME))->setValue(1.0f);
418 
419         mTrayMgr->showCursor();
420     }
421 
422 	/**
423 	 * Create the scene and load the content.
424 	 */
setupContent()425     void setupContent()
426     {
427         mViewport->setBackgroundColour(ColourValue(0.5, 0.5, 0.5, 1));
428 
429         // set our camera to orbit around the origin and show cursor
430         mCameraMan->setStyle(CS_FREELOOK);
431 		mCameraMan->setTopSpeed(20.0);
432         mCamera->move(Vector3(0, 10, 0));
433         mCamera->setFOVy(Radian(Degree(45).valueRadians())); // i.e. 60deg * 1.3.. maya and ogre use fovX and fovY
434         mCamera->setFarClipDistance(400);
435         mCamera->setNearClipDistance(0.1);
436         mTrayMgr->showCursor();
437 
438         // sibenik
439         mCamera->setPosition(27, 9, -2);
440         mCamera->lookAt(Vector3(-6, 2, 1));;
441 
442         // setup all meshes
443         for (unsigned int i = 0; i < mMeshNames.size(); i++) {
444             Entity* ent = mSceneMgr->createEntity(mMeshNames[i], mMeshNames[i] + ".mesh");
445             ent->setVisible(false);
446 
447             mSceneMgr->getRootSceneNode()->attachObject(ent);
448             mMeshes.push_back(ent);
449         }
450         mCurrentMeshIndex = 0;
451         mMeshes[mCurrentMeshIndex]->setVisible(true);
452 
453         setupCompositors();
454 
455         setupControls();
456 
457         changeCompositor(mCompositorNames[0]);
458         changePost(mPostNames[0]);
459 
460 		mGBufSchemeHandler = new SSAOGBufferSchemeHandler();
461 		MaterialManager::getSingleton().addListener(mGBufSchemeHandler, "GBuffer");
462     }
463 
464 	/**
465 	 * Change the current displayed mesh to the new mesh identified by its index.
466 	 * @param index The index of the new mesh in the mesh vector.
467 	 */
changeMesh(int index)468     void changeMesh(int index)
469     {
470         mMeshes[mCurrentMeshIndex]->setVisible(false);
471         mMeshes[index]->setVisible(true);
472         mCurrentMeshIndex = index;
473     }
474 
475 	/**
476 	 * Change the compositor to be used.
477 	 * @param compositor The name of the compositor
478 	 */
changeCompositor(Ogre::String compositor)479     void changeCompositor(Ogre::String compositor)
480     {
481         CompositorManager::getSingleton().setCompositorEnabled(mViewport, mCurrentCompositor, false);
482         mCurrentCompositor = compositor;
483         CompositorManager::getSingleton().setCompositorEnabled(mViewport, mCurrentCompositor, true);
484 
485         if (compositor == "SSAO/CreaseShading")
486         {
487             mTrayMgr->getWidget(SSAO_CREASE_MINIMUM_NAME)->show();
488             mTrayMgr->moveWidgetToTray(SSAO_CREASE_MINIMUM_NAME, TL_TOPLEFT);
489             mTrayMgr->getWidget(SSAO_CREASE_RANGE_NAME)->show();
490             mTrayMgr->moveWidgetToTray(SSAO_CREASE_RANGE_NAME, TL_TOPLEFT);
491             mTrayMgr->getWidget(SSAO_CREASE_BIAS_NAME)->show();
492             mTrayMgr->moveWidgetToTray(SSAO_CREASE_BIAS_NAME, TL_TOPLEFT);
493             mTrayMgr->getWidget(SSAO_CREASE_AVERAGER_NAME)->show();
494             mTrayMgr->moveWidgetToTray(SSAO_CREASE_AVERAGER_NAME, TL_TOPLEFT);
495             mTrayMgr->getWidget(SSAO_CREASE_KERNELSIZE_NAME)->show();
496             mTrayMgr->moveWidgetToTray(SSAO_CREASE_KERNELSIZE_NAME, TL_TOPLEFT);
497         }
498         else
499         {
500             mTrayMgr->getWidget(SSAO_CREASE_MINIMUM_NAME)->hide();
501             mTrayMgr->removeWidgetFromTray(SSAO_CREASE_MINIMUM_NAME);
502             mTrayMgr->getWidget(SSAO_CREASE_RANGE_NAME)->hide();
503             mTrayMgr->removeWidgetFromTray(SSAO_CREASE_RANGE_NAME);
504             mTrayMgr->getWidget(SSAO_CREASE_BIAS_NAME)->hide();
505             mTrayMgr->removeWidgetFromTray(SSAO_CREASE_BIAS_NAME);
506             mTrayMgr->getWidget(SSAO_CREASE_AVERAGER_NAME)->hide();
507             mTrayMgr->removeWidgetFromTray(SSAO_CREASE_AVERAGER_NAME);
508             mTrayMgr->getWidget(SSAO_CREASE_KERNELSIZE_NAME)->hide();
509             mTrayMgr->removeWidgetFromTray(SSAO_CREASE_KERNELSIZE_NAME);
510         }
511 
512         if (compositor == "SSAO/UnsharpMask")
513         {
514             mTrayMgr->getWidget(SSAO_UNSHARP_KERNEL_BIAS_NAME)->show();
515             mTrayMgr->moveWidgetToTray(SSAO_UNSHARP_KERNEL_BIAS_NAME, TL_TOPLEFT);
516             mTrayMgr->getWidget(SSAO_UNSHARP_LAMBDA_NAME)->show();
517             mTrayMgr->moveWidgetToTray(SSAO_UNSHARP_LAMBDA_NAME, TL_TOPLEFT);
518         }
519         else
520         {
521             mTrayMgr->getWidget(SSAO_UNSHARP_KERNEL_BIAS_NAME)->hide();
522             mTrayMgr->removeWidgetFromTray(SSAO_UNSHARP_KERNEL_BIAS_NAME);
523             mTrayMgr->getWidget(SSAO_UNSHARP_LAMBDA_NAME)->hide();
524             mTrayMgr->removeWidgetFromTray(SSAO_UNSHARP_LAMBDA_NAME);
525         }
526 
527         if (compositor == "SSAO/Crytek" || compositor == "SSAO/HorizonBased" || compositor == "SSAO/HemisphereMC" || compositor == "SSAO/Volumetric")
528         {
529             mTrayMgr->getWidget(SSAO_SAMPLE_SPACE_NAME)->show();
530             mTrayMgr->moveWidgetToTray(SSAO_SAMPLE_SPACE_NAME, TL_TOPLEFT);
531             CheckBox *samplingCheckBox = (CheckBox *)mTrayMgr->getWidget(SSAO_SAMPLE_SPACE_NAME);
532             samplingCheckBox->setChecked(samplingCheckBox->isChecked()); // easy way to update the sliders...
533         }
534         else
535         {
536             mTrayMgr->getWidget(SSAO_SAMPLE_SPACE_NAME)->hide();
537             mTrayMgr->removeWidgetFromTray(SSAO_SAMPLE_SPACE_NAME);
538             mTrayMgr->getWidget(SSAO_SAMPLE_LENGTH_SCREENSPACE)->hide();
539             mTrayMgr->removeWidgetFromTray(SSAO_SAMPLE_LENGTH_SCREENSPACE);
540             mTrayMgr->getWidget(SSAO_SAMPLE_LENGTH_WORLDSPACE)->hide();
541             mTrayMgr->removeWidgetFromTray(SSAO_SAMPLE_LENGTH_WORLDSPACE);
542         }
543 
544         if (compositor == "SSAO/HemisphereMC")
545         {
546             mTrayMgr->getWidget(SSAO_SAMPLE_LENGTH_EXPONENT_NAME)->show();
547             mTrayMgr->moveWidgetToTray(SSAO_SAMPLE_LENGTH_EXPONENT_NAME, TL_TOPLEFT);
548         }
549         else
550         {
551             mTrayMgr->getWidget(SSAO_SAMPLE_LENGTH_EXPONENT_NAME)->hide();
552             mTrayMgr->removeWidgetFromTray(SSAO_SAMPLE_LENGTH_EXPONENT_NAME);
553         }
554 
555         if (compositor == "SSAO/HorizonBased")
556         {
557             mTrayMgr->getWidget(SSAO_ANGLE_BIAS_NAME)->show();
558             mTrayMgr->moveWidgetToTray(SSAO_ANGLE_BIAS_NAME, TL_TOPLEFT);
559         }
560         else
561         {
562             mTrayMgr->getWidget(SSAO_ANGLE_BIAS_NAME)->hide();
563             mTrayMgr->removeWidgetFromTray(SSAO_ANGLE_BIAS_NAME);
564         }
565 
566         if (compositor == "SSAO/Crytek")
567         {
568             mTrayMgr->getWidget(SSAO_CRYTEK_OFFSET_SCALE_NAME)->show();
569             mTrayMgr->moveWidgetToTray(SSAO_CRYTEK_OFFSET_SCALE_NAME, TL_TOPLEFT);
570             mTrayMgr->getWidget(SSAO_CRYTEK_EDGE_HIGHLIGHT_NAME)->show();
571             mTrayMgr->moveWidgetToTray(SSAO_CRYTEK_EDGE_HIGHLIGHT_NAME, TL_TOPLEFT);
572             mTrayMgr->getWidget(SSAO_CRYTEK_DEFAULT_ACCESSIBILITY_NAME)->show();
573             mTrayMgr->moveWidgetToTray(SSAO_CRYTEK_DEFAULT_ACCESSIBILITY_NAME, TL_TOPLEFT);
574         }
575         else
576         {
577             mTrayMgr->getWidget(SSAO_CRYTEK_OFFSET_SCALE_NAME)->hide();
578             mTrayMgr->removeWidgetFromTray(SSAO_CRYTEK_OFFSET_SCALE_NAME);
579             mTrayMgr->getWidget(SSAO_CRYTEK_EDGE_HIGHLIGHT_NAME)->hide();
580             mTrayMgr->removeWidgetFromTray(SSAO_CRYTEK_EDGE_HIGHLIGHT_NAME);
581             mTrayMgr->getWidget(SSAO_CRYTEK_DEFAULT_ACCESSIBILITY_NAME)->hide();
582             mTrayMgr->removeWidgetFromTray(SSAO_CRYTEK_DEFAULT_ACCESSIBILITY_NAME);
583         }
584     }
585 
586 	/**
587 	 * Change the post filter to be used.
588 	 * @param post The name of the new post processing filter.
589 	 */
changePost(Ogre::String post)590     void changePost(Ogre::String post)
591     {
592         CompositorManager::getSingleton().setCompositorEnabled(mViewport, mCurrentPost, false);
593         mCurrentPost = post;
594         CompositorManager::getSingleton().setCompositorEnabled(mViewport, mCurrentPost, true);
595 
596 		if (post == "SSAO/Post/CrossBilateralFilter")
597         {
598             mTrayMgr->getWidget(SSAO_BILATERAL_PHOTOMETRIC_EXPONENT)->show();
599             mTrayMgr->moveWidgetToTray(SSAO_BILATERAL_PHOTOMETRIC_EXPONENT, TL_TOPLEFT);
600         }
601         else
602         {
603             mTrayMgr->getWidget(SSAO_BILATERAL_PHOTOMETRIC_EXPONENT)->hide();
604             mTrayMgr->removeWidgetFromTray(SSAO_BILATERAL_PHOTOMETRIC_EXPONENT);
605         }
606     }
607 
608 	// sdkTray listener callbacks
itemSelected(SelectMenu * menu)609     void itemSelected(SelectMenu* menu)
610     {
611         if (menu->getName() == SSAO_OBJECT_MENU_NAME)
612             changeMesh(menu->getSelectionIndex());
613 
614         else if (menu->getName() == SSAO_COMPOSITOR_MENU_NAME)
615             changeCompositor(menu->getSelectedItem());
616 
617         else if (menu->getName() == SSAO_POST_MENU_NAME)
618             changePost(menu->getSelectedItem());
619 
620         else if (menu->getName() == SSAO_CAMERA_MENU_NAME)
621         {
622             if (menu->getSelectedItem() == SSAO_CAMERA_SIBENIK)
623             {
624                 mCamera->setPosition(27, 9, -2);
625                 mCamera->lookAt(Vector3(-6, 2, 1));
626             }
627             else if (menu->getSelectedItem() == SSAO_CAMERA_CORNELL)
628             {
629                 mCamera->setPosition(0, 5, 20);
630                 mCamera->lookAt(Vector3(0, 5, 0));
631             }
632         }
633     }
634 
sliderMoved(Slider * slider)635     void sliderMoved(Slider* slider)
636     {
637         if (slider->getName() == SSAO_CREASE_MINIMUM_NAME)
638             setUniform("SSAO/CreaseShading", "SSAO/CreaseShading", "cMinimumCrease", slider->getValue(), false, 1);
639 
640         else if (slider->getName() == SSAO_CREASE_BIAS_NAME)
641             setUniform("SSAO/CreaseShading", "SSAO/CreaseShading", "cBias", slider->getValue(), false, 1);
642 
643         else if (slider->getName() == SSAO_CREASE_AVERAGER_NAME)
644             setUniform("SSAO/CreaseShading", "SSAO/CreaseShading", "cAverager", slider->getValue(), false, 1);
645 
646         else if (slider->getName() == SSAO_CREASE_RANGE_NAME)
647             setUniform("SSAO/CreaseShading", "SSAO/CreaseShading", "cRange", slider->getValue() * slider->getValue(), false, 1);
648 
649         else if (slider->getName() == SSAO_CREASE_KERNELSIZE_NAME)
650             setUniform("SSAO/CreaseShading", "SSAO/CreaseShading", "cKernelSize", slider->getValue(), false, 1);
651 
652         else if (slider->getName() == SSAO_SAMPLE_LENGTH_SCREENSPACE)
653         {
654             setUniform("SSAO/Crytek", "SSAO/Crytek", "cSampleLengthScreenSpace", slider->getValue()/100.0f, false, 1);
655             setUniform("SSAO/HorizonBased", "SSAO/HorizonBased", "cSampleLengthScreenSpace", slider->getValue()/100.0f, false, 1);
656             setUniform("SSAO/HemisphereMC", "SSAO/HemisphereMC", "cSampleLengthScreenSpace", slider->getValue()/100.0f, false, 1);
657             setUniform("SSAO/Volumetric", "SSAO/Volumetric", "cSampleLengthScreenSpace", slider->getValue()/100.0f, false, 1);
658         }
659         else if (slider->getName() == SSAO_SAMPLE_LENGTH_WORLDSPACE)
660         {
661             setUniform("SSAO/Crytek", "SSAO/Crytek", "cSampleLengthWorldSpace", slider->getValue(), false, 1);
662             setUniform("SSAO/HorizonBased", "SSAO/HorizonBased", "cSampleLengthWorldSpace", slider->getValue(), false, 1);
663             setUniform("SSAO/HemisphereMC", "SSAO/HemisphereMC", "cSampleLengthWorldSpace", slider->getValue(), false, 1);
664             setUniform("SSAO/Volumetric", "SSAO/Volumetric", "cSampleLengthWorldSpace", slider->getValue(), false, 1);
665         }
666 
667         else if (slider->getName() == SSAO_ANGLE_BIAS_NAME)
668             setUniform("SSAO/HorizonBased", "SSAO/HorizonBased", "cAngleBias", slider->getValue(), false, 1);
669 
670         else if (slider->getName() == SSAO_CRYTEK_OFFSET_SCALE_NAME)
671             setUniform("SSAO/Crytek", "SSAO/Crytek", "cOffsetScale", slider->getValue()/100, false, 1);
672 
673         else if (slider->getName() == SSAO_CRYTEK_EDGE_HIGHLIGHT_NAME)
674             setUniform("SSAO/Crytek", "SSAO/Crytek", "cEdgeHighlight", 2.0f - slider->getValue(), false, 1);
675 
676         else if (slider->getName() == SSAO_CRYTEK_DEFAULT_ACCESSIBILITY_NAME)
677             setUniform("SSAO/Crytek", "SSAO/Crytek", "cDefaultAccessibility", slider->getValue(), false, 1);
678 
679         else if (slider->getName() == SSAO_UNSHARP_KERNEL_BIAS_NAME)
680         {
681             setUniform("SSAO/UnsharpMask", "SSAO/UnsharpMask/GaussianBlurY", "cKernelWidthBias", slider->getValue(), false, 1);
682             setUniform("SSAO/UnsharpMask", "SSAO/UnsharpMask/GaussianBlurX", "cKernelWidthBias", slider->getValue(), false, 1);
683         }
684 
685         else if (slider->getName() == SSAO_UNSHARP_LAMBDA_NAME)
686             setUniform("SSAO/UnsharpMask", "SSAO/UnsharpMask", "cLambda", slider->getValue() * slider->getValue(), false, 1);
687 
688         else if (slider->getName() == SSAO_BILATERAL_PHOTOMETRIC_EXPONENT)
689         {
690             setUniform("SSAO/Post/CrossBilateralFilter", "SSAO/HorizonBased/CrossBilateralFilter/X", "cPhotometricExponent", slider->getValue(), false, 2);
691             setUniform("SSAO/Post/CrossBilateralFilter", "SSAO/HorizonBased/CrossBilateralFilter/Y", "cPhotometricExponent", slider->getValue(), false, 2);
692         }
693 
694         else if(slider->getName() == SSAO_SAMPLE_LENGTH_EXPONENT_NAME)
695             setUniform("SSAO/HemisphereMC", "SSAO/HemisphereMC", "cSampleLengthExponent", slider->getValue(), false, 1);
696 
697         CompositorManager::getSingleton().setCompositorEnabled(mViewport, mCurrentCompositor, true);
698         CompositorManager::getSingleton().setCompositorEnabled(mViewport, mCurrentPost, true);
699     }
700 
checkBoxToggled(OgreBites::CheckBox * box)701     void checkBoxToggled(OgreBites::CheckBox *box)
702     {
703 		if(box->getName() == SSAO_MODUALTE)
704 		{
705 			if (box->isChecked())
706 			{
707 				CompositorManager::getSingleton().addCompositor(mViewport, "SSAO/Post/Modulate");
708 	            CompositorManager::getSingleton().setCompositorEnabled(mViewport, "SSAO/Post/Modulate", true);
709 				mSceneMgr->setAmbientLight(ColourValue(0.5, 0.5, 0.5));
710 				mLight = mSceneMgr->createLight();
711 				mLight->setPosition(30, 80, 30);
712 			}
713 			else
714 			{
715 				mSceneMgr->destroyLight(mLight);
716 				mLight = NULL;
717                 CompositorManager::getSingleton().setCompositorEnabled(mViewport, "SSAO/Post/Modulate", false);
718 				CompositorManager::getSingleton().removeCompositor(mViewport, "SSAO/Post/Modulate");
719 			}
720 		}
721         else if (box->getName() == SSAO_SAMPLE_SPACE_NAME)
722         {
723             setUniform("SSAO/Crytek", "SSAO/Crytek", "cSampleInScreenspace", box->isChecked(), false, 1);
724             setUniform("SSAO/HorizonBased", "SSAO/HorizonBased", "cSampleInScreenspace", box->isChecked(), false, 1);
725             setUniform("SSAO/HemisphereMC", "SSAO/HemisphereMC", "cSampleInScreenspace", box->isChecked(), false, 1);
726             setUniform("SSAO/Volumetric", "SSAO/Volumetric", "cSampleInScreenspace", box->isChecked(), false, 1);
727             CompositorManager::getSingleton().setCompositorEnabled(mViewport, mCurrentCompositor, true);
728 
729             if (box->isChecked()) // we sample in screen space
730             {
731                 mTrayMgr->removeWidgetFromTray(SSAO_SAMPLE_LENGTH_WORLDSPACE);
732                 mTrayMgr->getWidget(SSAO_SAMPLE_LENGTH_WORLDSPACE)->hide();
733                 mTrayMgr->moveWidgetToTray(SSAO_SAMPLE_LENGTH_SCREENSPACE, TL_TOPLEFT);
734                 mTrayMgr->getWidget(SSAO_SAMPLE_LENGTH_SCREENSPACE)->show();
735             }
736             else
737             {
738                 mTrayMgr->removeWidgetFromTray(SSAO_SAMPLE_LENGTH_SCREENSPACE);
739                 mTrayMgr->getWidget(SSAO_SAMPLE_LENGTH_SCREENSPACE)->hide();
740                 mTrayMgr->moveWidgetToTray(SSAO_SAMPLE_LENGTH_WORLDSPACE, TL_TOPLEFT);
741                 mTrayMgr->getWidget(SSAO_SAMPLE_LENGTH_WORLDSPACE)->show();
742             }
743         }
744     }
745 
746 	// The following three methods are for mouse input
747 	/** @see Sample::mousePressed. */
748 #if (OGRE_PLATFORM != OGRE_PLATFORM_APPLE_IOS) && (OGRE_PLATFORM != OGRE_PLATFORM_ANDROID)
749 
mousePressed(const OIS::MouseEvent & evt,OIS::MouseButtonID id)750     bool mousePressed( const OIS::MouseEvent& evt, OIS::MouseButtonID id )
751     {
752         if (mTrayMgr->injectMouseDown(evt, id))
753             return true;
754         if (id == OIS::MB_Left)
755             mTrayMgr->hideCursor();  // hide the cursor if user left-clicks in the scene
756 
757         return true;
758     }
759 
760 	/** @see Sample::mouseReleased. */
mouseReleased(const OIS::MouseEvent & evt,OIS::MouseButtonID id)761     bool mouseReleased( const OIS::MouseEvent& evt, OIS::MouseButtonID id )
762     {
763         if (mTrayMgr->injectMouseUp(evt, id))
764             return true;
765         if (id == OIS::MB_Left)
766             mTrayMgr->showCursor();  // unhide the cursor if user lets go of LMB
767 
768         return true;
769     }
770 
771 	/** @see Sample::mouseMoved. */
mouseMoved(const OIS::MouseEvent & evt)772     bool mouseMoved( const OIS::MouseEvent& evt )
773     {
774         // only rotate the camera if cursor is hidden
775         if (mTrayMgr->isCursorVisible())
776             mTrayMgr->injectMouseMove(evt);
777         else
778         {
779             mCameraMan->injectMouseMove(evt);
780             static_cast<SelectMenu*>(mTrayMgr->getWidget(SSAO_CAMERA_MENU_NAME))->selectItem(SSAO_USER_CAMERA_ITEM);
781         }
782 
783         return true;
784     }
785 #endif
786 	/**
787 	 * Set the uniform value in the compositor
788 	 * @param compositor The name of the compositor
789 	 * @param material The material that contains the uniform
790 	 * @param uniform The name of the uniform parameter
791 	 * @param value The value
792 	 * @param setVisible Whether to set the compositor to visible or not.
793 	 * @param position The position at which the compositor should be added again.
794 	 * defaults to -1, which means that the compositor is readded at the end of the chain.
795 	 */
796     void setUniform(Ogre::String compositor, Ogre::String material, Ogre::String uniform, float value, bool setVisible, int position = -1)
797     {
798         // remove compositor first???
799         CompositorManager::getSingleton().removeCompositor(mViewport, compositor);
800 
801         MaterialManager::getSingleton().getByName(material)->getTechnique(0)->
802         getPass(0)->getFragmentProgramParameters()->setNamedConstant(uniform, value);
803 
804         // adding again
805         CompositorManager::getSingleton().addCompositor(mViewport, compositor, position);
806         CompositorManager::getSingleton().setCompositorEnabled(mViewport, compositor, setVisible);
807     }
808 };
809 
810 
811 
812 #endif /* __SSAO_H__ */
813