Hardware Occlusion Culling - Occlusion Query for Irrlicht
Hardware Occlusion Culling - Occlusion Query for Irrlicht
Hi, This is occlusion query example for Irrlicht (support Direct3D9 and OpenGL modes). For query test I use normal Hi-Poly meshes, so FPS results isn't so good, but in next release I will use Bounding meshes for Occlusion Query Pass and FPS will be better. This culling is very useful for large levels.
First pre alpha demo for D3D9 / OpenGL from (only binaries):
http://rapidshare.com/files/136728949/O ... nQuery.zip
Pre builded Irrlicht (rev 1498) with Occlusion Query support and example demo of usage it with source code:
http://rapidshare.com/files/137400230/O ... ev1498.zip
Patches for update Irrlicht (rev 1498) to support Occlusion Query:
http://nadro.net46.net/Patches/Occlusio ... 1498.patch
http://nadro.net46.net/Patches/Occlusio ... 1498.patch
First pre alpha demo for D3D9 / OpenGL from (only binaries):
http://rapidshare.com/files/136728949/O ... nQuery.zip
Pre builded Irrlicht (rev 1498) with Occlusion Query support and example demo of usage it with source code:
http://rapidshare.com/files/137400230/O ... ev1498.zip
Patches for update Irrlicht (rev 1498) to support Occlusion Query:
http://nadro.net46.net/Patches/Occlusio ... 1498.patch
http://nadro.net46.net/Patches/Occlusio ... 1498.patch
Last edited by Nadro on Fri Aug 15, 2008 12:51 pm, edited 2 times in total.
Library helping with network requests, tasks management, logger etc in desktop and mobile apps: https://github.com/GrupaPracuj/hermes
There's quite a delay before it seems the cull is done on the little elephant... or is it just updating the stats every second instead of every frame?
By using bounding meshes do you mean just using a bounding box? And is that the bounding box of the mesh doing the blocking? That wouldn't work very well obviously due to the elephant (and many other) mesh not being an actual box. Or do you mean you'd do bounding box tests first and then the high poly tests?
Maybe you could provide a lower poly version of the elephant for doing the tests on, but that would have to fit completely within the high poly elephant for it to not give inaccurate results.....
By using bounding meshes do you mean just using a bounding box? And is that the bounding box of the mesh doing the blocking? That wouldn't work very well obviously due to the elephant (and many other) mesh not being an actual box. Or do you mean you'd do bounding box tests first and then the high poly tests?
Maybe you could provide a lower poly version of the elephant for doing the tests on, but that would have to fit completely within the high poly elephant for it to not give inaccurate results.....
Stats are update only when FPS are change, so this delay is not true, all is ok for it. Bounding meshes is very low poly mesh of object (all elements of it can't be higher than orginal elements of Hi Poly mesh)
Library helping with network requests, tasks management, logger etc in desktop and mobile apps: https://github.com/GrupaPracuj/hermes
Hi, I made first version of Irrlicht interface for functions usage in Hardware Occlusion Query (support Direct3D9 and OpenGL):
//! Run all queries. Draw all meshes stored in all queries.
void runAllQueries();
//! Return query result.
int getQueryResult( scene::ISceneNode* vNode );
And small and easy, usefull function for clean buffers:
I created *.patch files for update Irrlicht to support Hardware Occlusion Query (tested with the latest rev 1498), and I release package with precompiled Irrlicht r1498 with Occlusion Query support and example demo with source. I add links for it in first post.
Source code of example demo:
I'm waiting for Your comments and suggestions.
Code: Select all
//! Create query. Get node for identification query and bounding mesh for occlusion test.
void createQuery( scene::ISceneNode* vNode, scene::IMesh* vMesh );
//! Remove query.
void removeQuery( scene::ISceneNode* vNode );
//! Remove all queries.
void removeAllQueries();
//! Run query. Draw a mesh stored in query.
void runQuery( scene::ISceneNode* vNode );
void runAllQueries();
//! Return query result.
int getQueryResult( scene::ISceneNode* vNode );
And small and easy, usefull function for clean buffers:
Code: Select all
//! Clears BackBuffer and/or ZBuffer.
void clearBuffers(bool backBuffer, bool zBuffer, SColor color);
Source code of example demo:
Code: Select all
#include <irrlicht.h>
#include <iostream>
using namespace irr;
using namespace core;
using namespace scene;
using namespace video;
int main()
{
E_DRIVER_TYPE driverType;
printf("Please select the driver you want for this example:\n"\
" (a) Direct3D 9.0c\n (b) OpenGL 1.5\n (otherKey) exit\n\n");
char i;
std::cin >> i;
switch(i)
{
case 'a': driverType = EDT_DIRECT3D9;break;
case 'b': driverType = EDT_OPENGL;break;
default: return 1;
}
IrrlichtDevice* device = createDevice( driverType, dimension2d<s32>(800, 600), 32,false, false, false, 0);
IVideoDriver* driver = device->getVideoDriver();
ISceneManager* smgr = device->getSceneManager();
IMesh* mesh = smgr->getMesh("elephant.obj")->getMesh(0);
IMeshSceneNode* node1 = smgr->addMeshSceneNode( mesh );
IMeshSceneNode* node2 = smgr->addMeshSceneNode( mesh );
if (node1)
{
node1->setMaterialFlag(EMF_LIGHTING, false);
node1->setMaterialTexture( 0, driver->getTexture("red.jpg") );
node1->setPosition(vector3df(0,0,0));
node1->setScale(vector3df(1,1,1));
node1->setOcclusionCulling( true ); // Activate occlusion query test for node1, If You need manualy hide node eg. for LOD, You have to disable it, because OC automatic set node1->setVisible(false/true); You can disable/enable OC in each momment.
driver->createQuery(node1, mesh); // Create query for node1; in query test we will use standard hi poly mesh, because I don't have low poly bounding mesh for it.
}
if (node2)
{
node2->setMaterialFlag(EMF_LIGHTING, false);
node2->setMaterialTexture( 0, driver->getTexture("blue.jpg") );
node2->setPosition(vector3df(0,0,40));
node2->setScale(vector3df(0.1,0.1,0.1));
node2->setOcclusionCulling( true );
driver->createQuery(node2, mesh);
}
ICameraSceneNode* cam = smgr->addCameraSceneNodeFPS();
cam->setPosition(vector3df(100,0,60));
cam->setTarget(vector3df(3,0,37));
int lastFPS = -1;
SColor Color = SColor(255,100,101,140);
while(device->run())
{
driver->beginScene(true, true, Color);
// *** Occlusion Query Pass *** //
// At first we have to render transformed camera
cam->OnRegisterSceneNode();
cam->OnAnimate(device->getTimer()->getTime());
cam->render();
driver->runAllQueries(); // Run all occlusion queries test, if node has got 'setOcclusionCulling(0)' is skipping in this test, if object is occluded: node1->setVisible(0); if not: node1->setVisible(1);
// driver->runQuery(node1); // this is alternative run query method for node1
// driver->runQuery(node2);
driver->clearBuffers(true,true,Color); // We can clear BackBuffer and ZBuffer after OC Pass
// *** End of Occlusion Query Pass *** //
if(lastFPS == -1)
cam->setTarget(vector3df(3,0,37)); // Set camera target in first frame
smgr->drawAll();
driver->endScene();
int tris = driver->getPrimitiveCountDrawn();
int fps = driver->getFPS();
if (lastFPS != fps)
{
core::stringw str = L"Occlusion Query Demo FPS: ";
str += fps;
str += " Tris: ";
str += tris;
str += " Node 1 fragments: ";
str += driver->getQueryResult(node1); // get visible fragments count for node
str += " Node 2 fragments: ";
str += driver->getQueryResult(node2);
device->setWindowCaption(str.c_str());
lastFPS = fps;
}
}
driver->removeAllQueries(); // Remove All Queries
// driver->removeQuery(node1); // this is alternative remove query method for node1
// driver->removeQuery(node2);
device->drop();
return 0;
}
Library helping with network requests, tasks management, logger etc in desktop and mobile apps: https://github.com/GrupaPracuj/hermes
that was a massive quintuple post!
Looks cool...I'll definitely be bookmarking this
-wyrmmage
Looks cool...I'll definitely be bookmarking this
-wyrmmage
Worlds at War (Current Project) - http://www.awkward-games.com
Ganadu'r, The Eternal Sage (Other Current Project) - http://rpg.naget.com
Ganadu'r, The Eternal Sage (Other Current Project) - http://rpg.naget.com
Ehh, when I submit my post I see error message from phpBB, so I don't update first post because I think than my post isn't submited, but now I see than this error is joke:D OK, links are ready in first post.
BTW. I forgot add in this release EAC_BOX frustum culling test in query test, but I add it in the next release.
BTW. I forgot add in this release EAC_BOX frustum culling test in query test, but I add it in the next release.
Library helping with network requests, tasks management, logger etc in desktop and mobile apps: https://github.com/GrupaPracuj/hermes
-
- Posts: 68
- Joined: Sat May 10, 2008 11:30 am
- Contact:
Hi full.metal.coder,
Yes, server has got problems... and links are broken. Yes, I use in my engine this oc code with bounding meshes and I have got big speed up of my project. You have to manualy add to this source EAC_BOX frustum culling test eg. from CSceneManager.cpp (and put it in query test), because I forgot about this usefull stuff in this version.
I don't have access to stable server so I put code here:
OcclusionQuery_Include_Rev1498.patch
OcclusionQuery_Source_Rev1498.patch
Yes, server has got problems... and links are broken. Yes, I use in my engine this oc code with bounding meshes and I have got big speed up of my project. You have to manualy add to this source EAC_BOX frustum culling test eg. from CSceneManager.cpp (and put it in query test), because I forgot about this usefull stuff in this version.
I don't have access to stable server so I put code here:
OcclusionQuery_Include_Rev1498.patch
Code: Select all
Index: ISceneNode.h
===================================================================
--- ISceneNode.h (revision 1498)
+++ ISceneNode.h (working copy)
@@ -44,7 +44,8 @@
: RelativeTranslation(position), RelativeRotation(rotation), RelativeScale(scale),
Parent(0), ID(id), SceneManager(mgr), TriangleSelector(0),
AutomaticCullingState(EAC_BOX), IsVisible(true),
- DebugDataVisible(EDS_OFF), IsDebugObject(false)
+ DebugDataVisible(EDS_OFF), IsDebugObject(false),
+ QueryPosition(-1), IsOcclusionCulling(0)
{
if (parent)
parent->addChild(this);
@@ -663,6 +664,31 @@
return 0; // to be implemented by derived classes
}
+ //! Set position on Qcclusion Query list.
+ void setQueryPosition( int vPosition )
+ {
+ if(vPosition >= 0)
+ QueryPosition = vPosition;
+ }
+
+ //! Get position on Qcclusion Query list.
+ int getQueryPosition()
+ {
+ return QueryPosition;
+ }
+
+ //! Set occlusion status.
+ void setOcclusionCulling( bool Value )
+ {
+ IsOcclusionCulling = Value;
+ }
+
+ //! Get occlusion status.
+ bool getOcclusionCulling()
+ {
+ return IsOcclusionCulling;
+ }
+
protected:
//! A clone function for the ISceneNode members.
@@ -753,6 +779,12 @@
//! Is debug object?
bool IsDebugObject;
+
+ //! Position on Qcclusion Query list.
+ int QueryPosition;
+
+ //! Is occluded?
+ bool IsOcclusionCulling;
};
} // end namespace scene
@@ -760,3 +792,4 @@
#endif
+
Index: IVideoDriver.h
===================================================================
--- IVideoDriver.h (revision 1498)
+++ IVideoDriver.h (working copy)
@@ -25,11 +25,14 @@
{
class IAttributes;
class IReadFile;
+ class ISceneNode;
} // end namespace io
namespace scene
{
class IMeshBuffer;
class IMeshManipulator;
+ class IMesh;
+ class ISceneNode;
} // end namespace scene
namespace video
@@ -917,6 +920,9 @@
*/
virtual void clearZBuffer() = 0;
+ //! Clears BackBuffer and/or ZBuffer.
+ virtual void clearBuffers(bool backBuffer, bool zBuffer, SColor color) = 0;
+
//! Make a screenshot of the last rendered frame.
/** \return An image created from the last rendered frame. */
virtual IImage* createScreenShot() = 0;
@@ -957,6 +963,24 @@
//! Returns the graphics card vendor name.
virtual core::stringc getVendorInfo() = 0;
+ //! Create query. Get node for identification query and bounding mesh for occlusion test.
+ virtual void createQuery( scene::ISceneNode* vNode, scene::IMesh* vMesh ) = 0;
+
+ //! Remove query.
+ virtual void removeQuery( scene::ISceneNode* vNode ) = 0;
+
+ //! Remove all queries.
+ virtual void removeAllQueries() = 0;
+
+ //! Run query. Draw a mesh stored in query.
+ virtual void runQuery( scene::ISceneNode* vNode ) = 0;
+
+ //! Run all queries. Draw all meshes stored in all queries.
+ virtual void runAllQueries() = 0;
+
+ //! Return query result.
+ virtual int getQueryResult( scene::ISceneNode* vNode ) = 0;
+
};
} // end namespace video
Code: Select all
Index: CD3D9Driver.cpp
===================================================================
--- CD3D9Driver.cpp (revision 1498)
+++ CD3D9Driver.cpp (working copy)
@@ -2410,6 +2410,26 @@
}
+//! Clears BackBuffer and/or ZBuffer.
+void CD3D9Driver::clearBuffers(bool backBuffer, bool zBuffer, SColor color)
+{
+ if (backBuffer || zBuffer)
+ {
+ DWORD flags = 0;
+
+ if (backBuffer)
+ flags |= D3DCLEAR_TARGET;
+
+ if (zBuffer)
+ flags |= D3DCLEAR_ZBUFFER;
+
+ HRESULT hr = pID3DDevice->Clear( 0, NULL, flags, color.color, 1.0, 0);
+ if (FAILED(hr))
+ os::Printer::log("CD3D9Driver clearBuffers() failed.", ELL_WARNING);
+ }
+}
+
+
//! Returns an image created from the last rendered frame.
IImage* CD3D9Driver::createScreenShot()
{
@@ -2519,6 +2539,147 @@
}
+//! Create query.
+void CD3D9Driver::createQuery( scene::ISceneNode* vNode, scene::IMesh* vMesh )
+{
+ if(!vNode || !vMesh)
+ return;
+
+ if(vNode->getQueryPosition() != -1)
+ return;
+
+ int Position = Query.size();
+ vNode->setQueryPosition(Position);
+
+ Query.push_back(0);
+ QueryResult.push_back(0);
+ QueryNode.push_back(vNode);
+ QueryMesh.push_back(vMesh);
+
+ pID3DDevice->CreateQuery( D3DQUERYTYPE_OCCLUSION, &Query[Position] );
+}
+
+//! Remove query.
+void CD3D9Driver::removeQuery( scene::ISceneNode* vNode )
+{
+ if(!vNode)
+ return;
+
+ int Position = vNode->getQueryPosition();
+
+ if(Position == -1)
+ return;
+
+ for(int current = Position + 1; current < Query.size(); current++)
+ {
+ QueryNode[current]->setQueryPosition(QueryNode[current]->getQueryPosition() - 1);
+ }
+
+ if( Query[Position] != NULL )
+ Query[Position]->Release();
+
+ Query.erase(Position);
+ QueryResult.erase(Position);
+ QueryNode.erase(Position);
+ QueryMesh.erase(Position);
+}
+
+//! Remove all queries.
+void CD3D9Driver::removeAllQueries()
+{
+ for(int current = 0; current < Query.size(); current++)
+ {
+ if( Query[current] != NULL )
+ Query[current]->Release();
+ }
+
+ Query.clear();
+ QueryResult.clear();
+ QueryNode.clear();
+ QueryMesh.clear();
+}
+
+//! Run query.
+void CD3D9Driver::runQuery( scene::ISceneNode* vNode )
+{
+ if(!vNode)
+ return;
+
+ int Position = vNode->getQueryPosition();
+
+ if(Position == -1)
+ return;
+
+ if(QueryNode[Position]->getOcclusionCulling() && QueryMesh[Position])
+ {
+ setTransform(video::ETS_WORLD, QueryNode[Position]->getRelativeTransformation());
+ Query[Position]->Issue( D3DISSUE_BEGIN );
+ {
+ for(int current = 0; current < QueryMesh[Position]->getMeshBufferCount(); current++)
+ drawMeshBuffer(QueryMesh[Position]->getMeshBuffer(current));
+ }
+ Query[Position]->Issue( D3DISSUE_END );
+
+ while( Query[Position]->GetData( (void*)&QueryResult[Position], sizeof(DWORD), D3DGETDATA_FLUSH) == S_FALSE )
+ {
+ }
+
+ if(QueryResult[Position] < 1)
+ {
+ QueryNode[Position]->setVisible(false);
+ }
+ else
+ {
+ QueryNode[Position]->setVisible(true);
+ }
+ }
+}
+
+//! Run all queries.
+void CD3D9Driver::runAllQueries()
+{
+ for(int current = 0; current < Query.size(); current++)
+ {
+ if(QueryNode[current])
+ {
+ if(QueryNode[current]->getOcclusionCulling() && QueryMesh[current])
+ {
+ setTransform(video::ETS_WORLD, QueryNode[current]->getRelativeTransformation());
+ Query[current]->Issue( D3DISSUE_BEGIN );
+ {
+ for(int scurrent = 0; scurrent < QueryMesh[current]->getMeshBufferCount(); scurrent++)
+ drawMeshBuffer(QueryMesh[current]->getMeshBuffer(scurrent));
+ }
+ Query[current]->Issue( D3DISSUE_END );
+
+ while( Query[current]->GetData( (void*)&QueryResult[current], sizeof(DWORD), D3DGETDATA_FLUSH) == S_FALSE )
+ {
+ }
+
+ if(QueryResult[current] < 1)
+ {
+ QueryNode[current]->setVisible(false);
+ }
+ else
+ {
+ QueryNode[current]->setVisible(true);
+ }
+ }
+ }
+ }
+}
+
+//! Return query result.
+int CD3D9Driver::getQueryResult( scene::ISceneNode* vNode )
+{
+ if(!vNode)
+ return -1;
+
+ int Position = vNode->getQueryPosition();
+ return QueryResult[Position];
+}
+
+
} // end namespace video
} // end namespace irr
Index: CD3D9Driver.h
===================================================================
--- CD3D9Driver.h (revision 1498)
+++ CD3D9Driver.h (working copy)
@@ -202,6 +202,9 @@
//! Clears the ZBuffer.
virtual void clearZBuffer();
+ //! Clears BackBuffer and/or ZBuffer.
+ virtual void clearBuffers(bool backBuffer, bool zBuffer, SColor color);
+
//! Returns an image created from the last rendered frame.
virtual IImage* createScreenShot();
@@ -221,6 +224,25 @@
//! Returns the graphics card vendor name.
virtual core::stringc getVendorInfo() {return vendorName;};
+ //! Create query.
+ virtual void createQuery( scene::ISceneNode* vNode, scene::IMesh* vMesh );
+
+ //! Remove query.
+ virtual void removeQuery( scene::ISceneNode* vNode );
+
+ //! Remove all queries.
+ virtual void removeAllQueries();
+
+ //! Run query.
+ virtual void runQuery( scene::ISceneNode* vNode );
+
+ //! Run all queries.
+ virtual void runAllQueries();
+
+ //! Return query result.
+ virtual int getQueryResult( scene::ISceneNode* vNode );
+
+
private:
// enumeration for rendering modes such as 2d and 3d for minizing the switching of renderStates.
@@ -326,6 +348,11 @@
SColorf AmbientLight;
core::stringc vendorName;
+
+ core::array<IDirect3DQuery9*> Query;
+ core::array<int> QueryResult;
+ core::array<scene::ISceneNode*> QueryNode;
+ core::array<scene::IMesh*> QueryMesh;
};
Index: CNullDriver.cpp
===================================================================
--- CNullDriver.cpp (revision 1498)
+++ CNullDriver.cpp (working copy)
@@ -1813,6 +1813,11 @@
}
+void CNullDriver::clearBuffers(bool backBuffer, bool zBuffer, SColor color)
+{
+}
+
+
//! Returns a pointer to the mesh manipulator.
scene::IMeshManipulator* CNullDriver::getMeshManipulator()
{
@@ -1871,7 +1876,38 @@
// not necessary
}
+//! Create query.
+void CNullDriver::createQuery( scene::ISceneNode* vNode, scene::IMesh* vMesh )
+{
+}
+//! Remove query.
+void CNullDriver::removeQuery( scene::ISceneNode* vNode )
+{
+}
+
+//! Remove all queries.
+void CNullDriver::removeAllQueries()
+{
+}
+
+//! Run query.
+void CNullDriver::runQuery( scene::ISceneNode* vNode )
+{
+}
+
+//! Run all queries.
+void CNullDriver::runAllQueries()
+{
+}
+
+//! Return query result.
+int CNullDriver::getQueryResult( scene::ISceneNode* vNode )
+{
+ return -1;
+}
+
+
} // end namespace
} // end namespace
Index: CNullDriver.h
===================================================================
--- CNullDriver.h (revision 1498)
+++ CNullDriver.h (working copy)
@@ -14,6 +14,8 @@
#include "irrMap.h"
#include "IAttributes.h"
#include "IMeshBuffer.h"
+#include "IMesh.h"
+#include "ISceneNode.h"
#include "CFPSCounter.h"
#include "S3DVertex.h"
#include "SLight.h"
@@ -456,6 +458,9 @@
//! Clears the ZBuffer.
virtual void clearZBuffer();
+ //! Clears BackBuffer and/or ZBuffer.
+ virtual void clearBuffers(bool backBuffer, bool zBuffer, SColor color);
+
//! Returns an image created from the last rendered frame.
virtual IImage* createScreenShot();
@@ -490,6 +495,24 @@
//! Returns the graphics card vendor name.
virtual core::stringc getVendorInfo() {return "Not available on this driver.";};
+ //! Create query.
+ virtual void createQuery( scene::ISceneNode* vNode, scene::IMesh* vMesh );
+
+ //! Remove query.
+ virtual void removeQuery( scene::ISceneNode* vNode );
+
+ //! Remove all queries.
+ virtual void removeAllQueries();
+
+ //! Run query.
+ virtual void runQuery( scene::ISceneNode* vNode );
+
+ //! Run all queries.
+ virtual void runAllQueries();
+
+ //! Return query result.
+ virtual int getQueryResult( scene::ISceneNode* vNode );
+
protected:
//! deletes all textures
Index: COpenGLDriver.cpp
===================================================================
--- COpenGLDriver.cpp (revision 1498)
+++ COpenGLDriver.cpp (working copy)
@@ -2603,6 +2603,33 @@
}
+//! Clears BackBuffer and/or ZBuffer.
+void COpenGLDriver::clearBuffers(bool backBuffer, bool zBuffer, SColor color)
+{
+ if (backBuffer || zBuffer)
+ {
+ GLbitfield mask = 0;
+
+ if (backBuffer)
+ {
+ const f32 inv = 1.0f / 255.0f;
+ glClearColor(color.getRed() * inv, color.getGreen() * inv,
+ color.getBlue() * inv, color.getAlpha() * inv);
+
+ mask |= GL_COLOR_BUFFER_BIT;
+ }
+
+ if (zBuffer)
+ {
+ glDepthMask(GL_TRUE);
+ mask |= GL_DEPTH_BUFFER_BIT;
+ }
+
+ glClear(mask);
+ }
+}
+
+
//! Returns an image created from the last rendered frame.
IImage* COpenGLDriver::createScreenShot()
{
@@ -2707,6 +2734,141 @@
}
+//! Create query.
+void COpenGLDriver::createQuery( scene::ISceneNode* vNode, scene::IMesh* vMesh )
+{
+ if(!vNode || !vMesh)
+ return;
+
+ if(vNode->getQueryPosition() != -1)
+ return;
+
+ int Position = Query.size();
+ vNode->setQueryPosition(Position);
+
+ Query.push_back(0);
+ QueryResult.push_back(0);
+ QueryNode.push_back(vNode);
+ QueryMesh.push_back(vMesh);
+
+ extGlGenQueries( 1, &Query[Position] );
+}
+
+//! Remove query.
+void COpenGLDriver::removeQuery( scene::ISceneNode* vNode )
+{
+ if(!vNode)
+ return;
+
+ int Position = vNode->getQueryPosition();
+
+ if(Position == -1)
+ return;
+
+ for(int current = Position + 1; current < Query.size(); current++)
+ {
+ QueryNode[current]->setQueryPosition(QueryNode[current]->getQueryPosition() - 1);
+ }
+
+ extGlDeleteQueries( 1, &Query[Position] );
+
+ Query.erase(Position);
+ QueryResult.erase(Position);
+ QueryNode.erase(Position);
+ QueryMesh.erase(Position);
+}
+
+//! Remove all queries.
+void COpenGLDriver::removeAllQueries()
+{
+ for(int current = 0; current < Query.size(); current++)
+ {
+ extGlDeleteQueries( 1, &Query[current] );
+ }
+
+ Query.clear();
+ QueryResult.clear();
+ QueryNode.clear();
+ QueryMesh.clear();
+}
+
+//! Run query.
+void COpenGLDriver::runQuery( scene::ISceneNode* vNode )
+{
+ if(!vNode)
+ return;
+
+ int Position = vNode->getQueryPosition();
+
+ if(Position == -1)
+ return;
+
+ if(QueryNode[Position]->getOcclusionCulling() && QueryMesh[Position])
+ {
+ setTransform(video::ETS_WORLD, QueryNode[Position]->getRelativeTransformation());
+ extGlBeginQuery( GL_SAMPLES_PASSED_ARB, Query[Position] );
+ {
+ for(int current = 0; current < QueryMesh[Position]->getMeshBufferCount(); current++)
+ drawMeshBuffer(QueryMesh[Position]->getMeshBuffer(current));
+ }
+ extGlEndQuery( GL_SAMPLES_PASSED_ARB );
+
+ extGlGetQueryObjectuiv( Query[Position], GL_QUERY_RESULT_ARB, (GLuint*)&QueryResult[Position] );
+
+ if(QueryResult[Position] < 1)
+ {
+ QueryNode[Position]->setVisible(false);
+ }
+ else
+ {
+ QueryNode[Position]->setVisible(true);
+ }
+ }
+}
+
+//! Run all queries.
+void COpenGLDriver::runAllQueries()
+{
+ for(int current = 0; current < Query.size(); current++)
+ {
+ if(QueryNode[current])
+ {
+ if(QueryNode[current]->getOcclusionCulling() && QueryMesh[current])
+ {
+ setTransform(video::ETS_WORLD, QueryNode[current]->getRelativeTransformation());
+ extGlBeginQuery( GL_SAMPLES_PASSED_ARB, Query[current] );
+ {
+ for(int scurrent = 0; scurrent < QueryMesh[current]->getMeshBufferCount(); scurrent++)
+ drawMeshBuffer(QueryMesh[current]->getMeshBuffer(scurrent));
+ }
+ extGlEndQuery( GL_SAMPLES_PASSED_ARB );
+
+ extGlGetQueryObjectuiv( Query[current], GL_QUERY_RESULT_ARB, (GLuint*)&QueryResult[current] );
+
+ if(QueryResult[current] < 1)
+ {
+ QueryNode[current]->setVisible(false);
+ }
+ else
+ {
+ QueryNode[current]->setVisible(true);
+ }
+ }
+ }
+ }
+}
+
+//! Return query result.
+int COpenGLDriver::getQueryResult( scene::ISceneNode* vNode )
+{
+ if(!vNode)
+ return -1;
+
+ int Position = vNode->getQueryPosition();
+ return QueryResult[Position];
+}
+
+
} // end namespace
} // end namespace
Index: COpenGLDriver.h
===================================================================
--- COpenGLDriver.h (revision 1498)
+++ COpenGLDriver.h (working copy)
@@ -307,6 +307,9 @@
//! Clears the ZBuffer.
virtual void clearZBuffer();
+ //! Clears BackBuffer and/or ZBuffer.
+ virtual void clearBuffers(bool backBuffer, bool zBuffer, SColor color);
+
//! Returns an image created from the last rendered frame.
virtual IImage* createScreenShot();
@@ -330,6 +333,24 @@
//! Returns the graphics card vendor name.
virtual core::stringc getVendorInfo() {return vendorName;};
+ //! Create query.
+ virtual void createQuery( scene::ISceneNode* vNode, scene::IMesh* vMesh );
+
+ //! Remove query.
+ virtual void removeQuery( scene::ISceneNode* vNode );
+
+ //! Remove all queries.
+ virtual void removeAllQueries();
+
+ //! Run query.
+ virtual void runQuery( scene::ISceneNode* vNode );
+
+ //! Run all queries.
+ virtual void runAllQueries();
+
+ //! Return query result.
+ virtual int getQueryResult( scene::ISceneNode* vNode );
+
private:
void uploadClipPlane(u32 index);
@@ -392,6 +413,11 @@
//! Color buffer format
ECOLOR_FORMAT ColorFormat;
+ core::array<GLuint> Query;
+ core::array<int> QueryResult;
+ core::array<scene::ISceneNode*> QueryNode;
+ core::array<scene::IMesh*> QueryMesh;
+
#ifdef _IRR_WINDOWS_API_
HDC HDc; // Private GDI Device Context
HWND Window;
Index: COpenGLExtensionHandler.cpp
===================================================================
--- COpenGLExtensionHandler.cpp (revision 1498)
+++ COpenGLExtensionHandler.cpp (working copy)
@@ -47,7 +47,9 @@
pGlRenderbufferStorageEXT(0), pGlFramebufferRenderbufferEXT(0),
pGlGenBuffersARB(0), pGlBindBufferARB(0), pGlBufferDataARB(0), pGlDeleteBuffersARB(0),
pGlBufferSubDataARB(0), pGlGetBufferSubDataARB(0), pGlMapBufferARB(0), pGlUnmapBufferARB(0),
- pGlIsBufferARB(0), pGlGetBufferParameterivARB(0), pGlGetBufferPointervARB(0)
+ pGlIsBufferARB(0), pGlGetBufferParameterivARB(0), pGlGetBufferPointervARB(0),
+ pGlGenQueriesARB(0), pGlDeleteQueriesARB(0), pGlIsQueryARB(0), pGlBeginQueryARB(0), pGlEndQueryARB(0),
+ pGlGetQueryivARB(0), pGlGetQueryObjectivARB(0), pGlGetQueryObjectuivARB(0)
#endif // _IRR_OPENGL_USE_EXTPOINTER_
@@ -177,6 +179,15 @@
pGlGetBufferParameterivARB= (PFNGLGETBUFFERPARAMETERIVARBPROC) wglGetProcAddress("glGetBufferParameterivARB");
pGlGetBufferPointervARB= (PFNGLGETBUFFERPOINTERVARBPROC) wglGetProcAddress("glGetBufferPointervARB");
+ // occlusion query
+ pGlGenQueriesARB = (PFNGLGENQUERIESARBPROC) wglGetProcAddress("glGenQueriesARB");
+ pGlDeleteQueriesARB = (PFNGLDELETEQUERIESARBPROC) wglGetProcAddress("glDeleteQueriesARB");
+ pGlIsQueryARB = (PFNGLISQUERYARBPROC) wglGetProcAddress("glIsQueryARB");
+ pGlBeginQueryARB = (PFNGLBEGINQUERYARBPROC) wglGetProcAddress("glBeginQueryARB");
+ pGlEndQueryARB = (PFNGLENDQUERYARBPROC) wglGetProcAddress("glEndQueryARB");
+ pGlGetQueryivARB = (PFNGLGETQUERYIVARBPROC) wglGetProcAddress("glGetQueryivARB");
+ pGlGetQueryObjectivARB = (PFNGLGETQUERYOBJECTIVARBPROC) wglGetProcAddress("glGetQueryObjectivARB");
+ pGlGetQueryObjectuivARB = (PFNGLGETQUERYOBJECTUIVARBPROC) wglGetProcAddress("glGetQueryObjectuivARB");
// vsync extension
wglSwapIntervalEXT = (PFNWGLSWAPINTERVALFARPROC) wglGetProcAddress("wglSwapIntervalEXT");
@@ -384,8 +395,32 @@
pGlGetBufferPointervARB = (PFNGLGETBUFFERPOINTERVARBPROC)
IRR_OGL_LOAD_EXTENSION(reinterpret_cast<const GLubyte*>("glGetBufferPointervARB"));
+
+ pGlGenQueriesARB = (PFNGLGENQUERIESARBPROC)
+ IRR_OGL_LOAD_EXTENSION(reinterpret_cast<const GLubyte*>("glGenQueriesARB"));
+
+ pGlDeleteQueriesARB = (PFNGLDELETEQUERIESARBPROC)
+ IRR_OGL_LOAD_EXTENSION(reinterpret_cast<const GLubyte*>("glDeleteQueriesARB"));
+ pGlIsQueryARB = (PFNGLISQUERYARBPROC)
+ IRR_OGL_LOAD_EXTENSION(reinterpret_cast<const GLubyte*>("glIsQueryARB"));
+ pGlBeginQueryARB = (PFNGLBEGINQUERYARBPROC)
+ IRR_OGL_LOAD_EXTENSION(reinterpret_cast<const GLubyte*>("glBeginQueryARB"));
+
+ pGlEndQueryARB = (PFNGLENDQUERYARBPROC)
+ IRR_OGL_LOAD_EXTENSION(reinterpret_cast<const GLubyte*>("glEndQueryARB"));
+
+ pGlGetQueryivARB = (PFNGLGETQUERYIVARBPROC)
+ IRR_OGL_LOAD_EXTENSION(reinterpret_cast<const GLubyte*>("glGetQueryivARB"));
+
+ pGlGetQueryObjectivARB = (PFNGLGETQUERYOBJECTIVARBPROC)
+ IRR_OGL_LOAD_EXTENSION(reinterpret_cast<const GLubyte*>("glGetQueryObjectivARB"));
+
+ pGlGetQueryObjectuivARB = (PFNGLGETQUERYOBJECTUIVARBPROC)
+ IRR_OGL_LOAD_EXTENSION(reinterpret_cast<const GLubyte*>("glGetQueryObjectuivARB"));
+
+
#endif // _IRR_OPENGL_USE_EXTPOINTER_
#endif // _IRR_WINDOWS_API_
Index: COpenGLExtensionHandler.h
===================================================================
--- COpenGLExtensionHandler.h (revision 1498)
+++ COpenGLExtensionHandler.h (working copy)
@@ -763,7 +763,17 @@
void extGlGetBufferParameteriv (GLenum target, GLenum pname, GLint *params);
void extGlGetBufferPointerv (GLenum target, GLenum pname, GLvoid **params);
+ // occlusion query
+ void extGlGenQueries (GLsizei n, GLuint *ids);
+ void extGlDeleteQueries (GLsizei n, const GLuint *ids);
+ GLboolean extGlIsQuery (GLuint id);
+ void extGlBeginQuery (GLenum target, GLuint id);
+ void extGlEndQuery (GLenum target);
+ void extGlGetQueryiv (GLenum target, GLenum pname, GLint *params);
+ void extGlGetQueryObjectiv (GLuint id, GLenum pname, GLint *params);
+ void extGlGetQueryObjectuiv (GLuint id, GLenum pname, GLuint *params);
+
protected:
// the global feature array
bool FeatureAvailable[IRR_OpenGL_Feature_Count];
@@ -831,6 +841,14 @@
PFNGLISBUFFERARBPROC pGlIsBufferARB;
PFNGLGETBUFFERPARAMETERIVARBPROC pGlGetBufferParameterivARB;
PFNGLGETBUFFERPOINTERVARBPROC pGlGetBufferPointervARB;
+ PFNGLGENQUERIESARBPROC pGlGenQueriesARB;
+ PFNGLDELETEQUERIESARBPROC pGlDeleteQueriesARB;
+ PFNGLISQUERYARBPROC pGlIsQueryARB;
+ PFNGLBEGINQUERYARBPROC pGlBeginQueryARB;
+ PFNGLENDQUERYARBPROC pGlEndQueryARB;
+ PFNGLGETQUERYIVARBPROC pGlGetQueryivARB;
+ PFNGLGETQUERYOBJECTIVARBPROC pGlGetQueryObjectivARB;
+ PFNGLGETQUERYOBJECTUIVARBPROC pGlGetQueryObjectuivARB;
@@ -1505,11 +1523,107 @@
#endif
}
+inline void COpenGLExtensionHandler::extGlGenQueries (GLsizei n, GLuint *ids)
+{
+#ifdef _IRR_OPENGL_USE_EXTPOINTER_
+ if (pGlGenQueriesARB)
+ pGlGenQueriesARB(n, ids);
+#elif defined(GL_ARB_occlusion_query)
+ glGenQueriesARB(n, ids);
+#else
+ os::Printer::log("glGenQueriesARB not supported", ELL_ERROR);
+#endif
+}
+inline void COpenGLExtensionHandler::extGlDeleteQueries (GLsizei n, const GLuint *ids)
+{
+#ifdef _IRR_OPENGL_USE_EXTPOINTER_
+ if (pGlDeleteQueriesARB)
+ pGlDeleteQueriesARB(n, ids);
+#elif defined(GL_ARB_occlusion_query)
+ glDeleteQueriesARB(n, ids);
+#else
+ os::Printer::log("glDeleteQueriesARB not supported", ELL_ERROR);
+#endif
}
+
+inline GLboolean COpenGLExtensionHandler::extGlIsQuery (GLuint id)
+{
+#ifdef _IRR_OPENGL_USE_EXTPOINTER_
+ if (pGlIsQueryARB)
+ pGlIsQueryARB(id);
+#elif defined(GL_ARB_occlusion_query)
+ glIsQueryARB(id);
+#else
+ os::Printer::log("glIsQueryARB not supported", ELL_ERROR);
+#endif
}
+inline void COpenGLExtensionHandler::extGlBeginQuery (GLenum target, GLuint id)
+{
+#ifdef _IRR_OPENGL_USE_EXTPOINTER_
+ if (pGlBeginQueryARB)
+ pGlBeginQueryARB(target, id);
+#elif defined(GL_ARB_occlusion_query)
+ glBeginQueryARB(target, id);
+#else
+ os::Printer::log("glBeginQueryARB not supported", ELL_ERROR);
#endif
+}
+inline void COpenGLExtensionHandler::extGlEndQuery (GLenum target)
+{
+#ifdef _IRR_OPENGL_USE_EXTPOINTER_
+ if (pGlEndQueryARB)
+ pGlEndQueryARB(target);
+#elif defined(GL_ARB_occlusion_query)
+ glEndQueryARB(target);
+#else
+ os::Printer::log("glEndQueryARB not supported", ELL_ERROR);
#endif
+}
+inline void COpenGLExtensionHandler::extGlGetQueryiv (GLenum target, GLenum pname, GLint *params)
+{
+#ifdef _IRR_OPENGL_USE_EXTPOINTER_
+ if (pGlGetQueryivARB)
+ pGlGetQueryivARB(target, pname, params);
+#elif defined(GL_ARB_occlusion_query)
+ glGetQueryivARB(target, pname, params);
+#else
+ os::Printer::log("glGetQueryivARB not supported", ELL_ERROR);
+#endif
+}
+
+inline void COpenGLExtensionHandler::extGlGetQueryObjectiv (GLuint id, GLenum pname, GLint *params)
+{
+#ifdef _IRR_OPENGL_USE_EXTPOINTER_
+ if (pGlGetQueryObjectivARB)
+ pGlGetQueryObjectivARB(id, pname, params);
+#elif defined(GL_ARB_occlusion_query)
+ glGetQueryObjectivARB(id, pname, params);
+#else
+ os::Printer::log("glGetQueryObjectivARB not supported", ELL_ERROR);
+#endif
+}
+
+inline void COpenGLExtensionHandler::extGlGetQueryObjectuiv (GLuint id, GLenum pname, GLuint *params)
+{
+#ifdef _IRR_OPENGL_USE_EXTPOINTER_
+ if (pGlGetQueryObjectuivARB)
+ pGlGetQueryObjectuivARB(id, pname, params);
+#elif defined(GL_ARB_occlusion_query)
+ glGetQueryObjectuivARB(id, pname, params);
+#else
+ os::Printer::log("glGetQueryObjectuivARB not supported", ELL_ERROR);
+#endif
+}
+
+
+}
+}
+
+#endif
+
+#endif
+
Library helping with network requests, tasks management, logger etc in desktop and mobile apps: https://github.com/GrupaPracuj/hermes
-
- Posts: 68
- Joined: Sat May 10, 2008 11:30 am
- Contact:
thanks a lot.
I've already updated my working copy now I got to implement a smart culling algorithm. I've found a couple of resources after a quick web search but I did not find any implementation so far, let alone a killer(tm) one...
http://http.developer.nvidia.com/GPUGem ... ter06.html
http://http.developer.nvidia.com/GPUGem ... _ch29.html
I guess I'll have to search more and experiment a bit.
I've already updated my working copy now I got to implement a smart culling algorithm. I've found a couple of resources after a quick web search but I did not find any implementation so far, let alone a killer(tm) one...
http://http.developer.nvidia.com/GPUGem ... ter06.html
http://http.developer.nvidia.com/GPUGem ... _ch29.html
I guess I'll have to search more and experiment a bit.
Hmm, one thing I would like to note though is the naming scheme. You name the functions runAllQueries, createQuery, etc. But you have to remember, there are more queries that OpenGL, and D3D, contain that aren't occlusion queries.
So you might just want to rename that, or the devs can rename it if they accept it into the engine. Just a note.
So you might just want to rename that, or the devs can rename it if they accept it into the engine. Just a note.
TheQuestion = 2B || !2B
Hi, I can't replay quickly because I change my PC. Yes this code isn't prepare for implementation in engine. Of course all core system is good, but user interface maybe will be better if We can will disable/enable occlusion per material E_MATERIAL_FLAG? end rename runQuery to runOcclusionQuery etc?
Library helping with network requests, tasks management, logger etc in desktop and mobile apps: https://github.com/GrupaPracuj/hermes