Use default PBR shader to the scene-loader 91/273891/15
authorseungho <sbsh.baek@samsung.com>
Fri, 15 Apr 2022 08:31:41 +0000 (17:31 +0900)
committerseungho <sbsh.baek@samsung.com>
Wed, 27 Apr 2022 12:09:03 +0000 (21:09 +0900)
 - glTF uses built-in shader for rendering.
 - glTF features of Emission and Ambient Occlusion are added.

Change-Id: I7b63ee171b8c66c777e1d8a0732860f7a35240e2
Signed-off-by: seungho <sbsh.baek@samsung.com>
12 files changed:
automated-tests/src/dali-scene-loader/utc-Dali-Gltf2Loader.cpp
automated-tests/src/dali-scene-loader/utc-Dali-ShaderDefinitionFactory.cpp
dali-scene-loader/internal/gltf2-asset.h
dali-scene-loader/internal/graphics/shaders/default-physically-based-shader.frag [new file with mode: 0644]
dali-scene-loader/internal/graphics/shaders/default-physically-based-shader.vert [new file with mode: 0644]
dali-scene-loader/public-api/gltf2-loader.cpp
dali-scene-loader/public-api/material-definition.cpp
dali-scene-loader/public-api/material-definition.h
dali-scene-loader/public-api/node-definition.cpp
dali-scene-loader/public-api/shader-definition-factory.cpp
dali-scene-loader/public-api/shader-definition.cpp
dali-scene-loader/public-api/shader-definition.h

