|
From: <axl...@us...> - 2009-07-05 15:48:17
|
Revision: 408
http://hgengine.svn.sourceforge.net/hgengine/?rev=408&view=rev
Author: axlecrusher
Date: 2009-07-05 15:48:11 +0000 (Sun, 05 Jul 2009)
Log Message:
-----------
Add a much improved occlusion test. This required changing how rendering works.
Specifically, PreRender() is now called on the entire render tree before any Render()
commands are issued. Prerender tells openGL to do a very fast occlusion test before doing
anything else with opengl.
This can be extreamly useful if large occluding geometry is rendered first, followed by many
smaller occluded objects.
Modified Paths:
--------------
Mercury2/src/BoundingBox.cpp
Mercury2/src/BoundingBox.h
Mercury2/src/HGMDLModel.cpp
Mercury2/src/HGMDLModel.h
Mercury2/src/Mercury2.cpp
Mercury2/src/MercuryAsset.cpp
Mercury2/src/MercuryAsset.h
Mercury2/src/MercuryNode.cpp
Mercury2/src/MercuryNode.h
Mercury2/src/MercuryVBO.cpp
Mercury2/src/MercuryVBO.h
Mercury2/src/RenderBuffer.cpp
Mercury2/src/RenderBuffer.h
Modified: Mercury2/src/BoundingBox.cpp
===================================================================
--- Mercury2/src/BoundingBox.cpp 2009-07-05 12:55:17 UTC (rev 407)
+++ Mercury2/src/BoundingBox.cpp 2009-07-05 15:48:11 UTC (rev 408)
@@ -4,19 +4,29 @@
#include <Viewport.h>
#include <Texture.h>
+#include <MercuryVBO.h>
+
#define SIGNED_DIST(x) m_normal.DotProduct(x)
// origional algorithim was -x<0
#define BEHIND_PLANE(x) x>=0
-bool BoundingVolume::IsOccluded()
+OcclusionResult::~OcclusionResult()
{
- uint32_t samples = 1;
- if (m_occlusionQuery != 0)
- glGetQueryObjectuivARB(m_occlusionQuery, GL_QUERY_RESULT_ARB, &samples);
- return samples==0;
+ if ( m_occlusionQuery != 0 )
+ glDeleteQueriesARB( 1, &m_occlusionQuery );
+ m_occlusionQuery = 0;
}
+uint32_t OcclusionResult::GetSamples() const
+{
+ if (m_occlusionQuery == 0) return ~0;
+
+ uint32_t samples;
+ glGetQueryObjectuivARB(m_occlusionQuery, GL_QUERY_RESULT_ARB, &samples);
+ return samples;
+}
+
BoundingBox::BoundingBox(const MercuryVertex& center, const MercuryVertex& extend)
:m_center(center), m_extend(extend)
{
@@ -101,6 +111,11 @@
bool BoundingBox::FrustumCull() const
{
+ /*feedback in openGL is probably depreciated
+ and is known to fallback to software
+ the OcclusionTest provides the same performence
+ it is probably best to avoid using this function */
+
static float b[3];
uint32_t samples;
const float* center = GetCenter();
@@ -147,49 +162,36 @@
return samples==0;
}
-void BoundingBox::DoOcclusionTest()
+void BoundingBox::DoOcclusionTest( OcclusionResult& result )
{
const float* center = GetCenter();
const float* extend = GetExtend();
-
+
glPushAttrib( GL_CURRENT_BIT | GL_ENABLE_BIT | GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
glDisable(GL_CULL_FACE);
glPushMatrix();
glTranslatef(center[0], center[1], center[2]);
glScalef(extend[0],extend[1],extend[2]);
-/*
- uint8_t tCount = Texture::NumberActiveTextures();
- for (uint8_t i = 0; i < tCount; ++i)
+
+ if (m_vboID == 0) InitVBO();
+
+ if ( MercuryVBO::m_lastVBOrendered != &m_vboID )
{
- glActiveTexture( GL_TEXTURE0+i );
- glClientActiveTextureARB( GL_TEXTURE0+i );
- glDisableClientState(GL_TEXTURE_COORD_ARRAY);
- glDisable( GL_TEXTURE_2D );
+ MercuryVBO::m_lastVBOrendered = &m_vboID;
+ glBindBufferARB(GL_ARRAY_BUFFER_ARB, m_vboID); // once
+ glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0); // once
+ glVertexPointer(3, GL_FLOAT, 0, 0); // once
}
-*/
- InitVBO();
- glBindBufferARB(GL_ARRAY_BUFFER_ARB, m_vboID);
- glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0);
- glVertexPointer(3, GL_FLOAT, 0, 0);
-
- if (m_occlusionQuery == 0) glGenQueriesARB(1, &m_occlusionQuery);
- glBeginQueryARB(GL_SAMPLES_PASSED_ARB, m_occlusionQuery);
+ if (result.GetQueryID() == 0) glGenQueriesARB(1, &result.GetQueryID());
+ glBeginQueryARB(GL_SAMPLES_PASSED_ARB, result.GetQueryID());
glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
glDepthMask(GL_FALSE);
glDrawArrays(GL_QUADS, 0, 24);
-/*
- for (uint8_t i = 0; i < tCount; ++i)
- {
- glActiveTexture( GL_TEXTURE0+i );
- glClientActiveTextureARB(GL_TEXTURE0+i);
- glEnableClientState(GL_TEXTURE_COORD_ARRAY);
- glEnable( GL_TEXTURE_2D );
- }
-*/
+
glEndQueryARB(GL_SAMPLES_PASSED_ARB);
// glGetQueryObjectuivARB(q, GL_QUERY_RESULT_ARB, &samples);
@@ -323,8 +325,6 @@
void BoundingBox::InitVBO()
{
- if (m_vboID != 0) return;
-
glGenBuffersARB(1, &m_vboID);
//vertex VBO
Modified: Mercury2/src/BoundingBox.h
===================================================================
--- Mercury2/src/BoundingBox.h 2009-07-05 12:55:17 UTC (rev 407)
+++ Mercury2/src/BoundingBox.h 2009-07-05 15:48:11 UTC (rev 408)
@@ -10,6 +10,21 @@
#include <AlignedBuffer.h>
+class OcclusionResult
+{
+ public:
+ OcclusionResult()
+ :m_occlusionQuery(0)
+ {}
+ ~OcclusionResult();
+
+ uint32_t GetSamples() const;
+ inline uint32_t IsOccluded() const { return GetSamples() == 0; }
+ inline uint32_t& GetQueryID() { return m_occlusionQuery; }
+ private:
+ uint32_t m_occlusionQuery;
+};
+
class BoundingVolume
{
public:
@@ -27,10 +42,15 @@
virtual bool Clip( const MercuryPlane& p ) = 0;
virtual bool Clip( const Frustum& f ) = 0;
- virtual bool FrustumCull() const = 0;
+ virtual bool FrustumCull() const = 0; //Do not use
// virtual bool OcclusionCull() const = 0;
- bool IsOccluded();
- virtual void DoOcclusionTest() = 0;
+
+ /** This uses openGL to do an occlusion test in hardware.
+ The answer is not immediately known, but this can be run on the GPU
+ while the CPU does something else. Get the anser later by calling
+ IsOccluded() on the result.
+ **/
+ virtual void DoOcclusionTest(OcclusionResult& result) = 0;
protected:
uint32_t m_occlusionQuery;
@@ -65,9 +85,9 @@
virtual bool Clip( const MercuryPlane& p );
virtual bool Clip( const Frustum& f );
- virtual bool FrustumCull() const;
+ virtual bool FrustumCull() const; //Do not use
// virtual bool OcclusionCull() const;
- virtual void DoOcclusionTest();
+ virtual void DoOcclusionTest(OcclusionResult& result);
private:
void ComputeNormals();
Modified: Mercury2/src/HGMDLModel.cpp
===================================================================
--- Mercury2/src/HGMDLModel.cpp 2009-07-05 12:55:17 UTC (rev 407)
+++ Mercury2/src/HGMDLModel.cpp 2009-07-05 15:48:11 UTC (rev 408)
@@ -1,5 +1,5 @@
#include <HGMDLModel.h>
-
+#include <MercuryNode.h>
REGISTER_ASSET_TYPE(HGMDLModel);
const uint16_t EXPCTMJRV = 2;
@@ -58,17 +58,21 @@
}
}
+void HGMDLModel::PreRender(const MercuryNode* node)
+{
+ if ( GetLoadState() != LOADING )
+ for(uint16_t i = 0; i < m_meshes.size(); ++i)
+ m_meshes[i]->PreRender(node);
+}
+
void HGMDLModel::Render(const MercuryNode* node)
{
- bool cull;
if ( GetLoadState() != LOADING )
{
for(uint16_t i = 0; i < m_meshes.size(); ++i)
{
- cull = false;
- const BoundingVolume* bv = m_meshes[i]->GetBoundingVolume();
- if (bv) cull = bv->FrustumCull();
- if ( !cull ) m_meshes[i]->Render(node);
+ if ( !node->GetOcclusionResult().IsOccluded() )
+ m_meshes[i]->Render(node);
}
}
}
Modified: Mercury2/src/HGMDLModel.h
===================================================================
--- Mercury2/src/HGMDLModel.h 2009-07-05 12:55:17 UTC (rev 407)
+++ Mercury2/src/HGMDLModel.h 2009-07-05 15:48:11 UTC (rev 408)
@@ -18,6 +18,8 @@
static void LoadModel(MercuryFile* hgmdl, HGMDLModel* model);
static HGMDLModel* Generate();
+
+ virtual void PreRender(const MercuryNode* node);
virtual void Render(const MercuryNode* node);
private:
Modified: Mercury2/src/Mercury2.cpp
===================================================================
--- Mercury2/src/Mercury2.cpp 2009-07-05 12:55:17 UTC (rev 407)
+++ Mercury2/src/Mercury2.cpp 2009-07-05 15:48:11 UTC (rev 408)
@@ -87,6 +87,7 @@
// renderGraph.Render();
// RenderableNode::RecursiveRender(root);
// printf("\n");
+ root->RecursivePreRender();
root->RecursiveRender();
renderGraph.RenderAlpha();
w->SwapBuffers();
Modified: Mercury2/src/MercuryAsset.cpp
===================================================================
--- Mercury2/src/MercuryAsset.cpp 2009-07-05 12:55:17 UTC (rev 407)
+++ Mercury2/src/MercuryAsset.cpp 2009-07-05 15:48:11 UTC (rev 408)
@@ -16,6 +16,7 @@
void MercuryAsset::Init(MercuryNode* node)
{
// RenderableNode* rn;
+ if ( node ) node->AddPreRender(this);
if ( node ) node->AddRender(this);
}
@@ -36,6 +37,13 @@
SetLoadState( LOADED );
}
+void MercuryAsset::PreRender(const MercuryNode* node)
+{
+ MercuryNode* n = const_cast<MercuryNode*>(node);
+ if ( m_boundingVolume )
+ m_boundingVolume->DoOcclusionTest( n->GetOcclusionResult() );
+}
+
void MercuryAsset::DrawAxes()
{
glBegin(GL_LINES);
Modified: Mercury2/src/MercuryAsset.h
===================================================================
--- Mercury2/src/MercuryAsset.h 2009-07-05 12:55:17 UTC (rev 407)
+++ Mercury2/src/MercuryAsset.h 2009-07-05 15:48:11 UTC (rev 408)
@@ -32,8 +32,13 @@
virtual void Init(MercuryNode* node);
- virtual void PreRender(const MercuryNode* node) {};
+ /** PreRender should be called before any real openGL render commands.
+ It is used to handles things like frustum culling, and occlusion culling.
+ Currently only occlusion culling test is run here.**/
+ virtual void PreRender(const MercuryNode* node);
+
virtual void Render(const MercuryNode* node) = 0;
+
virtual void PostRender(const MercuryNode* node) {};
///Loads an asset from an XMLAsset representing itself
@@ -43,7 +48,7 @@
inline void IsInstanced(bool b) { m_isInstanced = b; }
- inline const BoundingVolume* GetBoundingVolume() const { return m_boundingVolume; }
+ inline BoundingVolume* GetBoundingVolume() const { return m_boundingVolume; }
inline const MString& Path() const { return m_path; }
void DrawAxes();
Modified: Mercury2/src/MercuryNode.cpp
===================================================================
--- Mercury2/src/MercuryNode.cpp 2009-07-05 12:55:17 UTC (rev 407)
+++ Mercury2/src/MercuryNode.cpp 2009-07-05 15:48:11 UTC (rev 408)
@@ -129,25 +129,36 @@
child->RecursiveUpdate(dTime);
}
-void MercuryNode::RecursiveRender()
+void MercuryNode::RecursivePreRender()
{
- MercuryMatrix modelView;
- ShaderAttribute sa;
+ if ( IsHidden() ) return;
MercuryMatrix matrix = FindGlobalMatrix();
+ MercuryMatrix modelView = ManipulateMatrix( matrix );
+ glLoadMatrix( modelView );
+
PreRender( matrix ); //calls on children assets
-
- modelView = ManipulateMatrix( matrix );
+
+ for (MercuryNode* child = FirstChild(); child != NULL; child = NextChild(child))
+ child->RecursivePreRender();
+}
+
+void MercuryNode::RecursiveRender()
+{
+ if ( IsHidden() || m_occlusionResult.IsOccluded() ) return;
+
+ MercuryMatrix matrix = FindGlobalMatrix();
+ MercuryMatrix modelView = ManipulateMatrix( matrix );
// if ( IsHidden() || IsCulled(modelView) ) return;
- if ( IsHidden() ) return;
glLoadMatrix( modelView );
+ ShaderAttribute sa;
sa.type = ShaderAttribute::TYPE_MATRIX;
sa.value.matrix = matrix.Ptr();
Shader::SetAttribute("HG_ModelMatrix", sa);
-
+
Render( modelView ); //calls on children assets
//call render on other render graph entries under me
@@ -218,15 +229,9 @@
void MercuryNode::Render(const MercuryMatrix& matrix)
{
- bool cull;
list< MercuryAsset* >::iterator i;
for (i = m_render.begin(); i != m_render.end(); ++i )
- {
- cull = false;
- const BoundingVolume* bv = (*i)->GetBoundingVolume();
- if (bv) cull = bv->FrustumCull();
- if ( !cull ) (*i)->Render(this);
- }
+ (*i)->Render(this);
}
void MercuryNode::PostRender(const MercuryMatrix& matrix)
Modified: Mercury2/src/MercuryNode.h
===================================================================
--- Mercury2/src/MercuryNode.h 2009-07-05 12:55:17 UTC (rev 407)
+++ Mercury2/src/MercuryNode.h 2009-07-05 15:48:11 UTC (rev 408)
@@ -9,6 +9,7 @@
#include <MessageHandler.h>
#include <MercuryAsset.h>
+#include <BoundingBox.h>
/** This is the basic node of the scene graph. It is not intended to be instanced.
Each node exists as a single entity in the scene graph.
@@ -52,6 +53,7 @@
void ThreadedUpdate(float dTime);
+ void RecursivePreRender();
void RecursiveRender();
///Run on parent when a child is added
@@ -92,7 +94,9 @@
bool IsHidden() { return m_hidden; }
virtual MercuryMatrix ManipulateMatrix(const MercuryMatrix& matrix);
-
+
+ inline OcclusionResult& GetOcclusionResult() { return m_occlusionResult; }
+ inline const OcclusionResult& GetOcclusionResult() const { return m_occlusionResult; }
protected:
std::list< MercuryNode* > m_children; //These nodes are unique, not instanced
MercuryNode* m_parent;
@@ -106,6 +110,8 @@
private:
bool IsInAssetList(MercuryAsset* asset) const;
+ OcclusionResult m_occlusionResult;
+
//The asset is actually stored here
std::list< MAutoPtr< MercuryAsset > > m_assets;
Modified: Mercury2/src/MercuryVBO.cpp
===================================================================
--- Mercury2/src/MercuryVBO.cpp 2009-07-05 12:55:17 UTC (rev 407)
+++ Mercury2/src/MercuryVBO.cpp 2009-07-05 15:48:11 UTC (rev 408)
@@ -27,19 +27,13 @@
uint8_t numTextures = Texture::NumberActiveTextures();
uint16_t stride = sizeof(float)*8;
- if ( m_initiated )
- {
- if ( this != m_lastVBOrendered)
- {
- glBindBufferARB(GL_ARRAY_BUFFER_ARB, m_bufferIDs[0]);
- glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, m_bufferIDs[1]);
- }
- }
- else
- InitVBO();
+ if ( !m_initiated ) InitVBO();
- if ( this != m_lastVBOrendered)
+ if ( this != m_lastVBOrendered )
{
+ m_lastVBOrendered = this;
+ glBindBufferARB(GL_ARRAY_BUFFER_ARB, m_bufferIDs[0]);
+ glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, m_bufferIDs[1]);
glVertexPointer(3, GL_FLOAT, stride, BUFFER_OFFSET(sizeof(float)*5));
++m_vboBinds;
}
@@ -57,9 +51,7 @@
glDrawRangeElements(GL_TRIANGLES, 0, m_indexData.Length()-1, m_indexData.Length(), GL_UNSIGNED_SHORT, NULL);
m_vboBatches++;
-
- m_lastVBOrendered = this;
-
+
if (m_boundingVolume && SHOWBOUNDINGVOLUME) m_boundingVolume->Render();
if ( SHOWAXISES ) DrawAxes();
}
Modified: Mercury2/src/MercuryVBO.h
===================================================================
--- Mercury2/src/MercuryVBO.h 2009-07-05 12:55:17 UTC (rev 407)
+++ Mercury2/src/MercuryVBO.h 2009-07-05 15:48:11 UTC (rev 408)
@@ -24,12 +24,14 @@
float * GetVertexHandle() { return &m_vertexData[0]; }
short unsigned int * GetIndexHandle() { return &m_indexData[0]; }
+
+ static void* m_lastVBOrendered;
+
private:
virtual void InitVBO();
unsigned int m_bufferIDs[2];
bool m_initiated;
- static void* m_lastVBOrendered;
protected:
AlignedBuffer<float> m_vertexData;
Modified: Mercury2/src/RenderBuffer.cpp
===================================================================
--- Mercury2/src/RenderBuffer.cpp 2009-07-05 12:55:17 UTC (rev 407)
+++ Mercury2/src/RenderBuffer.cpp 2009-07-05 15:48:11 UTC (rev 408)
@@ -24,18 +24,15 @@
RenderableNode* rn = RenderableNode::Cast( node );
if ( rn )
{
- rn->AddPreRender( this );
+// rn->AddPreRender( this );
rn->AddPostRender( this );
}
}
-void RenderBuffer::PreRender(const MercuryNode* node)
-{
- if ( !m_initiated ) InitRenderBuffer();
-}
-
void RenderBuffer::Render(const MercuryNode* node)
{
+ if ( !m_initiated ) InitRenderBuffer();
+
glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, m_bufferID);
if ( NeedResize() ) AllocateSpace();
Modified: Mercury2/src/RenderBuffer.h
===================================================================
--- Mercury2/src/RenderBuffer.h 2009-07-05 12:55:17 UTC (rev 407)
+++ Mercury2/src/RenderBuffer.h 2009-07-05 15:48:11 UTC (rev 408)
@@ -20,7 +20,6 @@
virtual void Init(MercuryNode* node);
- virtual void PreRender(const MercuryNode* node);
virtual void Render(const MercuryNode* node);
virtual void PostRender(const MercuryNode* node);
virtual void LoadFromXML(const XMLNode& node);
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|