Browse Source

Add initial support for shadow mapping

master
C. J. Howard 6 years ago
parent
commit
5902f9f05c
8 changed files with 197 additions and 45 deletions
  1. +1
    -1
      data
  2. +1
    -1
      lib/emergent
  3. +73
    -17
      src/application.cpp
  4. +10
    -3
      src/application.hpp
  5. +9
    -1
      src/game/tool.cpp
  6. +3
    -1
      src/materials.hpp
  7. +93
    -20
      src/render-passes.cpp
  8. +7
    -1
      src/render-passes.hpp

+ 1
- 1
data

@ -1 +1 @@
Subproject commit 251460a52158fbf7e3523257aaf134f66240fab6
Subproject commit fd13a89510dded63f3068561ba50b8d540220eb7

+ 1
- 1
lib/emergent

@ -1 +1 @@
Subproject commit 19d7fcdb76c3516702a8723b2d125ed07e6dc0c9
Subproject commit 031d4b56493568e5fc863752fa104784e3e1ff38

+ 73
- 17
src/application.cpp View File

@ -457,10 +457,6 @@ int Application::execute()
uiRootElement->update();
uiBatcher->batch(uiBatch, uiRootElement);
// Clear depth and stencil buffers
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
// Render scene
renderer.render(scene);
@ -636,35 +632,82 @@ bool Application::loadScene()
bgCamera.setCompositor(&bgCompositor);
bgCamera.setCompositeIndex(0);
// Set shadow map resolution
shadowMapResolution = 4096;
// Generate shadow map framebuffer
glGenFramebuffers(1, &shadowMapFramebuffer);
glBindFramebuffer(GL_FRAMEBUFFER, shadowMapFramebuffer);
// Generate shadow map depth texture
glGenTextures(1, &shadowMapDepthTexture);
glBindTexture(GL_TEXTURE_2D, shadowMapDepthTexture);
glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT24, shadowMapResolution, shadowMapResolution, 0, GL_DEPTH_COMPONENT, GL_FLOAT, nullptr);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC, GL_LESS);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_NONE);
// Attach depth texture to framebuffer
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, shadowMapDepthTexture, 0);
glDrawBuffer(GL_NONE);
glReadBuffer(GL_NONE);
// Unbind shadow map depth texture
glBindTexture(GL_TEXTURE_2D, 0);
// Setup shadow map render target
shadowMapRenderTarget.width = shadowMapResolution;
shadowMapRenderTarget.height = shadowMapResolution;
shadowMapRenderTarget.framebuffer = shadowMapFramebuffer;
// Setup shadow map render pass
shadowMapPass.setRenderTarget(&shadowMapRenderTarget);
// Setup shadow map compositor
shadowMapCompositor.addPass(&shadowMapPass);
shadowMapCompositor.load(nullptr);
// Setup skybox pass
skyboxPass.setRenderTarget(&defaultRenderTarget);
//defaultCompositor.addPass(&skyboxPass);
// Setup soil pass
soilPass.setRenderTarget(&defaultRenderTarget);
defaultCompositor.addPass(&soilPass);
// Setup lighting pass
lightingPass.setRenderTarget(&defaultRenderTarget);
lightingPass.setShadowMap(0);
lightingPass.setShadowCamera(&camera);
defaultCompositor.addPass(&lightingPass);
lightingPass.setShadowMap(shadowMapDepthTexture);
lightingPass.setShadowCamera(&sunlightCamera);
// Setup debug pass
debugPass.setRenderTarget(&defaultRenderTarget);
//defaultCompositor.addPass(&debugPass);
// Load compositor
//defaultCompositor.addPass(&skyboxPass);
defaultCompositor.addPass(&soilPass);
defaultCompositor.addPass(&lightingPass);
//defaultCompositor.addPass(&debugPass);
defaultCompositor.load(nullptr);
// 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.setCompositor(&shadowMapCompositor);
sunlightCamera.setCompositeIndex(0);
defaultLayer->addObject(&sunlightCamera);
// Setup camera
camera.lookAt(
glm::vec3(0.0f, 0.0f, 10.0f),
glm::vec3(0.0f, 0.0f, 0.0f),
glm::vec3(0.0f, 1.0f, 0.0f));
camera.lookAt(Vector3(0.0f, 0.0f, 10.0f), Vector3(0.0f, 0.0f, 0.0f), Vector3(0.0f, 1.0f, 0.0f));
camera.setCompositor(&defaultCompositor);
camera.setCompositeIndex(0);
camera.setCompositeIndex(1);
defaultLayer->addObject(&camera);
// Debug
@ -732,6 +775,11 @@ bool Application::loadUI()
mouseLeftTexture = textureLoader->load("data/textures/mouse-left.png");
mouseRightTexture = textureLoader->load("data/textures/mouse-right.png");
depthTexture = new Texture();
depthTexture->setTextureID(shadowMapDepthTexture);
depthTexture->setWidth(shadowMapResolution);
depthTexture->setHeight(shadowMapResolution);
// Get strings
std::string pressAnyKeyString;
std::string copyrightString;
@ -1030,6 +1078,13 @@ bool Application::loadUI()
foodIndicatorImage->setTexture(foodIndicatorTexture);
//uiRootElement->addChild(foodIndicatorImage);
depthTextureImage = new UIImage();
depthTextureImage->setAnchor(Vector2(0.0f, 1.0f));
depthTextureImage->setDimensions(Vector2(256, 256));
depthTextureImage->setTranslation(Vector2(0.0f, 0.0f));
depthTextureImage->setTexture(depthTexture);
uiRootElement->addChild(depthTextureImage);
// Create level ID
levelIDLabel = new UILabel();
levelIDLabel->setAnchor(Vector2(0.5f, 0.0f));
@ -1306,6 +1361,7 @@ bool Application::loadUI()
defaultRenderTarget.width = width;
defaultRenderTarget.height = height;
defaultRenderTarget.framebuffer = 0;
resizeUI();
return true;

