Added dawn

This commit is contained in:
Vladislav Khorev 2026-06-04 18:01:51 +03:00
parent 83b92e9881
commit c8d743b932
13 changed files with 88 additions and 40 deletions

View File

@ -4,6 +4,8 @@ uniform int uPointLightCount;
uniform vec3 uPointLightPos[4];
uniform vec3 uPointLightDir[4];
uniform vec3 uPointLightColor[4];
uniform vec3 uAmbientColor;
uniform vec3 uFogColor;
varying vec2 texCoord;
varying float fogDistance;
@ -21,8 +23,7 @@ void main()
if (color.a < 0.1)
discard;
float ambient = 0.37;
vec3 lighting = vec3(ambient);
vec3 lighting = uAmbientColor;
bool hasNormal = dot(fragNormal, fragNormal) > 0.001;
vec3 N = hasNormal ? normalize(fragNormal) : vec3(0.0);
@ -48,7 +49,7 @@ void main()
color.rgb *= lighting;
vec3 fogColor = vec3(0.01, 0.01, 0.05);
vec3 fogColor = uFogColor;
float fogFactor = clamp((fogDistance - 15.0) / 8.0, 0.0, 1.0);
color.rgb = mix(color.rgb, fogColor, fogFactor);

View File

@ -6,6 +6,8 @@ uniform int uPointLightCount;
uniform vec3 uPointLightPos[4];
uniform vec3 uPointLightDir[4];
uniform vec3 uPointLightColor[4];
uniform vec3 uAmbientColor;
uniform vec3 uFogColor;
varying vec2 texCoord;
varying vec4 fragPosLightSpace;
@ -59,8 +61,7 @@ void main()
if (color.a < 0.1)
discard;
float ambient = 0.37;
vec3 lighting = vec3(ambient);
vec3 lighting = uAmbientColor;
bool hasNormal = dot(fragNormal, fragNormal) > 0.001;
vec3 N = hasNormal ? normalize(fragNormal) : vec3(0.0);
@ -87,7 +88,7 @@ void main()
color.rgb *= lighting;
vec3 fogColor = vec3(0.01, 0.01, 0.05);
vec3 fogColor = uFogColor;
float fogFactor = clamp((fogDistance - 15.0) / 8.0, 0.0, 1.0);
color.rgb = mix(color.rgb, fogColor, fogFactor);

View File

@ -8,6 +8,8 @@ uniform int uPointLightCount;
uniform vec3 uPointLightPos[4];
uniform vec3 uPointLightDir[4];
uniform vec3 uPointLightColor[4];
uniform vec3 uAmbientColor;
uniform vec3 uFogColor;
varying vec2 texCoord;
varying vec4 fragPosLightSpace;
@ -61,8 +63,7 @@ void main()
if (color.a < 0.1)
discard;
float ambient = 0.37;
vec3 lighting = vec3(ambient);
vec3 lighting = uAmbientColor;
bool hasNormal = dot(fragNormal, fragNormal) > 0.001;
vec3 N = hasNormal ? normalize(fragNormal) : vec3(0.0);
@ -89,7 +90,7 @@ void main()
color.rgb *= lighting;
vec3 fogColor = vec3(0.01, 0.01, 0.05);
vec3 fogColor = uFogColor;
float fogFactor = clamp((fogDistance - 15.0) / 8.0, 0.0, 1.0);
color.rgb = mix(color.rgb, fogColor, fogFactor);

View File

@ -6,6 +6,8 @@ uniform int uPointLightCount;
uniform vec3 uPointLightPos[4];
uniform vec3 uPointLightDir[4];
uniform vec3 uPointLightColor[4];
uniform vec3 uAmbientColor;
uniform vec3 uFogColor;
varying vec2 texCoord;
varying float fogDistance;
@ -23,8 +25,7 @@ void main()
if (color.a < 0.1)
discard;
float ambient = 0.37;
vec3 lighting = vec3(ambient);
vec3 lighting = uAmbientColor;
bool hasNormal = dot(fragNormal, fragNormal) > 0.001;
vec3 N = hasNormal ? normalize(fragNormal) : vec3(0.0);
@ -50,7 +51,7 @@ void main()
color.rgb *= lighting;
vec3 fogColor = vec3(0.01, 0.01, 0.05);
vec3 fogColor = uFogColor;
float fogFactor = clamp((fogDistance - 15.0) / 8.0, 0.0, 1.0);
color.rgb = mix(color.rgb, fogColor, fogFactor);

