Skybox rendering example 83/131683/6
authorVictor Cebollada <v.cebollada@samsung.com>
Mon, 29 May 2017 15:39:23 +0000 (16:39 +0100)
committerVictor Cebollada <v.cebollada@samsung.com>
Wed, 31 May 2017 15:51:03 +0000 (16:51 +0100)
Change-Id: I1b2fa79708f93836069ed81a0d4c17c6aeb6094d

22 files changed:
com.samsung.dali-demo.xml
demo/dali-demo.cpp
examples/rendering-skybox/look-camera.cpp [new file with mode: 0644]
examples/rendering-skybox/look-camera.h [new file with mode: 0644]
examples/rendering-skybox/rendering-skybox.cpp [new file with mode: 0644]
resources/images/lake_back.jpg [new file with mode: 0644]
resources/images/lake_bottom.jpg [new file with mode: 0644]
resources/images/lake_front.jpg [new file with mode: 0644]
resources/images/lake_left.jpg [new file with mode: 0644]
resources/images/lake_right.jpg [new file with mode: 0644]
resources/images/lake_top.jpg [new file with mode: 0644]
resources/po/as.po
resources/po/de.po
resources/po/en_GB.po
resources/po/en_US.po
resources/po/es.po
resources/po/fi.po
resources/po/ko.po
resources/po/ml.po
resources/po/ur.po
resources/po/zn_CH.po
shared/dali-demo-strings.h

index 9dab573..a71c9a3 100644 (file)
        <ui-application appid="rendering-basic-light.example" exec="/usr/apps/com.samsung.dali-demo/bin/rendering-basic-light.example" nodisplay="true" multiple="false" type="c++app" taskmanage="true">
                <label>Basic Light</label>
        </ui-application>
+       <ui-application appid="rendering-skybox.example" exec="/usr/apps/com.samsung.dali-demo/bin/rendering-skybox.example" nodisplay="true" multiple="false" type="c++app" taskmanage="true">
+               <label>Skybox</label>
+       </ui-application>
 </manifest>
index 566c57e..093a2f2 100644 (file)
@@ -48,6 +48,7 @@ int DALI_EXPORT_API main(int argc, char **argv)
   demo.AddExample(Example("renderer-stencil.example", DALI_DEMO_STR_TITLE_RENDERER_STENCIL));
   demo.AddExample(Example("shadows-and-lights.example", DALI_DEMO_STR_TITLE_LIGHTS_AND_SHADOWS));
   demo.AddExample(Example("sparkle.example", DALI_DEMO_STR_TITLE_SPARKLE));
+  demo.AddExample(Example("rendering-skybox.example", DALI_DEMO_STR_TITLE_SKYBOX));
 
   demo.SortAlphabetically( true );
 