+ 10
- 3
src/application.hpp View File

@ -178,14 +178,17 @@ public:
// Graphics
Renderer renderer;
RenderTarget defaultRenderTarget;
int shadowMapResolution;
GLuint shadowMapDepthTexture;
GLuint shadowMapFramebuffer;
RenderTarget shadowMapRenderTarget;
GLuint shadowFramebuffer;
GLuint shadowDepthTexture;
ShadowMapRenderPass shadowMapPass;
Compositor shadowMapCompositor;
SoilRenderPass soilPass;
LightingRenderPass lightingPass;
DebugRenderPass debugPass;
Compositor shadowCompositor;
Compositor defaultCompositor;
BillboardBatch* uiBatch;
UIBatcher* uiBatcher;
@ -271,6 +274,8 @@ public:
Texture* mouseLeftTexture;
Texture* mouseRightTexture;
Texture* depthTexture;
// UI elements
Vector4 selectedColor;
Vector4 deselectedColor;
@ -318,6 +323,8 @@ public:
UIImage* contextButtonImage0;
UIImage* contextButtonImage1;
UIImage* depthTextureImage;
UILabel* levelIDLabel;
UILabel* levelNameLabel;

+ 9
- 1
src/game/tool.cpp View File

@ -19,7 +19,10 @@ Tool::~Tool()
void Tool::setActive(bool active)
{
this->active = active;
modelInstance.setActive(active);
if (!active)
{
modelInstance.setActive(active);
}
}
void Tool::setCameraController(const SurfaceCameraController* cameraController)
@ -88,6 +91,8 @@ Forceps::~Forceps()
void Forceps::update(float dt)
{
modelInstance.setActive(active);
// Update tweener
tweener->update(dt);
@ -368,6 +373,7 @@ void Lens::update(float dt)
modelInstance.setTranslation(translation);
modelInstance.setRotation(rotation);
*/
modelInstance.setActive(active);
Quaternion alignment = glm::angleAxis(cameraController->getAzimuth() + glm::radians(90.0f), Vector3(0, 1, 0));
Quaternion rotation = glm::normalize(alignment);
@ -398,6 +404,8 @@ Brush::~Brush()
void Brush::update(float dt)
{
modelInstance.setActive(active);
Quaternion alignment = glm::angleAxis(cameraController->getAzimuth(), Vector3(0, 1, 0));
Quaternion rotation = glm::normalize(alignment);
Vector3 translation = pick + Vector3(0, hoverDistance, 0);

+ 3
- 1
src/materials.hpp View File

@ -62,7 +62,9 @@ public:
albedoOpacityMap(nullptr),
metalnessRoughnessMap(nullptr),
normalOcclusionMap(nullptr),
flags((unsigned int)Flags::OBJECT)
flags((unsigned int)Flags::OBJECT),
shadowCaster(true),
shadowReceiver(true)
{};
virtual ~PhysicalMaterial() {};
virtual unsigned int getMaterialFormatID() const;

+ 93
- 20
src/render-passes.cpp View File

@ -22,15 +22,32 @@
#include <iostream>
ShadowMapRenderPass::ShadowMapRenderPass():
depthShader(nullptr)
unskinnedShader(nullptr),
skinnedShader(nullptr)
{
modelViewProjectionParam = parameterSet.addParameter("modelViewProjection", ShaderParameter::Type::MATRIX_4, 1);
maxBoneCount = 64;
modelViewProjectionParam = parameterSet.addParameter("modelViewProjectionMatrix", ShaderParameter::Type::MATRIX_4, 1);
matrixPaletteParam = parameterSet.addParameter("matrixPalette", ShaderParameter::Type::MATRIX_4, maxBoneCount);
}
bool ShadowMapRenderPass::load(const RenderContext* renderContext)
{
depthShader = shaderLoader.load("data/shaders/depth-pass.glsl", &parameterSet);
if (!depthShader)
// Load unskinned shader
shaderLoader.undefine();
shaderLoader.define("VERTEX_POSITION", EMERGENT_VERTEX_POSITION);
unskinnedShader = shaderLoader.load("data/shaders/depth-pass.glsl", &parameterSet);
if (!unskinnedShader)
{
return false;
}
// Load skinned shader
shaderLoader.define("SKINNED");
shaderLoader.define("VERTEX_BONE_INDICES", EMERGENT_VERTEX_BONE_INDICES);
shaderLoader.define("VERTEX_BONE_WEIGHTS", EMERGENT_VERTEX_BONE_WEIGHTS);
shaderLoader.define("MAX_BONE_COUNT", maxBoneCount);
skinnedShader = shaderLoader.load("data/shaders/depth-pass.glsl", &parameterSet);
if (!skinnedShader)
{
return false;
}
@ -40,8 +57,11 @@ bool ShadowMapRenderPass::load(const RenderContext* renderContext)
void ShadowMapRenderPass::unload()
{
delete depthShader;
depthShader = nullptr;
delete unskinnedShader;
unskinnedShader = nullptr;
delete skinnedShader;
skinnedShader = nullptr;
}
void ShadowMapRenderPass::render(RenderContext* renderContext)
@ -51,7 +71,6 @@ void ShadowMapRenderPass::render(RenderContext* renderContext)
glViewport(0, 0, renderTarget->width, renderTarget->height);
// Clear the framebuffer depth
glClearDepth(1.0);
glClear(GL_DEPTH_BUFFER_BIT);
// Enable depth testing
@ -59,43 +78,68 @@ void ShadowMapRenderPass::render(RenderContext* renderContext)
glDepthMask(GL_TRUE);
glDepthFunc(GL_LESS);
// Enable backface culling
glEnable(GL_CULL_FACE);
glCullFace(GL_BACK);
// Draw back faces
glDisable(GL_CULL_FACE);
// Disable alpha blending
glDisable(GL_BLEND);
// Bind shader
depthShader->bind();
const Camera& camera = *(renderContext->camera);
const std::list<RenderOperation>* operations = renderContext->queue->getOperations();
const std::list<RenderOperation>* operations = renderContext->queue->getOperations();
Shader* shader = nullptr;
// Render operations
for (const RenderOperation& operation: *operations)
{
{
// Skip render operations with unsupported materials
if (operation.material->getMaterialFormatID() != static_cast<unsigned int>(MaterialFormat::PHYSICAL))
{
continue;
}
const PhysicalMaterial* material = static_cast<const PhysicalMaterial*>(operation.material);
// 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 = camera.getViewProjection() * modelMatrix;
depthShader->setParameter(modelViewProjectionParam, modelViewProjectionMatrix);
Matrix4 modelViewProjectionMatrix = camera.getViewProjection() * modelMatrix;
shader->setParameter(modelViewProjectionParam, modelViewProjectionMatrix);
glBindVertexArray(operation.vao);
glDrawElementsBaseVertex(GL_TRIANGLES, operation.triangleCount * 3, GL_UNSIGNED_INT, (void*)0, operation.indexOffset);
}
glBindFramebuffer(GL_FRAMEBUFFER, 0);
}
@ -234,6 +278,10 @@ void SoilRenderPass::unload()
void SoilRenderPass::render(RenderContext* renderContext)
{
// Bind framebuffer and setup viewport
glBindFramebuffer(GL_FRAMEBUFFER, renderTarget->framebuffer);
glViewport(0, 0, renderTarget->width, renderTarget->height);
// Bind shader
shader->bind();
@ -313,6 +361,8 @@ LightingRenderPass::LightingRenderPass():
modelViewProjectionParam = parameterSet.addParameter("modelViewProjectionMatrix", ShaderParameter::Type::MATRIX_4, 1);
normalModelViewParam = parameterSet.addParameter("normalModelViewMatrix", ShaderParameter::Type::MATRIX_3, 1);
normalModelParam = parameterSet.addParameter("normalModelMatrix", ShaderParameter::Type::MATRIX_3, 1);
lightViewProjectionParam = parameterSet.addParameter("lightViewProjectionMatrix", ShaderParameter::Type::MATRIX_4, 1);
shadowMapParam = parameterSet.addParameter("shadowMap", ShaderParameter::Type::INT, 1);
cameraPositionParam = parameterSet.addParameter("cameraPosition", ShaderParameter::Type::VECTOR_3, 1);
directionalLightCountParam = parameterSet.addParameter("directionalLightCount", ShaderParameter::Type::INT, 1);
directionalLightColorsParam = parameterSet.addParameter("directionalLightColors", ShaderParameter::Type::VECTOR_3, 1);
@ -789,6 +839,14 @@ void LightingRenderPass::render(RenderContext* renderContext)
const Camera& camera = *(renderContext->camera);
std::list<RenderOperation>* operations = renderContext->queue->getOperations();
// Bind framebuffer and setup viewport
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);
// Enable depth testing
glEnable(GL_DEPTH_TEST);
glDepthMask(GL_TRUE);
@ -808,13 +866,19 @@ void LightingRenderPass::render(RenderContext* renderContext)
Vector3 directionalLightDirections[3];
directionalLightColors[0] = Vector3(1);
directionalLightDirections[0] = glm::normalize(Vector3(camera.getView() * -Vector4(0, 0, -1, 0)));
// Calculate the (light-space) view-projection matrix
Matrix4 lightViewProjectionMatrix = shadowCamera->getViewProjection();
glActiveTexture(GL_TEXTURE3);
glBindTexture(GL_TEXTURE_CUBE_MAP, diffuseCubemap->getTextureID());
glActiveTexture(GL_TEXTURE4);
glBindTexture(GL_TEXTURE_CUBE_MAP, specularCubemap->getTextureID());
glActiveTexture(GL_TEXTURE5);
glBindTexture(GL_TEXTURE_2D, shadowMap);
Shader* shader = nullptr;
Texture* albedoOpacityMap = nullptr;
Texture* metalnessRoughnessMap = nullptr;
@ -859,11 +923,13 @@ void LightingRenderPass::render(RenderContext* renderContext)
shader->bind();
// Pass static params
shader->setParameter(lightViewProjectionParam, lightViewProjectionMatrix);
shader->setParameter(albedoOpacityMapParam, 0);
shader->setParameter(metalnessRoughnessMapParam, 1);
shader->setParameter(normalOcclusionMapParam, 2);
shader->setParameter(diffuseCubemapParam, 3);
shader->setParameter(specularCubemapParam, 4);
shader->setParameter(shadowMapParam, 5);
shader->setParameter(directionalLightCountParam, directionalLightCount);
shader->setParameter(directionalLightColorsParam, 0, &directionalLightColors[0], directionalLightCount);
shader->setParameter(directionalLightDirectionsParam, 0, &directionalLightDirections[0], directionalLightCount);
@ -927,6 +993,9 @@ void LightingRenderPass::render(RenderContext* renderContext)
glBindVertexArray(operation.vao);
glDrawElementsBaseVertex(GL_TRIANGLES, operation.triangleCount * 3, GL_UNSIGNED_INT, (void*)0, operation.indexOffset);
}
glActiveTexture(GL_TEXTURE5);
glBindTexture(GL_TEXTURE_2D, 0);
}
bool LightingRenderPass::loadShader(const RenderOperation& operation)
@ -1105,6 +1174,10 @@ void DebugRenderPass::unload()
void DebugRenderPass::render(RenderContext* renderContext)
{
// Bind framebuffer and setup viewport
glBindFramebuffer(GL_FRAMEBUFFER, renderTarget->framebuffer);
glViewport(0, 0, renderTarget->width, renderTarget->height);
const Camera& camera = *(renderContext->camera);
/*

+ 7
- 1
src/render-passes.hpp View File

@ -41,9 +41,13 @@ public:
private:
ShaderParameterSet parameterSet;
const ShaderParameter* modelViewProjectionParam;
const ShaderParameter* matrixPaletteParam;
ShaderLoader shaderLoader;
Shader* depthShader;
Shader* unskinnedShader;
Shader* skinnedShader;
int maxBoneCount;
};
/**
@ -144,6 +148,8 @@ private:
const ShaderParameter* modelViewProjectionParam;
const ShaderParameter* normalModelViewParam;
const ShaderParameter* normalModelParam;
const ShaderParameter* lightViewProjectionParam;
const ShaderParameter* shadowMapParam;
const ShaderParameter* cameraPositionParam;
const ShaderParameter* directionalLightCountParam;
const ShaderParameter* directionalLightColorsParam;

Loading…
Cancel
Save