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)
|
feat(animation): 452 named constants, 30-phase character animation state machine
Add animation_ids.hpp/cpp with all 452 WoW animation ID constants (anim::STAND,
anim::RUN, anim::FIRE_BOW, ... anim::FLY_BACKWARDS, etc.), nameFromId() O(1)
lookup, and flyVariant() compact 218-element ground→FLY_* resolver.
Expand AnimationController into a full state machine with 20+ named states:
spell cast (directed→omni→cast fallback chain, instant one-shot release),
hit reactions (WOUND/CRIT/DODGE/BLOCK/SHIELD_BLOCK), stun, wounded idle,
stealth animation substitution, loot, fishing channel, sit/sleep/kneel
down→loop→up transitions, sheathe/unsheathe combat enter/exit, ranged weapons
(BOW/GUN/CROSSBOW/THROWN with reload states), game object OPEN/CLOSE/DESTROY,
vehicle enter/exit, mount flight directionals (FLY_LEFT/RIGHT/UP/DOWN/BACKWARDS),
emote state variants, off-hand/pierce/dual-wield alternation, NPC
birth/spawn/drown/rise, sprint aura override, totem idle, NPC greeting/farewell.
Add spell_defines.hpp with SpellEffect (~45 constants) and SpellMissInfo
(12 constants) namespaces; replace all magic numbers in spell_handler.cpp.
Add GAMEOBJECT_BYTES_1 to update field table (all 4 expansion JSONs) and wire
GameObjectStateCallback. Add DBC cross-validation on world entry.
Expand tools/_ANIM_NAMES from ~35 to 452 entries in m2_viewer.py and
asset_pipeline_gui.py. Add tests/test_animation_ids.cpp.
Bug fixes included:
- Stand state 1 was animating READY_2H(27) — fixed to SITTING(97)
- Spell casts ended freeze-frame — add one-shot release animation
- NPC 2H swing probe chain missing ATTACK_2H_LOOSE (polearm/staff)
- Chair sits (states 2/4/5/6) incorrectly played floor-sit transition
- STOP(3) used for all spell casts — replaced with model-aware chain
2026-04-04 23:02:53 +03:00
|
|
|
|
.setNoDepthTest() // Sky layer: celestials always render (skybox doesn't write depth)
|
2026-02-23 07:40:51 -08:00
|
|
|
|
.setColorBlendAttachment(PipelineBuilder::blendAdditive())
|
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)
|
2026-03-24 09:47:03 -07:00
|
|
|
|
.build(device, vkCtx_->getPipelineCache());
|
2026-02-21 19:41:21 -08:00
|
|
|
|
|
|
|
|
|
|
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)
|
2026-02-23 07:40:51 -08:00
|
|
|
|
.setColorBlendAttachment(PipelineBuilder::blendAdditive())
|
2026-02-22 02:59:24 -08:00
|
|
|
|
.setMultisample(vkCtx_->getMsaaSamples())
|
|
|
|
|
|
.setLayout(pipelineLayout_)
|
|
|
|
|
|
.setRenderPass(vkCtx_->getImGuiRenderPass())
|
|
|
|
|
|
.setDynamicStates(dynamicStates)
|
2026-03-24 09:47:03 -07:00
|
|
|
|
.build(device, vkCtx_->getPipelineCache());
|
2026-02-22 02:59:24 -08:00
|
|
|
|
|
|
|
|
|
|
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;
|
feat(animation): 452 named constants, 30-phase character animation state machine
Add animation_ids.hpp/cpp with all 452 WoW animation ID constants (anim::STAND,
anim::RUN, anim::FIRE_BOW, ... anim::FLY_BACKWARDS, etc.), nameFromId() O(1)
lookup, and flyVariant() compact 218-element ground→FLY_* resolver.
Expand AnimationController into a full state machine with 20+ named states:
spell cast (directed→omni→cast fallback chain, instant one-shot release),
hit reactions (WOUND/CRIT/DODGE/BLOCK/SHIELD_BLOCK), stun, wounded idle,
stealth animation substitution, loot, fishing channel, sit/sleep/kneel
down→loop→up transitions, sheathe/unsheathe combat enter/exit, ranged weapons
(BOW/GUN/CROSSBOW/THROWN with reload states), game object OPEN/CLOSE/DESTROY,
vehicle enter/exit, mount flight directionals (FLY_LEFT/RIGHT/UP/DOWN/BACKWARDS),
emote state variants, off-hand/pierce/dual-wield alternation, NPC
birth/spawn/drown/rise, sprint aura override, totem idle, NPC greeting/farewell.
Add spell_defines.hpp with SpellEffect (~45 constants) and SpellMissInfo
(12 constants) namespaces; replace all magic numbers in spell_handler.cpp.
Add GAMEOBJECT_BYTES_1 to update field table (all 4 expansion JSONs) and wire
GameObjectStateCallback. Add DBC cross-validation on world entry.
Expand tools/_ANIM_NAMES from ~35 to 452 entries in m2_viewer.py and
asset_pipeline_gui.py. Add tests/test_animation_ids.cpp.
Bug fixes included:
- Stand state 1 was animating READY_2H(27) — fixed to SITTING(97)
- Spell casts ended freeze-frame — add one-shot release animation
- NPC 2H swing probe chain missing ATTACK_2H_LOOSE (polearm/staff)
- Chair sits (states 2/4/5/6) incorrectly played floor-sit transition
- STOP(3) used for all spell casts — replaced with model-aware chain
2026-04-04 23:02:53 +03:00
|
|
|
|
// Keep timer in a range where GPU sin() precision is reliable (< ~10000).
|
|
|
|
|
|
// The noise period repeats at multiples of 1.0 on each axis, so fmod by a
|
|
|
|
|
|
// large integer preserves visual continuity.
|
|
|
|
|
|
if (sunHazeTimer_ > 10000.0f) {
|
|
|
|
|
|
sunHazeTimer_ = std::fmod(sunHazeTimer_, 10000.0f);
|
|
|
|
|
|
}
|
2026-02-21 03:10:45 -08:00
|
|
|
|
|
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
|