index 47515b3..b4dceb9 100644 (file)
@@ -167,12 +167,15 @@ int UtcDaliGltfLoaderSuccess1(void)
   DALI_TEST_EQUAL(2u, materials.size());
   const MaterialDefinition materialGroundTruth[]{
     {MaterialDefinition::ALBEDO | MaterialDefinition::METALLIC | MaterialDefinition::ROUGHNESS |
+       MaterialDefinition::EMISSIVE | MaterialDefinition::OCCLUSION |
        MaterialDefinition::NORMAL | MaterialDefinition::TRANSPARENCY | MaterialDefinition::GLTF_CHANNELS |
        (0x80 << MaterialDefinition::ALPHA_CUTOFF_SHIFT),
      0,
      Vector4(1.f, .766f, .336f, 1.f),
+     Vector3(0.2, 0.1, 0.0),
      1.f,
      0.f,
+     1.f,
      {
        {MaterialDefinition::ALBEDO,
         {"AnimatedCube_BaseColor.png",
@@ -183,13 +186,22 @@ int UtcDaliGltfLoaderSuccess1(void)
        {MaterialDefinition::NORMAL,
         {"AnimatedCube_BaseColor.png",
          SamplerFlags::Encode(FilterMode::LINEAR_MIPMAP_LINEAR, FilterMode::LINEAR, WrapMode::CLAMP_TO_EDGE, WrapMode::REPEAT)}},
+       {MaterialDefinition::OCCLUSION,
+        {"AnimatedCube_BaseColor.png",
+         SamplerFlags::Encode(FilterMode::LINEAR_MIPMAP_LINEAR, FilterMode::LINEAR, WrapMode::CLAMP_TO_EDGE, WrapMode::REPEAT)}},
+       {MaterialDefinition::EMISSIVE,
+        {"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 |
        MaterialDefinition::NORMAL | MaterialDefinition::GLTF_CHANNELS,
      0,
      Vector4(1.f, .766f, .336f, 1.f),
+     Vector3(0.2, 0.1, 0.0),
      1.f,
      0.f,
+     1.f,
      {
        {MaterialDefinition::ALBEDO,
         {"AnimatedCube_BaseColor.png",
@@ -200,6 +212,12 @@ int UtcDaliGltfLoaderSuccess1(void)
        {MaterialDefinition::NORMAL,
         {"AnimatedCube_BaseColor.png",
          SamplerFlags::Encode(FilterMode::LINEAR_MIPMAP_LINEAR, FilterMode::LINEAR, WrapMode::CLAMP_TO_EDGE, WrapMode::REPEAT)}},
+       {MaterialDefinition::OCCLUSION,
+        {"AnimatedCube_BaseColor.png",
+         SamplerFlags::Encode(FilterMode::LINEAR_MIPMAP_LINEAR, FilterMode::LINEAR, WrapMode::CLAMP_TO_EDGE, WrapMode::REPEAT)}},
+       {MaterialDefinition::EMISSIVE,
+        {"AnimatedCube_BaseColor.png",
+         SamplerFlags::Encode(FilterMode::LINEAR_MIPMAP_LINEAR, FilterMode::LINEAR, WrapMode::CLAMP_TO_EDGE, WrapMode::REPEAT)}},
      }},
   };
 
index 80ed66d..3fd8fbb 100644 (file)
@@ -31,11 +31,6 @@ using namespace Dali::SceneLoader;
 
 namespace
 {
-bool EndsWith(const std::string& str, const std::string& suffix) // ends_width() is C++20
-{
-  return str.size() >= suffix.size() && str.substr(str.size() - suffix.size()).compare(suffix) == 0;
-}
-
 MaterialDefinition& NewMaterialDefinition(ResourceBundle& resources)
 {
   resources.mMaterials.push_back({});
@@ -281,8 +276,6 @@ int UtcDaliShaderDefinitionFactoryProduceShader(void)
     DALI_TEST_EQUAL(ps.shaderIdx, shaderIdx);
 
     auto& shaderDef = ctx.resources.mShaders[shaderIdx].first;
-    DALI_TEST_CHECK(EndsWith(shaderDef.mVertexShaderPath, ".vsh"));
-    DALI_TEST_CHECK(EndsWith(shaderDef.mFragmentShaderPath, ".fsh"));
     DALI_TEST_EQUAL(shaderDef.mRendererState, rendererState);
 
     uint32_t definesUnmatched = shaderDef.mDefines.size();
index f5bd6b9..e074c28 100644 (file)
@@ -317,6 +317,7 @@ struct TextureInfo
   Ref<gltf2::Texture> mTexture;
   uint32_t            mTexCoord = 0;
   float               mScale    = 1.f;
+  float               mStrength = 1.f;
 
   operator bool() const
   {
diff --git a/dali-scene-loader/internal/graphics/shaders/default-physically-based-shader.frag b/dali-scene-loader/internal/graphics/shaders/default-physically-based-shader.frag
new file mode 100644 (file)
index 0000000..2581ad6
--- /dev/null
@@ -0,0 +1,183 @@
+#version 300 es
+
+#ifdef HIGHP
+  precision highp float;
+#else
+  precision mediump float;
+#endif
+
+#ifdef THREE_TEX
+#ifdef GLTF_CHANNELS
+// https://github.com/KhronosGroup/glTF/tree/master/specification/2.0#pbrmetallicroughnessmetallicroughnesstexture
+#define METALLIC b
+#define ROUGHNESS g
+#else //GLTF_CHANNELS
+#define METALLIC r
+#define ROUGHNESS a
+#endif //GLTF_CHANNELS
+#endif //THREE_TEX
+
+#ifdef THREE_TEX
+  uniform sampler2D sAlbedoAlpha;
+  uniform sampler2D sMetalRoughness;
+  uniform sampler2D sNormal;
+
+#ifdef ALPHA_TEST
+  uniform float uAlphaThreshold;
+#endif //ALPHA_TEST
+
+#else
+  uniform sampler2D sAlbedoMetal;
+  uniform sampler2D sNormalRoughness;
+#endif
+
+#ifdef OCCLUSION
+  uniform sampler2D sOcclusion;
+  uniform float uOcclusionStrength;
+#endif
+
+#ifdef EMISSIVE
+  uniform sampler2D sEmissive;
+  uniform vec3 uEmissiveFactor;
+#endif
+
+uniform samplerCube sDiffuse;
+uniform samplerCube sSpecular;
+
+// Number of mip map levels in the texture
+uniform float uMaxLOD;
+
+// Transformation matrix of the cubemap texture
+uniform mat4 uCubeMatrix;
+
+uniform vec4 uColor;
+uniform float uMetallicFactor;
+uniform float uRoughnessFactor;
+
+//IBL Light intensity
+uniform float uIblIntensity;
+
+// TODO: Multiple texture coordinate will be supported.
+in vec2 vUV;
+in vec3 vNormal;
+in vec3 vTangent;
+in vec3 vViewVec;
+
+out vec4 FragColor;
+
+// Functions for BRDF calculation come from
+// https://www.unrealengine.com/blog/physically-based-shading-on-mobile
+// Based on the paper by Dimitar Lazarov
+// http://blog.selfshadow.com/publications/s2013-shading-course/lazarov/s2013_pbs_black_ops_2_notes.pdf
+vec3 EnvBRDFApprox( vec3 SpecularColor, float Roughness, float NoV )
+{
+  const vec4 c0 = vec4( -1.0, -0.0275, -0.572, 0.022 );
+  const vec4 c1 = vec4( 1.0, 0.0425, 1.04, -0.04 );
+  vec4 r = Roughness * c0 + c1;
+  float a004 = min( r.x * r.x, exp2( -9.28 * NoV ) ) * r.x + r.y;
+  vec2 AB = vec2( -1.04, 1.04 ) * a004 + r.zw;
+
+  return SpecularColor * AB.x + AB.y;
+}
+
+void main()
+{
+  // We get information from the maps (albedo, normal map, roughness, metalness
+  // I access the maps in the order they will be used
+#ifdef THREE_TEX
+  vec4 albedoAlpha = texture(sAlbedoAlpha, vUV.st);
+  float alpha = albedoAlpha.a;
+#ifdef ALPHA_TEST
+  if (alpha <= uAlphaThreshold)
+  {
+    discard;
+  }
+#endif //ALPHA_TEST
+  vec3 albedoColor = albedoAlpha.rgb * uColor.rgb;
+
+  vec4 metalRoughness = texture(sMetalRoughness, vUV.st);
+  float metallic = metalRoughness.METALLIC * uMetallicFactor;
+  float roughness = metalRoughness.ROUGHNESS * uRoughnessFactor;
+
+  vec3 normalMap = texture(sNormal, vUV.st).rgb;
+#else  //THREE_TEX
+  vec4 albedoMetal = texture(sAlbedoMetal, vUV.st);
+  vec3 albedoColor = albedoMetal.rgb * uColor.rgb;
+  float metallic = albedoMetal.a * uMetallicFactor;
+
+  vec4 normalRoughness = texture(sNormalRoughness, vUV.st);
+  vec3 normalMap = normalRoughness.rgb;
+  float roughness = normalRoughness.a * uRoughnessFactor;
+#endif
+  //Normalize vectors
+  vec3 normal = normalize(vNormal);
+  vec3 tangent = normalize(vTangent);
+
+  // NOTE: normal and tangent have to be orthogonal for the result of the cross()
+  // product to be a unit vector. We might find that we need to normalize().
+  vec3 bitangent = cross(normal, tangent);
+
+  vec3 viewVec = normalize(vViewVec);
+
+  // Create Inverse Local to world matrix
+  mat3 vInvTBN = mat3(tangent, bitangent, normal);
+
+  // Get normal map info in world space
+  normalMap = normalize(normalMap - 0.5);
+  vec3 newNormal = vInvTBN * normalMap.rgb;
+
+  // Calculate normal dot view vector
+  float NoV = max(dot(newNormal, -viewVec), 0.0);
+
+  // Reflect vector
+  vec3 reflectionVec = reflect(viewVec, newNormal);
+
+  //transform it now to environment coordinates (used when the environment rotates)
+  vec3 reflecCube = (uCubeMatrix * vec4( reflectionVec, 0.0 ) ).xyz;
+  reflecCube = normalize( reflecCube );
+
+  //transform it now to environment coordinates
+  vec3 normalCube = ( uCubeMatrix * vec4( newNormal, 0.0 ) ).xyz;
+  normalCube = normalize( normalCube );
+
+  // Get irradiance from diffuse cubemap
+  vec3 irradiance = texture( sDiffuse, normalCube ).rgb;
+
+  // Access reflection color using roughness value
+  float finalLod = mix( 0.0, uMaxLOD - 2.0, roughness);
+  vec3 reflectionColor = textureLod(sSpecular, reflecCube, finalLod).rgb;
+
+  // We are supposed to be using DielectricColor (0.04) of a plastic (almost everything)
+  // http://blog.selfshadow.com/publications/s2014-shading-course/hoffman/s2014_pbs_physics_math_slides.pdf
+  // however that seems to prevent achieving very dark tones (i.e. get dark gray blacks).
+  vec3 DiffuseColor = albedoColor - albedoColor * metallic;  // 1 mad
+  vec3 SpecularColor = mix( vec3(0.04), albedoColor, metallic); // 2 mad
+
+  // Calculate specular color using Magic Function (takes original roughness and normal dot view).
+  vec3 specColor =  reflectionColor.rgb * EnvBRDFApprox(SpecularColor, roughness, NoV );
+
+  // Multiply the result by albedo texture and do energy conservation
+  vec3 diffuseColor = irradiance * DiffuseColor;
+
+  // Final color is the sum of the diffuse and specular term
+  vec3 finalColor = diffuseColor + specColor;
+
+  finalColor = sqrt( finalColor ) * uIblIntensity;
+
+
+#ifdef OCCLUSION
+  float ao = texture(sOcclusion, vUV.st).r;
+  finalColor = mix( finalColor, finalColor * ao, uOcclusionStrength );
+#endif
+
+#ifdef EMISSIVE
+  vec3 emissive = texture( sEmissive, vUV.st ).rgb * uEmissiveFactor;
+  finalColor += emissive;
+#endif
+
+#ifdef THREE_TEX
+  FragColor = vec4( finalColor, alpha );
+#else //THREE_TEX
+  FragColor = vec4( finalColor, 1.0 );
+#endif //THREE_TEX
+}
diff --git a/dali-scene-loader/internal/graphics/shaders/default-physically-based-shader.vert b/dali-scene-loader/internal/graphics/shaders/default-physically-based-shader.vert
new file mode 100644 (file)
index 0000000..e9381c5
--- /dev/null
@@ -0,0 +1,149 @@
+#version 300 es
+
+#ifdef HIGHP
+  precision highp float;
+#else
+  precision mediump float;
+#endif
+
+in vec3 aPosition;
+in vec2 aTexCoord;
+in vec3 aNormal;
+in vec3 aTangent;
+
+#ifdef MORPH
+  uniform sampler2D sBlendShapeGeometry;
+#endif
+
+out vec2 vUV;
+out vec3 vNormal;
+out vec3 vTangent;
+out vec3 vViewVec;
+
+uniform highp mat4 uMvpMatrix;
+uniform highp mat4 uViewMatrix;
+uniform mat3 uNormalMatrix;
+uniform mat4 uModelMatrix;
+uniform mat4 uModelView;
+uniform mat4 uProjection;
+
+#ifdef SKINNING
+  in vec4 aJoints;
+  in vec4 aWeights;
+  #define MAX_BONES 64
+  uniform mat4 uBone[MAX_BONES];
+#endif
+
+#ifdef MORPH
+#define MAX_BLEND_SHAPE_NUMBER 128
+uniform int uNumberOfBlendShapes;                                   ///< Total number of blend shapes loaded.
+uniform float uBlendShapeWeight[MAX_BLEND_SHAPE_NUMBER];            ///< The weight of each blend shape.
+#ifdef MORPH_VERSION_2_0
+uniform float uBlendShapeUnnormalizeFactor;                         ///< Factor used to unnormalize the geometry of the blend shape.
+#else
+uniform float uBlendShapeUnnormalizeFactor[MAX_BLEND_SHAPE_NUMBER]; ///< Factor used to unnormalize the geometry of the blend shape.
+#endif
+uniform int uBlendShapeComponentSize;                               ///< The size in the texture of either the vertices, normals or tangents. Used to calculate the offset to address them.
+#endif
+
+void main()
+{
+  vec4 position = vec4(aPosition, 1.0);
+  vec3 normal = aNormal;
+  vec3 tangent = aTangent;
+
+#ifdef MORPH
+  int width = textureSize( sBlendShapeGeometry, 0 ).x;
+
+  int blendShapeBufferOffset = 0;
+  for( int index = 0; index < uNumberOfBlendShapes; ++index )
+  {
+#ifdef MORPH_POSITION
+    // Calculate the index to retrieve the geometry from the texture.
+    int vertexId = gl_VertexID + blendShapeBufferOffset;
+    int x = vertexId % width;
+    int y = vertexId / width;
+
+    vec3 diff = vec3(0.0);
+    // Retrieves the blend shape geometry from the texture, unnormalizes it and multiply by the weight.
+    if( 0.0 != uBlendShapeWeight[index] )
+    {
+#ifdef MORPH_VERSION_2_0
+       float unnormalizeFactor = uBlendShapeUnnormalizeFactor;
+#else
+       float unnormalizeFactor = uBlendShapeUnnormalizeFactor[index];
+#endif
+
+      diff = uBlendShapeWeight[index] * unnormalizeFactor * ( texelFetch( sBlendShapeGeometry, ivec2(x, y), 0 ).xyz - 0.5 );
+    }
+
+    position.xyz += diff;
+
+    blendShapeBufferOffset += uBlendShapeComponentSize;
+#endif
+
+#ifdef MORPH_NORMAL
+    // Calculate the index to retrieve the normal from the texture.
+    vertexId = gl_VertexID + blendShapeBufferOffset;
+    x = vertexId % width;
+    y = vertexId / width;
+
+    // Retrieves the blend shape normal from the texture, unnormalizes it and multiply by the weight.
+    if( 0.0 != uBlendShapeWeight[index] )
+    {
+      diff = uBlendShapeWeight[index] * 2.0 * ( texelFetch( sBlendShapeGeometry, ivec2(x, y), 0 ).xyz - 0.5 );
+    }
+
+    normal += diff.xyz;
+
+    blendShapeBufferOffset += uBlendShapeComponentSize;
+#endif
+
+#ifdef MORPH_TANGENT
+    // Calculate the index to retrieve the tangent from the texture.
+    vertexId = gl_VertexID + blendShapeBufferOffset;
+    x = vertexId % width;
+    y = vertexId / width;
+
+    // Retrieves the blend shape tangent from the texture, unnormalizes it and multiply by the weight.
+    if( 0.0 != uBlendShapeWeight[index] )
+    {
+      diff = uBlendShapeWeight[index] * 2.0 * ( texelFetch( sBlendShapeGeometry, ivec2(x, y), 0 ).xyz - 0.5 );
+    }
+
+    tangent += diff.xyz;
+
+    blendShapeBufferOffset += uBlendShapeComponentSize;
+#endif
+  }
+
+#endif
+
+#ifdef SKINNING
+  mat4 bone = uBone[int(aJoints.x)] * aWeights.x +
+    uBone[int(aJoints.y)] * aWeights.y +
+    uBone[int(aJoints.z)] * aWeights.z +
+    uBone[int(aJoints.w)] * aWeights.w;
+  position = bone * position;
+  normal = (bone * vec4(normal, 0.0)).xyz;
+  tangent = (bone * vec4(tangent, 0.0)).xyz;
+#endif
+
+  vec4 vPosition = uModelMatrix * position;
+
+  vNormal = normalize(uNormalMatrix * normal);
+
+  vTangent = normalize(uNormalMatrix * tangent);
+
+
+  vec4 viewPosition = uViewMatrix * vPosition;
+  gl_Position = uProjection * viewPosition;
+
+#ifdef FLIP_V
+  vUV = vec2(aTexCoord.x, 1.0 - aTexCoord.y);
+#else
+  vUV = aTexCoord;
+#endif
+
+  vViewVec = viewPosition.xyz;
+}
index 923d0e4..be7e538 100644 (file)
@@ -157,7 +157,8 @@ const auto TEXURE_READER = std::move(js::Reader<gt::Texture>()
 const auto TEXURE_INFO_READER = std::move(js::Reader<gt::TextureInfo>()
                                             .Register(*js::MakeProperty("index", gt::RefReader<gt::Document>::Read<gt::Texture, &gt::Document::mTextures>, &gt::TextureInfo::mTexture))
                                             .Register(*js::MakeProperty("texCoord", js::Read::Number<uint32_t>, &gt::TextureInfo::mTexCoord))
-                                            .Register(*js::MakeProperty("scale", js::Read::Number<float>, &gt::TextureInfo::mScale)));
+                                            .Register(*js::MakeProperty("scale", js::Read::Number<float>, &gt::TextureInfo::mScale))
+                                            .Register(*js::MakeProperty("strength", js::Read::Number<float>, &gt::TextureInfo::mStrength)));
 
 const auto MATERIAL_PBR_READER = std::move(js::Reader<gt::Material::Pbr>()
                                              .Register(*js::MakeProperty("baseColorFactor", gt::ReadDaliVector<Vector4>, &gt::Material::Pbr::mBaseColorFactor))
@@ -440,7 +441,7 @@ void ConvertMaterial(const gt::Material& m, decltype(ResourceBundle::mMaterials)
 
   matDef.mColor = pbr.mBaseColorFactor;
 
-  matDef.mTextureStages.reserve(!!pbr.mBaseColorTexture + !!pbr.mMetallicRoughnessTexture + !!m.mNormalTexture);
+  matDef.mTextureStages.reserve(!!pbr.mBaseColorTexture + !!pbr.mMetallicRoughnessTexture + !!m.mNormalTexture + !!m.mOcclusionTexture + !!m.mEmissiveTexture);
   if(pbr.mBaseColorTexture)
   {
     const auto semantic = MaterialDefinition::ALBEDO;
@@ -470,6 +471,23 @@ void ConvertMaterial(const gt::Material& m, decltype(ResourceBundle::mMaterials)
   }
 
   // TODO: handle doubleSided
+  if(m.mOcclusionTexture)
+  {
+    const auto semantic = MaterialDefinition::OCCLUSION;
+    matDef.mTextureStages.push_back({semantic, ConvertTextureInfo(m.mOcclusionTexture)});
+    // TODO: and there had better be one
+    matDef.mFlags |= semantic;
+    matDef.mOcclusionStrength = m.mOcclusionTexture.mStrength;
+  }
+
+  if(m.mEmissiveTexture)
+  {
+    const auto semantic = MaterialDefinition::EMISSIVE;
+    matDef.mTextureStages.push_back({semantic, ConvertTextureInfo(m.mEmissiveTexture)});
+    // TODO: and there had better be one
+    matDef.mFlags |= semantic;
+    matDef.mEmissiveFactor = m.mEmissiveFactor;
+  }
 
   outMaterials.emplace_back(std::move(matDef), TextureSet());
 }
index 3c7a391..1342ced 100644 (file)
@@ -110,7 +110,9 @@ MaterialDefinition::LoadRaw(const std::string& imagesPath) const
   RawData raw;
 
   const bool hasTransparency = MaskMatch(mFlags, TRANSPARENCY);
-  uint32_t   numBuffers      = mTextureStages.size() + (hasTransparency ? !CheckTextures(ALBEDO) + !CheckTextures(METALLIC | ROUGHNESS) + !CheckTextures(NORMAL) : !CheckTextures(ALBEDO | METALLIC) + !CheckTextures(NORMAL | ROUGHNESS));
+  // Why we add additional count here?
+  uint32_t numBuffers = mTextureStages.size() + (hasTransparency ? !CheckTextures(ALBEDO) + !CheckTextures(METALLIC | ROUGHNESS) + !CheckTextures(NORMAL)
+                                                                 : !CheckTextures(ALBEDO | METALLIC) + !CheckTextures(NORMAL | ROUGHNESS));
   if(numBuffers == 0)
   {
     return raw;
@@ -210,7 +212,7 @@ MaterialDefinition::LoadRaw(const std::string& imagesPath) const
     }
   }
 
-  // Extra textures. TODO: emissive, occlusion etc.
+  // Extra textures.
   if(checkStage(SUBSURFACE))
   {
     raw.mTextures.push_back({SyncImageLoader::Load(imagesPath + iTexture->mTexture.mImageUri), iTexture->mTexture.mSamplerFlags});
@@ -223,6 +225,12 @@ MaterialDefinition::LoadRaw(const std::string& imagesPath) const
     ++iTexture;
   }
 
+  if(checkStage(EMISSIVE))
+  {
+    raw.mTextures.push_back({SyncImageLoader::Load(imagesPath + iTexture->mTexture.mImageUri), iTexture->mTexture.mSamplerFlags});
+    ++iTexture;
+  }
+
   return raw;
 }
 
index 80e93e7..e36f74b 100644 (file)
@@ -219,10 +219,12 @@ struct DALI_SCENE_LOADER_API MaterialDefinition
 public: // DATA
   uint32_t mFlags = 0x0;
 
-  Index                     mEnvironmentIdx = 0;
-  Vector4                   mColor          = Color::WHITE;
-  float                     mMetallic       = 1.f;
-  float                     mRoughness      = 1.f;
+  Index                     mEnvironmentIdx    = 0;
+  Vector4                   mColor             = Color::WHITE;
+  Vector3                   mEmissiveFactor    = Vector3::ZERO;
+  float                     mMetallic          = 1.f;
+  float                     mRoughness         = 1.f;
+  float                     mOcclusionStrength = 1.f;
   std::vector<TextureStage> mTextureStages;
 };
 
index 45e0b23..e8f6b82 100644 (file)
@@ -153,6 +153,14 @@ void ModelNode::OnCreate(const NodeDefinition& node, NodeDefinition::CreateParam
   auto& matDef = resources.mMaterials[mMaterialIdx].first;
   actor.RegisterProperty("uMetallicFactor", matDef.mMetallic);
   actor.RegisterProperty("uRoughnessFactor", matDef.mRoughness);
+  if(matDef.mFlags & MaterialDefinition::OCCLUSION)
+  {
+    actor.RegisterProperty("uOcclusionStrength", matDef.mOcclusionStrength);
+  }
+  if(matDef.mFlags & MaterialDefinition::EMISSIVE)
+  {
+    actor.RegisterProperty("uEmissiveFactor", matDef.mEmissiveFactor);
+  }
 
   Index envIdx = matDef.mEnvironmentIdx;
   actor.RegisterProperty("uIblIntensity", resources.mEnvironmentMaps[envIdx].first.mIblIntensity);
index bd6b168..6f9ab4e 100644 (file)
@@ -56,8 +56,6 @@ struct ResourceReceiver : IResourceReceiver
   }
 };
 
-const std::string PBR_SHADER_NAME = "dli_pbr";
-
 void RetrieveBlendShapeComponents(const std::vector<MeshDefinition::BlendShape>& blendShapes, bool& hasPositions, bool& hasNormals, bool& hasTangents)
 {
   for(const auto& blendShape : blendShapes)
@@ -72,9 +70,6 @@ uint64_t HashNode(const NodeDefinition& nodeDef, const MaterialDefinition& mater
 {
   Hash hash;
 
-  // note: could be per vertex / fragment component - in WatchViewer, these have the same name.
-  hash.Add(PBR_SHADER_NAME);
-
   const bool hasTransparency = MaskMatch(materialDef.mFlags, MaterialDefinition::TRANSPARENCY);
   hash.Add(hasTransparency);
 
@@ -101,6 +96,11 @@ uint64_t HashNode(const NodeDefinition& nodeDef, const MaterialDefinition& mater
     hash.Add("OCCL" /*USION*/);
   }
 
+  if(MaskMatch(materialDef.mFlags, MaterialDefinition::EMISSIVE))
+  {
+    hash.Add("EMIS" /*SIVE*/);
+  }
+
   if(MaskMatch(materialDef.mFlags, MaterialDefinition::GLTF_CHANNELS))
   {
     hash.Add("GLTF" /*_CHANNELS*/);
@@ -192,8 +192,7 @@ Index ShaderDefinitionFactory::ProduceShader(const NodeDefinition& nodeDef)
   }
 
   ShaderDefinition shaderDef;
-  shaderDef.mVertexShaderPath   = PBR_SHADER_NAME + ".vsh";
-  shaderDef.mFragmentShaderPath = PBR_SHADER_NAME + ".fsh";
+  shaderDef.mUseBuiltInShader = true;
   shaderDef.mRendererState      = RendererState::DEPTH_TEST | RendererState::DEPTH_WRITE | RendererState::CULL_BACK;
 
   auto&      materialDef     = *receiver.mMaterialDef;
@@ -222,12 +221,17 @@ Index ShaderDefinitionFactory::ProduceShader(const NodeDefinition& nodeDef)
     shaderDef.mDefines.push_back("SSS");
   }
 
-  if(MaskMatch(receiver.mMaterialDef->mFlags, MaterialDefinition::OCCLUSION))
+  if(MaskMatch(materialDef.mFlags, MaterialDefinition::OCCLUSION))
   {
     shaderDef.mDefines.push_back("OCCLUSION");
   }
 
-  if(MaskMatch(receiver.mMaterialDef->mFlags, MaterialDefinition::GLTF_CHANNELS))
+  if(MaskMatch(materialDef.mFlags, MaterialDefinition::EMISSIVE))
+  {
+    shaderDef.mDefines.push_back("EMISSIVE");
+  }
+
+  if(MaskMatch(materialDef.mFlags, MaterialDefinition::GLTF_CHANNELS))
   {
     shaderDef.mDefines.push_back("GLTF_CHANNELS");
   }
index 73c18ba..71024f3 100644 (file)
@@ -18,6 +18,7 @@
 // INTERNAL INCLUDES
 #include "dali-scene-loader/public-api/shader-definition.h"
 #include "dali-scene-loader/public-api/utils.h"
+#include <dali-scene-loader/internal/graphics/builtin-shader-extern-gen.h>
 
 namespace Dali
 {
@@ -36,7 +37,8 @@ ShaderDefinition::ShaderDefinition(const ShaderDefinition& other)
   mFragmentShaderPath(other.mFragmentShaderPath),
   mDefines(other.mDefines),
   mHints(other.mHints),
-  mUniforms(other.mUniforms)
+  mUniforms(other.mUniforms),
+  mUseBuiltInShader(false)
 {
 }
 
@@ -80,28 +82,38 @@ ShaderDefinition::LoadRaw(const std::string& shadersPath) const
 {
   RawData raw;
 
-  bool fail               = false;
-  raw.mVertexShaderSource = LoadTextFile((shadersPath + mVertexShaderPath).c_str(), &fail);
-  if(!fail)
+  bool fail = false;
+  if(!mUseBuiltInShader)
   {
-    raw.mFragmentShaderSource = LoadTextFile((shadersPath + mFragmentShaderPath).c_str(), &fail);
+    raw.mVertexShaderSource = LoadTextFile((shadersPath + mVertexShaderPath).c_str(), &fail);
     if(!fail)
     {
-      for(auto definevar : mDefines)
+      raw.mFragmentShaderSource = LoadTextFile((shadersPath + mFragmentShaderPath).c_str(), &fail);
+      if(fail)
       {
-        ApplyDefine(raw.mVertexShaderSource, definevar);
-        ApplyDefine(raw.mFragmentShaderSource, definevar);
+        ExceptionFlinger(ASSERT_LOCATION) << "Failed to load shader source from '" << shadersPath + mFragmentShaderPath << "'.";
       }
     }
     else
     {
-      ExceptionFlinger(ASSERT_LOCATION) << "Failed to load shader source from '" << shadersPath + mFragmentShaderPath << "'.";
+      ExceptionFlinger(ASSERT_LOCATION) << "Failed to load shader source from '" << shadersPath + mVertexShaderPath << "'.";
     }
   }
   else
   {
-    ExceptionFlinger(ASSERT_LOCATION) << "Failed to load shader source from '" << shadersPath + mVertexShaderPath << "'.";
+    raw.mVertexShaderSource   = SHADER_DEFAULT_PHYSICALLY_BASED_SHADER_VERT.data();
+    raw.mFragmentShaderSource = SHADER_DEFAULT_PHYSICALLY_BASED_SHADER_FRAG.data();
+  }
+
+  if(!fail)
+  {
+    for(auto definevar : mDefines)
+    {
+      ApplyDefine(raw.mVertexShaderSource, definevar);
+      ApplyDefine(raw.mFragmentShaderSource, definevar);
+    }
   }
+
   return raw;
 }
 
index d7f390b..5d0a49e 100644 (file)
@@ -79,8 +79,8 @@ public: // DATA
   std::string              mFragmentShaderPath;
   std::vector<std::string> mDefines;
   std::vector<std::string> mHints;
-
-  Property::Map mUniforms;
+  Property::Map            mUniforms;
+  bool                     mUseBuiltInShader;
 };
 
 } // namespace SceneLoader