From 4b2416041a5075fe913779f94d692d6279fdadf7 Mon Sep 17 00:00:00 2001 From: Kearwood Gilbert Date: Thu, 17 Jan 2013 19:27:17 -0800 Subject: [PATCH] Flares now disappear behind objects. --- KREngine/KREngine/Classes/KRCamera.cpp | 23 +++++++ KREngine/KREngine/Classes/KRLight.cpp | 88 +++++++++++++++++++++----- KREngine/KREngine/Classes/KRLight.h | 4 ++ KREngine/KREngine/Classes/KRMesh.cpp | 2 +- KREngine/KREngine/Classes/KRModel.cpp | 2 +- KREngine/KREngine/Classes/KRNode.h | 4 +- 6 files changed, 103 insertions(+), 20 deletions(-) diff --git a/KREngine/KREngine/Classes/KRCamera.cpp b/KREngine/KREngine/Classes/KRCamera.cpp index 949a69f..d86d456 100644 --- a/KREngine/KREngine/Classes/KRCamera.cpp +++ b/KREngine/KREngine/Classes/KRCamera.cpp @@ -266,6 +266,29 @@ void KRCamera::renderFrame(float deltaTime) // Render all transparent geometry scene.render(this, m_viewport.getVisibleBounds(), m_viewport, KRNode::RENDER_PASS_FORWARD_TRANSPARENT, false); + // ----====---- Particle Occlusion Tests ----====---- + + // Set render target + GLDEBUG(glBindFramebuffer(GL_FRAMEBUFFER, compositeFramebuffer)); + GLDEBUG(glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, compositeDepthTexture, 0)); + + // Disable backface culling + GLDEBUG(glDisable(GL_CULL_FACE)); + + // Disable z-buffer write + GLDEBUG(glDepthMask(GL_FALSE)); + + // Enable z-buffer test + GLDEBUG(glEnable(GL_DEPTH_TEST)); + GLDEBUG(glDepthFunc(GL_LEQUAL)); + GLDEBUG(glDepthRangef(0.0, 1.0)); + + // Enable additive blending + GLDEBUG(glEnable(GL_BLEND)); + GLDEBUG(glBlendFunc(GL_ONE, GL_ONE)); + + // ----====---- Perform Occlusion Tests ----====---- + scene.render(this, m_viewport.getVisibleBounds(), m_viewport, RENDER_PASS_PARTICLE_OCCLUSION, false); // ----====---- Flares ----====---- diff --git a/KREngine/KREngine/Classes/KRLight.cpp b/KREngine/KREngine/Classes/KRLight.cpp index a1a3137..d53f639 100644 --- a/KREngine/KREngine/Classes/KRLight.cpp +++ b/KREngine/KREngine/Classes/KRLight.cpp @@ -29,10 +29,12 @@ KRLight::KRLight(KRScene &scene, std::string name) : KRNode(scene, name) m_flareTexture = ""; m_pFlareTexture = NULL; m_flareSize = 0.0; + m_flareOcclusionSize = 0.05; m_casts_shadow = true; m_light_shafts = true; m_dust_particle_density = 0.1f; m_dust_particle_size = 1.0f; + m_occlusionQuery = 0; // Initialize shadow buffers m_cShadowBuffers = 0; @@ -45,6 +47,10 @@ KRLight::KRLight(KRScene &scene, std::string name) : KRNode(scene, name) KRLight::~KRLight() { + if(m_occlusionQuery) { + GLDEBUG(glDeleteQueriesEXT(1, &m_occlusionQuery)); + m_occlusionQuery = 0; + } allocateShadowBuffers(0); } @@ -57,6 +63,7 @@ tinyxml2::XMLElement *KRLight::saveXML( tinyxml2::XMLNode *parent) e->SetAttribute("color_b", m_color.z); e->SetAttribute("decay_start", m_decayStart); e->SetAttribute("flare_size", m_flareSize); + e->SetAttribute("flare_occlusion_size", m_flareOcclusionSize); e->SetAttribute("flare_texture", m_flareTexture.c_str()); e->SetAttribute("casts_shadow", m_casts_shadow ? "true" : "false"); e->SetAttribute("light_shafts", m_light_shafts ? "true" : "false"); @@ -92,6 +99,10 @@ void KRLight::loadXML(tinyxml2::XMLElement *e) { m_flareSize = 0.0; } + if(e->QueryFloatAttribute("flare_occlusion_size", &m_flareOcclusionSize) != tinyxml2::XML_SUCCESS) { + m_flareOcclusionSize = 0.05; + } + if(e->QueryBoolAttribute("casts_shadow", &m_casts_shadow) != tinyxml2::XML_SUCCESS) { m_casts_shadow = true; } @@ -133,6 +144,10 @@ void KRLight::setFlareSize(float flare_size) { m_flareSize = flare_size; } +void KRLight::setOcclusionSize(float occlusion_size) { + m_flareOcclusionSize; +} + void KRLight::setIntensity(float intensity) { m_intensity = intensity; } @@ -230,27 +245,66 @@ void KRLight::render(KRCamera *pCamera, std::vector &lights, const KR } + if(renderPass == KRNode::RENDER_PASS_PARTICLE_OCCLUSION) { + if(m_flareTexture.size() && m_flareSize > 0.0f) { + + + KRMat4 occlusion_test_sphere_matrix = KRMat4(); + occlusion_test_sphere_matrix.scale(m_localScale * m_flareOcclusionSize); + occlusion_test_sphere_matrix.translate(m_localTranslation); + if(m_parentNode) { + occlusion_test_sphere_matrix *= m_parentNode->getModelMatrix(); + } + + if(getContext().getShaderManager()->selectShader("occlusion_test", *pCamera, lights, 0, viewport, occlusion_test_sphere_matrix, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, renderPass)) { + + GLDEBUG(glGenQueriesEXT(1, &m_occlusionQuery)); + GLDEBUG(glBeginQueryEXT(GL_ANY_SAMPLES_PASSED_EXT, m_occlusionQuery)); + + std::vector sphereModels = getContext().getModelManager()->getModel("__sphere"); + if(sphereModels.size()) { + for(int i=0; i < sphereModels[0]->getSubmeshCount(); i++) { + sphereModels[0]->renderSubmesh(i); + } + } + + GLDEBUG(glEndQueryEXT(GL_ANY_SAMPLES_PASSED_EXT)); + + } + } + } + if(renderPass == KRNode::RENDER_PASS_ADDITIVE_PARTICLES) { if(m_flareTexture.size() && m_flareSize > 0.0f) { - if(!m_pFlareTexture && m_flareTexture.size()) { - m_pFlareTexture = getContext().getTextureManager()->getTexture(m_flareTexture.c_str()); - } - if(m_pFlareTexture) { - // Disable z-buffer test - GLDEBUG(glDisable(GL_DEPTH_TEST)); - GLDEBUG(glDepthRangef(0.0, 1.0)); + if(m_occlusionQuery) { + GLuint params = 0; + GLDEBUG(glGetQueryObjectuivEXT(m_occlusionQuery, GL_QUERY_RESULT_EXT, ¶ms)); + GLDEBUG(glDeleteQueriesEXT(1, &m_occlusionQuery)); - // Render light flare on transparency pass - KRShader *pShader = getContext().getShaderManager()->getShader("flare", pCamera, lights, 0, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, renderPass); - if(getContext().getShaderManager()->selectShader(*pCamera, pShader, viewport, getModelMatrix(), lights, 0, renderPass)) { - GLDEBUG(glUniform1f( - pShader->m_uniforms[KRShader::KRENGINE_UNIFORM_FLARE_SIZE], - m_flareSize - )); - m_pContext->getTextureManager()->selectTexture(0, m_pFlareTexture); - m_pContext->getModelManager()->bindVBO((void *)KRENGINE_VBO_2D_SQUARE, KRENGINE_VBO_2D_SQUARE_SIZE, true, false, false, true, false, false, false); - GLDEBUG(glDrawArrays(GL_TRIANGLE_STRIP, 0, 4)); + if(params) { + + if(!m_pFlareTexture && m_flareTexture.size()) { + m_pFlareTexture = getContext().getTextureManager()->getTexture(m_flareTexture.c_str()); + } + + if(m_pFlareTexture) { + // Disable z-buffer test + GLDEBUG(glDisable(GL_DEPTH_TEST)); + GLDEBUG(glDepthRangef(0.0, 1.0)); + + // Render light flare on transparency pass + KRShader *pShader = getContext().getShaderManager()->getShader("flare", pCamera, lights, 0, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, renderPass); + if(getContext().getShaderManager()->selectShader(*pCamera, pShader, viewport, getModelMatrix(), lights, 0, renderPass)) { + GLDEBUG(glUniform1f( + pShader->m_uniforms[KRShader::KRENGINE_UNIFORM_FLARE_SIZE], + m_flareSize + )); + m_pContext->getTextureManager()->selectTexture(0, m_pFlareTexture); + m_pContext->getModelManager()->bindVBO((void *)KRENGINE_VBO_2D_SQUARE, KRENGINE_VBO_2D_SQUARE_SIZE, true, false, false, true, false, false, false); + GLDEBUG(glDrawArrays(GL_TRIANGLE_STRIP, 0, 4)); + } + } } } } diff --git a/KREngine/KREngine/Classes/KRLight.h b/KREngine/KREngine/Classes/KRLight.h index 9136500..da130f4 100644 --- a/KREngine/KREngine/Classes/KRLight.h +++ b/KREngine/KREngine/Classes/KRLight.h @@ -39,6 +39,7 @@ public: void setFlareTexture(std::string flare_texture); void setFlareSize(float flare_size); + void setOcclusionSize(float occlusion_size); void deleteBuffers(); virtual void render(KRCamera *pCamera, std::vector &lights, const KRViewport &viewport, KRNode::RenderPass renderPass); @@ -58,6 +59,7 @@ protected: std::string m_flareTexture; KRTexture *m_pFlareTexture; float m_flareSize; + float m_flareOcclusionSize; bool m_casts_shadow; bool m_light_shafts; @@ -65,6 +67,8 @@ protected: float m_dust_particle_size; float m_dust_particle_intensity; + GLuint m_occlusionQuery; // Occlusion query for attenuating occluded flares + // Shadow Maps int m_cShadowBuffers; diff --git a/KREngine/KREngine/Classes/KRMesh.cpp b/KREngine/KREngine/Classes/KRMesh.cpp index c48f661..b447af4 100644 --- a/KREngine/KREngine/Classes/KRMesh.cpp +++ b/KREngine/KREngine/Classes/KRMesh.cpp @@ -134,7 +134,7 @@ void KRMesh::loadPack(KRDataBlock *data) { void KRMesh::render(KRCamera *pCamera, std::vector &lights, const KRViewport &viewport, const KRMat4 &matModel, KRTexture *pLightMap, KRNode::RenderPass renderPass, const std::vector &bones) { //fprintf(stderr, "Rendering model: %s\n", m_name.c_str()); - if(renderPass != KRNode::RENDER_PASS_ADDITIVE_PARTICLES && renderPass != KRNode::RENDER_PASS_VOLUMETRIC_EFFECTS_ADDITIVE) { + if(renderPass != KRNode::RENDER_PASS_ADDITIVE_PARTICLES && renderPass != KRNode::RENDER_PASS_PARTICLE_OCCLUSION && renderPass != KRNode::RENDER_PASS_VOLUMETRIC_EFFECTS_ADDITIVE) { if(m_materials.size() == 0) { vector submeshes = getSubmeshes(); diff --git a/KREngine/KREngine/Classes/KRModel.cpp b/KREngine/KREngine/Classes/KRModel.cpp index 9705f45..72849c6 100644 --- a/KREngine/KREngine/Classes/KRModel.cpp +++ b/KREngine/KREngine/Classes/KRModel.cpp @@ -98,7 +98,7 @@ void KRModel::render(KRCamera *pCamera, std::vector &lights, const KR KRNode::render(pCamera, lights, viewport, renderPass); - if(renderPass != KRNode::RENDER_PASS_DEFERRED_LIGHTS && (renderPass != KRNode::RENDER_PASS_FORWARD_TRANSPARENT || this->hasTransparency()) && renderPass != KRNode::RENDER_PASS_ADDITIVE_PARTICLES && renderPass != KRNode::RENDER_PASS_VOLUMETRIC_EFFECTS_ADDITIVE) { + if(renderPass != KRNode::RENDER_PASS_DEFERRED_LIGHTS && (renderPass != KRNode::RENDER_PASS_FORWARD_TRANSPARENT || this->hasTransparency()) && renderPass != KRNode::RENDER_PASS_ADDITIVE_PARTICLES && renderPass != KRNode::RENDER_PASS_PARTICLE_OCCLUSION && renderPass != KRNode::RENDER_PASS_VOLUMETRIC_EFFECTS_ADDITIVE) { // Don't render meshes on second pass of the deferred lighting renderer, as only lights will be applied loadModel(); diff --git a/KREngine/KREngine/Classes/KRNode.h b/KREngine/KREngine/Classes/KRNode.h index 990517f..863743a 100644 --- a/KREngine/KREngine/Classes/KRNode.h +++ b/KREngine/KREngine/Classes/KRNode.h @@ -33,6 +33,7 @@ public: RENDER_PASS_DEFERRED_LIGHTS, RENDER_PASS_DEFERRED_OPAQUE, RENDER_PASS_FORWARD_TRANSPARENT, + RENDER_PASS_PARTICLE_OCCLUSION, RENDER_PASS_ADDITIVE_PARTICLES, RENDER_PASS_VOLUMETRIC_EFFECTS_ADDITIVE, RENDER_PASS_GENERATE_SHADOWMAPS, @@ -109,6 +110,8 @@ protected: KRVector3 m_initialLocalScale; KRVector3 m_initialLocalRotation; + KRNode *m_parentNode; + private: void invalidateModelMatrix(); void invalidateBindPoseMatrix(); @@ -124,7 +127,6 @@ private: std::string m_name; std::vector m_childNodes; - KRNode *m_parentNode; KRScene *m_pScene;