diff --git a/KREngine/KREngine/Classes/KRAABB.cpp b/KREngine/KREngine/Classes/KRAABB.cpp index 9477bf1..119fe4f 100644 --- a/KREngine/KREngine/Classes/KRAABB.cpp +++ b/KREngine/KREngine/Classes/KRAABB.cpp @@ -8,6 +8,7 @@ #include "KRAABB.h" #include "KRMat4.h" +#include "assert.h" KRAABB::KRAABB(const KRVector3 &minPoint, const KRVector3 &maxPoint) { @@ -87,6 +88,11 @@ bool KRAABB::contains(const KRAABB &b) const return b.min.x >= min.x && b.min.y >= min.y && b.min.z >= min.z && b.max.x <= max.x && b.max.y <= max.y && b.max.z <= max.z; } +bool KRAABB::contains(const KRVector3 &v) const +{ + return v.x >= min.x && v.x <= max.x && v.y >= min.y && v.y <= max.y && v.z >= min.z && v.z <= max.z; +} + KRAABB KRAABB::Infinite() { return KRAABB(KRVector3::Min(), KRVector3::Max()); @@ -102,13 +108,13 @@ bool KRAABB::visible(const KRMat4 &matViewProjection) const int outside_count[6] = {0, 0, 0, 0, 0, 0}; for(int iCorner=0; iCorner<8; iCorner++) { - KRVector3 cornerVertex = KRVector3( + KRVector3 sourceCornerVertex = KRVector3( (iCorner & 1) == 0 ? min.x : max.x, (iCorner & 2) == 0 ? min.y : max.y, (iCorner & 4) == 0 ? min.z : max.z); - - cornerVertex = KRMat4::Dot(matViewProjection, cornerVertex); - float cornerVertexW = KRMat4::DotW(matViewProjection, cornerVertex); + + KRVector3 cornerVertex = KRMat4::Dot(matViewProjection, sourceCornerVertex); + float cornerVertexW = KRMat4::DotW(matViewProjection, sourceCornerVertex); if(cornerVertex.x < -cornerVertexW) { outside_count[0]++; @@ -130,6 +136,37 @@ bool KRAABB::visible(const KRMat4 &matViewProjection) const } } +// for(int iCorner=0; iCorner<8; iCorner++) { +// KRVector3 sourceCornerVertex = KRVector3( +// (iCorner & 1) == 0 ? min.x : max.x, +// (iCorner & 2) == 0 ? min.y : max.y, +// (iCorner & 4) == 0 ? min.z : max.z); +// +// KRVector3 cornerVertex = KRMat4::Dot(matViewProjection, sourceCornerVertex); +// float cornerVertexW = KRMat4::DotW(matViewProjection, sourceCornerVertex); +// cornerVertex /= cornerVertexW; +// +// +// if(cornerVertex.x < -1.0) { +// outside_count[0]++; +// } +// if(cornerVertex.y < -1.0) { +// outside_count[1]++; +// } +// if(cornerVertex.z < -1.0) { +// outside_count[2]++; +// } +// if(cornerVertex.x > 1.0) { +// outside_count[3]++; +// } +// if(cornerVertex.y > 1.0) { +// outside_count[4]++; +// } +// if(cornerVertex.z > 1.0) { +// outside_count[5]++; +// } +// } + bool is_visible = true; for(int iFace=0; iFace < 6; iFace++) { if(outside_count[iFace] == 8) { @@ -138,9 +175,10 @@ bool KRAABB::visible(const KRMat4 &matViewProjection) const } if(!is_visible) { - fprintf(stderr, "AABB culled: %i%i%i%i%i%i out, (%f, %f, %f) - (%f, %f, %f)\n", outside_count[0], outside_count[1], outside_count[2], outside_count[3], outside_count[4], outside_count[5], min.x, min.y, min.z, max.x, max.y, max.z); + //fprintf(stderr, "AABB culled: %i%i%i%i%i%i out, (%f, %f, %f) - (%f, %f, %f)\n", outside_count[0], outside_count[1], outside_count[2], outside_count[3], outside_count[4], outside_count[5], min.x, min.y, min.z, max.x, max.y, max.z); } else { - fprintf(stderr, "AABB visible: %i%i%i%i%i%i out, (%f, %f, %f) - (%f, %f, %f)\n", outside_count[0], outside_count[1], outside_count[2], outside_count[3], outside_count[4], outside_count[5], min.x, min.y, min.z, max.x, max.y, max.z); + //fprintf(stderr, "AABB visible: %i%i%i%i%i%i out, (%f, %f, %f) - (%f, %f, %f)\n", outside_count[0], outside_count[1], outside_count[2], outside_count[3], outside_count[4], outside_count[5], min.x, min.y, min.z, max.x, max.y, max.z); } + //is_visible = true; return is_visible; } diff --git a/KREngine/KREngine/Classes/KRAABB.h b/KREngine/KREngine/Classes/KRAABB.h index b1ee5c5..481ba5c 100644 --- a/KREngine/KREngine/Classes/KRAABB.h +++ b/KREngine/KREngine/Classes/KRAABB.h @@ -24,6 +24,7 @@ public: KRVector3 size() const; bool intersects(const KRAABB& b) const; bool contains(const KRAABB &b) const; + bool contains(const KRVector3 &v) const; bool visible(const KRMat4 &matViewProjection) const; KRAABB& operator =(const KRAABB& b); diff --git a/KREngine/KREngine/Classes/KRCamera.cpp b/KREngine/KREngine/Classes/KRCamera.cpp index c96c0ad..3cf0297 100644 --- a/KREngine/KREngine/Classes/KRCamera.cpp +++ b/KREngine/KREngine/Classes/KRCamera.cpp @@ -192,6 +192,9 @@ void KRCamera::renderFrame(KRScene &scene, KRMat4 &viewMatrix, KRVector3 &lightD setViewportSize(KRVector2(backingWidth, backingHeight)); KRBoundingVolume frustrumVolume = KRBoundingVolume(viewMatrix, perspective_fov, getViewportSize().x / getViewportSize().y, perspective_nearz, perspective_farz); + + std::set newVisibleBounds; + if(bEnableDeferredLighting) { // ----====---- Opaque Geometry, Deferred rendering Pass 1 ----====---- @@ -216,7 +219,7 @@ void KRCamera::renderFrame(KRScene &scene, KRMat4 &viewMatrix, KRVector3 &lightD GLDEBUG(glDisable(GL_BLEND)); // Render the geometry - scene.render(this, m_visibleBounds, 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, newVisibleBounds); // ----====---- Opaque Geometry, Deferred rendering Pass 2 ----====---- // Set render target @@ -242,9 +245,7 @@ void KRCamera::renderFrame(KRScene &scene, KRMat4 &viewMatrix, KRVector3 &lightD // Render the geometry - scene.render(this, m_visibleBounds, m_pContext, frustrumVolume, viewMatrix, cameraPosition, lightDirection, shadowmvpmatrix, shadowDepthTexture, 0, KRNode::RENDER_PASS_DEFERRED_LIGHTS); - - scene.getOcclusionQueryResults(m_visibleBounds); + scene.render(this, m_visibleBounds, m_pContext, frustrumVolume, viewMatrix, cameraPosition, lightDirection, shadowmvpmatrix, shadowDepthTexture, 0, KRNode::RENDER_PASS_DEFERRED_LIGHTS, newVisibleBounds); // ----====---- Opaque Geometry, Deferred rendering Pass 3 ----====---- // Set render target @@ -275,7 +276,8 @@ void KRCamera::renderFrame(KRScene &scene, KRMat4 &viewMatrix, KRVector3 &lightD GLDEBUG(glDepthMask(GL_TRUE)); // Render the geometry - scene.render(this, m_visibleBounds, m_pContext, frustrumVolume, viewMatrix, cameraPosition, lightDirection, shadowmvpmatrix, shadowDepthTexture, m_cShadowBuffers, KRNode::RENDER_PASS_DEFERRED_OPAQUE); + std::set emptyBoundsSet; // At this point, we only render octree nodes that produced fragments during the 1st pass into the GBuffer + scene.render(this, emptyBoundsSet, m_pContext, frustrumVolume, viewMatrix, cameraPosition, lightDirection, shadowmvpmatrix, shadowDepthTexture, m_cShadowBuffers, KRNode::RENDER_PASS_DEFERRED_OPAQUE, newVisibleBounds); // Deactivate source buffer texture units m_pContext->getTextureManager()->selectTexture(6, NULL); @@ -312,9 +314,7 @@ void KRCamera::renderFrame(KRScene &scene, KRMat4 &viewMatrix, KRVector3 &lightD // Render the geometry - scene.render(this, m_visibleBounds, m_pContext, frustrumVolume, viewMatrix, cameraPosition, lightDirection, shadowmvpmatrix, shadowDepthTexture, m_cShadowBuffers, KRNode::RENDER_PASS_FORWARD_OPAQUE); - - scene.getOcclusionQueryResults(m_visibleBounds); + scene.render(this, m_visibleBounds, m_pContext, frustrumVolume, viewMatrix, cameraPosition, lightDirection, shadowmvpmatrix, shadowDepthTexture, m_cShadowBuffers, KRNode::RENDER_PASS_FORWARD_OPAQUE, newVisibleBounds); } // ----====---- Transparent Geometry, Forward Rendering ----====---- @@ -339,7 +339,7 @@ void KRCamera::renderFrame(KRScene &scene, KRMat4 &viewMatrix, KRVector3 &lightD GLDEBUG(glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)); // Render all transparent geometry - scene.render(this, m_visibleBounds, 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, newVisibleBounds); // ----====---- Flares ----====---- @@ -363,7 +363,7 @@ void KRCamera::renderFrame(KRScene &scene, KRMat4 &viewMatrix, KRVector3 &lightD GLDEBUG(glBlendFunc(GL_ONE, GL_ONE)); // Render all flares - scene.render(this, m_visibleBounds, 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, newVisibleBounds); // ----====---- Debug Overlay ----====---- @@ -395,15 +395,13 @@ void KRCamera::renderFrame(KRScene &scene, KRMat4 &viewMatrix, KRVector3 &lightD } } -// scene.getOcclusionQueryResults(m_visibleBounds); - - // fprintf(stderr, "visible bounds: %i\n", (int)m_visibleBounds.size()); + m_visibleBounds = newVisibleBounds; // Re-enable z-buffer write GLDEBUG(glDepthMask(GL_TRUE)); - fprintf(stderr, "VBO Mem: %i Kbyte Texture Mem: %i Kbyte Shader Handles: %i\n", (int)m_pContext->getModelManager()->getMemUsed() / 1024, (int)m_pContext->getTextureManager()->getMemUsed() / 1024, (int)m_pContext->getShaderManager()->getShaderHandlesUsed()); + fprintf(stderr, "VBO Mem: %i Kbyte Texture Mem: %i Kbyte Shader Handles: %i Visible Bounds: %i\n", (int)m_pContext->getModelManager()->getMemUsed() / 1024, (int)m_pContext->getTextureManager()->getMemUsed() / 1024, (int)m_pContext->getShaderManager()->getShaderHandlesUsed(), (int)m_visibleBounds.size()); } @@ -574,8 +572,10 @@ void KRCamera::renderShadowBuffer(KRScene &scene, int iShadow) KRVector3 cameraPosition; KRVector3 lightDirection; KRBoundingVolume shadowVolume = KRBoundingVolume(vertices); - 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]); + + std::set newVisibleBounds; + scene.render(this, m_shadowVisibleBounds[iShadow], m_pContext, shadowVolume, shadowmvpmatrix[iShadow], cameraPosition, lightDirection, shadowmvpmatrix, NULL, m_cShadowBuffers, KRNode::RENDER_PASS_SHADOWMAP, newVisibleBounds); + m_shadowVisibleBounds[iShadow] = newVisibleBounds; GLDEBUG(glViewport(0, 0, backingWidth, backingHeight)); } diff --git a/KREngine/KREngine/Classes/KRInstance.cpp b/KREngine/KREngine/Classes/KRInstance.cpp index 90965f0..fbfd72c 100644 --- a/KREngine/KREngine/Classes/KRInstance.cpp +++ b/KREngine/KREngine/Classes/KRInstance.cpp @@ -91,8 +91,8 @@ void KRInstance::render(KRCamera *pCamera, KRContext *pContext, KRBoundingVolume } if(m_pModel != NULL) { - if(getExtents(pContext).test_intersect(frustrumVolume) || renderPass == RENDER_PASS_SHADOWMAP) { - //if(m_pModel != NULL && (getBounds().visible(viewMatrix * projectionMatrix) || renderPass == RENDER_PASS_SHADOWMAP)) { + //if(getExtents(pContext).test_intersect(frustrumVolume) || renderPass == RENDER_PASS_SHADOWMAP) { + if(getBounds().visible(viewMatrix * projectionMatrix)) { if(m_pLightMap == NULL && m_lightMap.size()) { m_pLightMap = pContext->getTextureManager()->getTexture(m_lightMap.c_str()); diff --git a/KREngine/KREngine/Classes/KROctree.cpp b/KREngine/KREngine/Classes/KROctree.cpp index 5f8dcc3..c66ec86 100644 --- a/KREngine/KREngine/Classes/KROctree.cpp +++ b/KREngine/KREngine/Classes/KROctree.cpp @@ -91,12 +91,3 @@ std::set &KROctree::getOuterSceneNodes() { return m_outerSceneNodes; } -#if TARGET_OS_IPHONE -void KROctree::getOcclusionQueryResults(std::set &renderedBounds) -{ - renderedBounds.clear(); - if(m_pRootNode) { - m_pRootNode->getOcclusionQueryResults(renderedBounds); - } -} -#endif diff --git a/KREngine/KREngine/Classes/KROctree.h b/KREngine/KREngine/Classes/KROctree.h index a0028e8..1572013 100644 --- a/KREngine/KREngine/Classes/KROctree.h +++ b/KREngine/KREngine/Classes/KROctree.h @@ -26,9 +26,7 @@ public: KROctreeNode *getRootNode(); std::set &getOuterSceneNodes(); -#if TARGET_OS_IPHONE - void getOcclusionQueryResults(std::set &renderedBounds); -#endif + private: KROctreeNode *m_pRootNode; std::setm_outerSceneNodes; diff --git a/KREngine/KREngine/Classes/KROctreeNode.cpp b/KREngine/KREngine/Classes/KROctreeNode.cpp index 41508d2..d2480cf 100644 --- a/KREngine/KREngine/Classes/KROctreeNode.cpp +++ b/KREngine/KREngine/Classes/KROctreeNode.cpp @@ -15,8 +15,6 @@ KROctreeNode::KROctreeNode(const KRAABB &bounds) : m_bounds(bounds) m_occlusionQuery = 0; m_occlusionTested = false; - m_occlusionQueryTransparent = 0; - m_occlusionTestedTransparent = false; m_activeQuery = false; } @@ -28,8 +26,6 @@ KROctreeNode::KROctreeNode(const KRAABB &bounds, int iChild, KROctreeNode *pChil m_occlusionQuery = 0; m_occlusionTested = false; - m_occlusionQueryTransparent = 0; - m_occlusionTestedTransparent = false; m_activeQuery = false; } @@ -44,21 +40,13 @@ KROctreeNode::~KROctreeNode() if(m_occlusionTested) { GLDEBUG(glDeleteQueriesEXT(1, &m_occlusionQuery)); } - if(m_occlusionTestedTransparent) { - GLDEBUG(glDeleteQueriesEXT(1, &m_occlusionQueryTransparent)); - } #endif } #if TARGET_OS_IPHONE -void KROctreeNode::beginOcclusionQuery(bool bTransparentPass) +void KROctreeNode::beginOcclusionQuery() { - if(bTransparentPass && !m_occlusionTestedTransparent) { - GLDEBUG(glGenQueriesEXT(1, &m_occlusionQueryTransparent)); - GLDEBUG(glBeginQueryEXT(GL_ANY_SAMPLES_PASSED_EXT, m_occlusionQueryTransparent)); - m_occlusionTestedTransparent = true; - m_activeQuery = true; - } else if(!bTransparentPass && !m_occlusionTested){ + if(!m_occlusionTested){ GLDEBUG(glGenQueriesEXT(1, &m_occlusionQuery)); GLDEBUG(glBeginQueryEXT(GL_ANY_SAMPLES_PASSED_EXT, m_occlusionQuery)); m_occlusionTested = true; @@ -74,54 +62,9 @@ void KROctreeNode::endOcclusionQuery() } } -bool KROctreeNode::getOcclusionQueryResults(std::set &renderedBounds) -{ - bool bRendered = false; - bool bGoDeeper = false; - - if(m_occlusionTested) { - GLuint params = 0; - GLDEBUG(glGetQueryObjectuivEXT(m_occlusionQuery, GL_QUERY_RESULT_EXT, ¶ms)); - if(params) bRendered = true; // At least one opaque fragment processed - - GLDEBUG(glDeleteQueriesEXT(1, &m_occlusionQuery)); - m_occlusionTested = false; - bGoDeeper = true; - } - if(m_occlusionTestedTransparent) { - GLuint params = 0; - GLDEBUG(glGetQueryObjectuivEXT(m_occlusionQueryTransparent, GL_QUERY_RESULT_EXT, ¶ms)); - if(params) bRendered = true; // At least one transparent fragment processed - - GLDEBUG(glDeleteQueriesEXT(1, &m_occlusionQueryTransparent)); - m_occlusionTestedTransparent = false; - - bGoDeeper = true; - } - - // FINDME - Test Code: - //bGoDeeper = true; - //bRendered = 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; -} - #endif + KRAABB KROctreeNode::getBounds() { return m_bounds; @@ -157,55 +100,7 @@ KRAABB KROctreeNode::getChildBounds(int iChild) } int KROctreeNode::getChildIndex(KRNode *pNode) -{ - /* - - KRVector3 min = pNode->getMinPoint(); - KRVector3 max = pNode->getMaxPoint(); - - // 0: max.x < center.x && max.y < center.y && max.z < center.z - // 1: min.x > center.x && max.y < center.y && max.z < center.z - // 2: max.x < center.x && min.y > center.y && max.z < center.z - // 3: min.x > center.x && min.y > center.y && max.z < center.z - // 4: max.x < center.x && max.y < center.y && min.z > center.z - // 5: min.x > center.x && max.y < center.y && min.z > center.z - // 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_bounds.center(); - int iChild = -1; - if(max.z < center.z) { - if(max.y < center.y) { - if(max.x < center.x) { - iChild = 0; - } else if(min.x > center.x) { - iChild = 1; - } - } else if(min.y > center.y) { - if(max.x < center.x) { - iChild = 2; - } else if(min.x > center.x) { - iChild = 3; - } - } - } else if(min.z > center.z) { - if(max.y < center.y) { - if(min.x > center.x) { - iChild = 4; - } else if(min.x > center.x) { - iChild = 5; - } - } else if(min.y > center.y) { - if(max.x < center.x) { - iChild = 6; - } else if(min.x > center.x) { - iChild = 7; - } - } - } - return iChild; - */ - +{ for(int iChild=0; iChild < 8; iChild++) { if(getChildBounds(iChild).contains(pNode->getBounds())) { return iChild; diff --git a/KREngine/KREngine/Classes/KROctreeNode.h b/KREngine/KREngine/Classes/KROctreeNode.h index 8f38303..77b7e9d 100644 --- a/KREngine/KREngine/Classes/KROctreeNode.h +++ b/KREngine/KREngine/Classes/KROctreeNode.h @@ -38,19 +38,14 @@ public: bool canShrinkRoot() const; KROctreeNode *stripChild(); - void beginOcclusionQuery(bool bTransparentPass); + void beginOcclusionQuery(); void endOcclusionQuery(); - bool getOcclusionQueryResults(std::set &renderedBounds); -private: GLuint m_occlusionQuery; bool m_occlusionTested; - - GLuint m_occlusionQueryTransparent; - bool m_occlusionTestedTransparent; - bool m_activeQuery; +private: KRAABB m_bounds; diff --git a/KREngine/KREngine/Classes/KRScene.cpp b/KREngine/KREngine/Classes/KRScene.cpp index 4bce639..50e2ebe 100644 --- a/KREngine/KREngine/Classes/KRScene.cpp +++ b/KREngine/KREngine/Classes/KRScene.cpp @@ -56,7 +56,7 @@ KRScene::~KRScene() { #if TARGET_OS_IPHONE -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) { +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, std::set &newVisibleBounds) { updateOctree(); @@ -103,7 +103,33 @@ void KRScene::render(KRCamera *pCamera, std::set &visibleBounds, KRConte pCamera->dSunB = sun_color.z; } - render(m_nodeTree.getRootNode(), visibleBounds, pCamera, pContext, frustrumVolume, viewMatrix, cameraPosition, forward_render_light_direction, pShadowMatrices, shadowDepthTextures, cShadowBuffers, renderPass); + std::vector remainingOctrees; + std::vector remainingOctreesTestResults; + std::vector remainingOctreesTestResultsOnly; + if(m_nodeTree.getRootNode() != NULL) { + remainingOctrees.push_back(m_nodeTree.getRootNode()); + } + + std::vector newRemainingOctrees; + std::vector newRemainingOctreesTestResults; + while((!remainingOctrees.empty() || !remainingOctreesTestResults.empty())) { + newRemainingOctrees.clear(); + newRemainingOctreesTestResults.clear(); + for(std::vector::iterator octree_itr = remainingOctrees.begin(); octree_itr != remainingOctrees.end(); octree_itr++) { + render(*octree_itr, visibleBounds, pCamera, pContext, frustrumVolume, viewMatrix, cameraPosition, forward_render_light_direction, pShadowMatrices, shadowDepthTextures, cShadowBuffers, renderPass, newRemainingOctrees, newRemainingOctreesTestResults, remainingOctreesTestResultsOnly, newVisibleBounds, false, false); + } + for(std::vector::iterator octree_itr = remainingOctreesTestResults.begin(); octree_itr != remainingOctreesTestResults.end(); octree_itr++) { + render(*octree_itr, visibleBounds, pCamera, pContext, frustrumVolume, viewMatrix, cameraPosition, forward_render_light_direction, pShadowMatrices, shadowDepthTextures, cShadowBuffers, renderPass, newRemainingOctrees, newRemainingOctreesTestResults, remainingOctreesTestResultsOnly, newVisibleBounds, true, false); + } + remainingOctrees = newRemainingOctrees; + remainingOctreesTestResults = newRemainingOctreesTestResults; + } + + newRemainingOctrees.clear(); + newRemainingOctreesTestResults.clear(); + for(std::vector::iterator octree_itr = remainingOctreesTestResultsOnly.begin(); octree_itr != remainingOctreesTestResultsOnly.end(); octree_itr++) { + render(*octree_itr, visibleBounds, pCamera, pContext, frustrumVolume, viewMatrix, cameraPosition, forward_render_light_direction, pShadowMatrices, shadowDepthTextures, cShadowBuffers, renderPass, newRemainingOctrees, newRemainingOctreesTestResults, remainingOctreesTestResultsOnly, newVisibleBounds, true, true); + } for(std::set::iterator itr=m_nodeTree.getOuterSceneNodes().begin(); itr != m_nodeTree.getOuterSceneNodes().end(); itr++) { @@ -111,61 +137,94 @@ void KRScene::render(KRCamera *pCamera, std::set &visibleBounds, KRConte } } -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) +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, std::vector &remainingOctrees, std::vector &remainingOctreesTestResults, std::vector &remainingOctreesTestResultsOnly, std::set &newVisibleBounds, bool bOcclusionResultsPass, bool bOcclusionTestResultsOnly) { if(pOctreeNode) { - KRMat4 projectionMatrix; - if(renderPass != KRNode::RENDER_PASS_SHADOWMAP) { - projectionMatrix = pCamera->getProjectionMatrix(); - } KRAABB octreeBounds = pOctreeNode->getBounds(); - KRBoundingVolume frustrumVolumeNoNearClip = KRBoundingVolume(viewMatrix, pCamera->perspective_fov, pCamera->m_viewportSize.x / pCamera->m_viewportSize.y, 0.0, pCamera->perspective_farz); - - //if(true) { - //if(pOctreeNode->getBounds().visible(viewMatrix * projectionMatrix)) { // Only recurse deeper if within the view frustrum - if(frustrumVolumeNoNearClip.test_intersect(pOctreeNode->getBounds())) { // Only recurse deeper if within the view frustrum + if(bOcclusionResultsPass) { + // ----====---- Occlusion results pass ----====---- + if(pOctreeNode->m_occlusionTested) { + GLuint params = 0; + GLDEBUG(glGetQueryObjectuivEXT(pOctreeNode->m_occlusionQuery, GL_QUERY_RESULT_EXT, ¶ms)); + if(params) { + newVisibleBounds.insert(octreeBounds); // Record the actual tests that succeeded during this frame + visibleBounds.insert(octreeBounds); // Update the list of tests that we won't repeat for subsequent passes during this frame + if(!bOcclusionTestResultsOnly) { + // Schedule a pass to perform the rendering + remainingOctrees.push_back(pOctreeNode); + } + } + + GLDEBUG(glDeleteQueriesEXT(1, &pOctreeNode->m_occlusionQuery)); + pOctreeNode->m_occlusionTested = false; + pOctreeNode->m_occlusionQuery = 0; + } + } else { - bool can_occlusion_test = renderPass == KRNode::RENDER_PASS_FORWARD_OPAQUE || renderPass == KRNode::RENDER_PASS_DEFERRED_GBUFFER/* || renderPass == KRNode::RENDER_PASS_FORWARD_TRANSPARENT*/; + +// KRBoundingVolume frustrumVolumeNoNearClip = KRBoundingVolume(viewMatrix, pCamera->perspective_fov, pCamera->m_viewportSize.x / pCamera->m_viewportSize.y, 0.0, pCamera->perspective_farz); +// if(frustrumVolumeNoNearClip.test_intersect(pOctreeNode->getBounds())) { // Only recurse deeper if within the view frustrum +// - // can_occlusion_test = false; - bool bVisible = true; - //bool bVisible = visibleBounds.find(octreeBounds) != visibleBounds.end(); - if(bVisible) { - if(can_occlusion_test) { - pOctreeNode->beginOcclusionQuery(renderPass == KRNode::RENDER_PASS_FORWARD_TRANSPARENT); - } - - // Occlusion test indicates that this bounding box was visible in the last frame - for(std::set::iterator itr=pOctreeNode->getSceneNodes().begin(); itr != pOctreeNode->getSceneNodes().end(); itr++) { - //assert(pOctreeNode->getBounds().contains((*itr)->getBounds())); // Sanity check - - (*itr)->render(pCamera, pContext, frustrumVolume, viewMatrix, cameraPosition, lightDirection, pShadowMatrices, shadowDepthTextures, cShadowBuffers, renderPass); - } - - if(can_occlusion_test) { - pOctreeNode->endOcclusionQuery(); - } - - - bool bRenderChildren = renderPass != KRNode::RENDER_PASS_DEFERRED_OPAQUE; - if(!bRenderChildren) { - bRenderChildren = visibleBounds.find(octreeBounds) != visibleBounds.end(); - } - if(bRenderChildren) { - for(int i=0; i<8; i++) { - render(pOctreeNode->getChildren()[i], visibleBounds, pCamera, pContext, frustrumVolume, viewMatrix, cameraPosition, lightDirection, pShadowMatrices, shadowDepthTextures, cShadowBuffers, renderPass); + + KRMat4 projectionMatrix; + if(renderPass != KRNode::RENDER_PASS_SHADOWMAP) { + projectionMatrix = pCamera->getProjectionMatrix(); + } + if(pOctreeNode->getBounds().visible(viewMatrix * projectionMatrix)) { // Only recurse deeper if within the view frustrum + + // ----====---- Rendering and occlusion test pass ----====---- + bool bVisible = false; + bool bNeedOcclusionTest = true; + + //bVisible = true; // FINDME - Test Code + + if(!bVisible) { + // Assume bounding boxes are visible without occlusion test queries if the camera is inside the box. + // The near clipping plane of the camera is taken into consideration by expanding the match area + KRMat4 invView = viewMatrix; + invView.invert(); + KRVector3 cameraPos = KRMat4::Dot(invView, KRVector3::Zero()); + KRAABB cameraExtents = KRAABB(cameraPos - KRVector3(pCamera->perspective_nearz), cameraPos + KRVector3(pCamera->perspective_nearz)); + bVisible = octreeBounds.intersects(cameraExtents); + if(bVisible) { + newVisibleBounds.insert(octreeBounds); // Record the actual tests that succeeded during this frame + visibleBounds.insert(octreeBounds); // Update the list of tests that we won't repeat for subsequent passes during this frame + bNeedOcclusionTest = false; } } - } else if(KRNode::RENDER_PASS_FORWARD_OPAQUE || renderPass == KRNode::RENDER_PASS_DEFERRED_OPAQUE) { - if(pOctreeNode->getSceneNodes().empty()) { - for(int i=0; i<8; i++) { - render(pOctreeNode->getChildren()[i], visibleBounds, pCamera, pContext, frustrumVolume, viewMatrix, cameraPosition, lightDirection, pShadowMatrices, shadowDepthTextures, cShadowBuffers, renderPass); + + if(!bVisible) { + // Check if an occlusion query from the prior pass has returned true + bVisible = newVisibleBounds.find(octreeBounds) != newVisibleBounds.end(); + if(bVisible) { + bNeedOcclusionTest = false; } - } else { - pOctreeNode->beginOcclusionQuery(renderPass == KRNode::RENDER_PASS_FORWARD_TRANSPARENT); + } + + if(!bVisible) { + // Take advantage of temporal consistency of visible elements from frame to frame + // If the previous frame rendered this octree, then attempt to render it in this frame without performing a pre-occlusion test + bVisible = visibleBounds.find(octreeBounds) != visibleBounds.end(); + // We don't set bNeedOcclusionTest to false here, as we need to perform an occlusion test to record if this octree node was visible for the next frame + } + + if(!bVisible) { + // Optimization: If this is an empty octree node with only a single child node, then immediately try to render the child node without an occlusion test for this higher level, as it would be more expensive than the occlusion test for the child + if(pOctreeNode->getSceneNodes().empty()) { + int child_count = 0; + for(int i=0; i<8; i++) { + if(pOctreeNode->getChildren()[i] != NULL) child_count++; + } + if(child_count == 1) bVisible = true; + } + } + + if(bNeedOcclusionTest) { + pOctreeNode->beginOcclusionQuery(); KRShader *pVisShader = m_pContext->getShaderManager()->getShader("occlusion_test", pCamera, false, false, false, 0, false, false, false, false, false, false, false, false, false, KRNode::RENDER_PASS_FORWARD_TRANSPARENT); @@ -180,22 +239,60 @@ void KRScene::render(KROctreeNode *pOctreeNode, std::set &visibleBounds, // Enable additive blending GLDEBUG(glEnable(GL_BLEND)); GLDEBUG(glBlendFunc(GL_ONE, GL_ONE)); - + + + if(renderPass == KRNode::RENDER_PASS_FORWARD_OPAQUE || + renderPass == KRNode::RENDER_PASS_DEFERRED_GBUFFER || + renderPass == KRNode::RENDER_PASS_DEFERRED_OPAQUE || + renderPass == KRNode::RENDER_PASS_SHADOWMAP) { + + // Disable z-buffer write + GLDEBUG(glDepthMask(GL_FALSE)); + } if(pVisShader->bind(pCamera, viewMatrix, mvpmatrix, cameraPosition, lightDirection, pShadowMatrices, shadowDepthTextures, 0, KRNode::RENDER_PASS_FORWARD_TRANSPARENT)) { GLDEBUG(glDrawArrays(GL_TRIANGLE_STRIP, 0, 14)); } + if(renderPass == KRNode::RENDER_PASS_FORWARD_OPAQUE || + renderPass == KRNode::RENDER_PASS_DEFERRED_GBUFFER || + renderPass == KRNode::RENDER_PASS_DEFERRED_OPAQUE || + renderPass == KRNode::RENDER_PASS_SHADOWMAP) { + + // Re-enable z-buffer write + GLDEBUG(glDepthMask(GL_TRUE)); + } + GLDEBUG(glDisable(GL_BLEND)); pOctreeNode->endOcclusionQuery(); + + + if(bVisible) { + // Schedule a pass to get the result of the occlusion test only for future frames and passes, without rendering the model or recurring further + remainingOctreesTestResultsOnly.push_back(pOctreeNode); + } else { + // Schedule a pass to get the result of the occlusion test and continue recursion and rendering if test is true + remainingOctreesTestResults.push_back(pOctreeNode); + } + } + + if(bVisible) { + + for(std::set::iterator itr=pOctreeNode->getSceneNodes().begin(); itr != pOctreeNode->getSceneNodes().end(); itr++) { + //assert(pOctreeNode->getBounds().contains((*itr)->getBounds())); // Sanity check + (*itr)->render(pCamera, pContext, frustrumVolume, viewMatrix, cameraPosition, lightDirection, pShadowMatrices, shadowDepthTextures, cShadowBuffers, renderPass); + } + + for(int i=0; i<8; i++) { + render(pOctreeNode->getChildren()[i], visibleBounds, pCamera, pContext, frustrumVolume, viewMatrix, cameraPosition, lightDirection, pShadowMatrices, shadowDepthTextures, cShadowBuffers, renderPass, remainingOctrees, remainingOctreesTestResults, remainingOctreesTestResultsOnly, newVisibleBounds, false, false); + } } } - - } else { - //fprintf(stderr, "Octree culled: (%f, %f, %f) - (%f, %f, %f)\n", pOctreeNode->getBounds().min.x, pOctreeNode->getBounds().min.y, pOctreeNode->getBounds().min.z, pOctreeNode->getBounds().max.x, pOctreeNode->getBounds().max.y, pOctreeNode->getBounds().max.z); + } } +// fprintf(stderr, "Octree culled: (%f, %f, %f) - (%f, %f, %f)\n", pOctreeNode->getBounds().min.x, pOctreeNode->getBounds().min.y, pOctreeNode->getBounds().min.z, pOctreeNode->getBounds().max.x, pOctreeNode->getBounds().max.y, pOctreeNode->getBounds().max.z); } #endif @@ -317,9 +414,4 @@ void KRScene::updateOctree() } #if TARGET_OS_IPHONE -void KRScene::getOcclusionQueryResults(std::set &renderedBounds) -{ - m_nodeTree.getOcclusionQueryResults(renderedBounds); -} - #endif diff --git a/KREngine/KREngine/Classes/KRScene.h b/KREngine/KREngine/Classes/KRScene.h index cbafd4d..44a0d21 100644 --- a/KREngine/KREngine/Classes/KRScene.h +++ b/KREngine/KREngine/Classes/KRScene.h @@ -64,12 +64,9 @@ public: #if TARGET_OS_IPHONE - 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(KRCamera *pCamera, std::set &visibleBounds, KRContext *pContext, KRBoundingVolume &frustrumVolume, KRMat4 &viewMatrix, KRVector3 &cameraPosition, KRVector3 &lightDirection, KRMat4 *pShadowMatrices, GLuint *shadowDepthTextures, int cShadowBuffers, KRNode::RenderPass renderPass, std::set &newVisibleBounds); - 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); + 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, std::vector &remainingOctrees, std::vector &remainingOctreesTestResults, std::vector &remainingOctreesTestResultsOnly, std::set &newVisibleBounds, bool bOcclusionResultsPass, bool bOcclusionTestResultsOnly); #endif diff --git a/KREngine/KREngine/Classes/KRTextureManager.h b/KREngine/KREngine/Classes/KRTextureManager.h index b3ead49..bc2837f 100644 --- a/KREngine/KREngine/Classes/KRTextureManager.h +++ b/KREngine/KREngine/Classes/KRTextureManager.h @@ -31,7 +31,7 @@ #define KRENGINE_MAX_TEXTURE_UNITS 8 #define KRENGINE_MAX_TEXTURE_HANDLES 10000 -#define KRENGINE_MAX_TEXTURE_MEM 100000000 +#define KRENGINE_MAX_TEXTURE_MEM 128000000 #ifndef KRTEXTUREMANAGER_H #define KRTEXTUREMANAGER_H diff --git a/KREngine/KREngine/Shaders/occlusion_test.fsh b/KREngine/KREngine/Shaders/occlusion_test.fsh index 53c21a3..5beec00 100644 --- a/KREngine/KREngine/Shaders/occlusion_test.fsh +++ b/KREngine/KREngine/Shaders/occlusion_test.fsh @@ -30,5 +30,6 @@ // void main() { + //gl_FragColor = vec4(0.00, 0.00, 0.00, 0.00); gl_FragColor = vec4(0.00, 0.00, 0.00, 0.00); } diff --git a/KRWorldBuilder/KRWorldBuilder.xcodeproj/xcuserdata/kearwood.xcuserdatad/xcschemes/KRWorldBuilder.xcscheme b/KRWorldBuilder/KRWorldBuilder.xcodeproj/xcuserdata/kearwood.xcuserdatad/xcschemes/KRWorldBuilder.xcscheme index f7f1724..6dabe4a 100644 --- a/KRWorldBuilder/KRWorldBuilder.xcodeproj/xcuserdata/kearwood.xcuserdatad/xcschemes/KRWorldBuilder.xcscheme +++ b/KRWorldBuilder/KRWorldBuilder.xcodeproj/xcuserdata/kearwood.xcuserdatad/xcschemes/KRWorldBuilder.xcscheme @@ -1,6 +1,6 @@ diff --git a/objview/Classes/KRObjViewGLView.mm b/objview/Classes/KRObjViewGLView.mm index ac94f58..0833bc7 100644 --- a/objview/Classes/KRObjViewGLView.mm +++ b/objview/Classes/KRObjViewGLView.mm @@ -106,7 +106,7 @@ } [self.engine setNearZ: 5.0]; - [self.engine setFarZ: 3000.0]; + [self.engine setFarZ: 5000.0]; //[renderEngine setNearZ: 1.0]; //[renderEngine setFarZ: 3000.0]; diff --git a/objview/Classes/KRObjViewViewController.mm b/objview/Classes/KRObjViewViewController.mm index 40118cb..e7544f0 100644 --- a/objview/Classes/KRObjViewViewController.mm +++ b/objview/Classes/KRObjViewViewController.mm @@ -252,7 +252,7 @@ } - double dScaleFactor = 200.0f * deltaTime; + double dScaleFactor = 500.0f * deltaTime; camera_position.z += (-cos(camera_pitch) * cos(camera_yaw) * leftStickDeltaX + -cos(camera_pitch) * cos(camera_yaw - 90.0f * d2r) * -leftStickDeltaY) * dScaleFactor; camera_position.x += (cos(camera_pitch) * sin(camera_yaw) * leftStickDeltaX + cos(camera_pitch) * sin(camera_yaw - 90.0f * d2r) * -leftStickDeltaY) * dScaleFactor; diff --git a/objview/KRObjView.xcodeproj/project.pbxproj b/objview/KRObjView.xcodeproj/project.pbxproj index 4d13b24..2fd571c 100644 --- a/objview/KRObjView.xcodeproj/project.pbxproj +++ b/objview/KRObjView.xcodeproj/project.pbxproj @@ -271,7 +271,7 @@ 29B97313FDCFA39411CA2CEA /* Project object */ = { isa = PBXProject; attributes = { - LastUpgradeCheck = 0440; + LastUpgradeCheck = 0450; }; buildConfigurationList = C01FCF4E08A954540054247B /* Build configuration list for PBXProject "KRObjView" */; compatibilityVersion = "Xcode 3.2";