Use Mipmap level to sample specular texture 53/290053/6
authorseungho baek <sbsh.baek@samsung.com>
Fri, 17 Mar 2023 14:02:17 +0000 (23:02 +0900)
committerseungho baek <sbsh.baek@samsung.com>
Sat, 18 Mar 2023 06:20:30 +0000 (15:20 +0900)
Change-Id: If1f4346b22571600d490150bd05bf851eefe1a24
Signed-off-by: seungho baek <sbsh.baek@samsung.com>
19 files changed:
dali-scene3d/internal/common/environment-map-load-task.cpp
dali-scene3d/internal/common/environment-map-load-task.h
dali-scene3d/internal/common/image-based-light-observer.h
dali-scene3d/internal/controls/model/model-impl.cpp
dali-scene3d/internal/controls/model/model-impl.h
dali-scene3d/internal/controls/scene-view/scene-view-impl.cpp
dali-scene3d/internal/controls/scene-view/scene-view-impl.h
dali-scene3d/internal/graphics/shaders/default-physically-based-shader.frag
dali-scene3d/public-api/controls/model/model.cpp
dali-scene3d/public-api/controls/model/model.h
dali-scene3d/public-api/controls/scene-view/scene-view.h
dali-scene3d/public-api/loader/environment-definition.cpp
dali-scene3d/public-api/loader/environment-definition.h
dali-scene3d/public-api/loader/environment-map-data.h
dali-scene3d/public-api/loader/environment-map-loader.cpp
dali-scene3d/public-api/loader/ktx-loader.cpp
dali-scene3d/public-api/loader/node-definition.cpp
dali-scene3d/public-api/loader/node-definition.h
dali-scene3d/public-api/loader/shader-definition-factory.cpp

index 5ff0d51..6b5f5fb 100644 (file)
@@ -61,6 +61,11 @@ Dali::Texture EnvironmentMapLoadTask::GetLoadedTexture()
   return (HasSucceeded()) ? mEnvironmentMapData.GetTexture() : Texture();
 }
 
+uint32_t EnvironmentMapLoadTask::GetMipmapLevels()
+{
+  return (HasSucceeded()) ? mEnvironmentMapData.GetMipmapLevels() : 1u;
+}
+
 } // namespace Internal
 
 } // namespace Scene3D
index 446665c..0bb134f 100644 (file)
@@ -77,6 +77,12 @@ public:
    */
   Dali::Texture GetLoadedTexture();
 
+  /**
+   * Retrieves Mipmap levels of loaded Ibl texture
+   * @return mipmap levels of loaded Ibl texture
+   */
+  uint32_t GetMipmapLevels();
+
 private:
   // Undefined
   EnvironmentMapLoadTask(const EnvironmentMapLoadTask& task) = delete;
index 16bcf32..f9f1e06 100644 (file)
@@ -47,8 +47,9 @@ public:
    * @param[in] diffuseTexture cube map texture that can be used as a diffuse IBL source.
    * @param[in] specularTexture cube map texture that can be used as a specular IBL source.
    * @param[in] scaleFactor scale factor that controls light source intensity in [0.0f, 1.0f]. Default value is 1.0f.
+   * @param[in] specularMipmapLevels mipmap levels of specular texture
    */
