From 04e7a7e83c6e2817b2a47d1549e7d9b21abf63d1 Mon Sep 17 00:00:00 2001 From: kearwood Date: Thu, 30 Aug 2012 22:37:44 +0000 Subject: [PATCH] Implemented KRAABB class. Occlusion culling in progress --HG-- extra : convert_revision : svn%3A7752d6cf-9f14-4ad2-affc-04f1e67b81a5/trunk%4085 --- KREngine/KREngine.xcodeproj/project.pbxproj | 12 ++ KREngine/KREngine/Classes/KRAABB.cpp | 75 +++++++++++ KREngine/KREngine/Classes/KRAABB.h | 37 ++++++ KREngine/KREngine/Classes/KRCamera.cpp | 19 +-- KREngine/KREngine/Classes/KRCamera.h | 4 + KREngine/KREngine/Classes/KROctree.cpp | 23 ++-- KREngine/KREngine/Classes/KROctree.h | 2 + KREngine/KREngine/Classes/KROctreeNode.cpp | 133 +++++++++++++++----- KREngine/KREngine/Classes/KROctreeNode.h | 24 +++- KREngine/KREngine/Classes/KRScene.cpp | 15 ++- KREngine/KREngine/Classes/KRScene.h | 7 +- KREngine/KREngine/Classes/KRVector3.cpp | 35 ++++++ KREngine/KREngine/Classes/KRVector3.h | 4 + 13 files changed, 334 insertions(+), 56 deletions(-) create mode 100644 KREngine/KREngine/Classes/KRAABB.cpp create mode 100644 KREngine/KREngine/Classes/KRAABB.h diff --git a/KREngine/KREngine.xcodeproj/project.pbxproj b/KREngine/KREngine.xcodeproj/project.pbxproj index f32a9a1..a719011 100644 --- a/KREngine/KREngine.xcodeproj/project.pbxproj +++ b/KREngine/KREngine.xcodeproj/project.pbxproj @@ -9,6 +9,10 @@ /* Begin PBXBuildFile section */ 1000469D15E6EF550053B072 /* KRSkyBox.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1000469B15E6EF550053B072 /* KRSkyBox.cpp */; }; 1000469E15E6EF550053B072 /* KRSkyBox.h in Headers */ = {isa = PBXBuildFile; fileRef = 1000469C15E6EF550053B072 /* KRSkyBox.h */; }; + E40BA45415EFF79500D7C3DD /* KRAABB.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E40BA45215EFF79500D7C3DD /* KRAABB.cpp */; }; + E40BA45515EFF79500D7C3DD /* KRAABB.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E40BA45215EFF79500D7C3DD /* KRAABB.cpp */; }; + E40BA45615EFF79500D7C3DD /* KRAABB.h in Headers */ = {isa = PBXBuildFile; fileRef = E40BA45315EFF79500D7C3DD /* KRAABB.h */; }; + E40BA45715EFF79500D7C3DD /* KRAABB.h in Headers */ = {isa = PBXBuildFile; fileRef = E40BA45315EFF79500D7C3DD /* KRAABB.h */; }; E414BAE21435557300A668C4 /* KRInstance.h in Headers */ = {isa = PBXBuildFile; fileRef = E414BAE11435557300A668C4 /* KRInstance.h */; }; E414BAE51435558900A668C4 /* KRInstance.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E414BAE41435558800A668C4 /* KRInstance.cpp */; }; E414BAE7143557D200A668C4 /* KRScene.h in Headers */ = {isa = PBXBuildFile; fileRef = E414BAE6143557D200A668C4 /* KRScene.h */; }; @@ -167,6 +171,8 @@ /* Begin PBXFileReference section */ 1000469B15E6EF550053B072 /* KRSkyBox.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = KRSkyBox.cpp; path = Classes/KRSkyBox.cpp; sourceTree = ""; }; 1000469C15E6EF550053B072 /* KRSkyBox.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = KRSkyBox.h; path = Classes/KRSkyBox.h; sourceTree = ""; }; + E40BA45215EFF79500D7C3DD /* KRAABB.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = KRAABB.cpp; path = Classes/KRAABB.cpp; sourceTree = ""; }; + E40BA45315EFF79500D7C3DD /* KRAABB.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = KRAABB.h; path = Classes/KRAABB.h; sourceTree = ""; }; E414BAE11435557300A668C4 /* KRInstance.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; lineEnding = 0; name = KRInstance.h; path = Classes/KRInstance.h; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.objcpp; }; E414BAE41435558800A668C4 /* KRInstance.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; lineEnding = 0; name = KRInstance.cpp; path = Classes/KRInstance.cpp; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.cpp; }; E414BAE6143557D200A668C4 /* KRScene.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; lineEnding = 0; name = KRScene.h; path = Classes/KRScene.h; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.objcpp; }; @@ -371,6 +377,8 @@ E497B945151BA99400D3DC67 /* KRVector2.cpp */, E42CB1EB158446940066E0D8 /* KRQuaternion.h */, E42CB1EF158446AB0066E0D8 /* KRQuaternion.cpp */, + E40BA45215EFF79500D7C3DD /* KRAABB.cpp */, + E40BA45315EFF79500D7C3DD /* KRAABB.h */, ); name = Math; sourceTree = ""; @@ -583,6 +591,7 @@ E4924C2715EE95E800B965C6 /* KROctree.h in Headers */, E4924C2C15EE96AB00B965C6 /* KROctreeNode.h in Headers */, 1000469E15E6EF550053B072 /* KRSkyBox.h in Headers */, + E40BA45615EFF79500D7C3DD /* KRAABB.h in Headers */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -624,6 +633,7 @@ E42CB1ED158446940066E0D8 /* KRQuaternion.h in Headers */, E43B0ACC15DDBB8500A5CB9F /* KRNotified.h in Headers */, E43B0AD915DDCA0F00A5CB9F /* KRContextObject.h in Headers */, + E40BA45715EFF79500D7C3DD /* KRAABB.h in Headers */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -744,6 +754,7 @@ E4924C2615EE95E800B965C6 /* KROctree.cpp in Sources */, E4924C2B15EE96AB00B965C6 /* KROctreeNode.cpp in Sources */, 1000469D15E6EF550053B072 /* KRSkyBox.cpp in Sources */, + E40BA45415EFF79500D7C3DD /* KRAABB.cpp in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -784,6 +795,7 @@ E42CB1F1158446AB0066E0D8 /* KRQuaternion.cpp in Sources */, E43B0ACA15DDBB8500A5CB9F /* KRNotified.cpp in Sources */, E43B0AD715DDCA0F00A5CB9F /* KRContextObject.cpp in Sources */, + E40BA45515EFF79500D7C3DD /* KRAABB.cpp in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/KREngine/KREngine/Classes/KRAABB.cpp b/KREngine/KREngine/Classes/KRAABB.cpp new file mode 100644 index 0000000..3dc9e87 --- /dev/null +++ b/KREngine/KREngine/Classes/KRAABB.cpp @@ -0,0 +1,75 @@ +// +// KRAABB.cpp +// KREngine +// +// Created by Kearwood Gilbert on 2012-08-30. +// Copyright (c) 2012 Kearwood Software. All rights reserved. +// + +#include "KRAABB.h" + +KRAABB::KRAABB(const KRVector3 &minPoint, const KRVector3 &maxPoint) +{ + min = minPoint; + max = maxPoint; +} +KRAABB::~KRAABB() +{ + +} + +KRAABB& KRAABB::operator =(const KRAABB& b) +{ + min = b.min; + max = b.max; + + return *this; +} + +bool KRAABB::operator ==(const KRAABB& b) const +{ + return min == b.min && max == b.max; +} + +bool KRAABB::operator !=(const KRAABB& b) const +{ + return min != b.min || max != b.max; +} + +KRVector3 KRAABB::center() +{ + return (min + max) / 2.0f; +} + +KRVector3 KRAABB::size() +{ + return max - min; +} + +bool KRAABB::operator >(const KRAABB& b) const +{ + // Comparison operators are implemented to allow insertion into sorted containers such as std::set + if(min > b.min) { + return true; + } else if(min < b.min) { + return false; + } else if(max > b.max) { + return true; + } else { + return false; + } + +} +bool KRAABB::operator <(const KRAABB& b) const +{ + // Comparison operators are implemented to allow insertion into sorted containers such as std::set + if(min < b.min) { + return true; + } else if(min > b.min) { + return false; + } else if(max < b.max) { + return true; + } else { + return false; + } +} \ No newline at end of file diff --git a/KREngine/KREngine/Classes/KRAABB.h b/KREngine/KREngine/Classes/KRAABB.h new file mode 100644 index 0000000..9e35470 --- /dev/null +++ b/KREngine/KREngine/Classes/KRAABB.h @@ -0,0 +1,37 @@ +// +// KRAABB.h +// KREngine +// +// Created by Kearwood Gilbert on 2012-08-30. +// Copyright (c) 2012 Kearwood Software. All rights reserved. +// + +// Axis aligned bounding box + +#ifndef KRAABB_H +#define KRAABB_H + +#include "KRVector3.h" + +class KRAABB { +public: + KRAABB(const KRVector3 &minPoint, const KRVector3 &maxPoint); + ~KRAABB(); + + KRVector3 center(); + KRVector3 size(); + + KRAABB& operator =(const KRAABB& b); + bool operator ==(const KRAABB& b) const; + bool operator !=(const KRAABB& b) const; + + // Comparison operators are implemented to allow insertion into sorted containers such as std::set + bool operator >(const KRAABB& b) const; + bool operator <(const KRAABB& b) const; + + KRVector3 min; + KRVector3 max; +}; + + +#endif /* defined(KRAABB_H) */ diff --git a/KREngine/KREngine/Classes/KRCamera.cpp b/KREngine/KREngine/Classes/KRCamera.cpp index d703663..4128ed5 100644 --- a/KREngine/KREngine/Classes/KRCamera.cpp +++ b/KREngine/KREngine/Classes/KRCamera.cpp @@ -213,7 +213,7 @@ void KRCamera::renderFrame(KRScene &scene, KRMat4 &viewMatrix, KRVector3 &lightD glDisable(GL_BLEND); // Render the geometry - scene.render(this, m_pContext, frustrumVolume, viewMatrix, cameraPosition, lightDirection, shadowmvpmatrix, shadowDepthTexture, m_cShadowBuffers, KRNode::RENDER_PASS_DEFERRED_GBUFFER); + scene.render(this, m_visibleBounds, m_pContext, frustrumVolume, viewMatrix, cameraPosition, lightDirection, shadowmvpmatrix, shadowDepthTexture, m_cShadowBuffers, KRNode::RENDER_PASS_DEFERRED_GBUFFER); // ----====---- Opaque Geometry, Deferred rendering Pass 2 ----====---- // Set render target @@ -237,7 +237,7 @@ void KRCamera::renderFrame(KRScene &scene, KRMat4 &viewMatrix, KRVector3 &lightD // Render the geometry - scene.render(this, m_pContext, frustrumVolume, viewMatrix, cameraPosition, lightDirection, shadowmvpmatrix, shadowDepthTexture, 0, KRNode::RENDER_PASS_DEFERRED_LIGHTS); + scene.render(this, m_visibleBounds, m_pContext, frustrumVolume, viewMatrix, cameraPosition, lightDirection, shadowmvpmatrix, shadowDepthTexture, 0, KRNode::RENDER_PASS_DEFERRED_LIGHTS); // ----====---- Opaque Geometry, Deferred rendering Pass 3 ----====---- // Set render target @@ -267,7 +267,7 @@ void KRCamera::renderFrame(KRScene &scene, KRMat4 &viewMatrix, KRVector3 &lightD glDepthMask(GL_TRUE); // Render the geometry - scene.render(this, m_pContext, frustrumVolume, viewMatrix, cameraPosition, lightDirection, shadowmvpmatrix, shadowDepthTexture, m_cShadowBuffers, KRNode::RENDER_PASS_DEFERRED_OPAQUE); + scene.render(this, m_visibleBounds, m_pContext, frustrumVolume, viewMatrix, cameraPosition, lightDirection, shadowmvpmatrix, shadowDepthTexture, m_cShadowBuffers, KRNode::RENDER_PASS_DEFERRED_OPAQUE); // Deactivate source buffer texture units glActiveTexture(GL_TEXTURE6); @@ -302,7 +302,7 @@ void KRCamera::renderFrame(KRScene &scene, KRMat4 &viewMatrix, KRVector3 &lightD // Render the geometry - scene.render(this, m_pContext, frustrumVolume, viewMatrix, cameraPosition, lightDirection, shadowmvpmatrix, shadowDepthTexture, m_cShadowBuffers, KRNode::RENDER_PASS_FORWARD_OPAQUE); + scene.render(this, m_visibleBounds, m_pContext, frustrumVolume, viewMatrix, cameraPosition, lightDirection, shadowmvpmatrix, shadowDepthTexture, m_cShadowBuffers, KRNode::RENDER_PASS_FORWARD_OPAQUE); } // ----====---- Transparent Geometry, Forward Rendering ----====---- @@ -327,7 +327,7 @@ void KRCamera::renderFrame(KRScene &scene, KRMat4 &viewMatrix, KRVector3 &lightD glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // Render all transparent geometry - scene.render(this, m_pContext, frustrumVolume, viewMatrix, cameraPosition, lightDirection, shadowmvpmatrix, shadowDepthTexture, m_cShadowBuffers, KRNode::RENDER_PASS_FORWARD_TRANSPARENT); + scene.render(this, m_visibleBounds, m_pContext, frustrumVolume, viewMatrix, cameraPosition, lightDirection, shadowmvpmatrix, shadowDepthTexture, m_cShadowBuffers, KRNode::RENDER_PASS_FORWARD_TRANSPARENT); // ----====---- Flares ----====---- @@ -350,10 +350,14 @@ void KRCamera::renderFrame(KRScene &scene, KRMat4 &viewMatrix, KRVector3 &lightD glBlendFunc(GL_ONE, GL_ONE); // Render all flares - scene.render(this, m_pContext, frustrumVolume, viewMatrix, cameraPosition, lightDirection, shadowmvpmatrix, shadowDepthTexture, m_cShadowBuffers, KRNode::RENDER_PASS_FLARES); + scene.render(this, m_visibleBounds, m_pContext, frustrumVolume, viewMatrix, cameraPosition, lightDirection, shadowmvpmatrix, shadowDepthTexture, m_cShadowBuffers, KRNode::RENDER_PASS_FLARES); // Re-enable z-buffer write glDepthMask(GL_TRUE); + + scene.getOcclusionQueryResults(m_visibleBounds); + + fprintf(stderr, "visible bounds: %i\n", (int)m_visibleBounds.size()); } @@ -539,7 +543,8 @@ void KRCamera::renderShadowBuffer(KRScene &scene, int iShadow) KRVector3 cameraPosition; KRVector3 lightDirection; KRBoundingVolume shadowVolume = KRBoundingVolume(vertices); - scene.render(this, m_pContext, shadowVolume, shadowmvpmatrix[iShadow], cameraPosition, lightDirection, shadowmvpmatrix, NULL, m_cShadowBuffers, KRNode::RENDER_PASS_SHADOWMAP); + scene.render(this, m_shadowVisibleBounds[iShadow], m_pContext, shadowVolume, shadowmvpmatrix[iShadow], cameraPosition, lightDirection, shadowmvpmatrix, NULL, m_cShadowBuffers, KRNode::RENDER_PASS_SHADOWMAP); + scene.getOcclusionQueryResults(m_shadowVisibleBounds[iShadow]); glViewport(0, 0, backingWidth, backingHeight); } diff --git a/KREngine/KREngine/Classes/KRCamera.h b/KREngine/KREngine/Classes/KRCamera.h index 38636bd..e672753 100644 --- a/KREngine/KREngine/Classes/KRCamera.h +++ b/KREngine/KREngine/Classes/KRCamera.h @@ -37,6 +37,7 @@ #import "KRMat4.h" #import "KRVector2.h" #import "KRNotified.h" +#import "KRAABB.h" #define KRENGINE_MAX_SHADOW_BUFFERS 3 @@ -196,6 +197,9 @@ private: std::list m_transparentInstances; + std::set m_visibleBounds; // AABB's that output fragments in the last frame + std::set m_shadowVisibleBounds[KRENGINE_MAX_SHADOW_BUFFERS]; // AABB's that output fragments in the last frame for each shadow map + }; #endif diff --git a/KREngine/KREngine/Classes/KROctree.cpp b/KREngine/KREngine/Classes/KROctree.cpp index f90de69..5f4b0cc 100644 --- a/KREngine/KREngine/Classes/KROctree.cpp +++ b/KREngine/KREngine/Classes/KROctree.cpp @@ -31,19 +31,18 @@ void KROctree::add(KRNode *pNode) } else { if(m_pRootNode == NULL) { // First item inserted, create a node large enough to fit it - m_pRootNode = new KROctreeNode(pNode->getMinPoint(), pNode->getMaxPoint()); + m_pRootNode = new KROctreeNode(KRAABB(pNode->getMinPoint(), pNode->getMaxPoint())); m_pRootNode->add(pNode); } else { // Keep encapsulating the root node until the new root contains the inserted node bool bInsideRoot = false; while(!bInsideRoot) { - KRVector3 rootMinPoint = m_pRootNode->getMinPoint(); - KRVector3 rootMaxPoint = m_pRootNode->getMaxPoint(); - KRVector3 rootSize = rootMaxPoint - rootMinPoint; - if(minPoint.x < rootMinPoint.x || minPoint.y < rootMinPoint.y || minPoint.z < rootMinPoint.z) { - m_pRootNode = new KROctreeNode(rootMinPoint - rootSize, rootMaxPoint, 7, m_pRootNode); - } else if(maxPoint.x > rootMaxPoint.x || maxPoint.y > rootMaxPoint.y || maxPoint.z > rootMaxPoint.z) { - m_pRootNode = new KROctreeNode(rootMaxPoint, rootMaxPoint + rootSize, 0, m_pRootNode); + KRAABB rootBounds = m_pRootNode->getBounds(); + KRVector3 rootSize = rootBounds.size(); + if(minPoint.x < rootBounds.min.x || minPoint.y < rootBounds.min.y || minPoint.z < rootBounds.min.z) { + m_pRootNode = new KROctreeNode(KRAABB(rootBounds.min - rootSize, rootBounds.max), 7, m_pRootNode); + } else if(maxPoint.x > rootBounds.max.x || maxPoint.y > rootBounds.max.y || maxPoint.z > rootBounds.max.z) { + m_pRootNode = new KROctreeNode(KRAABB(rootBounds.max, rootBounds.max + rootSize), 0, m_pRootNode); } else { bInsideRoot = true; } @@ -93,3 +92,11 @@ std::set &KROctree::getOuterSceneNodes() return m_outerSceneNodes; } +void KROctree::getOcclusionQueryResults(std::set &renderedBounds) +{ + renderedBounds.clear(); + if(m_pRootNode) { + m_pRootNode->getOcclusionQueryResults(renderedBounds); + } +} + diff --git a/KREngine/KREngine/Classes/KROctree.h b/KREngine/KREngine/Classes/KROctree.h index 5c4b9a4..9b725a1 100644 --- a/KREngine/KREngine/Classes/KROctree.h +++ b/KREngine/KREngine/Classes/KROctree.h @@ -27,6 +27,8 @@ public: KROctreeNode *getRootNode(); std::set &getOuterSceneNodes(); + void getOcclusionQueryResults(std::set &renderedBounds); + private: KROctreeNode *m_pRootNode; std::setm_outerSceneNodes; diff --git a/KREngine/KREngine/Classes/KROctreeNode.cpp b/KREngine/KREngine/Classes/KROctreeNode.cpp index f42cf9b..648cc28 100644 --- a/KREngine/KREngine/Classes/KROctreeNode.cpp +++ b/KREngine/KREngine/Classes/KROctreeNode.cpp @@ -9,20 +9,28 @@ #include "KROctreeNode.h" #include "KRNode.h" -KROctreeNode::KROctreeNode(const KRVector3 &minPoint, const KRVector3 &maxPoint) +KROctreeNode::KROctreeNode(const KRAABB &bounds) : m_bounds(bounds) { - m_minPoint = minPoint; - m_maxPoint = maxPoint; for(int i=0; i<8; i++) m_children[i] = NULL; + + m_occlusionQuery = 0; + m_occlusionTested = false; + m_occlusionQueryTransparent = 0; + m_occlusionTestedTransparent = false; + m_activeQuery = false; } -KROctreeNode::KROctreeNode(const KRVector3 &minPoint, const KRVector3 &maxPoint, int iChild, KROctreeNode *pChild) +KROctreeNode::KROctreeNode(const KRAABB &bounds, int iChild, KROctreeNode *pChild) : m_bounds(bounds) { // This constructor is used when expanding the octree and replacing the root node with a new root that encapsulates it - m_minPoint = minPoint; - m_maxPoint = maxPoint; for(int i=0; i<8; i++) m_children[i] = NULL; m_children[iChild] = pChild; + + m_occlusionQuery = 0; + m_occlusionTested = false; + m_occlusionQueryTransparent = 0; + m_occlusionTestedTransparent = false; + m_activeQuery = false; } KROctreeNode::~KROctreeNode() @@ -32,28 +40,105 @@ KROctreeNode::~KROctreeNode() delete m_children[i]; } } + + if(m_occlusionTested) { + glDeleteQueriesEXT(1, &m_occlusionQuery); + } + if(m_occlusionTestedTransparent) { + glDeleteQueriesEXT(1, &m_occlusionQueryTransparent); + } +} + + +void KROctreeNode::beginOcclusionQuery(bool bTransparentPass) +{ + if(bTransparentPass && !m_occlusionTestedTransparent) { + glGenQueriesEXT(1, &m_occlusionQueryTransparent); + glBeginQueryEXT(GL_ANY_SAMPLES_PASSED_EXT, m_occlusionQueryTransparent); + m_occlusionTestedTransparent = true; + m_activeQuery = true; + } else if(!bTransparentPass && !m_occlusionTested){ + glGenQueriesEXT(1, &m_occlusionQuery); + glBeginQueryEXT(GL_ANY_SAMPLES_PASSED_EXT, m_occlusionQuery); + m_occlusionTested = true; + m_activeQuery = true; + } +} + +void KROctreeNode::endOcclusionQuery() +{ + if(m_activeQuery) { + // Only end a query if we started one + glEndQueryEXT(GL_ANY_SAMPLES_PASSED_EXT); + } +} + +bool KROctreeNode::getOcclusionQueryResults(std::set &renderedBounds) +{ + bool bRendered = false; + bool bGoDeeper = false; + + if(m_occlusionTested) { + GLuint params = 0; + glGetQueryObjectuivEXT(m_occlusionQuery, GL_QUERY_RESULT_EXT, ¶ms); + if(params) bRendered = true; // At least one opaque fragment processed + + glDeleteQueriesEXT(1, &m_occlusionQuery); + m_occlusionTested = false; + bGoDeeper = true; + } + if(m_occlusionTestedTransparent) { + GLuint params = 0; + glGetQueryObjectuivEXT(m_occlusionQueryTransparent, GL_QUERY_RESULT_EXT, ¶ms); + if(params) bRendered = true; // At least one transparent fragment processed + + glDeleteQueriesEXT(1, &m_occlusionQueryTransparent); + m_occlusionTestedTransparent = false; + + bGoDeeper = true; + } + + if(bGoDeeper) { // Only recurse deeper if we reached this level in the previous pass + for(int i=0; i<8; i++) { + if(m_children[i]) { + if(m_children[i]->getOcclusionQueryResults(renderedBounds)) { + bRendered = true; // We must always include the parent, even if the parent's local scene graph nodes are fully occluded + } + } + } + } + + if(bRendered) { + renderedBounds.insert(m_bounds); + } + + return bRendered; +} + +KRAABB KROctreeNode::getBounds() +{ + return m_bounds; } void KROctreeNode::add(KRNode *pNode) { - - - KRVector3 center = (m_minPoint + m_maxPoint) / 2.0f; + KRVector3 center = m_bounds.center(); int iChild = getChildIndex(pNode); if(iChild == -1) { m_sceneNodes.insert(pNode); } else { if(m_children[iChild] == NULL) { - m_children[iChild] = new KROctreeNode( - KRVector3( - (iChild & 1) == 0 ? m_minPoint.x : center.x, - (iChild & 2) == 0 ? m_minPoint.y : center.y, - (iChild & 4) == 0 ? m_minPoint.z : center.z), - KRVector3( - (iChild & 1) == 0 ? center.x : m_maxPoint.x, - (iChild & 2) == 0 ? center.y : m_maxPoint.y, - (iChild & 4) == 0 ? center.z : m_maxPoint.z) + m_children[iChild] = new KROctreeNode(KRAABB( + KRVector3( + (iChild & 1) == 0 ? m_bounds.min.x : center.x, + (iChild & 2) == 0 ? m_bounds.min.y : center.y, + (iChild & 4) == 0 ? m_bounds.min.z : center.z), + KRVector3( + (iChild & 1) == 0 ? center.x : m_bounds.max.x, + (iChild & 2) == 0 ? center.y : m_bounds.max.y, + (iChild & 4) == 0 ? center.z : m_bounds.max.z) + ) ); } m_children[iChild]->add(pNode); @@ -73,7 +158,7 @@ int KROctreeNode::getChildIndex(KRNode *pNode) // 6: max.x < center.x && min.y > center.y && min.z > center.z // 7: min.x > center.x && min.y > center.y && min.z > center.z - KRVector3 center = (m_minPoint + m_maxPoint) / 2.0f; + KRVector3 center = m_bounds.center(); int iChild = -1; if(max.z < center.z) { if(max.y < center.y) { @@ -126,16 +211,6 @@ void KROctreeNode::update(KRNode *pNode) } -KRVector3 KROctreeNode::getMinPoint() -{ - return m_minPoint; -} - -KRVector3 KROctreeNode::getMaxPoint() -{ - return m_maxPoint; -} - bool KROctreeNode::isEmpty() const { for(int i=0; i<8; i++) { diff --git a/KREngine/KREngine/Classes/KROctreeNode.h b/KREngine/KREngine/Classes/KROctreeNode.h index 79883f6..601b147 100644 --- a/KREngine/KREngine/Classes/KROctreeNode.h +++ b/KREngine/KREngine/Classes/KROctreeNode.h @@ -11,13 +11,14 @@ #import "KREngine-common.h" #include "KRVector3.h" +#include "KRAABB.h" class KRNode; class KROctreeNode { public: - KROctreeNode(const KRVector3 &minPoint, const KRVector3 &maxPoint); - KROctreeNode(const KRVector3 &minPoint, const KRVector3 &maxPoint, int iChild, KROctreeNode *pChild); + KROctreeNode(const KRAABB &bounds); + KROctreeNode(const KRAABB &bounds, int iChild, KROctreeNode *pChild); ~KROctreeNode(); KROctreeNode **getChildren(); @@ -27,8 +28,7 @@ public: void remove(KRNode *pNode); void update(KRNode *pNode); - KRVector3 getMinPoint(); - KRVector3 getMaxPoint(); + KRAABB getBounds(); void setChildNode(int iChild, KROctreeNode *pChild); int getChildIndex(KRNode *pNode); @@ -37,9 +37,21 @@ public: bool canShrinkRoot() const; KROctreeNode *stripChild(); + void beginOcclusionQuery(bool bTransparentPass); + void endOcclusionQuery(); + bool getOcclusionQueryResults(std::set &renderedBounds); + private: - KRVector3 m_minPoint; - KRVector3 m_maxPoint; + + GLuint m_occlusionQuery; + bool m_occlusionTested; + + GLuint m_occlusionQueryTransparent; + bool m_occlusionTestedTransparent; + + bool m_activeQuery; + + KRAABB m_bounds; KROctreeNode *m_children[8]; diff --git a/KREngine/KREngine/Classes/KRScene.cpp b/KREngine/KREngine/Classes/KRScene.cpp index 06898ed..13860b3 100644 --- a/KREngine/KREngine/Classes/KRScene.cpp +++ b/KREngine/KREngine/Classes/KRScene.cpp @@ -54,7 +54,7 @@ KRScene::~KRScene() { #if TARGET_OS_IPHONE -void KRScene::render(KRCamera *pCamera, KRContext *pContext, KRBoundingVolume &frustrumVolume, KRMat4 &viewMatrix, KRVector3 &cameraPosition, KRVector3 &lightDirection, KRMat4 *pShadowMatrices, GLuint *shadowDepthTextures, int cShadowBuffers, KRNode::RenderPass renderPass) { +void KRScene::render(KRCamera *pCamera, std::set &visibleBounds, KRContext *pContext, KRBoundingVolume &frustrumVolume, KRMat4 &viewMatrix, KRVector3 &cameraPosition, KRVector3 &lightDirection, KRMat4 *pShadowMatrices, GLuint *shadowDepthTextures, int cShadowBuffers, KRNode::RenderPass renderPass) { updateOctree(); @@ -124,7 +124,7 @@ void KRScene::render(KRCamera *pCamera, KRContext *pContext, KRBoundingVolume &f */ //m_pRootNode->render(pCamera, pContext, frustrumVolume, viewMatrix, cameraPosition, forward_render_light_direction, pShadowMatrices, shadowDepthTextures, cShadowBuffers, renderPass); - render(m_nodeTree.getRootNode(), pCamera, pContext, frustrumVolume, viewMatrix, cameraPosition, forward_render_light_direction, pShadowMatrices, shadowDepthTextures, cShadowBuffers, renderPass); + render(m_nodeTree.getRootNode(), visibleBounds, pCamera, pContext, frustrumVolume, viewMatrix, cameraPosition, forward_render_light_direction, pShadowMatrices, shadowDepthTextures, cShadowBuffers, renderPass); for(std::set::iterator itr=m_nodeTree.getOuterSceneNodes().begin(); itr != m_nodeTree.getOuterSceneNodes().end(); itr++) { @@ -132,14 +132,16 @@ void KRScene::render(KRCamera *pCamera, KRContext *pContext, KRBoundingVolume &f } } -void KRScene::render(KROctreeNode *pOctreeNode, KRCamera *pCamera, KRContext *pContext, KRBoundingVolume &frustrumVolume, KRMat4 &viewMatrix, KRVector3 &cameraPosition, KRVector3 &lightDirection, KRMat4 *pShadowMatrices, GLuint *shadowDepthTextures, int cShadowBuffers, KRNode::RenderPass renderPass) +void KRScene::render(KROctreeNode *pOctreeNode, std::set &visibleBounds, KRCamera *pCamera, KRContext *pContext, KRBoundingVolume &frustrumVolume, KRMat4 &viewMatrix, KRVector3 &cameraPosition, KRVector3 &lightDirection, KRMat4 *pShadowMatrices, GLuint *shadowDepthTextures, int cShadowBuffers, KRNode::RenderPass renderPass) { if(pOctreeNode) { + pOctreeNode->beginOcclusionQuery(renderPass == KRNode::RENDER_PASS_FORWARD_TRANSPARENT); for(std::set::iterator itr=pOctreeNode->getSceneNodes().begin(); itr != pOctreeNode->getSceneNodes().end(); itr++) { (*itr)->render(pCamera, pContext, frustrumVolume, viewMatrix, cameraPosition, lightDirection, pShadowMatrices, shadowDepthTextures, cShadowBuffers, renderPass); } + pOctreeNode->endOcclusionQuery(); for(int i=0; i<8; i++) { - render(pOctreeNode->getChildren()[i], pCamera, pContext, frustrumVolume, viewMatrix, cameraPosition, lightDirection, pShadowMatrices, shadowDepthTextures, cShadowBuffers, renderPass); + render(pOctreeNode->getChildren()[i], visibleBounds, pCamera, pContext, frustrumVolume, viewMatrix, cameraPosition, lightDirection, pShadowMatrices, shadowDepthTextures, cShadowBuffers, renderPass); } } } @@ -258,3 +260,8 @@ void KRScene::updateOctree() m_newNodes.clear(); m_modifiedNodes.clear(); } + +void KRScene::getOcclusionQueryResults(std::set &renderedBounds) +{ + m_nodeTree.getOcclusionQueryResults(renderedBounds); +} diff --git a/KREngine/KREngine/Classes/KRScene.h b/KREngine/KREngine/Classes/KRScene.h index 669bc35..e88d274 100644 --- a/KREngine/KREngine/Classes/KRScene.h +++ b/KREngine/KREngine/Classes/KRScene.h @@ -64,9 +64,12 @@ public: #if TARGET_OS_IPHONE - void render(KRCamera *pCamera, KRContext *pContext, KRBoundingVolume &frustrumVolume, KRMat4 &viewMatrix, KRVector3 &cameraPosition, KRVector3 &lightDirection, KRMat4 *pShadowMatrices, GLuint *shadowDepthTextures, int cShadowBuffers, KRNode::RenderPass renderPass); + void render(KRCamera *pCamera, std::set &visibleBounds, KRContext *pContext, KRBoundingVolume &frustrumVolume, KRMat4 &viewMatrix, KRVector3 &cameraPosition, KRVector3 &lightDirection, KRMat4 *pShadowMatrices, GLuint *shadowDepthTextures, int cShadowBuffers, KRNode::RenderPass renderPass); - void render(KROctreeNode *pOctreeNode, KRCamera *pCamera, KRContext *pContext, KRBoundingVolume &frustrumVolume, KRMat4 &viewMatrix, KRVector3 &cameraPosition, KRVector3 &lightDirection, KRMat4 *pShadowMatrices, GLuint *shadowDepthTextures, int cShadowBuffers, KRNode::RenderPass renderPass); + void render(KROctreeNode *pOctreeNode, std::set &visibleBounds, KRCamera *pCamera, KRContext *pContext, KRBoundingVolume &frustrumVolume, KRMat4 &viewMatrix, KRVector3 &cameraPosition, KRVector3 &lightDirection, KRMat4 *pShadowMatrices, GLuint *shadowDepthTextures, int cShadowBuffers, KRNode::RenderPass renderPass); + + + void getOcclusionQueryResults(std::set &renderedBounds); #endif diff --git a/KREngine/KREngine/Classes/KRVector3.cpp b/KREngine/KREngine/Classes/KRVector3.cpp index a6f5c64..b8f5345 100644 --- a/KREngine/KREngine/Classes/KRVector3.cpp +++ b/KREngine/KREngine/Classes/KRVector3.cpp @@ -255,3 +255,38 @@ float KRVector3::Dot(const KRVector3 &v1, const KRVector3 &v2) { return v1.x * v2.x + v1.y * v2.y + v1.z * v2.z; } +bool KRVector3::operator >(const KRVector3& b) const +{ + // Comparison operators are implemented to allow insertion into sorted containers such as std::set + if(x > b.x) { + return true; + } else if(x < b.x) { + return false; + } else if(y > b.y) { + return true; + } else if(y < b.y) { + return false; + } else if(z > b.z) { + return true; + } else { + return false; + } +} + +bool KRVector3::operator <(const KRVector3& b) const +{ + // Comparison operators are implemented to allow insertion into sorted containers such as std::set + if(x < b.x) { + return true; + } else if(x > b.x) { + return false; + } else if(y < b.y) { + return true; + } else if(y > b.y) { + return false; + } else if(z < b.z) { + return true; + } else { + return false; + } +} diff --git a/KREngine/KREngine/Classes/KRVector3.h b/KREngine/KREngine/Classes/KRVector3.h index 3ece381..07cb32b 100644 --- a/KREngine/KREngine/Classes/KRVector3.h +++ b/KREngine/KREngine/Classes/KRVector3.h @@ -62,6 +62,10 @@ public: bool operator ==(const KRVector3& b) const; bool operator !=(const KRVector3& b) const; + // Comparison operators are implemented to allow insertion into sorted containers such as std::set + bool operator >(const KRVector3& b) const; + bool operator <(const KRVector3& b) const; + float& operator[](unsigned i); float operator[](unsigned i) const;