From 04bd2bbe16a9e43759c496a3cf647adbacc90239 Mon Sep 17 00:00:00 2001 From: kearwood Date: Thu, 15 Nov 2012 22:05:25 +0000 Subject: [PATCH] Refactoring to enable multiple lights in forward rendering in progress --HG-- extra : convert_revision : svn%3A7752d6cf-9f14-4ad2-affc-04f1e67b81a5/trunk%40156 --- KREngine/KREngine/Classes/KRCamera.cpp | 296 ++++-------------- KREngine/KREngine/Classes/KRCamera.h | 13 - .../KREngine/Classes/KRDirectionalLight.cpp | 65 +++- .../KREngine/Classes/KRDirectionalLight.h | 6 +- KREngine/KREngine/Classes/KRInstance.cpp | 12 +- KREngine/KREngine/Classes/KRInstance.h | 2 +- KREngine/KREngine/Classes/KRLight.cpp | 176 ++++++++++- KREngine/KREngine/Classes/KRLight.h | 22 +- KREngine/KREngine/Classes/KRMaterial.cpp | 18 +- KREngine/KREngine/Classes/KRMaterial.h | 2 +- KREngine/KREngine/Classes/KRModel.cpp | 8 +- KREngine/KREngine/Classes/KRModel.h | 2 +- KREngine/KREngine/Classes/KRNode.cpp | 3 +- KREngine/KREngine/Classes/KRNode.h | 5 +- KREngine/KREngine/Classes/KRParticleSystem.h | 2 +- .../Classes/KRParticleSystemBrownian.cpp | 8 +- .../Classes/KRParticleSystemBrownian.h | 2 +- KREngine/KREngine/Classes/KRPointLight.cpp | 9 +- KREngine/KREngine/Classes/KRPointLight.h | 2 +- KREngine/KREngine/Classes/KRScene.cpp | 109 +++---- KREngine/KREngine/Classes/KRScene.h | 7 +- KREngine/KREngine/Classes/KRShader.cpp | 44 ++- KREngine/KREngine/Classes/KRShader.h | 9 +- KREngine/KREngine/Classes/KRShaderManager.cpp | 7 +- KREngine/KREngine/Classes/KRShaderManager.h | 2 +- KREngine/KREngine/Classes/KRViewport.cpp | 2 + KREngine/KREngine/Classes/KRViewport.h | 5 + 27 files changed, 464 insertions(+), 374 deletions(-) diff --git a/KREngine/KREngine/Classes/KRCamera.cpp b/KREngine/KREngine/Classes/KRCamera.cpp index 7e1ac37..b964117 100644 --- a/KREngine/KREngine/Classes/KRCamera.cpp +++ b/KREngine/KREngine/Classes/KRCamera.cpp @@ -13,7 +13,7 @@ // 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 @@ -34,6 +34,7 @@ #include #include #import +#include #import "KRVector2.h" #import "KRCamera.h" @@ -107,8 +108,7 @@ KRCamera::KRCamera(KRContext &context) : KRContextObject(context) { volumetricLightAccumulationTexture = 0; - memset(shadowFramebuffer, sizeof(GLuint) * KRENGINE_MAX_SHADOW_BUFFERS, 0); - memset(shadowDepthTexture, sizeof(GLuint) * KRENGINE_MAX_SHADOW_BUFFERS, 0); + m_iFrame = 0; @@ -121,8 +121,6 @@ KRCamera::KRCamera(KRContext &context) : KRContextObject(context) { volumetric_environment_max_distance = 1000.0f; volumetric_environment_quality = (50 - 5.0) / 495.0f; volumetric_environment_intensity = 1.0f; - - invalidateShadowBuffers(); } KRCamera::~KRCamera() { @@ -168,61 +166,6 @@ void KRCamera::renderFrame(KRScene &scene, KRMat4 &viewMatrix, float deltaTime) if(firstDirectionalLight) { lightDirection = firstDirectionalLight->getWorldLightDirection(); } - - allocateShadowBuffers(m_cShadowBuffers); - for(int iShadow=0; iShadow < m_cShadowBuffers; iShadow++) { - GLfloat shadowMinDepths[3][3] = {{0.0, 0.0, 0.0},{0.0, 0.0, 0.0},{0.0, 0.05, 0.3}}; - GLfloat shadowMaxDepths[3][3] = {{0.0, 0.0, 1.0},{0.1, 0.0, 0.0},{0.1, 0.3, 1.0}}; - - - - - - KRVector3 shadowLook = -KRVector3::Normalize(lightDirection); - - KRVector3 shadowUp(0.0, 1.0, 0.0); - if(KRVector3::Dot(shadowUp, shadowLook) > 0.99f) shadowUp = KRVector3(0.0, 0.0, 1.0); // Ensure shadow look direction is not parallel with the shadowUp direction - - KRMat4 matShadowView = KRMat4::LookAt(m_viewport.getCameraPosition() - shadowLook, m_viewport.getCameraPosition(), shadowUp); - - - KRMat4 matShadowProjection = KRMat4(); - matShadowProjection.scale(0.001, 0.001, 0.001); - - KRMat4 matBias; - matBias.bias(); - matShadowProjection *= matBias; - - - - -// KRAABB frustrumWorldBounds = KRAABB(KRVector3(-1.0, -1.0, 0.0), KRVector3(1.0, 1.0, 1.0), m_viewport.getInverseProjectionMatrix() * m_viewport.getInverseViewMatrix()); -// matShadowProjection.translate(KRVector3(0.0, 0.0, -frustrumWorldBounds.size().z)); -// matShadowProjection.scale(2.0 / frustrumWorldBounds.size().x, 2.0 / frustrumWorldBounds.size().y, 2.0 / frustrumWorldBounds.size().z); -// matShadowView.translate(-m_viewport.getCameraPosition()); - - //matShadowProjection *= matBias; - - m_shadowViewports[iShadow] = KRViewport(KRVector2(KRENGINE_SHADOW_MAP_WIDTH, KRENGINE_SHADOW_MAP_HEIGHT), matShadowView, matShadowProjection); - -// KRMat4 newShadowMVP; -// if(shadowMaxDepths[m_cShadowBuffers - 1][iShadow] == 0.0) { -// KRBoundingVolume ext = KRBoundingVolume(-KRVector3::One(), KRVector3::One(), KRMat4()); // HACK - Temporary workaround to compile until this logic is updated to use information from the Octree -// -// newShadowMVP = ext.calcShadowProj(&scene, m_pContext, scene.sun_yaw, scene.sun_pitch); -// } else { -// KRBoundingVolume frustrumSliceVolume = KRBoundingVolume(viewMatrix, perspective_fov, getViewportSize().x / getViewportSize().y, perspective_nearz + (perspective_farz - perspective_nearz) * shadowMinDepths[m_cShadowBuffers - 1][iShadow], perspective_nearz + (perspective_farz - perspective_nearz) * shadowMaxDepths[m_cShadowBuffers - 1][iShadow]); -// newShadowMVP = frustrumSliceVolume.calcShadowProj(&scene, m_pContext, scene.sun_yaw, scene.sun_pitch); -// } - -// KRBoundingVolume frustrumSliceVolume = KRBoundingVolume(viewMatrix, perspective_fov, getViewportSize().x / getViewportSize().y, perspective_nearz + (perspective_farz - perspective_nearz) * shadowMinDepths[m_cShadowBuffers - 1][iShadow], perspective_nearz + (perspective_farz - perspective_nearz) * shadowMaxDepths[m_cShadowBuffers - 1][iShadow]); -// newShadowMVP = frustrumSliceVolume.calcShadowProj(&scene, m_pContext, scene.sun_yaw, scene.sun_pitch); -// -// m_shadowViewports[iShadow] = KRViewport(KRVector2(KRENGINE_SHADOW_MAP_WIDTH, KRENGINE_SHADOW_MAP_HEIGHT), KRMat4(), newShadowMVP); -// - renderShadowBuffer(scene, iShadow); - - } renderFrame(scene, lightDirection, deltaTime); @@ -241,6 +184,10 @@ void KRCamera::renderFrame(KRScene &scene, KRVector3 &lightDirection, float delt std::set newVisibleBounds; +// GLuint shadowDepthTexture[KRENGINE_MAX_SHADOW_BUFFERS]; +// KRViewport shadowViewports[KRENGINE_MAX_SHADOW_BUFFERS]; +// int cShadows = 0; + if(bEnableDeferredLighting) { // ----====---- Opaque Geometry, Deferred rendering Pass 1 ----====---- @@ -265,7 +212,11 @@ void KRCamera::renderFrame(KRScene &scene, KRVector3 &lightDirection, float delt GLDEBUG(glDisable(GL_BLEND)); // Render the geometry - scene.render(this, m_viewport.getVisibleBounds(), m_pContext, m_viewport, m_shadowViewports, lightDirection, shadowDepthTexture, m_cShadowBuffers, KRNode::RENDER_PASS_DEFERRED_GBUFFER, newVisibleBounds); + scene.render(this, m_viewport.getVisibleBounds(), m_viewport, KRNode::RENDER_PASS_DEFERRED_GBUFFER, newVisibleBounds); + + // ----====---- Generate Shadowmaps for Lights ----====---- + scene.render(this, m_viewport.getVisibleBounds(), m_viewport, KRNode::RENDER_PASS_GENERATE_SHADOWMAPS, newVisibleBounds); + GLDEBUG(glViewport(0, 0, m_viewport.getSize().x, m_viewport.getSize().y)); // ----====---- Opaque Geometry, Deferred rendering Pass 2 ----====---- // Set render target @@ -291,7 +242,7 @@ void KRCamera::renderFrame(KRScene &scene, KRVector3 &lightDirection, float delt // Render the geometry - scene.render(this, m_viewport.getVisibleBounds(), m_pContext, m_viewport, m_shadowViewports, lightDirection, shadowDepthTexture, 0, KRNode::RENDER_PASS_DEFERRED_LIGHTS, newVisibleBounds); + scene.render(this, m_viewport.getVisibleBounds(), m_viewport, KRNode::RENDER_PASS_GENERATE_SHADOWMAPS, newVisibleBounds); // ----====---- Opaque Geometry, Deferred rendering Pass 3 ----====---- // Set render target @@ -323,7 +274,7 @@ void KRCamera::renderFrame(KRScene &scene, KRVector3 &lightDirection, float delt // Render the geometry 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, m_viewport, m_shadowViewports, lightDirection, shadowDepthTexture, m_cShadowBuffers, KRNode::RENDER_PASS_DEFERRED_OPAQUE, newVisibleBounds); + scene.render(this, emptyBoundsSet, m_viewport, KRNode::RENDER_PASS_DEFERRED_OPAQUE, newVisibleBounds); // Deactivate source buffer texture units m_pContext->getTextureManager()->selectTexture(6, NULL, 0); @@ -333,6 +284,10 @@ void KRCamera::renderFrame(KRScene &scene, KRVector3 &lightDirection, float delt GLDEBUG(glActiveTexture(GL_TEXTURE7)); GLDEBUG(glBindTexture(GL_TEXTURE_2D, 0)); } else { + // ----====---- Generate Shadowmaps for Lights ----====---- + scene.render(this, m_viewport.getVisibleBounds(), m_viewport, KRNode::RENDER_PASS_GENERATE_SHADOWMAPS, newVisibleBounds); + GLDEBUG(glViewport(0, 0, m_viewport.getSize().x, m_viewport.getSize().y)); + // ----====---- Opaque Geometry, Forward Rendering ----====---- // Set render target @@ -361,7 +316,7 @@ void KRCamera::renderFrame(KRScene &scene, KRVector3 &lightDirection, float delt // Render the geometry - scene.render(this, m_viewport.getVisibleBounds(), m_pContext, m_viewport, m_shadowViewports, lightDirection, shadowDepthTexture, m_cShadowBuffers, KRNode::RENDER_PASS_FORWARD_OPAQUE, newVisibleBounds); + scene.render(this, m_viewport.getVisibleBounds(), m_viewport, KRNode::RENDER_PASS_FORWARD_OPAQUE, newVisibleBounds); } // ----====---- Sky Box ----====---- @@ -386,8 +341,8 @@ void KRCamera::renderFrame(KRScene &scene, KRVector3 &lightDirection, float delt } if(m_pSkyBoxTexture) { - KRShader *pShader = getContext().getShaderManager()->getShader("sky_box", this, false, false, false, 0, false, false, false, false, false, false, false, false, false, false, false, false, false, KRNode::RENDER_PASS_FORWARD_OPAQUE); - pShader->bind(m_viewport, m_shadowViewports, KRMat4(), lightDirection, NULL, 0, KRNode::RENDER_PASS_FORWARD_OPAQUE); + KRShader *pShader = getContext().getShaderManager()->getShader("sky_box", this, std::stack(), false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, KRNode::RENDER_PASS_FORWARD_OPAQUE); + pShader->bind(m_viewport, KRMat4(), std::stack(), KRNode::RENDER_PASS_FORWARD_OPAQUE); getContext().getTextureManager()->selectTexture(0, m_pSkyBoxTexture, 2048); @@ -421,7 +376,7 @@ void KRCamera::renderFrame(KRScene &scene, KRVector3 &lightDirection, float delt GLDEBUG(glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)); // Render all transparent geometry - scene.render(this, m_viewport.getVisibleBounds(), m_pContext, m_viewport, m_shadowViewports, lightDirection, shadowDepthTexture, m_cShadowBuffers, KRNode::RENDER_PASS_FORWARD_TRANSPARENT, newVisibleBounds); + scene.render(this, m_viewport.getVisibleBounds(), m_viewport, KRNode::RENDER_PASS_FORWARD_TRANSPARENT, newVisibleBounds); // ----====---- Flares ----====---- @@ -445,11 +400,12 @@ void KRCamera::renderFrame(KRScene &scene, KRVector3 &lightDirection, float delt GLDEBUG(glBlendFunc(GL_ONE, GL_ONE)); // Render all flares - scene.render(this, m_viewport.getVisibleBounds(), m_pContext, m_viewport, m_shadowViewports, lightDirection, shadowDepthTexture, m_cShadowBuffers, KRNode::RENDER_PASS_ADDITIVE_PARTICLES, newVisibleBounds); + scene.render(this, m_viewport.getVisibleBounds(), m_viewport, KRNode::RENDER_PASS_ADDITIVE_PARTICLES, newVisibleBounds); // ----====---- Volumetric Lighting ----====---- - if(m_cShadowBuffers >= 1 && volumetric_environment_enable) { + if(volumetric_environment_enable) { + KRViewport volumetricLightingViewport = KRViewport(KRVector2(volumetricBufferWidth, volumetricBufferHeight), m_viewport.getViewMatrix(), m_viewport.getProjectionMatrix()); if(volumetric_environment_downsample != 0) { // Set render target @@ -463,6 +419,8 @@ void KRCamera::renderFrame(KRScene &scene, KRVector3 &lightDirection, float delt m_pContext->getTextureManager()->selectTexture(0, NULL, 0); GLDEBUG(glActiveTexture(GL_TEXTURE0)); GLDEBUG(glBindTexture(GL_TEXTURE_2D, compositeDepthTexture)); + + glViewport(0, 0, volumetricLightingViewport.getSize().x, volumetricLightingViewport.getSize().y); } else { // Enable z-buffer test GLDEBUG(glEnable(GL_DEPTH_TEST)); @@ -470,28 +428,7 @@ void KRCamera::renderFrame(KRScene &scene, KRVector3 &lightDirection, float delt GLDEBUG(glDepthRangef(0.0, 1.0)); } - std::string shader_name = volumetric_environment_downsample != 0 ? "volumetric_fog_downsampled" : "volumetric_fog"; - - KRShader *pFogShader = m_pContext->getShaderManager()->getShader(shader_name, 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(KRVector2(volumetricBufferWidth, volumetricBufferHeight), 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 = (int)(volumetric_environment_quality * 495.0) + 5; - - float slice_near = -getPerspectiveNearZ(); - float slice_far = -volumetric_environment_max_distance; - float slice_spacing = (slice_far - slice_near) / slice_count; - - KRVector2(slice_near, slice_spacing).setUniform(pFogShader->m_uniforms[KRShader::KRENGINE_UNIFORM_SLICE_DEPTH_SCALE]); - (KRVector3::One() * volumetric_environment_intensity * -slice_spacing / 1000.0f).setUniform(pFogShader->m_uniforms[KRShader::KRENGINE_UNIFORM_LIGHT_COLOR]); - - m_pContext->getModelManager()->bindVBO((void *)m_pContext->getModelManager()->getVolumetricLightingVertexes(), KRModelManager::MAX_VOLUMETRIC_PLANES * 6 * sizeof(KRModelManager::VolumetricLightingVertexData), true, false, false, false, false); - GLDEBUG(glDrawArrays(GL_TRIANGLES, 0, slice_count*6)); - } + scene.render(this, m_viewport.getVisibleBounds(), volumetricLightingViewport, KRNode::RENDER_PASS_VOLUMETRIC_EFFECTS_ADDITIVE, newVisibleBounds); if(volumetric_environment_downsample != 0) { // Set render target @@ -521,7 +458,7 @@ void KRCamera::renderFrame(KRScene &scene, KRVector3 &lightDirection, float delt GLDEBUG(glBlendFunc(GL_ONE, GL_ONE)); - KRShader *pVisShader = m_pContext->getShaderManager()->getShader("visualize_overlay", this, false, false, false, 0, false, false, false, false, false, false, false, false, false, false, false, false, false, KRNode::RENDER_PASS_FORWARD_TRANSPARENT); + KRShader *pVisShader = getContext().getShaderManager()->getShader("visualize_overlay", this, std::stack(), false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, KRNode::RENDER_PASS_FORWARD_TRANSPARENT); KRMat4 projectionMatrix = getProjectionMatrix(); @@ -530,7 +467,7 @@ void KRCamera::renderFrame(KRScene &scene, KRVector3 &lightDirection, float delt KRMat4 matModel = KRMat4(); matModel.scale((*itr).size() / 2.0f); matModel.translate((*itr).center()); - if(pVisShader->bind(m_viewport, m_shadowViewports, matModel, lightDirection, shadowDepthTexture, 0, KRNode::RENDER_PASS_FORWARD_TRANSPARENT)) { + if(pVisShader->bind(m_viewport, matModel, std::stack(), KRNode::RENDER_PASS_FORWARD_TRANSPARENT)) { GLDEBUG(glDrawArrays(GL_TRIANGLE_STRIP, 0, 14)); } } @@ -660,55 +597,10 @@ void KRCamera::createBuffers() { GLDEBUG(glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, volumetricLightAccumulationTexture, 0)); } } - allocateShadowBuffers(m_cShadowBuffers); -} - -void KRCamera::allocateShadowBuffers(int cBuffers) { - // First deallocate buffers no longer needed - for(int iShadow = cBuffers; iShadow < KRENGINE_MAX_SHADOW_BUFFERS; iShadow++) { - if (shadowDepthTexture[iShadow]) { - GLDEBUG(glDeleteTextures(1, shadowDepthTexture + iShadow)); - shadowDepthTexture[iShadow] = 0; - } - - if (shadowFramebuffer[iShadow]) { - GLDEBUG(glDeleteFramebuffers(1, shadowFramebuffer + iShadow)); - shadowFramebuffer[iShadow] = 0; - } - } - - // Allocate newly required buffers - for(int iShadow = 0; iShadow < cBuffers; iShadow++) { - if(!shadowDepthTexture[iShadow]) { - shadowValid[iShadow] = false; - - GLDEBUG(glGenFramebuffers(1, shadowFramebuffer + iShadow)); - GLDEBUG(glGenTextures(1, shadowDepthTexture + iShadow)); - // ===== Create offscreen shadow framebuffer object ===== - - GLDEBUG(glBindFramebuffer(GL_FRAMEBUFFER, shadowFramebuffer[iShadow])); - - // ----- Create Depth Texture for shadowFramebuffer ----- - GLDEBUG( glBindTexture(GL_TEXTURE_2D, shadowDepthTexture[iShadow])); - GLDEBUG(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST)); - GLDEBUG(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST)); - GLDEBUG(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE)); - GLDEBUG(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE)); -#if GL_EXT_shadow_samplers - GLDEBUG(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE_EXT, GL_COMPARE_REF_TO_TEXTURE_EXT)); // TODO - Detect GL_EXT_shadow_samplers and only activate if available - GLDEBUG(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC_EXT, GL_LEQUAL)); // TODO - Detect GL_EXT_shadow_samplers and only activate if available -#endif - GLDEBUG(glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, KRENGINE_SHADOW_MAP_WIDTH, KRENGINE_SHADOW_MAP_HEIGHT, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, NULL)); - - GLDEBUG(glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, shadowDepthTexture[iShadow], 0)); - } - } } void KRCamera::destroyBuffers() { - allocateShadowBuffers(0); - if (compositeDepthTexture) { GLDEBUG(glDeleteTextures(1, &compositeDepthTexture)); compositeDepthTexture = 0; @@ -745,70 +637,6 @@ void KRCamera::destroyBuffers() } } - -void KRCamera::renderShadowBuffer(KRScene &scene, int iShadow) -{ - - glViewport(0, 0, m_shadowViewports[iShadow].getSize().x, m_shadowViewports[iShadow].getSize().y); - - GLDEBUG(glBindFramebuffer(GL_FRAMEBUFFER, shadowFramebuffer[iShadow])); - GLDEBUG(glClearDepthf(1.0f)); - GLDEBUG(glClear(GL_DEPTH_BUFFER_BIT)); - - glViewport(1, 1, m_shadowViewports[iShadow].getSize().x - 2, m_shadowViewports[iShadow].getSize().y - 2); - - GLDEBUG(glDisable(GL_DITHER)); - - GLDEBUG(glCullFace(GL_BACK)); // Enable frontface culling, which eliminates some self-cast shadow artifacts - GLDEBUG(glEnable(GL_CULL_FACE)); - - // Enable z-buffer test - GLDEBUG(glEnable(GL_DEPTH_TEST)); - GLDEBUG(glDepthFunc(GL_LESS)); - GLDEBUG(glDepthRangef(0.0, 1.0)); - - // Disable alpha blending as we are using alpha channel for packed depth info - GLDEBUG(glDisable(GL_BLEND)); - - // Use shader program - KRShader *shadowShader = m_pContext->getShaderManager()->getShader("ShadowShader", this, false, false, false, 0, false, false, false, false, false, false, false, false, false, false, false, false, false, KRNode::RENDER_PASS_FORWARD_TRANSPARENT); - - shadowShader->bind(m_shadowViewports[iShadow], m_shadowViewports, KRMat4(), KRVector3(), NULL, 0, KRNode::RENDER_PASS_SHADOWMAP); - -// // Bind our modelmatrix variable to be a uniform called mvpmatrix in our shaderprogram -// shadowmvpmatrix[iShadow].setUniform(shadowShader->m_uniforms[KRShader::KRENGINE_UNIFORM_SHADOWMVP1]); - -// // Calculate the bounding volume of the light map -// KRMat4 matInvShadow = shadowmvpmatrix[iShadow]; -// matInvShadow.invert(); -// -// KRVector3 vertices[8]; -// vertices[0] = KRVector3(-1.0, -1.0, 0.0); -// vertices[1] = KRVector3(1.0, -1.0, 0.0); -// vertices[2] = KRVector3(1.0, 1.0, 0.0); -// vertices[3] = KRVector3(-1.0, 1.0, 0.0); -// vertices[4] = KRVector3(-1.0, -1.0, 1.0); -// vertices[5] = KRVector3(1.0, -1.0, 1.0); -// vertices[6] = KRVector3(1.0, 1.0, 1.0); -// vertices[7] = KRVector3(-1.0, 1.0, 1.0); -// -// for(int iVertex=0; iVertex < 8; iVertex++) { -// vertices[iVertex] = KRMat4::Dot(matInvShadow, vertices[iVertex]); -// } -// -// KRVector3 cameraPosition; -// KRVector3 lightDirection; -// KRBoundingVolume shadowVolume = KRBoundingVolume(vertices); - - - KRVector3 temp = KRVector3(); - std::set newVisibleBounds; - scene.render(this, m_shadowViewports[iShadow].getVisibleBounds(), m_pContext, m_shadowViewports[iShadow], m_shadowViewports, temp, NULL, m_cShadowBuffers, KRNode::RENDER_PASS_SHADOWMAP, newVisibleBounds); - - m_shadowViewports[iShadow].setVisibleBounds(newVisibleBounds); - GLDEBUG(glViewport(0, 0, m_viewport.getSize().x, m_viewport.getSize().y)); -} - void KRCamera::renderPost() { // Disable alpha blending @@ -836,8 +664,8 @@ void KRCamera::renderPost() GLDEBUG(glDisable(GL_DEPTH_TEST)); - KRShader *postShader = m_pContext->getShaderManager()->getShader("PostShader", this, false, false, false, 0, false, false, false, false, false, false, false, false, false, false, false, false, false, KRNode::RENDER_PASS_FORWARD_TRANSPARENT); - postShader->bind(m_viewport, m_shadowViewports, KRMat4(), KRVector3(), shadowDepthTexture, m_cShadowBuffers, KRNode::RENDER_PASS_FORWARD_TRANSPARENT); + KRShader *postShader = m_pContext->getShaderManager()->getShader("PostShader", this, std::stack(), false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, KRNode::RENDER_PASS_FORWARD_TRANSPARENT); + postShader->bind(m_viewport, KRMat4(), std::stack(), KRNode::RENDER_PASS_FORWARD_TRANSPARENT); m_pContext->getTextureManager()->selectTexture(0, NULL, 0); GLDEBUG(glActiveTexture(GL_TEXTURE0)); @@ -867,37 +695,37 @@ void KRCamera::renderPost() GLDEBUG(glBindTexture(GL_TEXTURE_2D, 0)); - if(bShowShadowBuffer) { - KRShader *blitShader = m_pContext->getShaderManager()->getShader("simple_blit", this, false, false, false, 0, false, false, false, false, false, false, false, false, false, false, false, false, false, KRNode::RENDER_PASS_FORWARD_TRANSPARENT); - - for(int iShadow=0; iShadow < m_cShadowBuffers; iShadow++) { - KRMat4 viewMatrix = KRMat4(); - viewMatrix.scale(0.20, 0.20, 0.20); - viewMatrix.translate(-0.70, 0.70 - 0.45 * iShadow, 0.0); - blitShader->bind(KRViewport(getViewportSize(), viewMatrix, KRMat4()), m_shadowViewports, KRMat4(), KRVector3(), NULL, 0, KRNode::RENDER_PASS_FORWARD_TRANSPARENT); - m_pContext->getTextureManager()->selectTexture(1, NULL, 0); - m_pContext->getModelManager()->bindVBO((void *)KRENGINE_VBO_2D_SQUARE, KRENGINE_VBO_2D_SQUARE_SIZE, true, false, false, true, false); - GLDEBUG(glActiveTexture(GL_TEXTURE0)); - GLDEBUG(glBindTexture(GL_TEXTURE_2D, shadowDepthTexture[iShadow])); -#if GL_EXT_shadow_samplers - GLDEBUG(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE_EXT, GL_NONE)); // TODO - Detect GL_EXT_shadow_samplers and only activate if available -#endif - GLDEBUG(glDrawArrays(GL_TRIANGLE_STRIP, 0, 4)); -#if GL_EXT_shadow_samplers - GLDEBUG(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE_EXT, GL_COMPARE_REF_TO_TEXTURE_EXT)); // TODO - Detect GL_EXT_shadow_samplers and only activate if available -#endif - } - - m_pContext->getTextureManager()->selectTexture(0, NULL, 0); - GLDEBUG(glActiveTexture(GL_TEXTURE0)); - GLDEBUG(glBindTexture(GL_TEXTURE_2D, 0)); - } +// if(bShowShadowBuffer) { +// KRShader *blitShader = m_pContext->getShaderManager()->getShader("simple_blit", this, false, false, false, 0, false, false, false, false, false, false, false, false, false, false, false, false, false, KRNode::RENDER_PASS_FORWARD_TRANSPARENT); +// +// for(int iShadow=0; iShadow < m_cShadowBuffers; iShadow++) { +// KRMat4 viewMatrix = KRMat4(); +// viewMatrix.scale(0.20, 0.20, 0.20); +// viewMatrix.translate(-0.70, 0.70 - 0.45 * iShadow, 0.0); +// blitShader->bind(KRViewport(getViewportSize(), viewMatrix, KRMat4()), shadowViewports, KRMat4(), KRVector3(), NULL, 0, KRNode::RENDER_PASS_FORWARD_TRANSPARENT); +// m_pContext->getTextureManager()->selectTexture(1, NULL, 0); +// m_pContext->getModelManager()->bindVBO((void *)KRENGINE_VBO_2D_SQUARE, KRENGINE_VBO_2D_SQUARE_SIZE, true, false, false, true, false); +// GLDEBUG(glActiveTexture(GL_TEXTURE0)); +// GLDEBUG(glBindTexture(GL_TEXTURE_2D, shadowDepthTexture[iShadow])); +//#if GL_EXT_shadow_samplers +// GLDEBUG(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE_EXT, GL_NONE)); // TODO - Detect GL_EXT_shadow_samplers and only activate if available +//#endif +// GLDEBUG(glDrawArrays(GL_TRIANGLE_STRIP, 0, 4)); +//#if GL_EXT_shadow_samplers +// GLDEBUG(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE_EXT, GL_COMPARE_REF_TO_TEXTURE_EXT)); // TODO - Detect GL_EXT_shadow_samplers and only activate if available +//#endif +// } +// +// m_pContext->getTextureManager()->selectTexture(0, NULL, 0); +// GLDEBUG(glActiveTexture(GL_TEXTURE0)); +// GLDEBUG(glBindTexture(GL_TEXTURE_2D, 0)); +// } const char *szText = m_debug_text.c_str(); if(*szText) { - KRShader *fontShader = m_pContext->getShaderManager()->getShader("debug_font", this, false, false, false, 0, false, false, false, false, false, false, false, false, false, false, false, false, false, KRNode::RENDER_PASS_FORWARD_TRANSPARENT); + KRShader *fontShader = m_pContext->getShaderManager()->getShader("debug_font", this, std::stack(), false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, KRNode::RENDER_PASS_FORWARD_TRANSPARENT); m_pContext->getTextureManager()->selectTexture(0, m_pContext->getTextureManager()->getTexture("font"), 2048); @@ -942,12 +770,6 @@ void KRCamera::renderPost() } -void KRCamera::invalidateShadowBuffers() { - for(int i=0; i < m_cShadowBuffers; i++) { - shadowValid[i] = false; - } -} - void KRCamera::setSkyBox(const std::string &skyBoxName) { m_pSkyBoxTexture = NULL; m_skyBoxName = skyBoxName; @@ -965,13 +787,11 @@ void KRCamera::setPerspectiveNear(float v) { if(perspective_nearz != v) { perspective_nearz = v; - invalidateShadowBuffers(); } } void KRCamera::setPerpsectiveFarZ(float v) { if(perspective_farz != v) { perspective_farz = v; - invalidateShadowBuffers(); } } diff --git a/KREngine/KREngine/Classes/KRCamera.h b/KREngine/KREngine/Classes/KRCamera.h index b826b07..7b7111d 100644 --- a/KREngine/KREngine/Classes/KRCamera.h +++ b/KREngine/KREngine/Classes/KRCamera.h @@ -43,10 +43,6 @@ #import "KRContext.h" #import "KRViewport.h" -#define KRENGINE_MAX_SHADOW_BUFFERS 3 -#define KRENGINE_SHADOW_MAP_WIDTH 4096 -#define KRENGINE_SHADOW_MAP_HEIGHT 4096 - class KRInstance; class KRScene; class KRViewport; @@ -130,9 +126,6 @@ public: private: KRVector3 m_position; - void renderShadowBuffer(KRScene &scene, int iShadow); - void invalidateShadowBuffers(); - void allocateShadowBuffers(int cBuffers); void createBuffers(); float perspective_nearz; @@ -145,12 +138,6 @@ private: GLuint volumetricLightAccumulationBuffer, volumetricLightAccumulationTexture; - - GLuint shadowFramebuffer[KRENGINE_MAX_SHADOW_BUFFERS], shadowDepthTexture[KRENGINE_MAX_SHADOW_BUFFERS]; - bool shadowValid[KRENGINE_MAX_SHADOW_BUFFERS]; - - KRViewport m_shadowViewports[KRENGINE_MAX_SHADOW_BUFFERS]; - void renderPost(); void destroyBuffers(); diff --git a/KREngine/KREngine/Classes/KRDirectionalLight.cpp b/KREngine/KREngine/Classes/KRDirectionalLight.cpp index 98f4650..e97c6bd 100644 --- a/KREngine/KREngine/Classes/KRDirectionalLight.cpp +++ b/KREngine/KREngine/Classes/KRDirectionalLight.cpp @@ -48,11 +48,68 @@ KRVector3 KRDirectionalLight::getLocalLightDirection() { return KRVector3(0.0, 0.0, 1.0); } + +int KRDirectionalLight::configureShadowBufferViewports(const KRViewport &viewport) { + for(int iShadow=0; iShadow < 1; iShadow++) { + GLfloat shadowMinDepths[3][3] = {{0.0, 0.0, 0.0},{0.0, 0.0, 0.0},{0.0, 0.05, 0.3}}; + GLfloat shadowMaxDepths[3][3] = {{0.0, 0.0, 1.0},{0.1, 0.0, 0.0},{0.1, 0.3, 1.0}}; + + KRVector3 shadowLook = -KRVector3::Normalize(getWorldLightDirection()); + + KRVector3 shadowUp(0.0, 1.0, 0.0); + if(KRVector3::Dot(shadowUp, shadowLook) > 0.99f) shadowUp = KRVector3(0.0, 0.0, 1.0); // Ensure shadow look direction is not parallel with the shadowUp direction + + KRMat4 matShadowView = KRMat4::LookAt(viewport.getCameraPosition() - shadowLook, viewport.getCameraPosition(), shadowUp); + + + KRMat4 matShadowProjection = KRMat4(); + matShadowProjection.scale(0.001, 0.001, 0.001); + + KRMat4 matBias; + matBias.bias(); + matShadowProjection *= matBias; + + + + + // KRAABB frustrumWorldBounds = KRAABB(KRVector3(-1.0, -1.0, 0.0), KRVector3(1.0, 1.0, 1.0), m_viewport.getInverseProjectionMatrix() * m_viewport.getInverseViewMatrix()); + // matShadowProjection.translate(KRVector3(0.0, 0.0, -frustrumWorldBounds.size().z)); + // matShadowProjection.scale(2.0 / frustrumWorldBounds.size().x, 2.0 / frustrumWorldBounds.size().y, 2.0 / frustrumWorldBounds.size().z); + // matShadowView.translate(-m_viewport.getCameraPosition()); + + //matShadowProjection *= matBias; + + m_shadowViewports[iShadow] = KRViewport(KRVector2(KRENGINE_SHADOW_MAP_WIDTH, KRENGINE_SHADOW_MAP_HEIGHT), matShadowView, matShadowProjection); + + // KRMat4 newShadowMVP; + // if(shadowMaxDepths[m_cShadowBuffers - 1][iShadow] == 0.0) { + // KRBoundingVolume ext = KRBoundingVolume(-KRVector3::One(), KRVector3::One(), KRMat4()); // HACK - Temporary workaround to compile until this logic is updated to use information from the Octree + // + // newShadowMVP = ext.calcShadowProj(&scene, m_pContext, scene.sun_yaw, scene.sun_pitch); + // } else { + // KRBoundingVolume frustrumSliceVolume = KRBoundingVolume(viewMatrix, perspective_fov, getViewportSize().x / getViewportSize().y, perspective_nearz + (perspective_farz - perspective_nearz) * shadowMinDepths[m_cShadowBuffers - 1][iShadow], perspective_nearz + (perspective_farz - perspective_nearz) * shadowMaxDepths[m_cShadowBuffers - 1][iShadow]); + // newShadowMVP = frustrumSliceVolume.calcShadowProj(&scene, m_pContext, scene.sun_yaw, scene.sun_pitch); + // } + + // KRBoundingVolume frustrumSliceVolume = KRBoundingVolume(viewMatrix, perspective_fov, getViewportSize().x / getViewportSize().y, perspective_nearz + (perspective_farz - perspective_nearz) * shadowMinDepths[m_cShadowBuffers - 1][iShadow], perspective_nearz + (perspective_farz - perspective_nearz) * shadowMaxDepths[m_cShadowBuffers - 1][iShadow]); + // newShadowMVP = frustrumSliceVolume.calcShadowProj(&scene, m_pContext, scene.sun_yaw, scene.sun_pitch); + // + // m_shadowViewports[iShadow] = KRViewport(KRVector2(KRENGINE_SHADOW_MAP_WIDTH, KRENGINE_SHADOW_MAP_HEIGHT), KRMat4(), newShadowMVP); + // + + +// renderShadowBuffer(scene, iShadow); + + } + + return 1; +} + #if TARGET_OS_IPHONE -void KRDirectionalLight::render(KRCamera *pCamera, KRContext *pContext, const KRViewport &viewport, const KRViewport *pShadowViewports, KRVector3 &lightDirection, GLuint *shadowDepthTextures, int cShadowBuffers, KRNode::RenderPass renderPass) { +void KRDirectionalLight::render(KRCamera *pCamera, std::stack &lights, const KRViewport &viewport, KRNode::RenderPass renderPass) { - KRLight::render(pCamera, pContext, viewport, pShadowViewports, lightDirection, shadowDepthTextures, cShadowBuffers, renderPass); + KRLight::render(pCamera, lights, viewport, renderPass); if(renderPass == KRNode::RENDER_PASS_DEFERRED_LIGHTS) { // Lights are rendered on the second pass of the deferred renderer @@ -65,8 +122,8 @@ void KRDirectionalLight::render(KRCamera *pCamera, KRContext *pContext, const KR light_direction_view_space = KRMat4::Dot(matModelViewInverseTranspose, light_direction_view_space); light_direction_view_space.normalize(); - KRShader *pShader = pContext->getShaderManager()->getShader("light_directional", pCamera, false, false, false, 0, false, false, false, false, false, false, false, false, false, false, false, false, false, renderPass); - if(pShader->bind(viewport, pShadowViewports, getModelMatrix(), lightDirection, shadowDepthTextures, 0, renderPass)) { + KRShader *pShader = getContext().getShaderManager()->getShader("light_directional", pCamera, lights, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, renderPass); + if(pShader->bind(viewport, getModelMatrix(), lights, renderPass)) { light_direction_view_space.setUniform(pShader->m_uniforms[KRShader::KRENGINE_UNIFORM_LIGHT_DIRECTION_VIEW_SPACE]); m_color.setUniform(pShader->m_uniforms[KRShader::KRENGINE_UNIFORM_LIGHT_COLOR]); diff --git a/KREngine/KREngine/Classes/KRDirectionalLight.h b/KREngine/KREngine/Classes/KRDirectionalLight.h index a273ceb..d53f874 100644 --- a/KREngine/KREngine/Classes/KRDirectionalLight.h +++ b/KREngine/KREngine/Classes/KRDirectionalLight.h @@ -25,9 +25,13 @@ public: #if TARGET_OS_IPHONE - virtual void render(KRCamera *pCamera, KRContext *pContext, const KRViewport &viewport, const KRViewport *pShadowViewports, KRVector3 &lightDirection, GLuint *shadowDepthTextures, int cShadowBuffers, KRNode::RenderPass renderPass); + virtual void render(KRCamera *pCamera, std::stack &lights, const KRViewport &viewport, KRNode::RenderPass renderPass); #endif +protected: + + virtual int configureShadowBufferViewports(const KRViewport &viewport); + }; diff --git a/KREngine/KREngine/Classes/KRInstance.cpp b/KREngine/KREngine/Classes/KRInstance.cpp index a48dfcd..b6586f1 100644 --- a/KREngine/KREngine/Classes/KRInstance.cpp +++ b/KREngine/KREngine/Classes/KRInstance.cpp @@ -75,12 +75,12 @@ void KRInstance::loadModel() { #if TARGET_OS_IPHONE -void KRInstance::render(KRCamera *pCamera, KRContext *pContext, const KRViewport &viewport, const KRViewport *pShadowViewports, KRVector3 &lightDirection, GLuint *shadowDepthTextures, int cShadowBuffers, KRNode::RenderPass renderPass) { +void KRInstance::render(KRCamera *pCamera, std::stack &lights, const KRViewport &viewport, KRNode::RenderPass renderPass) { - KRNode::render(pCamera, pContext, viewport, pShadowViewports, lightDirection, shadowDepthTextures, cShadowBuffers, renderPass); + 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) { + 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) { // Don't render meshes on second pass of the deferred lighting renderer, as only lights will be applied loadModel(); @@ -103,14 +103,14 @@ void KRInstance::render(KRCamera *pCamera, KRContext *pContext, const KRViewport } if(m_pLightMap == NULL && m_lightMap.size()) { - m_pLightMap = pContext->getTextureManager()->getTexture(m_lightMap.c_str()); + m_pLightMap = getContext().getTextureManager()->getTexture(m_lightMap.c_str()); } - if(m_pLightMap && pCamera->bEnableLightMap && renderPass != RENDER_PASS_SHADOWMAP) { + if(m_pLightMap && pCamera->bEnableLightMap && renderPass != RENDER_PASS_SHADOWMAP && renderPass != RENDER_PASS_GENERATE_SHADOWMAPS) { m_pContext->getTextureManager()->selectTexture(5, m_pLightMap, 2048); } - pModel->render(pCamera, pContext, viewport, pShadowViewports, getModelMatrix(), lightDirection, shadowDepthTextures, m_receivesShadow ? cShadowBuffers : 0, m_pLightMap, renderPass); + pModel->render(pCamera, lights, viewport, getModelMatrix(), m_pLightMap, renderPass); } } } diff --git a/KREngine/KREngine/Classes/KRInstance.h b/KREngine/KREngine/Classes/KRInstance.h index 0838f04..949c20c 100644 --- a/KREngine/KREngine/Classes/KRInstance.h +++ b/KREngine/KREngine/Classes/KRInstance.h @@ -58,7 +58,7 @@ public: #if TARGET_OS_IPHONE - virtual void render(KRCamera *pCamera, KRContext *pContext, const KRViewport &viewport, const KRViewport *pShadowViewports, KRVector3 &lightDirection, GLuint *shadowDepthTextures, int cShadowBuffers, KRNode::RenderPass renderPass); + virtual void render(KRCamera *pCamera, std::stack &lights, const KRViewport &viewport, KRNode::RenderPass renderPass); #endif bool hasTransparency(); diff --git a/KREngine/KREngine/Classes/KRLight.cpp b/KREngine/KREngine/Classes/KRLight.cpp index 14a21a4..afa53e7 100644 --- a/KREngine/KREngine/Classes/KRLight.cpp +++ b/KREngine/KREngine/Classes/KRLight.cpp @@ -29,11 +29,17 @@ KRLight::KRLight(KRScene &scene, std::string name) : KRNode(scene, name) m_flareTexture = ""; m_pFlareTexture = NULL; m_flareSize = 0.0; + + // Initialize shadow buffers + m_cShadowBuffers = 0; + memset(shadowFramebuffer, sizeof(GLuint) * KRENGINE_MAX_SHADOW_BUFFERS, 0); + memset(shadowDepthTexture, sizeof(GLuint) * KRENGINE_MAX_SHADOW_BUFFERS, 0); + memset(shadowValid, sizeof(bool) * KRENGINE_MAX_SHADOW_BUFFERS, 0); } KRLight::~KRLight() { - + allocateShadowBuffers(0); } tinyxml2::XMLElement *KRLight::saveXML( tinyxml2::XMLNode *parent) @@ -118,14 +124,44 @@ float KRLight::getDecayStart() { #if TARGET_OS_IPHONE -void KRLight::render(KRCamera *pCamera, KRContext *pContext, const KRViewport &viewport, const KRViewport *pShadowViewports, KRVector3 &lightDirection, GLuint *shadowDepthTextures, int cShadowBuffers, KRNode::RenderPass renderPass) { +void KRLight::render(KRCamera *pCamera, std::stack &lights, const KRViewport &viewport, KRNode::RenderPass renderPass) { - KRNode::render(pCamera, pContext, viewport, pShadowViewports, lightDirection, shadowDepthTextures, cShadowBuffers, renderPass); + KRNode::render(pCamera, lights, viewport, renderPass); + + if(renderPass == KRNode::RENDER_PASS_GENERATE_SHADOWMAPS) { + allocateShadowBuffers(configureShadowBufferViewports(viewport)); + renderShadowBuffers(pCamera); + } + + if(renderPass == KRNode::RENDER_PASS_VOLUMETRIC_EFFECTS_ADDITIVE) { + std::string shader_name = pCamera->volumetric_environment_downsample != 0 ? "volumetric_fog_downsampled" : "volumetric_fog"; + + std::stack this_light; + this_light.push(this); + + KRShader *pFogShader = m_pContext->getShaderManager()->getShader(shader_name, pCamera, this_light, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, KRNode::RENDER_PASS_ADDITIVE_PARTICLES); + + + if(pFogShader->bind(viewport, KRMat4(), std::stack(), KRNode::RENDER_PASS_VOLUMETRIC_EFFECTS_ADDITIVE)) { + int slice_count = (int)(pCamera->volumetric_environment_quality * 495.0) + 5; + + float slice_near = -pCamera->getPerspectiveNearZ(); + float slice_far = -pCamera->volumetric_environment_max_distance; + float slice_spacing = (slice_far - slice_near) / slice_count; + + KRVector2(slice_near, slice_spacing).setUniform(pFogShader->m_uniforms[KRShader::KRENGINE_UNIFORM_SLICE_DEPTH_SCALE]); + (KRVector3::One() * pCamera->volumetric_environment_intensity * -slice_spacing / 1000.0f).setUniform(pFogShader->m_uniforms[KRShader::KRENGINE_UNIFORM_LIGHT_COLOR]); + + m_pContext->getModelManager()->bindVBO((void *)m_pContext->getModelManager()->getVolumetricLightingVertexes(), KRModelManager::MAX_VOLUMETRIC_PLANES * 6 * sizeof(KRModelManager::VolumetricLightingVertexData), true, false, false, false, false); + GLDEBUG(glDrawArrays(GL_TRIANGLES, 0, slice_count*6)); + } + + } if(renderPass == KRNode::RENDER_PASS_ADDITIVE_PARTICLES) { if(m_flareTexture.size() && m_flareSize > 0.0f) { if(!m_pFlareTexture && m_flareTexture.size()) { - m_pFlareTexture = pContext->getTextureManager()->getTexture(m_flareTexture.c_str()); + m_pFlareTexture = getContext().getTextureManager()->getTexture(m_flareTexture.c_str()); } if(m_pFlareTexture) { @@ -134,8 +170,8 @@ void KRLight::render(KRCamera *pCamera, KRContext *pContext, const KRViewport &v GLDEBUG(glDepthRangef(0.0, 1.0)); // Render light flare on transparency pass - KRShader *pShader = pContext->getShaderManager()->getShader("flare", pCamera, false, false, false, 0, false, false, false, false, false, false, false, false, false, false, false, false, false, renderPass); - if(pShader->bind(viewport, pShadowViewports, getModelMatrix(), lightDirection, shadowDepthTextures, 0, renderPass)) { + KRShader *pShader = getContext().getShaderManager()->getShader("flare", pCamera, lights, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, renderPass); + if(pShader->bind(viewport, getModelMatrix(), lights, renderPass)) { GLDEBUG(glUniform1f( pShader->m_uniforms[KRShader::KRENGINE_UNIFORM_FLARE_SIZE], m_flareSize @@ -150,4 +186,132 @@ void KRLight::render(KRCamera *pCamera, KRContext *pContext, const KRViewport &v } } + +void KRLight::allocateShadowBuffers(int cBuffers) { + // First deallocate buffers no longer needed + for(int iShadow = cBuffers; iShadow < KRENGINE_MAX_SHADOW_BUFFERS; iShadow++) { + if (shadowDepthTexture[iShadow]) { + GLDEBUG(glDeleteTextures(1, shadowDepthTexture + iShadow)); + shadowDepthTexture[iShadow] = 0; + } + + if (shadowFramebuffer[iShadow]) { + GLDEBUG(glDeleteFramebuffers(1, shadowFramebuffer + iShadow)); + shadowFramebuffer[iShadow] = 0; + } + } + + // Allocate newly required buffers + for(int iShadow = 0; iShadow < cBuffers; iShadow++) { + KRVector2 viewportSize = m_shadowViewports[iShadow].getSize(); + + if(!shadowDepthTexture[iShadow]) { + shadowValid[iShadow] = false; + + GLDEBUG(glGenFramebuffers(1, shadowFramebuffer + iShadow)); + GLDEBUG(glGenTextures(1, shadowDepthTexture + iShadow)); + // ===== Create offscreen shadow framebuffer object ===== + + GLDEBUG(glBindFramebuffer(GL_FRAMEBUFFER, shadowFramebuffer[iShadow])); + + // ----- Create Depth Texture for shadowFramebuffer ----- + GLDEBUG( glBindTexture(GL_TEXTURE_2D, shadowDepthTexture[iShadow])); + GLDEBUG(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST)); + GLDEBUG(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST)); + GLDEBUG(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE)); + GLDEBUG(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE)); +#if GL_EXT_shadow_samplers + GLDEBUG(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE_EXT, GL_COMPARE_REF_TO_TEXTURE_EXT)); // TODO - Detect GL_EXT_shadow_samplers and only activate if available + GLDEBUG(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC_EXT, GL_LEQUAL)); // TODO - Detect GL_EXT_shadow_samplers and only activate if available +#endif + GLDEBUG(glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, viewportSize.x, viewportSize.y, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, NULL)); + + GLDEBUG(glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, shadowDepthTexture[iShadow], 0)); + } + } + + m_cShadowBuffers = cBuffers; +} + + +void KRLight::deleteBuffers() +{ + // Called when this light wasn't used in the last frame, so we can free the resources for use by other lights + allocateShadowBuffers(0); +} + +void KRLight::invalidateShadowBuffers() +{ + memset(shadowValid, sizeof(bool) * KRENGINE_MAX_SHADOW_BUFFERS, 0); +} + +int KRLight::configureShadowBufferViewports(const KRViewport &viewport) +{ + return 0; +} + +void KRLight::renderShadowBuffers(KRCamera *pCamera) +{ + for(int iShadow=0; iShadow < m_cShadowBuffers; iShadow++) { + glViewport(0, 0, m_shadowViewports[iShadow].getSize().x, m_shadowViewports[iShadow].getSize().y); + + GLDEBUG(glBindFramebuffer(GL_FRAMEBUFFER, shadowFramebuffer[iShadow])); + GLDEBUG(glClearDepthf(1.0f)); + GLDEBUG(glClear(GL_DEPTH_BUFFER_BIT)); + + glViewport(1, 1, m_shadowViewports[iShadow].getSize().x - 2, m_shadowViewports[iShadow].getSize().y - 2); + + GLDEBUG(glDisable(GL_DITHER)); + + GLDEBUG(glCullFace(GL_BACK)); // Enable frontface culling, which eliminates some self-cast shadow artifacts + GLDEBUG(glEnable(GL_CULL_FACE)); + + // Enable z-buffer test + GLDEBUG(glEnable(GL_DEPTH_TEST)); + GLDEBUG(glDepthFunc(GL_LESS)); + GLDEBUG(glDepthRangef(0.0, 1.0)); + + // Disable alpha blending as we are using alpha channel for packed depth info + GLDEBUG(glDisable(GL_BLEND)); + + // Use shader program + KRShader *shadowShader = m_pContext->getShaderManager()->getShader("ShadowShader", pCamera, std::stack(), false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, KRNode::RENDER_PASS_FORWARD_TRANSPARENT); + + shadowShader->bind(m_shadowViewports[iShadow], KRMat4(), std::stack(), KRNode::RENDER_PASS_SHADOWMAP); + + // // Bind our modelmatrix variable to be a uniform called mvpmatrix in our shaderprogram + // shadowmvpmatrix[iShadow].setUniform(shadowShader->m_uniforms[KRShader::KRENGINE_UNIFORM_SHADOWMVP1]); + + // // Calculate the bounding volume of the light map + // KRMat4 matInvShadow = shadowmvpmatrix[iShadow]; + // matInvShadow.invert(); + // + // KRVector3 vertices[8]; + // vertices[0] = KRVector3(-1.0, -1.0, 0.0); + // vertices[1] = KRVector3(1.0, -1.0, 0.0); + // vertices[2] = KRVector3(1.0, 1.0, 0.0); + // vertices[3] = KRVector3(-1.0, 1.0, 0.0); + // vertices[4] = KRVector3(-1.0, -1.0, 1.0); + // vertices[5] = KRVector3(1.0, -1.0, 1.0); + // vertices[6] = KRVector3(1.0, 1.0, 1.0); + // vertices[7] = KRVector3(-1.0, 1.0, 1.0); + // + // for(int iVertex=0; iVertex < 8; iVertex++) { + // vertices[iVertex] = KRMat4::Dot(matInvShadow, vertices[iVertex]); + // } + // + // KRVector3 cameraPosition; + // KRVector3 lightDirection; + // KRBoundingVolume shadowVolume = KRBoundingVolume(vertices); + + + std::set newVisibleBounds; + + getScene().render(pCamera, m_shadowViewports[iShadow].getVisibleBounds(), m_shadowViewports[iShadow], KRNode::RENDER_PASS_SHADOWMAP, newVisibleBounds); + + m_shadowViewports[iShadow].setVisibleBounds(newVisibleBounds); + + } +} + #endif diff --git a/KREngine/KREngine/Classes/KRLight.h b/KREngine/KREngine/Classes/KRLight.h index e33ba44..e95f3ac 100644 --- a/KREngine/KREngine/Classes/KRLight.h +++ b/KREngine/KREngine/Classes/KRLight.h @@ -15,6 +15,12 @@ static const float KRLIGHT_MIN_INFLUENCE = 0.15f; // 0.05f +// KRENGINE_MAX_SHADOW_BUFFERS must be at least 6 to allow omni-directional lights to render cube maps + +#define KRENGINE_MAX_SHADOW_BUFFERS 6 +#define KRENGINE_SHADOW_MAP_WIDTH 4096 +#define KRENGINE_SHADOW_MAP_HEIGHT 4096 + class KRLight : public KRNode { public: @@ -33,10 +39,11 @@ public: void setFlareTexture(std::string flare_texture); void setFlareSize(float flare_size); + void deleteBuffers(); #if TARGET_OS_IPHONE - virtual void render(KRCamera *pCamera, KRContext *pContext, const KRViewport &viewport, const KRViewport *pShadowViewports, KRVector3 &lightDirection, GLuint *shadowDepthTextures, int cShadowBuffers, KRNode::RenderPass renderPass); + virtual void render(KRCamera *pCamera, std::stack &lights, const KRViewport &viewport, KRNode::RenderPass renderPass); #endif @@ -50,6 +57,19 @@ protected: std::string m_flareTexture; KRTexture *m_pFlareTexture; float m_flareSize; + + + // Shadow Maps + int m_cShadowBuffers; + GLuint shadowFramebuffer[KRENGINE_MAX_SHADOW_BUFFERS], shadowDepthTexture[KRENGINE_MAX_SHADOW_BUFFERS]; + bool shadowValid[KRENGINE_MAX_SHADOW_BUFFERS]; + KRViewport m_shadowViewports[KRENGINE_MAX_SHADOW_BUFFERS]; + + void allocateShadowBuffers(int cBuffers); + void invalidateShadowBuffers(); + + virtual int configureShadowBufferViewports(const KRViewport &viewport); + void renderShadowBuffers(KRCamera *pCamera); }; #endif diff --git a/KREngine/KREngine/Classes/KRMaterial.cpp b/KREngine/KREngine/Classes/KRMaterial.cpp index c34bd90..2935ee8 100644 --- a/KREngine/KREngine/Classes/KRMaterial.cpp +++ b/KREngine/KREngine/Classes/KRMaterial.cpp @@ -201,27 +201,27 @@ bool KRMaterial::isTransparent() { } #if TARGET_OS_IPHONE -bool KRMaterial::bind(KRMaterial **prevBoundMaterial, char *szPrevShaderKey, const KRCamera *pCamera, const KRViewport &viewport, const KRViewport *pShadowViewports, const KRMat4 &matModel, const KRVector3 &lightDirection, GLuint *shadowDepthTextures, int cShadowBuffers, KRContext *pContext, KRTexture *pLightMap, KRNode::RenderPass renderPass) { +bool KRMaterial::bind(KRMaterial **prevBoundMaterial, char *szPrevShaderKey, const KRCamera *pCamera, std::stack &lights, const KRViewport &viewport, const KRMat4 &matModel, KRTexture *pLightMap, KRNode::RenderPass renderPass) { bool bSameMaterial = *prevBoundMaterial == this; bool bLightMap = pLightMap && pCamera->bEnableLightMap; if(!m_pAmbientMap && m_ambientMap.size()) { - m_pAmbientMap = pContext->getTextureManager()->getTexture(m_ambientMap.c_str()); + m_pAmbientMap = getContext().getTextureManager()->getTexture(m_ambientMap.c_str()); } if(!m_pDiffuseMap && m_diffuseMap.size()) { - m_pDiffuseMap = pContext->getTextureManager()->getTexture(m_diffuseMap.c_str()); + m_pDiffuseMap = getContext().getTextureManager()->getTexture(m_diffuseMap.c_str()); } if(!m_pNormalMap && m_normalMap.size()) { - m_pNormalMap = pContext->getTextureManager()->getTexture(m_normalMap.c_str()); + m_pNormalMap = getContext().getTextureManager()->getTexture(m_normalMap.c_str()); } if(!m_pSpecularMap && m_specularMap.size()) { - m_pSpecularMap = pContext->getTextureManager()->getTexture(m_specularMap.c_str()); + m_pSpecularMap = getContext().getTextureManager()->getTexture(m_specularMap.c_str()); } if(!m_pReflectionMap && m_reflectionMap.size()) { - m_pReflectionMap = pContext->getTextureManager()->getTexture(m_reflectionMap.c_str()); + m_pReflectionMap = getContext().getTextureManager()->getTexture(m_reflectionMap.c_str()); } if(!m_pReflectionCube && m_reflectionCube.size()) { - m_pReflectionCube = pContext->getTextureManager()->getTextureCube(m_reflectionCube.c_str()); + m_pReflectionCube = getContext().getTextureManager()->getTextureCube(m_reflectionCube.c_str()); } if(!bSameMaterial) { @@ -238,11 +238,11 @@ bool KRMaterial::bind(KRMaterial **prevBoundMaterial, char *szPrevShaderKey, con bool bAlphaBlend = (m_alpha_mode == KRMATERIAL_ALPHA_MODE_BLENDONESIDE) || (m_alpha_mode == KRMATERIAL_ALPHA_MODE_BLENDTWOSIDE); - KRShader *pShader = pContext->getShaderManager()->getShader("ObjectShader", pCamera, bDiffuseMap, bNormalMap, bSpecMap, bReflectionMap, bReflectionCubeMap, cShadowBuffers, bLightMap, m_diffuseMapScale != default_scale && bDiffuseMap, m_specularMapScale != default_scale && bSpecMap, m_reflectionMapScale != default_scale && bReflectionMap, m_normalMapScale != default_scale && bNormalMap, m_diffuseMapOffset != default_offset && bDiffuseMap, m_specularMapOffset != default_offset && bSpecMap, m_reflectionMapOffset != default_offset && bReflectionMap, m_normalMapOffset != default_offset && bNormalMap, bAlphaTest, bAlphaBlend, renderPass); + KRShader *pShader = getContext().getShaderManager()->getShader("ObjectShader", pCamera, lights, bDiffuseMap, bNormalMap, bSpecMap, bReflectionMap, bReflectionCubeMap, bLightMap, m_diffuseMapScale != default_scale && bDiffuseMap, m_specularMapScale != default_scale && bSpecMap, m_reflectionMapScale != default_scale && bReflectionMap, m_normalMapScale != default_scale && bNormalMap, m_diffuseMapOffset != default_offset && bDiffuseMap, m_specularMapOffset != default_offset && bSpecMap, m_reflectionMapOffset != default_offset && bReflectionMap, m_normalMapOffset != default_offset && bNormalMap, bAlphaTest, bAlphaBlend, renderPass); bool bSameShader = strcmp(pShader->getKey(), szPrevShaderKey) == 0; if(!bSameShader) { - if(!pShader->bind(viewport, pShadowViewports, matModel, lightDirection, shadowDepthTextures, cShadowBuffers, renderPass)) { + if(!pShader->bind(viewport, matModel, lights, renderPass)) { return false; } diff --git a/KREngine/KREngine/Classes/KRMaterial.h b/KREngine/KREngine/Classes/KRMaterial.h index 21cef67..b3b8a99 100644 --- a/KREngine/KREngine/Classes/KRMaterial.h +++ b/KREngine/KREngine/Classes/KRMaterial.h @@ -89,7 +89,7 @@ public: char *getName(); #if TARGET_OS_IPHONE - bool bind(KRMaterial **prevBoundMaterial, char *szPrevShaderKey, const KRCamera *pCamera, const KRViewport &viewport, const KRViewport *pShadowViewports, const KRMat4 &matModel, const KRVector3 &lightDirection, GLuint *shadowDepthTextures, int cShadowBuffers, KRContext *pContext, KRTexture *pLightMap, KRNode::RenderPass renderPass); + bool bind(KRMaterial **prevBoundMaterial, char *szPrevShaderKey, const KRCamera *pCamera, std::stack &lights, const KRViewport &viewport, const KRMat4 &matModel, KRTexture *pLightMap, KRNode::RenderPass renderPass); #endif diff --git a/KREngine/KREngine/Classes/KRModel.cpp b/KREngine/KREngine/Classes/KRModel.cpp index dfb40bd..2e0b2b5 100644 --- a/KREngine/KREngine/Classes/KRModel.cpp +++ b/KREngine/KREngine/Classes/KRModel.cpp @@ -111,17 +111,17 @@ void KRModel::loadPack(KRDataBlock *data) { #if TARGET_OS_IPHONE -void KRModel::render(KRCamera *pCamera, KRContext *pContext, const KRViewport &viewport, const KRViewport *pShadowViewports, const KRMat4 &matModel, const KRVector3 &lightDirection, GLuint *shadowDepthTextures, int cShadowBuffers, KRTexture *pLightMap, KRNode::RenderPass renderPass) { +void KRModel::render(KRCamera *pCamera, std::stack &lights, const KRViewport &viewport, const KRMat4 &matModel, KRTexture *pLightMap, KRNode::RenderPass renderPass) { //fprintf(stderr, "Rendering model: %s\n", m_name.c_str()); - if(renderPass != KRNode::RENDER_PASS_ADDITIVE_PARTICLES) { + if(renderPass != KRNode::RENDER_PASS_ADDITIVE_PARTICLES && renderPass != KRNode::RENDER_PASS_VOLUMETRIC_EFFECTS_ADDITIVE) { if(m_materials.size() == 0) { vector submeshes = getSubmeshes(); for(std::vector::iterator itr = submeshes.begin(); itr != submeshes.end(); itr++) { const char *szMaterialName = (*itr)->szMaterialName; - KRMaterial *pMaterial = pContext->getMaterialManager()->getMaterial(szMaterialName); + KRMaterial *pMaterial = getContext().getMaterialManager()->getMaterial(szMaterialName); m_materials.push_back(pMaterial); if(pMaterial) { m_uniqueMaterials.insert(pMaterial); @@ -164,7 +164,7 @@ void KRModel::render(KRCamera *pCamera, KRContext *pContext, const KRViewport &v if(pMaterial != NULL && pMaterial == (*mat_itr)) { if((!pMaterial->isTransparent() && renderPass != KRNode::RENDER_PASS_FORWARD_TRANSPARENT) || (pMaterial->isTransparent() && renderPass == KRNode::RENDER_PASS_FORWARD_TRANSPARENT)) { - if(pMaterial->bind(&pPrevBoundMaterial, szPrevShaderKey, pCamera, viewport, pShadowViewports, matModel, lightDirection, shadowDepthTextures, cShadowBuffers, pContext, pLightMap, renderPass)) { + if(pMaterial->bind(&pPrevBoundMaterial, szPrevShaderKey, pCamera, lights, viewport, matModel, pLightMap, renderPass)) { switch(pMaterial->getAlphaMode()) { case KRMaterial::KRMATERIAL_ALPHA_MODE_OPAQUE: // Non-transparent materials diff --git a/KREngine/KREngine/Classes/KRModel.h b/KREngine/KREngine/Classes/KRModel.h index 843281c..82acd84 100644 --- a/KREngine/KREngine/Classes/KRModel.h +++ b/KREngine/KREngine/Classes/KRModel.h @@ -69,7 +69,7 @@ public: #if TARGET_OS_IPHONE - void render(KRCamera *pCamera, KRContext *pContext, const KRViewport &viewport, const KRViewport *pShadowViewports, const KRMat4 &matModel, const KRVector3 &lightDirection, GLuint *shadowDepthTextures, int cShadowBuffers, KRTexture *pLightMap, KRNode::RenderPass renderPass); + void render(KRCamera *pCamera, std::stack &lights, const KRViewport &viewport, const KRMat4 &matModel, KRTexture *pLightMap, KRNode::RenderPass renderPass); #endif diff --git a/KREngine/KREngine/Classes/KRNode.cpp b/KREngine/KREngine/Classes/KRNode.cpp index 7fd4806..4277e11 100644 --- a/KREngine/KREngine/Classes/KRNode.cpp +++ b/KREngine/KREngine/Classes/KRNode.cpp @@ -168,7 +168,8 @@ KRNode *KRNode::LoadXML(KRScene &scene, tinyxml2::XMLElement *e) { #if TARGET_OS_IPHONE -void KRNode::render(KRCamera *pCamera, KRContext *pContext, const KRViewport &viewport, const KRViewport *pShadowViewports, KRVector3 &lightDirection, GLuint *shadowDepthTextures, int cShadowBuffers, RenderPass renderPass) { +void KRNode::render(KRCamera *pCamera, std::stack &lights, const KRViewport &viewport, RenderPass renderPass) +{ } #endif diff --git a/KREngine/KREngine/Classes/KRNode.h b/KREngine/KREngine/Classes/KRNode.h index c33f549..d37c2a1 100644 --- a/KREngine/KREngine/Classes/KRNode.h +++ b/KREngine/KREngine/Classes/KRNode.h @@ -13,6 +13,7 @@ #import "KRVector3.h" #import "KRViewport.h" #import "tinyxml2.h" +#import class KRCamera; class KRShaderManager; @@ -34,6 +35,8 @@ public: RENDER_PASS_DEFERRED_OPAQUE, RENDER_PASS_FORWARD_TRANSPARENT, RENDER_PASS_ADDITIVE_PARTICLES, + RENDER_PASS_VOLUMETRIC_EFFECTS_ADDITIVE, + RENDER_PASS_GENERATE_SHADOWMAPS, RENDER_PASS_SHADOWMAP }; @@ -68,7 +71,7 @@ public: KRScene &getScene(); #if TARGET_OS_IPHONE - virtual void render(KRCamera *pCamera, KRContext *pContext, const KRViewport &viewport, const KRViewport *pShadowViewports, KRVector3 &lightDirection, GLuint *shadowDepthTextures, int cShadowBuffers, RenderPass renderPass); + virtual void render(KRCamera *pCamera, std::stack &lights, const KRViewport &viewport, RenderPass renderPass); #endif diff --git a/KREngine/KREngine/Classes/KRParticleSystem.h b/KREngine/KREngine/Classes/KRParticleSystem.h index 9da436b..b096a59 100644 --- a/KREngine/KREngine/Classes/KRParticleSystem.h +++ b/KREngine/KREngine/Classes/KRParticleSystem.h @@ -23,7 +23,7 @@ public: #if TARGET_OS_IPHONE - virtual void render(KRCamera *pCamera, KRContext *pContext, const KRViewport &viewport, const KRViewport *pShadowViewports, KRVector3 &lightDirection, GLuint *shadowDepthTextures, int cShadowBuffers, KRNode::RenderPass renderPass) = 0; + virtual void render(KRCamera *pCamera, std::stack &lights, const KRViewport &viewport, KRNode::RenderPass renderPass) = 0; #endif protected: diff --git a/KREngine/KREngine/Classes/KRParticleSystemBrownian.cpp b/KREngine/KREngine/Classes/KRParticleSystemBrownian.cpp index fced613..51f1cae 100644 --- a/KREngine/KREngine/Classes/KRParticleSystemBrownian.cpp +++ b/KREngine/KREngine/Classes/KRParticleSystemBrownian.cpp @@ -52,10 +52,10 @@ void KRParticleSystemBrownian::physicsUpdate(float deltaTime) #if TARGET_OS_IPHONE -void KRParticleSystemBrownian::render(KRCamera *pCamera, KRContext *pContext, const KRViewport &viewport, const KRViewport *pShadowViewports, KRVector3 &lightDirection, GLuint *shadowDepthTextures, int cShadowBuffers, KRNode::RenderPass renderPass) { +void KRParticleSystemBrownian::render(KRCamera *pCamera, std::stack &lights, const KRViewport &viewport, KRNode::RenderPass renderPass) { - KRNode::render(pCamera, pContext, viewport, pShadowViewports, lightDirection, shadowDepthTextures, cShadowBuffers, renderPass); + KRNode::render(pCamera, lights, viewport, renderPass); if(renderPass == KRNode::RENDER_PASS_ADDITIVE_PARTICLES) { float lod_coverage = getBounds().coverage(viewport.getViewProjectionMatrix(), viewport.getSize()); // This also checks the view frustrum culling @@ -69,11 +69,11 @@ void KRParticleSystemBrownian::render(KRCamera *pCamera, KRContext *pContext, co KRTexture *pParticleTexture = m_pContext->getTextureManager()->getTexture("flare"); m_pContext->getTextureManager()->selectTexture(0, pParticleTexture, 2048); - KRShader *pParticleShader = m_pContext->getShaderManager()->getShader("particle", pCamera, false, false, false, 0, false, false, false, false, false, false, false, false, false, false, false, false, false, KRNode::RENDER_PASS_ADDITIVE_PARTICLES); + KRShader *pParticleShader = m_pContext->getShaderManager()->getShader("particle", pCamera, lights, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, renderPass); int particle_count = 10000; - if(pParticleShader->bind(viewport, pShadowViewports, getModelMatrix(), lightDirection, shadowDepthTextures, cShadowBuffers, KRNode::RENDER_PASS_ADDITIVE_PARTICLES)) { + if(pParticleShader->bind(viewport, getModelMatrix(), lights, renderPass)) { GLDEBUG(glUniform1f( pParticleShader->m_uniforms[KRShader::KRENGINE_UNIFORM_FLARE_SIZE], 1.0f diff --git a/KREngine/KREngine/Classes/KRParticleSystemBrownian.h b/KREngine/KREngine/Classes/KRParticleSystemBrownian.h index 202fe46..dce897e 100644 --- a/KREngine/KREngine/Classes/KRParticleSystemBrownian.h +++ b/KREngine/KREngine/Classes/KRParticleSystemBrownian.h @@ -26,7 +26,7 @@ public: #if TARGET_OS_IPHONE - virtual void render(KRCamera *pCamera, KRContext *pContext, const KRViewport &viewport, const KRViewport *pShadowViewports, KRVector3 &lightDirection, GLuint *shadowDepthTextures, int cShadowBuffers, KRNode::RenderPass renderPass); + virtual void render(KRCamera *pCamera, std::stack &lights, const KRViewport &viewport, KRNode::RenderPass renderPass); #endif diff --git a/KREngine/KREngine/Classes/KRPointLight.cpp b/KREngine/KREngine/Classes/KRPointLight.cpp index 00b8ba9..ee3d4e5 100644 --- a/KREngine/KREngine/Classes/KRPointLight.cpp +++ b/KREngine/KREngine/Classes/KRPointLight.cpp @@ -43,9 +43,10 @@ KRAABB KRPointLight::getBounds() { #if TARGET_OS_IPHONE -void KRPointLight::render(KRCamera *pCamera, KRContext *pContext, const KRViewport &viewport, const KRViewport *pShadowViewports, KRVector3 &lightDirection, GLuint *shadowDepthTextures, int cShadowBuffers, KRNode::RenderPass renderPass) { +void KRPointLight::render(KRCamera *pCamera, std::stack &lights, const KRViewport &viewport, KRNode::RenderPass renderPass) +{ - KRLight::render(pCamera, pContext, viewport, pShadowViewports, lightDirection, shadowDepthTextures, cShadowBuffers, renderPass); + KRLight::render(pCamera, lights, viewport, renderPass); bool bVisualize = renderPass == KRNode::RENDER_PASS_FORWARD_TRANSPARENT && pCamera->bShowDeferred; @@ -68,8 +69,8 @@ void KRPointLight::render(KRCamera *pCamera, KRContext *pContext, const KRViewpo bool bInsideLight = view_light_position.sqrMagnitude() <= (influence_radius + pCamera->getPerspectiveNearZ()) * (influence_radius + pCamera->getPerspectiveNearZ()); - KRShader *pShader = pContext->getShaderManager()->getShader(bVisualize ? "visualize_overlay" : (bInsideLight ? "light_point_inside" : "light_point"), pCamera, false, false, false, 0, false, false, false, false, false, false, false, false, false, false, false, false, false, renderPass); - if(pShader->bind(viewport, pShadowViewports, sphereModelMatrix, lightDirection, shadowDepthTextures, 0, renderPass)) { + KRShader *pShader = getContext().getShaderManager()->getShader(bVisualize ? "visualize_overlay" : (bInsideLight ? "light_point_inside" : "light_point"), pCamera, lights, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, renderPass); + if(pShader->bind(viewport, sphereModelMatrix, lights, renderPass)) { diff --git a/KREngine/KREngine/Classes/KRPointLight.h b/KREngine/KREngine/Classes/KRPointLight.h index 2b75764..ab43251 100644 --- a/KREngine/KREngine/Classes/KRPointLight.h +++ b/KREngine/KREngine/Classes/KRPointLight.h @@ -24,7 +24,7 @@ public: #if TARGET_OS_IPHONE - virtual void render(KRCamera *pCamera, KRContext *pContext, const KRViewport &viewport, const KRViewport *pShadowViewports, KRVector3 &lightDirection, GLuint *shadowDepthTextures, int cShadowBuffers, KRNode::RenderPass renderPass); + virtual void render(KRCamera *pCamera, std::stack &lights, const KRViewport &viewport, KRNode::RenderPass renderPass); #endif private: diff --git a/KREngine/KREngine/Classes/KRScene.cpp b/KREngine/KREngine/Classes/KRScene.cpp index 1cdb1b5..d0e3b0d 100644 --- a/KREngine/KREngine/Classes/KRScene.cpp +++ b/KREngine/KREngine/Classes/KRScene.cpp @@ -42,12 +42,9 @@ #import "KRStockGeometry.h" KRScene::KRScene(KRContext &context, std::string name) : KRResource(context, name) { - m_pContext = &context; m_pFirstDirectionalLight = NULL; m_pRootNode = new KRNode(*this, "scene_root"); - sun_yaw = 4.333; // TODO - Remove temporary testing code - sun_pitch = 0.55; m_skyBoxName = ""; } KRScene::~KRScene() { @@ -57,52 +54,29 @@ KRScene::~KRScene() { #if TARGET_OS_IPHONE -void KRScene::render(KRCamera *pCamera, const std::set &visibleBounds, KRContext *pContext, const KRViewport &viewport, const KRViewport *pShadowViewports, KRVector3 &lightDirection, GLuint *shadowDepthTextures, int cShadowBuffers, KRNode::RenderPass renderPass, std::set &newVisibleBounds) { +void KRScene::render(KRCamera *pCamera, const std::set &visibleBounds, const KRViewport &viewport, KRNode::RenderPass renderPass, std::set &newVisibleBounds) { + + std::stack lights; updateOctree(); pCamera->setSkyBox(m_skyBoxName); // This is temporary until the camera is moved into the scene graph - if(renderPass != KRNode::RENDER_PASS_SHADOWMAP) { - if(cShadowBuffers > 0) { - m_pContext->getTextureManager()->selectTexture(3, NULL, 0); - GLDEBUG(glActiveTexture(GL_TEXTURE3)); - GLDEBUG(glBindTexture(GL_TEXTURE_2D, shadowDepthTextures[0])); - GLDEBUG(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR)); - GLDEBUG(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR)); - GLDEBUG(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE)); - GLDEBUG(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE)); - } - - if(cShadowBuffers > 1) { - m_pContext->getTextureManager()->selectTexture(4, NULL, 0); - GLDEBUG(glActiveTexture(GL_TEXTURE4)); - GLDEBUG(glBindTexture(GL_TEXTURE_2D, shadowDepthTextures[1])); - GLDEBUG(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR)); - GLDEBUG(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR)); - GLDEBUG(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE)); - GLDEBUG(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE)); - } - - if(cShadowBuffers > 2) { - m_pContext->getTextureManager()->selectTexture(5, NULL, 0); - GLDEBUG(glActiveTexture(GL_TEXTURE5)); - GLDEBUG(glBindTexture(GL_TEXTURE_2D, shadowDepthTextures[2])); - GLDEBUG(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR)); - GLDEBUG(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR)); - GLDEBUG(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE)); - GLDEBUG(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE)); + std::set outerNodes = std::set(m_nodeTree.getOuterSceneNodes()); // HACK - Copying the std::set as it is potentially modified as KRNode's update their bounds during the iteration. This is very expensive and will be eliminated in the future. + + // Get lights from outer nodes (directional lights, which have no bounds) + for(std::set::iterator itr=outerNodes.begin(); itr != outerNodes.end(); itr++) { + KRNode *node = (*itr); + KRLight *light = dynamic_cast(node); + if(light) { + lights.push(light); } } - - KRVector3 forward_render_light_direction = lightDirection; - KRDirectionalLight *directional_light = getFirstDirectionalLight(); - if(directional_light) { - forward_render_light_direction = directional_light->getWorldLightDirection(); - KRVector3 sun_color = directional_light->getColor() * (directional_light->getIntensity() / 100.0f); - pCamera->dSunR = sun_color.x; - pCamera->dSunG = sun_color.y; - pCamera->dSunB = sun_color.z; + + // Render outer nodes + for(std::set::iterator itr=outerNodes.begin(); itr != outerNodes.end(); itr++) { + KRNode *node = (*itr); + node->render(pCamera, lights, viewport, renderPass); } std::vector remainingOctrees; @@ -118,10 +92,10 @@ void KRScene::render(KRCamera *pCamera, const std::set &visibleBounds, K newRemainingOctrees.clear(); newRemainingOctreesTestResults.clear(); for(std::vector::iterator octree_itr = remainingOctrees.begin(); octree_itr != remainingOctrees.end(); octree_itr++) { - render(*octree_itr, visibleBounds, pCamera, pContext, viewport, pShadowViewports, forward_render_light_direction, shadowDepthTextures, cShadowBuffers, renderPass, newRemainingOctrees, newRemainingOctreesTestResults, remainingOctreesTestResultsOnly, newVisibleBounds, false, false); + render(*octree_itr, visibleBounds, pCamera, lights, viewport, 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, viewport, pShadowViewports, forward_render_light_direction, shadowDepthTextures, cShadowBuffers, renderPass, newRemainingOctrees, newRemainingOctreesTestResults, remainingOctreesTestResultsOnly, newVisibleBounds, true, false); + render(*octree_itr, visibleBounds, pCamera, lights, viewport, renderPass, newRemainingOctrees, newRemainingOctreesTestResults, remainingOctreesTestResultsOnly, newVisibleBounds, true, false); } remainingOctrees = newRemainingOctrees; remainingOctreesTestResults = newRemainingOctreesTestResults; @@ -130,16 +104,11 @@ void KRScene::render(KRCamera *pCamera, const std::set &visibleBounds, K newRemainingOctrees.clear(); newRemainingOctreesTestResults.clear(); for(std::vector::iterator octree_itr = remainingOctreesTestResultsOnly.begin(); octree_itr != remainingOctreesTestResultsOnly.end(); octree_itr++) { - render(*octree_itr, visibleBounds, pCamera, pContext, viewport, pShadowViewports, forward_render_light_direction, shadowDepthTextures, cShadowBuffers, renderPass, newRemainingOctrees, newRemainingOctreesTestResults, remainingOctreesTestResultsOnly, newVisibleBounds, true, true); - } - - std::set outerNodes = std::set(m_nodeTree.getOuterSceneNodes()); // HACK - Copying the std::set as it is potentially modified as KRNode's update their bounds during the iteration. This is very expensive and will be eliminated in the future. - for(std::set::iterator itr=outerNodes.begin(); itr != outerNodes.end(); itr++) { - (*itr)->render(pCamera, pContext, viewport, pShadowViewports, lightDirection, shadowDepthTextures, cShadowBuffers, renderPass); + render(*octree_itr, visibleBounds, pCamera, lights, viewport, renderPass, newRemainingOctrees, newRemainingOctreesTestResults, remainingOctreesTestResultsOnly, newVisibleBounds, true, true); } } -void KRScene::render(KROctreeNode *pOctreeNode, const std::set &visibleBounds, KRCamera *pCamera, KRContext *pContext, const KRViewport &viewport, const KRViewport *pShadowViewports, KRVector3 &lightDirection, GLuint *shadowDepthTextures, int cShadowBuffers, KRNode::RenderPass renderPass, std::vector &remainingOctrees, std::vector &remainingOctreesTestResults, std::vector &remainingOctreesTestResultsOnly, std::set &newVisibleBounds, bool bOcclusionResultsPass, bool bOcclusionTestResultsOnly) +void KRScene::render(KROctreeNode *pOctreeNode, const std::set &visibleBounds, KRCamera *pCamera, std::stack lights, const KRViewport &viewport, KRNode::RenderPass renderPass, std::vector &remainingOctrees, std::vector &remainingOctreesTestResults, std::vector &remainingOctreesTestResultsOnly, std::set &newVisibleBounds, bool bOcclusionResultsPass, bool bOcclusionTestResultsOnly) { if(pOctreeNode) { @@ -215,16 +184,16 @@ void KRScene::render(KROctreeNode *pOctreeNode, const std::set &visibleB 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, false, false, false, false, KRNode::RENDER_PASS_FORWARD_TRANSPARENT); + KRShader *pVisShader = getContext().getShaderManager()->getShader("occlusion_test", pCamera, lights, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, KRNode::RENDER_PASS_FORWARD_TRANSPARENT); - m_pContext->getModelManager()->bindVBO((void *)KRENGINE_VBO_3D_CUBE, KRENGINE_VBO_3D_CUBE_SIZE, true, false, false, false, false); + getContext().getModelManager()->bindVBO((void *)KRENGINE_VBO_3D_CUBE, KRENGINE_VBO_3D_CUBE_SIZE, true, false, false, false, false); KRMat4 matModel = KRMat4(); matModel.scale(octreeBounds.size() / 2.0f); matModel.translate(octreeBounds.center()); KRMat4 mvpmatrix = matModel * viewport.getViewProjectionMatrix(); // Enable additive blending - if(renderPass != KRNode::RENDER_PASS_FORWARD_TRANSPARENT && renderPass != KRNode::RENDER_PASS_ADDITIVE_PARTICLES) { + if(renderPass != KRNode::RENDER_PASS_FORWARD_TRANSPARENT && renderPass != KRNode::RENDER_PASS_ADDITIVE_PARTICLES && renderPass != KRNode::RENDER_PASS_VOLUMETRIC_EFFECTS_ADDITIVE) { GLDEBUG(glEnable(GL_BLEND)); } GLDEBUG(glBlendFunc(GL_ONE, GL_ONE)); @@ -239,7 +208,7 @@ void KRScene::render(KROctreeNode *pOctreeNode, const std::set &visibleB GLDEBUG(glDepthMask(GL_FALSE)); } - if(pVisShader->bind(viewport, pShadowViewports, matModel, lightDirection, shadowDepthTextures, 0, KRNode::RENDER_PASS_FORWARD_TRANSPARENT)) { + if(pVisShader->bind(viewport, matModel, std::stack(), KRNode::RENDER_PASS_FORWARD_TRANSPARENT)) { GLDEBUG(glDrawArrays(GL_TRIANGLE_STRIP, 0, 14)); } @@ -254,12 +223,12 @@ void KRScene::render(KROctreeNode *pOctreeNode, const std::set &visibleB pOctreeNode->endOcclusionQuery(); - if(renderPass != KRNode::RENDER_PASS_FORWARD_TRANSPARENT && renderPass != KRNode::RENDER_PASS_ADDITIVE_PARTICLES) { + if(renderPass != KRNode::RENDER_PASS_FORWARD_TRANSPARENT && renderPass != KRNode::RENDER_PASS_ADDITIVE_PARTICLES && renderPass != KRNode::RENDER_PASS_VOLUMETRIC_EFFECTS_ADDITIVE) { GLDEBUG(glDisable(GL_BLEND)); } else if(renderPass == KRNode::RENDER_PASS_FORWARD_TRANSPARENT) { GLDEBUG(glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)); } else { - GLDEBUG(glBlendFunc(GL_ONE, GL_ONE)); + GLDEBUG(glBlendFunc(GL_ONE, GL_ONE)); // RENDER_PASS_FORWARD_TRANSPARENT and RENDER_PASS_VOLUMETRIC_EFFECTS_ADDITIVE } @@ -274,15 +243,33 @@ void KRScene::render(KROctreeNode *pOctreeNode, const std::set &visibleB if(bVisible) { + // Add lights that influence this octree level and its children to the stack + int light_count = 0; 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, viewport, pShadowViewports, lightDirection, shadowDepthTextures, cShadowBuffers, renderPass); + KRNode *node = (*itr); + KRLight *light = dynamic_cast(node); + if(light) { + lights.push(light); + light_count++; + } } - const int *childOctreeOrder = renderPass == KRNode::RENDER_PASS_FORWARD_TRANSPARENT || renderPass == KRNode::RENDER_PASS_ADDITIVE_PARTICLES ? viewport.getBackToFrontOrder() : viewport.getFrontToBackOrder(); + // Render objects that are at this octree level + for(std::set::iterator itr=pOctreeNode->getSceneNodes().begin(); itr != pOctreeNode->getSceneNodes().end(); itr++) { + //assert(pOctreeNode->getBounds().contains((*itr)->getBounds())); // Sanity check + (*itr)->render(pCamera, lights, viewport, renderPass); + } + + // Render child octrees + const int *childOctreeOrder = renderPass == KRNode::RENDER_PASS_FORWARD_TRANSPARENT || renderPass == KRNode::RENDER_PASS_ADDITIVE_PARTICLES || renderPass == KRNode::RENDER_PASS_VOLUMETRIC_EFFECTS_ADDITIVE ? viewport.getBackToFrontOrder() : viewport.getFrontToBackOrder(); for(int i=0; i<8; i++) { - render(pOctreeNode->getChildren()[childOctreeOrder[i]], visibleBounds, pCamera, pContext, viewport, pShadowViewports, lightDirection, shadowDepthTextures, cShadowBuffers, renderPass, remainingOctrees, remainingOctreesTestResults, remainingOctreesTestResultsOnly, newVisibleBounds, false, false); + render(pOctreeNode->getChildren()[childOctreeOrder[i]], visibleBounds, pCamera, lights, viewport, renderPass, remainingOctrees, remainingOctreesTestResults, remainingOctreesTestResultsOnly, newVisibleBounds, false, false); + } + + // Remove lights added at this octree level from the stack + while(light_count--) { + lights.pop(); } } } diff --git a/KREngine/KREngine/Classes/KRScene.h b/KREngine/KREngine/Classes/KRScene.h index ba58522..045c3b7 100644 --- a/KREngine/KREngine/Classes/KRScene.h +++ b/KREngine/KREngine/Classes/KRScene.h @@ -62,14 +62,12 @@ public: #if TARGET_OS_IPHONE - void render(KRCamera *pCamera, const std::set &visibleBounds, KRContext *pContext, const KRViewport &viewport, const KRViewport *pShadowViewports, KRVector3 &lightDirection, GLuint *shadowDepthTextures, int cShadowBuffers, KRNode::RenderPass renderPass, std::set &newVisibleBounds); + void render(KRCamera *pCamera, const std::set &visibleBounds, const KRViewport &viewport, KRNode::RenderPass renderPass, std::set &newVisibleBounds); - void render(KROctreeNode *pOctreeNode, const std::set &visibleBounds, KRCamera *pCamera, KRContext *pContext, const KRViewport &viewport, const KRViewport *pShadowViewports, KRVector3 &lightDirection, GLuint *shadowDepthTextures, int cShadowBuffers, KRNode::RenderPass renderPass, std::vector &remainingOctrees, std::vector &remainingOctreesTestResults, std::vector &remainingOctreesTestResultsOnly, std::set &newVisibleBounds, bool bOcclusionResultsPass, bool bOcclusionTestResultsOnly); + void render(KROctreeNode *pOctreeNode, const std::set &visibleBounds, KRCamera *pCamera, std::stack lights, const KRViewport &viewport, KRNode::RenderPass renderPass, std::vector &remainingOctrees, std::vector &remainingOctreesTestResults, std::vector &remainingOctreesTestResultsOnly, std::set &newVisibleBounds, bool bOcclusionResultsPass, bool bOcclusionTestResultsOnly); #endif - float sun_pitch, sun_yaw; - void notify_sceneGraphCreate(KRNode *pNode); void notify_sceneGraphDelete(KRNode *pNode); @@ -78,7 +76,6 @@ public: void physicsUpdate(float deltaTime); private: - KRContext *m_pContext; KRDirectionalLight *findFirstDirectionalLight(KRNode &node); KRNode *m_pRootNode; diff --git a/KREngine/KREngine/Classes/KRShader.cpp b/KREngine/KREngine/Classes/KRShader.cpp index fc617ac..bdb566d 100644 --- a/KREngine/KREngine/Classes/KRShader.cpp +++ b/KREngine/KREngine/Classes/KRShader.cpp @@ -32,7 +32,8 @@ #include "KRShader.h" #import "assert.h" -KRShader::KRShader(char *szKey, std::string options, std::string vertShaderSource, const std::string fragShaderSource) { +KRShader::KRShader(KRContext &context, char *szKey, std::string options, std::string vertShaderSource, const std::string fragShaderSource) : KRContextObject(context) +{ strcpy(m_szKey, szKey); m_iProgram = 0; GLuint vertexShader = 0, fragShader = 0; @@ -205,11 +206,48 @@ KRShader::~KRShader() { #if TARGET_OS_IPHONE -bool KRShader::bind(const KRViewport &viewport, const KRViewport *pShadowViewports, const KRMat4 &matModel, const KRVector3 &lightDirection, const GLuint *shadowDepthTextures, const int &cShadowBuffers, const KRNode::RenderPass &renderPass) { +bool KRShader::bind(const KRViewport &viewport, const KRMat4 &matModel, const std::stack &lights, const KRNode::RenderPass &renderPass) { if(m_iProgram == 0) { return false; } - GLDEBUG(glUseProgram(m_iProgram)); + + // FINDME - HACK - Temporary placeholder code + KRViewport *pShadowViewports = NULL; + KRVector3 lightDirection = KRVector3::Normalize(KRVector3(0.90, 0.70, 0.25)); + GLuint *shadowDepthTextures = NULL; + int cShadowBuffers = 0; + + GLDEBUG(glUseProgram(m_iProgram)); + + if(m_uniforms[KRENGINE_UNIFORM_SHADOWTEXTURE1] != -1 && cShadowBuffers > 0) { + m_pContext->getTextureManager()->selectTexture(3, NULL, 0); + GLDEBUG(glActiveTexture(GL_TEXTURE3)); + GLDEBUG(glBindTexture(GL_TEXTURE_2D, shadowDepthTextures[0])); + GLDEBUG(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR)); + GLDEBUG(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR)); + GLDEBUG(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE)); + GLDEBUG(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE)); + } + + if(m_uniforms[KRENGINE_UNIFORM_SHADOWTEXTURE2] != -1 && cShadowBuffers > 1) { + m_pContext->getTextureManager()->selectTexture(4, NULL, 0); + GLDEBUG(glActiveTexture(GL_TEXTURE4)); + GLDEBUG(glBindTexture(GL_TEXTURE_2D, shadowDepthTextures[1])); + GLDEBUG(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR)); + GLDEBUG(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR)); + GLDEBUG(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE)); + GLDEBUG(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE)); + } + + if(m_uniforms[KRENGINE_UNIFORM_SHADOWTEXTURE3] != -1 && cShadowBuffers > 2) { + m_pContext->getTextureManager()->selectTexture(5, NULL, 0); + GLDEBUG(glActiveTexture(GL_TEXTURE5)); + GLDEBUG(glBindTexture(GL_TEXTURE_2D, shadowDepthTextures[2])); + GLDEBUG(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR)); + GLDEBUG(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR)); + GLDEBUG(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE)); + GLDEBUG(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE)); + } if(m_uniforms[KRENGINE_UNIFORM_LIGHT_DIRECTION_MODEL_SPACE] != -1 || m_uniforms[KRENGINE_UNIFORM_CAMERAPOS_MODEL_SPACE] != -1) { KRMat4 inverseModelMatrix = matModel; diff --git a/KREngine/KREngine/Classes/KRShader.h b/KREngine/KREngine/Classes/KRShader.h index 1757592..bf2e646 100644 --- a/KREngine/KREngine/Classes/KRShader.h +++ b/KREngine/KREngine/Classes/KRShader.h @@ -32,6 +32,7 @@ #import #import #import +#import #import "KREngine-common.h" @@ -47,16 +48,16 @@ using std::vector; #import "KRNode.h" #import "KRViewport.h" -class KRShader { +class KRShader : public KRContextObject { public: - KRShader(char *szKey, std::string options, std::string vertShaderSource, const std::string fragShaderSource); - ~KRShader(); + KRShader(KRContext &context, char *szKey, std::string options, std::string vertShaderSource, const std::string fragShaderSource); + virtual ~KRShader(); GLuint getProgram(); char *getKey(); #if TARGET_OS_IPHONE - bool bind(const KRViewport &viewport, const KRViewport *pShadowViewports, const KRMat4 &matModel, const KRVector3 &lightDirection, const GLuint *shadowDepthTextures, const int &cShadowBuffers, const KRNode::RenderPass &renderPass); + bool bind(const KRViewport &viewport, const KRMat4 &matModel, const std::stack &lights, const KRNode::RenderPass &renderPass); #endif diff --git a/KREngine/KREngine/Classes/KRShaderManager.cpp b/KREngine/KREngine/Classes/KRShaderManager.cpp index 552219d..498bf75 100644 --- a/KREngine/KREngine/Classes/KRShaderManager.cpp +++ b/KREngine/KREngine/Classes/KRShaderManager.cpp @@ -45,8 +45,11 @@ KRShaderManager::~KRShaderManager() { } -KRShader *KRShaderManager::getShader(const std::string &shader_name, const KRCamera *pCamera, bool bDiffuseMap, bool bNormalMap, bool bSpecMap, bool bReflectionMap, bool bReflectionCubeMap, int iShadowQuality, bool bLightMap, bool bDiffuseMapScale,bool bSpecMapScale, bool bNormalMapScale, bool bReflectionMapScale, bool bDiffuseMapOffset, bool bSpecMapOffset, bool bNormalMapOffset, bool bReflectionMapOffset, bool bAlphaTest, bool bAlphaBlend, KRNode::RenderPass renderPass) { +KRShader *KRShaderManager::getShader(const std::string &shader_name, const KRCamera *pCamera, const std::stack &lights, bool bDiffuseMap, bool bNormalMap, bool bSpecMap, bool bReflectionMap, bool bReflectionCubeMap, bool bLightMap, bool bDiffuseMapScale,bool bSpecMapScale, bool bNormalMapScale, bool bReflectionMapScale, bool bDiffuseMapOffset, bool bSpecMapOffset, bool bNormalMapOffset, bool bReflectionMapOffset, bool bAlphaTest, bool bAlphaBlend, KRNode::RenderPass renderPass) { + int iShadowQuality = 0; // FINDME - HACK - Placeholder code, need to iterate through lights and dynamically build shader + + char szKey[256]; sprintf(szKey, "%d_%d_%d_%d_%d_%d_%d_%d_%d_%d_%d_%d_%d_%d_%d_%d_%d_%d_%d_%d_%d_%d_%d_%i_%s_%i_%d_%d_%f_%f_%f_%f_%f_%f_%f", pCamera->bEnablePerPixel, bAlphaTest, bAlphaBlend, bDiffuseMap, bNormalMap, bSpecMap, bReflectionMap, bReflectionCubeMap, pCamera->bDebugPSSM, iShadowQuality, pCamera->bEnableAmbient, pCamera->bEnableDiffuse, pCamera->bEnableSpecular, bLightMap, bDiffuseMapScale, bSpecMapScale, bReflectionMapScale, bNormalMapScale, bDiffuseMapOffset, bSpecMapOffset, bReflectionMapOffset, bNormalMapOffset,pCamera->volumetric_environment_enable, renderPass, shader_name.c_str(),pCamera->dof_quality,pCamera->bEnableFlash,pCamera->bEnableVignette,pCamera->dof_depth,pCamera->dof_falloff,pCamera->flash_depth,pCamera->flash_falloff,pCamera->flash_intensity,pCamera->vignette_radius,pCamera->vignette_falloff); @@ -130,7 +133,7 @@ KRShader *KRShaderManager::getShader(const std::string &shader_name, const KRCam stream << "\n"; std::string options = stream.str(); - pShader = new KRShader(szKey, options, m_vertShaderSource[shader_name], m_fragShaderSource[shader_name]); + pShader = new KRShader(getContext(), szKey, options, m_vertShaderSource[shader_name], m_fragShaderSource[shader_name]); m_shaders[szKey] = pShader; } diff --git a/KREngine/KREngine/Classes/KRShaderManager.h b/KREngine/KREngine/Classes/KRShaderManager.h index 515d5e0..ee91087 100644 --- a/KREngine/KREngine/Classes/KRShaderManager.h +++ b/KREngine/KREngine/Classes/KRShaderManager.h @@ -59,7 +59,7 @@ public: const std::string &getVertShaderSource(const std::string &name); - KRShader *getShader(const std::string &shader_name, const KRCamera *pCamera, bool bDiffuseMap, bool bNormalMap, bool bSpecMap, bool bReflectionMap, bool bReflectionCubeMap, int iShadowQuality, bool bLightMap, bool bDiffuseMapScale,bool bSpecMapScale, bool bNormalMapScale, bool bReflectionMapScale, bool bDiffuseMapOffset, bool bSpecMapOffset, bool bNormalMapOffset, bool bReflectionMapOffset, bool bAlphaTest, bool bAlphaBlend, KRNode::RenderPass renderPass); + KRShader *getShader(const std::string &shader_name, const KRCamera *pCamera, const std::stack &lights, bool bDiffuseMap, bool bNormalMap, bool bSpecMap, bool bReflectionMap, bool bReflectionCubeMap, bool bLightMap, bool bDiffuseMapScale,bool bSpecMapScale, bool bNormalMapScale, bool bReflectionMapScale, bool bDiffuseMapOffset, bool bSpecMapOffset, bool bNormalMapOffset, bool bReflectionMapOffset, bool bAlphaTest, bool bAlphaBlend, KRNode::RenderPass renderPass); long getShaderHandlesUsed(); diff --git a/KREngine/KREngine/Classes/KRViewport.cpp b/KREngine/KREngine/Classes/KRViewport.cpp index f0e7e24..002d9a3 100644 --- a/KREngine/KREngine/Classes/KRViewport.cpp +++ b/KREngine/KREngine/Classes/KRViewport.cpp @@ -11,6 +11,7 @@ #include "KRVector2.h" #include "KRMat4.h" #include "KRViewport.h" +#include "KRLight.h" KRViewport::KRViewport() @@ -163,3 +164,4 @@ void KRViewport::setVisibleBounds(const std::set visibleBounds) m_visibleBounds = visibleBounds; } + diff --git a/KREngine/KREngine/Classes/KRViewport.h b/KREngine/KREngine/Classes/KRViewport.h index 097b635..6523931 100644 --- a/KREngine/KREngine/Classes/KRViewport.h +++ b/KREngine/KREngine/Classes/KRViewport.h @@ -13,6 +13,8 @@ #include "KRMat4.h" #include "KRAABB.h" +class KRLight; + class KRViewport { public: KRViewport(); @@ -39,6 +41,9 @@ public: const std::set &getVisibleBounds(); void setVisibleBounds(const std::set visibleBounds); + const std::set &getVisibleLights(); + void setVisibleLights(const std::set visibleLights); + private: KRVector2 m_size; KRMat4 m_matView;