diff --git a/data b/data index 80851f2..f6fed6a 160000 --- a/data +++ b/data @@ -1 +1 @@ -Subproject commit 80851f29bad4062b4505549f572f853db7c50983 +Subproject commit f6fed6a858a3b4d71b879df0267b2881f270a18f diff --git a/src/application.hpp b/src/application.hpp index 74bb643..e3a205c 100644 --- a/src/application.hpp +++ b/src/application.hpp @@ -158,8 +158,6 @@ public: Camera uiCamera; Camera bgCamera; DirectionalLight sunlight; - Spotlight lensHotspot; - Spotlight lensFalloff; ModelInstance forcepsModelInstance; ModelInstance navigatorObject; ModelInstance antModelInstance; diff --git a/src/game/tool.cpp b/src/game/tool.cpp index 9244e14..86c9407 100644 --- a/src/game/tool.cpp +++ b/src/game/tool.cpp @@ -349,7 +349,15 @@ Lens::Lens(const Model* model) // Setup model instance modelInstance.setModel(model); - unfocusedDistance = 15.0f; + // Setup spotlight + spotlight.setColor(Vector3(1.0f)); + spotlight.setIntensity(10000.0f); + spotlight.setAttenuation(Vector3(1, 0, 1)); + spotlight.setCutoff(glm::radians(45.0f)); + spotlight.setExponent(700.0f); + spotlight.setActive(false); + + unfocusedDistance = 18.0f; focusedDistance = 12.0f; focused = false; sunDirection = Vector3(0, -1, 0); @@ -399,6 +407,7 @@ void Lens::update(float dt) modelInstance.setRotation(rotation); */ modelInstance.setActive(active); + spotlight.setActive(active); // Update tweener tweener->update(dt); @@ -420,6 +429,21 @@ void Lens::update(float dt) modelInstance.setTranslation(translation); modelInstance.setRotation(rotation); + + float spotlightDistanceFactor = (1.0 - (lensDistance - focusedDistance) / (unfocusedDistance - focusedDistance)) * 2.0f - 1.0f; + + spotlight.setTranslation(pick + sunDirection * (-lensDistance + 5.0f * spotlightDistanceFactor)); + spotlight.setDirection(sunDirection); +} + +void Lens::setActive(bool active) +{ + this->active = active; + if (!active) + { + modelInstance.setActive(active); + spotlight.setActive(active); + } } void Lens::focus() diff --git a/src/game/tool.hpp b/src/game/tool.hpp index 5de2733..9ba1bbe 100644 --- a/src/game/tool.hpp +++ b/src/game/tool.hpp @@ -55,7 +55,7 @@ public: /** * Activates or deactivates the tool. */ - void setActive(bool active); + virtual void setActive(bool active); /** * Sets the picking position. @@ -106,7 +106,6 @@ inline ModelInstance* Tool::getModelInstance() return &modelInstance; } - /** * The forceps tool can pick up ants and place them anywhere in the world. */ @@ -223,12 +222,24 @@ public: */ virtual void update(float dt); + /** + * Activates or deactivates the lens. + */ + virtual void setActive(bool active); + void focus(); void unfocus(); void setSunDirection(const Vector3& direction); + /** + * Returns the spotlight. + */ + const Spotlight* getSpotlight() const; + Spotlight* getSpotlight(); + private: + Spotlight spotlight; float unfocusedDistance; float focusedDistance; bool focused; @@ -238,6 +249,16 @@ private: Tween* ascentTween; }; +inline const Spotlight* Lens::getSpotlight() const +{ + return &spotlight; +} + +inline Spotlight* Lens::getSpotlight() +{ + return &spotlight; +} + /** * The brush tool can paint pheromones on the terrain. */ diff --git a/src/render-passes.cpp b/src/render-passes.cpp index 5615e5c..df6c2e4 100644 --- a/src/render-passes.cpp +++ b/src/render-passes.cpp @@ -681,6 +681,8 @@ LightingRenderPass::LightingRenderPass(): biasMatrix = glm::translate(Vector3(0.5f)) * glm::scale(Vector3(0.5f)); maxBoneCount = 64; + maxDirectionalLightCount = 1; + maxSpotlightCount = 1; matrixPaletteParam = parameterSet.addParameter("matrixPalette", ShaderParameter::Type::MATRIX_4, maxBoneCount); modelParam = parameterSet.addParameter("modelMatrix", ShaderParameter::Type::MATRIX_4, 1); @@ -692,8 +694,17 @@ LightingRenderPass::LightingRenderPass(): 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); - directionalLightDirectionsParam = parameterSet.addParameter("directionalLightDirections", ShaderParameter::Type::VECTOR_3, 1); + directionalLightColorsParam = parameterSet.addParameter("directionalLightColors", ShaderParameter::Type::VECTOR_3, maxDirectionalLightCount); + directionalLightDirectionsParam = parameterSet.addParameter("directionalLightDirections", ShaderParameter::Type::VECTOR_3, maxDirectionalLightCount); + + spotlightCountParam = parameterSet.addParameter("spotlightCount", ShaderParameter::Type::INT, 1); + spotlightColorsParam = parameterSet.addParameter("spotlightColors", ShaderParameter::Type::VECTOR_3, maxSpotlightCount); + spotlightPositionsParam = parameterSet.addParameter("spotlightPositions", ShaderParameter::Type::VECTOR_3, maxSpotlightCount); + spotlightAttenuationsParam = parameterSet.addParameter("spotlightAttenuations", ShaderParameter::Type::VECTOR_3, maxSpotlightCount); + spotlightDirectionsParam = parameterSet.addParameter("spotlightDirections", ShaderParameter::Type::VECTOR_3, maxSpotlightCount); + spotlightCutoffsParam = parameterSet.addParameter("spotlightCutoffs", ShaderParameter::Type::FLOAT, maxSpotlightCount); + spotlightExponentsParam = parameterSet.addParameter("spotlightExponents", ShaderParameter::Type::FLOAT, maxSpotlightCount); + albedoOpacityMapParam = parameterSet.addParameter("albedoOpacityMap", ShaderParameter::Type::INT, 1); metalnessRoughnessMapParam = parameterSet.addParameter("metalnessRoughnessMap", ShaderParameter::Type::INT, 1); normalOcclusionMapParam = parameterSet.addParameter("normalOcclusionMap", ShaderParameter::Type::INT, 1); @@ -711,8 +722,11 @@ bool LightingRenderPass::load(const RenderContext* renderContext) std::cerr << "Failed to load tree shadow" << std::endl; } - // Load unskinned shader shaderLoader.undefine(); + shaderLoader.define("MAX_DIRECTIONAL_LIGHT_COUNT", maxDirectionalLightCount); + shaderLoader.define("MAX_SPOTLIGHT_COUNT", maxSpotlightCount); + + // Load unskinned shader shaderLoader.define("TEXTURE_COUNT", 0); shaderLoader.define("VERTEX_POSITION", EMERGENT_VERTEX_POSITION); shaderLoader.define("VERTEX_NORMAL", EMERGENT_VERTEX_NORMAL); @@ -1167,12 +1181,48 @@ void LightingRenderPass::render(RenderContext* renderContext) glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - int directionalLightCount = 1; + Vector3 directionalLightColors[3]; Vector3 directionalLightDirections[3]; + + Vector3 spotlightColors[3]; + Vector3 spotlightPositions[3]; + Vector3 spotlightAttenuations[3]; + Vector3 spotlightDirections[3]; + float spotlightCutoffs[3]; + float spotlightExponents[3]; + + // Add directional light + int directionalLightCount = 1; directionalLightColors[0] = Vector3(1); directionalLightDirections[0] = glm::normalize(Vector3(camera.getView() * -Vector4(0, -2, -1, 0))); + // Add spotlights + int spotlightCount = 0; + const std::list* lights = renderContext->layer->getObjects(SceneObjectType::LIGHT); + if (lights != nullptr) + { + for (auto object: *lights) + { + const Light* light = static_cast(object); + LightType lightType = light->getLightType(); + + if (lightType == LightType::SPOTLIGHT && light->isActive()) + { + const Spotlight* spotlight = static_cast(light); + + spotlightColors[spotlightCount] = spotlight->getScaledColor(); + spotlightPositions[spotlightCount] = Vector3(camera.getView() * Vector4(spotlight->getTranslation(), 1.0f)); + spotlightAttenuations[spotlightCount] = spotlight->getAttenuation(); + spotlightDirections[spotlightCount] = glm::normalize(Vector3(camera.getView() * Vector4(-spotlight->getDirection(), 0.0f))); + spotlightCutoffs[spotlightCount] = spotlight->getCutoff(); + spotlightExponents[spotlightCount] = spotlight->getExponent(); + + ++spotlightCount; + } + } + } + // Calculate the (light-space) view-projection matrix Matrix4 lightViewProjectionMatrix = shadowMapPass->getTileMatrix(0) * biasMatrix * shadowMapPass->getCropMatrix(0) * shadowCamera->getViewProjection(); //Matrix4 lightViewProjectionMatrix = biasMatrix * shadowCamera->getViewProjection(); @@ -1240,6 +1290,15 @@ void LightingRenderPass::render(RenderContext* renderContext) shader->setParameter(directionalLightCountParam, directionalLightCount); shader->setParameter(directionalLightColorsParam, 0, &directionalLightColors[0], directionalLightCount); shader->setParameter(directionalLightDirectionsParam, 0, &directionalLightDirections[0], directionalLightCount); + + shader->setParameter(spotlightCountParam, spotlightCount); + shader->setParameter(spotlightColorsParam, 0, &spotlightColors[0], spotlightCount); + shader->setParameter(spotlightPositionsParam, 0, &spotlightPositions[0], spotlightCount); + shader->setParameter(spotlightAttenuationsParam, 0, &spotlightAttenuations[0], spotlightCount); + shader->setParameter(spotlightDirectionsParam, 0, &spotlightDirections[0], spotlightCount); + shader->setParameter(spotlightCutoffsParam, 0, &spotlightCutoffs[0], spotlightCount); + shader->setParameter(spotlightExponentsParam, 0, &spotlightExponents[0], spotlightCount); + shader->setParameter(cameraPositionParam, camera.getTranslation()); } diff --git a/src/render-passes.hpp b/src/render-passes.hpp index 56f43b2..08ca651 100644 --- a/src/render-passes.hpp +++ b/src/render-passes.hpp @@ -232,6 +232,15 @@ private: const ShaderParameter* directionalLightCountParam; const ShaderParameter* directionalLightColorsParam; const ShaderParameter* directionalLightDirectionsParam; + + const ShaderParameter* spotlightCountParam; + const ShaderParameter* spotlightColorsParam; + const ShaderParameter* spotlightPositionsParam; + const ShaderParameter* spotlightAttenuationsParam; + const ShaderParameter* spotlightDirectionsParam; + const ShaderParameter* spotlightCutoffsParam; + const ShaderParameter* spotlightExponentsParam; + const ShaderParameter* albedoOpacityMapParam; const ShaderParameter* metalnessRoughnessMapParam; const ShaderParameter* normalOcclusionMapParam; @@ -242,6 +251,8 @@ private: Shader* skinnedShader; int maxBoneCount; + int maxDirectionalLightCount; + int maxSpotlightCount; ShaderLoader shaderLoader; std::map shaderCache; //Shader* lightingShader; diff --git a/src/states/game-state.cpp b/src/states/game-state.cpp index 5ff9e3a..c9da9cb 100644 --- a/src/states/game-state.cpp +++ b/src/states/game-state.cpp @@ -63,6 +63,7 @@ void GameState::enter() // Add tools to scene application->defaultLayer->addObject(application->forceps->getModelInstance()); application->defaultLayer->addObject(application->lens->getModelInstance()); + application->defaultLayer->addObject(application->lens->getSpotlight()); application->defaultLayer->addObject(application->brush->getModelInstance()); @@ -70,9 +71,7 @@ void GameState::enter() application->defaultLayer->addObject(&application->currentLevel->terrainSurface); //application->defaultLayer->addObject(&application->currentLevel->terrainSubsurface); //application->defaultLayer->addObject(&application->biomeFloorModelInstance); - - - + // Spawn ants Navmesh* navmesh = application->currentLevel->terrain.getSurfaceNavmesh(); for (int i = 0; i < 200; ++i) @@ -309,6 +308,7 @@ void GameState::exit() application->defaultLayer->removeObject(&application->biomeFloorModelInstance); application->defaultLayer->removeObject(application->forceps->getModelInstance()); application->defaultLayer->removeObject(application->lens->getModelInstance()); + application->defaultLayer->removeObject(application->lens->getSpotlight()); application->defaultLayer->removeObject(application->brush->getModelInstance()); for (std::size_t i = 0; i < application->colony->getAntCount(); ++i) {