From 3fdc41843bd47cbed831e69c9529e8a5b41d5c3f Mon Sep 17 00:00:00 2001 From: Par Winzell Date: Sun, 25 Feb 2018 18:33:11 -0800 Subject: [PATCH] Support occlusion texture all the way. By oversight we had not included occlusionTexture in the core MaterialData. While we're at it, bake occlusion into the red channel of the merged metallic/roughness texture. --- src/Raw2Gltf.cpp | 43 +++++++++++++++++++++++++++++---------- src/glTF/MaterialData.cpp | 5 +++++ src/glTF/MaterialData.h | 2 ++ 3 files changed, 39 insertions(+), 11 deletions(-) diff --git a/src/Raw2Gltf.cpp b/src/Raw2Gltf.cpp index a440809..1852756 100644 --- a/src/Raw2Gltf.cpp +++ b/src/Raw2Gltf.cpp @@ -635,8 +635,9 @@ ModelData *Raw2Gltf( return (material.textures[usage] >= 0) ? getSimpleTexture(material.textures[usage], "simple") : nullptr; }; - TextureData *normalTexture = simpleTex(RAW_TEXTURE_USAGE_NORMAL).get(); + TextureData *normalTexture = simpleTex(RAW_TEXTURE_USAGE_NORMAL).get(); TextureData *emissiveTexture = simpleTex(RAW_TEXTURE_USAGE_EMISSIVE).get(); + TextureData *occlusionTexture = nullptr; // acquire derived texture of two RawTextureUsage as *TextData, or nullptr if neither exists auto merge2Tex = [&]( @@ -651,10 +652,24 @@ ModelData *Raw2Gltf( combine, tag, outputHasAlpha); }; + // acquire derived texture of two RawTextureUsage as *TextData, or nullptr if neither exists + auto merge3Tex = [&]( + const std::string tag, + RawTextureUsage u1, + RawTextureUsage u2, + RawTextureUsage u3, + const pixel_merger &combine, + bool outputHasAlpha + ) -> std::shared_ptr { + return getDerivedTexture( + { material.textures[u1], material.textures[u2], material.textures[u3] }, + combine, tag, outputHasAlpha); + }; + std::shared_ptr pbrMetRough; if (options.usePBRMetRough) { // albedo is a basic texture, no merging needed - std::shared_ptr baseColorTex, metRoughTex; + std::shared_ptr baseColorTex, aoMetRoughTex; Vec4f diffuseFactor; float metallic, roughness; @@ -667,9 +682,11 @@ ModelData *Raw2Gltf( */ RawMetRoughMatProps *props = (RawMetRoughMatProps *) material.info.get(); // merge metallic into the blue channel and roughness into the green, of a new combinatory texture - metRoughTex = merge2Tex("met_rough", - RAW_TEXTURE_USAGE_METALLIC, RAW_TEXTURE_USAGE_ROUGHNESS, - [&](const std::vector pixels) -> pixel { return { 0, (*pixels[1])[0], (*pixels[0])[0], 0 }; }, + aoMetRoughTex = merge3Tex("ao_met_rough", + RAW_TEXTURE_USAGE_OCCLUSION, RAW_TEXTURE_USAGE_METALLIC, RAW_TEXTURE_USAGE_ROUGHNESS, + [&](const std::vector pixels) -> pixel { + return { (*pixels[0])[0], (*pixels[2])[0], (*pixels[1])[0], 0 }; + }, false); baseColorTex = simpleTex(RAW_TEXTURE_USAGE_ALBEDO); diffuseFactor = props->diffuseFactor; @@ -677,6 +694,10 @@ ModelData *Raw2Gltf( roughness = props->roughness; emissiveFactor = props->emissiveFactor; emissiveIntensity = props->emissiveIntensity; + // add the occlusion texture only if actual occlusion pixels exist in the aoNetRough texture. + if (material.textures[RAW_TEXTURE_USAGE_OCCLUSION] >= 0) { + occlusionTexture = aoMetRoughTex.get(); + } } else { /** * Traditional FBX Material -> PBR Met/Rough glTF. @@ -697,10 +718,9 @@ ModelData *Raw2Gltf( emissiveFactor = props->emissiveFactor; emissiveIntensity = 1.0f; } - pbrMetRough.reset(new PBRMetallicRoughness(baseColorTex.get(), metRoughTex.get(), diffuseFactor, metallic, roughness)); + pbrMetRough.reset(new PBRMetallicRoughness(baseColorTex.get(), aoMetRoughTex.get(), diffuseFactor, metallic, roughness)); } - std::shared_ptr khrCmnUnlitMat; if (options.useKHRMatUnlit) { normalTexture = nullptr; @@ -725,13 +745,14 @@ ModelData *Raw2Gltf( khrCmnUnlitMat.reset(new KHRCmnUnlitMaterial()); } + if (!occlusionTexture) { + occlusionTexture = simpleTex(RAW_TEXTURE_USAGE_OCCLUSION).get(); + } std::shared_ptr mData = gltf->materials.hold( new MaterialData( - material.name, isTransparent, - normalTexture, emissiveTexture, - emissiveFactor * emissiveIntensity, - khrCmnUnlitMat, pbrMetRough)); + material.name, isTransparent, normalTexture, occlusionTexture, emissiveTexture, + emissiveFactor * emissiveIntensity, khrCmnUnlitMat, pbrMetRough)); materialsByName[materialHash(material)] = mData; } diff --git a/src/glTF/MaterialData.cpp b/src/glTF/MaterialData.cpp index 0360c33..3fbad6e 100644 --- a/src/glTF/MaterialData.cpp +++ b/src/glTF/MaterialData.cpp @@ -80,6 +80,7 @@ void to_json(json &j, const PBRMetallicRoughness &d) MaterialData::MaterialData( std::string name, bool isTransparent, const TextureData *normalTexture, + const TextureData *occlusionTexture, const TextureData *emissiveTexture, const Vec3f & emissiveFactor, std::shared_ptr const khrCmnConstantMaterial, std::shared_ptr const pbrMetallicRoughness) @@ -87,6 +88,7 @@ MaterialData::MaterialData( name(std::move(name)), isTransparent(isTransparent), normalTexture(Tex::ref(normalTexture)), + occlusionTexture(Tex::ref(occlusionTexture)), emissiveTexture(Tex::ref(emissiveTexture)), emissiveFactor(clamp(emissiveFactor)), khrCmnConstantMaterial(khrCmnConstantMaterial), @@ -102,6 +104,9 @@ json MaterialData::serialize() const if (normalTexture != nullptr) { result["normalTexture"] = *normalTexture; } + if (occlusionTexture != nullptr) { + result["occlusionTexture"] = *occlusionTexture; + } if (emissiveTexture != nullptr) { result["emissiveTexture"] = *emissiveTexture; } diff --git a/src/glTF/MaterialData.h b/src/glTF/MaterialData.h index eee5150..4ff4f1a 100644 --- a/src/glTF/MaterialData.h +++ b/src/glTF/MaterialData.h @@ -45,6 +45,7 @@ struct MaterialData : Holdable { MaterialData( std::string name, bool isTransparent, const TextureData *normalTexture, + const TextureData *occlusionTexture, const TextureData *emissiveTexture, const Vec3f &emissiveFactor, std::shared_ptr const khrCmnConstantMaterial, std::shared_ptr const pbrMetallicRoughness); @@ -54,6 +55,7 @@ struct MaterialData : Holdable const std::string name; const bool isTransparent; const std::unique_ptr normalTexture; + const std::unique_ptr occlusionTexture; const std::unique_ptr emissiveTexture; const Vec3f emissiveFactor;