-  virtual void NotifyImageBasedLightTexture(Dali::Texture diffuseTexture, Dali::Texture specularTexture, float scaleFactor) = 0;
+  virtual void NotifyImageBasedLightTexture(Dali::Texture diffuseTexture, Dali::Texture specularTexture, float scaleFactor, uint32_t specularMipmapLevels) = 0;
 
   /**
    * @brief Notifies Scale Factor of Image Based Light is changed by parent SceneView.
index 5aa4a5f..27e8bc8 100644 (file)
@@ -180,6 +180,8 @@ Model::Model(const std::string& modelUrl, const std::string& resourceDirectoryUr
   mModelPivot(AnchorPoint::CENTER),
   mSceneIblScaleFactor(1.0f),
   mIblScaleFactor(1.0f),
+  mSceneSpecularMipmapLevels(1u),
+  mSpecularMipmapLevels(1u),
   mModelChildrenSensitive(DEFAULT_MODEL_CHILDREN_SENSITIVE),
   mModelChildrenFocusable(DEFAULT_MODEL_CHILDREN_FOCUSABLE),
   mModelResourceReady(false),
@@ -330,18 +332,6 @@ void Model::SetImageBasedLightSource(const std::string& diffuseUrl, const std::s
   NotifyResourceReady();
 }
 
-void Model::SetImageBasedLightTexture(Dali::Texture diffuseTexture, Dali::Texture specularTexture, float scaleFactor)
-{
-  // If input texture is wrong, Model is rendered with SceneView's IBL.
-  if(mDiffuseTexture != diffuseTexture || mSpecularTexture != specularTexture)
-  {
-    mDiffuseTexture  = diffuseTexture;
-    mSpecularTexture = specularTexture;
-    mIblScaleFactor  = scaleFactor;
-    UpdateImageBasedLightTexture();
-  }
-}
-
 void Model::SetImageBasedLightScaleFactor(float scaleFactor)
 {
   mIblScaleFactor = scaleFactor;
@@ -566,15 +556,17 @@ void Model::CollectRenderableActor(Actor actor)
 
 void Model::UpdateImageBasedLightTexture()
 {
-  Dali::Texture currentDiffuseTexture  = (mDiffuseTexture && mSpecularTexture) ? mDiffuseTexture : mSceneDiffuseTexture;
-  Dali::Texture currentSpecularTexture = (mDiffuseTexture && mSpecularTexture) ? mSpecularTexture : mSceneSpecularTexture;
-  float         currentIblScaleFactor  = (mDiffuseTexture && mSpecularTexture) ? mIblScaleFactor : mSceneIblScaleFactor;
+  Dali::Texture currentDiffuseTexture          = (mDiffuseTexture && mSpecularTexture) ? mDiffuseTexture : mSceneDiffuseTexture;
+  Dali::Texture currentSpecularTexture         = (mDiffuseTexture && mSpecularTexture) ? mSpecularTexture : mSceneSpecularTexture;
+  float         currentIblScaleFactor          = (mDiffuseTexture && mSpecularTexture) ? mIblScaleFactor : mSceneIblScaleFactor;
+  uint32_t      currentIblSpecularMipmapLevels = (mDiffuseTexture && mSpecularTexture) ? mSpecularMipmapLevels : mSceneSpecularMipmapLevels;
 
   if(!currentDiffuseTexture || !currentSpecularTexture)
   {
-    currentDiffuseTexture  = mDefaultDiffuseTexture;
-    currentSpecularTexture = mDefaultSpecularTexture;
-    currentIblScaleFactor  = Dali::Scene3D::Loader::EnvironmentDefinition::GetDefaultIntensity();
+    currentDiffuseTexture          = mDefaultDiffuseTexture;
+    currentSpecularTexture         = mDefaultSpecularTexture;
+    currentIblScaleFactor          = Dali::Scene3D::Loader::EnvironmentDefinition::GetDefaultIntensity();
+    currentIblSpecularMipmapLevels = 1u;
   }
 
   for(auto&& actor : mRenderableActors)
@@ -626,6 +618,7 @@ void Model::UpdateImageBasedLightTexture()
       }
     }
     renderableActor.RegisterProperty(Dali::Scene3D::Loader::NodeDefinition::GetIblScaleFactorUniformName().data(), currentIblScaleFactor);
+    renderableActor.RegisterProperty(Dali::Scene3D::Loader::NodeDefinition::GetIblMaxLodUniformName().data(), static_cast<float>(currentIblSpecularMipmapLevels));
   }
 }
 
@@ -687,13 +680,14 @@ void Model::ApplyCameraTransform(Dali::CameraActor camera) const
   camera.SetProperty(Actor::Property::SCALE, resultScale);
 }
 
-void Model::NotifyImageBasedLightTexture(Dali::Texture diffuseTexture, Dali::Texture specularTexture, float scaleFactor)
+void Model::NotifyImageBasedLightTexture(Dali::Texture diffuseTexture, Dali::Texture specularTexture, float scaleFactor, uint32_t specularMipmapLevels)
 {
   if(mSceneDiffuseTexture != diffuseTexture || mSceneSpecularTexture != specularTexture)
   {
-    mSceneDiffuseTexture  = diffuseTexture;
-    mSceneSpecularTexture = specularTexture;
-    mSceneIblScaleFactor  = scaleFactor;
+    mSceneDiffuseTexture       = diffuseTexture;
+    mSceneSpecularTexture      = specularTexture;
+    mSceneIblScaleFactor       = scaleFactor;
+    mSceneSpecularMipmapLevels = specularMipmapLevels;
     // If Model IBL is not set, use SceneView's IBL.
     if(!mDiffuseTexture || !mSpecularTexture)
     {
@@ -767,7 +761,8 @@ void Model::OnIblDiffuseLoadComplete()
 
 void Model::OnIblSpecularLoadComplete()
 {
-  mSpecularTexture = mIblSpecularLoadTask->GetLoadedTexture();
+  mSpecularTexture      = mIblSpecularLoadTask->GetLoadedTexture();
+  mSpecularMipmapLevels = mIblSpecularLoadTask->GetMipmapLevels();
   ResetResourceTask(mIblSpecularLoadTask);
   mIblSpecularResourceReady = true;
   if(mIblDiffuseResourceReady && mIblSpecularResourceReady)
index 939de84..e5e36d9 100644 (file)
@@ -87,11 +87,6 @@ public:
   void SetImageBasedLightSource(const std::string& diffuseUrl, const std::string& specularUrl, float scaleFactor);
 
   /**
-   * @copydoc Model::SetImageBasedLightTexture()
-   */
-  void SetImageBasedLightTexture(Dali::Texture diffuseTexture, Dali::Texture specularTexture, float scaleFactor);
-
-  /**
    * @copydoc Model::SetImageBasedLightScaleFactor()
    */
   void SetImageBasedLightScaleFactor(float scaleFactor);
