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