From 1d22aa189d9d6c42404374b91bc730df41aa19f0 Mon Sep 17 00:00:00 2001 From: kearwood Date: Sat, 10 Nov 2012 00:51:03 +0000 Subject: [PATCH] Implemented multi-resolution rendering for volumetric lighting --HG-- extra : convert_revision : svn%3A7752d6cf-9f14-4ad2-affc-04f1e67b81a5/trunk%40154 --- KREngine/KREngine.xcodeproj/project.pbxproj | 8 ++- KREngine/KREngine/Classes/KRCamera.cpp | 51 ++++++++++++------- KREngine/KREngine/Classes/KRCamera.h | 4 +- KREngine/KREngine/Classes/KRInstance.cpp | 2 +- KREngine/KREngine/Classes/KRShaderManager.cpp | 2 +- KREngine/KREngine/Shaders/volumetric_fog.fsh | 7 +-- KREngine/KREngine/Shaders/volumetric_fog.vsh | 2 +- .../Shaders/volumetric_fog_downsampled.fsh | 41 +++++++++++++++ .../Shaders/volumetric_fog_downsampled.vsh | 50 ++++++++++++++++++ 9 files changed, 137 insertions(+), 30 deletions(-) create mode 100644 KREngine/KREngine/Shaders/volumetric_fog_downsampled.fsh create mode 100644 KREngine/KREngine/Shaders/volumetric_fog_downsampled.vsh diff --git a/KREngine/KREngine.xcodeproj/project.pbxproj b/KREngine/KREngine.xcodeproj/project.pbxproj index 4eecd53..40f15f3 100644 --- a/KREngine/KREngine.xcodeproj/project.pbxproj +++ b/KREngine/KREngine.xcodeproj/project.pbxproj @@ -23,6 +23,7 @@ E42CB1ED158446940066E0D8 /* KRQuaternion.h in Headers */ = {isa = PBXBuildFile; fileRef = E42CB1EB158446940066E0D8 /* KRQuaternion.h */; settings = {ATTRIBUTES = (Public, ); }; }; E42CB1F0158446AB0066E0D8 /* KRQuaternion.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E42CB1EF158446AB0066E0D8 /* KRQuaternion.cpp */; }; E42CB1F1158446AB0066E0D8 /* KRQuaternion.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E42CB1EF158446AB0066E0D8 /* KRQuaternion.cpp */; }; + E431C1B8164DB7B200BE1575 /* volumetric_fog_downsampled.fsh in Sources */ = {isa = PBXBuildFile; fileRef = E431C1B7164DB7B200BE1575 /* volumetric_fog_downsampled.fsh */; }; E4324BA416444C0D0043185B /* KRParticleSystem.h in Headers */ = {isa = PBXBuildFile; fileRef = E4324BA316444C0D0043185B /* KRParticleSystem.h */; }; E4324BA516444C0D0043185B /* KRParticleSystem.h in Headers */ = {isa = PBXBuildFile; fileRef = E4324BA316444C0D0043185B /* KRParticleSystem.h */; }; E4324BA816444C230043185B /* KRParticleSystem.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E4324BA716444C230043185B /* KRParticleSystem.cpp */; }; @@ -225,6 +226,8 @@ E42CB1EF158446AB0066E0D8 /* KRQuaternion.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = KRQuaternion.cpp; path = Classes/KRQuaternion.cpp; sourceTree = ""; }; E430D08015F8882F0010558D /* occlusion_test.fsh */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.glsl; name = occlusion_test.fsh; path = Shaders/occlusion_test.fsh; sourceTree = ""; }; E430D08815F88AD10010558D /* occlusion_test.vsh */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.glsl; name = occlusion_test.vsh; path = Shaders/occlusion_test.vsh; sourceTree = ""; }; + E431C1B6164DB79A00BE1575 /* volumetric_fog_downsampled.vsh */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.glsl; name = volumetric_fog_downsampled.vsh; path = Shaders/volumetric_fog_downsampled.vsh; sourceTree = ""; }; + E431C1B7164DB7B200BE1575 /* volumetric_fog_downsampled.fsh */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.glsl; name = volumetric_fog_downsampled.fsh; path = Shaders/volumetric_fog_downsampled.fsh; sourceTree = ""; }; E4324BA316444C0D0043185B /* KRParticleSystem.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = KRParticleSystem.h; path = Classes/KRParticleSystem.h; sourceTree = ""; }; E4324BA716444C230043185B /* KRParticleSystem.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = KRParticleSystem.cpp; path = Classes/KRParticleSystem.cpp; sourceTree = ""; }; E4324BAA16444DEF0043185B /* KRParticleSystemBrownian.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = KRParticleSystemBrownian.h; path = Classes/KRParticleSystemBrownian.h; sourceTree = ""; }; @@ -346,7 +349,7 @@ E4CE184C15FF124600F80870 /* light_point_inside.fsh */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.glsl; lineEnding = 0; name = light_point_inside.fsh; path = Shaders/light_point_inside.fsh; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.glsl; }; E4CE184E15FF125700F80870 /* light_point_inside.vsh */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.glsl; name = light_point_inside.vsh; path = Shaders/light_point_inside.vsh; sourceTree = ""; }; E4D133B91538F7480070068C /* light_directional.fsh */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.glsl; name = light_directional.fsh; path = Shaders/light_directional.fsh; sourceTree = ""; }; - E4D133BB1538F7560070068C /* light_directional.vsh */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.glsl; name = light_directional.vsh; path = Shaders/light_directional.vsh; sourceTree = ""; }; + E4D133BB1538F7560070068C /* light_directional.vsh */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.glsl; lineEnding = 0; name = light_directional.vsh; path = Shaders/light_directional.vsh; sourceTree = ""; }; E4F711A41512BB56007EE923 /* libfbxsdk-2012.2-static.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = "libfbxsdk-2012.2-static.a"; path = "../../../../../../../../Applications/Autodesk/FBXSDK20122/lib/gcc4/ub/libfbxsdk-2012.2-static.a"; sourceTree = ""; }; E4F975311536220900FD60B2 /* KRNode.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; lineEnding = 0; name = KRNode.h; path = Classes/KRNode.h; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.objcpp; }; E4F975351536221C00FD60B2 /* KRNode.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; lineEnding = 0; name = KRNode.cpp; path = Classes/KRNode.cpp; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.cpp; }; @@ -424,6 +427,8 @@ E45AC0491643452000DC3C3B /* particle.vsh */, E443C612164B5BE500FC4FD8 /* volumetric_fog.fsh */, E443C615164B5BFB00FC4FD8 /* volumetric_fog.vsh */, + E431C1B6164DB79A00BE1575 /* volumetric_fog_downsampled.vsh */, + E431C1B7164DB7B200BE1575 /* volumetric_fog_downsampled.fsh */, ); name = Shaders; sourceTree = ""; @@ -951,6 +956,7 @@ E4324BA816444C230043185B /* KRParticleSystem.cpp in Sources */, E4324BAE16444E120043185B /* KRParticleSystemBrownian.cpp in Sources */, E443C602164B122C00FC4FD8 /* KRVolumetricFog.cpp in Sources */, + E431C1B8164DB7B200BE1575 /* volumetric_fog_downsampled.fsh in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/KREngine/KREngine/Classes/KRCamera.cpp b/KREngine/KREngine/Classes/KRCamera.cpp index 82811c4..1cd9722 100644 --- a/KREngine/KREngine/Classes/KRCamera.cpp +++ b/KREngine/KREngine/Classes/KRCamera.cpp @@ -106,15 +106,16 @@ KRCamera::KRCamera(KRContext &context) : KRContextObject(context) { volumetricLightAccumulationTexture = 0; - memset(shadowFramebuffer, sizeof(GLuint) * 3, 0); - memset(shadowDepthTexture, sizeof(GLuint) * 3, 0); + memset(shadowFramebuffer, sizeof(GLuint) * KRENGINE_MAX_SHADOW_BUFFERS, 0); + memset(shadowDepthTexture, sizeof(GLuint) * KRENGINE_MAX_SHADOW_BUFFERS, 0); m_iFrame = 0; m_skyBoxName = ""; m_pSkyBoxTexture = NULL; - volumetric_light_downsample = 4; + volumetric_light_downsample = 8; + invalidateShadowBuffers(); } KRCamera::~KRCamera() { @@ -443,22 +444,32 @@ void KRCamera::renderFrame(KRScene &scene, KRVector3 &lightDirection, float delt if(m_cShadowBuffers >= 1) { - // Set render target - GLDEBUG(glBindFramebuffer(GL_FRAMEBUFFER, volumetricLightAccumulationBuffer)); - GLDEBUG(glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, compositeDepthTexture, 0)); - GLDEBUG(glClearColor(0.0f, 0.0f, 0.0f, 0.0f)); - GLDEBUG(glClear(GL_COLOR_BUFFER_BIT)); - - KRShader *pFogShader = m_pContext->getShaderManager()->getShader("volumetric_fog", this, false, false, false, 0, false, false, false, false, false, false, false, false, false, false, false, false, false, KRNode::RENDER_PASS_FORWARD_TRANSPARENT); - - KRViewport volumetricLightingViewport = KRViewport(m_viewport.getSize() / volumetric_light_downsample, m_viewport.getViewMatrix(), m_viewport.getProjectionMatrix()); - - if(pFogShader->bind(volumetricLightingViewport, m_shadowViewports, KRMat4(), lightDirection, shadowDepthTexture, m_cShadowBuffers, KRNode::RENDER_PASS_ADDITIVE_PARTICLES)) { + if(volumetric_light_downsample != 1) { + // Set render target + GLDEBUG(glBindFramebuffer(GL_FRAMEBUFFER, volumetricLightAccumulationBuffer)); + GLDEBUG(glClearColor(0.0f, 0.0f, 0.0f, 0.0f)); + GLDEBUG(glClear(GL_COLOR_BUFFER_BIT)); + // Disable z-buffer test + GLDEBUG(glDisable(GL_DEPTH_TEST)); + + m_pContext->getTextureManager()->selectTexture(0, NULL, 0); + GLDEBUG(glActiveTexture(GL_TEXTURE0)); + GLDEBUG(glBindTexture(GL_TEXTURE_2D, compositeDepthTexture)); + } else { // Enable z-buffer test GLDEBUG(glEnable(GL_DEPTH_TEST)); GLDEBUG(glDepthFunc(GL_LEQUAL)); GLDEBUG(glDepthRangef(0.0, 1.0)); + } + + KRShader *pFogShader = m_pContext->getShaderManager()->getShader(volumetric_light_downsample != 1 ? "volumetric_fog_downsampled" : "volumetric_fog", this, false, false, false, 0, false, false, false, false, false, false, false, false, false, false, false, false, false, KRNode::RENDER_PASS_ADDITIVE_PARTICLES); + + KRViewport volumetricLightingViewport = KRViewport(m_viewport.getSize() / volumetric_light_downsample, m_viewport.getViewMatrix(), m_viewport.getProjectionMatrix()); + glViewport(0, 0, volumetricLightingViewport.getSize().x, volumetricLightingViewport.getSize().y); + if(pFogShader->bind(volumetricLightingViewport, m_shadowViewports, KRMat4(), lightDirection, shadowDepthTexture, m_cShadowBuffers, KRNode::RENDER_PASS_ADDITIVE_PARTICLES)) { + + int slice_count = 50; @@ -472,9 +483,13 @@ void KRCamera::renderFrame(KRScene &scene, KRVector3 &lightDirection, float delt GLDEBUG(glDrawArrays(GL_TRIANGLES, 0, slice_count*6)); } - // Set render target - GLDEBUG(glBindFramebuffer(GL_FRAMEBUFFER, compositeFramebuffer)); - GLDEBUG(glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, compositeDepthTexture, 0)); + if(volumetric_light_downsample != 1) { + // Set render target + GLDEBUG(glBindFramebuffer(GL_FRAMEBUFFER, compositeFramebuffer)); + GLDEBUG(glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, compositeDepthTexture, 0)); + + glViewport(0, 0, m_viewport.getSize().x, m_viewport.getSize().y); + } } @@ -662,8 +677,6 @@ void KRCamera::destroyBuffers() lightAccumulationBuffer = 0; } - - if (volumetricLightAccumulationTexture) { GLDEBUG(glDeleteTextures(1, &volumetricLightAccumulationTexture)); volumetricLightAccumulationTexture = 0; diff --git a/KREngine/KREngine/Classes/KRCamera.h b/KREngine/KREngine/Classes/KRCamera.h index 5e1bc44..8a72ca6 100644 --- a/KREngine/KREngine/Classes/KRCamera.h +++ b/KREngine/KREngine/Classes/KRCamera.h @@ -44,8 +44,8 @@ #import "KRViewport.h" #define KRENGINE_MAX_SHADOW_BUFFERS 3 -#define KRENGINE_SHADOW_MAP_WIDTH 2048 -#define KRENGINE_SHADOW_MAP_HEIGHT 2048 +#define KRENGINE_SHADOW_MAP_WIDTH 512 +#define KRENGINE_SHADOW_MAP_HEIGHT 512 class KRInstance; class KRScene; diff --git a/KREngine/KREngine/Classes/KRInstance.cpp b/KREngine/KREngine/Classes/KRInstance.cpp index 4293e84..3b9904e 100644 --- a/KREngine/KREngine/Classes/KRInstance.cpp +++ b/KREngine/KREngine/Classes/KRInstance.cpp @@ -41,7 +41,7 @@ KRInstance::KRInstance(KRScene &scene, std::string instance_name, std::string mo m_model_name = model_name; m_min_lod_coverage = lod_min_coverage; m_receivesShadow = receives_shadow; - m_receivesShadow = true; + m_receivesShadow = false; } KRInstance::~KRInstance() { diff --git a/KREngine/KREngine/Classes/KRShaderManager.cpp b/KREngine/KREngine/Classes/KRShaderManager.cpp index f4431c3..f6df716 100644 --- a/KREngine/KREngine/Classes/KRShaderManager.cpp +++ b/KREngine/KREngine/Classes/KRShaderManager.cpp @@ -58,7 +58,7 @@ KRShader *KRShaderManager::getShader(const std::string &shader_name, const KRCam std::map::iterator itr = m_shaders.begin(); delete (*itr).second; m_shaders.erase(itr); - //fprintf(stderr, "Swapping shaders...\n"); + fprintf(stderr, "Swapping shaders...\n"); } stringstream stream; diff --git a/KREngine/KREngine/Shaders/volumetric_fog.fsh b/KREngine/KREngine/Shaders/volumetric_fog.fsh index ed1d3c9..45b31b2 100644 --- a/KREngine/KREngine/Shaders/volumetric_fog.fsh +++ b/KREngine/KREngine/Shaders/volumetric_fog.fsh @@ -29,13 +29,10 @@ #extension GL_EXT_shadow_samplers : require -varying highp vec4 shadowMapCoord1; +varying mediump vec4 shadowMapCoord1; uniform sampler2DShadow shadowTexture1; void main() { - gl_FragColor = vec4(0.04, 0.04, 0.04, 0.04); - - gl_FragColor *= shadow2DProjEXT(shadowTexture1, shadowMapCoord1); -// gl_FragColor = vec4(shadowMapCoord1.xyz, 1.0); + gl_FragColor = vec4(shadow2DProjEXT(shadowTexture1, shadowMapCoord1) * 0.02); } diff --git a/KREngine/KREngine/Shaders/volumetric_fog.vsh b/KREngine/KREngine/Shaders/volumetric_fog.vsh index 0188062..b1f146e 100644 --- a/KREngine/KREngine/Shaders/volumetric_fog.vsh +++ b/KREngine/KREngine/Shaders/volumetric_fog.vsh @@ -31,7 +31,7 @@ uniform highp mat4 inv_mvp_matrix; uniform highp vec2 slice_depth_scale; // First component is the depth for the nearest plane, in view space. Second component is the distance between planes, in view space uniform highp mat4 shadow_mvp1; -varying highp vec4 shadowMapCoord1; +varying mediump vec4 shadowMapCoord1; uniform highp mat4 projection_matrix; diff --git a/KREngine/KREngine/Shaders/volumetric_fog_downsampled.fsh b/KREngine/KREngine/Shaders/volumetric_fog_downsampled.fsh new file mode 100644 index 0000000..c1f9643 --- /dev/null +++ b/KREngine/KREngine/Shaders/volumetric_fog_downsampled.fsh @@ -0,0 +1,41 @@ +// Copyright 2012 Kearwood Gilbert. All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modification, are +// permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this list of +// conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, this list +// of conditions and the following disclaimer in the documentation and/or other materials +// provided with the distribution. +// +// THIS SOFTWARE IS PROVIDED BY KEARWOOD GILBERT ''AS IS'' AND ANY EXPRESS OR IMPLIED +// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KEARWOOD GILBERT OR +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// The views and conclusions contained in the software and documentation are those of the +// authors and should not be interpreted as representing official policies, either expressed +// or implied, of Kearwood Gilbert. +// + +#extension GL_EXT_shadow_samplers : require + +varying mediump vec4 shadowMapCoord1; +uniform sampler2DShadow shadowTexture1; +uniform lowp sampler2D depthFrame; +uniform mediump vec4 viewport; + +void main() +{ + if(gl_FragCoord.z > texture2D(depthFrame, vec2(gl_FragCoord.xy / viewport.zw)).r) discard; + + + gl_FragColor = vec4(shadow2DProjEXT(shadowTexture1, shadowMapCoord1) * 0.02); +} diff --git a/KREngine/KREngine/Shaders/volumetric_fog_downsampled.vsh b/KREngine/KREngine/Shaders/volumetric_fog_downsampled.vsh new file mode 100644 index 0000000..9bde6f3 --- /dev/null +++ b/KREngine/KREngine/Shaders/volumetric_fog_downsampled.vsh @@ -0,0 +1,50 @@ +// Copyright 2012 Kearwood Gilbert. All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modification, are +// permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this list of +// conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, this list +// of conditions and the following disclaimer in the documentation and/or other materials +// provided with the distribution. +// +// THIS SOFTWARE IS PROVIDED BY KEARWOOD GILBERT ''AS IS'' AND ANY EXPRESS OR IMPLIED +// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KEARWOOD GILBERT OR +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// The views and conclusions contained in the software and documentation are those of the +// authors and should not be interpreted as representing official policies, either expressed +// or implied, of Kearwood Gilbert. +// + +attribute highp vec4 vertex_position; +uniform highp mat4 inv_mvp_matrix; + +uniform highp vec2 slice_depth_scale; // First component is the depth for the nearest plane, in view space. Second component is the distance between planes, in view space + +uniform highp mat4 shadow_mvp1; +varying mediump vec4 shadowMapCoord1; + +uniform highp mat4 projection_matrix; + +void main() +{ + highp vec4 d = projection_matrix * vec4(0.0, 0.0, slice_depth_scale.x + vertex_position.z * slice_depth_scale.y, 1.0); + d /= d.w; + gl_Position = vec4(vertex_position.x, vertex_position.y, d.z, 1.0); + + + shadowMapCoord1 = inv_mvp_matrix * gl_Position; + shadowMapCoord1 /= shadowMapCoord1.w; + shadowMapCoord1.w = 1.0; + shadowMapCoord1 = shadow_mvp1 * shadowMapCoord1; + +}