From: Tom Robinson Date: Tue, 9 Aug 2016 15:15:13 +0000 (+0100) Subject: VR: Added skybox to mesh-visual.example X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=06a5896c866ab4433617ae864fbf252dbe83d2e5;p=platform%2Fcore%2Fuifw%2Fdali-demo.git VR: Added skybox to mesh-visual.example Change-Id: Ib6123083ee48cc169dcde9debe18b781e9b11cfc --- diff --git a/demo/dali-table-view.cpp b/demo/dali-table-view.cpp index daebe61..312c87e 100644 --- a/demo/dali-table-view.cpp +++ b/demo/dali-table-view.cpp @@ -180,6 +180,9 @@ void DaliTableView::SortAlphabetically( bool sortAlphabetically ) void DaliTableView::Initialize( Application& application ) { + //todor + application.SetViewMode( STEREO_HORIZONTAL ); + Stage::GetCurrent().KeyEventSignal().Connect( this, &DaliTableView::OnKeyEvent ); const Vector2 stageSize = Stage::GetCurrent().GetSize(); diff --git a/examples/mesh-visual/mesh-visual-example.cpp b/examples/mesh-visual/mesh-visual-example.cpp index 3340838..e3a4804 100644 --- a/examples/mesh-visual/mesh-visual-example.cpp +++ b/examples/mesh-visual/mesh-visual-example.cpp @@ -1,5 +1,7 @@ #include #include +#include "mesh-visual-shaders.h" +#include "shared/utility.h" using namespace Dali; using namespace Dali::Toolkit; @@ -44,7 +46,7 @@ namespace const float MODEL_SCALE = 0.75f; const float LIGHT_SCALE = 0.15f; const float BUTTONS_OFFSET_BOTTOM = 0.9f; - const int NUM_MESHES = 2; + const int NUM_MESHES = 1;//TODOVR //Used to identify actors. const int MODEL_TAG = 0; @@ -59,8 +61,8 @@ public: MeshVisualController( Application& application ) : mApplication( application ), //Store handle to the application. - mModelIndex( 1 ), //Start with metal robot. - mShadingModeIndex( 0 ), //Start with textured with detailed specular lighting. + mModelIndex( 2 ), //Start with metal robot. + mShadingModeIndex( 1 ), //Start with textured with detailed specular lighting. mTag( -1 ), //Non-valid default, which will get set to a correct value when used. mSelectedModelIndex( -1 ), //Non-valid default, which will get set to a correct value when used. mPaused( false ), //Animations play by default. @@ -77,6 +79,9 @@ public: // The Init signal is received once (only) during the Application lifetime void Create( Application& application ) { + //todor + application.SetViewMode( VR ); + // Get a handle to the stage Stage stage = Stage::GetCurrent(); stage.SetBackgroundColor( Vector4( 0.0, 0.5, 1.0, 1.0 ) ); @@ -92,6 +97,48 @@ public: baseLayer.TouchedSignal().Connect( this, &MeshVisualController::OnTouch ); stage.Add( baseLayer ); + + + const float CUBE_WIDTH_SCALE( 2.0f ); ///< The width (and height + depth) of the main and reflection cubes. + const char * const CUBE_TEXTURE( DEMO_IMAGE_DIR "people-medium-1.jpg" ); + const Vector4 CUBE_COLOR( 1.0f, 1.0f, 1.0f, 1.0f ); ///< White. + // Main cube: + // Make the demo scalable with different resolutions by basing + // the cube size on a percentage of the stage size. + float scaleSize( std::min( stage.GetSize().width, stage.GetSize().height ) ); + float cubeWidth( scaleSize * CUBE_WIDTH_SCALE ); + Vector3 cubeSize( cubeWidth, cubeWidth, cubeWidth ); + // Create the geometry for the cube, and the texture. + Geometry cubeGeometry = CreateCubeVertices( Vector3::ONE, false ); + TextureSet cubeTextureSet = CreateTextureSet( CUBE_TEXTURE ); + // Create the cube object and add it. + // Note: The cube is anchored around its base for animation purposes, so the position can be zero. + Toolkit::Control container = Toolkit::Control::New(); + container.SetAnchorPoint( AnchorPoint::BOTTOM_CENTER ); + container.SetParentOrigin( ParentOrigin::BOTTOM_CENTER ); + container.SetSize( cubeSize ); + container.SetPosition( 0.0f, 0.0f, 960.0f ); + container.SetResizePolicy( ResizePolicy::FIXED, Dimension::ALL_DIMENSIONS ); + // Create a renderer from the geometry and add the texture. + Renderer renderer = CreateRenderer( cubeGeometry, cubeSize, true, CUBE_COLOR ); + renderer.SetTextures( cubeTextureSet ); + // Setup the renderer properties: + // We are writing to the color buffer & culling back faces. + renderer.SetProperty( Renderer::Property::WRITE_TO_COLOR_BUFFER, true ); + renderer.SetProperty( Renderer::Property::FACE_CULLING_MODE, FaceCullingMode::FRONT ); + // No stencil is used for the main cube. + renderer.SetProperty( Renderer::Property::STENCIL_MODE, StencilMode::OFF ); + // We do need to write to the depth buffer as other objects need to appear underneath this cube. + renderer.SetProperty( Renderer::Property::DEPTH_WRITE_MODE, DepthWriteMode::OFF ); + // We do not need to test the depth buffer as we are culling the back faces. + renderer.SetProperty( Renderer::Property::DEPTH_TEST_MODE, DepthTestMode::OFF ); + // This object must be rendered 1st. + //renderer.SetProperty( Renderer::Property::DEPTH_INDEX, 0 * DEPTH_INDEX_GRANULARITY ); + container.AddRenderer( renderer ); + baseLayer.Add( container ); + + + //Place models on the scene. SetupModels( baseLayer ); @@ -126,10 +173,13 @@ public: mContainers[0].SetParentOrigin( ParentOrigin::CENTER ); mContainers[0].SetAnchorPoint( AnchorPoint::CENTER ); + //TODOVR +#if 0 //Top left model mContainers[1].SetSizeModeFactor( Vector3( MODEL_SCALE / 3.0f, MODEL_SCALE / 3.0f, 0.0f ) ); mContainers[1].SetParentOrigin( Vector3( 0.05, 0.03, 0.5 ) ); //Offset from top left mContainers[1].SetAnchorPoint( AnchorPoint::TOP_LEFT ); +#endif //Set up models for( int i = 0; i < NUM_MESHES; i++ ) @@ -163,6 +213,7 @@ public: //Place the various buttons on the bottom of the screen, with title labels where necessary. void SetupButtons( Layer layer ) { +#if 1 //Text label title for changing model or shader. TextLabel changeTitleLabel = TextLabel::New( "Switch" ); changeTitleLabel.SetResizePolicy( ResizePolicy::USE_NATURAL_SIZE, Dimension::ALL_DIMENSIONS ); @@ -170,7 +221,7 @@ public: changeTitleLabel.SetParentOrigin( Vector3( 0.2, BUTTONS_OFFSET_BOTTOM, 0.5 ) ); changeTitleLabel.SetAnchorPoint( AnchorPoint::BOTTOM_CENTER ); layer.Add( changeTitleLabel ); - +#endif //Create button for model changing PushButton modelButton = Toolkit::PushButton::New(); modelButton.SetResizePolicy( ResizePolicy::USE_NATURAL_SIZE, Dimension::ALL_DIMENSIONS ); @@ -180,6 +231,7 @@ public: modelButton.SetLabelText( "Model" ); changeTitleLabel.Add( modelButton ); +#if 0 //Create button for shader changing PushButton shaderButton = Toolkit::PushButton::New(); shaderButton.SetResizePolicy( ResizePolicy::USE_NATURAL_SIZE, Dimension::ALL_DIMENSIONS ); @@ -197,6 +249,7 @@ public: pauseButton.SetAnchorPoint( AnchorPoint::TOP_CENTER ); pauseButton.SetLabelText( " || " ); layer.Add( pauseButton ); +#endif //Text label title for light position mode. TextLabel lightTitleLabel = TextLabel::New( "Light Position" ); @@ -206,6 +259,7 @@ public: lightTitleLabel.SetAnchorPoint( AnchorPoint::BOTTOM_CENTER ); layer.Add( lightTitleLabel ); +#if 0 //Create button for switching between manual and fixed light position. PushButton lightButton = Toolkit::PushButton::New(); lightButton.SetResizePolicy( ResizePolicy::USE_NATURAL_SIZE, Dimension::ALL_DIMENSIONS ); @@ -214,6 +268,7 @@ public: lightButton.SetAnchorPoint( AnchorPoint::TOP_CENTER ); lightButton.SetLabelText( "FIXED" ); lightTitleLabel.Add( lightButton ); +#endif } //Add a point light source the the scene, on a layer above the first. @@ -466,7 +521,6 @@ public: return true; } - //Switch between a fixed light source in front of the screen, and a light source the user can drag around. bool OnChangeLightModeClicked( Toolkit::Button button ) { @@ -502,6 +556,238 @@ public: } private: + + /** + * @brief Struct to store the position, normal and texture coordinates of a single vertex. + */ + struct TexturedVertex + { + Vector3 position; + Vector3 normal; + Vector2 textureCoord; + }; + + /** + * @brief Creates a geometry object from vertices and indices. + * @param[in] vertices The object vertices + * @param[in] indices The object indices + * @return A geometry object + */ + Geometry CreateTexturedGeometry( Vector& vertices, Vector& indices ) + { + // Vertices + Property::Map vertexFormat; + vertexFormat[POSITION] = Property::VECTOR3; + vertexFormat[NORMAL] = Property::VECTOR3; + vertexFormat[TEXTURE] = Property::VECTOR2; + + PropertyBuffer surfaceVertices = PropertyBuffer::New( vertexFormat ); + surfaceVertices.SetData( &vertices[0u], vertices.Size() ); + + Geometry geometry = Geometry::New(); + geometry.AddVertexBuffer( surfaceVertices ); + + // Indices for triangle formulation + geometry.SetIndexBuffer( &indices[0u], indices.Size() ); + return geometry; + } + + /** + * @brief Creates a renderer from a geometry object. + * @param[in] geometry The geometry to use + * @param[in] dimensions The dimensions (will be passed in to the shader) + * @param[in] textured Set to true to use the texture versions of the shaders + * @param[in] color The base color for the renderer + * @return A renderer object + */ + Renderer CreateRenderer( Geometry geometry, Vector3 dimensions, bool textured, Vector4 color ) + { + Stage stage = Stage::GetCurrent(); + Shader shader; + + if( textured ) + { + shader = Shader::New( VERTEX_SHADER_TEXTURED, FRAGMENT_SHADER_TEXTURED ); + } + else + { + shader = Shader::New( VERTEX_SHADER, FRAGMENT_SHADER ); + } + + // Here we modify the light position based on half the stage size as a pre-calculation step. + // This avoids the work having to be done in the shader. + shader.RegisterProperty( LIGHT_POSITION_UNIFORM_NAME, Vector3( -stage.GetSize().width / 2.0f, -stage.GetSize().width / 2.0f, 1000.0f ) ); + shader.RegisterProperty( COLOR_UNIFORM_NAME, color ); + shader.RegisterProperty( OBJECT_DIMENSIONS_UNIFORM_NAME, dimensions ); + + return Renderer::New( geometry, shader ); + } + + /** + * @brief Helper method to create a TextureSet from an image URL. + * @param[in] url An image URL + * @return A TextureSet object + */ + TextureSet CreateTextureSet( const char* url ) + { + TextureSet textureSet = TextureSet::New(); + + if( textureSet ) + { + Texture texture = DemoHelper::LoadTexture( url ); + if( texture ) + { + textureSet.SetTexture( 0u, texture ); + } + } + + return textureSet; + } + + /** + * @brief Creates a geometry object for a cube (or cuboid). + * @param[in] dimensions The desired cube dimensions + * @param[in] reflectVerticalUVs Set to True to force the UVs to be vertically flipped + * @return A Geometry object + */ + Geometry CreateCubeVertices( Vector3 dimensions, bool reflectVerticalUVs ) + { + Vector vertices; + Vector indices; + int vertexIndex = 0u; // Tracks progress through vertices. + float scaledX = 0.5f * dimensions.x; + float scaledY = 0.5f * dimensions.y; + float scaledZ = 0.5f * dimensions.z; + float verticalTextureCoord = reflectVerticalUVs ? 0.0f : 1.0f; + + vertices.Resize( 4u * 6u ); // 4 vertices x 6 faces + + Vector positions; // Stores vertex positions, which are shared between vertexes at the same position but with a different normal. + positions.Resize( 8u ); + Vector normals; // Stores normals, which are shared between vertexes of the same face. + normals.Resize( 6u ); + + positions[0] = Vector3( -scaledX, scaledY, -scaledZ ); + positions[1] = Vector3( scaledX, scaledY, -scaledZ ); + positions[2] = Vector3( scaledX, scaledY, scaledZ ); + positions[3] = Vector3( -scaledX, scaledY, scaledZ ); + positions[4] = Vector3( -scaledX, -scaledY, -scaledZ ); + positions[5] = Vector3( scaledX, -scaledY, -scaledZ ); + positions[6] = Vector3( scaledX, -scaledY, scaledZ ); + positions[7] = Vector3( -scaledX, -scaledY, scaledZ ); + + normals[0] = Vector3( 0, 1, 0 ); + normals[1] = Vector3( 0, 0, -1 ); + normals[2] = Vector3( 1, 0, 0 ); + normals[3] = Vector3( 0, 0, 1 ); + normals[4] = Vector3( -1, 0, 0 ); + normals[5] = Vector3( 0, -1, 0 ); + + // Top face, upward normals. + for( int i = 0; i < 4; ++i, ++vertexIndex ) + { + vertices[vertexIndex].position = positions[i]; + vertices[vertexIndex].normal = normals[0]; + // The below logic forms the correct U/V pairs for a quad when "i" goes from 0 to 3. + vertices[vertexIndex].textureCoord = Vector2( ( i == 1 || i == 2 ) ? 1.0f : 0.0f, ( i == 2 || i == 3 ) ? 1.0f : 0.0f ); + } + + // Top face, outward normals. + for( int i = 0; i < 4; ++i, vertexIndex += 2 ) + { + vertices[vertexIndex].position = positions[i]; + vertices[vertexIndex].normal = normals[i + 1]; + + if( i == 3 ) + { + // End, so loop around. + vertices[vertexIndex + 1].position = positions[0]; + } + else + { + vertices[vertexIndex + 1].position = positions[i + 1]; + } + vertices[vertexIndex + 1].normal = normals[i + 1]; + + vertices[vertexIndex].textureCoord = Vector2( 0.0f, verticalTextureCoord ); + vertices[vertexIndex+1].textureCoord = Vector2( 1.0f, verticalTextureCoord ); + } + + // Flip the vertical texture coord for the UV values of the bottom points. + verticalTextureCoord = 1.0f - verticalTextureCoord; + + // Bottom face, outward normals. + for( int i = 0; i < 4; ++i, vertexIndex += 2 ) + { + vertices[vertexIndex].position = positions[i + 4]; + vertices[vertexIndex].normal = normals[i + 1]; + + if( i == 3 ) + { + // End, so loop around. + vertices[vertexIndex + 1].position = positions[4]; + } + else + { + vertices[vertexIndex + 1].position = positions[i + 5]; + } + vertices[vertexIndex + 1].normal = normals[i + 1]; + + vertices[vertexIndex].textureCoord = Vector2( 0.0f, verticalTextureCoord ); + vertices[vertexIndex+1].textureCoord = Vector2( 1.0f, verticalTextureCoord ); + } + + // Bottom face, downward normals. + for( int i = 0; i < 4; ++i, ++vertexIndex ) + { + // Reverse positions for bottom face to keep triangles clockwise (for culling). + vertices[vertexIndex].position = positions[ 7 - i ]; + vertices[vertexIndex].normal = normals[5]; + // The below logic forms the correct U/V pairs for a quad when "i" goes from 0 to 3. + vertices[vertexIndex].textureCoord = Vector2( ( i == 1 || i == 2 ) ? 1.0f : 0.0f, ( i == 2 || i == 3 ) ? 1.0f : 0.0f ); + } + + // Create cube indices. + int triangleIndex = 0u; //Track progress through indices. + indices.Resize( 3u * 12u ); // 3 points x 12 triangles. + + // Top face. + indices[triangleIndex] = 0; + indices[triangleIndex + 1] = 1; + indices[triangleIndex + 2] = 2; + indices[triangleIndex + 3] = 2; + indices[triangleIndex + 4] = 3; + indices[triangleIndex + 5] = 0; + triangleIndex += 6; + + int topFaceStart = 4u; + int bottomFaceStart = topFaceStart + 8u; + + // Side faces. + for( int i = 0; i < 8; i += 2, triangleIndex += 6 ) + { + indices[triangleIndex ] = i + topFaceStart; + indices[triangleIndex + 1] = i + bottomFaceStart + 1; + indices[triangleIndex + 2] = i + topFaceStart + 1; + indices[triangleIndex + 3] = i + topFaceStart; + indices[triangleIndex + 4] = i + bottomFaceStart; + indices[triangleIndex + 5] = i + bottomFaceStart + 1; + } + + // Bottom face. + indices[triangleIndex] = 20; + indices[triangleIndex + 1] = 21; + indices[triangleIndex + 2] = 22; + indices[triangleIndex + 3] = 22; + indices[triangleIndex + 4] = 23; + indices[triangleIndex + 5] = 20; + + // Use the helper method to create the geometry object. + return CreateTexturedGeometry( vertices, indices ); + } + +private: + Application& mApplication; //The models displayed on screen, including information about rotation. diff --git a/examples/mesh-visual/mesh-visual-shaders.h b/examples/mesh-visual/mesh-visual-shaders.h new file mode 100644 index 0000000..9bd88b8 --- /dev/null +++ b/examples/mesh-visual/mesh-visual-shaders.h @@ -0,0 +1,122 @@ +#ifndef DALI_DEMO_MESH_VISUAL_SHADERS_H +#define DALI_DEMO_MESH_VISUAL_SHADERS_H + +/* + * Copyright (c) 2016 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. + */ + +// EXTERNAL INCLUDES +#include + +// Shader uniforms: +const char * const COLOR_UNIFORM_NAME( "uColor" ); +const char * const OBJECT_DIMENSIONS_UNIFORM_NAME( "uObjectDimensions" ); +const char * const STAGE_SIZE_UNIFORM_NAME( "uStageSize" ); +const char * const LIGHT_POSITION_UNIFORM_NAME = "uLightPosition"; +const char * const POSITION( "aPosition"); +const char * const NORMAL( "aNormal" ); +const char * const TEXTURE( "aTexCoord" ); + +// Shader for todor (vertex): +const char* VERTEX_SHADER = DALI_COMPOSE_SHADER( + attribute mediump vec3 aPosition; + attribute highp vec3 aNormal; + attribute highp vec2 aTexCoord; + + varying mediump vec2 vTexCoord; + uniform mediump mat4 uMvpMatrix; + uniform mediump vec3 uSize; + uniform mediump vec3 uObjectDimensions; + varying mediump vec3 vIllumination; + uniform mediump mat4 uModelView; + uniform mediump mat4 uViewMatrix; + uniform mediump mat3 uNormalMatrix; + uniform mediump vec3 uLightPosition; + + void main() + { + mediump vec4 vertexPosition = vec4( aPosition * uObjectDimensions, 1.0 ); + vertexPosition = uMvpMatrix * vertexPosition; + + vec4 mvVertexPosition = uModelView * vertexPosition; + + vec3 vectorToLight = normalize( mat3( uViewMatrix ) * uLightPosition - mvVertexPosition.xyz ); + + vec3 normal = uNormalMatrix * aNormal; + float lightDiffuse = max( dot( vectorToLight, normal ), 0.0 ); + vIllumination = vec3( lightDiffuse * 0.5 + 0.5 ); + + gl_Position = vertexPosition; + } +); + +const char* FRAGMENT_SHADER = DALI_COMPOSE_SHADER( + varying mediump vec2 vTexCoord; + varying mediump vec3 vIllumination; + uniform lowp vec4 uColor; + uniform sampler2D sTexture; + + void main() + { + gl_FragColor = vec4( vIllumination.rgb * uColor.rgb, uColor.a ); + } +); + +const char* VERTEX_SHADER_TEXTURED = DALI_COMPOSE_SHADER( + attribute mediump vec3 aPosition; + attribute highp vec3 aNormal; + attribute highp vec2 aTexCoord; + + varying mediump vec2 vTexCoord; + uniform mediump mat4 uMvpMatrix; + uniform mediump vec3 uSize; + uniform mediump vec3 uObjectDimensions; + varying mediump vec3 vIllumination; + uniform mediump mat4 uModelView; + uniform mediump mat4 uViewMatrix; + uniform mediump mat3 uNormalMatrix; + uniform mediump vec3 uLightPosition; + + void main() + { + mediump vec4 vertexPosition = vec4( aPosition * uObjectDimensions, 1.0 ); + vertexPosition = uMvpMatrix * vertexPosition; + + vec4 mvVertexPosition = uModelView * vertexPosition; + + vec3 vectorToLight = normalize( mat3( uViewMatrix ) * uLightPosition - mvVertexPosition.xyz ); + + vec3 normal = uNormalMatrix * aNormal; + float lightDiffuse = max( dot( vectorToLight, normal ), 0.0 ); + vIllumination = vec3( lightDiffuse * 0.5 + 0.5 ); + + vTexCoord = aTexCoord; + gl_Position = vertexPosition; + } +); + +const char* FRAGMENT_SHADER_TEXTURED = DALI_COMPOSE_SHADER( + varying mediump vec2 vTexCoord; + varying mediump vec3 vIllumination; + uniform lowp vec4 uColor; + uniform sampler2D sTexture; + + void main() + { + gl_FragColor = vec4( texture2D( sTexture, vTexCoord ).rgb * vIllumination.rgb * uColor.rgb, uColor.a ); + } +); + +#endif // DALI_DEMO_MESH_VISUAL_SHADERS_H