From 6262255ee1dd731f10400d3e2ba7176febf87b62 Mon Sep 17 00:00:00 2001 From: seungho baek Date: Thu, 1 Dec 2022 14:51:41 +0900 Subject: [PATCH] Fix Scene3d::Loader bugs - Make Renderer translucent when AlphaMode is Blend - Use discard for AlphaMode.Mask in shader - Fixed ConvertSampler bug. - Fixed crash when there isn't "scene" property in glTF - Fixed wrong loading of buffer when the bufferView uses stride. - Returns MeshDefinition::Blob::GetBufferSize() only mLength This is because every use case of this method is to set real buffer size without considering stride. - Fix texture order of Specular and Specular color. Change-Id: I244b366a9d4c36ad478ea8908725187ffd3277f6 Signed-off-by: seungho baek --- automated-tests/resources/AnimatedCubeStride.gltf | 84 ++++++++++++++++++++++ .../src/dali-scene3d/utc-Dali-Gltf2Loader.cpp | 33 +++++++++ .../shaders/default-physically-based-shader.frag | 27 +++---- dali-scene3d/public-api/loader/gltf2-loader.cpp | 36 ++++++---- .../public-api/loader/material-definition.h | 3 + dali-scene3d/public-api/loader/mesh-definition.cpp | 26 ++++--- dali-scene3d/public-api/loader/node-definition.cpp | 16 +---- .../loader/shader-definition-factory.cpp | 32 ++++----- 8 files changed, 193 insertions(+), 64 deletions(-) create mode 100644 automated-tests/resources/AnimatedCubeStride.gltf diff --git a/automated-tests/resources/AnimatedCubeStride.gltf b/automated-tests/resources/AnimatedCubeStride.gltf new file mode 100644 index 0000000..d44ac0c --- /dev/null +++ b/automated-tests/resources/AnimatedCubeStride.gltf @@ -0,0 +1,84 @@ +{ + "accessors" : [ + { + "bufferView" : 0, + "byteOffset" : 0, + "componentType" : 5126, + "count" : 36, + "max" : [ + 1.000000, + 1.000000, + 1.000001 + ], + "min" : [ + -1.000000, + -1.000000, + -1.000000 + ], + "type" : "VEC3" + } + ], + "asset" : { + "generator" : "VKTS glTF 2.0 exporter", + "version" : "2.0" + }, + "bufferViews" : [ + { + "buffer" : 0, + "byteLength" : 864, + "byteOffset" : 132, + "target" : 34962, + "byteStride": 24 + } + ], + "buffers" : [ + { + "byteLength" : 1860, + "uri" : "AnimatedCube.bin" + } + ], + "materials" : [ + { + "name" : "AnimatedCube", + "pbrMetallicRoughness" : { + } + }, + { + "name" : "AnimatedCube2", + "pbrMetallicRoughness" : { + } + } + ], + "meshes" : [ + { + "name" : "AnimatedCube", + "primitives" : [ + { + "attributes" : { + "POSITION" : 0 + } + } + ] + } + ], + "nodes" : [ + { + "mesh" : 0, + "name" : "AnimatedCube", + "rotation" : [ + 0.000000, + -1.000000, + 0.000000, + 0.000000 + ] + } + ], + "scene" : 0, + "scenes" : [ + { + "nodes" : [ + 0 + ] + } + ] +} \ No newline at end of file diff --git a/automated-tests/src/dali-scene3d/utc-Dali-Gltf2Loader.cpp b/automated-tests/src/dali-scene3d/utc-Dali-Gltf2Loader.cpp index eb19c4d..369f19d 100644 --- a/automated-tests/src/dali-scene3d/utc-Dali-Gltf2Loader.cpp +++ b/automated-tests/src/dali-scene3d/utc-Dali-Gltf2Loader.cpp @@ -213,6 +213,8 @@ int UtcDaliGltfLoaderSuccess1(void) false, true, false, + true, + true, { {MaterialDefinition::ALBEDO, {"AnimatedCube_BaseColor.png", @@ -263,6 +265,8 @@ int UtcDaliGltfLoaderSuccess1(void) true, true, false, + true, + false, { {MaterialDefinition::ALBEDO, {"AnimatedCube_BaseColor.png", @@ -313,6 +317,8 @@ int UtcDaliGltfLoaderSuccess1(void) DALI_TEST_EQUAL(md.mNeedAlbedoTexture, m.mNeedAlbedoTexture); DALI_TEST_EQUAL(md.mNeedMetallicRoughnessTexture, m.mNeedMetallicRoughnessTexture); DALI_TEST_EQUAL(md.mNeedNormalTexture, m.mNeedNormalTexture); + DALI_TEST_EQUAL(md.mIsOpaque, m.mIsOpaque); + DALI_TEST_EQUAL(md.mIsMask, m.mIsMask); DALI_TEST_EQUAL(md.mTextureStages.size(), m.mTextureStages.size()); auto iTexture = md.mTextureStages.begin(); @@ -399,6 +405,33 @@ int UtcDaliGltfLoaderSuccess1(void) END_TEST; } +int UtcDaliGltfLoaderSuccess2(void) +{ + Context ctx; + ShaderDefinitionFactory sdf; + sdf.SetResources(ctx.resources); + + LoadGltfScene(TEST_RESOURCE_DIR "/AnimatedCubeStride.gltf", sdf, ctx.loadResult); + + DALI_TEST_EQUAL(1u, ctx.scene.GetRoots().size()); + DALI_TEST_EQUAL(1u, ctx.scene.GetNodeCount()); + + TestApplication app; + + Customization::Choices choices; + for(auto iRoot : ctx.scene.GetRoots()) + { + auto resourceRefs = ctx.resources.CreateRefCounter(); + ctx.scene.CountResourceRefs(iRoot, choices, resourceRefs); + ctx.resources.LoadResources(resourceRefs, ctx.pathProvider); + } + + DALI_TEST_EQUAL(true, ctx.resources.mMeshes[0u].first.mPositions.IsDefined()); + DALI_TEST_EQUAL(432, ctx.resources.mMeshes[0u].first.mPositions.mBlob.mLength); + + END_TEST; +} + int UtcDaliGltfLoaderSuccessShort(void) { TestApplication app; diff --git a/dali-scene3d/internal/graphics/shaders/default-physically-based-shader.frag b/dali-scene3d/internal/graphics/shaders/default-physically-based-shader.frag index 8c9e7ea..bca3ba0 100644 --- a/dali-scene3d/internal/graphics/shaders/default-physically-based-shader.frag +++ b/dali-scene3d/internal/graphics/shaders/default-physically-based-shader.frag @@ -55,15 +55,6 @@ uniform sampler2D sAlbedoMetal; uniform sampler2D sNormalRoughness; #endif -uniform float uSpecularFactor; -uniform vec3 uSpecularColorFactor; -#ifdef MATERIAL_SPECULAR_TEXTURE -uniform sampler2D sSpecular; -#endif -#ifdef MATERIAL_SPECULAR_COLOR_TEXTURE -uniform sampler2D sSpecularColor; -#endif - #ifdef OCCLUSION uniform sampler2D sOcclusion; uniform float uOcclusionStrength; @@ -74,6 +65,15 @@ uniform sampler2D sEmissive; uniform vec3 uEmissiveFactor; #endif +uniform float uSpecularFactor; +uniform vec3 uSpecularColorFactor; +#ifdef MATERIAL_SPECULAR_TEXTURE +uniform sampler2D sSpecular; +#endif +#ifdef MATERIAL_SPECULAR_COLOR_TEXTURE +uniform sampler2D sSpecularColor; +#endif + //// For IBL uniform sampler2D sbrdfLUT; uniform samplerCube sDiffuseEnvSampler; @@ -146,12 +146,15 @@ void main() #endif // THREE_TEX // The value of uOpaque and uMask can be 0.0 or 1.0. + // If uMask is 1.0, a Pixel that has bigger alpha than uAlphaThreashold becomes fully opaque, + // and, a pixel that has smaller alpha than uAlphaThreashold becomes fully transparent. // If uOpaque is 1.0, alpha value of final color is 1.0; - // If uOpaque is 0.0 and uMask is 1.0, alpha value of final color is 0.0 when input alpha is lower than uAlphaThreshold or - // 1.0 when input alpha is larger than uAlphaThreshold. // https://www.khronos.org/registry/glTF/specs/2.0/glTF-2.0.html#_material_alphamode + if(uMask > 0.5 && baseColor.a < uAlphaThreshold) + { + discard; + } baseColor.a = mix(baseColor.a, 1.0, uOpaque); - baseColor.a = min(mix(baseColor.a, floor(baseColor.a - uAlphaThreshold + 1.0), uMask), 1.0); metallic = clamp(metallic, 0.0, 1.0); // Roughness is authored as perceptual roughness; as is convention, diff --git a/dali-scene3d/public-api/loader/gltf2-loader.cpp b/dali-scene3d/public-api/loader/gltf2-loader.cpp index 75d7ad0..15f207a 100644 --- a/dali-scene3d/public-api/loader/gltf2-loader.cpp +++ b/dali-scene3d/public-api/loader/gltf2-loader.cpp @@ -425,7 +425,10 @@ SamplerFlags::Type ConvertSampler(const gt::Ref& s) { if(s) { - return (s->mMinFilter < gt::Filter::NEAREST_MIPMAP_NEAREST) ? (s->mMinFilter - gt::Filter::NEAREST) : ((s->mMinFilter - gt::Filter::NEAREST_MIPMAP_NEAREST) + 2) | ((s->mMagFilter - gt::Filter::NEAREST) << SamplerFlags::FILTER_MAG_SHIFT) | (ConvertWrapMode(s->mWrapS) << SamplerFlags::WRAP_S_SHIFT) | (ConvertWrapMode(s->mWrapT) << SamplerFlags::WRAP_T_SHIFT); + return ((s->mMinFilter < gt::Filter::NEAREST_MIPMAP_NEAREST) ? (s->mMinFilter - gt::Filter::NEAREST) : ((s->mMinFilter - gt::Filter::NEAREST_MIPMAP_NEAREST) + 2)) | + ((s->mMagFilter - gt::Filter::NEAREST) << SamplerFlags::FILTER_MAG_SHIFT) | + (ConvertWrapMode(s->mWrapS) << SamplerFlags::WRAP_S_SHIFT) | + (ConvertWrapMode(s->mWrapT) << SamplerFlags::WRAP_T_SHIFT); } else { @@ -459,13 +462,14 @@ void ConvertMaterial(const gt::Material& material, const std::unordered_map mTextureStages; }; diff --git a/dali-scene3d/public-api/loader/mesh-definition.cpp b/dali-scene3d/public-api/loader/mesh-definition.cpp index f147ca7..4b8f21d 100644 --- a/dali-scene3d/public-api/loader/mesh-definition.cpp +++ b/dali-scene3d/public-api/loader/mesh-definition.cpp @@ -82,18 +82,22 @@ bool ReadBlob(const MeshDefinition::Blob& descriptor, std::istream& source, uint } else { - DALI_ASSERT_DEBUG(descriptor.mStride > descriptor.mElementSizeHint); - const uint32_t diff = descriptor.mStride - descriptor.mElementSizeHint; - uint32_t readSize = 0; - while(readSize < descriptor.mLength && - source.read(reinterpret_cast(target), descriptor.mElementSizeHint) && - source.seekg(diff, std::istream::cur)) - { - readSize += descriptor.mStride; - target += descriptor.mElementSizeHint; + if(descriptor.mStride > descriptor.mElementSizeHint) + { + const uint32_t diff = descriptor.mStride - descriptor.mElementSizeHint; + uint32_t readSize = 0; + uint32_t totalSize = (descriptor.mLength / descriptor.mElementSizeHint) * descriptor.mStride; + while(readSize < totalSize && + source.read(reinterpret_cast(target), descriptor.mElementSizeHint) && + source.seekg(diff, std::istream::cur)) + { + readSize += descriptor.mStride; + target += descriptor.mElementSizeHint; + } + return readSize == totalSize; } - return readSize == descriptor.mLength; } + return false; } template @@ -518,7 +522,7 @@ MeshDefinition::Blob::Blob(uint32_t offset, uint32_t length, uint16_t stride, ui uint32_t MeshDefinition::Blob::GetBufferSize() const { - return IsConsecutive() ? mLength : (mLength * mElementSizeHint / mStride); + return mLength; } void MeshDefinition::Blob::ComputeMinMax(uint32_t numComponents, uint32_t count, float* values) diff --git a/dali-scene3d/public-api/loader/node-definition.cpp b/dali-scene3d/public-api/loader/node-definition.cpp index bbed301..10a4473 100644 --- a/dali-scene3d/public-api/loader/node-definition.cpp +++ b/dali-scene3d/public-api/loader/node-definition.cpp @@ -244,20 +244,10 @@ void ModelRenderable::OnCreate(const NodeDefinition& node, NodeDefinition::Creat renderer.RegisterProperty(IBL_INTENSITY_STRING.data(), resources.mEnvironmentMaps[envIdx].first.mIblIntensity); renderer.RegisterProperty(IBL_Y_DIRECTION.data(), resources.mEnvironmentMaps[envIdx].first.mYDirection); - float opaque = 0.0f; - float mask = 0.0f; + float opaque = matDef.mIsOpaque ? 1.0f : 0.0f; + float mask = matDef.mIsMask ? 1.0f : 0.0f; float alphaCutoff = matDef.GetAlphaCutoff(); - if(!MaskMatch(matDef.mFlags, MaterialDefinition::TRANSPARENCY)) - { - opaque = 1.0f; - } - else - { - if(alphaCutoff > 0.f) - { - mask = 1.0f; - } - } + renderer.RegisterProperty("uOpaque", opaque); renderer.RegisterProperty("uMask", mask); renderer.RegisterProperty("uAlphaThreshold", alphaCutoff); diff --git a/dali-scene3d/public-api/loader/shader-definition-factory.cpp b/dali-scene3d/public-api/loader/shader-definition-factory.cpp index a341d20..8a5b639 100644 --- a/dali-scene3d/public-api/loader/shader-definition-factory.cpp +++ b/dali-scene3d/public-api/loader/shader-definition-factory.cpp @@ -93,24 +93,24 @@ uint64_t HashNode(const MaterialDefinition& materialDef, const MeshDefinition& m hash.Add("SSS"); } - if(MaskMatch(materialDef.mFlags, MaterialDefinition::SPECULAR)) + if(MaskMatch(materialDef.mFlags, MaterialDefinition::OCCLUSION)) { - hash.Add("SPECTEX"); + hash.Add("OCCL" /*USION*/); } - if(MaskMatch(materialDef.mFlags, MaterialDefinition::SPECULAR_COLOR)) + if(MaskMatch(materialDef.mFlags, MaterialDefinition::EMISSIVE)) { - hash.Add("SPECCOLTEX"); + hash.Add("EMIS" /*SIVE*/); } - if(MaskMatch(materialDef.mFlags, MaterialDefinition::OCCLUSION)) + if(MaskMatch(materialDef.mFlags, MaterialDefinition::SPECULAR)) { - hash.Add("OCCL" /*USION*/); + hash.Add("SPECTEX"); } - if(MaskMatch(materialDef.mFlags, MaterialDefinition::EMISSIVE)) + if(MaskMatch(materialDef.mFlags, MaterialDefinition::SPECULAR_COLOR)) { - hash.Add("EMIS" /*SIVE*/); + hash.Add("SPECCOLTEX"); } if(MaskMatch(materialDef.mFlags, MaterialDefinition::GLTF_CHANNELS)) @@ -256,24 +256,24 @@ Index ShaderDefinitionFactory::ProduceShader(NodeDefinition::Renderable& rendera shaderDef.mDefines.push_back("SSS"); } - if(MaskMatch(materialDef.mFlags, MaterialDefinition::SPECULAR)) + if(MaskMatch(materialDef.mFlags, MaterialDefinition::OCCLUSION)) { - shaderDef.mDefines.push_back("MATERIAL_SPECULAR_TEXTURE"); + shaderDef.mDefines.push_back("OCCLUSION"); } - if(MaskMatch(materialDef.mFlags, MaterialDefinition::SPECULAR_COLOR)) + if(MaskMatch(materialDef.mFlags, MaterialDefinition::EMISSIVE)) { - shaderDef.mDefines.push_back("MATERIAL_SPECULAR_COLOR_TEXTURE"); + shaderDef.mDefines.push_back("EMISSIVE"); } - if(MaskMatch(materialDef.mFlags, MaterialDefinition::OCCLUSION)) + if(MaskMatch(materialDef.mFlags, MaterialDefinition::SPECULAR)) { - shaderDef.mDefines.push_back("OCCLUSION"); + shaderDef.mDefines.push_back("MATERIAL_SPECULAR_TEXTURE"); } - if(MaskMatch(materialDef.mFlags, MaterialDefinition::EMISSIVE)) + if(MaskMatch(materialDef.mFlags, MaterialDefinition::SPECULAR_COLOR)) { - shaderDef.mDefines.push_back("EMISSIVE"); + shaderDef.mDefines.push_back("MATERIAL_SPECULAR_COLOR_TEXTURE"); } if(MaskMatch(materialDef.mFlags, MaterialDefinition::GLTF_CHANNELS)) -- 2.7.4