mirror of
https://github.com/Kelsidavis/WoWee.git
synced 2026-05-02 15:53:51 +00:00
Merge pull request #55 from ldmonster/chore/code-quality-cleaup
Some checks are pending
Build / Build (arm64) (push) Waiting to run
Build / Build (x86-64) (push) Waiting to run
Build / Build (macOS arm64) (push) Waiting to run
Build / Build (windows-arm64) (push) Waiting to run
Build / Build (windows-x86-64) (push) Waiting to run
Security / CodeQL (C/C++) (push) Waiting to run
Security / Semgrep (push) Waiting to run
Security / Sanitizer Build (ASan/UBSan) (push) Waiting to run
Some checks are pending
Build / Build (arm64) (push) Waiting to run
Build / Build (x86-64) (push) Waiting to run
Build / Build (macOS arm64) (push) Waiting to run
Build / Build (windows-arm64) (push) Waiting to run
Build / Build (windows-x86-64) (push) Waiting to run
Security / CodeQL (C/C++) (push) Waiting to run
Security / Semgrep (push) Waiting to run
Security / Sanitizer Build (ASan/UBSan) (push) Waiting to run
[chore] Code Quality & DRY/KISS Cleanup
This commit is contained in:
commit
996dc56691
41 changed files with 849 additions and 424 deletions
|
|
@ -2130,7 +2130,9 @@ void CharacterRenderer::render(VkCommandBuffer cmd, VkDescriptorSet perFrameSet,
|
|||
}
|
||||
const float renderRadius = static_cast<float>(envSizeOrDefault("WOWEE_CHAR_RENDER_RADIUS", 130));
|
||||
const float renderRadiusSq = renderRadius * renderRadius;
|
||||
const float characterCullRadius = 2.0f; // Estimate character radius for frustum testing
|
||||
// Default frustum-cull radius when model bounds aren't available.
|
||||
// 4.0 covers Tauren, mounted characters, and most creature models.
|
||||
constexpr float kDefaultCharacterCullRadius = 4.0f;
|
||||
const glm::vec3 camPos = camera.getPosition();
|
||||
|
||||
// Extract frustum planes for per-instance visibility testing
|
||||
|
|
@ -2175,8 +2177,17 @@ void CharacterRenderer::render(VkCommandBuffer cmd, VkDescriptorSet perFrameSet,
|
|||
// Distance cull: skip if beyond render radius
|
||||
if (distSq > renderRadiusSq) continue;
|
||||
|
||||
// Compute per-instance bounding radius from model data when available.
|
||||
float cullRadius = kDefaultCharacterCullRadius;
|
||||
auto mIt = models.find(instance.modelId);
|
||||
if (mIt != models.end()) {
|
||||
float modelR = mIt->second.data.boundRadius;
|
||||
if (modelR > 0.01f)
|
||||
cullRadius = std::max(kDefaultCharacterCullRadius, modelR * std::max(0.001f, instance.scale));
|
||||
}
|
||||
|
||||
// Frustum cull: skip if outside view frustum
|
||||
if (!frustum.intersectsSphere(instance.position, characterCullRadius)) continue;
|
||||
if (!frustum.intersectsSphere(instance.position, cullRadius)) continue;
|
||||
}
|
||||
|
||||
if (!instance.cachedModel) continue;
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@
|
|||
#include "rendering/vk_frame_data.hpp"
|
||||
#include "rendering/camera.hpp"
|
||||
#include "rendering/frustum.hpp"
|
||||
#include "rendering/render_constants.hpp"
|
||||
#include "pipeline/asset_manager.hpp"
|
||||
#include "pipeline/blp_loader.hpp"
|
||||
#include "core/logger.hpp"
|
||||
|
|
@ -90,7 +91,7 @@ uint32_t M2Renderer::createInstance(uint32_t modelId, const glm::vec3& position,
|
|||
instance.idleSequenceIndex = 0;
|
||||
instance.animDuration = static_cast<float>(mdl.sequences[0].duration);
|
||||
instance.animTime = static_cast<float>(randRange(std::max(1u, mdl.sequences[0].duration)));
|
||||
instance.variationTimer = randFloat(3000.0f, 11000.0f);
|
||||
instance.variationTimer = randFloat(rendering::M2_VARIATION_TIMER_MIN_MS, rendering::M2_VARIATION_TIMER_MAX_MS);
|
||||
}
|
||||
|
||||
// Seed bone matrices from an existing instance of the same model so the
|
||||
|
|
@ -199,7 +200,7 @@ uint32_t M2Renderer::createInstanceWithMatrix(uint32_t modelId, const glm::mat4&
|
|||
instance.idleSequenceIndex = 0;
|
||||
instance.animDuration = static_cast<float>(mdl2.sequences[0].duration);
|
||||
instance.animTime = static_cast<float>(randRange(std::max(1u, mdl2.sequences[0].duration)));
|
||||
instance.variationTimer = randFloat(3000.0f, 11000.0f);
|
||||
instance.variationTimer = randFloat(rendering::M2_VARIATION_TIMER_MIN_MS, rendering::M2_VARIATION_TIMER_MAX_MS);
|
||||
}
|
||||
|
||||
// Seed bone matrices from an existing sibling so the instance renders immediately
|
||||
|
|
@ -263,7 +264,9 @@ void M2Renderer::update(float deltaTime, const glm::vec3& cameraPos, const glm::
|
|||
|
||||
// Cache camera state for frustum-culling bone computation
|
||||
cachedCamPos_ = cameraPos;
|
||||
const float maxRenderDistance = (instances.size() > 2000) ? 800.0f : 2800.0f;
|
||||
const float maxRenderDistance = (instances.size() > rendering::M2_HIGH_DENSITY_INSTANCE_THRESHOLD)
|
||||
? rendering::M2_MAX_RENDER_DISTANCE_HIGH_DENSITY
|
||||
: rendering::M2_MAX_RENDER_DISTANCE_LOW_DENSITY;
|
||||
cachedMaxRenderDistSq_ = maxRenderDistance * maxRenderDistance;
|
||||
|
||||
// Build frustum for culling bones
|
||||
|
|
@ -271,10 +274,10 @@ void M2Renderer::update(float deltaTime, const glm::vec3& cameraPos, const glm::
|
|||
updateFrustum.extractFromMatrix(viewProjection);
|
||||
|
||||
// --- Smoke particle spawning (only iterate tracked smoke instances) ---
|
||||
std::uniform_real_distribution<float> distXY(-0.4f, 0.4f);
|
||||
std::uniform_real_distribution<float> distXY(rendering::SMOKE_OFFSET_XY_MIN, rendering::SMOKE_OFFSET_XY_MAX);
|
||||
std::uniform_real_distribution<float> distVelXY(-0.3f, 0.3f);
|
||||
std::uniform_real_distribution<float> distVelZ(3.0f, 5.0f);
|
||||
std::uniform_real_distribution<float> distLife(4.0f, 7.0f);
|
||||
std::uniform_real_distribution<float> distVelZ(rendering::SMOKE_VEL_Z_MIN, rendering::SMOKE_VEL_Z_MAX);
|
||||
std::uniform_real_distribution<float> distLife(rendering::SMOKE_LIFETIME_MIN, rendering::SMOKE_LIFETIME_MAX);
|
||||
std::uniform_real_distribution<float> distDrift(-0.2f, 0.2f);
|
||||
|
||||
smokeEmitAccum += deltaTime;
|
||||
|
|
@ -287,13 +290,13 @@ void M2Renderer::update(float deltaTime, const glm::vec3& cameraPos, const glm::
|
|||
auto& instance = instances[si];
|
||||
|
||||
glm::vec3 emitWorld = glm::vec3(instance.modelMatrix * glm::vec4(0.0f, 0.0f, 0.0f, 1.0f));
|
||||
bool spark = (smokeRng() % 8 == 0);
|
||||
bool spark = (smokeRng() % rendering::SPARK_PROBABILITY_DENOM == 0);
|
||||
|
||||
SmokeParticle p;
|
||||
p.position = emitWorld + glm::vec3(distXY(smokeRng), distXY(smokeRng), 0.0f);
|
||||
if (spark) {
|
||||
p.velocity = glm::vec3(distVelXY(smokeRng) * 2.0f, distVelXY(smokeRng) * 2.0f, distVelZ(smokeRng) * 1.5f);
|
||||
p.maxLife = 0.8f + static_cast<float>(smokeRng() % 100) / 100.0f * 1.2f;
|
||||
p.maxLife = rendering::SPARK_LIFE_BASE + static_cast<float>(smokeRng() % 100) / 100.0f * rendering::SPARK_LIFE_RANGE;
|
||||
p.size = 0.5f;
|
||||
p.isSpark = 1.0f;
|
||||
} else {
|
||||
|
|
@ -320,12 +323,12 @@ void M2Renderer::update(float deltaTime, const glm::vec3& cameraPos, const glm::
|
|||
continue;
|
||||
}
|
||||
p.position += p.velocity * deltaTime;
|
||||
p.velocity.z *= 0.98f; // Slight deceleration
|
||||
p.velocity.z *= rendering::SMOKE_Z_VEL_DAMPING; // Slight deceleration
|
||||
p.velocity.x += distDrift(smokeRng) * deltaTime;
|
||||
p.velocity.y += distDrift(smokeRng) * deltaTime;
|
||||
// Grow from 1.0 to 3.5 over lifetime
|
||||
float t = p.life / p.maxLife;
|
||||
p.size = 1.0f + t * 2.5f;
|
||||
p.size = rendering::SMOKE_SIZE_START + t * rendering::SMOKE_SIZE_GROWTH;
|
||||
++i;
|
||||
}
|
||||
|
||||
|
|
@ -389,7 +392,7 @@ void M2Renderer::update(float deltaTime, const glm::vec3& cameraPos, const glm::
|
|||
|
||||
// Handle animation looping / variation transitions
|
||||
if (instance.animDuration <= 0.0f && instance.cachedHasParticleEmitters) {
|
||||
instance.animDuration = 3333.0f;
|
||||
instance.animDuration = rendering::M2_DEFAULT_PARTICLE_ANIM_MS;
|
||||
}
|
||||
if (instance.animDuration > 0.0f && instance.animTime >= instance.animDuration) {
|
||||
if (instance.playingVariation) {
|
||||
|
|
@ -399,7 +402,7 @@ void M2Renderer::update(float deltaTime, const glm::vec3& cameraPos, const glm::
|
|||
instance.animDuration = static_cast<float>(model.sequences[instance.idleSequenceIndex].duration);
|
||||
}
|
||||
instance.animTime = 0.0f;
|
||||
instance.variationTimer = randFloat(4000.0f, 10000.0f);
|
||||
instance.variationTimer = randFloat(rendering::M2_LOOP_VARIATION_TIMER_MIN_MS, rendering::M2_LOOP_VARIATION_TIMER_MAX_MS);
|
||||
} else {
|
||||
// Use iterative subtraction instead of fmod() to preserve precision
|
||||
float duration = std::max(1.0f, instance.animDuration);
|
||||
|
|
@ -421,7 +424,7 @@ void M2Renderer::update(float deltaTime, const glm::vec3& cameraPos, const glm::
|
|||
instance.animDuration = static_cast<float>(model.sequences[newSeq].duration);
|
||||
instance.animTime = 0.0f;
|
||||
} else {
|
||||
instance.variationTimer = randFloat(2000.0f, 6000.0f);
|
||||
instance.variationTimer = randFloat(rendering::M2_IDLE_VARIATION_TIMER_MIN_MS, rendering::M2_IDLE_VARIATION_TIMER_MAX_MS);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -431,21 +434,21 @@ void M2Renderer::update(float deltaTime, const glm::vec3& cameraPos, const glm::
|
|||
float cullRadius = worldRadius;
|
||||
glm::vec3 toCam = instance.position - cachedCamPos_;
|
||||
float distSq = glm::dot(toCam, toCam);
|
||||
float effectiveMaxDistSq = cachedMaxRenderDistSq_ * std::max(1.0f, cullRadius / 12.0f);
|
||||
float effectiveMaxDistSq = cachedMaxRenderDistSq_ * std::max(1.0f, cullRadius / rendering::M2_CULL_RADIUS_SCALE_DIVISOR);
|
||||
if (distSq > effectiveMaxDistSq) continue;
|
||||
float paddedRadius = std::max(cullRadius * 1.5f, cullRadius + 3.0f);
|
||||
float paddedRadius = std::max(cullRadius * rendering::M2_PADDED_RADIUS_SCALE, cullRadius + rendering::M2_PADDED_RADIUS_MIN_MARGIN);
|
||||
if (cullRadius > 0.0f && !updateFrustum.intersectsSphere(instance.position, paddedRadius)) continue;
|
||||
|
||||
// LOD 3 skip: models beyond 150 units use the lowest LOD mesh which has
|
||||
// no visible skeletal animation. Keep their last-computed bone matrices
|
||||
// (always valid — seeded on spawn) and avoid the expensive per-bone work.
|
||||
constexpr float kLOD3DistSq = 150.0f * 150.0f;
|
||||
constexpr float kLOD3DistSq = rendering::M2_LOD3_DISTANCE * rendering::M2_LOD3_DISTANCE;
|
||||
if (distSq > kLOD3DistSq) continue;
|
||||
|
||||
// Distance-based frame skipping: update distant bones less frequently
|
||||
uint32_t boneInterval = 1;
|
||||
if (distSq > 100.0f * 100.0f) boneInterval = 4;
|
||||
else if (distSq > 50.0f * 50.0f) boneInterval = 2;
|
||||
if (distSq > rendering::M2_BONE_SKIP_DIST_FAR * rendering::M2_BONE_SKIP_DIST_FAR) boneInterval = 4;
|
||||
else if (distSq > rendering::M2_BONE_SKIP_DIST_MID * rendering::M2_BONE_SKIP_DIST_MID) boneInterval = 2;
|
||||
instance.frameSkipCounter++;
|
||||
if ((instance.frameSkipCounter % boneInterval) != 0) continue;
|
||||
|
||||
|
|
@ -616,9 +619,12 @@ void M2Renderer::dispatchCullCompute(VkCommandBuffer cmd, uint32_t frameIndex, c
|
|||
const float* prevM = &prevVP_[0][0];
|
||||
for (int k = 0; k < 16; ++k)
|
||||
maxDiff = std::max(maxDiff, std::abs(curM[k] - prevM[k]));
|
||||
// Threshold: typical small camera motion produces diffs < 0.05.
|
||||
// A fast rotation easily exceeds 0.3. Skip HiZ when diff is large.
|
||||
if (maxDiff > 0.15f) hizSafe = false;
|
||||
// Threshold: typical tracking-camera motion (following a walking
|
||||
// character) produces diffs of 0.05–0.25. A fast rotation or
|
||||
// zoom easily exceeds 0.5. The previous threshold (0.15) caused
|
||||
// the HiZ pass to toggle on/off every other frame during normal
|
||||
// gameplay, which produced global M2 doodad flicker.
|
||||
if (maxDiff > rendering::HIZ_VP_DIFF_THRESHOLD) hizSafe = false;
|
||||
}
|
||||
|
||||
ubo->hizEnabled = hizSafe ? 1u : 0u;
|
||||
|
|
@ -656,11 +662,11 @@ void M2Renderer::dispatchCullCompute(VkCommandBuffer cmd, uint32_t frameIndex, c
|
|||
if (inst.cachedDisableAnimation) {
|
||||
cullRadius = std::max(cullRadius, 3.0f);
|
||||
}
|
||||
float effectiveMaxDistSq = maxRenderDistanceSq * std::max(1.0f, cullRadius / 12.0f);
|
||||
float effectiveMaxDistSq = maxRenderDistanceSq * std::max(1.0f, cullRadius / rendering::M2_CULL_RADIUS_SCALE_DIVISOR);
|
||||
if (inst.cachedDisableAnimation) effectiveMaxDistSq *= 2.6f;
|
||||
if (inst.cachedIsGroundDetail) effectiveMaxDistSq *= 0.9f;
|
||||
|
||||
float paddedRadius = std::max(cullRadius * 1.5f, cullRadius + 3.0f);
|
||||
float paddedRadius = std::max(cullRadius * rendering::M2_PADDED_RADIUS_SCALE, cullRadius + rendering::M2_PADDED_RADIUS_MIN_MARGIN);
|
||||
|
||||
uint32_t flags = 0;
|
||||
if (inst.cachedIsValid) flags |= 1u;
|
||||
|
|
@ -668,7 +674,9 @@ void M2Renderer::dispatchCullCompute(VkCommandBuffer cmd, uint32_t frameIndex, c
|
|||
if (inst.cachedIsInvisibleTrap) flags |= 4u;
|
||||
// Bit 3: previouslyVisible — the shader skips HiZ for objects
|
||||
// that were NOT rendered last frame (no reliable depth data).
|
||||
if (i < prevFrameVisible_.size() && prevFrameVisible_[i])
|
||||
// Hysteresis: treat as "previously visible" unless culled for
|
||||
// 2+ consecutive frames, preventing single-frame false-cull flicker.
|
||||
if (i < prevFrameVisible_.size() && prevFrameVisible_[i] < 2)
|
||||
flags |= 8u;
|
||||
|
||||
input[i].sphere = glm::vec4(inst.position, paddedRadius);
|
||||
|
|
@ -756,15 +764,25 @@ void M2Renderer::render(VkCommandBuffer cmd, VkDescriptorSet perFrameSet, const
|
|||
|
||||
// Snapshot the GPU visibility results into prevFrameVisible_ so the NEXT
|
||||
// frame's compute dispatch can set the per-instance `previouslyVisible`
|
||||
// flag (bit 3). Objects not visible this frame will skip HiZ next frame,
|
||||
// avoiding false culls from stale depth data.
|
||||
// flag (bit 3). We use a hysteresis counter instead of a binary flag to
|
||||
// prevent a 1-frame-on / 1-frame-off oscillation: an object must be HiZ-
|
||||
// culled for 2 consecutive frames before we stop considering it
|
||||
// "previously visible". This eliminates doodad flicker near characters
|
||||
// caused by stale depth data from character movement.
|
||||
if (gpuCullAvailable) {
|
||||
prevFrameVisible_.resize(numInstances);
|
||||
for (uint32_t i = 0; i < numInstances; ++i)
|
||||
prevFrameVisible_[i] = visibility[i] ? 1u : 0u;
|
||||
prevFrameVisible_.resize(numInstances, 0);
|
||||
for (uint32_t i = 0; i < numInstances; ++i) {
|
||||
if (visibility[i]) {
|
||||
// Visible this frame — reset cull counter.
|
||||
prevFrameVisible_[i] = 0;
|
||||
} else {
|
||||
// Culled this frame — increment counter (cap at 3 to avoid overflow).
|
||||
prevFrameVisible_[i] = std::min<uint8_t>(prevFrameVisible_[i] + 1, 3);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// No GPU cull data — conservatively mark all as visible
|
||||
prevFrameVisible_.assign(static_cast<size_t>(instances.size()), 1u);
|
||||
// No GPU cull data — conservatively mark all as visible (counter = 0).
|
||||
prevFrameVisible_.assign(static_cast<size_t>(instances.size()), 0);
|
||||
}
|
||||
|
||||
// If GPU culling was not dispatched, fallback: compute distances on CPU
|
||||
|
|
@ -818,12 +836,12 @@ void M2Renderer::render(VkCommandBuffer cmd, VkDescriptorSet perFrameSet, const
|
|||
float worldRadius = instance.cachedBoundRadius * instance.scale;
|
||||
float cullRadius = worldRadius;
|
||||
if (instance.cachedDisableAnimation) cullRadius = std::max(cullRadius, 3.0f);
|
||||
float effDistSq = maxRenderDistanceSq * std::max(1.0f, cullRadius / 12.0f);
|
||||
float effDistSq = maxRenderDistanceSq * std::max(1.0f, cullRadius / rendering::M2_CULL_RADIUS_SCALE_DIVISOR);
|
||||
if (instance.cachedDisableAnimation) effDistSq *= 2.6f;
|
||||
if (instance.cachedIsGroundDetail) effDistSq *= 0.9f;
|
||||
if (distSqTest > effDistSq) continue;
|
||||
|
||||
float paddedRadius = std::max(cullRadius * 1.5f, cullRadius + 3.0f);
|
||||
float paddedRadius = std::max(cullRadius * rendering::M2_PADDED_RADIUS_SCALE, cullRadius + rendering::M2_PADDED_RADIUS_MIN_MARGIN);
|
||||
if (cullRadius > 0.0f && !frustum.intersectsSphere(instance.position, paddedRadius)) continue;
|
||||
}
|
||||
|
||||
|
|
@ -833,7 +851,7 @@ void M2Renderer::render(VkCommandBuffer cmd, VkDescriptorSet perFrameSet, const
|
|||
float worldRadius = instance.cachedBoundRadius * instance.scale;
|
||||
float cullRadius = worldRadius;
|
||||
if (instance.cachedDisableAnimation) cullRadius = std::max(cullRadius, 3.0f);
|
||||
float effectiveMaxDistSq = maxRenderDistanceSq * std::max(1.0f, cullRadius / 12.0f);
|
||||
float effectiveMaxDistSq = maxRenderDistanceSq * std::max(1.0f, cullRadius / rendering::M2_CULL_RADIUS_SCALE_DIVISOR);
|
||||
if (instance.cachedDisableAnimation) effectiveMaxDistSq *= 2.6f;
|
||||
if (instance.cachedIsGroundDetail) effectiveMaxDistSq *= 0.9f;
|
||||
|
||||
|
|
|
|||
|
|
@ -531,19 +531,24 @@ bool Renderer::initialize(core::Window* win) {
|
|||
lensFlare = nullptr;
|
||||
|
||||
weather = std::make_unique<Weather>();
|
||||
weather->initialize(vkCtx, perFrameSetLayout);
|
||||
if (!weather->initialize(vkCtx, perFrameSetLayout))
|
||||
LOG_WARNING("Weather effect initialization failed (non-fatal)");
|
||||
|
||||
lightning = std::make_unique<Lightning>();
|
||||
lightning->initialize(vkCtx, perFrameSetLayout);
|
||||
if (!lightning->initialize(vkCtx, perFrameSetLayout))
|
||||
LOG_WARNING("Lightning effect initialization failed (non-fatal)");
|
||||
|
||||
swimEffects = std::make_unique<SwimEffects>();
|
||||
swimEffects->initialize(vkCtx, perFrameSetLayout);
|
||||
if (!swimEffects->initialize(vkCtx, perFrameSetLayout))
|
||||
LOG_WARNING("Swim effect initialization failed (non-fatal)");
|
||||
|
||||
mountDust = std::make_unique<MountDust>();
|
||||
mountDust->initialize(vkCtx, perFrameSetLayout);
|
||||
if (!mountDust->initialize(vkCtx, perFrameSetLayout))
|
||||
LOG_WARNING("Mount dust effect initialization failed (non-fatal)");
|
||||
|
||||
chargeEffect = std::make_unique<ChargeEffect>();
|
||||
chargeEffect->initialize(vkCtx, perFrameSetLayout);
|
||||
if (!chargeEffect->initialize(vkCtx, perFrameSetLayout))
|
||||
LOG_WARNING("Charge effect initialization failed (non-fatal)");
|
||||
|
||||
levelUpEffect = std::make_unique<LevelUpEffect>();
|
||||
|
||||
|
|
@ -1451,7 +1456,8 @@ void Renderer::runDeferredWorldInitStep(float deltaTime) {
|
|||
if (audioCoordinator_->getMovementSoundManager()) audioCoordinator_->getMovementSoundManager()->initialize(cachedAssetManager);
|
||||
break;
|
||||
case 5:
|
||||
if (questMarkerRenderer) questMarkerRenderer->initialize(vkCtx, perFrameSetLayout, cachedAssetManager);
|
||||
if (questMarkerRenderer && !questMarkerRenderer->initialize(vkCtx, perFrameSetLayout, cachedAssetManager))
|
||||
LOG_WARNING("Quest marker renderer re-init failed (non-fatal)");
|
||||
break;
|
||||
default:
|
||||
deferredWorldInitPending_ = false;
|
||||
|
|
@ -1930,7 +1936,8 @@ bool Renderer::initializeRenderers(pipeline::AssetManager* assetManager, const s
|
|||
// Create M2, WMO, and Character renderers
|
||||
if (!m2Renderer) {
|
||||
m2Renderer = std::make_unique<M2Renderer>();
|
||||
m2Renderer->initialize(vkCtx, perFrameSetLayout, assetManager);
|
||||
if (!m2Renderer->initialize(vkCtx, perFrameSetLayout, assetManager))
|
||||
LOG_ERROR("M2Renderer initialization failed");
|
||||
if (swimEffects) {
|
||||
swimEffects->setM2Renderer(m2Renderer.get());
|
||||
}
|
||||
|
|
@ -1959,21 +1966,26 @@ bool Renderer::initializeRenderers(pipeline::AssetManager* assetManager, const s
|
|||
}
|
||||
if (!wmoRenderer) {
|
||||
wmoRenderer = std::make_unique<WMORenderer>();
|
||||
wmoRenderer->initialize(vkCtx, perFrameSetLayout, assetManager);
|
||||
if (!wmoRenderer->initialize(vkCtx, perFrameSetLayout, assetManager))
|
||||
LOG_ERROR("WMORenderer initialization failed");
|
||||
if (shadowRenderPass != VK_NULL_HANDLE) {
|
||||
wmoRenderer->initializeShadow(shadowRenderPass);
|
||||
if (!wmoRenderer->initializeShadow(shadowRenderPass))
|
||||
LOG_WARNING("WMO shadow pipeline initialization failed");
|
||||
}
|
||||
}
|
||||
|
||||
// Initialize shadow pipelines for M2 if not yet done
|
||||
if (m2Renderer && shadowRenderPass != VK_NULL_HANDLE && !m2Renderer->hasShadowPipeline()) {
|
||||
m2Renderer->initializeShadow(shadowRenderPass);
|
||||
if (!m2Renderer->initializeShadow(shadowRenderPass))
|
||||
LOG_WARNING("M2 shadow pipeline initialization failed");
|
||||
}
|
||||
if (!characterRenderer) {
|
||||
characterRenderer = std::make_unique<CharacterRenderer>();
|
||||
characterRenderer->initialize(vkCtx, perFrameSetLayout, assetManager);
|
||||
if (!characterRenderer->initialize(vkCtx, perFrameSetLayout, assetManager))
|
||||
LOG_ERROR("CharacterRenderer initialization failed");
|
||||
if (shadowRenderPass != VK_NULL_HANDLE) {
|
||||
characterRenderer->initializeShadow(shadowRenderPass);
|
||||
if (!characterRenderer->initializeShadow(shadowRenderPass))
|
||||
LOG_WARNING("Character shadow pipeline initialization failed");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -2068,7 +2080,8 @@ bool Renderer::initializeRenderers(pipeline::AssetManager* assetManager, const s
|
|||
audioCoordinator_->getMovementSoundManager()->initialize(assetManager);
|
||||
}
|
||||
if (questMarkerRenderer) {
|
||||
questMarkerRenderer->initialize(vkCtx, perFrameSetLayout, assetManager);
|
||||
if (!questMarkerRenderer->initialize(vkCtx, perFrameSetLayout, assetManager))
|
||||
LOG_WARNING("Quest marker renderer initialization failed (non-fatal)");
|
||||
}
|
||||
|
||||
if (envFlagEnabled("WOWEE_PREWARM_ZONE_MUSIC", false)) {
|
||||
|
|
@ -2261,7 +2274,8 @@ bool Renderer::loadTerrainArea(const std::string& mapName, int centerX, int cent
|
|||
audioCoordinator_->getMovementSoundManager()->initialize(cachedAssetManager);
|
||||
}
|
||||
if (questMarkerRenderer && cachedAssetManager) {
|
||||
questMarkerRenderer->initialize(vkCtx, perFrameSetLayout, cachedAssetManager);
|
||||
if (!questMarkerRenderer->initialize(vkCtx, perFrameSetLayout, cachedAssetManager))
|
||||
LOG_WARNING("Quest marker renderer re-init failed (non-fatal)");
|
||||
}
|
||||
} else {
|
||||
deferredWorldInitPending_ = true;
|
||||
|
|
|
|||
|
|
@ -868,7 +868,8 @@ bool TerrainManager::advanceFinalization(FinalizingTile& ft) {
|
|||
|
||||
// Ensure M2 renderer has asset manager
|
||||
if (m2Renderer && assetManager) {
|
||||
m2Renderer->initialize(nullptr, VK_NULL_HANDLE, assetManager);
|
||||
if (!m2Renderer->initialize(nullptr, VK_NULL_HANDLE, assetManager))
|
||||
LOG_WARNING("M2Renderer terrain re-init failed");
|
||||
}
|
||||
|
||||
ft.phase = FinalizationPhase::M2_MODELS;
|
||||
|
|
@ -952,7 +953,8 @@ bool TerrainManager::advanceFinalization(FinalizingTile& ft) {
|
|||
case FinalizationPhase::WMO_MODELS: {
|
||||
// Upload multiple WMO models per call (batched GPU uploads)
|
||||
if (wmoRenderer && assetManager) {
|
||||
wmoRenderer->initialize(nullptr, VK_NULL_HANDLE, assetManager);
|
||||
if (!wmoRenderer->initialize(nullptr, VK_NULL_HANDLE, assetManager))
|
||||
LOG_WARNING("WMORenderer terrain re-init failed");
|
||||
// Set pre-decoded BLP cache and defer normal maps during streaming
|
||||
wmoRenderer->setPredecodedBLPCache(&pending->preloadedWMOTextures);
|
||||
wmoRenderer->setDeferNormalMaps(true);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue