diff --git a/data b/data index 802f027..bf5d69d 160000 --- a/data +++ b/data @@ -1 +1 @@ -Subproject commit 802f027beb17f435976c1788b58e793d41a77fd5 +Subproject commit bf5d69d87ef22cf3660e8d59d4c338995411e51d diff --git a/lib/emergent b/lib/emergent index 10c8ba8..a452354 160000 --- a/lib/emergent +++ b/lib/emergent @@ -1 +1 @@ -Subproject commit 10c8ba83a87c6042fd9671a8aaac1699e7b47b1d +Subproject commit a452354a06253cc1f6b79e5646c6fd7c704448b4 diff --git a/src/application.cpp b/src/application.cpp index fc2fe6f..886c0b5 100644 --- a/src/application.cpp +++ b/src/application.cpp @@ -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); diff --git a/src/render-passes.cpp b/src/render-passes.cpp index 666da79..71f75a3 100644 --- a/src/render-passes.cpp +++ b/src/render-passes.cpp @@ -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(i % 2) * 0.5f; float y = static_cast(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* operations = renderContext->queue->getOperations(); + std::list* 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(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(i) / static_cast(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::infinity()), Vector3(-std::numeric_limits::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) diff --git a/src/render-passes.hpp b/src/render-passes.hpp index 5d50d75..5cd3b1d 100644 --- a/src/render-passes.hpp +++ b/src/render-passes.hpp @@ -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; diff --git a/src/states/title-state.cpp b/src/states/title-state.cpp index 3c38807..f6feee3 100644 --- a/src/states/title-state.cpp +++ b/src/states/title-state.cpp @@ -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);