Browse Source

Improve shadow mapping and image-based lighting

master
C. J. Howard 7 years ago
parent
commit
645832d67b
7 changed files with 305 additions and 138 deletions
  1. +1
    -1
      data
  2. +1
    -1
      lib/emergent
  3. +46
    -40
      src/application.cpp
  4. +5
    -7
      src/application.hpp
  5. +221
    -72
      src/render-passes.cpp
  6. +24
    -2
      src/render-passes.hpp
  7. +7
    -15
      src/states/title-state.cpp

+ 1
- 1
data

@ -1 +1 @@
Subproject commit fd13a89510dded63f3068561ba50b8d540220eb7
Subproject commit 497de41a1d7cc7d82f73e6e9bb6da154f9f7eaee

+ 1
- 1
lib/emergent

@ -1 +1 @@
Subproject commit 031d4b56493568e5fc863752fa104784e3e1ff38
Subproject commit 1295773c23e7bf5e1f65f3a4dc61652cc8aba9f9

+ 46
- 40
src/application.cpp View File

@ -625,7 +625,7 @@ bool Application::loadScene()
bgBatch.update(); bgBatch.update();
vignettePass.setRenderTarget(&defaultRenderTarget); vignettePass.setRenderTarget(&defaultRenderTarget);
bgCompositor.addPass(&vignettePass);
//bgCompositor.addPass(&vignettePass);
bgCompositor.load(nullptr); bgCompositor.load(nullptr);
bgCamera.setOrthographic(0, 1.0f, 1.0f, 0, -1.0f, 1.0f); 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)); 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 // Setup shadow map render pass
shadowMapPass.setRenderTarget(&shadowMapRenderTarget); shadowMapPass.setRenderTarget(&shadowMapRenderTarget);
shadowMapPass.setViewCamera(&camera);
shadowMapPass.setLightCamera(&sunlightCamera);
// Setup shadow map compositor // Setup shadow map compositor
shadowMapCompositor.addPass(&shadowMapPass); shadowMapCompositor.addPass(&shadowMapPass);
@ -687,11 +689,12 @@ bool Application::loadScene()
lightingPass.setRenderTarget(&defaultRenderTarget); lightingPass.setRenderTarget(&defaultRenderTarget);
lightingPass.setShadowMap(shadowMapDepthTexture); lightingPass.setShadowMap(shadowMapDepthTexture);
lightingPass.setShadowCamera(&sunlightCamera); lightingPass.setShadowCamera(&sunlightCamera);
lightingPass.setShadowMapPass(&shadowMapPass);
// Setup debug pass // Setup debug pass
debugPass.setRenderTarget(&defaultRenderTarget); debugPass.setRenderTarget(&defaultRenderTarget);
//defaultCompositor.addPass(&skyboxPass);
defaultCompositor.addPass(&skyboxPass);
defaultCompositor.addPass(&soilPass); defaultCompositor.addPass(&soilPass);
defaultCompositor.addPass(&lightingPass); defaultCompositor.addPass(&lightingPass);
//defaultCompositor.addPass(&debugPass); //defaultCompositor.addPass(&debugPass);
@ -699,9 +702,10 @@ bool Application::loadScene()
// Setup sunlight camera // Setup sunlight camera
sunlightCamera.lookAt(Vector3(0.5f, 2.0f, 2.0f), Vector3(0, 0, 0), Vector3(0, 1, 0)); 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.setCompositor(&shadowMapCompositor);
sunlightCamera.setCompositeIndex(0); sunlightCamera.setCompositeIndex(0);
sunlightCamera.setCullingMask(nullptr);
defaultLayer->addObject(&sunlightCamera); defaultLayer->addObject(&sunlightCamera);
// Setup camera // Setup camera
@ -782,8 +786,6 @@ bool Application::loadUI()
// Get strings // Get strings
std::string pressAnyKeyString; std::string pressAnyKeyString;
std::string copyrightString;
std::string versionString;
std::string backString; std::string backString;
std::string challengeString; std::string challengeString;
std::string experimentString; std::string experimentString;
@ -799,8 +801,6 @@ bool Application::loadUI()
std::string returnToMainMenuString; std::string returnToMainMenuString;
std::string quitToDesktopString; std::string quitToDesktopString;
strings.get("press-any-key", &pressAnyKeyString); strings.get("press-any-key", &pressAnyKeyString);
strings.get("copyright", &copyrightString);
strings.get("version", &versionString);
strings.get("back", &backString); strings.get("back", &backString);
strings.get("challenge", &challengeString); strings.get("challenge", &challengeString);
strings.get("experiment", &experimentString); strings.get("experiment", &experimentString);
@ -837,6 +837,14 @@ bool Application::loadUI()
blackoutImage->setVisible(false); blackoutImage->setVisible(false);
uiRootElement->addChild(blackoutImage); 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 // Create splash screen element
splashImage = new UIImage(); splashImage = new UIImage();
splashImage->setAnchor(Anchor::CENTER); splashImage->setAnchor(Anchor::CENTER);
@ -854,28 +862,6 @@ bool Application::loadUI()
titleImage->setVisible(false); titleImage->setVisible(false);
uiRootElement->addChild(titleImage); 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 = new UILabel();
frameTimeLabel->setAnchor(Vector2(0.0f, 0.0f)); frameTimeLabel->setAnchor(Vector2(0.0f, 0.0f));
frameTimeLabel->setLayerOffset(99); frameTimeLabel->setLayerOffset(99);
@ -1164,19 +1150,11 @@ bool Application::loadUI()
titleFadeOutTween->setUpdateCallback(std::bind(&UIElement::setTintColor, titleImage, std::placeholders::_1)); titleFadeOutTween->setUpdateCallback(std::bind(&UIElement::setTintColor, titleImage, std::placeholders::_1));
tweener->addTween(titleFadeOutTween); tweener->addTween(titleFadeOutTween);
// Setup copyright tween
copyrightFadeInTween = new Tween<Vector4>(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<Vector4>(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 // Setup "Press any key" tween
anyKeyFadeInTween = new Tween<Vector4>(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<Vector4>(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)); anyKeyFadeInTween->setUpdateCallback(std::bind(&UIElement::setTintColor, anyKeyLabel, std::placeholders::_1));
tweener->addTween(anyKeyFadeInTween); tweener->addTween(anyKeyFadeInTween);
anyKeyFadeOutTween = new Tween<Vector4>(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<Vector4>(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)); anyKeyFadeOutTween->setUpdateCallback(std::bind(&UIElement::setTintColor, anyKeyLabel, std::placeholders::_1));
anyKeyFadeInTween->setEndCallback(std::bind(&TweenBase::start, anyKeyFadeOutTween)); anyKeyFadeInTween->setEndCallback(std::bind(&TweenBase::start, anyKeyFadeOutTween));
anyKeyFadeOutTween->setEndCallback(std::bind(&TweenBase::start, anyKeyFadeInTween)); anyKeyFadeOutTween->setEndCallback(std::bind(&TweenBase::start, anyKeyFadeInTween));
@ -1474,6 +1452,34 @@ bool Application::loadGame()
brush = new Brush(brushModel); brush = new Brush(brushModel);
brush->setCameraController(surfaceCam); 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; return true;
} }
@ -1606,7 +1612,7 @@ void Application::selectWorld(std::size_t index)
soilPass.setHorizonATexture(biome->soilHorizonA); soilPass.setHorizonATexture(biome->soilHorizonA);
soilPass.setHorizonBTexture(biome->soilHorizonB); soilPass.setHorizonBTexture(biome->soilHorizonB);
soilPass.setHorizonCTexture(biome->soilHorizonC); soilPass.setHorizonCTexture(biome->soilHorizonC);
skyboxPass.setCubemap(biome->specularCubemap);
//skyboxPass.setCubemap(biome->specularCubemap);
for (int i = 0; i < 5; ++i) for (int i = 0; i < 5; ++i)
{ {

+ 5
- 7
src/application.hpp View File

@ -283,11 +283,8 @@ public:
UIImage* blackoutImage; UIImage* blackoutImage;
UIImage* splashImage; UIImage* splashImage;
UIImage* titleImage; UIImage* titleImage;
UIContainer* titleScreenInfoContainer;
UILabel* copyrightLabel;
UILabel* versionLabel;
UIImage* darkenImage;
UILabel* frameTimeLabel; UILabel* frameTimeLabel;
UILabel* anyKeyLabel; UILabel* anyKeyLabel;
@ -340,8 +337,6 @@ public:
Tween<Vector4>* splashFadeOutTween; Tween<Vector4>* splashFadeOutTween;
Tween<Vector4>* titleFadeInTween; Tween<Vector4>* titleFadeInTween;
Tween<Vector4>* titleFadeOutTween; Tween<Vector4>* titleFadeOutTween;
Tween<Vector4>* copyrightFadeInTween;
Tween<Vector4>* copyrightFadeOutTween;
Tween<Vector4>* anyKeyFadeInTween; Tween<Vector4>* anyKeyFadeInTween;
Tween<Vector4>* anyKeyFadeOutTween; Tween<Vector4>* anyKeyFadeOutTween;
Tween<Vector4>* menuFadeInTween; Tween<Vector4>* menuFadeInTween;
@ -404,6 +399,9 @@ public:
Brush* brush; Brush* brush;
bool simulationPaused; bool simulationPaused;
Texture* radianceCubemap;
Texture* irradianceCubemap;
// Debug // Debug
LineBatcher* lineBatcher; LineBatcher* lineBatcher;
}; };