@@ -224,7 +219,7 @@ public: // Overrides ImageBasedLightObserver Methods.
   /**
    * @copydoc Dali::Scene3D::Internal::ImageBasedLightObserver::NotifyImageBasedLightTexture()
    */
-  void NotifyImageBasedLightTexture(Dali::Texture diffuseTexture, Dali::Texture specularTexture, float scaleFactor) override;
+  void NotifyImageBasedLightTexture(Dali::Texture diffuseTexture, Dali::Texture specularTexture, float scaleFactor, uint32_t specularMipmapLevels) override;
 
   /**
    * @copydoc Dali::Scene3D::Internal::ImageBasedLightObserver::NotifyImageBasedLightScaleFactor()
@@ -310,6 +305,8 @@ private:
   Vector3       mModelPivot;
   float         mSceneIblScaleFactor;
   float         mIblScaleFactor;
+  uint32_t      mSceneSpecularMipmapLevels;
+  uint32_t      mSpecularMipmapLevels;
   bool          mModelChildrenSensitive;
   bool          mModelChildrenFocusable;
   bool          mModelResourceReady;
index a4158e1..946eb98 100644 (file)
@@ -277,7 +277,7 @@ void SceneView::RegisterSceneItem(Scene3D::Internal::ImageBasedLightObserver* it
 {
   if(item)
   {
-    item->NotifyImageBasedLightTexture(mDiffuseTexture, mSpecularTexture, mIblScaleFactor);
+    item->NotifyImageBasedLightTexture(mDiffuseTexture, mSpecularTexture, mIblScaleFactor, mSpecularMipmapLevels);
     mItems.push_back(item);
   }
 }
@@ -353,6 +353,7 @@ void SceneView::SetImageBasedLightSource(const std::string& diffuseUrl, const st
     mDiffuseTexture.Reset();
     mSpecularTexture.Reset();
 
+    mSpecularMipmapLevels = 1u;
     NotifyImageBasedLightTextureChange();
   }
   else
@@ -826,6 +827,7 @@ void SceneView::OnIblDiffuseLoadComplete()
 void SceneView::OnIblSpecularLoadComplete()
 {
   mSpecularTexture          = mIblSpecularLoadTask->GetLoadedTexture();
+  mSpecularMipmapLevels     = mIblSpecularLoadTask->GetMipmapLevels();
   mIblSpecularResourceReady = true;
   if(mIblDiffuseResourceReady && mIblSpecularResourceReady)
   {
@@ -849,7 +851,7 @@ void SceneView::NotifyImageBasedLightTextureChange()
   {
     if(item)
     {
-      item->NotifyImageBasedLightTexture(mDiffuseTexture, mSpecularTexture, mIblScaleFactor);
+      item->NotifyImageBasedLightTexture(mDiffuseTexture, mSpecularTexture, mIblScaleFactor, mSpecularMipmapLevels);
     }
   }
 }
index 8b175fe..d9377ff 100644 (file)
@@ -323,6 +323,7 @@ private:
   Dali::Texture               mDiffuseTexture;
   Dali::Texture               mSpecularTexture;
   float                       mIblScaleFactor{1.0f};
+  uint32_t                    mSpecularMipmapLevels{1u};
   bool                        mUseFrameBuffer{false};
   bool                        mSkyboxResourceReady{true};
   bool                        mIblDiffuseResourceReady{true};
index c0ef6de..1579866 100644 (file)
@@ -78,6 +78,7 @@ uniform samplerCube sDiffuseEnvSampler;
 uniform samplerCube sSpecularEnvSampler;
 uniform float uIblIntensity;
 uniform vec3 uYDirection;
+uniform float uMaxLOD;
 
 // For Alpha Mode.
 uniform lowp float uOpaque;
@@ -194,7 +195,9 @@ void main()
   vec3 FssEss = specularWeight * (k_S * brdf.x + brdf.y);
 
   // Specular Light
-  lowp vec3 specularLight = linear(texture(sSpecularEnvSampler, reflection * uYDirection).rgb);
+  // uMaxLOD that means mipmap level of specular texture is used for bluring of reflection of specular following roughness.
+  float lod = perceptualRoughness * (uMaxLOD - 1.0);
+  lowp vec3 specularLight = linear(textureLod(sSpecularEnvSampler, reflection * uYDirection, lod).rgb);
   lowp vec3 specular = specularLight * FssEss;
 
   // Diffuse Light
index fa792f9..6f01a44 100644 (file)
@@ -92,11 +92,6 @@ void Model::SetImageBasedLightSource(const std::string& diffuseUrl, const std::s
   GetImpl(*this).SetImageBasedLightSource(diffuseUrl, specularUrl, scaleFactor);
 }
 
-void Model::SetImageBasedLightTexture(Texture diffuseTexture, Texture specularTexture, float scaleFactor)
-{
-  GetImpl(*this).SetImageBasedLightTexture(diffuseTexture, specularTexture, scaleFactor);
-}
-
 void Model::SetImageBasedLightScaleFactor(float scaleFactor)
 {
   GetImpl(*this).SetImageBasedLightScaleFactor(scaleFactor);
index da3f7a6..39e7723 100644 (file)
@@ -212,22 +212,10 @@ public:
   void SetImageBasedLightSource(const std::string& diffuseUrl, const std::string& specularUrl, float scaleFactor = 1.0f);
 
   /**
-   * @brief Sets Image Based Light Texture.
-   *
-   * @SINCE_2_1.41
-   * @param[in] diffuseTexture cube map texture that can be used as a diffuse IBL source.
-   * @param[in] specularTexture cube map texture that can be used as a specular IBL source.
-   * @param[in] scaleFactor scale factor that controls light source intensity in [0.0f, 1.0f]. Default value is 1.0f.
-   *
-   * @note Both of diffuse texture and specular texture should be available. If not, nothing applied.
-   */
-  void SetImageBasedLightTexture(Texture diffuseTexture, Texture specularTexture, float scaleFactor = 1.0f);
-
-  /**
    * @brief Sets Scale Factor of Image Based Light Source.
    *
    * @SINCE_2_1.41
-   * @note If SetImageBasedLightSource() or SetImageBasedLightTexture() method is called after this method, scaleFactor is overrided.
+   * @note If SetImageBasedLightSource() method is called after this method, scaleFactor is overrided.
    *
    * @param[in] scaleFactor scale factor that controls light source intensity in [0.0f, 1.0f].
    */
