mirror of
https://github.com/Kelsidavis/WoWee.git
synced 2026-03-22 23:30:14 +00:00
Implement WoW 3.3.5a DBC-driven lighting system
Add complete Blizzard-style time-of-day lighting pipeline: Spatial Volume System (Light.dbc): - Light volumes with position + inner/outer radius - Distance-based weighting with smoothstep falloff - Multi-volume blending (top 2 with normalized weights) - X,Z,Y coordinate handling + LIGHT_COORD_SCALE for ×36 quirk - Smooth zone transitions without popping Profile Selection (LightParams.dbc): - Weather variants: clear/rain/underwater - Links to 18 color + 6 float band curves per profile - Block indexing: LightParamsID × 18/6 + channel Time-of-Day Band Sampling (LightIntBand/LightFloatBand): - Half-minutes format (0-2879) with time clamping - Keyframe interpolation with midnight wrap - Wrap-safe initialization for edge cases - BGR color unpacking Multi-Volume Blending: - Weighted sum of all lighting params - Proper direction blending: normalize(sum(dir × weight)) - Blends ambient, diffuse, fog, sky, cloud density Temporal Smoothing: - Exponential blend to prevent frame snapping - Smooths ALL parameters (colors, fog, direction, sky) Game Time Support: - Accepts server-sent game time (WoW standard) - Falls back to local time if not provided - Manual override for testing Debug Features: - Volume distance/weight logging - Fog params logging - Coordinate scale verification Also: Move buff bar to top-left under player frame
This commit is contained in:
parent
3c13cf4b12
commit
69fa4c6e03
4 changed files with 819 additions and 4 deletions
263
include/rendering/lighting_manager.hpp
Normal file
263
include/rendering/lighting_manager.hpp
Normal file
|
|
@ -0,0 +1,263 @@
|
|||
#pragma once
|
||||
|
||||
#include <vector>
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <glm/glm.hpp>
|
||||
|
||||
namespace wowee {
|
||||
namespace pipeline { class DBCFile; class AssetManager; }
|
||||
|
||||
namespace rendering {
|
||||
|
||||
/**
|
||||
* Time-of-day lighting parameters sampled from DBC curves
|
||||
*/
|
||||
struct LightingParams {
|
||||
glm::vec3 ambientColor{0.4f, 0.4f, 0.5f}; // Fill lighting
|
||||
glm::vec3 diffuseColor{1.0f, 0.95f, 0.8f}; // Directional sun color
|
||||
glm::vec3 directionalDir{0.0f, -1.0f, 0.5f}; // Sun direction (normalized)
|
||||
|
||||
glm::vec3 fogColor{0.5f, 0.6f, 0.7f}; // Fog color
|
||||
float fogStart = 100.0f; // Fog start distance
|
||||
float fogEnd = 1000.0f; // Fog end distance
|
||||
float fogDensity = 0.001f; // Fog density
|
||||
|
||||
glm::vec3 skyTopColor{0.5f, 0.7f, 1.0f}; // Sky zenith color
|
||||
glm::vec3 skyMiddleColor{0.7f, 0.85f, 1.0f}; // Sky horizon color
|
||||
glm::vec3 skyBand1Color{0.9f, 0.95f, 1.0f}; // Sky band 1
|
||||
glm::vec3 skyBand2Color{1.0f, 0.98f, 0.9f}; // Sky band 2
|
||||
|
||||
float cloudDensity = 1.0f; // Cloud density/opacity
|
||||
float horizonGlow = 0.3f; // Horizon glow intensity
|
||||
};
|
||||
|
||||
/**
|
||||
* Light set keyframe for time-of-day interpolation
|
||||
*/
|
||||
struct LightKeyframe {
|
||||
uint32_t time; // Time in minutes since midnight (0-1439)
|
||||
|
||||
// Colors stored as RGB int tuples (0-255) in DBC
|
||||
glm::vec3 ambientColor;
|
||||
glm::vec3 diffuseColor;
|
||||
glm::vec3 fogColor;
|
||||
glm::vec3 skyTopColor;
|
||||
glm::vec3 skyMiddleColor;
|
||||
glm::vec3 skyBand1Color;
|
||||
glm::vec3 skyBand2Color;
|
||||
|
||||
float fogStart;
|
||||
float fogEnd;
|
||||
float fogDensity;
|
||||
float cloudDensity;
|
||||
float horizonGlow;
|
||||
};
|
||||
|
||||
/**
|
||||
* Light volume from Light.dbc (spatial lighting)
|
||||
*/
|
||||
struct LightVolume {
|
||||
uint32_t lightId = 0;
|
||||
uint32_t mapId = 0;
|
||||
glm::vec3 position{0.0f}; // World position (note: DBC stores as x,z,y!)
|
||||
float innerRadius = 0.0f; // Full weight radius
|
||||
float outerRadius = 0.0f; // Fade-out radius
|
||||
|
||||
// LightParams IDs for different conditions
|
||||
uint32_t lightParamsId = 0; // Normal/clear weather
|
||||
uint32_t lightParamsIdRain = 0; // Rainy weather
|
||||
uint32_t lightParamsIdUnderwater = 0;
|
||||
// More variants exist for phases, death, etc.
|
||||
};
|
||||
|
||||
/**
|
||||
* Color band with time-of-day keyframes
|
||||
*/
|
||||
struct ColorBand {
|
||||
uint8_t numKeyframes = 0;
|
||||
uint16_t times[16]; // Time keyframes (half-minutes since midnight)
|
||||
glm::vec3 colors[16]; // Color values (RGB 0-1)
|
||||
};
|
||||
|
||||
/**
|
||||
* Float band with time-of-day keyframes
|
||||
*/
|
||||
struct FloatBand {
|
||||
uint8_t numKeyframes = 0;
|
||||
uint16_t times[16]; // Time keyframes (half-minutes since midnight)
|
||||
float values[16]; // Float values
|
||||
};
|
||||
|
||||
/**
|
||||
* LightParams profile with 18 color bands + 6 float bands
|
||||
*/
|
||||
struct LightParamsProfile {
|
||||
uint32_t lightParamsId = 0;
|
||||
|
||||
// 18 color channels (IntBand)
|
||||
enum ColorChannel {
|
||||
AMBIENT_COLOR = 0,
|
||||
DIFFUSE_COLOR = 1,
|
||||
SKY_TOP_COLOR = 2,
|
||||
SKY_MIDDLE_COLOR = 3,
|
||||
SKY_BAND1_COLOR = 4,
|
||||
SKY_BAND2_COLOR = 5,
|
||||
FOG_COLOR = 6,
|
||||
// ... more channels exist (ocean, river, shadow, etc.)
|
||||
COLOR_CHANNEL_COUNT = 18
|
||||
};
|
||||
|
||||
ColorBand colorBands[COLOR_CHANNEL_COUNT];
|
||||
|
||||
// 6 float channels (FloatBand)
|
||||
enum FloatChannel {
|
||||
FOG_END = 0,
|
||||
FOG_START_SCALAR = 1, // Multiplier for fog start
|
||||
CLOUD_DENSITY = 2,
|
||||
FOG_DENSITY = 3,
|
||||
// ... more channels
|
||||
FLOAT_CHANNEL_COUNT = 6
|
||||
};
|
||||
|
||||
FloatBand floatBands[FLOAT_CHANNEL_COUNT];
|
||||
};
|
||||
|
||||
/**
|
||||
* WoW DBC-driven lighting manager
|
||||
*
|
||||
* Implements WotLK's time-of-day lighting system:
|
||||
* - Loads Light.dbc, LightParams.dbc, LightIntBand.dbc, LightFloatBand.dbc
|
||||
* - Samples lighting curves based on time-of-day
|
||||
* - Interpolates between keyframes
|
||||
* - Provides lighting parameters for rendering
|
||||
*/
|
||||
class LightingManager {
|
||||
public:
|
||||
LightingManager();
|
||||
~LightingManager();
|
||||
|
||||
/**
|
||||
* Initialize lighting system and load DBCs
|
||||
*/
|
||||
bool initialize(pipeline::AssetManager* assetManager);
|
||||
|
||||
/**
|
||||
* Update lighting for current time and player position
|
||||
* @param playerPos Player world position
|
||||
* @param mapId Current map ID
|
||||
* @param gameTime Optional game time in seconds (use -1 for real time)
|
||||
* @param isRaining Whether it's raining
|
||||
* @param isUnderwater Whether player is underwater
|
||||
*
|
||||
* Note: WoW uses server-sent game time, not local PC time.
|
||||
* Pass gameTime from SMSG_LOGIN_SETTIMESPEED or similar.
|
||||
*/
|
||||
void update(const glm::vec3& playerPos, uint32_t mapId,
|
||||
float gameTime = -1.0f,
|
||||
bool isRaining = false, bool isUnderwater = false);
|
||||
|
||||
/**
|
||||
* Get current lighting parameters
|
||||
*/
|
||||
const LightingParams& getLightingParams() const { return currentParams_; }
|
||||
|
||||
/**
|
||||
* Set whether player is indoors (disables outdoor lighting)
|
||||
*/
|
||||
void setIndoors(bool indoors) { isIndoors_ = indoors; }
|
||||
|
||||
/**
|
||||
* Get current time of day (0.0-1.0)
|
||||
*/
|
||||
float getTimeOfDay() const { return timeOfDay_; }
|
||||
|
||||
/**
|
||||
* Manually set time of day for testing
|
||||
*/
|
||||
void setTimeOfDay(float tod) { timeOfDay_ = tod; manualTime_ = true; }
|
||||
|
||||
/**
|
||||
* Use real time for day/night cycle
|
||||
*/
|
||||
void useRealTime(bool use) { manualTime_ = !use; }
|
||||
|
||||
private:
|
||||
/**
|
||||
* Load Light.dbc
|
||||
*/
|
||||
bool loadLightDbc(pipeline::AssetManager* assetManager);
|
||||
|
||||
/**
|
||||
* Load LightParams.dbc for zone→light mapping
|
||||
*/
|
||||
bool loadLightParamsDbc(pipeline::AssetManager* assetManager);
|
||||
|
||||
/**
|
||||
* Load LightIntBand.dbc and LightFloatBand.dbc for time curves
|
||||
*/
|
||||
bool loadLightBandDbcs(pipeline::AssetManager* assetManager);
|
||||
|
||||
/**
|
||||
* Weighted light volume for blending
|
||||
*/
|
||||
struct WeightedVolume {
|
||||
const LightVolume* volume = nullptr;
|
||||
float weight = 0.0f;
|
||||
};
|
||||
|
||||
/**
|
||||
* Find light volumes for blending (up to 4 with weight > 0)
|
||||
*/
|
||||
std::vector<WeightedVolume> findLightVolumes(const glm::vec3& playerPos, uint32_t mapId) const;
|
||||
|
||||
/**
|
||||
* Get LightParams ID based on conditions
|
||||
*/
|
||||
uint32_t selectLightParamsId(const LightVolume* volume, bool isRaining, bool isUnderwater) const;
|
||||
|
||||
/**
|
||||
* Sample lighting from LightParams profile
|
||||
*/
|
||||
LightingParams sampleLightParams(const LightParamsProfile* profile, uint16_t timeHalfMinutes) const;
|
||||
|
||||
/**
|
||||
* Sample color from band
|
||||
*/
|
||||
glm::vec3 sampleColorBand(const ColorBand& band, uint16_t timeHalfMinutes) const;
|
||||
|
||||
/**
|
||||
* Sample float from band
|
||||
*/
|
||||
float sampleFloatBand(const FloatBand& band, uint16_t timeHalfMinutes) const;
|
||||
|
||||
/**
|
||||
* Convert DBC BGR color to RGB vec3
|
||||
*/
|
||||
glm::vec3 dbcColorToVec3(uint32_t dbcColor) const;
|
||||
|
||||
pipeline::AssetManager* assetManager_ = nullptr;
|
||||
|
||||
// Light volumes by map
|
||||
std::map<uint32_t, std::vector<LightVolume>> lightVolumesByMap_;
|
||||
|
||||
// LightParams profiles by ID
|
||||
std::map<uint32_t, LightParamsProfile> lightParamsProfiles_;
|
||||
|
||||
// Current state
|
||||
LightingParams currentParams_;
|
||||
LightingParams targetParams_; // For smooth blending
|
||||
std::vector<WeightedVolume> activeVolumes_;
|
||||
glm::vec3 currentPlayerPos_{0.0f};
|
||||
uint32_t currentMapId_ = 0;
|
||||
float timeOfDay_ = 0.5f; // Start at noon
|
||||
bool isIndoors_ = false;
|
||||
bool manualTime_ = false;
|
||||
bool initialized_ = false;
|
||||
|
||||
// Fallback lighting
|
||||
LightingParams fallbackParams_;
|
||||
};
|
||||
|
||||
} // namespace rendering
|
||||
} // namespace wowee
|
||||
Loading…
Add table
Add a link
Reference in a new issue