diff --git a/src/core/application.cpp b/src/core/application.cpp index 99d47822..ac45084e 100644 --- a/src/core/application.cpp +++ b/src/core/application.cpp @@ -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(ti), bakeTex); - LOG_DEBUG("Applied baked NPC texture: ", bakePath, " to slot ", ti); + charRenderer->setModelTexture(modelId, static_cast(ti), finalTex); + LOG_DEBUG("Applied baked NPC texture to slot ", ti, ": ", bakePath); hasHumanoidTexture = true; } } diff --git a/src/rendering/character_renderer.cpp b/src/rendering/character_renderer.cpp index 05cc2aa4..472ebf62 100644 --- a/src/rendering/character_renderer.cpp +++ b/src/rendering/character_renderer.cpp @@ -580,10 +580,34 @@ GLuint CharacterRenderer::compositeWithRegions(const std::string& basePath, return whiteTexture; } - std::vector composite = base.data; + std::vector 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;