From c6417c151d14c7a406c137ddf7acaa9273c4922d Mon Sep 17 00:00:00 2001 From: kearwood Date: Tue, 11 Sep 2012 08:15:05 +0000 Subject: [PATCH] Performance improvement in the deferred lighting pipeline, utilizing hardware occlusion queries to avoid rendering objects in 3rd pass (Final Render) or loading their textures when they have been determined to be occluded in the 1st pass. (GBuffer populate) --HG-- extra : convert_revision : svn%3A7752d6cf-9f14-4ad2-affc-04f1e67b81a5/trunk%4094 --- KREngine/KREngine/Classes/KRCamera.cpp | 6 +++++- KREngine/KREngine/Classes/KROctree.cpp | 1 + KREngine/KREngine/Classes/KRScene.cpp | 28 +++++++++++++++++++------- 3 files changed, 27 insertions(+), 8 deletions(-) diff --git a/KREngine/KREngine/Classes/KRCamera.cpp b/KREngine/KREngine/Classes/KRCamera.cpp index e9dfd28..b164a3e 100644 --- a/KREngine/KREngine/Classes/KRCamera.cpp +++ b/KREngine/KREngine/Classes/KRCamera.cpp @@ -243,6 +243,8 @@ 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); + // ----====---- Opaque Geometry, Deferred rendering Pass 3 ----====---- // Set render target glBindFramebuffer(GL_FRAMEBUFFER, compositeFramebuffer); @@ -310,6 +312,8 @@ 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); } // ----====---- Transparent Geometry, Forward Rendering ----====---- @@ -409,7 +413,7 @@ void KRCamera::renderFrame(KRScene &scene, KRMat4 &viewMatrix, KRVector3 &lightD } } - scene.getOcclusionQueryResults(m_visibleBounds); +// scene.getOcclusionQueryResults(m_visibleBounds); // fprintf(stderr, "visible bounds: %i\n", (int)m_visibleBounds.size()); diff --git a/KREngine/KREngine/Classes/KROctree.cpp b/KREngine/KREngine/Classes/KROctree.cpp index da18a8a..5f8dcc3 100644 --- a/KREngine/KREngine/Classes/KROctree.cpp +++ b/KREngine/KREngine/Classes/KROctree.cpp @@ -31,6 +31,7 @@ void KROctree::add(KRNode *pNode) if(m_pRootNode == NULL) { // First item inserted, create a node large enough to fit it m_pRootNode = new KROctreeNode(nodeBounds); + //m_pRootNode = new KROctreeNode(KRAABB(nodeBounds.min - nodeBounds.size() * 0.25f, nodeBounds.max + nodeBounds.size() * 0.25f)); m_pRootNode->add(pNode); } else { // Keep encapsulating the root node until the new root contains the inserted node diff --git a/KREngine/KREngine/Classes/KRScene.cpp b/KREngine/KREngine/Classes/KRScene.cpp index 2d6ae64..8186e9e 100644 --- a/KREngine/KREngine/Classes/KRScene.cpp +++ b/KREngine/KREngine/Classes/KRScene.cpp @@ -146,19 +146,26 @@ void KRScene::render(KROctreeNode *pOctreeNode, std::set &visibleBounds, 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(frustrumVolume.test_intersect(pOctreeNode->getBounds())) { // Only recurse deeper if within the view frustrum + //if(frustrumVolumeNoNearClip.test_intersect(pOctreeNode->getBounds())) { // Only recurse deeper if within the view frustrum - bool can_occlusion_test = renderPass == KRNode::RENDER_PASS_FORWARD_OPAQUE || renderPass == KRNode::RENDER_PASS_DEFERRED_OPAQUE || renderPass == KRNode::RENDER_PASS_FORWARD_TRANSPARENT; + bool can_occlusion_test = renderPass == KRNode::RENDER_PASS_FORWARD_OPAQUE || renderPass == KRNode::RENDER_PASS_DEFERRED_GBUFFER || renderPass == KRNode::RENDER_PASS_FORWARD_TRANSPARENT; - if(true) { - //if(visibleBounds.find(octreeBounds) != visibleBounds.end()) { + + bool bVisible = true; +// bool bVisible = renderPass != KRNode::RENDER_PASS_DEFERRED_OPAQUE; +// if(!bVisible) { +// 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 @@ -170,8 +177,15 @@ void KRScene::render(KROctreeNode *pOctreeNode, std::set &visibleBounds, pOctreeNode->endOcclusionQuery(); } - for(int i=0; i<8; i++) { - render(pOctreeNode->getChildren()[i], visibleBounds, pCamera, pContext, frustrumVolume, viewMatrix, cameraPosition, lightDirection, pShadowMatrices, shadowDepthTextures, cShadowBuffers, renderPass); + + 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); + } } } else if(KRNode::RENDER_PASS_FORWARD_OPAQUE || renderPass == KRNode::RENDER_PASS_DEFERRED_OPAQUE) { if(pOctreeNode->getSceneNodes().empty()) {