From: Victor Cebollada Date: Mon, 29 May 2017 15:39:23 +0000 (+0100) Subject: Skybox rendering example X-Git-Tag: dali_1.2.42~2 X-Git-Url: http://review.tizen.org/git/?p=platform%2Fcore%2Fuifw%2Fdali-demo.git;a=commitdiff_plain;h=b44b0bec57527e881e9b973473373bc36cbb278b Skybox rendering example Change-Id: I1b2fa79708f93836069ed81a0d4c17c6aeb6094d --- diff --git a/com.samsung.dali-demo.xml b/com.samsung.dali-demo.xml index 9dab573..a71c9a3 100644 --- a/com.samsung.dali-demo.xml +++ b/com.samsung.dali-demo.xml @@ -221,4 +221,7 @@ + + + diff --git a/demo/dali-demo.cpp b/demo/dali-demo.cpp index 566c57e..093a2f2 100644 --- a/demo/dali-demo.cpp +++ b/demo/dali-demo.cpp @@ -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 index 0000000..9e6cf00 --- /dev/null +++ b/examples/rendering-skybox/look-camera.cpp @@ -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 +#include +#include +#include +#include + +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 index 0000000..6cd3a60 --- /dev/null +++ b/examples/rendering-skybox/look-camera.h @@ -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 +#include +#include + +/** + * @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 index 0000000..420ac61 --- /dev/null +++ b/examples/rendering-skybox/rendering-skybox.cpp @@ -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 +#include + +#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 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 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 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 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 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 index 0000000..4db3c2a Binary files /dev/null and b/resources/images/lake_top.jpg differ diff --git a/resources/po/as.po b/resources/po/as.po index 66f9e46..b4e4000 100755 --- a/resources/po/as.po +++ b/resources/po/as.po @@ -168,3 +168,6 @@ msgstr "রশ্মীয় অগ্রগতি অঙ্কন" msgid "DALI_DEMO_STR_TITLE_RENDERING_RAY_MARCHING" msgstr "রে মার্চিং" + +msgid "DALI_DEMO_STR_TITLE_SKYBOX" +msgstr "Skybox" diff --git a/resources/po/de.po b/resources/po/de.po index dc1c7cb..fe66ac4 100755 --- a/resources/po/de.po +++ b/resources/po/de.po @@ -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" diff --git a/resources/po/en_GB.po b/resources/po/en_GB.po index 8ccd957..4c9c8f1 100755 --- a/resources/po/en_GB.po +++ b/resources/po/en_GB.po @@ -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" diff --git a/resources/po/en_US.po b/resources/po/en_US.po index 9c8447a..ee9e456 100755 --- a/resources/po/en_US.po +++ b/resources/po/en_US.po @@ -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" diff --git a/resources/po/es.po b/resources/po/es.po index 834cad1..31a5ea7 100755 --- a/resources/po/es.po +++ b/resources/po/es.po @@ -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" diff --git a/resources/po/fi.po b/resources/po/fi.po index 811425b..1be314f 100755 --- a/resources/po/fi.po +++ b/resources/po/fi.po @@ -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" diff --git a/resources/po/ko.po b/resources/po/ko.po index 97da858..498cbf7 100755 --- a/resources/po/ko.po +++ b/resources/po/ko.po @@ -168,3 +168,6 @@ msgstr "방사형 진행 상황 그리기" msgid "DALI_DEMO_STR_TITLE_RENDERING_RAY_MARCHING" msgstr "레이 마칭" + +msgid "DALI_DEMO_STR_TITLE_SKYBOX" +msgstr "Skybox" diff --git a/resources/po/ml.po b/resources/po/ml.po index 88e1b29..fefc46d 100755 --- a/resources/po/ml.po +++ b/resources/po/ml.po @@ -168,3 +168,6 @@ msgstr "റേഡിയൽ പുരോഗതി ഡ്രോയിംഗ msgid "DALI_DEMO_STR_TITLE_RENDERING_RAY_MARCHING" msgstr "ലൈറ്റ് മാർച്ചിംഗ്" + +msgid "DALI_DEMO_STR_TITLE_SKYBOX" +msgstr "Skybox" diff --git a/resources/po/ur.po b/resources/po/ur.po index cab8aba..24bb67e 100755 --- a/resources/po/ur.po +++ b/resources/po/ur.po @@ -168,3 +168,6 @@ msgstr "ریڈیل پیش رفت ڈرائنگ" msgid "DALI_DEMO_STR_TITLE_RENDERING_RAY_MARCHING" msgstr "رے چلتے" + +msgid "DALI_DEMO_STR_TITLE_SKYBOX" +msgstr "Skybox" diff --git a/resources/po/zn_CH.po b/resources/po/zn_CH.po index 272a4fb..116d2ce 100755 --- a/resources/po/zn_CH.po +++ b/resources/po/zn_CH.po @@ -168,3 +168,6 @@ msgstr "绘制径向进度" msgid "DALI_DEMO_STR_TITLE_RENDERING_RAY_MARCHING" msgstr "射线行军" + +msgid "DALI_DEMO_STR_TITLE_SKYBOX" +msgstr "Skybox" diff --git a/shared/dali-demo-strings.h b/shared/dali-demo-strings.h index 5a8a1b8..adc0bca 100644 --- a/shared/dali-demo-strings.h +++ b/shared/dali-demo-strings.h @@ -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"