From 645832d67b2049c8d8f03dbb680dd352722f0eb4 Mon Sep 17 00:00:00 2001 From: "C. J. Howard" Date: Wed, 11 Oct 2017 19:25:54 +0800 Subject: [PATCH] Improve shadow mapping and image-based lighting --- data | 2 +- lib/emergent | 2 +- src/application.cpp | 86 ++++++----- src/application.hpp | 12 +- src/render-passes.cpp | 293 ++++++++++++++++++++++++++++--------- src/render-passes.hpp | 26 +++- src/states/title-state.cpp | 22 +-- 7 files changed, 305 insertions(+), 138 deletions(-) diff --git a/data b/data index fd13a89..497de41 160000 --- a/data +++ b/data @@ -1 +1 @@ -Subproject commit fd13a89510dded63f3068561ba50b8d540220eb7 +Subproject commit 497de41a1d7cc7d82f73e6e9bb6da154f9f7eaee diff --git a/lib/emergent b/lib/emergent index 031d4b5..1295773 160000 --- a/lib/emergent +++ b/lib/emergent @@ -1 +1 @@ -Subproject commit 031d4b56493568e5fc863752fa104784e3e1ff38 +Subproject commit 1295773c23e7bf5e1f65f3a4dc61652cc8aba9f9 diff --git a/src/application.cpp b/src/application.cpp index 1f14faa..92cc4df 100644 --- a/src/application.cpp +++ b/src/application.cpp @@ -625,7 +625,7 @@ bool Application::loadScene() bgBatch.update(); vignettePass.setRenderTarget(&defaultRenderTarget); - bgCompositor.addPass(&vignettePass); + //bgCompositor.addPass(&vignettePass); bgCompositor.load(nullptr); bgCamera.setOrthographic(0, 1.0f, 1.0f, 0, -1.0f, 1.0f); bgCamera.lookAt(glm::vec3(0), glm::vec3(0, 0, -1), glm::vec3(0, 1, 0)); @@ -672,6 +672,8 @@ bool Application::loadScene() // Setup shadow map render pass shadowMapPass.setRenderTarget(&shadowMapRenderTarget); + shadowMapPass.setViewCamera(&camera); + shadowMapPass.setLightCamera(&sunlightCamera); // Setup shadow map compositor shadowMapCompositor.addPass(&shadowMapPass); @@ -687,11 +689,12 @@ bool Application::loadScene() lightingPass.setRenderTarget(&defaultRenderTarget); lightingPass.setShadowMap(shadowMapDepthTexture); lightingPass.setShadowCamera(&sunlightCamera); + lightingPass.setShadowMapPass(&shadowMapPass); // Setup debug pass debugPass.setRenderTarget(&defaultRenderTarget); - //defaultCompositor.addPass(&skyboxPass); + defaultCompositor.addPass(&skyboxPass); defaultCompositor.addPass(&soilPass); defaultCompositor.addPass(&lightingPass); //defaultCompositor.addPass(&debugPass); @@ -699,9 +702,10 @@ bool Application::loadScene() // Setup sunlight camera sunlightCamera.lookAt(Vector3(0.5f, 2.0f, 2.0f), Vector3(0, 0, 0), Vector3(0, 1, 0)); - sunlightCamera.setOrthographic(-100.0f, 100.0f, -100.0f, 100.0f, -100.0f, 100.0f); + sunlightCamera.setOrthographic(-1.0f, 1.0f, -1.0f, 1.0f, -1.0f, 1.0f); sunlightCamera.setCompositor(&shadowMapCompositor); sunlightCamera.setCompositeIndex(0); + sunlightCamera.setCullingMask(nullptr); defaultLayer->addObject(&sunlightCamera); // Setup camera @@ -782,8 +786,6 @@ bool Application::loadUI() // Get strings std::string pressAnyKeyString; - std::string copyrightString; - std::string versionString; std::string backString; std::string challengeString; std::string experimentString; @@ -799,8 +801,6 @@ bool Application::loadUI() std::string returnToMainMenuString; std::string quitToDesktopString; strings.get("press-any-key", &pressAnyKeyString); - strings.get("copyright", ©rightString); - strings.get("version", &versionString); strings.get("back", &backString); strings.get("challenge", &challengeString); strings.get("experiment", &experimentString); @@ -837,6 +837,14 @@ bool Application::loadUI() blackoutImage->setVisible(false); uiRootElement->addChild(blackoutImage); + // Create darken element (for darkening title screen) + darkenImage = new UIImage(); + darkenImage->setDimensions(Vector2(width, height)); + darkenImage->setLayerOffset(-1); + darkenImage->setTintColor(Vector4(0.0f, 0.0f, 0.0f, 0.15f)); + darkenImage->setVisible(false); + uiRootElement->addChild(darkenImage); + // Create splash screen element splashImage = new UIImage(); splashImage->setAnchor(Anchor::CENTER); @@ -854,28 +862,6 @@ bool Application::loadUI() titleImage->setVisible(false); uiRootElement->addChild(titleImage); - // Create Title screen info element - titleScreenInfoContainer = new UIContainer(); - titleScreenInfoContainer->setDimensions(Vector2(width, height)); - titleScreenInfoContainer->setVisible(false); - uiRootElement->addChild(titleScreenInfoContainer); - - // Create copyright element - copyrightLabel = new UILabel(); - copyrightLabel->setAnchor(Vector2(0.0f, 1.0f)); - copyrightLabel->setFont(copyrightFont); - copyrightLabel->setTranslation(Vector2((int)(width * 0.025f), (int)(-height * 0.025f))); - copyrightLabel->setText(copyrightString); - titleScreenInfoContainer->addChild(copyrightLabel); - - // Create version element - versionLabel = new UILabel(); - versionLabel->setAnchor(Vector2(1.0f, 1.0f)); - versionLabel->setFont(copyrightFont); - versionLabel->setTranslation(Vector2((int)(-width * 0.025f), (int)(-height * 0.025f))); - versionLabel->setText(versionString); - titleScreenInfoContainer->addChild(versionLabel); - frameTimeLabel = new UILabel(); frameTimeLabel->setAnchor(Vector2(0.0f, 0.0f)); frameTimeLabel->setLayerOffset(99); @@ -1164,19 +1150,11 @@ bool Application::loadUI() titleFadeOutTween->setUpdateCallback(std::bind(&UIElement::setTintColor, titleImage, std::placeholders::_1)); tweener->addTween(titleFadeOutTween); - // Setup copyright tween - copyrightFadeInTween = new Tween(EaseFunction::IN_CUBIC, 0.0f, 1.0f, Vector4(0.0f, 0.0f, 0.0f, 0.0f), Vector4(0.0f, 0.0f, 0.0f, 0.5f)); - copyrightFadeInTween->setUpdateCallback(std::bind(&UIElement::setTintColor, titleScreenInfoContainer, std::placeholders::_1)); - tweener->addTween(copyrightFadeInTween); - copyrightFadeOutTween = new Tween(EaseFunction::OUT_CUBIC, 0.0f, 0.25f, Vector4(0.0f, 0.0f, 0.0f, 0.5f), Vector4(0.0f, 0.0f, 0.0f, -0.5f)); - copyrightFadeOutTween->setUpdateCallback(std::bind(&UIElement::setTintColor, titleScreenInfoContainer, std::placeholders::_1)); - tweener->addTween(copyrightFadeOutTween); - // Setup "Press any key" tween - anyKeyFadeInTween = new Tween(EaseFunction::LINEAR, 0.0f, 1.5f, Vector4(0.0f, 0.0f, 0.0f, 0.0f), Vector4(0.0f, 0.0f, 0.0f, 1.0f)); + anyKeyFadeInTween = new Tween(EaseFunction::LINEAR, 0.0f, 1.5f, Vector4(1.0f, 1.0f, 1.0f, 0.0f), Vector4(1.0f, 1.0f, 1.0f, 1.0f)); anyKeyFadeInTween->setUpdateCallback(std::bind(&UIElement::setTintColor, anyKeyLabel, std::placeholders::_1)); tweener->addTween(anyKeyFadeInTween); - anyKeyFadeOutTween = new Tween(EaseFunction::LINEAR, 0.0f, 1.5f, Vector4(0.0f, 0.0f, 0.0f, 1.0f), Vector4(0.0f, 0.0f, 0.0f, -1.0f)); + anyKeyFadeOutTween = new Tween(EaseFunction::LINEAR, 0.0f, 1.5f, Vector4(1.0f, 1.0f, 1.0f, 1.0f), Vector4(1.0f, 1.0f, 1.0f, -1.0f)); anyKeyFadeOutTween->setUpdateCallback(std::bind(&UIElement::setTintColor, anyKeyLabel, std::placeholders::_1)); anyKeyFadeInTween->setEndCallback(std::bind(&TweenBase::start, anyKeyFadeOutTween)); anyKeyFadeOutTween->setEndCallback(std::bind(&TweenBase::start, anyKeyFadeInTween)); @@ -1474,6 +1452,34 @@ bool Application::loadGame() brush = new Brush(brushModel); brush->setCameraController(surfaceCam); + + // Load radiance and irradiance cubemaps + textureLoader->setCubemap(true); + textureLoader->setMipmapChain(true); + textureLoader->setWrapS(false); + textureLoader->setWrapT(false); + textureLoader->setWrapR(false); + + std::string radianceCubemapFilename = std::string("data/textures/title-screen-sky-radiance-m%02d.hdr"); + std::string irradianceCubemapFilename = std::string("data/textures/title-screen-sky-irradiance-m%02d.hdr"); + + + radianceCubemap = textureLoader->load(radianceCubemapFilename); + if (!radianceCubemap) + { + std::cerr << "Failed to load radiance cubemap \"" << radianceCubemapFilename << "\"" << std::endl; + } + + irradianceCubemap = textureLoader->load(irradianceCubemapFilename); + if (!irradianceCubemap) + { + std::cerr << "Failed to load irradiance cubemap \"" << irradianceCubemapFilename << "\"" << std::endl; + } + + skyboxPass.setCubemap(radianceCubemap); + lightingPass.setDiffuseCubemap(irradianceCubemap); + lightingPass.setSpecularCubemap(radianceCubemap); + return true; } @@ -1606,7 +1612,7 @@ void Application::selectWorld(std::size_t index) soilPass.setHorizonATexture(biome->soilHorizonA); soilPass.setHorizonBTexture(biome->soilHorizonB); soilPass.setHorizonCTexture(biome->soilHorizonC); - skyboxPass.setCubemap(biome->specularCubemap); + //skyboxPass.setCubemap(biome->specularCubemap); for (int i = 0; i < 5; ++i) { diff --git a/src/application.hpp b/src/application.hpp index f34400f..e5e7616 100644 --- a/src/application.hpp +++ b/src/application.hpp @@ -283,11 +283,8 @@ public: UIImage* blackoutImage; UIImage* splashImage; UIImage* titleImage; - - UIContainer* titleScreenInfoContainer; - UILabel* copyrightLabel; - UILabel* versionLabel; - + UIImage* darkenImage; + UILabel* frameTimeLabel; UILabel* anyKeyLabel; @@ -340,8 +337,6 @@ public: Tween* splashFadeOutTween; Tween* titleFadeInTween; Tween* titleFadeOutTween; - Tween* copyrightFadeInTween; - Tween* copyrightFadeOutTween; Tween* anyKeyFadeInTween; Tween* anyKeyFadeOutTween; Tween* menuFadeInTween; @@ -404,6 +399,9 @@ public: Brush* brush; bool simulationPaused; + Texture* radianceCubemap; + Texture* irradianceCubemap; + // Debug LineBatcher* lineBatcher; }; diff --git a/src/render-passes.cpp b/src/render-passes.cpp index ae8ec79..10c3020 100644 --- a/src/render-passes.cpp +++ b/src/render-passes.cpp @@ -20,18 +20,66 @@ #include "render-passes.hpp" #include "materials.hpp" #include +#include ShadowMapRenderPass::ShadowMapRenderPass(): unskinnedShader(nullptr), - skinnedShader(nullptr) + skinnedShader(nullptr), + croppedShadowMapViewports(nullptr), + viewCamera(nullptr), + splitViewFrustum(nullptr), + cropMatrices(nullptr), + tileMatrices(nullptr) +{} + +bool ShadowMapRenderPass::load(const RenderContext* renderContext) { + // Set maximum number of bones for skinned meshes maxBoneCount = 64; + + // Set number of frustum splits + frustumSplitCount = 4; + + // Create split view frustum + splitViewFrustum = new SplitViewFrustum(frustumSplitCount); + + // Determine resolution of shadow maps + shadowMapResolution = 4096; + croppedShadowMapResolution = shadowMapResolution >> 1; + + // Allocate viewports + croppedShadowMapViewports = new Vector4[frustumSplitCount]; + + // Setup viewports + for (int i = 0; i < frustumSplitCount; ++i) + { + int x = i % 2; + int y = i / 2; + + Vector4* viewport = &croppedShadowMapViewports[i]; + (*viewport)[0] = static_cast(x * croppedShadowMapResolution); + (*viewport)[1] = static_cast(y * croppedShadowMapResolution); + (*viewport)[2] = static_cast(croppedShadowMapResolution); + (*viewport)[3] = static_cast(croppedShadowMapResolution); + } + + // Allocate matrices + cropMatrices = new Matrix4[frustumSplitCount]; + tileMatrices = new Matrix4[frustumSplitCount]; + + // Setup tile matrices + Matrix4 tileScale = glm::scale(Vector3(0.5f, 0.5f, 1.0f)); + for (int i = 0; i < frustumSplitCount; ++i) + { + float x = static_cast(i % 2) * 0.5f; + float y = static_cast(i / 2) * 0.5f; + tileMatrices[i] = glm::translate(Vector3(x, y, 0.0f)) * tileScale; + } + + // Setup shader parameters modelViewProjectionParam = parameterSet.addParameter("modelViewProjectionMatrix", ShaderParameter::Type::MATRIX_4, 1); matrixPaletteParam = parameterSet.addParameter("matrixPalette", ShaderParameter::Type::MATRIX_4, maxBoneCount); -} - -bool ShadowMapRenderPass::load(const RenderContext* renderContext) -{ + // Load unskinned shader shaderLoader.undefine(); shaderLoader.define("VERTEX_POSITION", EMERGENT_VERTEX_POSITION); @@ -62,6 +110,20 @@ void ShadowMapRenderPass::unload() delete skinnedShader; skinnedShader = nullptr; + + delete[] croppedShadowMapViewports; + croppedShadowMapViewports = nullptr; + + delete splitViewFrustum; + splitViewFrustum = nullptr; + + delete[] cropMatrices; + cropMatrices = nullptr; + + delete[] tileMatrices; + tileMatrices = nullptr; + + parameterSet.removeParameters(); } void ShadowMapRenderPass::render(RenderContext* renderContext) @@ -78,67 +140,170 @@ void ShadowMapRenderPass::render(RenderContext* renderContext) glDepthMask(GL_TRUE); glDepthFunc(GL_LESS); - // Draw back faces + // Draw front and back faces glDisable(GL_CULL_FACE); // Disable alpha blending glDisable(GL_BLEND); - const Camera& camera = *(renderContext->camera); + //const Camera& lightCamera = *(renderContext->camera); const std::list* operations = renderContext->queue->getOperations(); Shader* shader = nullptr; - // Render operations - for (const RenderOperation& operation: *operations) + // Update split view frustum + //splitViewFrustum->setMatrices(viewCamera->getView(), viewCamera->getProjection()); + + const ViewFrustum& viewFrustum = viewCamera->getViewFrustum(); + + // Find center of view frustum + Vector3 center = Vector3(0.0f); + for (std::size_t i = 0; i < viewFrustum.getCornerCount(); ++i) { - // Skip render operations with unsupported materials - if (operation.material->getMaterialFormatID() != static_cast(MaterialFormat::PHYSICAL)) - { - continue; - } + center += viewFrustum.getCorner(i); + } + center = center * 1.0f / static_cast(viewFrustum.getCornerCount()); + + // Position light camera in center of view frustum + //lightCamera->lookAt(center, center + lightCamera->getForward(), lightCamera->getUp()); + + // Calculate split distances + float clipNear = viewCamera->getClipNear(); + float clipFar = viewCamera->getClipFar(); + float* splitDistances = new float[frustumSplitCount + 1]; + float splitSchemeWeight = 0.5f; + + for (std::size_t i = 1; i < frustumSplitCount; ++i) + { + float part = static_cast(i) / static_cast(frustumSplitCount); - // Skip non shadow casters - const PhysicalMaterial* material = static_cast(operation.material); - if (!material->shadowCaster) - { - continue; - } + // Calculate uniform split distance + float uniformSplitDistance = clipNear + (clipFar - clipNear) * part; - // Select shader - Shader* targetShader = nullptr; - if (operation.pose != nullptr) - { - targetShader = skinnedShader; - } - else - { - targetShader = unskinnedShader; - } + // Calculate logarithmic split distance + float logSplitDistance = clipNear * std::pow(clipFar / clipNear, part); - // Switch shader if necessary - if (shader != targetShader) + + // Interpolate between uniform and logarithmic split distances + splitDistances[i] = logSplitDistance * splitSchemeWeight + uniformSplitDistance * (1.0f - splitSchemeWeight); + } + splitDistances[0] = clipNear; + splitDistances[frustumSplitCount] = clipFar; + + // For each frustum split + for (int i = 0; i < frustumSplitCount; ++i) + { + // Calculate crop matrix { - shader = targetShader; + ViewFrustum frustumSplit; - // Bind shader - shader->bind(); + // Determine near and far distances for this subfrustum + float splitNear = splitDistances[0]; + float splitFar = splitDistances[4]; + + // Calculate subfrustum projection matrix + Matrix4 splitProjection = glm::ortho(viewCamera->getClipLeft(), viewCamera->getClipRight(), viewCamera->getClipBottom(), viewCamera->getClipTop(), splitNear, splitFar); + + // Set subfrustum matrices + frustumSplit.setMatrices(viewCamera->getView(), splitProjection); + + // Create AABB containing the frustum split corners + AABB frustumSplitBounds(Vector3(std::numeric_limits::infinity()), Vector3(-std::numeric_limits::infinity())); + for (std::size_t j = 0; j < frustumSplit.getCornerCount(); ++j) + { + frustumSplitBounds.add(frustumSplit.getCorner(j)); + } + + // Transform frustum split bounds into light's clip space + AABB croppingBounds = frustumSplitBounds.transformed(lightCamera->getViewProjection()); + Vector3 cropMax = croppingBounds.getMax(); + Vector3 cropMin = croppingBounds.getMin(); + //cropMin.z = 0.0f; + + // Calculate scale + Vector3 scale; + scale.x = 2.0f / (cropMax.x - cropMin.x); + scale.y = 2.0f / (cropMax.y - cropMin.y); + scale.z = 1.0f / (cropMax.z - cropMin.z); + + // Quantize scale + //float scaleQuantizer = 64.0f; + //scale.x = 1.0f / std::ceil(1.0f / scale.x * scaleQuantizer) * scaleQuantizer; + //scale.y = 1.0f / std::ceil(1.0f / scale.y * scaleQuantizer) * scaleQuantizer; + + // Calculate offset + Vector3 offset; + offset.x = (cropMax.x + cropMin.x) * scale.x * -0.5f; + offset.y = (cropMax.y + cropMin.y) * scale.y * -0.5f; + offset.z = -cropMin.z * scale.z; + + // Quantize offset + //float halfTextureSize = static_cast(croppedShadowMapResolution) * 0.5f; + //offset.x = std::ceil(offset.x * halfTextureSize) / halfTextureSize; + //offset.y = std::ceil(offset.y * halfTextureSize) / halfTextureSize; + + cropMatrices[i] = glm::translate(offset) * glm::scale(scale); } - // Pass matrix palette - if (operation.pose != nullptr) - { - shader->setParameter(matrixPaletteParam, 0, operation.pose->getMatrixPalette(), operation.pose->getSkeleton()->getBoneCount()); - } + Matrix4 croppedViewProjection = cropMatrices[i] * lightCamera->getViewProjection(); - const Matrix4& modelMatrix = operation.transform; - Matrix4 modelViewProjectionMatrix = camera.getViewProjection() * modelMatrix; - shader->setParameter(modelViewProjectionParam, modelViewProjectionMatrix); + // Activate viewport for corresponding cropped shadow map + const Vector4& viewport = croppedShadowMapViewports[i]; + glViewport(viewport[0], viewport[1], viewport[2], viewport[3]); - glBindVertexArray(operation.vao); - glDrawElementsBaseVertex(GL_TRIANGLES, operation.triangleCount * 3, GL_UNSIGNED_INT, (void*)0, operation.indexOffset); + // Render operations + for (const RenderOperation& operation: *operations) + { + // Skip render operations with unsupported materials + if (operation.material->getMaterialFormatID() != static_cast(MaterialFormat::PHYSICAL)) + { + continue; + } + + // Skip non shadow casters + const PhysicalMaterial* material = static_cast(operation.material); + if (!material->shadowCaster) + { + continue; + } + + // Select shader + Shader* targetShader = nullptr; + if (operation.pose != nullptr) + { + targetShader = skinnedShader; + } + else + { + targetShader = unskinnedShader; + } + + // Switch shader if necessary + if (shader != targetShader) + { + shader = targetShader; + + // Bind shader + shader->bind(); + } + + // Pass matrix palette + if (operation.pose != nullptr) + { + shader->setParameter(matrixPaletteParam, 0, operation.pose->getMatrixPalette(), operation.pose->getSkeleton()->getBoneCount()); + } + + const Matrix4& modelMatrix = operation.transform; + Matrix4 modelViewProjectionMatrix = croppedViewProjection * modelMatrix; + shader->setParameter(modelViewProjectionParam, modelViewProjectionMatrix); + + glBindVertexArray(operation.vao); + glDrawElementsBaseVertex(GL_TRIANGLES, operation.triangleCount * 3, GL_UNSIGNED_INT, (void*)0, operation.indexOffset); + } } + delete[] splitDistances; + glBindFramebuffer(GL_FRAMEBUFFER, 0); } @@ -344,14 +509,12 @@ LightingRenderPass::LightingRenderPass(): shadowMap(0), shadowCamera(nullptr), treeShadow(nullptr), - diffuseCubemap(nullptr) + diffuseCubemap(nullptr), + specularCubemap(nullptr), + shadowMapPass(nullptr) { // Initialize bias matrix for calculating the model-view-projection-bias matrix (used for shadow map texture coordinate calculation) - biasMatrix = Matrix4( - 0.5f, 0.0f, 0.0f, 0.0f, - 0.0f, 0.5f, 0.0f, 0.0f, - 0.0f, 0.0f, 0.5f, 0.0f, - 0.5f, 0.5f, 0.5f, 1.0f); + biasMatrix = glm::translate(Vector3(0.5f)) * glm::scale(Vector3(0.5f)); maxBoneCount = 64; @@ -384,23 +547,6 @@ bool LightingRenderPass::load(const RenderContext* renderContext) std::cerr << "Failed to load tree shadow" << std::endl; } - // Load cubemap - textureLoader.setCubemap(true); - textureLoader.setMipmapChain(false); - diffuseCubemap = textureLoader.load("data/textures/campus-diffuse.png"); - if (!diffuseCubemap) - { - std::cerr << "Failed to load cubemap" << std::endl; - } - - textureLoader.setCubemap(true); - textureLoader.setMipmapChain(true); - specularCubemap = textureLoader.load("data/textures/campus-specular_m%02d.png"); - if (!specularCubemap) - { - std::cerr << "Failed to load cubemap" << std::endl; - } - // Load unskinned shader shaderLoader.undefine(); shaderLoader.define("TEXTURE_COUNT", 0); @@ -843,9 +989,8 @@ void LightingRenderPass::render(RenderContext* renderContext) glBindFramebuffer(GL_FRAMEBUFFER, renderTarget->framebuffer); glViewport(0, 0, renderTarget->width, renderTarget->height); - // Clear depth and stencil buffers - glClearColor(0.0f, 0.0f, 0.0f, 1.0f); - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + // Clear depth buffer + glClear(GL_DEPTH_BUFFER_BIT); // Enable depth testing glEnable(GL_DEPTH_TEST); @@ -868,7 +1013,8 @@ void LightingRenderPass::render(RenderContext* renderContext) directionalLightDirections[0] = glm::normalize(Vector3(camera.getView() * -Vector4(0, 0, -1, 0))); // Calculate the (light-space) view-projection matrix - Matrix4 lightViewProjectionMatrix = shadowCamera->getViewProjection(); + Matrix4 lightViewProjectionMatrix = shadowMapPass->getTileMatrix(0) * biasMatrix * shadowMapPass->getCropMatrix(0) * shadowCamera->getViewProjection(); + //Matrix4 lightViewProjectionMatrix = biasMatrix * shadowCamera->getViewProjection(); glActiveTexture(GL_TEXTURE3); glBindTexture(GL_TEXTURE_CUBE_MAP, diffuseCubemap->getTextureID()); @@ -1490,6 +1636,9 @@ void SkyboxRenderPass::render(RenderContext* renderContext) return; } + glBindFramebuffer(GL_FRAMEBUFFER, renderTarget->framebuffer); + glViewport(0, 0, renderTarget->width, renderTarget->height); + glDisable(GL_DEPTH_TEST); glDepthMask(GL_FALSE); diff --git a/src/render-passes.hpp b/src/render-passes.hpp index 7bd6980..3f5474a 100644 --- a/src/render-passes.hpp +++ b/src/render-passes.hpp @@ -38,6 +38,14 @@ public: virtual void unload(); virtual void render(RenderContext* renderContext); + inline void setViewCamera(const Camera* camera) { this->viewCamera = camera; } + inline void setLightCamera(Camera* camera) { this->lightCamera = camera; } + + inline int getFrustumSplitCount() const { return frustumSplitCount; } + inline const ViewFrustum& getSplitViewFrustum(std::size_t index) const { return splitViewFrustum->getSubfrustum(index); } + inline const Matrix4& getCropMatrix(std::size_t index) const { return cropMatrices[index]; } + inline const Matrix4& getTileMatrix(std::size_t index) const { return tileMatrices[index]; } + private: ShaderParameterSet parameterSet; const ShaderParameter* modelViewProjectionParam; @@ -48,6 +56,16 @@ private: Shader* unskinnedShader; Shader* skinnedShader; int maxBoneCount; + + int frustumSplitCount; + int shadowMapResolution; + int croppedShadowMapResolution; + Vector4* croppedShadowMapViewports; + Matrix4* cropMatrices; + Matrix4* tileMatrices; + const Camera* viewCamera; + Camera* lightCamera; + SplitViewFrustum* splitViewFrustum; }; /** @@ -130,6 +148,9 @@ public: inline void setShadowMap(GLuint shadowMap) { this->shadowMap = shadowMap; } inline void setShadowCamera(const Camera* camera) { this->shadowCamera = camera; } + inline void setShadowMapPass(const ShadowMapRenderPass* shadowMapPass) { this->shadowMapPass = shadowMapPass; } + inline void setDiffuseCubemap(const Texture* cubemap) { this->diffuseCubemap = cubemap; } + inline void setSpecularCubemap(const Texture* cubemap) { this->specularCubemap = cubemap; } private: class RenderOpCompare @@ -171,10 +192,11 @@ private: Matrix4 biasMatrix; GLuint shadowMap; Texture* treeShadow; - Texture* diffuseCubemap; - Texture* specularCubemap; + const Texture* diffuseCubemap; + const Texture* specularCubemap; const Camera* shadowCamera; float time; + const ShadowMapRenderPass* shadowMapPass; }; /** diff --git a/src/states/title-state.cpp b/src/states/title-state.cpp index 192d13c..5d2feda 100644 --- a/src/states/title-state.cpp +++ b/src/states/title-state.cpp @@ -29,7 +29,6 @@ const float fadeInDuration = 0.5f; const float hangDuration = 1.0f; const float fadeOutDuration = 0.5f; const float titleDelay = 2.0f; -const float copyrightDelay = 3.0f; const float pressAnyKeyDelay = 5.0f; TitleState::TitleState(Application* application): @@ -49,9 +48,6 @@ void TitleState::enter() application->backgroundLayer->addObject(&application->bgCamera); application->backgroundLayer->addObject(&application->bgBatch); - // Title ant hill - application->defaultLayer->addObject(&application->antHillModelInstance); - application->inputManager->addWindowObserver(this); windowResized(application->width, application->height); @@ -59,14 +55,17 @@ void TitleState::enter() application->surfaceCam->setCamera(&application->camera); application->surfaceCam->setFocalPoint(Vector3(0.0f)); application->surfaceCam->setFocalDistance(50.0f); - application->surfaceCam->setElevation(glm::radians(0.0f)); - application->surfaceCam->setAzimuth(glm::radians(0.0f)); + application->surfaceCam->setElevation(glm::radians(-30.0f)); + application->surfaceCam->setAzimuth(glm::radians(180.0f)); application->surfaceCam->setTargetFocalPoint(application->surfaceCam->getFocalPoint()); application->surfaceCam->setTargetFocalDistance(application->surfaceCam->getFocalDistance()); application->surfaceCam->setTargetElevation(application->surfaceCam->getElevation()); application->surfaceCam->setTargetAzimuth(application->surfaceCam->getAzimuth()); application->surfaceCam->update(0.0f); + application->darkenImage->setVisible(true); + + // Setup fade-in application->blackoutImage->setVisible(true); application->fadeInTween->start(); @@ -87,8 +86,6 @@ void TitleState::execute() { application->titleImage->setVisible(true); application->titleFadeInTween->start(); - application->titleScreenInfoContainer->setVisible(true); - application->copyrightFadeInTween->start(); } if (stateTime >= pressAnyKeyDelay && !application->anyKeyLabel->isVisible()) @@ -139,9 +136,6 @@ void TitleState::execute() application->titleImage->setTintColor(Vector4(1.0f)); application->anyKeyFadeInTween->start(); application->anyKeyLabel->setVisible(true); - application->copyrightFadeInTween->stop(); - application->titleScreenInfoContainer->setVisible(true); - application->titleScreenInfoContainer->setTintColor(Vector4(0.0f, 0.0f, 0.0f, 0.5f)); } else if (substate == 1) { @@ -152,8 +146,6 @@ void TitleState::execute() application->anyKeyFadeInTween->stop(); application->anyKeyFadeOutTween->stop(); application->anyKeyLabel->setVisible(false); - application->copyrightFadeInTween->stop(); - application->copyrightFadeOutTween->start(); application->antHillZoomInTween->start(); @@ -175,10 +167,10 @@ void TitleState::exit() // Hide UI application->titleImage->setVisible(false); application->anyKeyLabel->setVisible(false); - application->titleScreenInfoContainer->setVisible(false); + application->darkenImage->setVisible(false); + // Remove clear scene - application->defaultLayer->removeObject(&application->antHillModelInstance); application->backgroundLayer->removeObject(&application->bgCamera); application->backgroundLayer->removeObject(&application->bgBatch); }