diff --git a/data b/data index 251460a..fd13a89 160000 --- a/data +++ b/data @@ -1 +1 @@ -Subproject commit 251460a52158fbf7e3523257aaf134f66240fab6 +Subproject commit fd13a89510dded63f3068561ba50b8d540220eb7 diff --git a/lib/emergent b/lib/emergent index 19d7fcd..031d4b5 160000 --- a/lib/emergent +++ b/lib/emergent @@ -1 +1 @@ -Subproject commit 19d7fcdb76c3516702a8723b2d125ed07e6dc0c9 +Subproject commit 031d4b56493568e5fc863752fa104784e3e1ff38 diff --git a/src/application.cpp b/src/application.cpp index 9f29c16..1f14faa 100644 --- a/src/application.cpp +++ b/src/application.cpp @@ -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; diff --git a/src/application.hpp b/src/application.hpp index a1fb660..f34400f 100644 --- a/src/application.hpp +++ b/src/application.hpp @@ -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; diff --git a/src/game/tool.cpp b/src/game/tool.cpp index 2cc052d..dcdb166 100644 --- a/src/game/tool.cpp +++ b/src/game/tool.cpp @@ -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); diff --git a/src/materials.hpp b/src/materials.hpp index 8817e98..3d2e8a7 100644 --- a/src/materials.hpp +++ b/src/materials.hpp @@ -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; diff --git a/src/render-passes.cpp b/src/render-passes.cpp index c9d46e1..ae8ec79 100644 --- a/src/render-passes.cpp +++ b/src/render-passes.cpp @@ -22,15 +22,32 @@ #include 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", ¶meterSet); - if (!depthShader) + // Load unskinned shader + shaderLoader.undefine(); + shaderLoader.define("VERTEX_POSITION", EMERGENT_VERTEX_POSITION); + unskinnedShader = shaderLoader.load("data/shaders/depth-pass.glsl", ¶meterSet); + 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", ¶meterSet); + 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* operations = renderContext->queue->getOperations(); + const std::list* 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(MaterialFormat::PHYSICAL)) { continue; } - const PhysicalMaterial* material = static_cast(operation.material); - // 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 = 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* 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); /* diff --git a/src/render-passes.hpp b/src/render-passes.hpp index 91b10af..7bd6980 100644 --- a/src/render-passes.hpp +++ b/src/render-passes.hpp @@ -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;