From 20f6ad494cacb868c231152c47b75813c6b81b9e Mon Sep 17 00:00:00 2001 From: hydrogendeuteride Date: Fri, 5 Dec 2025 16:54:00 +0900 Subject: [PATCH] FIX: AO/Emissive loading fix --- shaders/gbuffer.frag | 8 +++++++- shaders/mesh.frag | 8 +++++++- src/core/assets/manager.cpp | 28 ++++++++++++++++++++++------ src/render/passes/geometry.cpp | 6 +++--- src/scene/vk_loader.cpp | 27 +++++++++++++++++++++++++-- 5 files changed, 64 insertions(+), 13 deletions(-) diff --git a/shaders/gbuffer.frag b/shaders/gbuffer.frag index c82a4a1..2dcf9a8 100644 --- a/shaders/gbuffer.frag +++ b/shaders/gbuffer.frag @@ -68,9 +68,15 @@ void main() { outNorm = vec4(Nw, roughness); outAlbedo = vec4(albedo, metallic); // Extra G-buffer: x = AO, yzw = emissive + // extra[0].y = AO strength, extra[0].z = hasAO flag (1 = use AO texture) + float hasAO = materialData.extra[0].z; float aoStrength = clamp(materialData.extra[0].y, 0.0, 1.0); float aoTex = texture(occlusionTex, inUV).r; - float ao = 1.0 - aoStrength + aoStrength * aoTex; + float ao = 1.0; + if (hasAO > 0.5) + { + ao = 1.0 - aoStrength + aoStrength * aoTex; + } vec3 emissiveFactor = materialData.extra[1].rgb; vec3 emissiveTex = texture(emissiveTex, inUV).rgb; vec3 emissive = emissiveTex * emissiveFactor; diff --git a/shaders/mesh.frag b/shaders/mesh.frag index 707d4bc..511715d 100644 --- a/shaders/mesh.frag +++ b/shaders/mesh.frag @@ -70,9 +70,15 @@ void main() vec3 diffIBL = (1.0 - metallic) * albedo * sh_eval_irradiance(N); // Ambient occlusion from texture + strength (indirect only) + // extra[0].y = AO strength, extra[0].z = hasAO flag (1 = use AO texture) + float hasAO = materialData.extra[0].z; float aoStrength = clamp(materialData.extra[0].y, 0.0, 1.0); float aoTex = texture(occlusionTex, inUV).r; - float ao = 1.0 - aoStrength + aoStrength * aoTex; + float ao = 1.0; + if (hasAO > 0.5) + { + ao = 1.0 - aoStrength + aoStrength * aoTex; + } // Emissive from texture and factor vec3 emissiveFactor = materialData.extra[1].rgb; diff --git a/src/core/assets/manager.cpp b/src/core/assets/manager.cpp index 3d67e3b..06ab40b 100644 --- a/src/core/assets/manager.cpp +++ b/src/core/assets/manager.cpp @@ -220,8 +220,28 @@ std::shared_ptr AssetManager::createMesh(const MeshCreateInfo &info) { const auto &opt = info.material.options; - // Fallbacks are bound now; real textures will patch in via TextureCache - AllocatedBuffer matBuffer = createMaterialBufferWithConstants(opt.constants); + GLTFMetallic_Roughness::MaterialConstants constants = opt.constants; + + if (!opt.occlusionPath.empty()) + { + if (constants.extra[0].y == 0.0f && constants.extra[0].z == 0.0f) + { + constants.extra[0].y = 1.0f; // AO strength + constants.extra[0].z = 1.0f; // hasAO flag + } + } + + if (!opt.emissivePath.empty()) + { + if (constants.extra[1].x == 0.0f && + constants.extra[1].y == 0.0f && + constants.extra[1].z == 0.0f) + { + constants.extra[1] = glm::vec4(1.0f, 1.0f, 1.0f, constants.extra[1].w); + } + } + + AllocatedBuffer matBuffer = createMaterialBufferWithConstants(constants); GLTFMetallic_Roughness::MaterialResources res{}; res.colorImage = _engine->_errorCheckerboardImage; @@ -519,10 +539,6 @@ AllocatedBuffer AssetManager::createMaterialBufferWithConstants( { matConstants->extra[0].x = 1.0f; // normal scale default } - if (matConstants->extra[0].y == 0.0f) - { - matConstants->extra[0].y = 1.0f; - } // Ensure writes are visible on non-coherent memory vmaFlushAllocation(_engine->_deviceManager->allocator(), matBuffer.allocation, 0, sizeof(GLTFMetallic_Roughness::MaterialConstants)); diff --git a/src/render/passes/geometry.cpp b/src/render/passes/geometry.cpp index bf4efc5..a0ec752 100644 --- a/src/render/passes/geometry.cpp +++ b/src/render/passes/geometry.cpp @@ -91,12 +91,12 @@ void GeometryPass::register_graph(RenderGraph *graph, builder.write_color(gbufferPosition, true, clear); builder.write_color(gbufferNormal, true, clear); builder.write_color(gbufferAlbedo, true, clear); - VkClearValue clearExtra{}; - clearExtra.color = {{1.f, 0.f, 0.f, 0.f}}; // AO=1, emissive=0 - builder.write_color(gbufferExtra, true, clearExtra); VkClearValue clearID{}; clearID.color.uint32[0] = 0u; builder.write_color(idHandle, true, clearID); + VkClearValue clearExtra{}; + clearExtra.color = {{1.f, 0.f, 0.f, 0.f}}; // AO=1, emissive=0 + builder.write_color(gbufferExtra, true, clearExtra); // Reverse-Z: clear depth to 0.0 VkClearValue depthClear{}; diff --git a/src/scene/vk_loader.cpp b/src/scene/vk_loader.cpp index 5fc450b..108ea84 100644 --- a/src/scene/vk_loader.cpp +++ b/src/scene/vk_loader.cpp @@ -389,12 +389,35 @@ std::optional > loadGltf(VulkanEngine *engine, constants.metal_rough_factors.y = mat.pbrData.roughnessFactor; // extra[0].x: normalScale (default 1.0) constants.extra[0].x = 1.0f; - // extra[0].y: occlusionStrength (0..1, default 1.0) - constants.extra[0].y = mat.occlusionTexture.has_value() ? mat.occlusionTexture->strength : 1.0f; + // extra[0].y: occlusionStrength (0..1) + // extra[0].z: hasAO flag (1.0 if an occlusionTexture is present, 0.0 otherwise) + if (mat.occlusionTexture.has_value()) + { + constants.extra[0].y = mat.occlusionTexture->strength; + constants.extra[0].z = 1.0f; + } + else + { + constants.extra[0].y = 0.0f; + constants.extra[0].z = 0.0f; + } // extra[1].rgb: emissiveFactor constants.extra[1].x = mat.emissiveFactor[0]; constants.extra[1].y = mat.emissiveFactor[1]; constants.extra[1].z = mat.emissiveFactor[2]; + // If an emissive texture is present but the factor is left at 0, + // default to white so the texture is visible (common authoring pattern). + if (mat.emissiveTexture.has_value()) + { + if (constants.extra[1].x == 0.0f && + constants.extra[1].y == 0.0f && + constants.extra[1].z == 0.0f) + { + constants.extra[1].x = 1.0f; + constants.extra[1].y = 1.0f; + constants.extra[1].z = 1.0f; + } + } // extra[2].x: alphaCutoff for MASK materials (>0 enables alpha test) constants.extra[2].x = 0.0f; if (mat.alphaMode == fastgltf::AlphaMode::Mask)