Merge "Support KHR_materials_specular and KHR_materials_ior extension of glTF" into...
authorSeungho BAEK <sbsh.baek@samsung.com>
Tue, 29 Nov 2022 06:35:56 +0000 (06:35 +0000)
committerGerrit Code Review <gerrit@review>
Tue, 29 Nov 2022 06:35:56 +0000 (06:35 +0000)
automated-tests/resources/AnimatedCube.gltf
automated-tests/src/dali-scene3d/utc-Dali-Gltf2Loader.cpp
automated-tests/src/dali-scene3d/utc-Dali-Model.cpp
automated-tests/src/dali-scene3d/utc-Dali-SceneView.cpp
dali-scene3d/internal/graphics/shaders/default-physically-based-shader.frag
dali-scene3d/internal/loader/gltf2-asset.h
dali-scene3d/public-api/loader/gltf2-loader.cpp
dali-scene3d/public-api/loader/material-definition.cpp
dali-scene3d/public-api/loader/material-definition.h
dali-scene3d/public-api/loader/node-definition.cpp
dali-scene3d/public-api/loader/shader-definition-factory.cpp

index 995d3b1..455120d 100644 (file)
@@ -1,4 +1,9 @@
 {
+   "extensionsUsed" : [
+       "KHR_materials_specular",
+       "KHR_materials_ior"
+   ],
+
    "accessors" : [
       {
          "bufferView" : 0,
    ],
    "materials" : [
       {
+         "extensions" : {
+            "KHR_materials_specular" : {
+               "specularColorFactor" : [
+                  0,
+                  0,
+                  1
+               ],
+               "specularFactor" : 0.5,
+               "specularTexture": {
+                "index": 0
+               },
+               "specularColorTexture": {
+                "index": 0
+               }
+             },
+             "KHR_materials_ior" : {
+                 "ior" : 1.0
+             }
+         },
          "name" : "AnimatedCube",
          "pbrMetallicRoughness" : {
             "baseColorTexture" : {
index b48ec38..d6687c5 100644 (file)
@@ -168,7 +168,7 @@ int UtcDaliGltfLoaderSuccess1(void)
   DALI_TEST_EQUAL(2u, materials.size());
   const MaterialDefinition materialGroundTruth[]{
     {MaterialDefinition::ALBEDO | MaterialDefinition::EMISSIVE | MaterialDefinition::OCCLUSION |
-       MaterialDefinition::NORMAL |
+       MaterialDefinition::NORMAL | MaterialDefinition::SPECULAR | MaterialDefinition::SPECULAR_COLOR |
        (0x80 << MaterialDefinition::ALPHA_CUTOFF_SHIFT),
      0,
      Color::WHITE,
@@ -178,6 +178,9 @@ int UtcDaliGltfLoaderSuccess1(void)
      1.f,
      1.f,
      Vector3(0.2, 0.1, 0.0),
+     0.0f,
+     0.5f,
+     Vector3(0, 0, 1),
      true,
      false,
      true,
@@ -195,6 +198,12 @@ int UtcDaliGltfLoaderSuccess1(void)
        {MaterialDefinition::EMISSIVE,
         {"AnimatedCube_BaseColor.png",
          SamplerFlags::Encode(FilterMode::LINEAR_MIPMAP_LINEAR, FilterMode::LINEAR, WrapMode::CLAMP_TO_EDGE, WrapMode::REPEAT)}},
+       {MaterialDefinition::SPECULAR,
+        {"AnimatedCube_BaseColor.png",
+         SamplerFlags::Encode(FilterMode::LINEAR_MIPMAP_LINEAR, FilterMode::LINEAR, WrapMode::CLAMP_TO_EDGE, WrapMode::REPEAT)}},
+       {MaterialDefinition::SPECULAR_COLOR,
+        {"AnimatedCube_BaseColor.png",
+         SamplerFlags::Encode(FilterMode::LINEAR_MIPMAP_LINEAR, FilterMode::LINEAR, WrapMode::CLAMP_TO_EDGE, WrapMode::REPEAT)}},
      }},
     {MaterialDefinition::ALBEDO | MaterialDefinition::METALLIC | MaterialDefinition::ROUGHNESS |
        MaterialDefinition::EMISSIVE | MaterialDefinition::OCCLUSION |
@@ -207,6 +216,9 @@ int UtcDaliGltfLoaderSuccess1(void)
      1.f,
      1.f,
      Vector3(0.2, 0.1, 0.0),
+     0.04f,
+     1.0f,
+     Vector3::ONE,
      true,
      true,
      true,
@@ -244,6 +256,9 @@ int UtcDaliGltfLoaderSuccess1(void)
     DALI_TEST_EQUAL(md.mNormalScale, m.mNormalScale);
     DALI_TEST_EQUAL(md.mOcclusionStrength, m.mOcclusionStrength);
     DALI_TEST_EQUAL(md.mEmissiveFactor, m.mEmissiveFactor);
+    DALI_TEST_EQUAL(md.mDielectricSpecular, m.mDielectricSpecular);
+    DALI_TEST_EQUAL(md.mSpecularFactor, m.mSpecularFactor);
+    DALI_TEST_EQUAL(md.mSpecularColorFactor, m.mSpecularColorFactor);
     DALI_TEST_EQUAL(md.mNeedAlbedoTexture, m.mNeedAlbedoTexture);
     DALI_TEST_EQUAL(md.mNeedMetallicRoughnessTexture, m.mNeedMetallicRoughnessTexture);
     DALI_TEST_EQUAL(md.mNeedNormalTexture, m.mNeedNormalTexture);
index b52aa62..7d92024 100644 (file)
@@ -339,15 +339,15 @@ int UtcDaliModelSetImageBasedLightSource01(void)
   DALI_TEST_CHECK(renderer);
 
   TextureSet textureSet = renderer.GetTextures();
-  DALI_TEST_EQUALS(textureSet.GetTextureCount(), 7u, TEST_LOCATION);
+  DALI_TEST_EQUALS(textureSet.GetTextureCount(), 9u, TEST_LOCATION);
 
-  Texture diffuseTexture  = textureSet.GetTexture(5u);
-  Texture specularTexture = textureSet.GetTexture(6u);
+  Texture diffuseTexture  = textureSet.GetTexture(7u);
+  Texture specularTexture = textureSet.GetTexture(8u);
 
   model.SetImageBasedLightSource(TEST_DIFFUSE_TEXTURE, TEST_SPECULAR_TEXTURE);
 
-  Texture newDiffuseTexture  = textureSet.GetTexture(5u);
-  Texture newSpecularTexture = textureSet.GetTexture(6u);
+  Texture newDiffuseTexture  = textureSet.GetTexture(7u);
+  Texture newSpecularTexture = textureSet.GetTexture(8u);
 
   DALI_TEST_NOT_EQUALS(diffuseTexture, newDiffuseTexture, 0.0f, TEST_LOCATION);
   DALI_TEST_NOT_EQUALS(specularTexture, newSpecularTexture, 0.0f, TEST_LOCATION);
@@ -373,15 +373,15 @@ int UtcDaliModelSetImageBasedLightSource02(void)
   DALI_TEST_CHECK(renderer);
 
   TextureSet textureSet = renderer.GetTextures();
-  DALI_TEST_EQUALS(textureSet.GetTextureCount(), 7u, TEST_LOCATION);
+  DALI_TEST_EQUALS(textureSet.GetTextureCount(), 9u, TEST_LOCATION);
 
-  Texture diffuseTexture  = textureSet.GetTexture(5u);
-  Texture specularTexture = textureSet.GetTexture(6u);
+  Texture diffuseTexture  = textureSet.GetTexture(7u);
+  Texture specularTexture = textureSet.GetTexture(8u);
 
   model.SetImageBasedLightSource("", "");
 
-  Texture newDiffuseTexture  = textureSet.GetTexture(5u);
-  Texture newSpecularTexture = textureSet.GetTexture(6u);
+  Texture newDiffuseTexture  = textureSet.GetTexture(7u);
+  Texture newSpecularTexture = textureSet.GetTexture(8u);
 
   DALI_TEST_EQUALS(diffuseTexture, newDiffuseTexture, TEST_LOCATION);
   DALI_TEST_EQUALS(specularTexture, newSpecularTexture, TEST_LOCATION);
@@ -407,15 +407,15 @@ int UtcDaliModelSetImageBasedLightSource03(void)
   DALI_TEST_CHECK(renderer);
 
   TextureSet textureSet = renderer.GetTextures();
-  DALI_TEST_EQUALS(textureSet.GetTextureCount(), 7u, TEST_LOCATION);
+  DALI_TEST_EQUALS(textureSet.GetTextureCount(), 9u, TEST_LOCATION);
 
-  Texture diffuseTexture  = textureSet.GetTexture(5u);
-  Texture specularTexture = textureSet.GetTexture(6u);
+  Texture diffuseTexture  = textureSet.GetTexture(7u);
+  Texture specularTexture = textureSet.GetTexture(8u);
 
   model.SetImageBasedLightSource("dummy.ktx", "dummy.ktx");
 
-  Texture newDiffuseTexture  = textureSet.GetTexture(5u);
-  Texture newSpecularTexture = textureSet.GetTexture(6u);
+  Texture newDiffuseTexture  = textureSet.GetTexture(7u);
+  Texture newSpecularTexture = textureSet.GetTexture(8u);
 
   DALI_TEST_EQUALS(diffuseTexture, newDiffuseTexture, TEST_LOCATION);
   DALI_TEST_EQUALS(specularTexture, newSpecularTexture, TEST_LOCATION);
index 08728df..bf9e015 100644 (file)
@@ -84,9 +84,9 @@ Dali::Texture GetDiffuseTexture(Dali::Scene3D::Model model)
     if(renderer)
     {
       TextureSet textureSet = renderer.GetTextures();
-      if(textureSet.GetTextureCount() == 7u)
+      if(textureSet.GetTextureCount() == 9u)
       {
-        texture = textureSet.GetTexture(5u);
+        texture = textureSet.GetTexture(7u);
       }
     }
   }
@@ -105,9 +105,9 @@ Dali::Texture GetSpecularTexture(Dali::Scene3D::Model model)
     if(renderer)
     {
       TextureSet textureSet = renderer.GetTextures();
-      if(textureSet.GetTextureCount() == 7u)
+      if(textureSet.GetTextureCount() == 9u)
       {
-        texture = textureSet.GetTexture(6u);
+        texture = textureSet.GetTexture(8u);
       }
     }
   }
index ee7eeff..8c9e7ea 100644 (file)
@@ -37,6 +37,7 @@ uniform lowp vec4 uColor; // Color from SceneGraph
 uniform lowp vec4 uColorFactor; // Color from material
 uniform lowp float uMetallicFactor;
 uniform lowp float uRoughnessFactor;
+uniform lowp float uDielectricSpecular;
 
 #ifdef THREE_TEX
 #ifdef BASECOLOR_TEX
@@ -54,6 +55,15 @@ 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;
@@ -84,43 +94,8 @@ in highp vec3 vPositionToCamera;
 
 out vec4 FragColor;
 
-struct PBRInfo
-{
-  mediump float NdotL;        // cos angle between normal and light direction
-  mediump float NdotV;        // cos angle between normal and view direction
-  mediump float NdotH;        // cos angle between normal and half vector
-  mediump float VdotH;        // cos angle between view direction and half vector
-  mediump vec3 reflectance0;  // full reflectance color (normal incidence angle)
-  mediump vec3 reflectance90; // reflectance color at grazing angle
-  lowp float alphaRoughness;  // roughness mapped to a more linear change in the roughness (proposed by [2])
-};
-
-const float M_PI = 3.141592653589793;
 const float c_MinRoughness = 0.04;
 
-vec3 specularReflection(PBRInfo pbrInputs)
-{
-  return pbrInputs.reflectance0 + (pbrInputs.reflectance90 - pbrInputs.reflectance0) * pow(clamp(1.0 - pbrInputs.VdotH, 0.0, 1.0), 5.0);
-}
-
-float geometricOcclusion(PBRInfo pbrInputs)
-{
-  mediump float NdotL = pbrInputs.NdotL;
-  mediump float NdotV = pbrInputs.NdotV;
-  lowp float r = pbrInputs.alphaRoughness;
-
-  lowp float attenuationL = 2.0 * NdotL / (NdotL + sqrt(r * r + (1.0 - r * r) * (NdotL * NdotL)));
-  lowp float attenuationV = 2.0 * NdotV / (NdotV + sqrt(r * r + (1.0 - r * r) * (NdotV * NdotV)));
-  return attenuationL * attenuationV;
-}
-
-float microfacetDistribution(PBRInfo pbrInputs)
-{
-  mediump float roughnessSq = pbrInputs.alphaRoughness * pbrInputs.alphaRoughness;
-  lowp float f = (pbrInputs.NdotH * roughnessSq - pbrInputs.NdotH) * pbrInputs.NdotH + 1.0;
-  return roughnessSq / (M_PI * f * f);
-}
-
 vec3 linear(vec3 color)
 {
   return pow(color, vec3(2.2));
@@ -182,35 +157,45 @@ void main()
   // Roughness is authored as perceptual roughness; as is convention,
   // convert to material roughness by squaring the perceptual roughness [2].
   perceptualRoughness = clamp(perceptualRoughness, c_MinRoughness, 1.0);
-  lowp float alphaRoughness = perceptualRoughness * perceptualRoughness;
-
-  lowp vec3 f0 = vec3(0.04);
-  lowp vec3 diffuseColor = baseColor.rgb * (vec3(1.0) - f0);
-  diffuseColor *= (1.0 - metallic);
-  lowp vec3 specularColor = mix(f0, baseColor.rgb, metallic);
 
-  // Compute reflectance.
-  lowp float reflectance = max(max(specularColor.r, specularColor.g), specularColor.b);
+  // Material ior
+  lowp vec3 f0 = vec3(uDielectricSpecular);
 
-  // For typical incident reflectance range (between 4% to 100%) set the grazing reflectance to 100% for typical fresnel effect.
-  // For very low reflectance range on highly diffuse objects (below 4%), incrementally reduce grazing reflecance to 0%.
-  lowp float reflectance90 = clamp(reflectance * 25.0, 0.0, 1.0);
-  lowp vec3 specularEnvironmentR0 = specularColor.rgb;
-  lowp vec3 specularEnvironmentR90 = vec3(1.0, 1.0, 1.0) * reflectance90;
+  // Material Specular
+  float specularWeight = 1.0;
+  vec4 materialSpecularTexture = vec4(1.0);
+#ifdef MATERIAL_SPECULAR_TEXTURE
+  materialSpecularTexture.a = texture(sSpecular, vUV).a;
+#endif
+#ifdef MATERIAL_SPECULAR_COLOR_TEXTURE
+  materialSpecularTexture.rgb = texture(sSpecularColor, vUV).rgb;
+#endif
+  specularWeight = uSpecularFactor * materialSpecularTexture.a;
+  f0 = min(f0 * uSpecularColorFactor * materialSpecularTexture.rgb, vec3(1.0));
+  f0 = mix(f0, baseColor.rgb, metallic);
 
   mediump vec3 v = normalize(vPositionToCamera); // Vector from surface point to camera
   mediump float NdotV = clamp(abs(dot(n, v)), 0.001, 1.0);
   mediump vec3 reflection = -normalize(reflect(v, n));
-
-  lowp vec3 color = vec3(0.0);
-  lowp vec3 diffuseLight = linear(texture(sDiffuseEnvSampler, n * uYDirection).rgb);
-  lowp vec3 specularLight = linear(texture(sSpecularEnvSampler, reflection * uYDirection).rgb);
-  // retrieve a scale and bias to F0. See [1], Figure 3
   lowp vec3 brdf = linear(texture(sbrdfLUT, vec2(NdotV, 1.0 - perceptualRoughness)).rgb);
+  vec3 Fr = max(vec3(1.0 - perceptualRoughness), f0) - f0;
+  vec3 k_S = f0 + Fr * pow(1.0 - NdotV, 5.0);
+  vec3 FssEss = specularWeight * (k_S * brdf.x + brdf.y);
 
-  lowp vec3 diffuse = diffuseLight * diffuseColor;
-  lowp vec3 specular = specularLight * (specularColor * brdf.x + brdf.y);
-  color += (diffuse + specular) * uIblIntensity;
+  // Specular Light
+  lowp vec3 specularLight = linear(texture(sSpecularEnvSampler, reflection * uYDirection).rgb);
+  lowp vec3 specular = specularLight * FssEss;
+
+  // Diffuse Light
+  lowp vec3 diffuseColor = mix(baseColor.rgb, vec3(0), metallic);
+  lowp vec3 irradiance = linear(texture(sDiffuseEnvSampler, n * uYDirection).rgb);
+  float Ems = (1.0 - (brdf.x + brdf.y));
+  vec3 F_avg = specularWeight * (f0 + (1.0 - f0) / 21.0);
+  vec3 FmsEms = Ems * FssEss * F_avg / (1.0 - F_avg * Ems);
+  vec3 k_D = diffuseColor * (1.0 - FssEss + FmsEms);
+  lowp vec3 diffuse = (FmsEms + k_D) * irradiance;
+
+  lowp vec3 color = (diffuse + specular) * uIblIntensity;
 
 #ifdef OCCLUSION
   lowp float ao = texture(sOcclusion, vUV).r;
index 7769751..3fa2705 100644 (file)
@@ -325,9 +325,36 @@ struct TextureInfo
   }
 };
 
+/**
+ * Material Ior is supported with KHR_materials_ior extension.
+ * https://github.com/KhronosGroup/glTF/tree/main/extensions/2.0/Khronos/KHR_materials_ior
+ */
+struct MaterialIor
+{
+  float mIor = MAXFLOAT;
+};
+
+/**
+ * Material Specular is supported with KHR_materials_ior extension.
+ * https://github.com/KhronosGroup/glTF/tree/main/extensions/2.0/Khronos/KHR_materials_specular
+ */
+struct MaterialSpecular
+{
+  float         mSpecularFactor = 1.0f;
+  TextureInfo   mSpecularTexture;
+  Dali::Vector3 mSpecularColorFactor = Dali::Vector3::ONE;
+  TextureInfo   mSpecularColorTexture;
+};
+
+struct MaterialExtensions
+{
+  MaterialSpecular mMaterialSpecular;
+  MaterialIor      mMaterialIor;
+};
+
 struct Material : Named
 {
-  struct Pbr //MetallicRoughness
+  struct Pbr // MetallicRoughness
   {
     Dali::Vector4 mBaseColorFactor = Dali::Vector4::ONE;
     TextureInfo   mBaseColorTexture;
@@ -338,15 +365,17 @@ struct Material : Named
     //TODO: extras
   };
 
-  Pbr             mPbrMetallicRoughness;
-  TextureInfo     mNormalTexture;
-  TextureInfo     mOcclusionTexture;
-  TextureInfo     mEmissiveTexture;
-  Dali::Vector3   mEmissiveFactor;
-  AlphaMode::Type mAlphaMode   = AlphaMode::OPAQUE;
-  float           mAlphaCutoff = .5f;
-  bool            mDoubleSided = false;
-  //TODO: extensions
+  Pbr               mPbrMetallicRoughness;
+  TextureInfo       mNormalTexture;
+  TextureInfo       mOcclusionTexture;
+  TextureInfo       mEmissiveTexture;
+  Dali::Vector3     mEmissiveFactor;
+  AlphaMode::Type   mAlphaMode   = AlphaMode::OPAQUE;
+  float             mAlphaCutoff = .5f;
+  bool              mDoubleSided = false;
+
+  //extensions
+  MaterialExtensions mMaterialExtensions;
   //TODO: extras
 };
 
index 36c1639..e6d34fc 100644 (file)
@@ -169,6 +169,20 @@ const auto MATERIAL_PBR_READER = std::move(js::Reader<gt::Material::Pbr>()
                                              .Register(*js::MakeProperty("roughnessFactor", js::Read::Number<float>, &gt::Material::Pbr::mRoughnessFactor))
                                              .Register(*js::MakeProperty("metallicRoughnessTexture", js::ObjectReader<gt::TextureInfo>::Read, &gt::Material::Pbr::mMetallicRoughnessTexture)));
 
+const auto MATERIAL_SPECULAR_READER = std::move(js::Reader<gt::MaterialSpecular>()
+                                                  .Register(*js::MakeProperty("specularFactor", js::Read::Number<float>, &gt::MaterialSpecular::mSpecularFactor))
+                                                  .Register(*js::MakeProperty("specularTexture", js::ObjectReader<gt::TextureInfo>::Read, &gt::MaterialSpecular::mSpecularTexture))
+                                                  .Register(*js::MakeProperty("specularColorFactor", gt::ReadDaliVector<Vector3>, &gt::MaterialSpecular::mSpecularColorFactor))
+                                                  .Register(*js::MakeProperty("specularColorTexture", js::ObjectReader<gt::TextureInfo>::Read, &gt::MaterialSpecular::mSpecularColorTexture)));
+
+const auto MATERIAL_IOR_READER = std::move(js::Reader<gt::MaterialIor>()
+                                             .Register(*js::MakeProperty("ior", js::Read::Number<float>, &gt::MaterialIor::mIor)));
+
+
+const auto MATERIAL_EXTENSION_READER = std::move(js::Reader<gt::MaterialExtensions>()
+                                                   .Register(*js::MakeProperty("KHR_materials_ior", js::ObjectReader<gt::MaterialIor>::Read, &gt::MaterialExtensions::mMaterialIor))
+                                                   .Register(*js::MakeProperty("KHR_materials_specular", js::ObjectReader<gt::MaterialSpecular>::Read, &gt::MaterialExtensions::mMaterialSpecular)));
+
 const auto MATERIAL_READER = std::move(js::Reader<gt::Material>()
                                          .Register(*new js::Property<gt::Material, std::string_view>("name", js::Read::StringView, &gt::Material::mName))
                                          .Register(*js::MakeProperty("pbrMetallicRoughness", js::ObjectReader<gt::Material::Pbr>::Read, &gt::Material::mPbrMetallicRoughness))
@@ -178,7 +192,8 @@ const auto MATERIAL_READER = std::move(js::Reader<gt::Material>()
                                          .Register(*js::MakeProperty("emissiveFactor", gt::ReadDaliVector<Vector3>, &gt::Material::mEmissiveFactor))
                                          .Register(*js::MakeProperty("alphaMode", gt::ReadStringEnum<gt::AlphaMode>, &gt::Material::mAlphaMode))
                                          .Register(*js::MakeProperty("alphaCutoff", js::Read::Number<float>, &gt::Material::mAlphaCutoff))
-                                         .Register(*js::MakeProperty("doubleSided", js::Read::Boolean, &gt::Material::mDoubleSided)));
+                                         .Register(*js::MakeProperty("doubleSided", js::Read::Boolean, &gt::Material::mDoubleSided))
+                                         .Register(*js::MakeProperty("extensions", js::ObjectReader<gt::MaterialExtensions>::Read, &gt::Material::mMaterialExtensions)));
 
 std::map<gt::Attribute::Type, gt::Ref<gt::Accessor>> ReadMeshPrimitiveAttributes(const json_value_s& j)
 {
@@ -504,6 +519,28 @@ void ConvertMaterial(const gt::Material& material, decltype(ResourceBundle::mMat
     matDef.mEmissiveFactor = material.mEmissiveFactor;
   }
 
+  if(material.mMaterialExtensions.mMaterialIor.mIor < MAXFLOAT)
+  {
+    float ior = material.mMaterialExtensions.mMaterialIor.mIor;
+    matDef.mDielectricSpecular = powf((ior-1.0f)/(ior+1.0f), 2.0f);
+  }
+  matDef.mSpecularFactor      = material.mMaterialExtensions.mMaterialSpecular.mSpecularFactor;
+  matDef.mSpecularColorFactor = material.mMaterialExtensions.mMaterialSpecular.mSpecularColorFactor;
+
+  if(material.mMaterialExtensions.mMaterialSpecular.mSpecularTexture)
+  {
+    const auto semantic = MaterialDefinition::SPECULAR;
+    matDef.mTextureStages.push_back({semantic, ConvertTextureInfo(material.mMaterialExtensions.mMaterialSpecular.mSpecularTexture)});
+    matDef.mFlags |= semantic;
+  }
+
+  if(material.mMaterialExtensions.mMaterialSpecular.mSpecularColorTexture)
+  {
+    const auto semantic = MaterialDefinition::SPECULAR_COLOR;
+    matDef.mTextureStages.push_back({semantic, ConvertTextureInfo(material.mMaterialExtensions.mMaterialSpecular.mSpecularColorTexture)});
+    matDef.mFlags |= semantic;
+  }
+
   matDef.mDoubleSided = material.mDoubleSided;
 
   outMaterials.emplace_back(std::move(matDef), TextureSet());
@@ -1143,6 +1180,9 @@ void SetObjectReaders()
   js::SetObjectReader(TEXURE_READER);
   js::SetObjectReader(TEXURE_INFO_READER);
   js::SetObjectReader(MATERIAL_PBR_READER);
+  js::SetObjectReader(MATERIAL_SPECULAR_READER);
+  js::SetObjectReader(MATERIAL_IOR_READER);
+  js::SetObjectReader(MATERIAL_EXTENSION_READER);
   js::SetObjectReader(MATERIAL_READER);
   js::SetObjectReader(MESH_PRIMITIVE_READER);
   js::SetObjectReader(MESH_READER);
index 480da95..7f86add 100644 (file)
@@ -236,6 +236,18 @@ MaterialDefinition::LoadRaw(const std::string& imagesPath) const
     ++iTexture;
   }
 
+  if(checkStage(SPECULAR))
+  {
+    raw.mTextures.push_back({SyncImageLoader::Load(imagesPath + iTexture->mTexture.mImageUri), iTexture->mTexture.mSamplerFlags});
+    ++iTexture;
+  }
+
+  if(checkStage(SPECULAR_COLOR))
+  {
+    raw.mTextures.push_back({SyncImageLoader::Load(imagesPath + iTexture->mTexture.mImageUri), iTexture->mTexture.mSamplerFlags});
+    ++iTexture;
+  }
+
   return raw;
 }
 
index e45b69b..119f7c4 100644 (file)
@@ -130,13 +130,15 @@ struct DALI_SCENE3D_API MaterialDefinition
   enum Flags : uint32_t
   {
     // Texture semantics
-    ALBEDO     = NthBit(0),
-    METALLIC   = NthBit(1),
-    ROUGHNESS  = NthBit(2),
-    NORMAL     = NthBit(3),
-    EMISSIVE   = NthBit(4), // TODO: support
-    OCCLUSION  = NthBit(5), // TODO: support
-    SUBSURFACE = NthBit(6), // Note: dli-only
+    ALBEDO         = NthBit(0),
+    METALLIC       = NthBit(1),
+    ROUGHNESS      = NthBit(2),
+    NORMAL         = NthBit(3),
+    EMISSIVE       = NthBit(4),
+    OCCLUSION      = NthBit(5),
+    SPECULAR       = NthBit(6),
+    SPECULAR_COLOR = NthBit(7),
+    SUBSURFACE     = NthBit(8), // Note: dli-only
 
     // Other binary options
     TRANSPARENCY  = NthBit(20),
@@ -221,14 +223,17 @@ struct DALI_SCENE3D_API MaterialDefinition
 public: // DATA
   uint32_t mFlags = 0x0;
 
-  Index   mEnvironmentIdx    = 0;
-  Vector4 mColor             = Color::WHITE;
-  float   mMetallic          = 1.f;
-  float   mRoughness         = 1.f;
-  Vector4 mBaseColorFactor   = Vector4::ONE;
-  float   mNormalScale       = 1.f;
-  float   mOcclusionStrength = 1.f;
-  Vector3 mEmissiveFactor    = Vector3::ZERO;
+  Index   mEnvironmentIdx      = 0;
+  Vector4 mColor               = Color::WHITE;
+  float   mMetallic            = 1.f;
+  float   mRoughness           = 1.f;
+  Vector4 mBaseColorFactor     = Vector4::ONE;
+  float   mNormalScale         = 1.f;
+  float   mOcclusionStrength   = 1.f;
+  Vector3 mEmissiveFactor      = Vector3::ZERO;
+  float   mDielectricSpecular  = 0.04f;
+  float   mSpecularFactor      = 1.0f;
+  Vector3 mSpecularColorFactor = Vector3::ONE;
 
   // For the glTF, each of albedo, metallicRoughness, normal textures are not essential.
   bool mNeedAlbedoTexture            = true;
index 87fc246..bbed301 100644 (file)
@@ -224,10 +224,13 @@ void ModelRenderable::OnCreate(const NodeDefinition& node, NodeDefinition::Creat
   renderer.RegisterProperty("uHasVertexColor", static_cast<float>(mesh.first.mColors.IsDefined()));
 
   auto& matDef = resources.mMaterials[mMaterialIdx].first;
-  renderer.RegisterProperty("uColorFactor", matDef.mBaseColorFactor);
-  renderer.RegisterProperty("uMetallicFactor", matDef.mMetallic);
-  renderer.RegisterProperty("uRoughnessFactor", matDef.mRoughness);
-  renderer.RegisterProperty("uNormalScale", matDef.mNormalScale);
+  actor.RegisterProperty("uColorFactor", matDef.mBaseColorFactor);
+  actor.RegisterProperty("uMetallicFactor", matDef.mMetallic);
+  actor.RegisterProperty("uRoughnessFactor", matDef.mRoughness);
+  actor.RegisterProperty("uDielectricSpecular", matDef.mDielectricSpecular);
+  actor.RegisterProperty("uSpecularFactor", matDef.mSpecularFactor);
+  actor.RegisterProperty("uSpecularColorFactor", matDef.mSpecularColorFactor);
+  actor.RegisterProperty("uNormalScale", matDef.mNormalScale);
   if(matDef.mFlags & MaterialDefinition::OCCLUSION)
   {
     renderer.RegisterProperty("uOcclusionStrength", matDef.mOcclusionStrength);
index ec41ef4..a341d20 100644 (file)
@@ -93,6 +93,16 @@ uint64_t HashNode(const MaterialDefinition& materialDef, const MeshDefinition& m
     hash.Add("SSS");
   }
 
+  if(MaskMatch(materialDef.mFlags, MaterialDefinition::SPECULAR))
+  {
+    hash.Add("SPECTEX");
+  }
+
+  if(MaskMatch(materialDef.mFlags, MaterialDefinition::SPECULAR_COLOR))
+  {
+    hash.Add("SPECCOLTEX");
+  }
+
   if(MaskMatch(materialDef.mFlags, MaterialDefinition::OCCLUSION))
   {
     hash.Add("OCCL" /*USION*/);
@@ -246,6 +256,16 @@ Index ShaderDefinitionFactory::ProduceShader(NodeDefinition::Renderable& rendera
       shaderDef.mDefines.push_back("SSS");
     }
 
+    if(MaskMatch(materialDef.mFlags, MaterialDefinition::SPECULAR))
+    {
+      shaderDef.mDefines.push_back("MATERIAL_SPECULAR_TEXTURE");
+    }
+
+    if(MaskMatch(materialDef.mFlags, MaterialDefinition::SPECULAR_COLOR))
+    {
+      shaderDef.mDefines.push_back("MATERIAL_SPECULAR_COLOR_TEXTURE");
+    }
+
     if(MaskMatch(materialDef.mFlags, MaterialDefinition::OCCLUSION))
     {
       shaderDef.mDefines.push_back("OCCLUSION");