2026-02-02 12:24:50 -08:00
|
|
|
|
#include "rendering/celestial.hpp"
|
2026-02-21 19:41:21 -08:00
|
|
|
|
#include "rendering/vk_context.hpp"
|
|
|
|
|
|
#include "rendering/vk_shader.hpp"
|
|
|
|
|
|
#include "rendering/vk_pipeline.hpp"
|
|
|
|
|
|
#include "rendering/vk_frame_data.hpp"
|
|
|
|
|
|
#include "rendering/vk_utils.hpp"
|
2026-02-02 12:24:50 -08:00
|
|
|
|
#include "core/logger.hpp"
|
|
|
|
|
|
#include <glm/gtc/matrix_transform.hpp>
|
|
|
|
|
|
#include <cmath>
|
2026-02-21 19:41:21 -08:00
|
|
|
|
#include <vector>
|
2026-02-02 12:24:50 -08:00
|
|
|
|
|
|
|
|
|
|
namespace wowee {
|
|
|
|
|
|
namespace rendering {
|
|
|
|
|
|
|
|
|
|
|
|
Celestial::Celestial() = default;
|
|
|
|
|
|
|
|
|
|
|
|
Celestial::~Celestial() {
|
|
|
|
|
|
shutdown();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-02-21 19:41:21 -08:00
|
|
|
|
bool Celestial::initialize(VkContext* ctx, VkDescriptorSetLayout perFrameLayout) {
|
|
|
|
|
|
LOG_INFO("Initializing celestial renderer (Vulkan)");
|
2026-02-02 12:24:50 -08:00
|
|
|
|
|
2026-02-21 19:41:21 -08:00
|
|
|
|
vkCtx_ = ctx;
|
|
|
|
|
|
VkDevice device = vkCtx_->getDevice();
|
2026-02-02 12:24:50 -08:00
|
|
|
|
|
2026-02-21 19:41:21 -08:00
|
|
|
|
// ------------------------------------------------------------------ shaders
|
|
|
|
|
|
VkShaderModule vertModule;
|
|
|
|
|
|
if (!vertModule.loadFromFile(device, "assets/shaders/celestial.vert.spv")) {
|
|
|
|
|
|
LOG_ERROR("Failed to load celestial vertex shader");
|
|
|
|
|
|
return false;
|
|
|
|
|
|
}
|
2026-02-02 12:24:50 -08:00
|
|
|
|
|
2026-02-21 19:41:21 -08:00
|
|
|
|
VkShaderModule fragModule;
|
|
|
|
|
|
if (!fragModule.loadFromFile(device, "assets/shaders/celestial.frag.spv")) {
|
|
|
|
|
|
LOG_ERROR("Failed to load celestial fragment shader");
|
|
|
|
|
|
return false;
|
|
|
|
|
|
}
|
2026-02-02 12:24:50 -08:00
|
|
|
|
|
2026-02-21 19:41:21 -08:00
|
|
|
|
VkPipelineShaderStageCreateInfo vertStage = vertModule.stageInfo(VK_SHADER_STAGE_VERTEX_BIT);
|
|
|
|
|
|
VkPipelineShaderStageCreateInfo fragStage = fragModule.stageInfo(VK_SHADER_STAGE_FRAGMENT_BIT);
|
2026-02-02 12:24:50 -08:00
|
|
|
|
|
2026-02-21 19:41:21 -08:00
|
|
|
|
// ------------------------------------------------------------------ push constants
|
|
|
|
|
|
// Layout: mat4(64) + vec4(16) + float*3(12) + pad(4) = 96 bytes
|
|
|
|
|
|
VkPushConstantRange pushRange{};
|
|
|
|
|
|
pushRange.stageFlags = VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT;
|
|
|
|
|
|
pushRange.offset = 0;
|
|
|
|
|
|
pushRange.size = sizeof(CelestialPush); // 96 bytes
|
2026-02-21 03:10:45 -08:00
|
|
|
|
|
2026-02-21 19:41:21 -08:00
|
|
|
|
// ------------------------------------------------------------------ pipeline layout
|
|
|
|
|
|
pipelineLayout_ = createPipelineLayout(device, {perFrameLayout}, {pushRange});
|
|
|
|
|
|
if (pipelineLayout_ == VK_NULL_HANDLE) {
|
|
|
|
|
|
LOG_ERROR("Failed to create celestial pipeline layout");
|
|
|
|
|
|
return false;
|
|
|
|
|
|
}
|
2026-02-21 03:10:45 -08:00
|
|
|
|
|
2026-02-21 19:41:21 -08:00
|
|
|
|
// ------------------------------------------------------------------ vertex input
|
|
|
|
|
|
// Vertex: vec3 pos + vec2 texCoord, stride = 20 bytes
|
|
|
|
|
|
VkVertexInputBindingDescription binding{};
|
|
|
|
|
|
binding.binding = 0;
|
|
|
|
|
|
binding.stride = 5 * sizeof(float); // 20 bytes
|
|
|
|
|
|
binding.inputRate = VK_VERTEX_INPUT_RATE_VERTEX;
|
|
|
|
|
|
|
|
|
|
|
|
VkVertexInputAttributeDescription posAttr{};
|
|
|
|
|
|
posAttr.location = 0;
|
|
|
|
|
|
posAttr.binding = 0;
|
|
|
|
|
|
posAttr.format = VK_FORMAT_R32G32B32_SFLOAT;
|
|
|
|
|
|
posAttr.offset = 0;
|
|
|
|
|
|
|
|
|
|
|
|
VkVertexInputAttributeDescription uvAttr{};
|
|
|
|
|
|
uvAttr.location = 1;
|
|
|
|
|
|
uvAttr.binding = 0;
|
|
|
|
|
|
uvAttr.format = VK_FORMAT_R32G32_SFLOAT;
|
|
|
|
|
|
uvAttr.offset = 3 * sizeof(float);
|
|
|
|
|
|
|
|
|
|
|
|
std::vector<VkDynamicState> dynamicStates = {
|
|
|
|
|
|
VK_DYNAMIC_STATE_VIEWPORT,
|
|
|
|
|
|
VK_DYNAMIC_STATE_SCISSOR
|
|
|
|
|
|
};
|
2026-02-02 12:24:50 -08:00
|
|
|
|
|
2026-02-21 19:41:21 -08:00
|
|
|
|
// ------------------------------------------------------------------ pipeline
|
|
|
|
|
|
pipeline_ = PipelineBuilder()
|
|
|
|
|
|
.setShaders(vertStage, fragStage)
|
|
|
|
|
|
.setVertexInput({binding}, {posAttr, uvAttr})
|
|
|
|
|
|
.setTopology(VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST)
|
|
|
|
|
|
.setRasterization(VK_POLYGON_MODE_FILL, VK_CULL_MODE_NONE)
|
|
|
|
|
|
.setDepthTest(true, false, VK_COMPARE_OP_LESS_OR_EQUAL) // test on, write off (sky layer)
|
|
|
|
|
|
.setColorBlendAttachment(PipelineBuilder::blendAlpha())
|
2026-02-22 02:59:24 -08:00
|
|
|
|
.setMultisample(vkCtx_->getMsaaSamples())
|
2026-02-21 19:41:21 -08:00
|
|
|
|
.setLayout(pipelineLayout_)
|
|
|
|
|
|
.setRenderPass(vkCtx_->getImGuiRenderPass())
|
|
|
|
|
|
.setDynamicStates(dynamicStates)
|
|
|
|
|
|
.build(device);
|
|
|
|
|
|
|
|
|
|
|
|
vertModule.destroy();
|
|
|
|
|
|
fragModule.destroy();
|
|
|
|
|
|
|
|
|
|
|
|
if (pipeline_ == VK_NULL_HANDLE) {
|
|
|
|
|
|
LOG_ERROR("Failed to create celestial pipeline");
|
2026-02-02 12:24:50 -08:00
|
|
|
|
return false;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-02-21 19:41:21 -08:00
|
|
|
|
// ------------------------------------------------------------------ geometry
|
|
|
|
|
|
createQuad();
|
2026-02-02 12:24:50 -08:00
|
|
|
|
|
|
|
|
|
|
LOG_INFO("Celestial renderer initialized");
|
|
|
|
|
|
return true;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-02-22 02:59:24 -08:00
|
|
|
|
void Celestial::recreatePipelines() {
|
|
|
|
|
|
if (!vkCtx_) return;
|
|
|
|
|
|
VkDevice device = vkCtx_->getDevice();
|
|
|
|
|
|
|
|
|
|
|
|
if (pipeline_ != VK_NULL_HANDLE) { vkDestroyPipeline(device, pipeline_, nullptr); pipeline_ = VK_NULL_HANDLE; }
|
|
|
|
|
|
|
|
|
|
|
|
VkShaderModule vertModule;
|
|
|
|
|
|
if (!vertModule.loadFromFile(device, "assets/shaders/celestial.vert.spv")) {
|
|
|
|
|
|
LOG_ERROR("Celestial::recreatePipelines: failed to load vertex shader");
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
VkShaderModule fragModule;
|
|
|
|
|
|
if (!fragModule.loadFromFile(device, "assets/shaders/celestial.frag.spv")) {
|
|
|
|
|
|
LOG_ERROR("Celestial::recreatePipelines: failed to load fragment shader");
|
|
|
|
|
|
vertModule.destroy();
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
VkPipelineShaderStageCreateInfo vertStage = vertModule.stageInfo(VK_SHADER_STAGE_VERTEX_BIT);
|
|
|
|
|
|
VkPipelineShaderStageCreateInfo fragStage = fragModule.stageInfo(VK_SHADER_STAGE_FRAGMENT_BIT);
|
|
|
|
|
|
|
|
|
|
|
|
// Vertex input (same as initialize)
|
|
|
|
|
|
VkVertexInputBindingDescription binding{};
|
|
|
|
|
|
binding.binding = 0;
|
|
|
|
|
|
binding.stride = 5 * sizeof(float);
|
|
|
|
|
|
binding.inputRate = VK_VERTEX_INPUT_RATE_VERTEX;
|
|
|
|
|
|
|
|
|
|
|
|
VkVertexInputAttributeDescription posAttr{};
|
|
|
|
|
|
posAttr.location = 0;
|
|
|
|
|
|
posAttr.binding = 0;
|
|
|
|
|
|
posAttr.format = VK_FORMAT_R32G32B32_SFLOAT;
|
|
|
|
|
|
posAttr.offset = 0;
|
|
|
|
|
|
|
|
|
|
|
|
VkVertexInputAttributeDescription uvAttr{};
|
|
|
|
|
|
uvAttr.location = 1;
|
|
|
|
|
|
uvAttr.binding = 0;
|
|
|
|
|
|
uvAttr.format = VK_FORMAT_R32G32_SFLOAT;
|
|
|
|
|
|
uvAttr.offset = 3 * sizeof(float);
|
|
|
|
|
|
|
|
|
|
|
|
std::vector<VkDynamicState> dynamicStates = {
|
|
|
|
|
|
VK_DYNAMIC_STATE_VIEWPORT,
|
|
|
|
|
|
VK_DYNAMIC_STATE_SCISSOR
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
pipeline_ = PipelineBuilder()
|
|
|
|
|
|
.setShaders(vertStage, fragStage)
|
|
|
|
|
|
.setVertexInput({binding}, {posAttr, uvAttr})
|
|
|
|
|
|
.setTopology(VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST)
|
|
|
|
|
|
.setRasterization(VK_POLYGON_MODE_FILL, VK_CULL_MODE_NONE)
|
|
|
|
|
|
.setDepthTest(true, false, VK_COMPARE_OP_LESS_OR_EQUAL)
|
|
|
|
|
|
.setColorBlendAttachment(PipelineBuilder::blendAlpha())
|
|
|
|
|
|
.setMultisample(vkCtx_->getMsaaSamples())
|
|
|
|
|
|
.setLayout(pipelineLayout_)
|
|
|
|
|
|
.setRenderPass(vkCtx_->getImGuiRenderPass())
|
|
|
|
|
|
.setDynamicStates(dynamicStates)
|
|
|
|
|
|
.build(device);
|
|
|
|
|
|
|
|
|
|
|
|
vertModule.destroy();
|
|
|
|
|
|
fragModule.destroy();
|
|
|
|
|
|
|
|
|
|
|
|
if (pipeline_ == VK_NULL_HANDLE) {
|
|
|
|
|
|
LOG_ERROR("Celestial::recreatePipelines: failed to create pipeline");
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-02-02 12:24:50 -08:00
|
|
|
|
void Celestial::shutdown() {
|
2026-02-21 19:41:21 -08:00
|
|
|
|
destroyQuad();
|
|
|
|
|
|
|
|
|
|
|
|
if (vkCtx_) {
|
|
|
|
|
|
VkDevice device = vkCtx_->getDevice();
|
|
|
|
|
|
if (pipeline_ != VK_NULL_HANDLE) {
|
|
|
|
|
|
vkDestroyPipeline(device, pipeline_, nullptr);
|
|
|
|
|
|
pipeline_ = VK_NULL_HANDLE;
|
|
|
|
|
|
}
|
|
|
|
|
|
if (pipelineLayout_ != VK_NULL_HANDLE) {
|
|
|
|
|
|
vkDestroyPipelineLayout(device, pipelineLayout_, nullptr);
|
|
|
|
|
|
pipelineLayout_ = VK_NULL_HANDLE;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
vkCtx_ = nullptr;
|
2026-02-02 12:24:50 -08:00
|
|
|
|
}
|
|
|
|
|
|
|
2026-02-21 19:41:21 -08:00
|
|
|
|
// ---------------------------------------------------------------------------
|
|
|
|
|
|
// Public render entry point
|
|
|
|
|
|
// ---------------------------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
|
|
void Celestial::render(VkCommandBuffer cmd, VkDescriptorSet perFrameSet,
|
|
|
|
|
|
float timeOfDay,
|
|
|
|
|
|
const glm::vec3* sunDir, const glm::vec3* sunColor,
|
|
|
|
|
|
float gameTime) {
|
|
|
|
|
|
if (!renderingEnabled_ || pipeline_ == VK_NULL_HANDLE) {
|
2026-02-02 12:24:50 -08:00
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-02-21 19:41:21 -08:00
|
|
|
|
// Update moon phases from server game time if provided
|
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)
2026-02-10 14:36:17 -08:00
|
|
|
|
if (gameTime >= 0.0f) {
|
|
|
|
|
|
updatePhasesFromGameTime(gameTime);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-02-21 19:41:21 -08:00
|
|
|
|
// Bind pipeline and per-frame descriptor set once — reused for all draws
|
|
|
|
|
|
vkCmdBindPipeline(cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline_);
|
|
|
|
|
|
vkCmdBindDescriptorSets(cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout_,
|
|
|
|
|
|
0, 1, &perFrameSet, 0, nullptr);
|
2026-02-21 03:10:45 -08:00
|
|
|
|
|
2026-02-21 19:41:21 -08:00
|
|
|
|
// Bind the shared quad buffers
|
|
|
|
|
|
VkDeviceSize offset = 0;
|
|
|
|
|
|
vkCmdBindVertexBuffers(cmd, 0, 1, &vertexBuffer_, &offset);
|
|
|
|
|
|
vkCmdBindIndexBuffer(cmd, indexBuffer_, 0, VK_INDEX_TYPE_UINT32);
|
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)
2026-02-10 14:36:17 -08:00
|
|
|
|
|
2026-02-21 19:41:21 -08:00
|
|
|
|
// Draw sun, then moon(s) — each call pushes different constants
|
|
|
|
|
|
renderSun(cmd, perFrameSet, timeOfDay, sunDir, sunColor);
|
|
|
|
|
|
renderMoon(cmd, perFrameSet, timeOfDay);
|
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)
2026-02-10 14:36:17 -08:00
|
|
|
|
if (dualMoonMode_) {
|
2026-02-21 19:41:21 -08:00
|
|
|
|
renderBlueChild(cmd, perFrameSet, timeOfDay);
|
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)
2026-02-10 14:36:17 -08:00
|
|
|
|
}
|
2026-02-02 12:24:50 -08:00
|
|
|
|
}
|
|
|
|
|
|
|
2026-02-21 19:41:21 -08:00
|
|
|
|
// ---------------------------------------------------------------------------
|
|
|
|
|
|
// Private per-body render helpers
|
|
|
|
|
|
// ---------------------------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
|
|
void Celestial::renderSun(VkCommandBuffer cmd, VkDescriptorSet /*perFrameSet*/,
|
|
|
|
|
|
float timeOfDay,
|
|
|
|
|
|
const glm::vec3* sunDir, const glm::vec3* sunColor) {
|
|
|
|
|
|
// Sun visible 5:00–19:00
|
2026-02-02 12:24:50 -08:00
|
|
|
|
if (timeOfDay < 5.0f || timeOfDay >= 19.0f) {
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-02-21 19:41:21 -08:00
|
|
|
|
// Resolve sun direction — prefer opposite of incoming light ray, clamp below horizon
|
2026-02-21 03:21:08 -08:00
|
|
|
|
glm::vec3 lightDir = sunDir ? glm::normalize(*sunDir) : glm::vec3(0.0f, 0.0f, -1.0f);
|
|
|
|
|
|
glm::vec3 dir = -lightDir;
|
|
|
|
|
|
if (dir.z < 0.0f) {
|
|
|
|
|
|
dir = lightDir;
|
|
|
|
|
|
}
|
2026-02-10 19:30:45 -08:00
|
|
|
|
|
|
|
|
|
|
const float sunDistance = 800.0f;
|
|
|
|
|
|
glm::vec3 sunPos = dir * sunDistance;
|
2026-02-02 12:24:50 -08:00
|
|
|
|
|
|
|
|
|
|
glm::mat4 model = glm::mat4(1.0f);
|
|
|
|
|
|
model = glm::translate(model, sunPos);
|
2026-02-21 19:41:21 -08:00
|
|
|
|
model = glm::scale(model, glm::vec3(95.0f, 95.0f, 1.0f));
|
2026-02-02 12:24:50 -08: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)
2026-02-10 14:36:17 -08:00
|
|
|
|
glm::vec3 color = sunColor ? *sunColor : getSunColor(timeOfDay);
|
2026-02-21 03:10:45 -08:00
|
|
|
|
const glm::vec3 warmSun(1.0f, 0.88f, 0.55f);
|
|
|
|
|
|
color = glm::mix(color, warmSun, 0.52f);
|
|
|
|
|
|
float intensity = getSunIntensity(timeOfDay) * 0.92f;
|
2026-02-02 12:24:50 -08:00
|
|
|
|
|
2026-02-21 19:41:21 -08:00
|
|
|
|
CelestialPush push{};
|
|
|
|
|
|
push.model = model;
|
|
|
|
|
|
push.celestialColor = glm::vec4(color, 1.0f);
|
|
|
|
|
|
push.intensity = intensity;
|
|
|
|
|
|
push.moonPhase = 0.5f; // unused for sun
|
|
|
|
|
|
push.animTime = sunHazeTimer_;
|
|
|
|
|
|
|
|
|
|
|
|
vkCmdPushConstants(cmd, pipelineLayout_,
|
|
|
|
|
|
VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT,
|
|
|
|
|
|
0, sizeof(push), &push);
|
2026-02-02 12:24:50 -08:00
|
|
|
|
|
2026-02-21 19:41:21 -08:00
|
|
|
|
vkCmdDrawIndexed(cmd, 6, 1, 0, 0, 0);
|
2026-02-02 12:24:50 -08:00
|
|
|
|
}
|
|
|
|
|
|
|
2026-02-21 19:41:21 -08:00
|
|
|
|
void Celestial::renderMoon(VkCommandBuffer cmd, VkDescriptorSet /*perFrameSet*/,
|
|
|
|
|
|
float timeOfDay) {
|
|
|
|
|
|
// Moon (White Lady) visible 19:00–5:00
|
2026-02-02 12:24:50 -08:00
|
|
|
|
if (timeOfDay >= 5.0f && timeOfDay < 19.0f) {
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
glm::vec3 moonPos = getMoonPosition(timeOfDay);
|
|
|
|
|
|
|
|
|
|
|
|
glm::mat4 model = glm::mat4(1.0f);
|
|
|
|
|
|
model = glm::translate(model, moonPos);
|
2026-02-21 19:41:21 -08:00
|
|
|
|
model = glm::scale(model, glm::vec3(40.0f, 40.0f, 1.0f));
|
2026-02-02 12:24:50 -08:00
|
|
|
|
|
|
|
|
|
|
glm::vec3 color = glm::vec3(0.8f, 0.85f, 1.0f);
|
|
|
|
|
|
|
|
|
|
|
|
float intensity = 1.0f;
|
|
|
|
|
|
if (timeOfDay >= 19.0f && timeOfDay < 21.0f) {
|
2026-02-21 19:41:21 -08:00
|
|
|
|
intensity = (timeOfDay - 19.0f) / 2.0f; // Fade in
|
|
|
|
|
|
} else if (timeOfDay >= 3.0f && timeOfDay < 5.0f) {
|
|
|
|
|
|
intensity = 1.0f - (timeOfDay - 3.0f) / 2.0f; // Fade out
|
2026-02-02 12:24:50 -08:00
|
|
|
|
}
|
|
|
|
|
|
|
2026-02-21 19:41:21 -08:00
|
|
|
|
CelestialPush push{};
|
|
|
|
|
|
push.model = model;
|
|
|
|
|
|
push.celestialColor = glm::vec4(color, 1.0f);
|
|
|
|
|
|
push.intensity = intensity;
|
|
|
|
|
|
push.moonPhase = whiteLadyPhase_;
|
|
|
|
|
|
push.animTime = sunHazeTimer_;
|
|
|
|
|
|
|
|
|
|
|
|
vkCmdPushConstants(cmd, pipelineLayout_,
|
|
|
|
|
|
VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT,
|
|
|
|
|
|
0, sizeof(push), &push);
|
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)
2026-02-10 14:36:17 -08:00
|
|
|
|
|
2026-02-21 19:41:21 -08:00
|
|
|
|
vkCmdDrawIndexed(cmd, 6, 1, 0, 0, 0);
|
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)
2026-02-10 14:36:17 -08:00
|
|
|
|
}
|
|
|
|
|
|
|
2026-02-21 19:41:21 -08:00
|
|
|
|
void Celestial::renderBlueChild(VkCommandBuffer cmd, VkDescriptorSet /*perFrameSet*/,
|
|
|
|
|
|
float timeOfDay) {
|
|
|
|
|
|
// Blue Child visible 19:00–5: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)
2026-02-10 14:36:17 -08:00
|
|
|
|
if (timeOfDay >= 5.0f && timeOfDay < 19.0f) {
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-02-21 19:41:21 -08:00
|
|
|
|
// Offset slightly from White Lady
|
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)
2026-02-10 14:36:17 -08:00
|
|
|
|
glm::vec3 moonPos = getMoonPosition(timeOfDay);
|
2026-02-21 19:41:21 -08:00
|
|
|
|
moonPos.x += 80.0f;
|
|
|
|
|
|
moonPos.z -= 40.0f;
|
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)
2026-02-10 14:36:17 -08:00
|
|
|
|
|
|
|
|
|
|
glm::mat4 model = glm::mat4(1.0f);
|
|
|
|
|
|
model = glm::translate(model, moonPos);
|
2026-02-21 19:41:21 -08:00
|
|
|
|
model = glm::scale(model, glm::vec3(30.0f, 30.0f, 1.0f));
|
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)
2026-02-10 14:36:17 -08:00
|
|
|
|
|
|
|
|
|
|
glm::vec3 color = glm::vec3(0.7f, 0.8f, 1.0f);
|
|
|
|
|
|
|
|
|
|
|
|
float intensity = 1.0f;
|
|
|
|
|
|
if (timeOfDay >= 19.0f && timeOfDay < 21.0f) {
|
|
|
|
|
|
intensity = (timeOfDay - 19.0f) / 2.0f;
|
2026-02-21 19:41:21 -08:00
|
|
|
|
} else if (timeOfDay >= 3.0f && timeOfDay < 5.0f) {
|
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)
2026-02-10 14:36:17 -08:00
|
|
|
|
intensity = 1.0f - (timeOfDay - 3.0f) / 2.0f;
|
|
|
|
|
|
}
|
2026-02-21 19:41:21 -08:00
|
|
|
|
intensity *= 0.7f; // Blue Child is dimmer
|
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)
2026-02-10 14:36:17 -08:00
|
|
|
|
|
2026-02-21 19:41:21 -08:00
|
|
|
|
CelestialPush push{};
|
|
|
|
|
|
push.model = model;
|
|
|
|
|
|
push.celestialColor = glm::vec4(color, 1.0f);
|
|
|
|
|
|
push.intensity = intensity;
|
|
|
|
|
|
push.moonPhase = blueChildPhase_;
|
|
|
|
|
|
push.animTime = sunHazeTimer_;
|
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)
2026-02-10 14:36:17 -08:00
|
|
|
|
|
2026-02-21 19:41:21 -08:00
|
|
|
|
vkCmdPushConstants(cmd, pipelineLayout_,
|
|
|
|
|
|
VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT,
|
|
|
|
|
|
0, sizeof(push), &push);
|
2026-02-02 12:24:50 -08:00
|
|
|
|
|
2026-02-21 19:41:21 -08:00
|
|
|
|
vkCmdDrawIndexed(cmd, 6, 1, 0, 0, 0);
|
2026-02-02 12:24:50 -08:00
|
|
|
|
}
|
|
|
|
|
|
|
2026-02-21 19:41:21 -08:00
|
|
|
|
// ---------------------------------------------------------------------------
|
|
|
|
|
|
// Position / colour query helpers (identical logic to GL version)
|
|
|
|
|
|
// ---------------------------------------------------------------------------
|
|
|
|
|
|
|
2026-02-02 12:24:50 -08:00
|
|
|
|
glm::vec3 Celestial::getSunPosition(float timeOfDay) const {
|
|
|
|
|
|
float angle = calculateCelestialAngle(timeOfDay, 6.0f, 18.0f);
|
2026-02-21 19:41:21 -08:00
|
|
|
|
const float radius = 800.0f;
|
|
|
|
|
|
const float height = 600.0f;
|
|
|
|
|
|
float x = radius * std::cos(angle);
|
|
|
|
|
|
float z = height * std::sin(angle);
|
|
|
|
|
|
return glm::vec3(x, 0.0f, z);
|
2026-02-02 12:24:50 -08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
glm::vec3 Celestial::getMoonPosition(float timeOfDay) const {
|
|
|
|
|
|
float moonTime = timeOfDay + 12.0f;
|
|
|
|
|
|
if (moonTime >= 24.0f) moonTime -= 24.0f;
|
|
|
|
|
|
float angle = calculateCelestialAngle(moonTime, 6.0f, 18.0f);
|
|
|
|
|
|
const float radius = 800.0f;
|
|
|
|
|
|
const float height = 600.0f;
|
2026-02-10 19:30:45 -08:00
|
|
|
|
float x = radius * std::cos(angle);
|
|
|
|
|
|
float z = height * std::sin(angle);
|
2026-02-21 19:41:21 -08:00
|
|
|
|
return glm::vec3(x, 0.0f, z);
|
2026-02-02 12:24:50 -08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
glm::vec3 Celestial::getSunColor(float timeOfDay) const {
|
|
|
|
|
|
if (timeOfDay >= 5.0f && timeOfDay < 7.0f) {
|
2026-02-21 19:41:21 -08:00
|
|
|
|
return glm::vec3(1.0f, 0.6f, 0.2f); // Sunrise orange
|
|
|
|
|
|
} else if (timeOfDay >= 7.0f && timeOfDay < 9.0f) {
|
2026-02-02 12:24:50 -08:00
|
|
|
|
float t = (timeOfDay - 7.0f) / 2.0f;
|
2026-02-21 19:41:21 -08:00
|
|
|
|
return glm::mix(glm::vec3(1.0f, 0.6f, 0.2f), glm::vec3(1.0f, 1.0f, 0.9f), t);
|
|
|
|
|
|
} else if (timeOfDay >= 9.0f && timeOfDay < 16.0f) {
|
|
|
|
|
|
return glm::vec3(1.0f, 1.0f, 0.9f); // Day yellow-white
|
|
|
|
|
|
} else if (timeOfDay >= 16.0f && timeOfDay < 18.0f) {
|
2026-02-02 12:24:50 -08:00
|
|
|
|
float t = (timeOfDay - 16.0f) / 2.0f;
|
2026-02-21 19:41:21 -08:00
|
|
|
|
return glm::mix(glm::vec3(1.0f, 1.0f, 0.9f), glm::vec3(1.0f, 0.5f, 0.1f), t);
|
|
|
|
|
|
} else {
|
|
|
|
|
|
return glm::vec3(1.0f, 0.4f, 0.1f); // Sunset orange
|
2026-02-02 12:24:50 -08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
float Celestial::getSunIntensity(float timeOfDay) const {
|
|
|
|
|
|
if (timeOfDay >= 5.0f && timeOfDay < 6.0f) {
|
2026-02-21 19:41:21 -08:00
|
|
|
|
return timeOfDay - 5.0f; // Fade in
|
|
|
|
|
|
} else if (timeOfDay >= 6.0f && timeOfDay < 18.0f) {
|
|
|
|
|
|
return 1.0f; // Full day
|
|
|
|
|
|
} else if (timeOfDay >= 18.0f && timeOfDay < 19.0f) {
|
|
|
|
|
|
return 1.0f - (timeOfDay - 18.0f); // Fade out
|
|
|
|
|
|
} else {
|
2026-02-02 12:24:50 -08:00
|
|
|
|
return 0.0f;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
float Celestial::calculateCelestialAngle(float timeOfDay, float riseTime, float setTime) const {
|
|
|
|
|
|
float duration = setTime - riseTime;
|
2026-02-21 19:41:21 -08:00
|
|
|
|
float elapsed = timeOfDay - riseTime;
|
2026-02-02 12:24:50 -08:00
|
|
|
|
float t = elapsed / duration;
|
2026-02-21 19:41:21 -08:00
|
|
|
|
return t * static_cast<float>(M_PI);
|
2026-02-02 12:24:50 -08:00
|
|
|
|
}
|
|
|
|
|
|
|
2026-02-21 19:41:21 -08:00
|
|
|
|
// ---------------------------------------------------------------------------
|
|
|
|
|
|
// Moon phase helpers
|
|
|
|
|
|
// ---------------------------------------------------------------------------
|
2026-02-02 12:24:50 -08:00
|
|
|
|
|
|
|
|
|
|
void Celestial::update(float deltaTime) {
|
2026-02-21 03:10:45 -08:00
|
|
|
|
sunHazeTimer_ += deltaTime;
|
|
|
|
|
|
|
2026-02-21 19:41:21 -08:00
|
|
|
|
if (!moonPhaseCycling_) {
|
2026-02-02 12:24:50 -08:00
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-02-21 19:41:21 -08:00
|
|
|
|
moonPhaseTimer_ += deltaTime;
|
|
|
|
|
|
whiteLadyPhase_ = std::fmod(moonPhaseTimer_ / MOON_CYCLE_DURATION, 1.0f);
|
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)
2026-02-10 14:36:17 -08:00
|
|
|
|
|
2026-02-21 19:41:21 -08:00
|
|
|
|
constexpr float BLUE_CHILD_CYCLE = 210.0f; // Slightly faster: 3.5 minutes
|
|
|
|
|
|
blueChildPhase_ = std::fmod(moonPhaseTimer_ / BLUE_CHILD_CYCLE, 1.0f);
|
2026-02-02 12:24:50 -08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void Celestial::setMoonPhase(float phase) {
|
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)
2026-02-10 14:36:17 -08:00
|
|
|
|
whiteLadyPhase_ = glm::clamp(phase, 0.0f, 1.0f);
|
2026-02-21 19:41:21 -08:00
|
|
|
|
moonPhaseTimer_ = whiteLadyPhase_ * MOON_CYCLE_DURATION;
|
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)
2026-02-10 14:36:17 -08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void Celestial::setBlueChildPhase(float phase) {
|
|
|
|
|
|
blueChildPhase_ = glm::clamp(phase, 0.0f, 1.0f);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
float Celestial::computePhaseFromGameTime(float gameTime, float cycleDays) const {
|
2026-02-21 19:41:21 -08:00
|
|
|
|
constexpr float SECONDS_PER_GAME_DAY = 1440.0f; // 24 real minutes
|
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)
2026-02-10 14:36:17 -08:00
|
|
|
|
float gameDays = gameTime / SECONDS_PER_GAME_DAY;
|
2026-02-21 19:41:21 -08:00
|
|
|
|
float phase = std::fmod(gameDays / cycleDays, 1.0f);
|
|
|
|
|
|
if (phase < 0.0f) phase += 1.0f;
|
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)
2026-02-10 14:36:17 -08:00
|
|
|
|
return phase;
|
|
|
|
|
|
}
|
2026-02-02 12:24:50 -08: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)
2026-02-10 14:36:17 -08:00
|
|
|
|
void Celestial::updatePhasesFromGameTime(float gameTime) {
|
|
|
|
|
|
whiteLadyPhase_ = computePhaseFromGameTime(gameTime, WHITE_LADY_CYCLE_DAYS);
|
|
|
|
|
|
blueChildPhase_ = computePhaseFromGameTime(gameTime, BLUE_CHILD_CYCLE_DAYS);
|
2026-02-02 12:24:50 -08:00
|
|
|
|
}
|
|
|
|
|
|
|
2026-02-21 19:41:21 -08:00
|
|
|
|
// ---------------------------------------------------------------------------
|
|
|
|
|
|
// GPU buffer management
|
|
|
|
|
|
// ---------------------------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
|
|
void Celestial::createQuad() {
|
|
|
|
|
|
// Billboard quad centred at origin, vertices: pos(vec3) + uv(vec2)
|
|
|
|
|
|
float vertices[] = {
|
|
|
|
|
|
// Position TexCoord
|
|
|
|
|
|
-0.5f, 0.5f, 0.0f, 0.0f, 1.0f, // Top-left
|
|
|
|
|
|
0.5f, 0.5f, 0.0f, 1.0f, 1.0f, // Top-right
|
|
|
|
|
|
0.5f, -0.5f, 0.0f, 1.0f, 0.0f, // Bottom-right
|
|
|
|
|
|
-0.5f, -0.5f, 0.0f, 0.0f, 0.0f, // Bottom-left
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
uint32_t indices[] = { 0, 1, 2, 0, 2, 3 };
|
|
|
|
|
|
|
|
|
|
|
|
AllocatedBuffer vbuf = uploadBuffer(*vkCtx_,
|
|
|
|
|
|
vertices, sizeof(vertices),
|
|
|
|
|
|
VK_BUFFER_USAGE_VERTEX_BUFFER_BIT);
|
|
|
|
|
|
vertexBuffer_ = vbuf.buffer;
|
|
|
|
|
|
vertexAlloc_ = vbuf.allocation;
|
|
|
|
|
|
|
|
|
|
|
|
AllocatedBuffer ibuf = uploadBuffer(*vkCtx_,
|
|
|
|
|
|
indices, sizeof(indices),
|
|
|
|
|
|
VK_BUFFER_USAGE_INDEX_BUFFER_BIT);
|
|
|
|
|
|
indexBuffer_ = ibuf.buffer;
|
|
|
|
|
|
indexAlloc_ = ibuf.allocation;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void Celestial::destroyQuad() {
|
|
|
|
|
|
if (!vkCtx_) return;
|
|
|
|
|
|
|
|
|
|
|
|
VmaAllocator allocator = vkCtx_->getAllocator();
|
|
|
|
|
|
|
|
|
|
|
|
if (vertexBuffer_ != VK_NULL_HANDLE) {
|
|
|
|
|
|
vmaDestroyBuffer(allocator, vertexBuffer_, vertexAlloc_);
|
|
|
|
|
|
vertexBuffer_ = VK_NULL_HANDLE;
|
|
|
|
|
|
vertexAlloc_ = VK_NULL_HANDLE;
|
|
|
|
|
|
}
|
|
|
|
|
|
if (indexBuffer_ != VK_NULL_HANDLE) {
|
|
|
|
|
|
vmaDestroyBuffer(allocator, indexBuffer_, indexAlloc_);
|
|
|
|
|
|
indexBuffer_ = VK_NULL_HANDLE;
|
|
|
|
|
|
indexAlloc_ = VK_NULL_HANDLE;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-02-02 12:24:50 -08:00
|
|
|
|
} // namespace rendering
|
|
|
|
|
|
} // namespace wowee
|