index f64715d..3866879 100644 (file)
@@ -278,7 +278,7 @@ public:
    * @brief Sets Scale Factor of Image Based Light Source.
    *
    * @SINCE_2_1.41
-   * @note If SetImageBasedLightSource() or SetImageBasedLightTexture() method is called after this method, scaleFactor is overriden.
+   * @note If SetImageBasedLightSource() method is called after this method, scaleFactor is overriden.
    * @note Default value is 1.0f.
    *
    * @param[in] scaleFactor scale factor that controls light source intensity in [0.0f, 1.0f].
index 16ec2df..5f4605e 100644 (file)
@@ -91,7 +91,8 @@ EnvironmentDefinition::Textures EnvironmentDefinition::Load(RawData&& raw) const
   // This texture should have 6 faces and 6 mipmaps
   if(!raw.mSpecular.mPixelData.empty())
   {
-    textures.mSpecular = raw.mSpecular.GetTexture();
+    textures.mSpecular             = raw.mSpecular.GetTexture();
+    textures.mSpecularMipmapLevels = raw.mSpecular.GetMipmapLevels();
   }
 
   if(raw.mBrdf)
index 3c4ceee..577a31f 100644 (file)
@@ -36,9 +36,10 @@ struct DALI_SCENE3D_API EnvironmentDefinition
 {
   struct Textures
   {
-    Texture mDiffuse;  // irradiance
-    Texture mSpecular; // radiance
-    Texture mBrdf;     // pre-computed brdf
+    Texture  mDiffuse;  // irradiance
+    Texture  mSpecular; // radiance
+    Texture  mBrdf;     // pre-computed brdf
+    uint32_t mSpecularMipmapLevels{1u};
 
     bool IsLoaded() const
     {
index 2feac5b..6d53cbc 100644 (file)
@@ -65,6 +65,16 @@ public:
     return mEnvironmentMapType;
   }
 
+  void SetMipmapLevels(uint32_t mipmapLevels)
+  {
+    mMipmapLevels = mipmapLevels;
+  }
+
+  uint32_t GetMipmapLevels()
+  {
+    return mMipmapLevels;
+  }
+
 public:
   std::vector<std::vector<PixelData> > mPixelData;
 
@@ -72,6 +82,7 @@ private:
   Dali::Texture                     mEnvironmentMapTexture;
   Dali::Shader                      mEnvironmentMapShader;
   Dali::Scene3D::EnvironmentMapType mEnvironmentMapType{Dali::Scene3D::EnvironmentMapType::AUTO};
+  uint32_t                          mMipmapLevels{1u};
 };
 
 } // namespace Dali::Scene3D::Loader
