/*
- * 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;
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);
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
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
{
public:
TexturedCubeController(Application& application)
- : mApplication(application)
+ : mApplication(application),
+ mCurrentSkyboxType(SkyboxType::CUBEMAP)
{
// Connect to the Application's Init signal
mApplication.InitSignal().Connect(this, &TexturedCubeController::Create);
// 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);
}
/**
}
}
+ 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
*/
*/
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);
}
/**
/**
* 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);
Shader mShaderCube;
Shader mShaderSkybox;
+ Shader mShaderSkyboxEquirectangular;
Geometry mGeometry;
TextureSet mTextureSet;
TextureSet mSkyboxTextures;
Renderer mSkyboxRenderer;
Actor mSkyboxActor;
+
+ TapGestureDetector mDoubleTapGesture;
+ SkyboxType mCurrentSkyboxType;
};
int DALI_EXPORT_API main(int argc, char** argv)