View File

@ -39,6 +39,7 @@ game_api.set_darklands_callbacks(
game_api.setIntValue("day", 1)
game_api.setIntValue("need_sleep", 1)
game_api.set_player_hp(10)
game_api.set_dawn()
end
)

View File

@ -590,6 +590,7 @@ game_api.set_darklands_callbacks(
player_left_darklands = true
morning_did_open_door_index = 0
setDay1MorningSetup()
game_api.set_dawn()
local px = game_api.get_player_x()

View File

@ -903,7 +903,7 @@ void Character::drawGpuSkinningWithShadow(Renderer& renderer, const Eigen::Matri
// ==================== Night pass with point lights ====================
void Character::drawNight(Renderer& renderer, const float* pointLightPosEye, const float* pointLightDirEye, const float* pointLightColors, int pointLightCount) {
void Character::drawNight(Renderer& renderer, const float* pointLightPosEye, const float* pointLightDirEye, const float* pointLightColors, int pointLightCount, const float* ambientColor, const float* fogColor) {
if (!enabled) return;
if (hitSparkEmitter.isConfigured() && hitSparkEmitter.getActiveParticleCount() > 0) {
hitSparkEmitter.draw(renderer, 1.0f, Environment::width, Environment::height, false);
@ -915,13 +915,13 @@ void Character::drawNight(Renderer& renderer, const float* pointLightPosEye, con
if (!isPlayer && hp <= 0) return;
if (useGpuSkinning) {
drawNightGpuSkinning(renderer, pointLightPosEye, pointLightDirEye, pointLightColors, pointLightCount);
drawNightGpuSkinning(renderer, pointLightPosEye, pointLightDirEye, pointLightColors, pointLightCount, ambientColor, fogColor);
} else {
drawNightCpu(renderer, pointLightPosEye, pointLightDirEye, pointLightColors, pointLightCount);
drawNightCpu(renderer, pointLightPosEye, pointLightDirEye, pointLightColors, pointLightCount, ambientColor, fogColor);
}
}
void Character::drawNightGpuSkinning(Renderer& renderer, const float* plPosEye, const float* plDirEye, const float* plColors, int plCount) {
void Character::drawNightGpuSkinning(Renderer& renderer, const float* plPosEye, const float* plDirEye, const float* plColors, int plCount, const float* ambientColor, const float* fogColor) {
AnimationState drawState = resolveActiveState();
auto it = animations.find(drawState);
if (it == animations.end()) return;
@ -933,6 +933,8 @@ void Character::drawNightGpuSkinning(Renderer& renderer, const float* plPosEye,
renderer.shaderManager.PushShader(nightSkinningShader);
renderer.RenderUniform1i(textureUniformName, 0);
renderer.RenderUniform3fv("uAmbientColor", ambientColor);
renderer.RenderUniform3fv("uFogColor", fogColor);
const float playerEyePosNight[3] = { 0.0f, 0.0f, -Environment::zoom };
renderer.RenderUniform3fv("uPlayerEyePos", playerEyePosNight);
renderer.RenderUniform1i("uPointLightCount", plCount);
@ -969,6 +971,8 @@ void Character::drawNightGpuSkinning(Renderer& renderer, const float* plPosEye,
renderer.shaderManager.PushShader("night_fog");
renderer.RenderUniform1i(textureUniformName, 0);
renderer.RenderUniform3fv("uAmbientColor", ambientColor);
renderer.RenderUniform3fv("uFogColor", fogColor);
renderer.RenderUniform3fv("uPlayerEyePos", playerEyePosNight);
renderer.RenderUniform1i("uPointLightCount", plCount);
if (plCount > 0) {
@ -983,7 +987,7 @@ void Character::drawNightGpuSkinning(Renderer& renderer, const float* plPosEye,
renderer.shaderManager.PopShader();
}
void Character::drawNightCpu(Renderer& renderer, const float* plPosEye, const float* plDirEye, const float* plColors, int plCount) {
void Character::drawNightCpu(Renderer& renderer, const float* plPosEye, const float* plDirEye, const float* plColors, int plCount, const float* ambientColor, const float* fogColor) {
AnimationState drawState = resolveActiveState();
auto it = animations.find(drawState);
if (it == animations.end()) return;
@ -992,6 +996,8 @@ void Character::drawNightCpu(Renderer& renderer, const float* plPosEye, const fl
renderer.shaderManager.PushShader(nightShader);
renderer.RenderUniform1i(textureUniformName, 0);
renderer.RenderUniform3fv("uAmbientColor", ambientColor);
renderer.RenderUniform3fv("uFogColor", fogColor);
const float playerEyePosNight[3] = { 0.0f, 0.0f, -Environment::zoom };
renderer.RenderUniform3fv("uPlayerEyePos", playerEyePosNight);
renderer.RenderUniform1i("uPointLightCount", plCount);
@ -1036,7 +1042,7 @@ void Character::drawNightCpu(Renderer& renderer, const float* plPosEye, const fl
void Character::drawNightWithShadow(Renderer& renderer,
const float* plPosEye, const float* plDirEye, const float* plColors, int plCount,
const Eigen::Matrix4f& lightFromCamera, GLuint shadowMapTex)
const Eigen::Matrix4f& lightFromCamera, GLuint shadowMapTex, const float* ambientColor, const float* fogColor)
{
if (!enabled) return;
if (hitSparkEmitter.isConfigured() && hitSparkEmitter.getActiveParticleCount() > 0) {
@ -1047,15 +1053,15 @@ void Character::drawNightWithShadow(Renderer& renderer,
if (!isPlayer && hp <= 0) return;
if (useGpuSkinning) {
drawNightGpuSkinningWithShadow(renderer, plPosEye, plDirEye, plColors, plCount, lightFromCamera, shadowMapTex);
drawNightGpuSkinningWithShadow(renderer, plPosEye, plDirEye, plColors, plCount, lightFromCamera, shadowMapTex, ambientColor, fogColor);
} else {
drawNightCpuWithShadow(renderer, plPosEye, plDirEye, plColors, plCount, lightFromCamera, shadowMapTex);
drawNightCpuWithShadow(renderer, plPosEye, plDirEye, plColors, plCount, lightFromCamera, shadowMapTex, ambientColor, fogColor);
}
}
void Character::drawNightGpuSkinningWithShadow(Renderer& renderer,
const float* plPosEye, const float* plDirEye, const float* plColors, int plCount,
const Eigen::Matrix4f& lightFromCamera, GLuint shadowMapTex)
const Eigen::Matrix4f& lightFromCamera, GLuint shadowMapTex, const float* ambientColor, const float* fogColor)
{
AnimationState drawState = resolveActiveState();
auto it = animations.find(drawState);
@ -1068,6 +1074,8 @@ void Character::drawNightGpuSkinningWithShadow(Renderer& renderer,
renderer.shaderManager.PushShader(nightShadowSkinningShader);
renderer.RenderUniform1i(textureUniformName, 0);
renderer.RenderUniform1i("uShadowMap", 1);
renderer.RenderUniform3fv("uAmbientColor", ambientColor);
renderer.RenderUniform3fv("uFogColor", fogColor);
renderer.RenderUniformMatrix4fv("uLightFromCamera", false, lightFromCamera.data());
// First light's eye-space direction used for shadow bias
if (plCount > 0) renderer.RenderUniform3fv("uLightDir", plDirEye);
@ -1114,6 +1122,8 @@ void Character::drawNightGpuSkinningWithShadow(Renderer& renderer,
renderer.shaderManager.PushShader("night_fog_shadow");
renderer.RenderUniform1i(textureUniformName, 0);
renderer.RenderUniform1i("uShadowMap", 1);
renderer.RenderUniform3fv("uAmbientColor", ambientColor);
renderer.RenderUniform3fv("uFogColor", fogColor);
renderer.RenderUniformMatrix4fv("uLightFromCamera", false, lightFromCamera.data());
if (plCount > 0) renderer.RenderUniform3fv("uLightDir", plDirEye);
renderer.RenderUniform3fv("uPlayerEyePos", playerEyePosNightShadow);
@ -1132,7 +1142,7 @@ void Character::drawNightGpuSkinningWithShadow(Renderer& renderer,
void Character::drawNightCpuWithShadow(Renderer& renderer,
const float* plPosEye, const float* plDirEye, const float* plColors, int plCount,
const Eigen::Matrix4f& lightFromCamera, GLuint shadowMapTex)
const Eigen::Matrix4f& lightFromCamera, GLuint shadowMapTex, const float* ambientColor, const float* fogColor)
{
AnimationState drawState = resolveActiveState();
auto it = animations.find(drawState);
@ -1143,6 +1153,8 @@ void Character::drawNightCpuWithShadow(Renderer& renderer,
renderer.shaderManager.PushShader(nightShadowShader);
renderer.RenderUniform1i(textureUniformName, 0);
renderer.RenderUniform1i("uShadowMap", 1);
renderer.RenderUniform3fv("uAmbientColor", ambientColor);
renderer.RenderUniform3fv("uFogColor", fogColor);
renderer.RenderUniformMatrix4fv("uLightFromCamera", false, lightFromCamera.data());
if (plCount > 0) renderer.RenderUniform3fv("uLightDir", plDirEye);

View File

@ -51,10 +51,10 @@ public:
void draw(Renderer& renderer);
void drawShadowDepth(Renderer& renderer);
void drawWithShadow(Renderer& renderer, const Eigen::Matrix4f& lightFromCamera, GLuint shadowMapTex, const Eigen::Vector3f& lightDirCamera);
void drawNight(Renderer& renderer, const float* pointLightPosEye, const float* pointLightDirEye, const float* pointLightColors, int pointLightCount);
void drawNight(Renderer& renderer, const float* pointLightPosEye, const float* pointLightDirEye, const float* pointLightColors, int pointLightCount, const float* ambientColor, const float* fogColor);
void drawNightWithShadow(Renderer& renderer,
const float* plPosEye, const float* plDirEye, const float* plColors, int plCount,
const Eigen::Matrix4f& lightFromCamera, GLuint shadowMapTex);
const Eigen::Matrix4f& lightFromCamera, GLuint shadowMapTex, const float* ambientColor, const float* fogColor);
// Character-to-character collision (XZ-plane). Used by Location to keep
// player/NPCs from walking through each other.
@ -206,15 +206,15 @@ private:
void drawGpuSkinningWithShadow(Renderer& renderer, const Eigen::Matrix4f& lightFromCamera, GLuint shadowMapTex, const Eigen::Vector3f& lightDirCamera);
void drawCpuWithShadow(Renderer& renderer, const Eigen::Matrix4f& lightFromCamera, GLuint shadowMapTex, const Eigen::Vector3f& lightDirCamera);
// Night: draw with spot-light shaders
void drawNightGpuSkinning(Renderer& renderer, const float* plPosEye, const float* plDirEye, const float* plColors, int plCount);
void drawNightCpu(Renderer& renderer, const float* plPosEye, const float* plDirEye, const float* plColors, int plCount);
void drawNightGpuSkinning(Renderer& renderer, const float* plPosEye, const float* plDirEye, const float* plColors, int plCount, const float* ambientColor, const float* fogColor);
void drawNightCpu(Renderer& renderer, const float* plPosEye, const float* plDirEye, const float* plColors, int plCount, const float* ambientColor, const float* fogColor);
// Night: draw with spot-light + shadow shaders
void drawNightGpuSkinningWithShadow(Renderer& renderer,
const float* plPosEye, const float* plDirEye, const float* plColors, int plCount,
const Eigen::Matrix4f& lightFromCamera, GLuint shadowMapTex);
const Eigen::Matrix4f& lightFromCamera, GLuint shadowMapTex, const float* ambientColor, const float* fogColor);
void drawNightCpuWithShadow(Renderer& renderer,
const float* plPosEye, const float* plDirEye, const float* plColors, int plCount,
const Eigen::Matrix4f& lightFromCamera, GLuint shadowMapTex);
const Eigen::Matrix4f& lightFromCamera, GLuint shadowMapTex, const float* ambientColor, const float* fogColor);
};
} // namespace ZL

View File

@ -271,7 +271,7 @@ namespace ZL
locations["uni_interior"]->setup(uniInteriorParams, &menuManager.questJournal);
locations["uni_interior"]->scriptEngine.setGlobalStore(&globalInts);
locations["uni_interior"]->scriptEngine.setGlobalFloatStore(&globalFloats);
locations["uni_interior"]->requestNightDayTransition = [this](bool isNight) { this->isNight = isNight; };
locations["uni_interior"]->requestNightDayTransition = [this](bool isNight, bool isDawn) { this->isNight = isNight; this->isDawn = isDawn; };
locations["uni_interior"]->requestDarklandsTransition = [this]() { return startDarklandsTransition(); };
locations["uni_interior"]->requestAdvanceDarklandsHud = [this]() { menuManager.advanceUniIntDarklandsHud(); };
if (locations["uni_interior"]->player)
@ -300,7 +300,7 @@ namespace ZL
locations["uni_exterior"]->setup(uniExteriorParams, &menuManager.questJournal);
locations["uni_exterior"]->scriptEngine.setGlobalStore(&globalInts);
locations["uni_exterior"]->scriptEngine.setGlobalFloatStore(&globalFloats);
locations["uni_exterior"]->requestNightDayTransition = [this](bool isNight) { this->isNight = isNight; };
locations["uni_exterior"]->requestNightDayTransition = [this](bool isNight, bool isDawn) { this->isNight = isNight; this->isDawn = isDawn; };
locations["uni_exterior"]->requestDarklandsTransition = [this]() { return startDarklandsTransition(); };
if (locations["uni_exterior"]->player)
locations["uni_exterior"]->player->onDeathAnimComplete = [this]() { startDarklandsTransition(); };
@ -363,7 +363,7 @@ namespace ZL
locations["location_dorm"]->setup(params_dorm, &menuManager.questJournal);
locations["location_dorm"]->scriptEngine.setGlobalStore(&globalInts);
locations["location_dorm"]->scriptEngine.setGlobalFloatStore(&globalFloats);
locations["location_dorm"]->requestNightDayTransition = [this](bool isNight) { this->isNight = isNight; };
locations["location_dorm"]->requestNightDayTransition = [this](bool isNight, bool isDawn) { this->isNight = isNight; this->isDawn = isDawn; };
locations["location_dorm"]->requestDarklandsTransition = [this]() { return startDarklandsTransition(); };
if (locations["location_dorm"]->player)
locations["location_dorm"]->player->onDeathAnimComplete = [this]() { startDarklandsTransition(); };
@ -538,6 +538,7 @@ namespace ZL
// Sync global flags so Location's draw functions see them.
currentLocation->isDarklands = isDarklands;
currentLocation->isNight = isNight;
currentLocation->isDawn = isDawn;
if (isDarklands) {
currentLocation->drawGameDarklands();
@ -747,12 +748,24 @@ namespace ZL
if (event.type == SDL_KEYDOWN && event.key.repeat == 0) {
switch (event.key.keysym.sym) {
case SDLK_8:
if (editorMode == EditorMode::InteractiveObjects && currentLocation) {
currentLocation->editor.selectInteractiveObject(8);
} else {
isDawn = !isDawn;
if (isDawn) isNight = true;
}
break;
case SDLK_9:
if (editorMode == EditorMode::InteractiveObjects && currentLocation) {
currentLocation->editor.selectInteractiveObject(9);
} else {
if (isDawn) {
isDawn = false; // step back: dawn → plain night
} else {
isNight = !isNight;
}
}
break;
case SDLK_0:
case SDLK_1:
@ -762,7 +775,6 @@ namespace ZL
case SDLK_5:
case SDLK_6:
case SDLK_7:
case SDLK_8:
if (editorMode == EditorMode::InteractiveObjects && currentLocation) {
currentLocation->editor.selectInteractiveObject(event.key.keysym.sym - SDLK_0);
} else if (event.key.keysym.sym == SDLK_0) {

View File

@ -54,6 +54,7 @@ namespace ZL {
// Global night mode state — persists across location transitions.
bool isNight = false;
bool isDawn = false; // sub-variant of night: brighter pink ambient, same lighting
Inventory inventory;
InteractiveObject* pickedUpObject = nullptr;

View File

@ -1017,6 +1017,14 @@ namespace ZL
}
const bool hasShadows = (shadowMap != nullptr && shadowLight != nullptr);
// Ambient and fog color: different for plain night vs dawn
static const float kNightAmbient[3] = { 0.37f, 0.37f, 0.37f };
static const float kDawnAmbient[3] = { 0.72f, 0.52f, 0.62f }; // brighter warm pink
static const float kNightFogColor[3] = { 0.01f, 0.01f, 0.05f };
static const float kDawnFogColor[3] = { 0.50f, 0.44f, 0.47f }; // grey with slight pink
const float* ambientColor = isDawn ? kDawnAmbient : kNightAmbient;
const float* fogColor = isDawn ? kDawnFogColor : kNightFogColor;
if (hasShadows) {
drawNightShadowDepthPass(*shadowLight);
}
@ -1038,6 +1046,8 @@ namespace ZL
const float playerEyePos[3] = { 0.0f, 0.0f, -Environment::zoom };
renderer.RenderUniform3fv("uPlayerEyePos", playerEyePos);
renderer.RenderUniform3fv("uAmbientColor", ambientColor);
renderer.RenderUniform3fv("uFogColor", fogColor);
renderer.PushPerspectiveProjectionMatrix(1.0 / 1.5,
static_cast<float>(Environment::width) / static_cast<float>(Environment::height),
@ -1111,11 +1121,11 @@ namespace ZL
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());
if (player) player->drawNightWithShadow(renderer, plPosEye, plDirEye, plColors, lightCount, lightFromCamera, shadowMap->getDepthTexture(), ambientColor, fogColor);
for (auto& npc : npcs) npc->drawNightWithShadow(renderer, plPosEye, plDirEye, plColors, lightCount, lightFromCamera, shadowMap->getDepthTexture(), ambientColor, fogColor);
} else {
if (player) player->drawNight(renderer, plPosEye, plDirEye, plColors, lightCount);
for (auto& npc : npcs) npc->drawNight(renderer, plPosEye, plDirEye, plColors, lightCount);
if (player) player->drawNight(renderer, plPosEye, plDirEye, plColors, lightCount, ambientColor, fogColor);
for (auto& npc : npcs) npc->drawNight(renderer, plPosEye, plDirEye, plColors, lightCount, ambientColor, fogColor);
}
for (auto& tz : teleportZones) tz.draw(renderer, Environment::zoom, Environment::width, Environment::height);

View File

@ -100,6 +100,7 @@ namespace ZL
// Read by draw functions and raycast — do not write from Location code.
bool isDarklands = false;
bool isNight = false;
bool isDawn = false;
// Called when the player successfully taps the ground and a floor walk target is set.
// Used by the tutorial system to detect the "tap to walk" gesture.
@ -109,7 +110,7 @@ namespace ZL
// request the transition without coupling Location to Game directly.
std::function<bool()> requestDarklandsTransition;
std::function<void(bool)> requestNightDayTransition;
std::function<void(bool, bool)> requestNightDayTransition;
// Set by Game after setup(). Lua calls this to advance the uni_interior HUD
// from step12 to step13 (trigger-zone encounter hint).

View File

@ -207,15 +207,21 @@ namespace ZL {
api.set_function("set_day",
[game]() {
game->requestNightDayTransition(false);
game->requestNightDayTransition(false, false);
});
api.set_function("set_night",
[game]() {
game->requestNightDayTransition(true);
game->requestNightDayTransition(true, false);
std::cout << "Set night called" << std::endl;
});
api.set_function("set_dawn",
[game]() {
game->requestNightDayTransition(true, true);
std::cout << "Set dawn called" << std::endl;
});
// advance_darklands_hud()
// Advances the uni_interior darklands HUD from step12 to step13.
// Call when the player enters the ghost trigger zone in darklands.