diff --git a/examples/rendering-skybox/look-camera.cpp b/examples/rendering-skybox/look-camera.cpp
new file mode 100644 (file)
index 0000000..9e6cf00
--- /dev/null
@@ -0,0 +1,181 @@
+/*
+ * Copyright (c) 2017 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#include "look-camera.h"
+
+#include <dali/public-api/common/stage.h>
+#include <dali/public-api/render-tasks/render-task-list.h>
+#include <dali/public-api/render-tasks/render-task.h>
+#include <dali/public-api/events/touch-data.h>
+#include <dali/public-api/events/touch-event.h>
+
+using namespace Dali;
+
+namespace
+{
+// Input sensitivity, the larger value, the more sensitive input
+// Default value has been chosen empirically
+const float   CAMERA_SENSITIVITY        ( 90.0f );
+
+// Vertical angle limit of the camera
+const float   CAMERA_VERTICAL_LIMIT     ( 80.0f );
+
+// Position where camera is instantiated by default
+const Vector3 CAMERA_DEFAULT_POSITION   ( 0.0f, 0.0f, 3.0f );
+
+// Field-of-View in degrees
+const float   CAMERA_DEFAULT_FOV        ( 60.0f );
+
+// Near plane
+const float   CAMERA_DEFAULT_NEAR       ( 0.1f );
+
+// Far plane
+const float   CAMERA_DEFAULT_FAR        ( 100.0f );
+
+// Default forward vector
+const Vector3 CAMERA_FORWARD            ( 0.0f, 0.0f, 1.0f );
+
+// Default up vector
+const Vector3 CAMERA_UP                 ( Vector3::YAXIS );
+}
+
+LookCamera::LookCamera()
+: mCameraYawPitch( 0.0f, 180.0f ),
+  mFovY( CAMERA_DEFAULT_FOV ),
+  mNear( CAMERA_DEFAULT_NEAR ),
+  mFar( CAMERA_DEFAULT_FAR ),
+  mCameraPosition( CAMERA_DEFAULT_POSITION )
+{
+}
+
+LookCamera::~LookCamera()
+{
+  mTimer.Stop();
+  mCameraActor.Remove( mInterceptorActor );
+}
+
+void LookCamera::Initialise( const Vector3& position, float fovY, float near, float far )
+{
+  mFovY = fovY;
+  mNear = near;
+  mFar = far;
+
+  // Camera position is shadowed in order to avoid using GetCurrentPosition()
+  mCameraPosition = position;
+
+  // Initialise default camera
+  InitialiseDefaultCamera();
+
+  // Create input interceptor actor
+  CreateInterceptorActor();
+
+  // Start timer
+  mTimer = Timer::New( 16 );
+  mTimer.TickSignal().Connect( this, &LookCamera::OnTick );
+  mTimer.Start();
+}
+
+bool LookCamera::OnTick()
+{
+  Vector2 stageSize = Stage::GetCurrent().GetSize();
+
+  // ---------------------------------------------------------------------
+  // update rotation
+  Vector2 tmp( mScreenLookDelta );
+  mScreenLookDelta = Vector2::ZERO;
+
+  float yaw = ( (tmp.y / stageSize.x ) * CAMERA_SENSITIVITY );
+  float pitch = ( (tmp.x / stageSize.y ) * CAMERA_SENSITIVITY );
+  mCameraYawPitch.x -= yaw;
+  mCameraYawPitch.y -= pitch;
+  if( abs( mCameraYawPitch.x ) > CAMERA_VERTICAL_LIMIT )
+  {
+    mCameraYawPitch.x = CAMERA_VERTICAL_LIMIT * ((mCameraYawPitch.x < 0) ? -1.0f : 1.0f );
+  }
+
+  Quaternion rotation;
+  Quaternion rotX( Degree( mCameraYawPitch.x), Vector3( 1.0f, 0.0f, 0.0f ) );
+  Quaternion rotY( Degree( mCameraYawPitch.y), Vector3( 0.0f, 1.0f, 0.0f ) );
+  rotation = ( rotY * rotX );
+
+  mCameraActor.SetOrientation( rotation );
+
+  return true;
+}
+
+void LookCamera::InitialiseDefaultCamera()
+{
+  Stage stage = Stage::GetCurrent();
+  mCameraActor = stage.GetRenderTaskList().GetTask(0).GetCameraActor();
+  mCameraActor.SetName( "LookCamera" );
+  mCameraActor.SetAnchorPoint( AnchorPoint::CENTER );
+  mCameraActor.SetParentOrigin( ParentOrigin::CENTER );
+  mCameraActor.SetFieldOfView( Radian( Degree( mFovY ) ) );
+
+  // should be read from file
+  mCameraActor.SetNearClippingPlane( mNear );
+  mCameraActor.SetFarClippingPlane( mFar );
+  mCameraActor.SetPosition( mCameraPosition );
+}
+
+void LookCamera::CreateInterceptorActor()
+{
+  Stage stage = Stage::GetCurrent();
+
+  mInterceptorActor = Actor::New();
+  mInterceptorActor.SetName( "InputInterceptor" );
+  mInterceptorActor.SetSize( Vector3( stage.GetSize().x, stage.GetSize().y, 1 ) );
+  mInterceptorActor.SetPosition( Vector3( 0.0, 0.0, 1.0  ) );
+  mInterceptorActor.SetAnchorPoint( AnchorPoint::CENTER );
+  mInterceptorActor.SetParentOrigin( ParentOrigin::CENTER );
+  mCameraActor.Add( mInterceptorActor );
+
+  // Connect TouchSignal to interceptor actor
+  mInterceptorActor.TouchSignal().Connect( this, &LookCamera::OnTouch );
+}
+
+bool LookCamera::OnTouch( Actor actor, const TouchData& touch )
+{
+  Stage stage = Stage::GetCurrent();
+
+  for( int i = 0; i < (int)touch.GetPointCount() && i < 3; ++i )
+  {
+    Vector2 position( touch.GetScreenPosition( i ) );
+
+    // touch started
+    if( touch.GetState( i ) == PointState::STARTED )
+    {
+      mOldTouchLookPosition = position;
+    }
+    else if( touch.GetState( i ) == PointState::FINISHED ||
+             touch.GetState( i ) == PointState::LEAVE ||
+             touch.GetState( i ) == PointState::INTERRUPTED
+             )
+    {
+      mScreenLookDelta = Vector2::ZERO;
+      mOldTouchLookPosition = Vector2::ZERO;
+    }
+    else // on motion
+    {
+      mScreenLookDelta.x += ( position.x - mOldTouchLookPosition.x );
+      mScreenLookDelta.y += ( position.y - mOldTouchLookPosition.y );
+      mOldTouchLookPosition = position;
+    }
+  }
+
+  return true;
+}
diff --git a/examples/rendering-skybox/look-camera.h b/examples/rendering-skybox/look-camera.h
new file mode 100644 (file)
index 0000000..6cd3a60
--- /dev/null
@@ -0,0 +1,105 @@
+#ifndef LOOK_CAMERA_H
+#define LOOK_CAMERA_H
+
+/*
+ * Copyright (c) 2017 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#include <dali/public-api/actors/camera-actor.h>
+#include <dali/public-api/adaptor-framework/timer.h>
+#include <dali/public-api/math/vector2.h>
+
+/**
+ * @brief The LookCamera class
+ *
+ * LookCamera handles user input to change the orientation of the default camera.
+ */
+class LookCamera : public Dali::ConnectionTracker
+{
+public:
+
+  /**
+   * Creates an instance of LookCamera
+   */
+  LookCamera();
+
+  /**
+   * Destroys an instance of LookCamera
+   */
+  ~LookCamera();
+
+  /**
+   * Initialise with given position, fovY, near, far
+   * @param[in] position Position of the camera.
+   * @param[in] fovY Field of view in degrees
+   * @param[in] near Near plane
+   * @param[in] far Far Plane
+   */
+  void Initialise( const Dali::Vector3& position, float fov, float near, float far );
+
+  /**
+   * Retrieves actor associated with camera object
+   * @return Returns camera actor
+   */
+  Dali::CameraActor GetCameraActor();
+
+private:
+
+  /**
+   * Sets up a perspective camera using Dali default camera
+   */
+  void InitialiseDefaultCamera();
+
+  /**
+   * Creates 'interceptor' actor. Interceptor actor is always parallel
+   * to the camera and positioned little bit in front of it in order to
+   * intercept user input.
+   */
+  void CreateInterceptorActor();
+
+  /**
+   * Handles onTouch signal on the 'interceptor' actor
+   * @param[in] actor Actor receiving signal
+   * @param[in] touch Touch data
+   */
+  bool OnTouch( Dali::Actor actor, const Dali::TouchData& touch );
+
+  /**
+   * Handles camera tick() update
+   * @return true if continue running timer, false otherwise
+   */
+  bool OnTick();
+
+private:
+
+  Dali::CameraActor mCameraActor; /// Camera actor
+  Dali::Actor mInterceptorActor; /// Actor intercepting user input
+
+  Dali::Timer mTimer; /// Per-frame timer
+
+  Dali::Vector2 mScreenLookDelta; /// Look delta vector in screen space
+  Dali::Vector2 mOldTouchLookPosition; /// Previous look vector in screen space
+
+  Dali::Vector2 mCameraYawPitch; /// Camera yaw-pitch angles
+
+  float mFovY; /// Camera field-of-view
+  float mNear; /// Near plane
+  float mFar; /// Far plane
+
+  Dali::Vector3 mCameraPosition; /// Current camera position ( shadowing the actor position )
+};
+
+#endif
diff --git a/examples/rendering-skybox/rendering-skybox.cpp b/examples/rendering-skybox/rendering-skybox.cpp
new file mode 100644 (file)
index 0000000..420ac61
--- /dev/null
@@ -0,0 +1,503 @@
+/*
+ * Copyright (c) 2017 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#include <dali/dali.h>
+#include <dali-toolkit/dali-toolkit.h>
+
+#include "look-camera.h"
+
+using namespace Dali;
+using namespace Toolkit;
+
+namespace
+{
+
+/*
+ * 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
+);
+
+const float CAMERA_DEFAULT_FOV(    60.0f );
+const float CAMERA_DEFAULT_NEAR(    0.1f );
+const float CAMERA_DEFAULT_FAR(  1000.0f );
+const Vector3 CAMERA_DEFAULT_POSITION( 0.0f, 0.0f, 100.0f );
+
+const char* TEXTURE_URL = DEMO_IMAGE_DIR "wood.png";
+
+const unsigned int SKYBOX_FACE_COUNT = 6;
+const unsigned int SKYBOX_FACE_WIDTH  = 2048;
+const unsigned int SKYBOX_FACE_HEIGHT = 2048;
+
+/*
+ * Credit to Joey do Vries for the following cubemap images
+ * Take from git://github.com/JoeyDeVries/LearnOpenGL.git
+ * The images are licensed under the terms of the CC BY 4.0 license:
+ * https://creativecommons.org/licenses/by/4.0/
+ */
+const char* SKYBOX_FACES[ SKYBOX_FACE_COUNT ] =
+{
+  DEMO_IMAGE_DIR "lake_right.jpg",
+  DEMO_IMAGE_DIR "lake_left.jpg",
+  DEMO_IMAGE_DIR "lake_top.jpg",
+  DEMO_IMAGE_DIR "lake_bottom.jpg",
+  DEMO_IMAGE_DIR "lake_back.jpg",
+  DEMO_IMAGE_DIR "lake_front.jpg"
+};
+
+}
+
+// This example shows how to create a skybox
+//
+// Recommended screen size on desktop: 1280x720
+//
+class TexturedCubeController : public ConnectionTracker
+{
+public:
+
+  TexturedCubeController( Application& application )
+  : mApplication( application )
+  {
+    // Connect to the Application's Init signal
+    mApplication.InitSignal().Connect( this, &TexturedCubeController::Create );
+  }
+
+  ~TexturedCubeController()
+  {
+    // Nothing to do here;
+  }
+
+  // The Init signal is received once (only) during the Application lifetime
+  void Create( Application& application )
+  {
+    // Disable indicator.
+    // It avoids reposition the camera to fit with the indicator height.
+    Dali::Window winHandle = application.GetWindow();
+    winHandle.ShowIndicator( Dali::Window::INVISIBLE );
+
+    // Get a handle to the stage
+    Stage stage = Stage::GetCurrent();
+    stage.SetBackgroundColor( Color::WHITE );
+
+    // Step 1. Setup camera
+    SetupCamera();
+
+    // Step 2. Create shaders
+    CreateShaders();
+
+    // Step 3. Create geometry
+    CreateCubeGeometry();
+    CreateSkyboxGeometry();
+
+    // Step 4. Display first a cube at the world origin.
+    //         The write on the depth buffer is enabled.
+    DisplayCube();
+
+    // Step 5. Display last the skybox surrounding the camera.
+    //         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();
+
+    // Step 6. Play animation to rotate the cube
+    PlayAnimation();
+
+    // Respond to key events
+    stage.KeyEventSignal().Connect( this, &TexturedCubeController::OnKeyEvent );
+  }
+
+  /**
+   * @brief Called when any key event is received
+   *
+   * Will use this to quit the application if Back or the Escape key is received
+   * @param[in] event The key event information
+   */
+  void OnKeyEvent( const KeyEvent& event )
+  {
+    if( event.state == KeyEvent::Down )
+    {
+      if ( IsKey( event, Dali::DALI_KEY_ESCAPE ) || IsKey( event, Dali::DALI_KEY_BACK ) )
+      {
+        mApplication.Quit();
+      }
+    }
+  }
+
+  /**
+   * @brief Setup a perspective camera pointing in the negative Z direction
+   */
+  void SetupCamera()
+  {
+    Stage stage = Stage::GetCurrent();
+
+    RenderTask renderTask = stage.GetRenderTaskList().GetTask( 0 );
+    renderTask.SetCullMode( false ); // avoid frustum culling affecting the skybox
+
+    mCamera.Initialise( CAMERA_DEFAULT_POSITION, CAMERA_DEFAULT_FOV, CAMERA_DEFAULT_NEAR, CAMERA_DEFAULT_FAR );
+  }
+
+  /**
+   * Creates a shader using inlined variable VERTEX_SHADER and FRAGMENT_SHADER
+   *
+   * Shaders are very basic and all they do is transforming vertices and sampling
+   * a texture.
+   */
+  void CreateShaders()
+  {
+    mShaderCube   = Shader::New( VERTEX_SHADER_CUBE, FRAGMENT_SHADER_CUBE );
+    mShaderSkybox = Shader::New( VERTEX_SHADER_SKYBOX, FRAGMENT_SHADER_SKYBOX );
+  }
+
+  /**
+   * @brief CreateCubeGeometry
+   * This function creates a cube geometry including texture coordinates.
+   * Also it demonstrates using the indexed draw feature by setting an index array.
+   */
+  void CreateCubeGeometry()
+  {
+    struct Vertex
+    {
+      Vector3 aPosition;
+      Vector2 aTexCoord;
+    };
+
+    Vertex vertices[] = {
+      { Vector3(  1.0f,-1.0f,-1.0f ), Vector2( 1.0, 1.0 ) },
+      { Vector3( -1.0f, 1.0f,-1.0f ), Vector2( 0.0, 0.0 ) },
+      { Vector3(  1.0f, 1.0f,-1.0f ), Vector2( 0.0, 1.0 ) },
+      { Vector3( -1.0f, 1.0f, 1.0f ), Vector2( 1.0, 1.0 ) },
+      { Vector3(  1.0f,-1.0f, 1.0f ), Vector2( 0.0, 0.0 ) },
+      { Vector3(  1.0f, 1.0f, 1.0f ), Vector2( 0.0, 1.0 ) },
+      { Vector3(  1.0f, 1.0f, 1.0f ), Vector2( 1.0, 1.0 ) },
+      { Vector3(  1.0f,-1.0f,-1.0f ), Vector2( 0.0, 0.0 ) },
+      { Vector3(  1.0f, 1.0f,-1.0f ), Vector2( 0.0, 1.0 ) },
+      { Vector3(  1.0f,-1.0f, 1.0f ), Vector2( 1.0, 1.0 ) },
+      { Vector3( -1.0f,-1.0f,-1.0f ), Vector2( 0.0, 0.0 ) },
+      { Vector3(  1.0f,-1.0f,-1.0f ), Vector2( 0.0, 1.0 ) },
+      { Vector3( -1.0f,-1.0f,-1.0f ), Vector2( 1.0, 1.0 ) },
+      { Vector3( -1.0f, 1.0f, 1.0f ), Vector2( 0.0, 0.0 ) },
+      { Vector3( -1.0f, 1.0f,-1.0f ), Vector2( 0.0, 1.0 ) },
+      { Vector3(  1.0f, 1.0f,-1.0f ), Vector2( 1.0, 1.0 ) },
+      { Vector3( -1.0f, 1.0f, 1.0f ), Vector2( 0.0, 0.0 ) },
+      { Vector3(  1.0f, 1.0f, 1.0f ), Vector2( 0.0, 1.0 ) },
+      { Vector3(  1.0f,-1.0f,-1.0f ), Vector2( 1.0, 1.0 ) },
+      { Vector3( -1.0f,-1.0f,-1.0f ), Vector2( 1.0, 0.0 ) },
+      { Vector3( -1.0f, 1.0f,-1.0f ), Vector2( 0.0, 0.0 ) },
+      { Vector3( -1.0f, 1.0f, 1.0f ), Vector2( 1.0, 1.0 ) },
+      { Vector3( -1.0f,-1.0f, 1.0f ), Vector2( 1.0, 0.0 ) },
+      { Vector3(  1.0f,-1.0f, 1.0f ), Vector2( 0.0, 0.0 ) },
+      { Vector3(  1.0f, 1.0f, 1.0f ), Vector2( 1.0, 1.0 ) },
+      { Vector3(  1.0f,-1.0f, 1.0f ), Vector2( 1.0, 0.0 ) },
+      { Vector3(  1.0f,-1.0f,-1.0f ), Vector2( 0.0, 0.0 ) },
+      { Vector3(  1.0f,-1.0f, 1.0f ), Vector2( 1.0, 1.0 ) },
+      { Vector3( -1.0f,-1.0f, 1.0f ), Vector2( 1.0, 0.0 ) },
+      { Vector3( -1.0f,-1.0f,-1.0f ), Vector2( 0.0, 0.0 ) },
+      { Vector3( -1.0f,-1.0f,-1.0f ), Vector2( 1.0, 1.0 ) },
+      { Vector3( -1.0f,-1.0f, 1.0f ), Vector2( 1.0, 0.0 ) },
+      { Vector3( -1.0f, 1.0f, 1.0f ), Vector2( 0.0, 0.0 ) },
+      { Vector3(  1.0f, 1.0f,-1.0f ), Vector2( 1.0, 1.0 ) },
+      { Vector3( -1.0f, 1.0f,-1.0f ), Vector2( 1.0, 0.0 ) },
+      { Vector3( -1.0f, 1.0f, 1.0f ), Vector2( 0.0, 0.0 ) },
+    };
+
+    PropertyBuffer vertexBuffer = PropertyBuffer::New( Property::Map()
+                                                       .Add( "aPosition", Property::VECTOR3 )
+                                                       .Add( "aTexCoord", Property::VECTOR2 ) );
+    vertexBuffer.SetData( vertices, sizeof(vertices) / sizeof(Vertex) );
+
+    // create indices
+    const unsigned short INDEX_CUBE[] = {
+      2, 1, 0,
+      5, 4, 3,
+      8, 7, 6,
+      11, 10, 9,
+      14, 13, 12,
+      17, 16, 15,
+      20, 19, 18,
+      23, 22, 21,
+      26, 25, 24,
+      29, 28, 27,
+      32, 31, 30,
+      35, 34, 33
+    };
+
+    mGeometry = Geometry::New();
+    mGeometry.AddVertexBuffer( vertexBuffer );
+    mGeometry.SetIndexBuffer( INDEX_CUBE,
+                              sizeof(INDEX_CUBE)/sizeof(INDEX_CUBE[0]) );
+    mGeometry.SetType( Geometry::TRIANGLES );
+  }
+
+  /**
+   * @brief CreateCubeGeometry
+   * This function creates a cube geometry including texture coordinates.
+   * Also it demonstrates using the indexed draw feature by setting an index array.
+   */
+  void CreateSkyboxGeometry()
+  {
+    struct Vertex
+    {
+      Vector3 aPosition;
+    };
+
+    Vertex skyboxVertices[] = {
+        // back
+        { Vector3(  -1.0f,  1.0f, -1.0f ) },
+        { Vector3(  -1.0f, -1.0f, -1.0f ) },
+        { Vector3(   1.0f, -1.0f, -1.0f ) },
+        { Vector3(   1.0f, -1.0f, -1.0f ) },
+        { Vector3(   1.0f,  1.0f, -1.0f ) },
+        { Vector3(  -1.0f,  1.0f, -1.0f ) },
+
+        // left
+        { Vector3(  -1.0f, -1.0f,  1.0f ) },
+        { Vector3(  -1.0f, -1.0f, -1.0f ) },
+        { Vector3(  -1.0f,  1.0f, -1.0f ) },
+        { Vector3(  -1.0f,  1.0f, -1.0f ) },
+        { Vector3(  -1.0f,  1.0f,  1.0f ) },
+        { Vector3(  -1.0f, -1.0f,  1.0f ) },
+
+        // right
+        { Vector3(   1.0f, -1.0f, -1.0f ) },
+        { Vector3(   1.0f, -1.0f,  1.0f ) },
+        { Vector3(   1.0f,  1.0f,  1.0f ) },
+        { Vector3(   1.0f,  1.0f,  1.0f ) },
+        { Vector3(   1.0f,  1.0f, -1.0f ) },
+        { Vector3(   1.0f, -1.0f, -1.0f ) },
+
+        // front
+        { Vector3(  -1.0f, -1.0f,  1.0f ) },
+        { Vector3(  -1.0f,  1.0f,  1.0f ) },
+        { Vector3(   1.0f,  1.0f,  1.0f ) },
+        { Vector3(   1.0f,  1.0f,  1.0f ) },
+        { Vector3(   1.0f, -1.0f,  1.0f ) },
+        { Vector3(  -1.0f, -1.0f,  1.0f ) },
+
+        // botton
+        { Vector3(  -1.0f,  1.0f, -1.0f ) },
+        { Vector3(   1.0f,  1.0f, -1.0f ) },
+        { Vector3(   1.0f,  1.0f,  1.0f ) },
+        { Vector3(   1.0f,  1.0f,  1.0f ) },
+        { Vector3(  -1.0f,  1.0f,  1.0f ) },
+        { Vector3(  -1.0f,  1.0f, -1.0f ) },
+
+        // top
+        { Vector3(  -1.0f, -1.0f, -1.0f ) },
+        { Vector3(  -1.0f, -1.0f,  1.0f ) },
+        { Vector3(   1.0f, -1.0f, -1.0f ) },
+        { Vector3(   1.0f, -1.0f, -1.0f ) },
+        { Vector3(  -1.0f, -1.0f,  1.0f ) },
+        { Vector3(   1.0f, -1.0f,  1.0f ) }
+    };
+
+    PropertyBuffer vertexBuffer = PropertyBuffer::New( Property::Map()
+                                                       .Add( "aPosition", Property::VECTOR3 ) );
+    vertexBuffer.SetData( skyboxVertices, sizeof(skyboxVertices) / sizeof(Vertex) );
+
+    mSkyboxGeometry = Geometry::New();
+    mSkyboxGeometry.AddVertexBuffer( vertexBuffer );
+    mSkyboxGeometry.SetType( Geometry::TRIANGLES );
+  }
+
+  /**
+   * Display a cube at the world origin
+   */
+  void DisplayCube()
+  {
+    // Load image from file
+    PixelData pixels = SyncImageLoader::Load( TEXTURE_URL );
+
+    Texture texture = Texture::New( TextureType::TEXTURE_2D, pixels.GetPixelFormat(), pixels.GetWidth(), pixels.GetHeight() );
+    texture.Upload( pixels, 0, 0, 0, 0, pixels.GetWidth(), pixels.GetHeight() );
+
+    // create TextureSet
+    mTextureSet = TextureSet::New();
+    mTextureSet.SetTexture( 0, texture );
+
+    mRenderer = Renderer::New( mGeometry, mShaderCube );
+    mRenderer.SetTextures( mTextureSet );
+    mRenderer.SetProperty( Renderer::Property::DEPTH_INDEX, 1.0f );
+
+    // A further optimization would be to enable debug testing instead
+    mRenderer.SetProperty( Renderer::Property::FACE_CULLING_MODE, FaceCullingMode::BACK );
+
+    // Enables the write on the depth buffer.
+    mRenderer.SetProperty( Renderer::Property::DEPTH_WRITE_MODE, DepthWriteMode::ON );
+
+    mActor = Actor::New();
+    mActor.SetName( "Cube" );
+    mActor.SetAnchorPoint( AnchorPoint::CENTER );
+    mActor.SetParentOrigin( ParentOrigin::CENTER );
+    mActor.AddRenderer( mRenderer );
+
+    mActor.SetSize( 10.f, 10.f, 10.f );
+
+    Stage stage = Stage::GetCurrent();
+    stage.Add( mActor );
+  }
+
+  /**
+   * Display a skybox surrounding the camera
+   */
+  void DisplaySkybox()
+  {
+    // 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++)
+    {
+      PixelData pixels = SyncImageLoader::Load( SKYBOX_FACES[i] );
+      texture.Upload( pixels, CubeMapLayer::POSITIVE_X + i, 0, 0, 0, SKYBOX_FACE_WIDTH, SKYBOX_FACE_HEIGHT );
+    }
+
+    // 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 );
+
+    // Enables the depth test.
+    mSkyboxRenderer.SetProperty( Renderer::Property::DEPTH_TEST_MODE, DepthTestMode::ON );
+
+    // The fragment shader will run only is those pixels that have the max depth value.
+    mSkyboxRenderer.SetProperty( Renderer::Property::DEPTH_FUNCTION, DepthFunction::LESS_EQUAL );
+
+    Stage stage = Stage::GetCurrent();
+
+    mSkyboxActor = Actor::New();
+    mSkyboxActor.SetName( "SkyBox" );
+    mSkyboxActor.SetAnchorPoint( AnchorPoint::CENTER );
+    mSkyboxActor.SetParentOrigin( ParentOrigin::CENTER );
+    mSkyboxActor.SetPosition( CAMERA_DEFAULT_POSITION );
+    mSkyboxActor.AddRenderer( mSkyboxRenderer );
+    stage.Add( mSkyboxActor );
+  }
+
+  /**
+   * Plays animation
+   */
+  void PlayAnimation()
+  {
+    mAnimation = Animation::New( 5.0f );
+    mAnimation.SetLooping( true );
+    mAnimation.AnimateBy( Property( mActor, Actor::Property::ORIENTATION ), Quaternion( Radian( Degree( 360 )), Vector3::ZAXIS ) );
+    mAnimation.AnimateBy( Property( mActor, Actor::Property::ORIENTATION ), Quaternion( Radian( Degree( 360 )), Vector3::YAXIS ) );
+    mAnimation.AnimateBy( Property( mActor, Actor::Property::ORIENTATION ), Quaternion( Radian( Degree( 360 )), Vector3::XAXIS ) );
+    mAnimation.Play();
+  }
+
+private:
+  Application&  mApplication;
+
+  LookCamera mCamera;
+
+  Shader mShaderCube;
+  Shader mShaderSkybox;
+
+  Geometry mGeometry;
+  TextureSet mTextureSet;
+  Renderer mRenderer;
+  Actor mActor;
+  Animation mAnimation;
+
+  Geometry mSkyboxGeometry;
+  TextureSet mSkyboxTextures;
+  Renderer mSkyboxRenderer;
+  Actor mSkyboxActor;
+};
+
+void RunTest( Application& application )
+{
+  TexturedCubeController test( application );
+
+  application.MainLoop();
+}
+
+// Entry point for Linux & Tizen applications
+//
+int DALI_EXPORT_API main( int argc, char **argv )
+{
+  Application application = Application::New( &argc, &argv );
+
+  RunTest( application );
+
+  return 0;
+}
diff --git a/resources/images/lake_back.jpg b/resources/images/lake_back.jpg
new file mode 100644 (file)
index 0000000..4e17b77
Binary files /dev/null and b/resources/images/lake_back.jpg differ
diff --git a/resources/images/lake_bottom.jpg b/resources/images/lake_bottom.jpg
new file mode 100644 (file)
index 0000000..893f394
Binary files /dev/null and b/resources/images/lake_bottom.jpg differ
diff --git a/resources/images/lake_front.jpg b/resources/images/lake_front.jpg
new file mode 100644 (file)
index 0000000..470a679
Binary files /dev/null and b/resources/images/lake_front.jpg differ
diff --git a/resources/images/lake_left.jpg b/resources/images/lake_left.jpg
new file mode 100644 (file)
index 0000000..5750b91
Binary files /dev/null and b/resources/images/lake_left.jpg differ
diff --git a/resources/images/lake_right.jpg b/resources/images/lake_right.jpg
new file mode 100644 (file)
index 0000000..8963037
Binary files /dev/null and b/resources/images/lake_right.jpg differ
diff --git a/resources/images/lake_top.jpg b/resources/images/lake_top.jpg
new file mode 100644 (file)
index 0000000..4db3c2a
Binary files /dev/null and b/resources/images/lake_top.jpg differ
index 66f9e46..b4e4000 100755 (executable)
@@ -168,3 +168,6 @@ msgstr "রশ্মীয় অগ্রগতি অঙ্কন"
 
 msgid "DALI_DEMO_STR_TITLE_RENDERING_RAY_MARCHING"
 msgstr "রে মার্চিং"
