diff --git a/KREngine/KREngine.xcodeproj/project.pbxproj b/KREngine/KREngine.xcodeproj/project.pbxproj index fb0b2f2..4727e45 100644 --- a/KREngine/KREngine.xcodeproj/project.pbxproj +++ b/KREngine/KREngine.xcodeproj/project.pbxproj @@ -35,18 +35,10 @@ E43B0AD715DDCA0F00A5CB9F /* KRContextObject.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E43B0AD415DDCA0C00A5CB9F /* KRContextObject.cpp */; }; E43B0AD815DDCA0F00A5CB9F /* KRContextObject.h in Headers */ = {isa = PBXBuildFile; fileRef = E43B0AD515DDCA0D00A5CB9F /* KRContextObject.h */; }; E43B0AD915DDCA0F00A5CB9F /* KRContextObject.h in Headers */ = {isa = PBXBuildFile; fileRef = E43B0AD515DDCA0D00A5CB9F /* KRContextObject.h */; settings = {ATTRIBUTES = (Public, ); }; }; - E45AC0301641D66300DC3C3B /* simple_blit.vsh in Sources */ = {isa = PBXBuildFile; fileRef = E45AC02F1641D66300DC3C3B /* simple_blit.vsh */; }; - E45AC0311641D66300DC3C3B /* simple_blit.vsh in Sources */ = {isa = PBXBuildFile; fileRef = E45AC02F1641D66300DC3C3B /* simple_blit.vsh */; }; - E45AC0341641D67300DC3C3B /* simple_blit.fsh in Sources */ = {isa = PBXBuildFile; fileRef = E45AC0331641D67300DC3C3B /* simple_blit.fsh */; }; - E45AC0351641D67300DC3C3B /* simple_blit.fsh in Sources */ = {isa = PBXBuildFile; fileRef = E45AC0331641D67300DC3C3B /* simple_blit.fsh */; }; - E45AC03F1641DE5D00DC3C3B /* debug_font.vsh in Sources */ = {isa = PBXBuildFile; fileRef = E45AC03E1641DE5D00DC3C3B /* debug_font.vsh */; }; - E45AC0401641DE5D00DC3C3B /* debug_font.vsh in Sources */ = {isa = PBXBuildFile; fileRef = E45AC03E1641DE5D00DC3C3B /* debug_font.vsh */; }; - E45AC0421641DE6D00DC3C3B /* debug_font.fsh in Sources */ = {isa = PBXBuildFile; fileRef = E45AC0411641DE6D00DC3C3B /* debug_font.fsh */; }; - E45AC0431641DE6D00DC3C3B /* debug_font.fsh in Sources */ = {isa = PBXBuildFile; fileRef = E45AC0411641DE6D00DC3C3B /* debug_font.fsh */; }; - E45AC0471643451300DC3C3B /* particle.fsh in Sources */ = {isa = PBXBuildFile; fileRef = E45AC0461643451200DC3C3B /* particle.fsh */; }; - E45AC0481643451300DC3C3B /* particle.fsh in Sources */ = {isa = PBXBuildFile; fileRef = E45AC0461643451200DC3C3B /* particle.fsh */; }; - E45AC04A1643452100DC3C3B /* particle.vsh in Sources */ = {isa = PBXBuildFile; fileRef = E45AC0491643452000DC3C3B /* particle.vsh */; }; - E45AC04B1643452100DC3C3B /* particle.vsh in Sources */ = {isa = PBXBuildFile; fileRef = E45AC0491643452000DC3C3B /* particle.vsh */; }; + E443C5FE164B120A00FC4FD8 /* KRVolumetricFog.h in Headers */ = {isa = PBXBuildFile; fileRef = E443C5FD164B120900FC4FD8 /* KRVolumetricFog.h */; }; + E443C5FF164B120A00FC4FD8 /* KRVolumetricFog.h in Headers */ = {isa = PBXBuildFile; fileRef = E443C5FD164B120900FC4FD8 /* KRVolumetricFog.h */; }; + E443C602164B122C00FC4FD8 /* KRVolumetricFog.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E443C601164B122C00FC4FD8 /* KRVolumetricFog.cpp */; }; + E443C603164B122C00FC4FD8 /* KRVolumetricFog.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E443C601164B122C00FC4FD8 /* KRVolumetricFog.cpp */; }; E461A152152E54B500F2044A /* KRLight.h in Headers */ = {isa = PBXBuildFile; fileRef = E461A151152E54B500F2044A /* KRLight.h */; }; E461A153152E54B500F2044A /* KRLight.h in Headers */ = {isa = PBXBuildFile; fileRef = E461A151152E54B500F2044A /* KRLight.h */; settings = {ATTRIBUTES = (Public, ); }; }; E461A156152E54F800F2044A /* KRLight.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E461A155152E54F700F2044A /* KRLight.cpp */; }; @@ -239,6 +231,12 @@ E4324BAD16444E120043185B /* KRParticleSystemBrownian.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = KRParticleSystemBrownian.cpp; path = Classes/KRParticleSystemBrownian.cpp; sourceTree = ""; }; E43B0AD415DDCA0C00A5CB9F /* KRContextObject.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = KRContextObject.cpp; path = Classes/KRContextObject.cpp; sourceTree = ""; }; E43B0AD515DDCA0D00A5CB9F /* KRContextObject.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = KRContextObject.h; path = Classes/KRContextObject.h; sourceTree = ""; }; + E443C5FD164B120900FC4FD8 /* KRVolumetricFog.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = KRVolumetricFog.h; path = Classes/KRVolumetricFog.h; sourceTree = ""; }; + E443C601164B122C00FC4FD8 /* KRVolumetricFog.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = KRVolumetricFog.cpp; path = Classes/KRVolumetricFog.cpp; sourceTree = ""; }; + E443C606164B27B400FC4FD8 /* volumetric_fog.fsh */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.glsl; name = volumetric_fog.fsh; path = Shaders/volumetric_fog.fsh; sourceTree = ""; }; + E443C609164B27C500FC4FD8 /* volumetric_fog.vsh */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.glsl; name = volumetric_fog.vsh; path = Shaders/volumetric_fog.vsh; sourceTree = ""; }; + E443C612164B5BE500FC4FD8 /* volumetric_fog_inside.fsh */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.glsl; name = volumetric_fog_inside.fsh; path = Shaders/volumetric_fog_inside.fsh; sourceTree = ""; }; + E443C615164B5BFB00FC4FD8 /* volumetric_fog_inside.vsh */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.glsl; name = volumetric_fog_inside.vsh; path = Shaders/volumetric_fog_inside.vsh; sourceTree = ""; }; E45772F113C9A13C0037BEEA /* ShadowShader.vsh */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.glsl; lineEnding = 0; name = ShadowShader.vsh; path = Shaders/ShadowShader.vsh; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.glsl; }; E45772F213C9A13C0037BEEA /* ShadowShader.fsh */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.glsl; name = ShadowShader.fsh; path = Shaders/ShadowShader.fsh; sourceTree = ""; }; E45772F313C9A13C0037BEEA /* PostShader.fsh */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.glsl; name = PostShader.fsh; path = Shaders/PostShader.fsh; sourceTree = ""; }; @@ -426,6 +424,10 @@ E45AC0411641DE6D00DC3C3B /* debug_font.fsh */, E45AC0461643451200DC3C3B /* particle.fsh */, E45AC0491643452000DC3C3B /* particle.vsh */, + E443C606164B27B400FC4FD8 /* volumetric_fog.fsh */, + E443C609164B27C500FC4FD8 /* volumetric_fog.vsh */, + E443C612164B5BE500FC4FD8 /* volumetric_fog_inside.fsh */, + E443C615164B5BFB00FC4FD8 /* volumetric_fog_inside.vsh */, ); name = Shaders; sourceTree = ""; @@ -584,6 +586,8 @@ E461A171152E599E00F2044A /* Lights */, E4F975311536220900FD60B2 /* KRNode.h */, E4F975351536221C00FD60B2 /* KRNode.cpp */, + E443C5FD164B120900FC4FD8 /* KRVolumetricFog.h */, + E443C601164B122C00FC4FD8 /* KRVolumetricFog.cpp */, ); name = "Scene Graph Nodes"; sourceTree = ""; @@ -767,6 +771,7 @@ E4CA11741639CBD6005D9400 /* KRViewport.h in Headers */, E4324BA416444C0D0043185B /* KRParticleSystem.h in Headers */, E4324BAB16444DEF0043185B /* KRParticleSystemBrownian.h in Headers */, + E443C5FE164B120A00FC4FD8 /* KRVolumetricFog.h in Headers */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -821,6 +826,7 @@ E461A169152E570700F2044A /* KRSpotLight.h in Headers */, E4324BA516444C0D0043185B /* KRParticleSystem.h in Headers */, E4324BAC16444DEF0043185B /* KRParticleSystemBrownian.h in Headers */, + E443C5FF164B120A00FC4FD8 /* KRVolumetricFog.h in Headers */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -946,14 +952,9 @@ E4CA10E91637BD2B005D9400 /* KRTexturePVR.cpp in Sources */, E4CA10EF1637BD58005D9400 /* KRTextureTGA.cpp in Sources */, E4CA11781639CC90005D9400 /* KRViewport.cpp in Sources */, - E45AC0301641D66300DC3C3B /* simple_blit.vsh in Sources */, - E45AC0341641D67300DC3C3B /* simple_blit.fsh in Sources */, - E45AC03F1641DE5D00DC3C3B /* debug_font.vsh in Sources */, - E45AC0421641DE6D00DC3C3B /* debug_font.fsh in Sources */, - E45AC0471643451300DC3C3B /* particle.fsh in Sources */, - E45AC04A1643452100DC3C3B /* particle.vsh in Sources */, E4324BA816444C230043185B /* KRParticleSystem.cpp in Sources */, E4324BAE16444E120043185B /* KRParticleSystemBrownian.cpp in Sources */, + E443C602164B122C00FC4FD8 /* KRVolumetricFog.cpp in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -1002,14 +1003,9 @@ E4CA10EA1637BD2B005D9400 /* KRTexturePVR.cpp in Sources */, E4CA10F01637BD58005D9400 /* KRTextureTGA.cpp in Sources */, E4CA11791639CC90005D9400 /* KRViewport.cpp in Sources */, - E45AC0311641D66300DC3C3B /* simple_blit.vsh in Sources */, - E45AC0351641D67300DC3C3B /* simple_blit.fsh in Sources */, - E45AC0401641DE5D00DC3C3B /* debug_font.vsh in Sources */, - E45AC0431641DE6D00DC3C3B /* debug_font.fsh in Sources */, - E45AC0481643451300DC3C3B /* particle.fsh in Sources */, - E45AC04B1643452100DC3C3B /* particle.vsh in Sources */, E4324BAF16444E120043185B /* KRParticleSystemBrownian.cpp in Sources */, E4324BB0164458930043185B /* KRParticleSystem.cpp in Sources */, + E443C603164B122C00FC4FD8 /* KRVolumetricFog.cpp in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/KREngine/KREngine/Classes/KRAABB.cpp b/KREngine/KREngine/Classes/KRAABB.cpp index d2dfda8..a69e59a 100644 --- a/KREngine/KREngine/Classes/KRAABB.cpp +++ b/KREngine/KREngine/Classes/KRAABB.cpp @@ -20,7 +20,7 @@ KRAABB::KRAABB(const KRVector3 &minPoint, const KRVector3 &maxPoint) KRAABB::KRAABB(const KRVector3 &corner1, const KRVector3 &corner2, const KRMat4 &modelMatrix) { for(int iCorner=0; iCorner<8; iCorner++) { - KRVector3 sourceCornerVertex = KRMat4::Dot(modelMatrix, KRVector3( + KRVector3 sourceCornerVertex = KRMat4::DotWDiv(modelMatrix, KRVector3( (iCorner & 1) == 0 ? corner1.x : corner2.x, (iCorner & 2) == 0 ? corner1.y : corner2.y, (iCorner & 4) == 0 ? corner1.z : corner2.z)); diff --git a/KREngine/KREngine/Classes/KRCamera.cpp b/KREngine/KREngine/Classes/KRCamera.cpp index 5d5cb72..4fd73c6 100644 --- a/KREngine/KREngine/Classes/KRCamera.cpp +++ b/KREngine/KREngine/Classes/KRCamera.cpp @@ -39,6 +39,7 @@ #import "KRCamera.h" #import "KRBoundingVolume.h" #import "KRStockGeometry.h" +#import "KRDirectionalLight.h" KRCamera::KRCamera(KRContext &context) : KRContextObject(context) { m_particlesAbsoluteTime = 0.0f; @@ -146,30 +147,52 @@ void KRCamera::renderFrame(KRScene &scene, KRMat4 &viewMatrix, float deltaTime) setViewportSize(KRVector2(backingWidth, backingHeight)); m_viewport = KRViewport(getViewportSize(), viewMatrix, getProjectionMatrix()); - + m_pContext->rotateBuffers(true); - KRVector3 lightDirection(0.0, 0.0, 1.0); - - // ----- Render Model ----- - KRMat4 shadowvp; - shadowvp.rotate(scene.sun_pitch, X_AXIS); - shadowvp.rotate(scene.sun_yaw, Y_AXIS); - lightDirection = KRMat4::Dot(shadowvp, lightDirection); - lightDirection.normalize(); - shadowvp.invert(); - + KRDirectionalLight *firstDirectionalLight = scene.getFirstDirectionalLight(); + KRVector3 lightDirection = KRVector3::Normalize(KRVector3(0.90, 0.70, 0.25)); + if(firstDirectionalLight) { + lightDirection = firstDirectionalLight->getWorldLightDirection(); + } + allocateShadowBuffers(m_cShadowBuffers); - int iOffset=m_iFrame % m_cShadowBuffers; - for(int iShadow2=iOffset; iShadow2 < m_cShadowBuffers + iOffset; iShadow2++) { - int iShadow = iShadow2 % 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}}; - KRMat4 newShadowMVP; + + + + 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 // @@ -179,22 +202,13 @@ void KRCamera::renderFrame(KRScene &scene, KRMat4 &viewMatrix, float deltaTime) // 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); - - - if(!(shadowmvpmatrix[iShadow] == newShadowMVP)) { - shadowValid[iShadow] = false; - } - - if(!shadowValid[iShadow]) { - shadowValid[iShadow] = true; - - shadowmvpmatrix[iShadow] = newShadowMVP; - renderShadowBuffer(scene, iShadow); - - break; - } +// 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); @@ -237,7 +251,7 @@ void KRCamera::renderFrame(KRScene &scene, KRVector3 &lightDirection, float delt GLDEBUG(glDisable(GL_BLEND)); // Render the geometry - scene.render(this, m_visibleBounds, m_pContext, m_viewport, lightDirection, shadowmvpmatrix, shadowDepthTexture, m_cShadowBuffers, KRNode::RENDER_PASS_DEFERRED_GBUFFER, newVisibleBounds); + scene.render(this, m_viewport.getVisibleBounds(), m_pContext, m_viewport, m_shadowViewports, lightDirection, shadowDepthTexture, m_cShadowBuffers, KRNode::RENDER_PASS_DEFERRED_GBUFFER, newVisibleBounds); // ----====---- Opaque Geometry, Deferred rendering Pass 2 ----====---- // Set render target @@ -263,7 +277,7 @@ void KRCamera::renderFrame(KRScene &scene, KRVector3 &lightDirection, float delt // Render the geometry - scene.render(this, m_visibleBounds, m_pContext, m_viewport, lightDirection, shadowmvpmatrix, shadowDepthTexture, 0, KRNode::RENDER_PASS_DEFERRED_LIGHTS, newVisibleBounds); + scene.render(this, m_viewport.getVisibleBounds(), m_pContext, m_viewport, m_shadowViewports, lightDirection, shadowDepthTexture, 0, KRNode::RENDER_PASS_DEFERRED_LIGHTS, newVisibleBounds); // ----====---- Opaque Geometry, Deferred rendering Pass 3 ----====---- // Set render target @@ -295,7 +309,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, lightDirection, shadowmvpmatrix, shadowDepthTexture, m_cShadowBuffers, KRNode::RENDER_PASS_DEFERRED_OPAQUE, newVisibleBounds); + scene.render(this, emptyBoundsSet, m_pContext, m_viewport, m_shadowViewports, lightDirection, shadowDepthTexture, m_cShadowBuffers, KRNode::RENDER_PASS_DEFERRED_OPAQUE, newVisibleBounds); // Deactivate source buffer texture units m_pContext->getTextureManager()->selectTexture(6, NULL, 0); @@ -333,7 +347,7 @@ void KRCamera::renderFrame(KRScene &scene, KRVector3 &lightDirection, float delt // Render the geometry - scene.render(this, m_visibleBounds, m_pContext, m_viewport, lightDirection, shadowmvpmatrix, shadowDepthTexture, m_cShadowBuffers, KRNode::RENDER_PASS_FORWARD_OPAQUE, newVisibleBounds); + scene.render(this, m_viewport.getVisibleBounds(), m_pContext, m_viewport, m_shadowViewports, lightDirection, shadowDepthTexture, m_cShadowBuffers, KRNode::RENDER_PASS_FORWARD_OPAQUE, newVisibleBounds); } // ----====---- Sky Box ----====---- @@ -359,7 +373,7 @@ 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, KRMat4(), lightDirection, NULL, NULL, 0, KRNode::RENDER_PASS_FORWARD_OPAQUE); + pShader->bind(m_viewport, m_shadowViewports, KRMat4(), lightDirection, NULL, 0, KRNode::RENDER_PASS_FORWARD_OPAQUE); getContext().getTextureManager()->selectTexture(0, m_pSkyBoxTexture, 2048); @@ -393,7 +407,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_visibleBounds, m_pContext, m_viewport, lightDirection, shadowmvpmatrix, shadowDepthTexture, m_cShadowBuffers, KRNode::RENDER_PASS_FORWARD_TRANSPARENT, newVisibleBounds); + scene.render(this, m_viewport.getVisibleBounds(), m_pContext, m_viewport, m_shadowViewports, lightDirection, shadowDepthTexture, m_cShadowBuffers, KRNode::RENDER_PASS_FORWARD_TRANSPARENT, newVisibleBounds); // ----====---- Flares ----====---- @@ -417,7 +431,7 @@ void KRCamera::renderFrame(KRScene &scene, KRVector3 &lightDirection, float delt GLDEBUG(glBlendFunc(GL_ONE, GL_ONE)); // Render all flares - scene.render(this, m_visibleBounds, m_pContext, m_viewport, lightDirection, shadowmvpmatrix, shadowDepthTexture, m_cShadowBuffers, KRNode::RENDER_PASS_ADDITIVE_PARTICLES, newVisibleBounds); + scene.render(this, m_viewport.getVisibleBounds(), m_pContext, m_viewport, m_shadowViewports, lightDirection, shadowDepthTexture, m_cShadowBuffers, KRNode::RENDER_PASS_ADDITIVE_PARTICLES, newVisibleBounds); // ----====---- Debug Overlay ----====---- @@ -442,17 +456,17 @@ void KRCamera::renderFrame(KRScene &scene, KRVector3 &lightDirection, float delt KRMat4 projectionMatrix = getProjectionMatrix(); m_pContext->getModelManager()->bindVBO((void *)KRENGINE_VBO_3D_CUBE, KRENGINE_VBO_3D_CUBE_SIZE, true, false, false, false, false); - for(std::set::iterator itr=m_visibleBounds.begin(); itr != m_visibleBounds.end(); itr++) { + for(std::set::iterator itr=m_viewport.getVisibleBounds().begin(); itr != m_viewport.getVisibleBounds().end(); itr++) { KRMat4 matModel = KRMat4(); matModel.scale((*itr).size() / 2.0f); matModel.translate((*itr).center()); - if(pVisShader->bind(m_viewport, matModel, lightDirection, shadowmvpmatrix, shadowDepthTexture, 0, KRNode::RENDER_PASS_FORWARD_TRANSPARENT)) { + if(pVisShader->bind(m_viewport, m_shadowViewports, matModel, lightDirection, shadowDepthTexture, 0, KRNode::RENDER_PASS_FORWARD_TRANSPARENT)) { GLDEBUG(glDrawArrays(GL_TRIANGLE_STRIP, 0, 14)); } } } - m_visibleBounds = newVisibleBounds; + m_viewport.setVisibleBounds(newVisibleBounds); // Re-enable z-buffer write GLDEBUG(glDepthMask(GL_TRUE)); @@ -548,6 +562,10 @@ void KRCamera::allocateShadowBuffers(int cBuffers) { 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)); @@ -589,11 +607,13 @@ 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, 2046, 2046); + glViewport(1, 1, m_shadowViewports[iShadow].getSize().x - 2, m_shadowViewports[iShadow].getSize().y - 2); GLDEBUG(glDisable(GL_DITHER)); @@ -611,40 +631,40 @@ void KRCamera::renderShadowBuffer(KRScene &scene, int iShadow) // 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); - KRViewport viewport = KRViewport(getViewportSize(), KRMat4(), KRMat4()); - shadowShader->bind(viewport, KRMat4(), KRVector3(), NULL, NULL, 0, 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]); +// // 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(); +// // 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 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; - viewport = KRViewport(m_viewport.getSize(), KRMat4(), shadowmvpmatrix[iShadow]); - scene.render(this, m_shadowVisibleBounds[iShadow], m_pContext, viewport, lightDirection, shadowmvpmatrix, NULL, m_cShadowBuffers, KRNode::RENDER_PASS_SHADOWMAP, 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_shadowVisibleBounds[iShadow] = newVisibleBounds; - GLDEBUG(glViewport(0, 0, backingWidth, backingHeight)); + m_shadowViewports[iShadow].setVisibleBounds(newVisibleBounds); + GLDEBUG(glViewport(0, 0, m_viewport.getSize().x, m_viewport.getSize().y)); } void KRCamera::renderPost() @@ -675,7 +695,7 @@ 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(KRViewport(getViewportSize(), KRMat4(), KRMat4()), KRMat4(), KRVector3(), NULL, NULL, 0, KRNode::RENDER_PASS_FORWARD_TRANSPARENT); + postShader->bind(m_viewport, m_shadowViewports, KRMat4(), KRVector3(), NULL, 0, KRNode::RENDER_PASS_FORWARD_TRANSPARENT); m_pContext->getTextureManager()->selectTexture(0, NULL, 0); GLDEBUG(glActiveTexture(GL_TEXTURE0)); @@ -706,12 +726,18 @@ void KRCamera::renderPost() 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()), KRMat4(), KRVector3(), NULL, NULL, 0, KRNode::RENDER_PASS_FORWARD_TRANSPARENT); + 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); diff --git a/KREngine/KREngine/Classes/KRCamera.h b/KREngine/KREngine/Classes/KRCamera.h index 678f9a8..a2dd652 100644 --- a/KREngine/KREngine/Classes/KRCamera.h +++ b/KREngine/KREngine/Classes/KRCamera.h @@ -137,7 +137,6 @@ private: GLuint shadowFramebuffer[KRENGINE_MAX_SHADOW_BUFFERS], shadowDepthTexture[KRENGINE_MAX_SHADOW_BUFFERS]; bool shadowValid[KRENGINE_MAX_SHADOW_BUFFERS]; - KRMat4 shadowmvpmatrix[KRENGINE_MAX_SHADOW_BUFFERS]; /* MVP Matrix for view from light source */ KRViewport m_shadowViewports[KRENGINE_MAX_SHADOW_BUFFERS]; @@ -172,9 +171,6 @@ private: float m_distance; }; - std::set m_visibleBounds; // AABB's that output fragments in the last frame - std::set m_shadowVisibleBounds[KRENGINE_MAX_SHADOW_BUFFERS]; // AABB's that output fragments in the last frame for each shadow map - std::string m_skyBoxName; KRTexture *m_pSkyBoxTexture; diff --git a/KREngine/KREngine/Classes/KRDirectionalLight.cpp b/KREngine/KREngine/Classes/KRDirectionalLight.cpp index 03b0e74..98f4650 100644 --- a/KREngine/KREngine/Classes/KRDirectionalLight.cpp +++ b/KREngine/KREngine/Classes/KRDirectionalLight.cpp @@ -50,9 +50,9 @@ KRVector3 KRDirectionalLight::getLocalLightDirection() { #if TARGET_OS_IPHONE -void KRDirectionalLight::render(KRCamera *pCamera, KRContext *pContext, const KRViewport &viewport, KRVector3 &lightDirection, KRMat4 *pShadowMatrices, GLuint *shadowDepthTextures, int cShadowBuffers, KRNode::RenderPass renderPass) { +void KRDirectionalLight::render(KRCamera *pCamera, KRContext *pContext, const KRViewport &viewport, const KRViewport *pShadowViewports, KRVector3 &lightDirection, GLuint *shadowDepthTextures, int cShadowBuffers, KRNode::RenderPass renderPass) { - KRLight::render(pCamera, pContext, viewport, lightDirection, pShadowMatrices, shadowDepthTextures, cShadowBuffers, renderPass); + KRLight::render(pCamera, pContext, viewport, pShadowViewports, lightDirection, shadowDepthTextures, cShadowBuffers, renderPass); if(renderPass == KRNode::RENDER_PASS_DEFERRED_LIGHTS) { // Lights are rendered on the second pass of the deferred renderer @@ -66,7 +66,7 @@ void KRDirectionalLight::render(KRCamera *pCamera, KRContext *pContext, const KR 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, getModelMatrix(), lightDirection, pShadowMatrices, shadowDepthTextures, 0, renderPass)) { + if(pShader->bind(viewport, pShadowViewports, getModelMatrix(), lightDirection, shadowDepthTextures, 0, 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 aa62534..a273ceb 100644 --- a/KREngine/KREngine/Classes/KRDirectionalLight.h +++ b/KREngine/KREngine/Classes/KRDirectionalLight.h @@ -25,7 +25,7 @@ public: #if TARGET_OS_IPHONE - virtual void render(KRCamera *pCamera, KRContext *pContext, const KRViewport &viewport, KRVector3 &lightDirection, KRMat4 *pShadowMatrices, GLuint *shadowDepthTextures, int cShadowBuffers, KRNode::RenderPass renderPass); + virtual void render(KRCamera *pCamera, KRContext *pContext, const KRViewport &viewport, const KRViewport *pShadowViewports, KRVector3 &lightDirection, GLuint *shadowDepthTextures, int cShadowBuffers, KRNode::RenderPass renderPass); #endif }; diff --git a/KREngine/KREngine/Classes/KRInstance.cpp b/KREngine/KREngine/Classes/KRInstance.cpp index 149515f..4293e84 100644 --- a/KREngine/KREngine/Classes/KRInstance.cpp +++ b/KREngine/KREngine/Classes/KRInstance.cpp @@ -35,11 +35,13 @@ #import "KRModel.h" #include -KRInstance::KRInstance(KRScene &scene, std::string instance_name, std::string model_name, std::string light_map, float lod_min_coverage) : KRNode(scene, instance_name) { +KRInstance::KRInstance(KRScene &scene, std::string instance_name, std::string model_name, std::string light_map, float lod_min_coverage, bool receives_shadow) : KRNode(scene, instance_name) { m_lightMap = light_map; m_pLightMap = NULL; m_model_name = model_name; m_min_lod_coverage = lod_min_coverage; + m_receivesShadow = receives_shadow; + m_receivesShadow = true; } KRInstance::~KRInstance() { @@ -56,6 +58,7 @@ tinyxml2::XMLElement *KRInstance::saveXML( tinyxml2::XMLNode *parent) e->SetAttribute("mesh_name", m_model_name.c_str()); e->SetAttribute("light_map", m_lightMap.c_str()); e->SetAttribute("lod_min_coverage", m_min_lod_coverage); + e->SetAttribute("receives_shadow", m_receivesShadow ? "true" : "false"); return e; } @@ -73,10 +76,10 @@ void KRInstance::loadModel() { #if TARGET_OS_IPHONE -void KRInstance::render(KRCamera *pCamera, KRContext *pContext, const KRViewport &viewport, KRVector3 &lightDirection, KRMat4 *pShadowMatrices, GLuint *shadowDepthTextures, int cShadowBuffers, KRNode::RenderPass renderPass) { +void KRInstance::render(KRCamera *pCamera, KRContext *pContext, const KRViewport &viewport, const KRViewport *pShadowViewports, KRVector3 &lightDirection, GLuint *shadowDepthTextures, int cShadowBuffers, KRNode::RenderPass renderPass) { - KRNode::render(pCamera, pContext, viewport, lightDirection, pShadowMatrices, shadowDepthTextures, cShadowBuffers, renderPass); + KRNode::render(pCamera, pContext, viewport, pShadowViewports, lightDirection, shadowDepthTextures, cShadowBuffers, renderPass); if(renderPass != KRNode::RENDER_PASS_DEFERRED_LIGHTS && (renderPass != KRNode::RENDER_PASS_FORWARD_TRANSPARENT || this->hasTransparency()) && renderPass != KRNode::RENDER_PASS_ADDITIVE_PARTICLES) { // Don't render meshes on second pass of the deferred lighting renderer, as only lights will be applied @@ -104,11 +107,11 @@ void KRInstance::render(KRCamera *pCamera, KRContext *pContext, const KRViewport m_pLightMap = pContext->getTextureManager()->getTexture(m_lightMap.c_str()); } - if(cShadowBuffers == 0 && m_pLightMap && pCamera->bEnableLightMap && renderPass != RENDER_PASS_SHADOWMAP) { + if(m_pLightMap && pCamera->bEnableLightMap && renderPass != RENDER_PASS_SHADOWMAP) { m_pContext->getTextureManager()->selectTexture(5, m_pLightMap, 2048); } - pModel->render(pCamera, pContext, viewport, getModelMatrix(), lightDirection, pShadowMatrices, shadowDepthTextures, cShadowBuffers, m_pLightMap, renderPass); + pModel->render(pCamera, pContext, viewport, pShadowViewports, getModelMatrix(), lightDirection, shadowDepthTextures, m_receivesShadow ? cShadowBuffers : 0, m_pLightMap, renderPass); } } } diff --git a/KREngine/KREngine/Classes/KRInstance.h b/KREngine/KREngine/Classes/KRInstance.h index 9719bea..0838f04 100644 --- a/KREngine/KREngine/Classes/KRInstance.h +++ b/KREngine/KREngine/Classes/KRInstance.h @@ -50,7 +50,7 @@ class KRInstance : public KRNode { public: - KRInstance(KRScene &scene, std::string instance_name, std::string model_name, std::string light_map, float lod_min_coverage); + KRInstance(KRScene &scene, std::string instance_name, std::string model_name, std::string light_map, float lod_min_coverage, bool receives_shadow); virtual ~KRInstance(); virtual std::string getElementName(); @@ -58,7 +58,7 @@ public: #if TARGET_OS_IPHONE - virtual void render(KRCamera *pCamera, KRContext *pContext, const KRViewport &viewport, KRVector3 &lightDirection, KRMat4 *pShadowMatrices, GLuint *shadowDepthTextures, int cShadowBuffers, KRNode::RenderPass renderPass); + virtual void render(KRCamera *pCamera, KRContext *pContext, const KRViewport &viewport, const KRViewport *pShadowViewports, KRVector3 &lightDirection, GLuint *shadowDepthTextures, int cShadowBuffers, KRNode::RenderPass renderPass); #endif bool hasTransparency(); @@ -75,6 +75,8 @@ private: float m_min_lod_coverage; void loadModel(); + + bool m_receivesShadow; }; diff --git a/KREngine/KREngine/Classes/KRLight.cpp b/KREngine/KREngine/Classes/KRLight.cpp index c83f2fb..14a21a4 100644 --- a/KREngine/KREngine/Classes/KRLight.cpp +++ b/KREngine/KREngine/Classes/KRLight.cpp @@ -118,9 +118,9 @@ float KRLight::getDecayStart() { #if TARGET_OS_IPHONE -void KRLight::render(KRCamera *pCamera, KRContext *pContext, const KRViewport &viewport, KRVector3 &lightDirection, KRMat4 *pShadowMatrices, GLuint *shadowDepthTextures, int cShadowBuffers, KRNode::RenderPass renderPass) { +void KRLight::render(KRCamera *pCamera, KRContext *pContext, const KRViewport &viewport, const KRViewport *pShadowViewports, KRVector3 &lightDirection, GLuint *shadowDepthTextures, int cShadowBuffers, KRNode::RenderPass renderPass) { - KRNode::render(pCamera, pContext, viewport, lightDirection, pShadowMatrices, shadowDepthTextures, cShadowBuffers, renderPass); + KRNode::render(pCamera, pContext, viewport, pShadowViewports, lightDirection, shadowDepthTextures, cShadowBuffers, renderPass); if(renderPass == KRNode::RENDER_PASS_ADDITIVE_PARTICLES) { if(m_flareTexture.size() && m_flareSize > 0.0f) { @@ -135,7 +135,7 @@ void KRLight::render(KRCamera *pCamera, KRContext *pContext, const KRViewport &v // 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, getModelMatrix(), lightDirection, pShadowMatrices, shadowDepthTextures, 0, renderPass)) { + if(pShader->bind(viewport, pShadowViewports, getModelMatrix(), lightDirection, shadowDepthTextures, 0, renderPass)) { GLDEBUG(glUniform1f( pShader->m_uniforms[KRShader::KRENGINE_UNIFORM_FLARE_SIZE], m_flareSize diff --git a/KREngine/KREngine/Classes/KRLight.h b/KREngine/KREngine/Classes/KRLight.h index 2b05a86..e33ba44 100644 --- a/KREngine/KREngine/Classes/KRLight.h +++ b/KREngine/KREngine/Classes/KRLight.h @@ -36,7 +36,7 @@ public: #if TARGET_OS_IPHONE - virtual void render(KRCamera *pCamera, KRContext *pContext, const KRViewport &viewport, KRVector3 &lightDirection, KRMat4 *pShadowMatrices, GLuint *shadowDepthTextures, int cShadowBuffers, KRNode::RenderPass renderPass); + virtual void render(KRCamera *pCamera, KRContext *pContext, const KRViewport &viewport, const KRViewport *pShadowViewports, KRVector3 &lightDirection, GLuint *shadowDepthTextures, int cShadowBuffers, KRNode::RenderPass renderPass); #endif diff --git a/KREngine/KREngine/Classes/KRMaterial.cpp b/KREngine/KREngine/Classes/KRMaterial.cpp index e77be36..c34bd90 100644 --- a/KREngine/KREngine/Classes/KRMaterial.cpp +++ b/KREngine/KREngine/Classes/KRMaterial.cpp @@ -201,7 +201,7 @@ bool KRMaterial::isTransparent() { } #if TARGET_OS_IPHONE -bool KRMaterial::bind(KRMaterial **prevBoundMaterial, char *szPrevShaderKey, const KRCamera *pCamera, const KRViewport &viewport, const KRMat4 &matModel, const KRVector3 &lightDirection, KRMat4 *pShadowMatrices, GLuint *shadowDepthTextures, int cShadowBuffers, KRContext *pContext, KRTexture *pLightMap, KRNode::RenderPass renderPass) { +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 bSameMaterial = *prevBoundMaterial == this; bool bLightMap = pLightMap && pCamera->bEnableLightMap; @@ -242,7 +242,7 @@ bool KRMaterial::bind(KRMaterial **prevBoundMaterial, char *szPrevShaderKey, con bool bSameShader = strcmp(pShader->getKey(), szPrevShaderKey) == 0; if(!bSameShader) { - if(!pShader->bind(viewport, matModel, lightDirection, pShadowMatrices, shadowDepthTextures, cShadowBuffers, renderPass)) { + if(!pShader->bind(viewport, pShadowViewports, matModel, lightDirection, shadowDepthTextures, cShadowBuffers, renderPass)) { return false; } diff --git a/KREngine/KREngine/Classes/KRMaterial.h b/KREngine/KREngine/Classes/KRMaterial.h index 904d3ce..21cef67 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 KRMat4 &matModel, const KRVector3 &lightDirection, KRMat4 *pShadowMatrices, GLuint *shadowDepthTextures, int cShadowBuffers, KRContext *pContext, KRTexture *pLightMap, KRNode::RenderPass renderPass); + 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); #endif diff --git a/KREngine/KREngine/Classes/KRModel.cpp b/KREngine/KREngine/Classes/KRModel.cpp index e04b86e..f2c4dc8 100644 --- a/KREngine/KREngine/Classes/KRModel.cpp +++ b/KREngine/KREngine/Classes/KRModel.cpp @@ -111,7 +111,7 @@ void KRModel::loadPack(KRDataBlock *data) { #if TARGET_OS_IPHONE -void KRModel::render(KRCamera *pCamera, KRContext *pContext, const KRViewport &viewport, const KRMat4 &matModel, const KRVector3 &lightDirection, KRMat4 *pShadowMatrices, GLuint *shadowDepthTextures, int cShadowBuffers, KRTexture *pLightMap, KRNode::RenderPass renderPass) { +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) { //fprintf(stderr, "Rendering model: %s\n", m_name.c_str()); if(renderPass != KRNode::RENDER_PASS_ADDITIVE_PARTICLES) { @@ -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, matModel, lightDirection, pShadowMatrices, shadowDepthTextures, cShadowBuffers, pContext, pLightMap, renderPass)) { + if(pMaterial->bind(&pPrevBoundMaterial, szPrevShaderKey, pCamera, viewport, pShadowViewports, matModel, lightDirection, shadowDepthTextures, cShadowBuffers, pContext, 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 bd1ec51..843281c 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 KRMat4 &matModel, const KRVector3 &lightDirection, KRMat4 *pShadowMatrices, GLuint *shadowDepthTextures, int cShadowBuffers, KRTexture *pLightMap, KRNode::RenderPass renderPass); + 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); #endif diff --git a/KREngine/KREngine/Classes/KRModelManager.cpp b/KREngine/KREngine/Classes/KRModelManager.cpp index 17b2fc6..0cd2575 100644 --- a/KREngine/KREngine/Classes/KRModelManager.cpp +++ b/KREngine/KREngine/Classes/KRModelManager.cpp @@ -40,6 +40,7 @@ KRModelManager::KRModelManager(KRContext &context) : KRContextObject(context) { m_currentVBO.data = NULL; m_vboMemUsed = 0; m_randomParticleVertexData = NULL; + m_volumetricLightingVertexData = NULL; } KRModelManager::~KRModelManager() { @@ -48,6 +49,7 @@ KRModelManager::~KRModelManager() { } m_models.empty(); if(m_randomParticleVertexData != NULL) delete m_randomParticleVertexData; + if(m_volumetricLightingVertexData != NULL) delete m_volumetricLightingVertexData; } KRModel *KRModelManager::loadModel(const char *szName, KRDataBlock *pData) { @@ -249,6 +251,53 @@ void KRModelManager::rotateBuffers(bool new_frame) } +KRModelManager::VolumetricLightingVertexData *KRModelManager::getVolumetricLightingVertexes() +{ + const int MAX_PLANES=500; + if(m_volumetricLightingVertexData == NULL) { + m_volumetricLightingVertexData = (VolumetricLightingVertexData *)malloc(sizeof(VolumetricLightingVertexData) * MAX_PLANES * 6); + int iVertex=0; + for(int iPlane=0; iPlane < MAX_PLANES; iPlane++) { + m_volumetricLightingVertexData[iVertex].vertex.x = -1.0f; + m_volumetricLightingVertexData[iVertex].vertex.y = -1.0f; + m_volumetricLightingVertexData[iVertex].vertex.z = iPlane; + iVertex++; + + m_volumetricLightingVertexData[iVertex].vertex.x = 1.0f; + m_volumetricLightingVertexData[iVertex].vertex.y = -1.0f; + m_volumetricLightingVertexData[iVertex].vertex.z = iPlane; + iVertex++; + + m_volumetricLightingVertexData[iVertex].vertex.x = -1.0f; + m_volumetricLightingVertexData[iVertex].vertex.y = 1.0f; + m_volumetricLightingVertexData[iVertex].vertex.z = iPlane; + iVertex++; + + m_volumetricLightingVertexData[iVertex].vertex.x = -1.0f; + m_volumetricLightingVertexData[iVertex].vertex.y = 1.0f; + m_volumetricLightingVertexData[iVertex].vertex.z = iPlane; + iVertex++; + + m_volumetricLightingVertexData[iVertex].vertex.x = 1.0f; + m_volumetricLightingVertexData[iVertex].vertex.y = -1.0f; + m_volumetricLightingVertexData[iVertex].vertex.z = iPlane; + iVertex++; + + + m_volumetricLightingVertexData[iVertex].vertex.x = 1.0f; + m_volumetricLightingVertexData[iVertex].vertex.y = 1.0f; + m_volumetricLightingVertexData[iVertex].vertex.z = iPlane; + iVertex++; + +// -1.0f, -1.0f, +// 1.0f, -1.0f, +// -1.0f, 1.0f, +// 1.0f, 1.0f, + } + } + return m_volumetricLightingVertexData; +} + KRModelManager::RandomParticleVertexData *KRModelManager::getRandomParticles() { const int MAX_PARTICLES=500000; diff --git a/KREngine/KREngine/Classes/KRModelManager.h b/KREngine/KREngine/Classes/KRModelManager.h index 2dd0e2a..26fd25a 100644 --- a/KREngine/KREngine/Classes/KRModelManager.h +++ b/KREngine/KREngine/Classes/KRModelManager.h @@ -80,7 +80,12 @@ public: TexCoord uva; } RandomParticleVertexData; + typedef struct { + KRVector3D vertex; + } VolumetricLightingVertexData; + RandomParticleVertexData *getRandomParticles(); + VolumetricLightingVertexData *getVolumetricLightingVertexes(); private: std::multimap m_models; // Multiple models with the same name/key may be inserted, representing multiple LOD levels of the model @@ -99,6 +104,8 @@ private: std::map m_vbosPool; RandomParticleVertexData *m_randomParticleVertexData; + VolumetricLightingVertexData *m_volumetricLightingVertexData; + }; #endif diff --git a/KREngine/KREngine/Classes/KRNode.cpp b/KREngine/KREngine/Classes/KRNode.cpp index 0f8f97f..6cb4da7 100644 --- a/KREngine/KREngine/Classes/KRNode.cpp +++ b/KREngine/KREngine/Classes/KRNode.cpp @@ -17,6 +17,7 @@ #import "KRInstance.h" #import "KRParticleSystem.h" #import "KRParticleSystemBrownian.h" +#import "KRVolumetricFog.h" #import "KRAABB.h" #import "KRQuaternion.h" @@ -147,12 +148,22 @@ KRNode *KRNode::LoadXML(KRScene &scene, tinyxml2::XMLElement *e) { new_node = new KRSpotLight(scene, szName); } else if(strcmp(szElementName, "brownian_particles") == 0) { new_node = new KRParticleSystemBrownian(scene, szName); + } else if(strcmp(szElementName, "volumetric_fog") == 0) { + float lod_min_coverage = 0.0f; + if(e->QueryFloatAttribute("lod_min_coverage", &lod_min_coverage) != tinyxml2::XML_SUCCESS) { + lod_min_coverage = 0.0f; //1.0f / 1024.0f / 768.0f; // FINDME - HACK - Need to dynamically select the absolute minimum based on the render buffer size + } + new_node = new KRVolumetricFog(scene, szName, szName, lod_min_coverage); } else if(strcmp(szElementName, "mesh") == 0) { float lod_min_coverage = 0.0f; if(e->QueryFloatAttribute("lod_min_coverage", &lod_min_coverage) != tinyxml2::XML_SUCCESS) { lod_min_coverage = 0.0f; //1.0f / 1024.0f / 768.0f; // FINDME - HACK - Need to dynamically select the absolute minimum based on the render buffer size } - new_node = new KRInstance(scene, szName, szName, e->Attribute("light_map"), lod_min_coverage); + bool receives_shadow = true; + if(e->QueryBoolAttribute("receives_shadow", &receives_shadow) != tinyxml2::XML_SUCCESS) { + receives_shadow = true; + } + new_node = new KRInstance(scene, szName, szName, e->Attribute("light_map"), lod_min_coverage, receives_shadow); } if(new_node) { @@ -164,7 +175,7 @@ KRNode *KRNode::LoadXML(KRScene &scene, tinyxml2::XMLElement *e) { #if TARGET_OS_IPHONE -void KRNode::render(KRCamera *pCamera, KRContext *pContext, const KRViewport &viewport, KRVector3 &lightDirection, KRMat4 *pShadowMatrices, GLuint *shadowDepthTextures, int cShadowBuffers, RenderPass renderPass) { +void KRNode::render(KRCamera *pCamera, KRContext *pContext, const KRViewport &viewport, const KRViewport *pShadowViewports, KRVector3 &lightDirection, GLuint *shadowDepthTextures, int cShadowBuffers, RenderPass renderPass) { } #endif @@ -211,3 +222,14 @@ const KRMat4 &KRNode::getModelMatrix() } return m_modelMatrix; } + + +void KRNode::physicsUpdate(float deltaTime) +{ + +} + +bool KRNode::hasPhysics() +{ + return false; +} \ No newline at end of file diff --git a/KREngine/KREngine/Classes/KRNode.h b/KREngine/KREngine/Classes/KRNode.h index 72bf087..c33f549 100644 --- a/KREngine/KREngine/Classes/KRNode.h +++ b/KREngine/KREngine/Classes/KRNode.h @@ -68,10 +68,13 @@ public: KRScene &getScene(); #if TARGET_OS_IPHONE - virtual void render(KRCamera *pCamera, KRContext *pContext, const KRViewport &viewport, KRVector3 &lightDirection, KRMat4 *pShadowMatrices, GLuint *shadowDepthTextures, int cShadowBuffers, RenderPass renderPass); + virtual void render(KRCamera *pCamera, KRContext *pContext, const KRViewport &viewport, const KRViewport *pShadowViewports, KRVector3 &lightDirection, GLuint *shadowDepthTextures, int cShadowBuffers, RenderPass renderPass); #endif + virtual void physicsUpdate(float deltaTime); + virtual bool hasPhysics(); + protected: KRVector3 m_localTranslation; KRVector3 m_localScale; diff --git a/KREngine/KREngine/Classes/KRParticleSystem.h b/KREngine/KREngine/Classes/KRParticleSystem.h index 35bf241..9da436b 100644 --- a/KREngine/KREngine/Classes/KRParticleSystem.h +++ b/KREngine/KREngine/Classes/KRParticleSystem.h @@ -19,6 +19,13 @@ public: virtual void loadXML(tinyxml2::XMLElement *e); virtual tinyxml2::XMLElement *saveXML( tinyxml2::XMLNode *parent); + virtual KRAABB getBounds() = 0; + +#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; +#endif + protected: KRParticleSystem(KRScene &scene, std::string name); private: diff --git a/KREngine/KREngine/Classes/KRParticleSystemBrownian.cpp b/KREngine/KREngine/Classes/KRParticleSystemBrownian.cpp index 439e7dc..fced613 100644 --- a/KREngine/KREngine/Classes/KRParticleSystemBrownian.cpp +++ b/KREngine/KREngine/Classes/KRParticleSystemBrownian.cpp @@ -7,10 +7,13 @@ // #include "KRParticleSystemBrownian.h" +#include "KRAABB.h" +#include "KRTexture.h" +#include "KRContext.h" KRParticleSystemBrownian::KRParticleSystemBrownian(KRScene &scene, std::string name) : KRParticleSystem(scene, name) { - + m_particlesAbsoluteTime = 0.0f; } KRParticleSystemBrownian::~KRParticleSystemBrownian() @@ -35,17 +38,60 @@ tinyxml2::XMLElement *KRParticleSystemBrownian::saveXML( tinyxml2::XMLNode *pare } +KRAABB KRParticleSystemBrownian::getBounds() +{ + return KRAABB(-KRVector3::One(), KRVector3::One(), getModelMatrix()); +} + +void KRParticleSystemBrownian::physicsUpdate(float deltaTime) +{ + KRParticleSystem::physicsUpdate(deltaTime); + m_particlesAbsoluteTime += 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) { + + + KRNode::render(pCamera, pContext, viewport, pShadowViewports, lightDirection, shadowDepthTextures, cShadowBuffers, renderPass); + + if(renderPass == KRNode::RENDER_PASS_ADDITIVE_PARTICLES) { + float lod_coverage = getBounds().coverage(viewport.getViewProjectionMatrix(), viewport.getSize()); // This also checks the view frustrum culling + if(lod_coverage > 0.0f) { + + + // Enable z-buffer test + GLDEBUG(glEnable(GL_DEPTH_TEST)); + GLDEBUG(glDepthRangef(0.0, 1.0)); + + 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); + + int particle_count = 10000; + + if(pParticleShader->bind(viewport, pShadowViewports, getModelMatrix(), lightDirection, shadowDepthTextures, cShadowBuffers, KRNode::RENDER_PASS_ADDITIVE_PARTICLES)) { + GLDEBUG(glUniform1f( + pParticleShader->m_uniforms[KRShader::KRENGINE_UNIFORM_FLARE_SIZE], + 1.0f + )); + + m_pContext->getModelManager()->bindVBO((void *)m_pContext->getModelManager()->getRandomParticles(), particle_count * 3 * sizeof(KRModelManager::RandomParticleVertexData), true, false, false, true, false); + GLDEBUG(glDrawArrays(GL_TRIANGLES, 0, particle_count*3)); + } + } + } +} + +#endif + // -// m_particlesAbsoluteTime += deltaTime; + // -// // Enable z-buffer test -// GLDEBUG(glEnable(GL_DEPTH_TEST)); -// GLDEBUG(glDepthRangef(0.0, 1.0)); -// -// KRTexture *pParticleTexture = m_pContext->getTextureManager()->getTexture("flare"); -// m_pContext->getTextureManager()->selectTexture(0, pParticleTexture, 2048); -// -// KRShader *pParticleShader = m_pContext->getShaderManager()->getShader("particle", this, false, false, false, 0, false, false, false, false, false, false, false, false, false, false, false, false, false, KRNode::RENDER_PASS_ADDITIVE_PARTICLES); + // // KRMat4 particleModelMatrix = KRMat4(); //// particleModelMatrix.scale(particleBlockScale); diff --git a/KREngine/KREngine/Classes/KRParticleSystemBrownian.h b/KREngine/KREngine/Classes/KRParticleSystemBrownian.h index 3c3d568..202fe46 100644 --- a/KREngine/KREngine/Classes/KRParticleSystemBrownian.h +++ b/KREngine/KREngine/Classes/KRParticleSystemBrownian.h @@ -19,8 +19,20 @@ public: virtual std::string getElementName(); virtual void loadXML(tinyxml2::XMLElement *e); virtual tinyxml2::XMLElement *saveXML( tinyxml2::XMLNode *parent); -private: + + virtual KRAABB getBounds(); + + +#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); +#endif + + + virtual void physicsUpdate(float deltaTime); +private: + float m_particlesAbsoluteTime; }; #endif diff --git a/KREngine/KREngine/Classes/KRPointLight.cpp b/KREngine/KREngine/Classes/KRPointLight.cpp index fed4684..00b8ba9 100644 --- a/KREngine/KREngine/Classes/KRPointLight.cpp +++ b/KREngine/KREngine/Classes/KRPointLight.cpp @@ -43,9 +43,9 @@ KRAABB KRPointLight::getBounds() { #if TARGET_OS_IPHONE -void KRPointLight::render(KRCamera *pCamera, KRContext *pContext, const KRViewport &viewport, KRVector3 &lightDirection, KRMat4 *pShadowMatrices, GLuint *shadowDepthTextures, int cShadowBuffers, KRNode::RenderPass renderPass) { +void KRPointLight::render(KRCamera *pCamera, KRContext *pContext, const KRViewport &viewport, const KRViewport *pShadowViewports, KRVector3 &lightDirection, GLuint *shadowDepthTextures, int cShadowBuffers, KRNode::RenderPass renderPass) { - KRLight::render(pCamera, pContext, viewport, lightDirection, pShadowMatrices, shadowDepthTextures, cShadowBuffers, renderPass); + KRLight::render(pCamera, pContext, viewport, pShadowViewports, lightDirection, shadowDepthTextures, cShadowBuffers, renderPass); bool bVisualize = renderPass == KRNode::RENDER_PASS_FORWARD_TRANSPARENT && pCamera->bShowDeferred; @@ -69,7 +69,7 @@ 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, sphereModelMatrix, lightDirection, pShadowMatrices, shadowDepthTextures, 0, renderPass)) { + if(pShader->bind(viewport, pShadowViewports, sphereModelMatrix, lightDirection, shadowDepthTextures, 0, renderPass)) { diff --git a/KREngine/KREngine/Classes/KRPointLight.h b/KREngine/KREngine/Classes/KRPointLight.h index 0f75460..2b75764 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, KRVector3 &lightDirection, KRMat4 *pShadowMatrices, GLuint *shadowDepthTextures, int cShadowBuffers, KRNode::RenderPass renderPass); + virtual void render(KRCamera *pCamera, KRContext *pContext, const KRViewport &viewport, const KRViewport *pShadowViewports, KRVector3 &lightDirection, GLuint *shadowDepthTextures, int cShadowBuffers, KRNode::RenderPass renderPass); #endif private: diff --git a/KREngine/KREngine/Classes/KRScene.cpp b/KREngine/KREngine/Classes/KRScene.cpp index 3c4096f..1cdb1b5 100644 --- a/KREngine/KREngine/Classes/KRScene.cpp +++ b/KREngine/KREngine/Classes/KRScene.cpp @@ -57,7 +57,7 @@ KRScene::~KRScene() { #if TARGET_OS_IPHONE -void KRScene::render(KRCamera *pCamera, std::set &visibleBounds, KRContext *pContext, const KRViewport &viewport, KRVector3 &lightDirection, KRMat4 *pShadowMatrices, GLuint *shadowDepthTextures, int cShadowBuffers, KRNode::RenderPass renderPass, std::set &newVisibleBounds) { +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) { updateOctree(); pCamera->setSkyBox(m_skyBoxName); // This is temporary until the camera is moved into the scene graph @@ -118,10 +118,10 @@ void KRScene::render(KRCamera *pCamera, std::set &visibleBounds, KRConte 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, forward_render_light_direction, pShadowMatrices, shadowDepthTextures, cShadowBuffers, renderPass, newRemainingOctrees, newRemainingOctreesTestResults, remainingOctreesTestResultsOnly, newVisibleBounds, false, false); + render(*octree_itr, visibleBounds, pCamera, pContext, viewport, pShadowViewports, forward_render_light_direction, shadowDepthTextures, cShadowBuffers, renderPass, newRemainingOctrees, newRemainingOctreesTestResults, remainingOctreesTestResultsOnly, newVisibleBounds, false, false); } for(std::vector::iterator octree_itr = remainingOctreesTestResults.begin(); octree_itr != remainingOctreesTestResults.end(); octree_itr++) { - render(*octree_itr, visibleBounds, pCamera, pContext, viewport, forward_render_light_direction, pShadowMatrices, shadowDepthTextures, cShadowBuffers, renderPass, newRemainingOctrees, newRemainingOctreesTestResults, remainingOctreesTestResultsOnly, newVisibleBounds, true, false); + render(*octree_itr, visibleBounds, pCamera, pContext, viewport, pShadowViewports, forward_render_light_direction, shadowDepthTextures, cShadowBuffers, renderPass, newRemainingOctrees, newRemainingOctreesTestResults, remainingOctreesTestResultsOnly, newVisibleBounds, true, false); } remainingOctrees = newRemainingOctrees; remainingOctreesTestResults = newRemainingOctreesTestResults; @@ -130,16 +130,16 @@ void KRScene::render(KRCamera *pCamera, std::set &visibleBounds, KRConte 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, forward_render_light_direction, pShadowMatrices, shadowDepthTextures, cShadowBuffers, renderPass, newRemainingOctrees, newRemainingOctreesTestResults, remainingOctreesTestResultsOnly, newVisibleBounds, true, true); + 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, lightDirection, pShadowMatrices, shadowDepthTextures, cShadowBuffers, renderPass); + (*itr)->render(pCamera, pContext, viewport, pShadowViewports, lightDirection, shadowDepthTextures, cShadowBuffers, renderPass); } } -void KRScene::render(KROctreeNode *pOctreeNode, std::set &visibleBounds, KRCamera *pCamera, KRContext *pContext, const KRViewport &viewport, KRVector3 &lightDirection, KRMat4 *pShadowMatrices, GLuint *shadowDepthTextures, int cShadowBuffers, KRNode::RenderPass renderPass, std::vector &remainingOctrees, std::vector &remainingOctreesTestResults, std::vector &remainingOctreesTestResultsOnly, std::set &newVisibleBounds, bool bOcclusionResultsPass, bool bOcclusionTestResultsOnly) +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) { if(pOctreeNode) { @@ -152,7 +152,7 @@ void KRScene::render(KROctreeNode *pOctreeNode, std::set &visibleBounds, GLDEBUG(glGetQueryObjectuivEXT(pOctreeNode->m_occlusionQuery, GL_QUERY_RESULT_EXT, ¶ms)); if(params) { newVisibleBounds.insert(octreeBounds); // Record the actual tests that succeeded during this frame - visibleBounds.insert(octreeBounds); // Update the list of tests that we won't repeat for subsequent passes during this frame +// visibleBounds.insert(octreeBounds); // Update the list of tests that we won't repeat for subsequent passes during this frame if(!bOcclusionTestResultsOnly) { // Schedule a pass to perform the rendering remainingOctrees.push_back(pOctreeNode); @@ -181,7 +181,7 @@ void KRScene::render(KROctreeNode *pOctreeNode, std::set &visibleBounds, bVisible = octreeBounds.intersects(cameraExtents); if(bVisible) { newVisibleBounds.insert(octreeBounds); // Record the actual tests that succeeded during this frame - visibleBounds.insert(octreeBounds); // Update the list of tests that we won't repeat for subsequent passes during this frame +// visibleBounds.insert(octreeBounds); // Update the list of tests that we won't repeat for subsequent passes during this frame bNeedOcclusionTest = false; } } @@ -239,7 +239,7 @@ void KRScene::render(KROctreeNode *pOctreeNode, std::set &visibleBounds, GLDEBUG(glDepthMask(GL_FALSE)); } - if(pVisShader->bind(viewport, matModel, lightDirection, pShadowMatrices, shadowDepthTextures, 0, KRNode::RENDER_PASS_FORWARD_TRANSPARENT)) { + if(pVisShader->bind(viewport, pShadowViewports, matModel, lightDirection, shadowDepthTextures, 0, KRNode::RENDER_PASS_FORWARD_TRANSPARENT)) { GLDEBUG(glDrawArrays(GL_TRIANGLE_STRIP, 0, 14)); } @@ -276,13 +276,13 @@ void KRScene::render(KROctreeNode *pOctreeNode, std::set &visibleBounds, 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, lightDirection, pShadowMatrices, shadowDepthTextures, cShadowBuffers, renderPass); + (*itr)->render(pCamera, pContext, viewport, pShadowViewports, lightDirection, shadowDepthTextures, cShadowBuffers, renderPass); } const int *childOctreeOrder = renderPass == KRNode::RENDER_PASS_FORWARD_TRANSPARENT || renderPass == KRNode::RENDER_PASS_ADDITIVE_PARTICLES ? viewport.getBackToFrontOrder() : viewport.getFrontToBackOrder(); for(int i=0; i<8; i++) { - render(pOctreeNode->getChildren()[childOctreeOrder[i]], visibleBounds, pCamera, pContext, viewport, lightDirection, pShadowMatrices, shadowDepthTextures, cShadowBuffers, renderPass, remainingOctrees, remainingOctreesTestResults, remainingOctreesTestResultsOnly, newVisibleBounds, false, false); + render(pOctreeNode->getChildren()[childOctreeOrder[i]], visibleBounds, pCamera, pContext, viewport, pShadowViewports, lightDirection, shadowDepthTextures, cShadowBuffers, renderPass, remainingOctrees, remainingOctreesTestResults, remainingOctreesTestResultsOnly, newVisibleBounds, false, false); } } } @@ -360,13 +360,17 @@ KRDirectionalLight *KRScene::getFirstDirectionalLight() void KRScene::notify_sceneGraphCreate(KRNode *pNode) { m_nodeTree.add(pNode); + if(pNode->hasPhysics()) { + m_physicsNodes.erase(pNode); + } // m_newNodes.insert(pNode); } void KRScene::notify_sceneGraphDelete(KRNode *pNode) { m_nodeTree.remove(pNode); -// + m_physicsNodes.erase(pNode); +// // m_modifiedNodes.erase(pNode); // if(!m_newNodes.erase(pNode)) { // m_nodeTree.remove(pNode); @@ -390,6 +394,14 @@ void KRScene::updateOctree() // m_newNodes.clear(); // m_modifiedNodes.clear(); } + +void KRScene::physicsUpdate(float deltaTime) +{ + for(std::set::iterator itr=m_physicsNodes.begin(); itr != m_physicsNodes.end(); itr++) { + (*itr)->physicsUpdate(deltaTime); + } +} + #if TARGET_OS_IPHONE #endif diff --git a/KREngine/KREngine/Classes/KRScene.h b/KREngine/KREngine/Classes/KRScene.h index fbf1804..ba58522 100644 --- a/KREngine/KREngine/Classes/KRScene.h +++ b/KREngine/KREngine/Classes/KRScene.h @@ -62,9 +62,9 @@ public: #if TARGET_OS_IPHONE - void render(KRCamera *pCamera, std::set &visibleBounds, KRContext *pContext, const KRViewport &viewport, KRVector3 &lightDirection, KRMat4 *pShadowMatrices, GLuint *shadowDepthTextures, int cShadowBuffers, KRNode::RenderPass renderPass, std::set &newVisibleBounds); + 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(KROctreeNode *pOctreeNode, std::set &visibleBounds, KRCamera *pCamera, KRContext *pContext, const KRViewport &viewport, KRVector3 &lightDirection, KRMat4 *pShadowMatrices, GLuint *shadowDepthTextures, int cShadowBuffers, KRNode::RenderPass renderPass, std::vector &remainingOctrees, std::vector &remainingOctreesTestResults, std::vector &remainingOctreesTestResultsOnly, std::set &newVisibleBounds, bool bOcclusionResultsPass, bool bOcclusionTestResultsOnly); + 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); #endif @@ -75,6 +75,8 @@ public: void notify_sceneGraphDelete(KRNode *pNode); void notify_sceneGraphModify(KRNode *pNode); + void physicsUpdate(float deltaTime); + private: KRContext *m_pContext; KRDirectionalLight *findFirstDirectionalLight(KRNode &node); @@ -85,6 +87,10 @@ private: std::set m_newNodes; std::set m_modifiedNodes; + + + std::set m_physicsNodes; + KROctree m_nodeTree; void updateOctree(); diff --git a/KREngine/KREngine/Classes/KRShader.cpp b/KREngine/KREngine/Classes/KRShader.cpp index e2c0cae..2ba15fd 100644 --- a/KREngine/KREngine/Classes/KRShader.cpp +++ b/KREngine/KREngine/Classes/KRShader.cpp @@ -136,6 +136,7 @@ KRShader::KRShader(char *szKey, std::string options, std::string vertShaderSourc GLDEBUG(m_uniforms[KRENGINE_UNIFORM_MODEL_INVERSE_TRANSPOSE] = glGetUniformLocation(m_iProgram, "model_inverse_transpose_matrix")); GLDEBUG(m_uniforms[KRENGINE_UNIFORM_MODEL_VIEW] = glGetUniformLocation(m_iProgram, "model_view_matrix")); GLDEBUG(m_uniforms[KRENGINE_UNIFORM_MODEL_MATRIX] = glGetUniformLocation(m_iProgram, "model_matrix")); + GLDEBUG(m_uniforms[KRENGINE_UNIFORM_PROJECTION_MATRIX] = glGetUniformLocation(m_iProgram, "projection_matrix")); GLDEBUG(m_uniforms[KRENGINE_UNIFORM_SHADOWMVP1] = glGetUniformLocation(m_iProgram, "shadow_mvp1")); GLDEBUG(m_uniforms[KRENGINE_UNIFORM_SHADOWMVP2] = glGetUniformLocation(m_iProgram, "shadow_mvp2")); @@ -167,6 +168,7 @@ KRShader::KRShader(char *szKey, std::string options, std::string vertShaderSourc GLDEBUG(m_uniforms[KRENGINE_UNIFORM_GBUFFER_DEPTH] = glGetUniformLocation(m_iProgram, "gbuffer_depth")); GLDEBUG(m_uniforms[KRENGINE_UNIFORM_DEPTH_FRAME] = glGetUniformLocation(m_iProgram, "depthFrame")); GLDEBUG(m_uniforms[KRENGINE_UNIFORM_RENDER_FRAME] = glGetUniformLocation(m_iProgram, "renderFrame")); + GLDEBUG(m_uniforms[KRENGINE_UNIFORM_SLICE_DEPTH_SCALE] = glGetUniformLocation(m_iProgram, "slice_depth_scale")); } } catch(...) { @@ -201,7 +203,7 @@ KRShader::~KRShader() { #if TARGET_OS_IPHONE -bool KRShader::bind(const KRViewport &viewport, const KRMat4 &matModel, const KRVector3 &lightDirection, const KRMat4 *pShadowMatrices, const GLuint *shadowDepthTextures, const int &cShadowBuffers, const KRNode::RenderPass &renderPass) { +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) { if(m_iProgram == 0) { return false; } @@ -235,7 +237,7 @@ bool KRShader::bind(const KRViewport &viewport, const KRMat4 &matModel, const KR } } - if(m_uniforms[KRShader::KRENGINE_UNIFORM_LIGHT_POSITION_VIEW_SPACE] != -1 || m_uniforms[KRENGINE_UNIFORM_MODEL_VIEW_INVERSE_TRANSPOSE] != -1) { + if(m_uniforms[KRShader::KRENGINE_UNIFORM_LIGHT_POSITION_VIEW_SPACE] != -1 || m_uniforms[KRENGINE_UNIFORM_MODEL_VIEW_INVERSE_TRANSPOSE] != -1 || m_uniforms[KRShader::KRENGINE_UNIFORM_MODEL_VIEW] != -1) { KRMat4 matModelView = matModel * viewport.getViewMatrix(); matModelView.setUniform(m_uniforms[KRShader::KRENGINE_UNIFORM_MODEL_VIEW]); @@ -280,6 +282,9 @@ bool KRShader::bind(const KRViewport &viewport, const KRMat4 &matModel, const KR } matModel.setUniform(m_uniforms[KRShader::KRENGINE_UNIFORM_MODEL_MATRIX]); + if(m_uniforms[KRENGINE_UNIFORM_PROJECTION_MATRIX] != -1) { + viewport.getProjectionMatrix().setUniform(m_uniforms[KRENGINE_UNIFORM_PROJECTION_MATRIX]); + } if(m_uniforms[KRENGINE_UNIFORM_VIEWPORT] != -1) { GLDEBUG(glUniform4f( @@ -293,7 +298,10 @@ bool KRShader::bind(const KRViewport &viewport, const KRMat4 &matModel, const KR // Bind the shadowmap space matrices for(int iShadow=0; iShadow < cShadowBuffers; iShadow++) { - pShadowMatrices[iShadow].setUniform(m_uniforms[KRENGINE_UNIFORM_SHADOWMVP1 + iShadow]); + KRMat4 matBias; + matBias.translate(1.0, 1.0, 1.0); + matBias.scale(0.5); + (matModel * pShadowViewports[iShadow].getViewProjectionMatrix() * matBias).setUniform(m_uniforms[KRENGINE_UNIFORM_SHADOWMVP1 + iShadow]); } // Sets the diffuseTexture variable to the first texture unit diff --git a/KREngine/KREngine/Classes/KRShader.h b/KREngine/KREngine/Classes/KRShader.h index f005f99..ff0f65a 100644 --- a/KREngine/KREngine/Classes/KRShader.h +++ b/KREngine/KREngine/Classes/KRShader.h @@ -56,7 +56,7 @@ public: #if TARGET_OS_IPHONE - bool bind(const KRViewport &viewport, const KRMat4 &matModel, const KRVector3 &lightDirection, const KRMat4 *pShadowMatrices, const GLuint *shadowDepthTextures, const int &cShadowBuffers, const KRNode::RenderPass &renderPass); + bool bind(const KRViewport &viewport, const KRViewport *pShadowViewports, const KRMat4 &matModel, const KRVector3 &lightDirection, const GLuint *shadowDepthTextures, const int &cShadowBuffers, const KRNode::RenderPass &renderPass); #endif @@ -96,6 +96,7 @@ public: KRENGINE_UNIFORM_MODEL_INVERSE_TRANSPOSE, KRENGINE_UNIFORM_MODEL_VIEW, KRENGINE_UNIFORM_MODEL_MATRIX, + KRENGINE_UNIFORM_PROJECTION_MATRIX, KRENGINE_UNIFORM_CAMERAPOS_MODEL_SPACE, KRENGINE_UNIFORM_VIEWPORT, @@ -126,6 +127,8 @@ public: KRENGINE_UNIFORM_DEPTH_FRAME, KRENGINE_UNIFORM_RENDER_FRAME, + KRENGINE_UNIFORM_SLICE_DEPTH_SCALE, + KRENGINE_NUM_UNIFORMS }; GLint m_uniforms[KRENGINE_NUM_UNIFORMS]; diff --git a/KREngine/KREngine/Classes/KRViewport.cpp b/KREngine/KREngine/Classes/KRViewport.cpp index f64a489..f0e7e24 100644 --- a/KREngine/KREngine/Classes/KRViewport.cpp +++ b/KREngine/KREngine/Classes/KRViewport.cpp @@ -151,3 +151,15 @@ void KRViewport::calculateDerivedValues() m_backToFrontOrder[i] = m_frontToBackOrder[7-i]; } } + + +const std::set &KRViewport::getVisibleBounds() +{ + return m_visibleBounds; +} + +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 1b130bc..097b635 100644 --- a/KREngine/KREngine/Classes/KRViewport.h +++ b/KREngine/KREngine/Classes/KRViewport.h @@ -11,6 +11,7 @@ #include "KRVector2.h" #include "KRMat4.h" +#include "KRAABB.h" class KRViewport { public: @@ -35,6 +36,9 @@ public: // Overload assignment operator KRViewport& operator=(const KRViewport &v); + const std::set &getVisibleBounds(); + void setVisibleBounds(const std::set visibleBounds); + private: KRVector2 m_size; KRMat4 m_matView; @@ -52,6 +56,8 @@ private: int m_backToFrontOrder[8]; void calculateDerivedValues(); + + std::set m_visibleBounds; // AABB's that output fragments in the last frame }; #endif diff --git a/KREngine/KREngine/Classes/KRVolumetricFog.cpp b/KREngine/KREngine/Classes/KRVolumetricFog.cpp new file mode 100644 index 0000000..80c7ef8 --- /dev/null +++ b/KREngine/KREngine/Classes/KRVolumetricFog.cpp @@ -0,0 +1,174 @@ +// +// KRVolumetricFog.cpp +// KREngine +// +// 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. +// + +#include +#import "KRVolumetricFog.h" +#import "KRContext.h" +#import "KRModel.h" +#import "KRShader.h" +#include + +KRVolumetricFog::KRVolumetricFog(KRScene &scene, std::string instance_name, std::string model_name, float lod_min_coverage) : KRNode(scene, instance_name) { + m_model_name = model_name; + m_min_lod_coverage = lod_min_coverage; +} + +KRVolumetricFog::~KRVolumetricFog() { + +} + +std::string KRVolumetricFog::getElementName() { + return "volumetric_fog"; +} + +tinyxml2::XMLElement *KRVolumetricFog::saveXML( tinyxml2::XMLNode *parent) +{ + tinyxml2::XMLElement *e = KRNode::saveXML(parent); + e->SetAttribute("mesh_name", m_model_name.c_str()); + e->SetAttribute("lod_min_coverage", m_min_lod_coverage); + return e; +} + +void KRVolumetricFog::loadModel() { + if(m_models.size() == 0) { + m_models = m_pContext->getModelManager()->getModel(m_model_name.c_str()); // The model manager returns the LOD levels in sorted order, with the highest detail first + if(m_models.size() > 0) { + getScene().notify_sceneGraphModify(this); + } + // if(m_pModel == NULL) { + // fprintf(stderr, "KREngine - Model not found: %s\n", m_model_name.c_str()); + // } + } +} + +#if TARGET_OS_IPHONE + +void KRVolumetricFog::render(KRCamera *pCamera, KRContext *pContext, const KRViewport &viewport, const KRViewport *pShadowViewports, KRVector3 &lightDirection, GLuint *shadowDepthTextures, int cShadowBuffers, KRNode::RenderPass renderPass) { + + + KRNode::render(pCamera, pContext, viewport, pShadowViewports, lightDirection, shadowDepthTextures, cShadowBuffers, renderPass); + + if(renderPass == KRNode::RENDER_PASS_ADDITIVE_PARTICLES) { + // Don't render meshes on second pass of the deferred lighting renderer, as only lights will be applied + + loadModel(); + + KRAABB bounds = getBounds(); + + if(m_models.size() > 0 && cShadowBuffers > 0) { + float lod_coverage = bounds.coverage(viewport.getViewProjectionMatrix(), viewport.getSize()); // This also checks the view frustrum culling + if(lod_coverage > m_min_lod_coverage) { + + // ---===--- Select the best LOD model based on screen coverage ---===--- + std::vector::iterator itr=m_models.begin(); + KRModel *pModel = *itr++; + + while(itr != m_models.end()) { + KRModel *pLODModel = *itr++; + if((float)pLODModel->getLODCoverage() / 100.0f > lod_coverage && pLODModel->getLODCoverage() < pModel->getLODCoverage()) { + pModel = pLODModel; + } else { + break; + } + } + + + KRShader *pFogShader = m_pContext->getShaderManager()->getShader("volumetric_fog_inside", pCamera, false, false, false, 0, false, false, false, false, false, false, false, false, false, false, false, false, false, KRNode::RENDER_PASS_FORWARD_TRANSPARENT); + + if(pFogShader->bind(viewport, pShadowViewports, getModelMatrix(), lightDirection, shadowDepthTextures, cShadowBuffers, KRNode::RENDER_PASS_ADDITIVE_PARTICLES)) { + + KRAABB viewSpaceBounds = KRAABB(bounds.min, bounds.max, viewport.getViewProjectionMatrix()); + + // Enable z-buffer test + GLDEBUG(glEnable(GL_DEPTH_TEST)); + GLDEBUG(glDepthFunc(GL_LEQUAL)); + GLDEBUG(glDepthRangef(0.0, 1.0)); + + // Enable backface culling + GLDEBUG(glCullFace(GL_BACK)); + GLDEBUG(glEnable(GL_CULL_FACE)); + + + int slice_count = 50; + + float slice_near = -100.0; + float slice_far = -1000.0; + float slice_spacing = (slice_far - slice_near) / slice_count; + + KRVector2(slice_near, slice_spacing).setUniform(pFogShader->m_uniforms[KRShader::KRENGINE_UNIFORM_SLICE_DEPTH_SCALE]); + + m_pContext->getModelManager()->bindVBO((void *)m_pContext->getModelManager()->getVolumetricLightingVertexes(), slice_count * 6 * sizeof(KRModelManager::VolumetricLightingVertexData), true, false, false, false, false); + GLDEBUG(glDrawArrays(GL_TRIANGLES, 0, slice_count*6)); + + /* + + + float slice_near = viewSpaceBounds.max.z; + float slice_far = viewSpaceBounds.min.z; + slice_near = -1.0; + slice_far = 1.0; + float slice_spacing = (slice_far - slice_near) / slice_count; + // slice_spacing = 1.0f / slice_count; +// slice_near = 0.0f; + for(int slice=0; slice < slice_count; slice++) { + KRVector2(slice_near + slice * slice_spacing, slice_spacing).setUniform(pFogShader->m_uniforms[KRShader::KRENGINE_UNIFORM_SLICE_DEPTH_SCALE]); + int mesh_count = pModel->getSubmeshes().size(); + for(int iMesh=0; iMesh < mesh_count; iMesh++) { + pModel->renderSubmesh(iMesh); + } + } + */ + + } + } + } + } +} + +#endif + +bool KRVolumetricFog::hasTransparency() { + if(m_models.size() > 0) { + return m_models[0]->hasTransparency(); + } else { + return false; + } +} + +KRAABB KRVolumetricFog::getBounds() { + loadModel(); + if(m_models.size() > 0) { + return KRAABB(m_models[0]->getMinPoint(), m_models[0]->getMaxPoint(), getModelMatrix()); + } else { + return KRAABB::Infinite(); + } +} + diff --git a/KREngine/KREngine/Classes/KRVolumetricFog.h b/KREngine/KREngine/Classes/KRVolumetricFog.h new file mode 100644 index 0000000..89473ff --- /dev/null +++ b/KREngine/KREngine/Classes/KRVolumetricFog.h @@ -0,0 +1,79 @@ +// +// KRVolumetricFog.h +// KREngine +// +// 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. +// + + + +#import "KREngine-common.h" + +#ifndef KRVOLUMETRICFOG_H +#define KRVOLUMETRICFOG_H + +#import "KRModel.h" +#import "KRMat4.h" +#import "KRVector3.h" +#import "KRVolumetricFog.h" +#import "KRCamera.h" +#import "KRModelManager.h" +#import "KRNode.h" +#import "KRContext.h" +#import "KRModel.h" +#import "KRTexture.h" + +class KRVolumetricFog : public KRNode { + +public: + KRVolumetricFog(KRScene &scene, std::string instance_name, std::string model_name, float lod_min_coverage); + virtual ~KRVolumetricFog(); + + virtual std::string getElementName(); + virtual tinyxml2::XMLElement *saveXML( tinyxml2::XMLNode *parent); + +#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); +#endif + + bool hasTransparency(); + + + virtual KRAABB getBounds(); + +private: + std::vector m_models; + std::string m_model_name; + + + float m_min_lod_coverage; + void loadModel(); +}; + + +#endif diff --git a/KREngine/KREngine/Shaders/ObjectShader.fsh b/KREngine/KREngine/Shaders/ObjectShader.fsh index 9d434ea..2baefe1 100644 --- a/KREngine/KREngine/Shaders/ObjectShader.fsh +++ b/KREngine/KREngine/Shaders/ObjectShader.fsh @@ -5,7 +5,7 @@ // // 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. @@ -25,6 +25,8 @@ // or implied, of Kearwood Gilbert. // +#extension GL_EXT_shadow_samplers : require + #if ENABLE_PER_PIXEL == 1 || GBUFFER_PASS == 1 uniform mediump float material_shininess; #if HAS_NORMAL_MAP == 1 @@ -99,7 +101,11 @@ #if SHADOW_QUALITY >= 1 - uniform sampler2D shadowTexture1; + #ifdef GL_EXT_shadow_samplers + uniform sampler2DShadow shadowTexture1; + #else + uniform sampler2D shadowTexture1; + #endif varying highp vec4 shadowMapCoord1; #endif @@ -212,62 +218,72 @@ void main() #endif } - #if SHADOW_QUALITY == 1 - highp float shadowMapDepth = 1.0; - highp float vertexShadowDepth = 1.0; - highp vec2 shadowMapPos = ((shadowMapCoord1 / shadowMapCoord1.w + 1.0) / 2.0).st; - - if(shadowMapCoord1.x >= -1.0 && shadowMapCoord1.x <= 1.0 && shadowMapCoord1.y >= -1.0 && shadowMapCoord1.y <= 1.0 && shadowMapCoord1.z >= 0.0 && shadowMapCoord1.z <= 1.0) { - #if DEBUG_PSSM == 1 - diffuseMaterial = diffuseMaterial * vec4(0.75, 0.75, 0.5, 1.0) + vec4(0.0, 0.0, 0.5, 0.0); + #ifdef GL_EXT_shadow_samplers + #if SHADOW_QUALITY == 1 + lowp float shadow = shadow2DProjEXT(shadowTexture1, shadowMapCoord1); + lamberFactor *= shadow; + specularFactor *= shadow; #endif - shadowMapDepth = texture2D(shadowTexture1, shadowMapPos).z; - vertexShadowDepth = ((shadowMapCoord1 / shadowMapCoord1.w + 1.0) / 2.0).z; - } - #endif + #else + + #if SHADOW_QUALITY == 1 - #if SHADOW_QUALITY >= 2 - - highp float shadowMapDepth = 1.0; - highp float vertexShadowDepth = 1.0; - - if(shadowMapCoord1.x >= -1.0 && shadowMapCoord1.x <= 1.0 && shadowMapCoord1.y >= -1.0 && shadowMapCoord1.y <= 1.0 && shadowMapCoord1.z >= 0.0 && shadowMapCoord1.z <= 1.0) { - #if DEBUG_PSSM == 1 - diffuseMaterial = diffuseMaterial * vec4(0.75, 0.75, 0.5, 1.0) + vec4(0.0, 0.0, 0.5, 0.0); - #endif - highp vec2 shadowMapPos = ((shadowMapCoord1 / shadowMapCoord1.w + 1.0) / 2.0).st; - shadowMapDepth = texture2D(shadowTexture1, shadowMapPos).z; - vertexShadowDepth = ((shadowMapCoord1 / shadowMapCoord1.w + 1.0) / 2.0).z; - } else if(shadowMapCoord2.s >= -1.0 && shadowMapCoord2.s <= 1.0 && shadowMapCoord2.t >= -1.0 && shadowMapCoord2.t <= 1.0 && shadowMapCoord2.z >= 0.0 && shadowMapCoord2.z <= 1.0) { - #if DEBUG_PSSM == 1 - diffuseMaterial = diffuseMaterial * vec4(0.75, 0.50, 0.75, 1.0) + vec4(0.0, 0.5, 0.0, 0.0); - #endif - highp vec2 shadowMapPos = ((shadowMapCoord2 / shadowMapCoord2.w + 1.0) / 2.0).st; - shadowMapDepth = texture2D(shadowTexture2, shadowMapPos).z; - vertexShadowDepth = ((shadowMapCoord2 / shadowMapCoord2.w + 1.0) / 2.0).z; - } - #if SHADOW_QUALITY >= 3 - else if(shadowMapCoord3.s >= -1.0 && shadowMapCoord3.s <= 1.0 && shadowMapCoord3.t >= -1.0 && shadowMapCoord3.t <= 1.0 && shadowMapCoord3.z >= 0.0 && shadowMapCoord3.z <= 1.0) { + highp float shadowMapDepth = 1.0; + highp float vertexShadowDepth = 1.0; + highp vec2 shadowMapPos = (shadowMapCoord1 / shadowMapCoord1.w).st; + + if(shadowMapCoord1.x >= -1.0 && shadowMapCoord1.x <= 1.0 && shadowMapCoord1.y >= -1.0 && shadowMapCoord1.y <= 1.0 && shadowMapCoord1.z >= 0.0 && shadowMapCoord1.z <= 1.0) { #if DEBUG_PSSM == 1 - diffuseMaterial = diffuseMaterial * vec4(0.50, 0.75, 0.75, 1.0) + vec4(0.5, 0.0, 0.0, 0.0); + diffuseMaterial = diffuseMaterial * vec4(0.75, 0.75, 0.5, 1.0) + vec4(0.0, 0.0, 0.5, 0.0); #endif - highp vec2 shadowMapPos = ((shadowMapCoord3 / shadowMapCoord3.w + 1.0) / 2.0).st; - shadowMapDepth = texture2D(shadowTexture3, shadowMapPos).z; - vertexShadowDepth = ((shadowMapCoord3 / shadowMapCoord3.w + 1.0) / 2.0).z; - } - + shadowMapDepth = texture2D(shadowTexture1, shadowMapPos).z; + vertexShadowDepth = (shadowMapCoord1 / shadowMapCoord1.w).z; + } #endif - #endif + + #if SHADOW_QUALITY >= 2 + + highp float shadowMapDepth = 1.0; + highp float vertexShadowDepth = 1.0; - #if SHADOW_QUALITY >= 1 - if(vertexShadowDepth >= shadowMapDepth && shadowMapDepth < 1.0) { - #if GBUFFER_PASS == 3 - lamberFactor = vec3(0.0); - #else - lamberFactor = 0.0; + if(shadowMapCoord1.x >= -1.0 && shadowMapCoord1.x <= 1.0 && shadowMapCoord1.y >= -1.0 && shadowMapCoord1.y <= 1.0 && shadowMapCoord1.z >= 0.0 && shadowMapCoord1.z <= 1.0) { + #if DEBUG_PSSM == 1 + diffuseMaterial = diffuseMaterial * vec4(0.75, 0.75, 0.5, 1.0) + vec4(0.0, 0.0, 0.5, 0.0); + #endif + highp vec2 shadowMapPos = (shadowMapCoord1 / shadowMapCoord1.w).st; + shadowMapDepth = texture2D(shadowTexture1, shadowMapPos).z; + vertexShadowDepth = (shadowMapCoord1 / shadowMapCoord1.w).z; + } else if(shadowMapCoord2.s >= -1.0 && shadowMapCoord2.s <= 1.0 && shadowMapCoord2.t >= -1.0 && shadowMapCoord2.t <= 1.0 && shadowMapCoord2.z >= 0.0 && shadowMapCoord2.z <= 1.0) { + #if DEBUG_PSSM == 1 + diffuseMaterial = diffuseMaterial * vec4(0.75, 0.50, 0.75, 1.0) + vec4(0.0, 0.5, 0.0, 0.0); + #endif + highp vec2 shadowMapPos = (shadowMapCoord2 / shadowMapCoord2.w).st; + shadowMapDepth = texture2D(shadowTexture2, shadowMapPos).z; + vertexShadowDepth = (shadowMapCoord2 / shadowMapCoord2.w).z; + } + #if SHADOW_QUALITY >= 3 + else if(shadowMapCoord3.s >= -1.0 && shadowMapCoord3.s <= 1.0 && shadowMapCoord3.t >= -1.0 && shadowMapCoord3.t <= 1.0 && shadowMapCoord3.z >= 0.0 && shadowMapCoord3.z <= 1.0) { + #if DEBUG_PSSM == 1 + diffuseMaterial = diffuseMaterial * vec4(0.50, 0.75, 0.75, 1.0) + vec4(0.5, 0.0, 0.0, 0.0); + #endif + highp vec2 shadowMapPos = (shadowMapCoord3 / shadowMapCoord3.w).st; + shadowMapDepth = texture2D(shadowTexture3, shadowMapPos).z; + vertexShadowDepth = (shadowMapCoord3 / shadowMapCoord3.w).z; + } + #endif - specularFactor = 0.0; - } + #endif + + #if SHADOW_QUALITY >= 1 + if(vertexShadowDepth >= shadowMapDepth && shadowMapDepth < 1.0) { + #if GBUFFER_PASS == 3 + lamberFactor = vec3(0.0); + #else + lamberFactor = 0.0; + #endif + specularFactor = 0.0; + } + #endif #endif #endif diff --git a/KREngine/KREngine/Shaders/volumetric_fog.fsh b/KREngine/KREngine/Shaders/volumetric_fog.fsh new file mode 100644 index 0000000..2d049f2 --- /dev/null +++ b/KREngine/KREngine/Shaders/volumetric_fog.fsh @@ -0,0 +1,33 @@ +// 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. +// + +//varying mediump vec2 texCoord; + +void main() +{ + gl_FragColor = vec4(0.0, 0.02, 0.02, 0.02); +} diff --git a/KREngine/KREngine/Shaders/volumetric_fog.vsh b/KREngine/KREngine/Shaders/volumetric_fog.vsh new file mode 100644 index 0000000..f75aa4f --- /dev/null +++ b/KREngine/KREngine/Shaders/volumetric_fog.vsh @@ -0,0 +1,62 @@ +// 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 mvp_matrix; // mvp_matrix is the result of multiplying the model, view, and projection matrices +//uniform highp mat4 model_view_matrix; +//uniform highp mat4 projection_matrix; +//uniform highp mat4 inv_projection_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 + +void main() +{ + // Transform position + /* + position = shadow_mvp1 * vec4(vertex_position,1.0); + */ +// gl_Position = mvp_matrix * vertex_position; + /* + // Pass UV co-ordinates + texCoord = vertex_uv.st; + */ + + +// highp vec4 p = model_view_matrix * vertex_position; +// p.z = slice_depth_scale.x; +// gl_Position = projection_matrix * p; + +// highp vec4 p = mvp_matrix * vertex_position; +// p = inv_projection_matrix * p; +// p = projection_matrix * p; +// gl_Position = p; + + + highp vec4 p = mvp_matrix * vertex_position; + p.z = slice_depth_scale.x * p.w; + gl_Position = p; +} diff --git a/KREngine/KREngine/Shaders/volumetric_fog_inside.fsh b/KREngine/KREngine/Shaders/volumetric_fog_inside.fsh new file mode 100644 index 0000000..ed1d3c9 --- /dev/null +++ b/KREngine/KREngine/Shaders/volumetric_fog_inside.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. +// + +//varying mediump vec2 texCoord; + +#extension GL_EXT_shadow_samplers : require + +varying highp 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); +} diff --git a/KREngine/KREngine/Shaders/volumetric_fog_inside.vsh b/KREngine/KREngine/Shaders/volumetric_fog_inside.vsh new file mode 100644 index 0000000..1942263 --- /dev/null +++ b/KREngine/KREngine/Shaders/volumetric_fog_inside.vsh @@ -0,0 +1,54 @@ +// 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 highp vec4 shadowMapCoord1; + +uniform highp mat4 projection_matrix; + +void main() +{ + +// gl_Position = vec4(vertex_position.x, vertex_position.y, slice_depth_scale.x + vertex_position.z * slice_depth_scale.y, 1.0); + + + 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; + +}