[dali_2.2.6] Merge branch 'devel/master'
[platform/core/uifw/dali-demo.git] / examples / rendering-skybox / rendering-skybox.cpp
index d2d0f29..d6bf994 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2020 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2022 Samsung Electronics Co., Ltd.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
 #include <dali-toolkit/dali-toolkit.h>
 #include <dali/dali.h>
 
+#include "generated/rendering-skybox-cube-frag.h"
+#include "generated/rendering-skybox-cube-vert.h"
+#include "generated/rendering-skybox-equirectangular-frag.h"
+#include "generated/rendering-skybox-frag.h"
+#include "generated/rendering-skybox-vert.h"
 #include "look-camera.h"
 
 using namespace Dali;
@@ -25,77 +30,6 @@ using namespace Toolkit;
 
 namespace
 {
-// clang-format off
-/*
- * Vertex shader for a textured cube
- */
-const char* VERTEX_SHADER_CUBE = DALI_COMPOSE_SHADER(
-attribute mediump vec3 aPosition;\n // DALi shader builtin
-attribute mediump vec2 aTexCoord;\n // DALi shader builtin
-uniform   mediump mat4 uMvpMatrix;\n // DALi shader builtin
-uniform   mediump vec3 uSize;\n // DALi shader builtin
-\n
-varying mediump vec2 vTexCoord;\n
-void main()\n
-{\n
-  mediump vec4 vertexPosition = vec4(aPosition, 1.0);\n
-  vertexPosition.xyz *= uSize;\n
-  vTexCoord = aTexCoord;\n
-  gl_Position = uMvpMatrix * vertexPosition;\n
-}\n
-);
-
-/*
- * Fragment shader for a textured cube
- */
-const char* FRAGMENT_SHADER_CUBE = DALI_COMPOSE_SHADER(
-uniform sampler2D uTexture;\n
-\n
-varying mediump vec2 vTexCoord;\n
-void main()\n
-{\n
-  mediump vec4 texColor = texture2D( uTexture, vTexCoord );\n
-  gl_FragColor = texColor;\n
-}\n
-);
-
-/*
- * Vertex shader for a skybox
- */
-const char* VERTEX_SHADER_SKYBOX = DALI_COMPOSE_SHADER(
-attribute mediump vec3 aPosition;\n // DALi shader builtin
-uniform   mediump mat4 uMvpMatrix;\n // DALi shader builtin
-\n
-varying mediump vec3 vTexCoord;\n
-void main()\n
-{\n
-  vTexCoord.x =  aPosition.x;\n
-  vTexCoord.y = -aPosition.y;\n // convert to GL coords
-  vTexCoord.z =  aPosition.z;\n
-
-  mediump vec4 vertexPosition = vec4(aPosition, 1.0);\n
-  vec4 clipSpacePosition = uMvpMatrix * vertexPosition;\n
-  gl_Position = clipSpacePosition.xyww;\n // Writes 1.0, the maximum depth value, into the depth buffer.
-                                          // This is an optimization to avoid running the fragment shader
-                                          // for the pixels hidden by the scene's objects.
-}\n
-);
-
-/*
- * Fragment shader for a skybox
- */
-const char* FRAGMENT_SHADER_SKYBOX = DALI_COMPOSE_SHADER(
-uniform samplerCube uSkyBoxTexture;\n
-\n
-varying mediump vec3 vTexCoord;\n
-void main()\n
-{\n
-  mediump vec4 texColor = textureCube( uSkyBoxTexture, vTexCoord );\n
-  gl_FragColor = texColor;\n
-}\n
-);
-// clang-format on
-
 const float   CAMERA_DEFAULT_FOV(60.0f);
 const float   CAMERA_DEFAULT_NEAR(0.1f);
 const float   CAMERA_DEFAULT_FAR(1000.0f);
@@ -107,6 +41,15 @@ const unsigned int SKYBOX_FACE_COUNT  = 6;
 const unsigned int SKYBOX_FACE_WIDTH  = 2048;
 const unsigned int SKYBOX_FACE_HEIGHT = 2048;
 
+/**
+ * @brief The skybox types supported by the application.
+ */
+enum class SkyboxType
+{
+  CUBEMAP,        ///< Skybox in cubemap
+  EQUIRECTANGULAR ///< Skybox in equirectangular projection
+};
+
 /*
  * Credit to Joey do Vries for the following cubemap images
  * Take from git://github.com/JoeyDeVries/LearnOpenGL.git
@@ -122,6 +65,13 @@ const char* SKYBOX_FACES[SKYBOX_FACE_COUNT] =
     DEMO_IMAGE_DIR "lake_back.jpg",
     DEMO_IMAGE_DIR "lake_front.jpg"};
 
+/*
+ * Take from Wikimedia Commons, the free media repository
+ * https://commons.wikimedia.org
+ * The image is licensed under the terms of the CC BY-SA 4.0 license:
+ * https://creativecommons.org/licenses/by-sa/4.0
+ */
+const char* EQUIRECTANGULAR_TEXTURE_URL = DEMO_IMAGE_DIR "veste_oberhaus_spherical_panoramic.jpg";
 } // namespace
 
 // This example shows how to create a skybox