+
+msgid "DALI_DEMO_STR_TITLE_SKYBOX"
+msgstr "Skybox"
index dc1c7cb..fe66ac4 100755 (executable)
@@ -168,3 +168,6 @@ msgstr "Radialer Fortschritt zeichnen"
 
 msgid "DALI_DEMO_STR_TITLE_RENDERING_RAY_MARCHING"
 msgstr "Ray marschieren"
+
+msgid "DALI_DEMO_STR_TITLE_SKYBOX"
+msgstr "Skybox"
index 8ccd957..4c9c8f1 100755 (executable)
@@ -180,3 +180,6 @@ msgstr "Draw radial progress"
 
 msgid "DALI_DEMO_STR_TITLE_RENDERING_RAY_MARCHING"
 msgstr "Ray Marching"
+
+msgid "DALI_DEMO_STR_TITLE_SKYBOX"
+msgstr "Skybox"
index 9c8447a..ee9e456 100755 (executable)
@@ -180,3 +180,6 @@ msgstr "Draw radial progress"
 
 msgid "DALI_DEMO_STR_TITLE_RENDERING_RAY_MARCHING"
 msgstr "Ray Marching"
+
+msgid "DALI_DEMO_STR_TITLE_SKYBOX"
+msgstr "Skybox"
index 834cad1..31a5ea7 100755 (executable)
@@ -168,3 +168,6 @@ msgstr "Dibujo progreso radial"
 
 msgid "DALI_DEMO_STR_TITLE_RENDERING_RAY_MARCHING"
 msgstr "trazado de rayos"
