Fix NPC missing body parts by using baked textures as-is

Baked NPC textures already include complete appearance (skin, features,
armor). Equipment component textures are designed for player characters
with different UV layout and were causing body parts to disappear.
This commit is contained in:
Kelsi 2026-02-05 23:15:57 -08:00
parent 10ceb2b3a8
commit 9e3d12c0dc
2 changed files with 32 additions and 8 deletions

View file

@ -1790,17 +1790,17 @@ void Application::spawnOnlineCreature(uint64_t guid, uint32_t displayId, float x
" hands=", extra.equipDisplayId[8], " tabard=", extra.equipDisplayId[9],
" cape=", extra.equipDisplayId[10]);
// Use baked texture directly (256x256 - equipment overlays not compatible)
// Baked NPC textures already include the complete body skin with face
// Use baked texture as-is (baked textures already include full NPC appearance)
// Equipment component textures are only for player characters with CharComponentTextureSections UV layout
if (!extra.bakeName.empty()) {
std::string bakePath = "Textures\\BakedNpcTextures\\" + extra.bakeName;
GLuint bakeTex = charRenderer->loadTexture(bakePath);
if (bakeTex != 0) {
// Apply to type-1 texture slot (body skin)
GLuint finalTex = charRenderer->loadTexture(bakePath);
if (finalTex != 0) {
for (size_t ti = 0; ti < model.textures.size(); ti++) {
if (model.textures[ti].type == 1) {
charRenderer->setModelTexture(modelId, static_cast<uint32_t>(ti), bakeTex);
LOG_DEBUG("Applied baked NPC texture: ", bakePath, " to slot ", ti);
charRenderer->setModelTexture(modelId, static_cast<uint32_t>(ti), finalTex);
LOG_DEBUG("Applied baked NPC texture to slot ", ti, ": ", bakePath);
hasHumanoidTexture = true;
}
}

View file

@ -580,10 +580,34 @@ GLuint CharacterRenderer::compositeWithRegions(const std::string& basePath,
return whiteTexture;
}
std::vector<uint8_t> composite = base.data;
std::vector<uint8_t> composite;
int width = base.width;
int height = base.height;
// If base texture is 256x256 (e.g., baked NPC texture), upscale to 512x512
// so equipment regions can be composited at correct coordinates
if (width == 256 && height == 256 && !regionLayers.empty()) {
width = 512;
height = 512;
composite.resize(width * height * 4);
// Simple 2x nearest-neighbor upscale
for (int y = 0; y < 512; y++) {
for (int x = 0; x < 512; x++) {
int srcX = x / 2;
int srcY = y / 2;
int srcIdx = (srcY * 256 + srcX) * 4;
int dstIdx = (y * 512 + x) * 4;
composite[dstIdx + 0] = base.data[srcIdx + 0];
composite[dstIdx + 1] = base.data[srcIdx + 1];
composite[dstIdx + 2] = base.data[srcIdx + 2];
composite[dstIdx + 3] = base.data[srcIdx + 3];
}
}
core::Logger::getInstance().info("compositeWithRegions: upscaled 256x256 to 512x512");
} else {
composite = base.data;
}
// Blend underwear overlays (same logic as compositeTextures)
for (const auto& ul : baseLayers) {
if (ul.empty()) continue;