+ 221
- 72
src/render-passes.cpp View File

@ -20,18 +20,66 @@
#include "render-passes.hpp" #include "render-passes.hpp"
#include "materials.hpp" #include "materials.hpp"
#include <iostream> #include <iostream>
#include <limits>
ShadowMapRenderPass::ShadowMapRenderPass(): ShadowMapRenderPass::ShadowMapRenderPass():
unskinnedShader(nullptr), 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; 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<float>(x * croppedShadowMapResolution);
(*viewport)[1] = static_cast<float>(y * croppedShadowMapResolution);
(*viewport)[2] = static_cast<float>(croppedShadowMapResolution);
(*viewport)[3] = static_cast<float>(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<float>(i % 2) * 0.5f;
float y = static_cast<float>(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); modelViewProjectionParam = parameterSet.addParameter("modelViewProjectionMatrix", ShaderParameter::Type::MATRIX_4, 1);
matrixPaletteParam = parameterSet.addParameter("matrixPalette", ShaderParameter::Type::MATRIX_4, maxBoneCount); matrixPaletteParam = parameterSet.addParameter("matrixPalette", ShaderParameter::Type::MATRIX_4, maxBoneCount);
}
bool ShadowMapRenderPass::load(const RenderContext* renderContext)
{
// Load unskinned shader // Load unskinned shader
shaderLoader.undefine(); shaderLoader.undefine();
shaderLoader.define("VERTEX_POSITION", EMERGENT_VERTEX_POSITION); shaderLoader.define("VERTEX_POSITION", EMERGENT_VERTEX_POSITION);
@ -62,6 +110,20 @@ void ShadowMapRenderPass::unload()
delete skinnedShader; delete skinnedShader;
skinnedShader = nullptr; 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) void ShadowMapRenderPass::render(RenderContext* renderContext)
@ -78,67 +140,170 @@ void ShadowMapRenderPass::render(RenderContext* renderContext)
glDepthMask(GL_TRUE); glDepthMask(GL_TRUE);
glDepthFunc(GL_LESS); glDepthFunc(GL_LESS);
// Draw back faces
// Draw front and back faces
glDisable(GL_CULL_FACE); glDisable(GL_CULL_FACE);
// Disable alpha blending // Disable alpha blending
glDisable(GL_BLEND); glDisable(GL_BLEND);
const Camera& camera = *(renderContext->camera);
//const Camera& lightCamera = *(renderContext->camera);
const std::list<RenderOperation>* operations = renderContext->queue->getOperations(); const std::list<RenderOperation>* operations = renderContext->queue->getOperations();
Shader* shader = nullptr; 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<unsigned int>(MaterialFormat::PHYSICAL))
{
continue;
}
center += viewFrustum.getCorner(i);
}
center = center * 1.0f / static_cast<float>(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<float>(i) / static_cast<float>(frustumSplitCount);
// Skip non shadow casters
const PhysicalMaterial* material = static_cast<const PhysicalMaterial*>(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<float>::infinity()), Vector3(-std::numeric_limits<float>::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<float>(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<unsigned int>(MaterialFormat::PHYSICAL))
{
continue;
}
// Skip non shadow casters
const PhysicalMaterial* material = static_cast<const PhysicalMaterial*>(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); glBindFramebuffer(GL_FRAMEBUFFER, 0);
} }
@ -344,14 +509,12 @@ LightingRenderPass::LightingRenderPass():
shadowMap(0), shadowMap(0),
shadowCamera(nullptr), shadowCamera(nullptr),
treeShadow(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) // 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; maxBoneCount = 64;
@ -384,23 +547,6 @@ bool LightingRenderPass::load(const RenderContext* renderContext)
std::cerr << "Failed to load tree shadow" << std::endl; 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 // Load unskinned shader
shaderLoader.undefine(); shaderLoader.undefine();
shaderLoader.define("TEXTURE_COUNT", 0); shaderLoader.define("TEXTURE_COUNT", 0);
@ -843,9 +989,8 @@ void LightingRenderPass::render(RenderContext* renderContext)
glBindFramebuffer(GL_FRAMEBUFFER, renderTarget->framebuffer); glBindFramebuffer(GL_FRAMEBUFFER, renderTarget->framebuffer);
glViewport(0, 0, renderTarget->width, renderTarget->height); 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 // Enable depth testing
glEnable(GL_DEPTH_TEST); 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))); directionalLightDirections[0] = glm::normalize(Vector3(camera.getView() * -Vector4(0, 0, -1, 0)));
// Calculate the (light-space) view-projection matrix // 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); glActiveTexture(GL_TEXTURE3);
glBindTexture(GL_TEXTURE_CUBE_MAP, diffuseCubemap->getTextureID()); glBindTexture(GL_TEXTURE_CUBE_MAP, diffuseCubemap->getTextureID());
@ -1490,6 +1636,9 @@ void SkyboxRenderPass::render(RenderContext* renderContext)
return; return;
} }
glBindFramebuffer(GL_FRAMEBUFFER, renderTarget->framebuffer);
glViewport(0, 0, renderTarget->width, renderTarget->height);
glDisable(GL_DEPTH_TEST); glDisable(GL_DEPTH_TEST);
glDepthMask(GL_FALSE); glDepthMask(GL_FALSE);

+ 24
- 2
src/render-passes.hpp View File

@ -38,6 +38,14 @@ public:
virtual void unload(); virtual void unload();
virtual void render(RenderContext* renderContext); 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: private:
ShaderParameterSet parameterSet; ShaderParameterSet parameterSet;
const ShaderParameter* modelViewProjectionParam; const ShaderParameter* modelViewProjectionParam;
@ -48,6 +56,16 @@ private:
Shader* unskinnedShader; Shader* unskinnedShader;
Shader* skinnedShader; Shader* skinnedShader;
int maxBoneCount; 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 setShadowMap(GLuint shadowMap) { this->shadowMap = shadowMap; }
inline void setShadowCamera(const Camera* camera) { this->shadowCamera = camera; } 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: private:
class RenderOpCompare class RenderOpCompare
@ -171,10 +192,11 @@ private:
Matrix4 biasMatrix; Matrix4 biasMatrix;
GLuint shadowMap; GLuint shadowMap;
Texture* treeShadow; Texture* treeShadow;
Texture* diffuseCubemap;
Texture* specularCubemap;
const Texture* diffuseCubemap;
const Texture* specularCubemap;
const Camera* shadowCamera; const Camera* shadowCamera;
float time; float time;
const ShadowMapRenderPass* shadowMapPass;
}; };
/** /**

+ 7
- 15
src/states/title-state.cpp View File

@ -29,7 +29,6 @@ const float fadeInDuration = 0.5f;
const float hangDuration = 1.0f; const float hangDuration = 1.0f;
const float fadeOutDuration = 0.5f; const float fadeOutDuration = 0.5f;
const float titleDelay = 2.0f; const float titleDelay = 2.0f;
const float copyrightDelay = 3.0f;
const float pressAnyKeyDelay = 5.0f; const float pressAnyKeyDelay = 5.0f;
TitleState::TitleState(Application* application): TitleState::TitleState(Application* application):
@ -49,9 +48,6 @@ void TitleState::enter()
application->backgroundLayer->addObject(&application->bgCamera); application->backgroundLayer->addObject(&application->bgCamera);
application->backgroundLayer->addObject(&application->bgBatch); application->backgroundLayer->addObject(&application->bgBatch);
// Title ant hill
application->defaultLayer->addObject(&application->antHillModelInstance);
application->inputManager->addWindowObserver(this); application->inputManager->addWindowObserver(this);
windowResized(application->width, application->height); windowResized(application->width, application->height);
@ -59,14 +55,17 @@ void TitleState::enter()
application->surfaceCam->setCamera(&application->camera); application->surfaceCam->setCamera(&application->camera);
application->surfaceCam->setFocalPoint(Vector3(0.0f)); application->surfaceCam->setFocalPoint(Vector3(0.0f));
application->surfaceCam->setFocalDistance(50.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->setTargetFocalPoint(application->surfaceCam->getFocalPoint());
application->surfaceCam->setTargetFocalDistance(application->surfaceCam->getFocalDistance()); application->surfaceCam->setTargetFocalDistance(application->surfaceCam->getFocalDistance());
application->surfaceCam->setTargetElevation(application->surfaceCam->getElevation()); application->surfaceCam->setTargetElevation(application->surfaceCam->getElevation());
application->surfaceCam->setTargetAzimuth(application->surfaceCam->getAzimuth()); application->surfaceCam->setTargetAzimuth(application->surfaceCam->getAzimuth());
application->surfaceCam->update(0.0f); application->surfaceCam->update(0.0f);
application->darkenImage->setVisible(true);
// Setup fade-in // Setup fade-in
application->blackoutImage->setVisible(true); application->blackoutImage->setVisible(true);
application->fadeInTween->start(); application->fadeInTween->start();
@ -87,8 +86,6 @@ void TitleState::execute()
{ {
application->titleImage->setVisible(true); application->titleImage->setVisible(true);
application->titleFadeInTween->start(); application->titleFadeInTween->start();
application->titleScreenInfoContainer->setVisible(true);
application->copyrightFadeInTween->start();
} }
if (stateTime >= pressAnyKeyDelay && !application->anyKeyLabel->isVisible()) if (stateTime >= pressAnyKeyDelay && !application->anyKeyLabel->isVisible())
@ -139,9 +136,6 @@ void TitleState::execute()
application->titleImage->setTintColor(Vector4(1.0f)); application->titleImage->setTintColor(Vector4(1.0f));
application->anyKeyFadeInTween->start(); application->anyKeyFadeInTween->start();
application->anyKeyLabel->setVisible(true); 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) else if (substate == 1)
{ {
@ -152,8 +146,6 @@ void TitleState::execute()
application->anyKeyFadeInTween->stop(); application->anyKeyFadeInTween->stop();
application->anyKeyFadeOutTween->stop(); application->anyKeyFadeOutTween->stop();
application->anyKeyLabel->setVisible(false); application->anyKeyLabel->setVisible(false);
application->copyrightFadeInTween->stop();
application->copyrightFadeOutTween->start();
application->antHillZoomInTween->start(); application->antHillZoomInTween->start();
@ -175,10 +167,10 @@ void TitleState::exit()
// Hide UI // Hide UI
application->titleImage->setVisible(false); application->titleImage->setVisible(false);
application->anyKeyLabel->setVisible(false); application->anyKeyLabel->setVisible(false);
application->titleScreenInfoContainer->setVisible(false);
application->darkenImage->setVisible(false);
// Remove clear scene // Remove clear scene
application->defaultLayer->removeObject(&application->antHillModelInstance);
application->backgroundLayer->removeObject(&application->bgCamera); application->backgroundLayer->removeObject(&application->bgCamera);
application->backgroundLayer->removeObject(&application->bgBatch); application->backgroundLayer->removeObject(&application->bgBatch);
} }

Loading…
Cancel
Save