index 7abff75..306d3b2 100644 (file)
@@ -21,6 +21,7 @@
 // EXTERNAL INCLUDES
 #include <dali/devel-api/adaptor-framework/image-loading.h>
 #include <string.h>
+#include <cmath>
 #include <filesystem>
 
 // INTERNAL INCLUDES
@@ -168,6 +169,8 @@ bool LoadEnvironmentMapData(const std::string& environmentMapUrl, Scene3D::Loade
       {
         environmentMapData.mPixelData[i][0] = GetCubeFace(pixelBuffer, i, cubeType, faceWidth, faceHeight);
       }
+      uint32_t mipmap = static_cast<uint32_t>(1 + std::floor(std::log2(std::max(environmentMapData.mPixelData[0][0].GetWidth(), environmentMapData.mPixelData[0][0].GetHeight()))));
+      environmentMapData.SetMipmapLevels(mipmap);
       environmentMapData.SetEnvironmentMapType(Scene3D::EnvironmentMapType::CUBEMAP);
     }
     else
@@ -193,7 +196,9 @@ bool LoadEnvironmentMap(const std::string& environmentMapUrl, EnvironmentMapData
   std::string           extension = modelPath.extension();
   std::transform(extension.begin(), extension.end(), extension.begin(), ::tolower);
 
-  return (extension == KTX_EXTENSION) ? Dali::Scene3D::Loader::LoadKtxData(environmentMapUrl, environmentMapData) : LoadEnvironmentMapData(environmentMapUrl, environmentMapData);
+  bool successed = (extension == KTX_EXTENSION) ? Dali::Scene3D::Loader::LoadKtxData(environmentMapUrl, environmentMapData) : LoadEnvironmentMapData(environmentMapUrl, environmentMapData);
+
+  return successed;
 }
 
 } // namespace Loader
