From 9ab4244206bcbbc57d91400d4c2c0965db530f87 Mon Sep 17 00:00:00 2001 From: Pavel Rojtberg Date: Thu, 12 Sep 2024 00:26:21 +0200 Subject: [PATCH 1/4] GL*: HardwareOcclusionQuery - allow calling methods out of order like on D3D. Previously this would trigget GL errors. --- .../GL/src/OgreGLHardwareOcclusionQuery.cpp | 16 ++++++++++++++++ .../src/OgreGL3PlusHardwareOcclusionQuery.cpp | 16 ++++++++++++++++ .../src/OgreGLES2HardwareOcclusionQuery.cpp | 16 ++++++++++++++++ 3 files changed, 48 insertions(+) diff --git a/RenderSystems/GL/src/OgreGLHardwareOcclusionQuery.cpp b/RenderSystems/GL/src/OgreGLHardwareOcclusionQuery.cpp index 9afca66ab59..7a1a9d5bd6e 100644 --- a/RenderSystems/GL/src/OgreGLHardwareOcclusionQuery.cpp +++ b/RenderSystems/GL/src/OgreGLHardwareOcclusionQuery.cpp @@ -62,6 +62,7 @@ GLHardwareOcclusionQuery::~GLHardwareOcclusionQuery() void GLHardwareOcclusionQuery::beginOcclusionQuery() { glBeginQueryARB(GL_SAMPLES_PASSED_ARB, mQueryID); + mIsQueryResultStillOutstanding = true; } //------------------------------------------------------------------ void GLHardwareOcclusionQuery::endOcclusionQuery() @@ -71,17 +72,32 @@ void GLHardwareOcclusionQuery::endOcclusionQuery() //------------------------------------------------------------------ bool GLHardwareOcclusionQuery::pullOcclusionQuery( unsigned int* NumOfFragments ) { + if (!mIsQueryResultStillOutstanding) + { + *NumOfFragments = mPixelCount; + return true; + } + glGetQueryObjectuivARB(mQueryID, GL_QUERY_RESULT_ARB, (GLuint*)NumOfFragments); mPixelCount = *NumOfFragments; + + mIsQueryResultStillOutstanding = false; + return true; } //------------------------------------------------------------------ bool GLHardwareOcclusionQuery::isStillOutstanding(void) { + if (!mIsQueryResultStillOutstanding) + return false; + GLuint available = GL_FALSE; glGetQueryObjectuivARB(mQueryID, GL_QUERY_RESULT_AVAILABLE_ARB, &available); + if(available == GL_TRUE) + pullOcclusionQuery(&mPixelCount); + // GL_TRUE means a wait would occur return !(available == GL_TRUE); } diff --git a/RenderSystems/GL3Plus/src/OgreGL3PlusHardwareOcclusionQuery.cpp b/RenderSystems/GL3Plus/src/OgreGL3PlusHardwareOcclusionQuery.cpp index e40a492f5b6..97fb429bd47 100644 --- a/RenderSystems/GL3Plus/src/OgreGL3PlusHardwareOcclusionQuery.cpp +++ b/RenderSystems/GL3Plus/src/OgreGL3PlusHardwareOcclusionQuery.cpp @@ -64,6 +64,7 @@ namespace Ogre { void GL3PlusHardwareOcclusionQuery::beginOcclusionQuery() { OGRE_CHECK_GL_ERROR(glBeginQuery(GL_SAMPLES_PASSED, mQueryID)); + mIsQueryResultStillOutstanding = true; } void GL3PlusHardwareOcclusionQuery::endOcclusionQuery() @@ -73,17 +74,32 @@ namespace Ogre { bool GL3PlusHardwareOcclusionQuery::pullOcclusionQuery( unsigned int* NumOfFragments ) { + if (!mIsQueryResultStillOutstanding) + { + *NumOfFragments = mPixelCount; + return true; + } + OGRE_CHECK_GL_ERROR(glGetQueryObjectuiv(mQueryID, GL_QUERY_RESULT, (GLuint*)NumOfFragments)); mPixelCount = *NumOfFragments; + + mIsQueryResultStillOutstanding = false; + return true; } bool GL3PlusHardwareOcclusionQuery::isStillOutstanding(void) { + if (!mIsQueryResultStillOutstanding) + return false; + GLuint available = GL_FALSE; OGRE_CHECK_GL_ERROR(glGetQueryObjectuiv(mQueryID, GL_QUERY_RESULT_AVAILABLE, &available)); + if(available == GL_TRUE) + pullOcclusionQuery(&mPixelCount); + // GL_TRUE means a wait would occur return !(available == GL_TRUE); } diff --git a/RenderSystems/GLES2/src/OgreGLES2HardwareOcclusionQuery.cpp b/RenderSystems/GLES2/src/OgreGLES2HardwareOcclusionQuery.cpp index eb64f30eb81..6701258f4b1 100644 --- a/RenderSystems/GLES2/src/OgreGLES2HardwareOcclusionQuery.cpp +++ b/RenderSystems/GLES2/src/OgreGLES2HardwareOcclusionQuery.cpp @@ -78,6 +78,7 @@ void GLES2HardwareOcclusionQuery::notifyOnContextReset() void GLES2HardwareOcclusionQuery::beginOcclusionQuery() { OGRE_CHECK_GL_ERROR(glBeginQueryEXT(GL_ANY_SAMPLES_PASSED_EXT, mQueryID)); + mIsQueryResultStillOutstanding = true; } //------------------------------------------------------------------ void GLES2HardwareOcclusionQuery::endOcclusionQuery() @@ -87,17 +88,32 @@ void GLES2HardwareOcclusionQuery::endOcclusionQuery() //------------------------------------------------------------------ bool GLES2HardwareOcclusionQuery::pullOcclusionQuery( unsigned int* NumOfFragments ) { + if (!mIsQueryResultStillOutstanding) + { + *NumOfFragments = mPixelCount; + return true; + } + OGRE_CHECK_GL_ERROR(glGetQueryObjectuivEXT(mQueryID, GL_QUERY_RESULT_EXT, (GLuint*)NumOfFragments)); mPixelCount = *NumOfFragments; + + mIsQueryResultStillOutstanding = false; + return true; } //------------------------------------------------------------------ bool GLES2HardwareOcclusionQuery::isStillOutstanding(void) { + if (!mIsQueryResultStillOutstanding) + return false; + GLuint available = GL_FALSE; OGRE_CHECK_GL_ERROR(glGetQueryObjectuivEXT(mQueryID, GL_QUERY_RESULT_AVAILABLE_EXT, &available)); + if(available == GL_TRUE) + pullOcclusionQuery(&mPixelCount); + // GL_TRUE means a wait would occur return !(available == GL_TRUE); } From a49c0d34d759f63e3769dd19545e53c4df5ee83c Mon Sep 17 00:00:00 2001 From: Pavel Rojtberg Date: Thu, 12 Sep 2024 00:27:56 +0200 Subject: [PATCH 2/4] D3D*: HardwareOcclusionQuery - retain LastQuerysPixelcount like on D3D. Also drop unused overload. --- .../Direct3D11/include/OgreD3D11HardwareOcclusionQuery.h | 1 - .../Direct3D11/src/OgreD3D11HardwareOcclusionQuery.cpp | 1 - .../Direct3D9/include/OgreD3D9HardwareOcclusionQuery.h | 1 - .../Direct3D9/src/OgreD3D9HardwareOcclusionQuery.cpp | 8 -------- 4 files changed, 11 deletions(-) diff --git a/RenderSystems/Direct3D11/include/OgreD3D11HardwareOcclusionQuery.h b/RenderSystems/Direct3D11/include/OgreD3D11HardwareOcclusionQuery.h index dbea8a89eb0..a63daaa539c 100644 --- a/RenderSystems/Direct3D11/include/OgreD3D11HardwareOcclusionQuery.h +++ b/RenderSystems/Direct3D11/include/OgreD3D11HardwareOcclusionQuery.h @@ -75,7 +75,6 @@ namespace Ogre { void beginOcclusionQuery(); void endOcclusionQuery(); bool pullOcclusionQuery( unsigned int* NumOfFragments); - unsigned int getLastQuerysPixelcount() { return mPixelCount; } bool isStillOutstanding(void); diff --git a/RenderSystems/Direct3D11/src/OgreD3D11HardwareOcclusionQuery.cpp b/RenderSystems/Direct3D11/src/OgreD3D11HardwareOcclusionQuery.cpp index 993fc8036d5..8bad32466ef 100644 --- a/RenderSystems/Direct3D11/src/OgreD3D11HardwareOcclusionQuery.cpp +++ b/RenderSystems/Direct3D11/src/OgreD3D11HardwareOcclusionQuery.cpp @@ -68,7 +68,6 @@ namespace Ogre { { mDevice.GetImmediateContext()->Begin(mQuery.Get());//Issue(D3DISSUE_BEGIN); mIsQueryResultStillOutstanding = true; - mPixelCount = 0; } void D3D11HardwareOcclusionQuery::endOcclusionQuery() diff --git a/RenderSystems/Direct3D9/include/OgreD3D9HardwareOcclusionQuery.h b/RenderSystems/Direct3D9/include/OgreD3D9HardwareOcclusionQuery.h index 4e968b7d5e3..322a4ffcdaf 100644 --- a/RenderSystems/Direct3D9/include/OgreD3D9HardwareOcclusionQuery.h +++ b/RenderSystems/Direct3D9/include/OgreD3D9HardwareOcclusionQuery.h @@ -76,7 +76,6 @@ namespace Ogre { void beginOcclusionQuery(); void endOcclusionQuery(); bool pullOcclusionQuery( unsigned int* NumOfFragments); - unsigned int getLastQuerysPixelcount(); bool isStillOutstanding(void); // Called immediately after the Direct3D device has been created. diff --git a/RenderSystems/Direct3D9/src/OgreD3D9HardwareOcclusionQuery.cpp b/RenderSystems/Direct3D9/src/OgreD3D9HardwareOcclusionQuery.cpp index c4a186de4c1..9f81af88153 100644 --- a/RenderSystems/Direct3D9/src/OgreD3D9HardwareOcclusionQuery.cpp +++ b/RenderSystems/Direct3D9/src/OgreD3D9HardwareOcclusionQuery.cpp @@ -86,7 +86,6 @@ namespace Ogre { { pOccQuery->Issue(D3DISSUE_BEGIN); mIsQueryResultStillOutstanding = true; - mPixelCount = 0; } } @@ -141,7 +140,6 @@ namespace Ogre { if (hr == D3DERR_DEVICELOST) { *NumOfFragments = 0; - mPixelCount = 0; SAFE_RELEASE(it->second); break; } @@ -156,12 +154,6 @@ namespace Ogre { return true; } - //------------------------------------------------------------------ - unsigned int D3D9HardwareOcclusionQuery::getLastQuerysPixelcount() - { - return mPixelCount; - } - //------------------------------------------------------------------ bool D3D9HardwareOcclusionQuery::isStillOutstanding(void) { From c7479fa4ca55a9c1bab29b3c41a45a05b0399e7d Mon Sep 17 00:00:00 2001 From: Pavel Rojtberg Date: Thu, 12 Sep 2024 01:20:01 +0200 Subject: [PATCH 3/4] Main: HardwareOcclusionQuery - add more descriptive API and improve docs formatting --- OgreMain/include/OgreHardwareOcclusionQuery.h | 75 +++++++------------ 1 file changed, 27 insertions(+), 48 deletions(-) diff --git a/OgreMain/include/OgreHardwareOcclusionQuery.h b/OgreMain/include/OgreHardwareOcclusionQuery.h index 927883d1069..774677eb03f 100644 --- a/OgreMain/include/OgreHardwareOcclusionQuery.h +++ b/OgreMain/include/OgreHardwareOcclusionQuery.h @@ -42,85 +42,64 @@ namespace Ogre { * @{ */ /** - * This is a abstract class that that provides the interface for the query class for - * hardware occlusion. + * Query how many pixels have passed the per-fragment tests. * - * @author Lee Sandberg - * Updated on 13/8/2005 by Tuan Kuranes email: tuan.kuranes@free.fr + * Create one OcclusionQuery per outstanding query or one per tested object + * + * Then, in the rendering loop: + * 1. Draw all occluders + * 2. @ref begin() + * 3. Draw the polygons to be tested + * 4. @ref end() + * + * Results must be pulled using @ref waitForResult() */ - class _OgreExport HardwareOcclusionQuery : public RenderSysAlloc +class _OgreExport HardwareOcclusionQuery : public RenderSysAlloc { -//---------------------------------------------------------------------- -// Public methods -//-- public: - /** - * Object public member functions - */ - - /** - * Default object constructor - * - */ HardwareOcclusionQuery(); - /** - * Object destructor - */ virtual ~HardwareOcclusionQuery(); /** * Starts the hardware occlusion query - * @remarks Simple usage: Create one or more OcclusionQuery object one per outstanding query or one per tested object - * OcclusionQuery* mOcclusionQuery; - * createOcclusionQuery( &mOcclusionQuery ); - * In the rendering loop: - * Draw all occluders - * mOcclusionQuery->startOcclusionQuery(); - * Draw the polygons to be tested - * mOcclusionQuery->endOcclusionQuery(); - * - * Results must be pulled using: - * UINT mNumberOfPixelsVisable; - * pullOcclusionQuery( &mNumberOfPixelsVisable ); - * */ + void begin() { beginOcclusionQuery(); } virtual void beginOcclusionQuery() = 0; /** * Ends the hardware occlusion test */ + void end() { endOcclusionQuery(); } virtual void endOcclusionQuery() = 0; /** - * Pulls the hardware occlusion query. - * @note Waits until the query result is available; use isStillOutstanding - * if just want to test if the result is available. - * @retval NumOfFragments will get the resulting number of fragments. + * Waits until the query result is available. + * use @ref resultReady() if just want to test if the result is available. + * @retval result will get the resulting number of fragments. * @return True if success or false if not. */ - virtual bool pullOcclusionQuery(unsigned int* NumOfFragments) = 0; + bool waitForResult(unsigned int* result) { return pullOcclusionQuery(result); } + virtual bool pullOcclusionQuery(unsigned int* result) = 0; /** - * Let's you get the last pixel count with out doing the hardware occlusion test + * Let's you get the last pixel count with out doing the hardware occlusion test. + * This function won't give you new values, just the old value. * @return The last fragment count from the last test. - * Remarks This function won't give you new values, just the old value. */ - unsigned int getLastQuerysPixelcount() const { return mPixelCount; } + uint32 getLastResult() const { return mPixelCount; } + OGRE_DEPRECATED uint32 getLastQuerysPixelcount() const { return getLastResult(); } /** * Lets you know when query is done, or still be processed by the Hardware - * @return true if query isn't finished. + * @return true if query is finished. */ - virtual bool isStillOutstanding(void) = 0; - + bool resultReady() { return !isStillOutstanding(); } + virtual bool isStillOutstanding(void) = 0; - //---------------------------------------------------------------------- - // protected members - //-- - protected : + protected: /// Number of visible pixels determined by last query - unsigned int mPixelCount; + uint32 mPixelCount; /// Has the query returned a result yet? bool mIsQueryResultStillOutstanding; }; From 006aca5b61d17f736da168ff49ff0c0ccb5c7adc Mon Sep 17 00:00:00 2001 From: Pavel Rojtberg Date: Thu, 12 Sep 2024 01:21:00 +0200 Subject: [PATCH 4/4] Samples: Lighting - refactor occlusion query code --- Samples/Simple/include/Lighting.h | 188 +++++++++++++----------------- 1 file changed, 78 insertions(+), 110 deletions(-) diff --git a/Samples/Simple/include/Lighting.h b/Samples/Simple/include/Lighting.h index 4218bf82030..5370df707c9 100644 --- a/Samples/Simple/include/Lighting.h +++ b/Samples/Simple/include/Lighting.h @@ -7,7 +7,48 @@ using namespace Ogre; using namespace OgreBites; -class _OgreSampleClassExport Sample_Lighting : public SdkSample, public RenderObjectListener +struct OcclusionQueryActivator : public RenderObjectListener +{ + HardwareOcclusionQuery* mActiveQuery = NULL; + + std::map mQueryMap; + + // Event raised when render single object started. + void notifyRenderSingleObject(Renderable* rend, const Pass* pass, const AutoParamDataSource* source, + const LightList* pLightList, bool suppressRenderStateChanges) override + { + // + // The following code activates and deactivates the occlusion queries + // so that the queries only include the rendering of their intended targets + // + + // Close the last occlusion query + // Each occlusion query should only last a single rendering + if (mActiveQuery) + { + mActiveQuery->end(); + mActiveQuery = NULL; + } + + // Open a new occlusion query + + // Check if a the object being rendered needs + // to be occlusion queried, and by which query instance. + auto it = mQueryMap.find(rend); + if(it == mQueryMap.end()) + return; + + // Stop occlusion query until we get the information + // (may not happen on the same frame they are requested in) + if(!it->second->resultReady()) + return; + + mActiveQuery = it->second; + mActiveQuery->begin(); + } +}; + +class _OgreSampleClassExport Sample_Lighting : public SdkSample { static const uint8 cPriorityMain = 50; static const uint8 cPriorityQuery = 51; @@ -25,11 +66,7 @@ class _OgreSampleClassExport Sample_Lighting : public SdkSample, public RenderOb mLight1QueryArea(NULL), mLight1QueryVisible(NULL), mLight2QueryArea(NULL), - mLight2QueryVisible(NULL), - mActiveQuery(NULL), - mUseOcclusionQuery(false), - mDoOcclusionQuery(false) - + mLight2QueryVisible(NULL) { mInfo["Title"] = "Lighting"; mInfo["Description"] = "Shows OGRE's lighting support. Also demonstrates " @@ -41,40 +78,24 @@ class _OgreSampleClassExport Sample_Lighting : public SdkSample, public RenderOb bool frameRenderingQueued(const FrameEvent& evt) override { - // Modulate the light flare according to performed occlusion queries - if (mUseOcclusionQuery) + if (mLight1QueryArea) { - // Stop occlusion queries until we get their information - // (may not happen on the same frame they are requested in) - mDoOcclusionQuery = false; + // Modulate the lights according to the query data + unsigned int lightAreaCount; + unsigned int lightVisibleCount; + float ratio; - // Check if all query information available - if ((mLight1QueryArea->isStillOutstanding() == false) && - (mLight1QueryVisible->isStillOutstanding() == false) && - (mLight2QueryArea->isStillOutstanding() == false) && - (mLight2QueryVisible->isStillOutstanding() == false)) - { - // Modulate the lights according to the query data - unsigned int lightAreaCount; - unsigned int lightVisibleCount; - float ratio; - - mLight1QueryArea->pullOcclusionQuery(&lightAreaCount); - mLight1QueryVisible->pullOcclusionQuery(&lightVisibleCount); - ratio = float(lightVisibleCount) / float(lightAreaCount); - mLight1BBFlare->setColour(mTrail->getInitialColour(0) * ratio); - - mLight2QueryArea->pullOcclusionQuery(&lightAreaCount); - mLight2QueryVisible->pullOcclusionQuery(&lightVisibleCount); - ratio = float(lightVisibleCount) / float(lightAreaCount); - mLight2BBFlare->setColour(mTrail->getInitialColour(1) * ratio); - - // Request new query data - mDoOcclusionQuery = true; - } + lightAreaCount = mLight1QueryArea->getLastResult(); + lightVisibleCount = mLight1QueryVisible->getLastResult(); + ratio = float(lightVisibleCount) / float(lightAreaCount); + mLight1BBFlare->setColour(mTrail->getInitialColour(0) * ratio); + + lightAreaCount = mLight2QueryArea->getLastResult(); + lightVisibleCount = mLight2QueryVisible->getLastResult(); + ratio = float(lightVisibleCount) / float(lightAreaCount); + mLight2BBFlare->setColour(mTrail->getInitialColour(1) * ratio); } - return SdkSample::frameRenderingQueued(evt); // don't forget the parent class updates! } @@ -112,26 +133,15 @@ class _OgreSampleClassExport Sample_Lighting : public SdkSample, public RenderOb mTrail->setRenderQueueGroup(cPriorityLights); // Create the occlusion queries to be used in this sample - try { - RenderSystem* renderSystem = Ogre::Root::getSingleton().getRenderSystem(); - mLight1QueryArea = renderSystem->createHardwareOcclusionQuery(); - mLight1QueryVisible = renderSystem->createHardwareOcclusionQuery(); - mLight2QueryArea = renderSystem->createHardwareOcclusionQuery(); - mLight2QueryVisible = renderSystem->createHardwareOcclusionQuery(); - - mUseOcclusionQuery = (mLight1QueryArea != NULL) && - (mLight1QueryVisible != NULL) && - (mLight2QueryArea != NULL) && - (mLight2QueryVisible != NULL); - } - catch (Exception& e) - { - mUseOcclusionQuery = false; - } + RenderSystem* renderSystem = Ogre::Root::getSingleton().getRenderSystem(); + mLight1QueryArea = renderSystem->createHardwareOcclusionQuery(); + mLight1QueryVisible = renderSystem->createHardwareOcclusionQuery(); + mLight2QueryArea = renderSystem->createHardwareOcclusionQuery(); + mLight2QueryVisible = renderSystem->createHardwareOcclusionQuery(); - if (mUseOcclusionQuery == false) + if (!mLight1QueryArea) { - LogManager::getSingleton().logError("Sample_Lighting - failed to create hardware occlusion query"); + LogManager::getSingleton().logWarning("Sample_Lighting - hardware occlusion query not available"); } // Create the materials to be used by the objects used fo the occlusion query @@ -195,7 +205,7 @@ class _OgreSampleClassExport Sample_Lighting : public SdkSample, public RenderOb bbs->setRenderQueueGroup(cPriorityLights); node->attachObject(bbs); - if (mUseOcclusionQuery) + if (mLight1QueryArea) { // Attach a billboard which will be used to get a relative area occupied by the light mLight1BBQueryArea = mSceneMgr->createBillboardSet(1); @@ -254,7 +264,7 @@ class _OgreSampleClassExport Sample_Lighting : public SdkSample, public RenderOb bbs->setRenderQueueGroup(cPriorityLights); node->attachObject(bbs); - if (mUseOcclusionQuery) + if (mLight1QueryArea) { // Attach a billboard which will be used to get a relative area occupied by the light mLight2BBQueryArea = mSceneMgr->createBillboardSet(1); @@ -271,65 +281,23 @@ class _OgreSampleClassExport Sample_Lighting : public SdkSample, public RenderOb mLight2BBQueryVisible->setMaterial(matQueryVisible); mLight2BBQueryVisible->setRenderQueueGroup(cPriorityQuery); node->attachObject(mLight2BBQueryVisible); - } - - // Setup the listener for the occlusion query - if (mUseOcclusionQuery) - { - mSceneMgr->addRenderObjectListener(this); - mDoOcclusionQuery = true; - } - } - - // Event raised when render single object started. - void notifyRenderSingleObject(Renderable* rend, const Pass* pass, const AutoParamDataSource* source, - const LightList* pLightList, bool suppressRenderStateChanges) override - { - // - // The following code activates and deactivates the occlusion queries - // so that the queries only include the rendering of their intended targets - // - - // Close the last occlusion query - // Each occlusion query should only last a single rendering - if (mActiveQuery != NULL) - { - mActiveQuery->endOcclusionQuery(); - mActiveQuery = NULL; - } - // Open a new occlusion query - if (mDoOcclusionQuery == true) - { - // Check if a the object being rendered needs - // to be occlusion queried, and by which query instance. - if (rend == mLight1BBQueryArea) - mActiveQuery = mLight1QueryArea; - else if (rend == mLight1BBQueryVisible) - mActiveQuery = mLight1QueryVisible; - else if (rend == mLight2BBQueryArea) - mActiveQuery = mLight2QueryArea; - else if (rend == mLight2BBQueryVisible) - mActiveQuery = mLight2QueryVisible; - - if (mActiveQuery != NULL) - { - mActiveQuery->beginOcclusionQuery(); - } + mOcclusionQueryActivator.mQueryMap[mLight2BBQueryArea] = mLight2QueryArea; + mOcclusionQueryActivator.mQueryMap[mLight2BBQueryVisible] = mLight2QueryVisible; + mOcclusionQueryActivator.mQueryMap[mLight1BBQueryArea] = mLight1QueryArea; + mOcclusionQueryActivator.mQueryMap[mLight1BBQueryVisible] = mLight1QueryVisible; + // Setup the listener for the occlusion query + mSceneMgr->addRenderObjectListener(&mOcclusionQueryActivator); } } void cleanupContent() override { RenderSystem* renderSystem = Ogre::Root::getSingleton().getRenderSystem(); - if (mLight1QueryArea != NULL) - renderSystem->destroyHardwareOcclusionQuery(mLight1QueryArea); - if (mLight1QueryVisible != NULL) - renderSystem->destroyHardwareOcclusionQuery(mLight1QueryVisible); - if (mLight2QueryArea != NULL) - renderSystem->destroyHardwareOcclusionQuery(mLight2QueryArea); - if (mLight2QueryVisible != NULL) - renderSystem->destroyHardwareOcclusionQuery(mLight2QueryVisible); + for (const auto& it : mOcclusionQueryActivator.mQueryMap) + { + renderSystem->destroyHardwareOcclusionQuery(it.second); + } } RibbonTrail* mTrail; @@ -345,10 +313,10 @@ class _OgreSampleClassExport Sample_Lighting : public SdkSample, public RenderOb HardwareOcclusionQuery* mLight1QueryVisible; HardwareOcclusionQuery* mLight2QueryArea; HardwareOcclusionQuery* mLight2QueryVisible; - HardwareOcclusionQuery* mActiveQuery; + + OcclusionQueryActivator mOcclusionQueryActivator; bool mUseOcclusionQuery; - bool mDoOcclusionQuery; }; #endif