mirror of
https://github.com/Kelsidavis/WoWee.git
synced 2026-03-25 16:30:15 +00:00
Implement WoW-accurate DBC-driven sky system with lore-faithful celestial bodies
Add SkySystem coordinator that follows WoW's actual architecture where skyboxes are authoritative and procedural elements serve as fallbacks. Integrate lighting system across all renderers (terrain, WMO, M2, character) with unified parameters. Sky System: - SkySystem coordinator manages skybox, celestial bodies, stars, clouds, lens flare - Skybox is authoritative (baked stars from M2 models, procedural fallback only) - skyboxHasStars flag gates procedural star rendering (prevents double-star bug) Celestial Bodies (Lore-Accurate): - Two moons: White Lady (30-day cycle, pale white) + Blue Child (27-day cycle, pale blue) - Deterministic moon phases from server gameTime (not deltaTime toys) - Sun positioning driven by LightingManager directionalDir (DBC-sourced) - Camera-locked sky dome (translation ignored, rotation applied) Lighting Integration: - Apply LightingManager params to WMO, M2, character renderers - Unified lighting: directional light, diffuse color, ambient color, fog - Star occlusion by cloud density (70% weight) and fog density (30% weight) Documentation: - Add comprehensive SKY_SYSTEM.md technical guide - Update MEMORY.md with sky system architecture and anti-patterns - Update README.md with WoW-accurate descriptions Critical design decisions: - NO latitude-based star rotation (Azeroth not modeled as spherical planet) - NO always-on procedural stars (skybox authority prevents zone identity loss) - NO universal dual-moon setup (map-specific celestial configurations)
This commit is contained in:
parent
159a434c60
commit
8e60d0e781
16 changed files with 1036 additions and 47 deletions
|
|
@ -125,11 +125,17 @@ void Celestial::shutdown() {
|
|||
celestialShader.reset();
|
||||
}
|
||||
|
||||
void Celestial::render(const Camera& camera, float timeOfDay) {
|
||||
void Celestial::render(const Camera& camera, float timeOfDay,
|
||||
const glm::vec3* sunDir, const glm::vec3* sunColor, float gameTime) {
|
||||
if (!renderingEnabled || vao == 0 || !celestialShader) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Update moon phases from game time if available (deterministic)
|
||||
if (gameTime >= 0.0f) {
|
||||
updatePhasesFromGameTime(gameTime);
|
||||
}
|
||||
|
||||
// Enable blending for celestial glow
|
||||
glEnable(GL_BLEND);
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
|
|
@ -137,16 +143,21 @@ void Celestial::render(const Camera& camera, float timeOfDay) {
|
|||
// Disable depth writing (but keep depth testing)
|
||||
glDepthMask(GL_FALSE);
|
||||
|
||||
// Render sun and moon
|
||||
renderSun(camera, timeOfDay);
|
||||
renderMoon(camera, timeOfDay);
|
||||
// Render sun and moons (pass lighting parameters)
|
||||
renderSun(camera, timeOfDay, sunDir, sunColor);
|
||||
renderMoon(camera, timeOfDay); // White Lady (primary moon)
|
||||
|
||||
if (dualMoonMode_) {
|
||||
renderBlueChild(camera, timeOfDay); // Blue Child (secondary moon)
|
||||
}
|
||||
|
||||
// Restore state
|
||||
glDepthMask(GL_TRUE);
|
||||
glDisable(GL_BLEND);
|
||||
}
|
||||
|
||||
void Celestial::renderSun(const Camera& camera, float timeOfDay) {
|
||||
void Celestial::renderSun(const Camera& camera, float timeOfDay,
|
||||
const glm::vec3* sunDir, const glm::vec3* sunColor) {
|
||||
// Sun visible from 5:00 to 19:00
|
||||
if (timeOfDay < 5.0f || timeOfDay >= 19.0f) {
|
||||
return;
|
||||
|
|
@ -154,8 +165,16 @@ void Celestial::renderSun(const Camera& camera, float timeOfDay) {
|
|||
|
||||
celestialShader->use();
|
||||
|
||||
// Get sun position
|
||||
glm::vec3 sunPos = getSunPosition(timeOfDay);
|
||||
// Get sun position (use lighting direction if provided)
|
||||
glm::vec3 sunPos;
|
||||
if (sunDir) {
|
||||
// Place sun along the lighting direction at far distance
|
||||
const float sunDistance = 800.0f;
|
||||
sunPos = -*sunDir * sunDistance; // Negative because light comes FROM sun
|
||||
} else {
|
||||
// Fallback to time-based position
|
||||
sunPos = getSunPosition(timeOfDay);
|
||||
}
|
||||
|
||||
// Create model matrix
|
||||
glm::mat4 model = glm::mat4(1.0f);
|
||||
|
|
@ -170,8 +189,8 @@ void Celestial::renderSun(const Camera& camera, float timeOfDay) {
|
|||
celestialShader->setUniform("view", view);
|
||||
celestialShader->setUniform("projection", projection);
|
||||
|
||||
// Sun color and intensity
|
||||
glm::vec3 color = getSunColor(timeOfDay);
|
||||
// Sun color and intensity (use lighting color if provided)
|
||||
glm::vec3 color = sunColor ? *sunColor : getSunColor(timeOfDay);
|
||||
float intensity = getSunIntensity(timeOfDay);
|
||||
|
||||
celestialShader->setUniform("celestialColor", color);
|
||||
|
|
@ -224,7 +243,61 @@ void Celestial::renderMoon(const Camera& camera, float timeOfDay) {
|
|||
|
||||
celestialShader->setUniform("celestialColor", color);
|
||||
celestialShader->setUniform("intensity", intensity);
|
||||
celestialShader->setUniform("moonPhase", moonPhase);
|
||||
celestialShader->setUniform("moonPhase", whiteLadyPhase_);
|
||||
|
||||
// Render quad
|
||||
glBindVertexArray(vao);
|
||||
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, nullptr);
|
||||
glBindVertexArray(0);
|
||||
}
|
||||
|
||||
void Celestial::renderBlueChild(const Camera& camera, float timeOfDay) {
|
||||
// Blue Child visible from 19:00 to 5:00 (night, same as White Lady)
|
||||
if (timeOfDay >= 5.0f && timeOfDay < 19.0f) {
|
||||
return;
|
||||
}
|
||||
|
||||
celestialShader->use();
|
||||
|
||||
// Get moon position (offset slightly from White Lady)
|
||||
glm::vec3 moonPos = getMoonPosition(timeOfDay);
|
||||
// Offset Blue Child to the right and slightly lower
|
||||
moonPos.x += 80.0f; // Right offset
|
||||
moonPos.z -= 40.0f; // Slightly lower
|
||||
|
||||
// Create model matrix (smaller than White Lady)
|
||||
glm::mat4 model = glm::mat4(1.0f);
|
||||
model = glm::translate(model, moonPos);
|
||||
model = glm::scale(model, glm::vec3(30.0f, 30.0f, 1.0f)); // 30 unit diameter (smaller)
|
||||
|
||||
// Set uniforms
|
||||
glm::mat4 view = camera.getViewMatrix();
|
||||
glm::mat4 projection = camera.getProjectionMatrix();
|
||||
|
||||
celestialShader->setUniform("model", model);
|
||||
celestialShader->setUniform("view", view);
|
||||
celestialShader->setUniform("projection", projection);
|
||||
|
||||
// Blue Child color (pale blue tint)
|
||||
glm::vec3 color = glm::vec3(0.7f, 0.8f, 1.0f);
|
||||
|
||||
// Fade in/out at transitions (same as White Lady)
|
||||
float intensity = 1.0f;
|
||||
if (timeOfDay >= 19.0f && timeOfDay < 21.0f) {
|
||||
// Fade in (19:00-21:00)
|
||||
intensity = (timeOfDay - 19.0f) / 2.0f;
|
||||
}
|
||||
else if (timeOfDay >= 3.0f && timeOfDay < 5.0f) {
|
||||
// Fade out (3:00-5:00)
|
||||
intensity = 1.0f - (timeOfDay - 3.0f) / 2.0f;
|
||||
}
|
||||
|
||||
// Blue Child is dimmer than White Lady
|
||||
intensity *= 0.7f;
|
||||
|
||||
celestialShader->setUniform("celestialColor", color);
|
||||
celestialShader->setUniform("intensity", intensity);
|
||||
celestialShader->setUniform("moonPhase", blueChildPhase_);
|
||||
|
||||
// Render quad
|
||||
glBindVertexArray(vao);
|
||||
|
|
@ -396,16 +469,49 @@ void Celestial::update(float deltaTime) {
|
|||
// Update moon phase timer
|
||||
moonPhaseTimer += deltaTime;
|
||||
|
||||
// Moon completes full cycle in MOON_CYCLE_DURATION seconds
|
||||
moonPhase = std::fmod(moonPhaseTimer / MOON_CYCLE_DURATION, 1.0f);
|
||||
// White Lady completes full cycle in MOON_CYCLE_DURATION seconds
|
||||
whiteLadyPhase_ = std::fmod(moonPhaseTimer / MOON_CYCLE_DURATION, 1.0f);
|
||||
|
||||
// Blue Child has a different cycle rate (slightly faster, 3.5 minutes)
|
||||
constexpr float BLUE_CHILD_CYCLE = 210.0f;
|
||||
blueChildPhase_ = std::fmod(moonPhaseTimer / BLUE_CHILD_CYCLE, 1.0f);
|
||||
}
|
||||
|
||||
void Celestial::setMoonPhase(float phase) {
|
||||
// Clamp phase to 0.0-1.0
|
||||
moonPhase = glm::clamp(phase, 0.0f, 1.0f);
|
||||
// Set White Lady phase (primary moon)
|
||||
whiteLadyPhase_ = glm::clamp(phase, 0.0f, 1.0f);
|
||||
|
||||
// Update timer to match phase
|
||||
moonPhaseTimer = moonPhase * MOON_CYCLE_DURATION;
|
||||
// Update timer to match White Lady phase
|
||||
moonPhaseTimer = whiteLadyPhase_ * MOON_CYCLE_DURATION;
|
||||
}
|
||||
|
||||
void Celestial::setBlueChildPhase(float phase) {
|
||||
// Set Blue Child phase (secondary moon)
|
||||
blueChildPhase_ = glm::clamp(phase, 0.0f, 1.0f);
|
||||
}
|
||||
|
||||
float Celestial::computePhaseFromGameTime(float gameTime, float cycleDays) const {
|
||||
// WoW game time: 1 game day = 24 real minutes = 1440 seconds
|
||||
constexpr float SECONDS_PER_GAME_DAY = 1440.0f;
|
||||
|
||||
// Convert game time to game days
|
||||
float gameDays = gameTime / SECONDS_PER_GAME_DAY;
|
||||
|
||||
// Compute phase as fraction of lunar cycle (0.0-1.0)
|
||||
float phase = std::fmod(gameDays / cycleDays, 1.0f);
|
||||
|
||||
// Ensure positive (fmod can return negative for negative input)
|
||||
if (phase < 0.0f) {
|
||||
phase += 1.0f;
|
||||
}
|
||||
|
||||
return phase;
|
||||
}
|
||||
|
||||
void Celestial::updatePhasesFromGameTime(float gameTime) {
|
||||
// Compute deterministic phases from server game time
|
||||
whiteLadyPhase_ = computePhaseFromGameTime(gameTime, WHITE_LADY_CYCLE_DAYS);
|
||||
blueChildPhase_ = computePhaseFromGameTime(gameTime, BLUE_CHILD_CYCLE_DAYS);
|
||||
}
|
||||
|
||||
} // namespace rendering
|
||||
|
|
|
|||
|
|
@ -1163,8 +1163,8 @@ void CharacterRenderer::render(const Camera& camera, const glm::mat4& view, cons
|
|||
characterShader->use();
|
||||
characterShader->setUniform("uView", view);
|
||||
characterShader->setUniform("uProjection", projection);
|
||||
characterShader->setUniform("uLightDir", glm::vec3(0.0f, -1.0f, 0.3f));
|
||||
characterShader->setUniform("uLightColor", glm::vec3(1.5f, 1.4f, 1.3f));
|
||||
characterShader->setUniform("uLightDir", lightDir);
|
||||
characterShader->setUniform("uLightColor", lightColor);
|
||||
characterShader->setUniform("uSpecularIntensity", 0.5f);
|
||||
characterShader->setUniform("uViewPos", camera.getPosition());
|
||||
|
||||
|
|
|
|||
|
|
@ -1652,7 +1652,7 @@ void M2Renderer::render(const Camera& camera, const glm::mat4& view, const glm::
|
|||
shader->setUniform("uView", view);
|
||||
shader->setUniform("uProjection", projection);
|
||||
shader->setUniform("uLightDir", lightDir);
|
||||
shader->setUniform("uLightColor", glm::vec3(1.5f, 1.4f, 1.3f));
|
||||
shader->setUniform("uLightColor", lightColor);
|
||||
shader->setUniform("uSpecularIntensity", onTaxi_ ? 0.0f : 0.5f); // Disable specular during taxi for performance
|
||||
shader->setUniform("uAmbientColor", ambientColor);
|
||||
shader->setUniform("uViewPos", camera.getPosition());
|
||||
|
|
|
|||
|
|
@ -1764,14 +1764,27 @@ void Renderer::renderWorld(game::World* world) {
|
|||
skybox->render(*camera, timeOfDay);
|
||||
}
|
||||
|
||||
// Render stars after skybox
|
||||
if (starField && camera) {
|
||||
starField->render(*camera, timeOfDay);
|
||||
// Get lighting parameters for celestial rendering
|
||||
const glm::vec3* sunDir = nullptr;
|
||||
const glm::vec3* sunColor = nullptr;
|
||||
float cloudDensity = 0.0f;
|
||||
float fogDensity = 0.0f;
|
||||
if (lightingManager) {
|
||||
const auto& lighting = lightingManager->getLightingParams();
|
||||
sunDir = &lighting.directionalDir;
|
||||
sunColor = &lighting.diffuseColor;
|
||||
cloudDensity = lighting.cloudDensity;
|
||||
fogDensity = lighting.fogDensity;
|
||||
}
|
||||
|
||||
// Render celestial bodies (sun/moon) after stars
|
||||
// Render stars after skybox (affected by cloud/fog density)
|
||||
if (starField && camera) {
|
||||
starField->render(*camera, timeOfDay, cloudDensity, fogDensity);
|
||||
}
|
||||
|
||||
// Render celestial bodies (sun/moon) after stars (sun uses lighting direction/color)
|
||||
if (celestial && camera) {
|
||||
celestial->render(*camera, timeOfDay);
|
||||
celestial->render(*camera, timeOfDay, sunDir, sunColor);
|
||||
}
|
||||
|
||||
// Render clouds after celestial bodies
|
||||
|
|
@ -1781,12 +1794,43 @@ void Renderer::renderWorld(game::World* world) {
|
|||
|
||||
// Render lens flare (screen-space effect, render after celestial bodies)
|
||||
if (lensFlare && camera && celestial) {
|
||||
glm::vec3 sunPosition = celestial->getSunPosition(timeOfDay);
|
||||
// Use lighting direction for sun position if available
|
||||
glm::vec3 sunPosition;
|
||||
if (sunDir) {
|
||||
const float sunDistance = 800.0f;
|
||||
sunPosition = -*sunDir * sunDistance;
|
||||
} else {
|
||||
sunPosition = celestial->getSunPosition(timeOfDay);
|
||||
}
|
||||
lensFlare->render(*camera, sunPosition, timeOfDay);
|
||||
}
|
||||
|
||||
// Update fog across all renderers based on time of day (match sky color)
|
||||
if (skybox) {
|
||||
// Apply lighting and fog to all renderers
|
||||
if (lightingManager) {
|
||||
const auto& lighting = lightingManager->getLightingParams();
|
||||
|
||||
float lightDir[3] = {lighting.directionalDir.x, lighting.directionalDir.y, lighting.directionalDir.z};
|
||||
float lightColor[3] = {lighting.diffuseColor.r, lighting.diffuseColor.g, lighting.diffuseColor.b};
|
||||
float ambientColor[3] = {lighting.ambientColor.r, lighting.ambientColor.g, lighting.ambientColor.b};
|
||||
float fogColorArray[3] = {lighting.fogColor.r, lighting.fogColor.g, lighting.fogColor.b};
|
||||
|
||||
if (wmoRenderer) {
|
||||
wmoRenderer->setLighting(lightDir, lightColor, ambientColor);
|
||||
wmoRenderer->setFog(glm::vec3(fogColorArray[0], fogColorArray[1], fogColorArray[2]),
|
||||
lighting.fogStart, lighting.fogEnd);
|
||||
}
|
||||
if (m2Renderer) {
|
||||
m2Renderer->setLighting(lightDir, lightColor, ambientColor);
|
||||
m2Renderer->setFog(glm::vec3(fogColorArray[0], fogColorArray[1], fogColorArray[2]),
|
||||
lighting.fogStart, lighting.fogEnd);
|
||||
}
|
||||
if (characterRenderer) {
|
||||
characterRenderer->setLighting(lightDir, lightColor, ambientColor);
|
||||
characterRenderer->setFog(glm::vec3(fogColorArray[0], fogColorArray[1], fogColorArray[2]),
|
||||
lighting.fogStart, lighting.fogEnd);
|
||||
}
|
||||
} else if (skybox) {
|
||||
// Fallback to skybox-based fog if no lighting manager
|
||||
glm::vec3 horizonColor = skybox->getHorizonColor(timeOfDay);
|
||||
if (wmoRenderer) wmoRenderer->setFog(horizonColor, 100.0f, 600.0f);
|
||||
if (m2Renderer) m2Renderer->setFog(horizonColor, 100.0f, 600.0f);
|
||||
|
|
|
|||
183
src/rendering/sky_system.cpp
Normal file
183
src/rendering/sky_system.cpp
Normal file
|
|
@ -0,0 +1,183 @@
|
|||
#include "rendering/sky_system.hpp"
|
||||
#include "rendering/skybox.hpp"
|
||||
#include "rendering/celestial.hpp"
|
||||
#include "rendering/starfield.hpp"
|
||||
#include "rendering/clouds.hpp"
|
||||
#include "rendering/lens_flare.hpp"
|
||||
#include "rendering/camera.hpp"
|
||||
#include "core/logger.hpp"
|
||||
|
||||
namespace wowee {
|
||||
namespace rendering {
|
||||
|
||||
SkySystem::SkySystem() = default;
|
||||
|
||||
SkySystem::~SkySystem() {
|
||||
shutdown();
|
||||
}
|
||||
|
||||
bool SkySystem::initialize() {
|
||||
if (initialized_) {
|
||||
LOG_WARNING("SkySystem already initialized");
|
||||
return true;
|
||||
}
|
||||
|
||||
LOG_INFO("Initializing sky system");
|
||||
|
||||
// Initialize skybox (authoritative)
|
||||
skybox_ = std::make_unique<Skybox>();
|
||||
if (!skybox_->initialize()) {
|
||||
LOG_ERROR("Failed to initialize skybox");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Initialize celestial bodies (sun + 2 moons)
|
||||
celestial_ = std::make_unique<Celestial>();
|
||||
if (!celestial_->initialize()) {
|
||||
LOG_ERROR("Failed to initialize celestial bodies");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Initialize procedural stars (FALLBACK only)
|
||||
starField_ = std::make_unique<StarField>();
|
||||
if (!starField_->initialize()) {
|
||||
LOG_ERROR("Failed to initialize star field");
|
||||
return false;
|
||||
}
|
||||
// Default: disabled (skybox is authoritative)
|
||||
starField_->setEnabled(false);
|
||||
|
||||
// Initialize clouds
|
||||
clouds_ = std::make_unique<Clouds>();
|
||||
if (!clouds_->initialize()) {
|
||||
LOG_ERROR("Failed to initialize clouds");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Initialize lens flare
|
||||
lensFlare_ = std::make_unique<LensFlare>();
|
||||
if (!lensFlare_->initialize()) {
|
||||
LOG_ERROR("Failed to initialize lens flare");
|
||||
return false;
|
||||
}
|
||||
|
||||
initialized_ = true;
|
||||
LOG_INFO("Sky system initialized successfully");
|
||||
return true;
|
||||
}
|
||||
|
||||
void SkySystem::shutdown() {
|
||||
if (!initialized_) {
|
||||
return;
|
||||
}
|
||||
|
||||
LOG_INFO("Shutting down sky system");
|
||||
|
||||
// Shutdown components that have explicit shutdown methods
|
||||
if (starField_) starField_->shutdown();
|
||||
if (celestial_) celestial_->shutdown();
|
||||
if (skybox_) skybox_->shutdown();
|
||||
|
||||
// Reset all (destructors handle cleanup for clouds/lensFlare)
|
||||
lensFlare_.reset();
|
||||
clouds_.reset();
|
||||
starField_.reset();
|
||||
celestial_.reset();
|
||||
skybox_.reset();
|
||||
|
||||
initialized_ = false;
|
||||
}
|
||||
|
||||
void SkySystem::update(float deltaTime) {
|
||||
if (!initialized_) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Update time-based systems
|
||||
if (skybox_) skybox_->update(deltaTime);
|
||||
if (celestial_) celestial_->update(deltaTime);
|
||||
if (starField_) starField_->update(deltaTime);
|
||||
}
|
||||
|
||||
void SkySystem::render(const Camera& camera, const SkyParams& params) {
|
||||
if (!initialized_) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Render skybox first (authoritative, includes baked stars)
|
||||
if (skybox_) {
|
||||
skybox_->render(camera, params.timeOfDay);
|
||||
}
|
||||
|
||||
// Decide whether to render procedural stars
|
||||
bool renderProceduralStars = false;
|
||||
if (debugSkyMode_) {
|
||||
// Debug mode: always show procedural stars
|
||||
renderProceduralStars = true;
|
||||
} else if (proceduralStarsEnabled_) {
|
||||
// Fallback mode: show only if skybox doesn't have stars
|
||||
renderProceduralStars = !params.skyboxHasStars;
|
||||
}
|
||||
|
||||
// Render procedural stars (FALLBACK or DEBUG only)
|
||||
if (renderProceduralStars && starField_) {
|
||||
starField_->setEnabled(true);
|
||||
starField_->render(camera, params.timeOfDay, params.cloudDensity, params.fogDensity);
|
||||
} else if (starField_) {
|
||||
starField_->setEnabled(false);
|
||||
}
|
||||
|
||||
// Render celestial bodies (sun + White Lady + Blue Child)
|
||||
// Pass gameTime for deterministic moon phases
|
||||
if (celestial_) {
|
||||
celestial_->render(camera, params.timeOfDay, ¶ms.directionalDir, ¶ms.sunColor, params.gameTime);
|
||||
}
|
||||
|
||||
// Render clouds
|
||||
if (clouds_) {
|
||||
clouds_->render(camera, params.timeOfDay);
|
||||
}
|
||||
|
||||
// Render lens flare (sun glow effect)
|
||||
if (lensFlare_) {
|
||||
glm::vec3 sunPos = getSunPosition(params);
|
||||
lensFlare_->render(camera, sunPos, params.timeOfDay);
|
||||
}
|
||||
}
|
||||
|
||||
glm::vec3 SkySystem::getSunPosition(const SkyParams& params) const {
|
||||
// Use lighting direction for sun position
|
||||
const float sunDistance = 800.0f;
|
||||
return -params.directionalDir * sunDistance; // Negative because light comes FROM sun
|
||||
}
|
||||
|
||||
|
||||
void SkySystem::setMoonPhaseCycling(bool enabled) {
|
||||
if (celestial_) {
|
||||
celestial_->setMoonPhaseCycling(enabled);
|
||||
}
|
||||
}
|
||||
|
||||
void SkySystem::setWhiteLadyPhase(float phase) {
|
||||
if (celestial_) {
|
||||
celestial_->setMoonPhase(phase); // White Lady is primary moon
|
||||
}
|
||||
}
|
||||
|
||||
void SkySystem::setBlueChildPhase(float phase) {
|
||||
if (celestial_) {
|
||||
celestial_->setBlueChildPhase(phase);
|
||||
}
|
||||
}
|
||||
|
||||
float SkySystem::getWhiteLadyPhase() const {
|
||||
return celestial_ ? celestial_->getMoonPhase() : 0.5f;
|
||||
}
|
||||
|
||||
float SkySystem::getBlueChildPhase() const {
|
||||
// TODO: Second moon support
|
||||
return 0.25f; // Placeholder phase
|
||||
}
|
||||
|
||||
} // namespace rendering
|
||||
} // namespace wowee
|
||||
|
|
@ -98,7 +98,8 @@ void StarField::shutdown() {
|
|||
stars.clear();
|
||||
}
|
||||
|
||||
void StarField::render(const Camera& camera, float timeOfDay) {
|
||||
void StarField::render(const Camera& camera, float timeOfDay,
|
||||
float cloudDensity, float fogDensity) {
|
||||
if (!renderingEnabled || vao == 0 || !starShader || stars.empty()) {
|
||||
return;
|
||||
}
|
||||
|
|
@ -106,6 +107,10 @@ void StarField::render(const Camera& camera, float timeOfDay) {
|
|||
// Get star intensity based on time of day
|
||||
float intensity = getStarIntensity(timeOfDay);
|
||||
|
||||
// Reduce intensity based on cloud density and fog (more clouds/fog = fewer visible stars)
|
||||
intensity *= (1.0f - glm::clamp(cloudDensity * 0.7f, 0.0f, 1.0f));
|
||||
intensity *= (1.0f - glm::clamp(fogDensity * 0.3f, 0.0f, 1.0f));
|
||||
|
||||
// Don't render if stars would be invisible
|
||||
if (intensity <= 0.01f) {
|
||||
return;
|
||||
|
|
|
|||
|
|
@ -583,6 +583,21 @@ void WMORenderer::clearCollisionFocus() {
|
|||
collisionFocusEnabled = false;
|
||||
}
|
||||
|
||||
void WMORenderer::setLighting(const float lightDirIn[3], const float lightColorIn[3],
|
||||
const float ambientColorIn[3]) {
|
||||
lightDir[0] = lightDirIn[0];
|
||||
lightDir[1] = lightDirIn[1];
|
||||
lightDir[2] = lightDirIn[2];
|
||||
|
||||
lightColor[0] = lightColorIn[0];
|
||||
lightColor[1] = lightColorIn[1];
|
||||
lightColor[2] = lightColorIn[2];
|
||||
|
||||
ambientColor[0] = ambientColorIn[0];
|
||||
ambientColor[1] = ambientColorIn[1];
|
||||
ambientColor[2] = ambientColorIn[2];
|
||||
}
|
||||
|
||||
void WMORenderer::resetQueryStats() {
|
||||
queryTimeMs = 0.0;
|
||||
queryCallCount = 0;
|
||||
|
|
@ -802,10 +817,10 @@ void WMORenderer::render(const Camera& camera, const glm::mat4& view, const glm:
|
|||
shader->setUniform("uView", view);
|
||||
shader->setUniform("uProjection", projection);
|
||||
shader->setUniform("uViewPos", camera.getPosition());
|
||||
shader->setUniform("uLightDir", glm::vec3(-0.3f, -0.7f, -0.6f)); // Default sun direction
|
||||
shader->setUniform("uLightColor", glm::vec3(1.5f, 1.4f, 1.3f));
|
||||
shader->setUniform("uLightDir", glm::vec3(lightDir[0], lightDir[1], lightDir[2]));
|
||||
shader->setUniform("uLightColor", glm::vec3(lightColor[0], lightColor[1], lightColor[2]));
|
||||
shader->setUniform("uSpecularIntensity", 0.5f);
|
||||
shader->setUniform("uAmbientColor", glm::vec3(0.55f, 0.55f, 0.6f));
|
||||
shader->setUniform("uAmbientColor", glm::vec3(ambientColor[0], ambientColor[1], ambientColor[2]));
|
||||
shader->setUniform("uFogColor", fogColor);
|
||||
shader->setUniform("uFogStart", fogStart);
|
||||
shader->setUniform("uFogEnd", fogEnd);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue