mirror of
https://github.com/Kelsidavis/WoWee.git
synced 2026-02-20 08:14:55 -05:00
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
264 lines
7.4 KiB
C++
264 lines
7.4 KiB
C++
#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
|