@@ -132,7 +82,8 @@ class TexturedCubeController : public ConnectionTracker
 {
 public:
   TexturedCubeController(Application& application)
-  : mApplication(application)
+  : mApplication(application),
+    mCurrentSkyboxType(SkyboxType::CUBEMAP)
   {
     // Connect to the Application's Init signal
     mApplication.InitSignal().Connect(this, &TexturedCubeController::Create);
@@ -168,13 +119,18 @@ public:
     //         The depth test is enabled, the shader sets 1.0, which is the maximum depth and
     //         the depth function is set to LESS or EQUAL so the fragment shader will run only
     //         in those pixels that any other object has written on them.
-    DisplaySkybox();
+    DisplaySkybox(mCurrentSkyboxType);
 
     // Step 6. Play animation to rotate the cube
     PlayAnimation();
 
     // Respond to key events
     window.KeyEventSignal().Connect(this, &TexturedCubeController::OnKeyEvent);
+
+    // Create a tap gesture detector to detect double tap
+    mDoubleTapGesture = TapGestureDetector::New(2);
+    mDoubleTapGesture.Attach(window.GetRootLayer());
+    mDoubleTapGesture.DetectedSignal().Connect(this, &TexturedCubeController::OnDoubleTap);
   }
 
   /**
@@ -194,6 +150,20 @@ public:
     }
   }
 
+  void OnDoubleTap(Actor /*actor*/, const TapGesture& /*gesture*/)
+  {
+    if(mCurrentSkyboxType == SkyboxType::CUBEMAP)
+    {
+      mCurrentSkyboxType = SkyboxType::EQUIRECTANGULAR;
+    }
+    else
+    {
+      mCurrentSkyboxType = SkyboxType::CUBEMAP;
+    }
+
+    DisplaySkybox(mCurrentSkyboxType);
+  }
+
   /**
    * @brief Setup a perspective camera pointing in the negative Z direction
    */
@@ -215,8 +185,9 @@ public:
    */
   void CreateShaders()
   {
-    mShaderCube   = Shader::New(VERTEX_SHADER_CUBE, FRAGMENT_SHADER_CUBE);
-    mShaderSkybox = Shader::New(VERTEX_SHADER_SKYBOX, FRAGMENT_SHADER_SKYBOX);
+    mShaderCube                  = Shader::New(SHADER_RENDERING_SKYBOX_CUBE_VERT, SHADER_RENDERING_SKYBOX_CUBE_FRAG);
+    mShaderSkybox                = Shader::New(SHADER_RENDERING_SKYBOX_VERT, SHADER_RENDERING_SKYBOX_FRAG);
+    mShaderSkyboxEquirectangular = Shader::New(SHADER_RENDERING_SKYBOX_VERT, SHADER_RENDERING_SKYBOX_EQUIRECTANGULAR_FRAG);
   }
 
   /**
@@ -397,21 +368,41 @@ public:
   /**
    * Display a skybox surrounding the camera
    */
-  void DisplaySkybox()
+  void DisplaySkybox(SkyboxType type)
   {
-    // Load skybox faces from file
-    Texture texture = Texture::New(TextureType::TEXTURE_CUBE, Pixel::RGBA8888, SKYBOX_FACE_WIDTH, SKYBOX_FACE_HEIGHT);
-    for(unsigned int i = 0; i < SKYBOX_FACE_COUNT; i++)
+    mSkyboxTextures.Reset();
+    mSkyboxRenderer.Reset();
+    mSkyboxActor.Reset();
+
+    Texture texture;
+
+    if(type == SkyboxType::CUBEMAP)
     {
-      PixelData pixels = SyncImageLoader::Load(SKYBOX_FACES[i]);
-      texture.Upload(pixels, CubeMapLayer::POSITIVE_X + i, 0, 0, 0, SKYBOX_FACE_WIDTH, SKYBOX_FACE_HEIGHT);
+      // Load skybox faces from file
+      texture = Texture::New(TextureType::TEXTURE_CUBE, Pixel::RGBA8888, SKYBOX_FACE_WIDTH, SKYBOX_FACE_HEIGHT);
+      for(unsigned int i = 0; i < SKYBOX_FACE_COUNT; i++)
+      {
+        PixelData pixels = SyncImageLoader::Load(SKYBOX_FACES[i]);
+        texture.Upload(pixels, CubeMapLayer::POSITIVE_X + i, 0, 0, 0, SKYBOX_FACE_WIDTH, SKYBOX_FACE_HEIGHT);
+      }
+
+      mSkyboxRenderer = Renderer::New(mSkyboxGeometry, mShaderSkybox);
+    }
+    else
+    {
+      // Load equirectangular image from file
+      PixelData pixels = SyncImageLoader::Load(EQUIRECTANGULAR_TEXTURE_URL);
+
+      texture = Texture::New(TextureType::TEXTURE_2D, pixels.GetPixelFormat(), pixels.GetWidth(), pixels.GetHeight());
+      texture.Upload(pixels, 0, 0, 0, 0, pixels.GetWidth(), pixels.GetHeight());
+
+      mSkyboxRenderer = Renderer::New(mSkyboxGeometry, mShaderSkyboxEquirectangular);
     }
 
     // create TextureSet
     mSkyboxTextures = TextureSet::New();
     mSkyboxTextures.SetTexture(0, texture);
 
-    mSkyboxRenderer = Renderer::New(mSkyboxGeometry, mShaderSkybox);
     mSkyboxRenderer.SetTextures(mSkyboxTextures);
     mSkyboxRenderer.SetProperty(Renderer::Property::DEPTH_INDEX, 2.0f);
 
@@ -452,6 +443,7 @@ private:
 
   Shader mShaderCube;
   Shader mShaderSkybox;
+  Shader mShaderSkyboxEquirectangular;
 
   Geometry   mGeometry;
   TextureSet mTextureSet;
@@ -463,6 +455,9 @@ private:
   TextureSet mSkyboxTextures;
   Renderer   mSkyboxRenderer;
   Actor      mSkyboxActor;
+
+  TapGestureDetector mDoubleTapGesture;
+  SkyboxType         mCurrentSkyboxType;
 };
 
 int DALI_EXPORT_API main(int argc, char** argv)