index 2261ff8..66e15e2 100644 (file)
@@ -214,6 +214,7 @@ bool LoadKtxData(const std::string& path, EnvironmentMapData& environmentMapData
   header.numberOfArrayElements = std::max(header.numberOfArrayElements, 1u);
   header.pixelDepth            = std::max(header.pixelDepth, 1u);
   header.pixelHeight           = std::max(header.pixelHeight, 1u);
+  environmentMapData.SetMipmapLevels(header.numberOfMipmapLevels);
 
   environmentMapData.mPixelData.resize(header.numberOfFaces);
   for(uint32_t face = 0u; face < header.numberOfFaces; ++face)
index f110150..833d489 100644 (file)
@@ -28,6 +28,7 @@ namespace
 {
 constexpr std::string_view IBL_INTENSITY_STRING("uIblIntensity");
 constexpr std::string_view IBL_Y_DIRECTION("uYDirection");
+constexpr std::string_view IBL_MAXLOD("uMaxLOD");
 } // namespace
 
 namespace Scene3D
@@ -118,6 +119,11 @@ std::string_view NodeDefinition::GetIblYDirectionUniformName()
   return IBL_Y_DIRECTION;
 }
 
+std::string_view NodeDefinition::GetIblMaxLodUniformName()
+{
+  return IBL_MAXLOD;
+}
+
 bool NodeDefinition::GetExtents(const ResourceBundle& resources, Vector3& min, Vector3& max) const
 {
   if(mRenderables.empty())
@@ -260,7 +266,9 @@ void ModelRenderable::OnCreate(const NodeDefinition& node, NodeDefinition::Creat
 
   renderer.SetTextures(textures);
 
+  uint32_t specularMipmap = resources.mEnvironmentMaps[envIdx].second.mSpecularMipmapLevels;
   actor.SetProperty(Actor::Property::COLOR, mColor);
+  actor.RegisterProperty(IBL_MAXLOD.data(), static_cast<float>(specularMipmap));
 }
 
 void ArcRenderable::OnCreate(const NodeDefinition& node, NodeDefinition::CreateParams& params, Actor& actor) const
index 7474a5f..f73d39b 100644 (file)
@@ -249,6 +249,13 @@ public: // METHODS
    */
   static std::string_view GetIblYDirectionUniformName();
 
+  /**
+   * @brief Retrieves ibl MaxLod uniform name.
+   * This uniform name can be used to set max lod of ibl in shader.
+   * @return std::string_view of the Max Lod uniform name.
+   */
+  static std::string_view GetIblMaxLodUniformName();
+
 public: // DATA
   static const char* ORIGINAL_MATRIX_PROPERTY_NAME;
 
index 5db7ab0..6a0bf8a 100644 (file)
@@ -363,7 +363,6 @@ Index ShaderDefinitionFactory::ProduceShader(NodeDefinition::Renderable& rendera
       }
     }
 
-    shaderDef.mUniforms["uMaxLOD"]     = 6.f;
     shaderDef.mUniforms["uCubeMatrix"] = Matrix::IDENTITY;
 
     Index result    = resources.mShaders.size();