Working on the night mode
This commit is contained in:
1 parent
e6bfe85e2e
commit
442d3a7945
18 files changed
+1060
-2
No files matched your search
@@ -9,6 +9,7 @@
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
#include <cfloat>
|
||||
#include <limits>
|
||||
#include "GameConstants.h"
|
||||
#include "Character.h"
|
||||
#include "external/nlohmann/json.hpp"
|
||||
@@ -878,6 +879,185 @@ namespace ZL
|
||||
}
|
||||
}
|
||||
|
||||
void Location::drawNightShadowDepthPass(const PointLight& light)
|
||||
{
|
||||
if (!shadowMap) return;
|
||||
static constexpr float kSpotFovY = static_cast<float>(M_PI) * 0.5f; // 90°
|
||||
shadowMap->updateSpotlightMatrix(light.position, light.direction, kSpotFovY, 0.1f, 20.0f);
|
||||
shadowMap->bind();
|
||||
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
glDepthFunc(GL_LESS);
|
||||
glEnable(GL_CULL_FACE);
|
||||
|
||||
renderer.shaderManager.PushShader("shadow_depth");
|
||||
renderer.PushPerspectiveProjectionMatrix(kSpotFovY, 1.0f, 0.1f, 20.0f);
|
||||
renderer.PushSpecialMatrix(shadowMap->getLightViewMatrix());
|
||||
|
||||
for (auto& [name, gameObj] : gameObjects) {
|
||||
renderer.DrawVertexRenderStruct(gameObj.mesh);
|
||||
}
|
||||
for (auto& intObj : interactiveObjects) {
|
||||
if (intObj.isActive && intObj.loadedObject.texture) {
|
||||
renderer.PushMatrix();
|
||||
renderer.TranslateMatrix(intObj.position);
|
||||
renderer.DrawVertexRenderStruct(intObj.loadedObject.mesh);
|
||||
renderer.PopMatrix();
|
||||
}
|
||||
}
|
||||
if (player) player->drawShadowDepth(renderer);
|
||||
for (auto& npc : npcs) npc->drawShadowDepth(renderer);
|
||||
|
||||
renderer.PopMatrix(); // light view
|
||||
renderer.PopProjectionMatrix();
|
||||
renderer.shaderManager.PopShader();
|
||||
|
||||
glDisable(GL_CULL_FACE);
|
||||
shadowMap->unbind();
|
||||
}
|
||||
|
||||
void Location::drawGameNight()
|
||||
{
|
||||
// --- Find nearest spotlight for shadow casting ---
|
||||
const PointLight* shadowLight = nullptr;
|
||||
if (player && !pointLights.empty()) {
|
||||
float minDist = FLT_MAX;
|
||||
for (const auto& pl : pointLights) {
|
||||
const float d = (pl.position - player->position).norm();
|
||||
if (d < minDist) { minDist = d; shadowLight = &pl; }
|
||||
}
|
||||
}
|
||||
const bool hasShadows = (shadowMap != nullptr && shadowLight != nullptr);
|
||||
|
||||
if (hasShadows) {
|
||||
drawNightShadowDepthPass(*shadowLight);
|
||||
}
|
||||
|
||||
// --- Main render pass ---
|
||||
glClearColor(0.01f, 0.01f, 0.05f, 1.0f);
|
||||
glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
|
||||
|
||||
const std::string mainShader = hasShadows ? "night_fog_shadow" : "night_fog";
|
||||
renderer.shaderManager.PushShader(mainShader);
|
||||
renderer.RenderUniform1i(textureUniformName, 0);
|
||||
|
||||
if (hasShadows) {
|
||||
renderer.RenderUniform1i("uShadowMap", 1);
|
||||
glActiveTexture(GL_TEXTURE1);
|
||||
glBindTexture(GL_TEXTURE_2D, shadowMap->getDepthTexture());
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
}
|
||||
|
||||
const float playerEyePos[3] = { 0.0f, 0.0f, -Environment::zoom };
|
||||
renderer.RenderUniform3fv("uPlayerEyePos", playerEyePos);
|
||||
|
||||
renderer.PushPerspectiveProjectionMatrix(1.0 / 1.5,
|
||||
static_cast<float>(Environment::width) / static_cast<float>(Environment::height),
|
||||
Environment::CONST_Z_NEAR, Environment::CONST_Z_FAR);
|
||||
renderer.PushMatrix();
|
||||
|
||||
renderer.LoadIdentity();
|
||||
renderer.TranslateMatrix({ 0, 0, -1.0f * Environment::zoom });
|
||||
|
||||
renderer.RotateMatrix(Eigen::Quaternionf(Eigen::AngleAxisf(cameraInclination, Eigen::Vector3f::UnitX())).toRotationMatrix());
|
||||
renderer.RotateMatrix(Eigen::Quaternionf(Eigen::AngleAxisf(cameraAzimuth, Eigen::Vector3f::UnitY())).toRotationMatrix());
|
||||
const Eigen::Vector3f& camTarget = player ? player->position : Eigen::Vector3f::Zero();
|
||||
renderer.TranslateMatrix({ -camTarget.x(), -camTarget.y(), -camTarget.z() });
|
||||
|
||||
cameraViewMatrix = renderer.GetCurrentModelViewMatrix();
|
||||
|
||||
// Transform spot lights to eye space and build uniform arrays (max 4)
|
||||
static constexpr int MAX_POINT_LIGHTS = 4;
|
||||
float plPosEye[MAX_POINT_LIGHTS * 3] = {};
|
||||
float plDirEye[MAX_POINT_LIGHTS * 3] = {};
|
||||
float plColors[MAX_POINT_LIGHTS * 3] = {};
|
||||
const Eigen::Matrix3f camRot = cameraViewMatrix.block<3, 3>(0, 0);
|
||||
const int lightCount = min(static_cast<int>(pointLights.size()), MAX_POINT_LIGHTS);
|
||||
for (int i = 0; i < lightCount; ++i) {
|
||||
const Eigen::Vector4f worldPos(pointLights[i].position.x(), pointLights[i].position.y(), pointLights[i].position.z(), 1.0f);
|
||||
const Eigen::Vector4f eyePos4 = cameraViewMatrix * worldPos;
|
||||
plPosEye[i * 3 + 0] = eyePos4.x();
|
||||
plPosEye[i * 3 + 1] = eyePos4.y();
|
||||
plPosEye[i * 3 + 2] = eyePos4.z();
|
||||
const Eigen::Vector3f eyeDir = camRot * pointLights[i].direction;
|
||||
plDirEye[i * 3 + 0] = eyeDir.x();
|
||||
plDirEye[i * 3 + 1] = eyeDir.y();
|
||||
plDirEye[i * 3 + 2] = eyeDir.z();
|
||||
plColors[i * 3 + 0] = pointLights[i].color.x();
|
||||
plColors[i * 3 + 1] = pointLights[i].color.y();
|
||||
plColors[i * 3 + 2] = pointLights[i].color.z();
|
||||
}
|
||||
|
||||
// Compute light-from-camera matrix for shadow lookup
|
||||
Eigen::Matrix4f lightFromCamera = Eigen::Matrix4f::Identity();
|
||||
if (hasShadows) {
|
||||
lightFromCamera = shadowMap->getLightSpaceMatrix() * cameraViewMatrix.inverse();
|
||||
renderer.RenderUniformMatrix4fv("uLightFromCamera", false, lightFromCamera.data());
|
||||
// Pass first light's eye-space direction as uLightDir for shadow bias
|
||||
renderer.RenderUniform3fv("uLightDir", plDirEye);
|
||||
}
|
||||
|
||||
renderer.RenderUniform1i("uPointLightCount", lightCount);
|
||||
if (lightCount > 0) {
|
||||
renderer.RenderUniform3fvArray("uPointLightPos[0]", lightCount, plPosEye);
|
||||
renderer.RenderUniform3fvArray("uPointLightDir[0]", lightCount, plDirEye);
|
||||
renderer.RenderUniform3fvArray("uPointLightColor[0]", lightCount, plColors);
|
||||
}
|
||||
|
||||
renderer.RenderUniform1f("uAlpha", 1.0f);
|
||||
for (auto& [name, gameObj] : gameObjects) {
|
||||
if (!gameObj.texture) continue;
|
||||
glBindTexture(GL_TEXTURE_2D, gameObj.texture->getTexID());
|
||||
renderer.DrawVertexRenderStruct(gameObj.mesh);
|
||||
}
|
||||
|
||||
for (auto& intObj : interactiveObjects) {
|
||||
if (intObj.isActive) {
|
||||
intObj.draw(renderer);
|
||||
}
|
||||
}
|
||||
|
||||
renderer.RenderUniform1f("uAlpha", 1.0f);
|
||||
if (player) player->prepareHitSparksForDraw(cameraViewMatrix);
|
||||
for (auto& npc : npcs) npc->prepareHitSparksForDraw(cameraViewMatrix);
|
||||
for (auto& tz : teleportZones) tz.prepareForDraw(cameraViewMatrix);
|
||||
|
||||
if (hasShadows) {
|
||||
if (player) player->drawNightWithShadow(renderer, plPosEye, plDirEye, plColors, lightCount, lightFromCamera, shadowMap->getDepthTexture());
|
||||
for (auto& npc : npcs) npc->drawNightWithShadow(renderer, plPosEye, plDirEye, plColors, lightCount, lightFromCamera, shadowMap->getDepthTexture());
|
||||
} else {
|
||||
if (player) player->drawNight(renderer, plPosEye, plDirEye, plColors, lightCount);
|
||||
for (auto& npc : npcs) npc->drawNight(renderer, plPosEye, plDirEye, plColors, lightCount);
|
||||
}
|
||||
|
||||
for (auto& tz : teleportZones) tz.draw(renderer, Environment::zoom, Environment::width, Environment::height);
|
||||
|
||||
if (editorMode == EditorMode::Navigation) {
|
||||
editor.drawNavigation();
|
||||
editor.drawPoints();
|
||||
}
|
||||
if (editorMode == EditorMode::InteractiveObjects) {
|
||||
editor.drawInteractiveObjectBounds();
|
||||
}
|
||||
|
||||
renderer.PopMatrix();
|
||||
renderer.PopProjectionMatrix();
|
||||
renderer.shaderManager.PopShader();
|
||||
|
||||
if (npcNameText) {
|
||||
Eigen::Matrix4f proj = MakePerspectiveMatrix(1.0f / 1.5f,
|
||||
static_cast<float>(Environment::width) / static_cast<float>(Environment::height),
|
||||
Environment::CONST_Z_NEAR, Environment::CONST_Z_FAR);
|
||||
for (auto& npc : npcs) {
|
||||
if (npc) npc->drawName(*npcNameText, cameraViewMatrix, proj);
|
||||
}
|
||||
if (player) player->drawHealthBar(renderer, cameraViewMatrix, proj);
|
||||
for (auto& npc : npcs) {
|
||||
if (npc) npc->drawHealthBar(renderer, cameraViewMatrix, proj);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool Location::setNavigationAreaAvailable(const std::string& areaName, bool available)
|
||||
{
|
||||
if (!navigation) return false;
|
||||
|
||||
Reference in new issue
Block a user