+
+msgid "DALI_DEMO_STR_TITLE_SKYBOX"
+msgstr "Skybox"
index 811425b..1be314f 100755 (executable)
@@ -168,3 +168,6 @@ msgstr "Piirustus radial edistyminen"
 
 msgid "DALI_DEMO_STR_TITLE_RENDERING_RAY_MARCHING"
 msgstr "Ray marssi"
+
+msgid "DALI_DEMO_STR_TITLE_SKYBOX"
+msgstr "Skybox"
index 97da858..498cbf7 100755 (executable)
@@ -168,3 +168,6 @@ msgstr "방사형 진행 상황 그리기"
 
 msgid "DALI_DEMO_STR_TITLE_RENDERING_RAY_MARCHING"
 msgstr "레이 마칭"
+
+msgid "DALI_DEMO_STR_TITLE_SKYBOX"
+msgstr "Skybox"
index 88e1b29..fefc46d 100755 (executable)
@@ -168,3 +168,6 @@ msgstr "റേഡിയൽ പുരോഗതി ഡ്രോയിംഗ
 
 msgid "DALI_DEMO_STR_TITLE_RENDERING_RAY_MARCHING"
 msgstr "ലൈറ്റ് മാർച്ചിംഗ്"
+
+msgid "DALI_DEMO_STR_TITLE_SKYBOX"
+msgstr "Skybox"
index cab8aba..24bb67e 100755 (executable)
@@ -168,3 +168,6 @@ msgstr "ریڈیل پیش رفت ڈرائنگ"
 
 msgid "DALI_DEMO_STR_TITLE_RENDERING_RAY_MARCHING"
 msgstr "رے چلتے"
