Browse Source

Reconsolidate PSSM code

master
C. J. Howard 6 years ago
parent
commit
631de3eba8
6 changed files with 74 additions and 140 deletions
  1. +1
    -1
      data
  2. +1
    -1
      lib/emergent
  3. +2
    -2
      src/application.cpp
  4. +61
    -129
      src/render-passes.cpp
  5. +8
    -6
      src/render-passes.hpp
  6. +1
    -1
      src/states/title-state.cpp

+ 1
- 1
data

@ -1 +1 @@
Subproject commit 802f027beb17f435976c1788b58e793d41a77fd5
Subproject commit bf5d69d87ef22cf3660e8d59d4c338995411e51d

+ 1
- 1
lib/emergent

@ -1 +1 @@
Subproject commit 10c8ba83a87c6042fd9671a8aaac1699e7b47b1d
Subproject commit a452354a06253cc1f6b79e5646c6fd7c704448b4

+ 2
- 2
src/application.cpp View File

@ -775,13 +775,13 @@ bool Application::loadScene()
// 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);
glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT32, 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);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_REF_TO_TEXTURE);
// Attach depth texture to framebuffer
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, shadowMapDepthTexture, 0);

+ 61
- 129
src/render-passes.cpp View File

@ -201,24 +201,19 @@ bool ShadowMapRenderPass::load(const RenderContext* renderContext)
// Set maximum number of bones for skinned meshes
maxBoneCount = 64;
// Set number of frustum splits
frustumSplitCount = 4;
// Create array of split distances
splitDistances = new float[frustumSplitCount + 1];
// Create split view frustum
splitViewFrustum = new SplitViewFrustum(frustumSplitCount);
splitViewFrustum = new SplitViewFrustum(4);
splitViewFrustum->setSplitSchemeWeight(0.85f);
// Determine resolution of shadow maps
shadowMapResolution = 4096;
croppedShadowMapResolution = shadowMapResolution >> 1;
// Allocate viewports
croppedShadowMapViewports = new Vector4[frustumSplitCount];
croppedShadowMapViewports = new Vector4[splitViewFrustum->getSubfrustumCount()];
// Setup viewports
for (int i = 0; i < frustumSplitCount; ++i)
for (int i = 0; i < splitViewFrustum->getSubfrustumCount(); ++i)
{
int x = i % 2;
int y = i / 2;
@ -231,12 +226,12 @@ bool ShadowMapRenderPass::load(const RenderContext* renderContext)
}
// Allocate matrices
cropMatrices = new Matrix4[frustumSplitCount];
tileMatrices = new Matrix4[frustumSplitCount];
cropMatrices = new Matrix4[splitViewFrustum->getSubfrustumCount()];
tileMatrices = new Matrix4[splitViewFrustum->getSubfrustumCount()];
// Setup tile matrices
Matrix4 tileScale = glm::scale(Vector3(0.5f, 0.5f, 1.0f));
for (int i = 0; i < frustumSplitCount; ++i)
for (int i = 0; i < splitViewFrustum->getSubfrustumCount(); ++i)
{
float x = static_cast<float>(i % 2) * 0.5f;
float y = static_cast<float>(i / 2) * 0.5f;
@ -281,9 +276,6 @@ void ShadowMapRenderPass::unload()
delete[] croppedShadowMapViewports;
croppedShadowMapViewports = nullptr;
delete[] splitDistances;
splitDistances = nullptr;
delete splitViewFrustum;
splitViewFrustum = nullptr;
@ -312,133 +304,40 @@ void ShadowMapRenderPass::render(RenderContext* renderContext)
// Draw front and back faces
glEnable(GL_CULL_FACE);
glCullFace(GL_BACK);
// Disable alpha blending
glDisable(GL_BLEND);
//const Camera& lightCamera = *(renderContext->camera);
const std::list<RenderOperation>* operations = renderContext->queue->getOperations();
std::list<RenderOperation>* operations = renderContext->queue->getOperations();
Shader* shader = nullptr;
GLuint boundVAO = 0;
// 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)
{
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(), Vector3(0, 1, 0));
splitViewFrustum->setMatrices(viewCamera->getView(), viewCamera->getProjection());
// Calculate split distances
float clipNear = viewCamera->getClipNear();
float clipFar = viewCamera->getClipFar();
float splitSchemeWeight = 0.85f;
for (std::size_t i = 1; i < frustumSplitCount; ++i)
{
float part = static_cast<float>(i) / static_cast<float>(frustumSplitCount);
// Calculate uniform split distance
float uniformSplitDistance = clipNear + (clipFar - clipNear) * part;
// Calculate logarithmic split distance
float logSplitDistance = clipNear * std::pow(clipFar / clipNear, part);
// Interpolate between uniform and logarithmic split distances
splitDistances[i] = logSplitDistance * splitSchemeWeight + uniformSplitDistance * (1.0f - splitSchemeWeight);
}
splitDistances[0] = clipNear;
splitDistances[frustumSplitCount] = clipFar;
// Sort operations
operations->sort(RenderOpCompare());
// For each frustum split
for (int i = 0; i < frustumSplitCount; ++i)
for (int i = 0; i < splitViewFrustum->getSubfrustumCount(); ++i)
{
// Calculate crop matrix
{
ViewFrustum frustumSplit;
// Determine near and far distances for this subfrustum
float splitNear = splitDistances[i];
float splitFar = splitDistances[i + 1];
Matrix4 splitView = viewCamera->getView();
// Calculate subfrustum projection matrix
Matrix4 splitProjection = glm::ortho(lightCamera->getClipLeft(), lightCamera->getClipRight(), lightCamera->getClipBottom(), lightCamera->getClipTop(), splitNear, splitFar);
splitProjection = viewCamera->getProjection();
splitProjection[2][2] = -(splitFar + splitNear) / (splitFar - splitNear);
splitProjection[3][2] = -(2.0f * splitFar * splitNear) / (splitFar - splitNear);
// Set subfrustum matrices
frustumSplit.setMatrices(splitView, splitProjection);
const ViewFrustum& subfrustum = splitViewFrustum->getSubfrustum(i);
// Create AABB containing the frustum split corners
// Frustum corners in NDC-space
Vector3 splitCorners[8] =
{
Vector3(-1.0f, 1.0f, -1.0f),
Vector3( 1.0f, 1.0f, -1.0f),
Vector3(-1.0f, -1.0f, -1.0f),
Vector3( 1.0f, -1.0f, -1.0f),
Vector3(-1.0f, 1.0f, 1.0f),
Vector3( 1.0f, 1.0f, 1.0f),
Vector3(-1.0f, -1.0f, 1.0f),
Vector3( 1.0f, -1.0f, 1.0f)
};
Matrix4 splitInverseViewProjection = glm::inverse(frustumSplit.getViewProjectionMatrix());
for (int j = 0; j < 8; ++j)
{
Vector4 transformedCorner = splitInverseViewProjection * Vector4(splitCorners[j], 1.0f);
splitCorners[j] = Vector3(transformedCorner) / transformedCorner.w;
}
AABB frustumSplitBounds(splitCorners[0], splitCorners[0]);
// Create AABB containing the subfrustum corners
AABB subfrustumBounds(subfrustum.getCorner(0), subfrustum.getCorner(0));
for (std::size_t j = 1; j < 8; ++j)
{
frustumSplitBounds.add(splitCorners[j]);
}
AABB croppingBounds(Vector3(std::numeric_limits<float>::infinity()), Vector3(-std::numeric_limits<float>::infinity()));
for (int j = 0; j < 8; ++j)
{
Vector3 minPoint = frustumSplitBounds.getMin();
Vector3 maxPoint = frustumSplitBounds.getMax();
Vector3 aabbCorners[8] =
{
minPoint,
Vector3(minPoint.x, minPoint.y, maxPoint.z),
Vector3(minPoint.x, maxPoint.y, minPoint.z),
Vector3(minPoint.x, maxPoint.y, maxPoint.z),
Vector3(maxPoint.x, minPoint.y, minPoint.z),
Vector3(maxPoint.x, minPoint.y, maxPoint.z),
Vector3(maxPoint.x, maxPoint.y, minPoint.z),
maxPoint
};
Vector4 transformedPoint = lightCamera->getViewProjection() * Vector4(aabbCorners[j], 1.0f);
croppingBounds.add(Vector3(transformedPoint / transformedPoint.w));
subfrustumBounds.add(subfrustum.getCorner(j));
}
// Transform frustum split bounds into light's clip space
//AABB croppingBounds = frustumSplitBounds.transformed(lightCamera->getView());
// Transform subfrustum bounds into light's clip space
AABB croppingBounds = subfrustumBounds.transformed(lightCamera->getViewProjection());
Vector3 cropMax = croppingBounds.getMax();
Vector3 cropMin = croppingBounds.getMin();
//cropMin.z = 0.0f;
// Calculate scale
Vector3 scale;
@ -517,14 +416,41 @@ void ShadowMapRenderPass::render(RenderContext* renderContext)
Matrix4 modelViewProjectionMatrix = croppedViewProjection * modelMatrix;
shader->setParameter(modelViewProjectionParam, modelViewProjectionMatrix);
glBindVertexArray(operation.vao);
if (boundVAO != operation.vao)
{
glBindVertexArray(operation.vao);
boundVAO = operation.vao;
}
glDrawElementsBaseVertex(GL_TRIANGLES, operation.triangleCount * 3, GL_UNSIGNED_INT, (void*)0, operation.indexOffset);
}
}
glBindFramebuffer(GL_FRAMEBUFFER, 0);
}
bool ShadowMapRenderPass::RenderOpCompare::operator()(const RenderOperation& opA, const RenderOperation& opB) const
{
// If A is rigged
if (opA.pose != nullptr)
{
// And B is rigged
if (opB.pose != nullptr)
{
// Sort by VAO ID
return (opA.vao <= opB.vao);
}
else
{
// Render A first
return true;
}
}
// Sort by VAO ID
return (opA.vao <= opB.vao);
}
LightingRenderPass::LightingRenderPass():
shadowMap(0),
shadowCamera(nullptr),
@ -1041,11 +967,9 @@ void LightingRenderPass::render(RenderContext* renderContext)
Vector4 splitDistances;
for (int i = 0; i < 4; ++i)
{
splitDistances[i] = shadowMapPass->getSplitDistance(i + 1);
splitDistances[i] = shadowMapPass->getSplitViewFrustum().getSplitDistance(i + 1);
}
Vector3 directionalLightColors[3];
Vector3 directionalLightDirections[3];
@ -1107,6 +1031,7 @@ void LightingRenderPass::render(RenderContext* renderContext)
glBindTexture(GL_TEXTURE_2D, shadowMap);
Shader* shader = nullptr;
GLuint boundVAO = 0;
Texture* albedoOpacityMap = nullptr;
Texture* metalnessRoughnessMap = nullptr;
Texture* normalOcclusionMap = nullptr;
@ -1114,6 +1039,8 @@ void LightingRenderPass::render(RenderContext* renderContext)
// Sort operations
operations->sort(RenderOpCompare());
int switches = 0;
// Render operations
for (const RenderOperation& operation: *operations)
{
@ -1227,12 +1154,17 @@ void LightingRenderPass::render(RenderContext* renderContext)
shader->setParameter(normalModelViewParam, normalModelViewMatrix);
shader->setParameter(normalModelParam, normalModelMatrix);
glBindVertexArray(operation.vao);
if (boundVAO != operation.vao)
{
glBindVertexArray(operation.vao);
boundVAO = operation.vao;
}
glDrawElementsBaseVertex(GL_TRIANGLES, operation.triangleCount * 3, GL_UNSIGNED_INT, (void*)0, operation.indexOffset);
}
glActiveTexture(GL_TEXTURE5);
glBindTexture(GL_TEXTURE_2D, 0);
glBindTexture(GL_TEXTURE_2D, 0);
}
bool LightingRenderPass::loadShader(const RenderOperation& operation)

+ 8
- 6
src/render-passes.hpp View File

@ -98,14 +98,18 @@ public:
inline void setViewCamera(const Camera* camera) { this->viewCamera = camera; }
inline void setLightCamera(Camera* camera) { this->lightCamera = camera; }
inline float getSplitDistance(std::size_t index) const { return splitDistances[index]; }
inline int getFrustumSplitCount() const { return frustumSplitCount; }
inline const ViewFrustum& getSplitViewFrustum(std::size_t index) const { return splitViewFrustum->getSubfrustum(index); }
inline const SplitViewFrustum& getSplitViewFrustum() const { return *splitViewFrustum; }
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:
class RenderOpCompare
{
public:
// Sort render opations
bool operator()(const RenderOperation& opA, const RenderOperation& opB) const;
};
ShaderParameterSet parameterSet;
const ShaderParameter* modelViewProjectionParam;
const ShaderParameter* matrixPaletteParam;
@ -116,8 +120,6 @@ private:
Shader* skinnedShader;
int maxBoneCount;
int frustumSplitCount;
float* splitDistances;
int shadowMapResolution;
int croppedShadowMapResolution;
Vector4* croppedShadowMapViewports;

+ 1
- 1
src/states/title-state.cpp View File

@ -43,7 +43,7 @@ void TitleState::enter()
glm::radians(30.0f),
application->resolution.x / application->resolution.y,
0.5f,
1000.0f);
500.0f);
// Setup camera controller
application->orbitCam->attachCamera(&application->camera);

Loading…
Cancel
Save