+
+msgid "DALI_DEMO_STR_TITLE_SKYBOX"
+msgstr "Skybox"
index 272a4fb..116d2ce 100755 (executable)
@@ -168,3 +168,6 @@ msgstr "绘制径向进度"
 
 msgid "DALI_DEMO_STR_TITLE_RENDERING_RAY_MARCHING"
 msgstr "射线行军"
+
+msgid "DALI_DEMO_STR_TITLE_SKYBOX"
+msgstr "Skybox"
index 5a8a1b8..adc0bca 100644 (file)
@@ -81,6 +81,7 @@ extern "C"
 #define DALI_DEMO_STR_TITLE_SIMPLE_VISUALS_CONTROL      dgettext(DALI_DEMO_DOMAIN_LOCAL, "DALI_DEMO_STR_TITLE_SIMPLE_VISUALS")
 #define DALI_DEMO_STR_TITLE_SCRIPT_BASED_UI             dgettext(DALI_DEMO_DOMAIN_LOCAL, "DALI_DEMO_STR_TITLE_SCRIPT_BASED_UI")
 #define DALI_DEMO_STR_TITLE_SCROLL_VIEW                 dgettext(DALI_DEMO_DOMAIN_LOCAL, "DALI_DEMO_STR_TITLE_SCROLL_VIEW")
+#define DALI_DEMO_STR_TITLE_SKYBOX                      dgettext(DALI_DEMO_DOMAIN_LOCAL, "DALI_DEMO_STR_TITLE_SKYBOX")
 #define DALI_DEMO_STR_TITLE_SPARKLE                     dgettext(DALI_DEMO_DOMAIN_LOCAL, "DALI_DEMO_STR_TITLE_SPARKLE")
 #define DALI_DEMO_STR_TITLE_STYLING                     dgettext(DALI_DEMO_DOMAIN_LOCAL, "DALI_DEMO_STR_TITLE_STYLING")
 #define DALI_DEMO_STR_TITLE_TEXTURED_MESH               dgettext(DALI_DEMO_DOMAIN_LOCAL, "DALI_DEMO_STR_TITLE_TEXTURED_MESH")
@@ -144,6 +145,7 @@ extern "C"
 #define DALI_DEMO_STR_TITLE_SIMPLE_VISUALS_CONTROL      "Simple Visuals Control"
 #define DALI_DEMO_STR_TITLE_SCRIPT_BASED_UI             "Script Based UI"
 #define DALI_DEMO_STR_TITLE_SCROLL_VIEW                 "Scroll View"
+#define DALI_DEMO_STR_TITLE_SKYBOX                      "Skybox"
 #define DALI_DEMO_STR_TITLE_SPARKLE                     "Sparkle"
 #define DALI_DEMO_STR_TITLE_STYLING                     "Styling"
 #define DALI_DEMO_STR_TITLE_TEXTURED_MESH               "Mesh Texture"