Merge "Tizen Directory Migration" into devel/master
[platform/core/uifw/dali-toolkit.git] / dali-toolkit / internal / controls / renderers / mesh / mesh-renderer.cpp
index dd52948..c2316af 100644 (file)
@@ -20,7 +20,6 @@
 
 // EXTERNAL INCLUDES
 #include <dali/integration-api/debug.h>
-#include <dali/public-api/images/resource-image.h>
 #include <dali/public-api/common/stage.h>
 #include <dali/devel-api/adaptor-framework/bitmap-loader.h>
 #include <dali/devel-api/adaptor-framework/file-loader.h>
@@ -28,8 +27,6 @@
 
 //INTERNAL INCLUDES
 #include <dali-toolkit/internal/controls/renderers/renderer-string-constants.h>
-#include <dali-toolkit/internal/controls/renderers/renderer-factory-impl.h>
-#include <dali-toolkit/internal/controls/renderers/renderer-factory-cache.h>
 #include <dali-toolkit/internal/controls/renderers/control-renderer-data-impl.h>
 
 namespace Dali
@@ -83,9 +80,13 @@ enum TextureIndex
   GLOSS_INDEX = 2u
 };
 
-const char * const RENDERER_TYPE_VALUE( "mesh" ); //String label for which type of control renderer this is.
-const char * const LIGHT_POSITION( "uLightPosition" ); //Shader property
-const char * const OBJECT_MATRIX( "uObjectMatrix" ); //Shader property
+//Shader properties
+const char * const OBJECT_MATRIX_UNIFORM_NAME( "uObjectMatrix" );
+const char * const STAGE_OFFSET_UNIFORM_NAME( "uStageOffset" );
+
+const char * const SHADER_TYPE_TEXTURELESS( "TEXTURELESS" );
+const char * const SHADER_TYPE_DIFFUSE_TEXTURE( "DIFFUSE_TEXTURE" );
+const char * const SHADER_TYPE_ALL_TEXTURES( "ALL_TEXTURES" );
 
 //Shaders
 //If a shader requires certain textures, they must be listed in order,
@@ -99,24 +100,27 @@ const char* SIMPLE_VERTEX_SHADER = DALI_COMPOSE_SHADER(
   uniform mediump vec3 uSize;\n
   uniform mediump mat4 uMvpMatrix;\n
   uniform mediump mat4 uModelView;\n
+  uniform mediump mat4 uViewMatrix;\n
   uniform mediump mat3 uNormalMatrix;
   uniform mediump mat4 uObjectMatrix;\n
-  uniform mediump vec3 uLightPosition;\n
+  uniform mediump vec3 lightPosition;\n
+  uniform mediump vec2 uStageOffset;\n
 
   void main()\n
   {\n
-    vec4 vertexPosition = vec4( aPosition * min( uSize.x, uSize.y ), 1.0 );\n
-    vertexPosition = uObjectMatrix * vertexPosition;\n
+    vec4 normalisedVertexPosition = vec4( aPosition * min( uSize.x, uSize.y ), 1.0 );\n
+    vec4 vertexPosition = uObjectMatrix * normalisedVertexPosition;\n
     vertexPosition = uMvpMatrix * vertexPosition;\n
 
     //Illumination in Model-View space - Transform attributes and uniforms\n
-    vec4 vertPos = uModelView * vec4( aPosition.xyz, 1.0 );\n
+    vec4 mvVertexPosition = uModelView * normalisedVertexPosition;\n
     vec3 normal = uNormalMatrix * mat3( uObjectMatrix ) * aNormal;\n
-    vec4 centre = uModelView * vec4( 0.0, 0.0, 0.0, 1.0 );\n
-    vec4 lightPos = vec4( centre.x, centre.y, uLightPosition.z, 1.0 );\n
-    vec3 vecToLight = normalize( lightPos.xyz - vertPos.xyz );\n
 
-    float lightDiffuse = max( dot( vecToLight, normal ), 0.0 );\n
+    vec4 mvLightPosition = vec4( ( lightPosition.xy - uStageOffset ), lightPosition.z, 1.0 );\n
+    mvLightPosition = uViewMatrix * mvLightPosition;\n
+    vec3 vectorToLight = normalize( mvLightPosition.xyz - mvVertexPosition.xyz );\n
+
+    float lightDiffuse = max( dot( vectorToLight, normal ), 0.0 );\n
     vIllumination = vec3( lightDiffuse * 0.5 + 0.5 );\n
 
     gl_Position = vertexPosition;\n
@@ -146,33 +150,34 @@ const char* VERTEX_SHADER = DALI_COMPOSE_SHADER(
   uniform mediump vec3 uSize;\n
   uniform mediump mat4 uMvpMatrix;\n
   uniform mediump mat4 uModelView;
+  uniform mediump mat4 uViewMatrix;\n
   uniform mediump mat3 uNormalMatrix;
   uniform mediump mat4 uObjectMatrix;\n
-  uniform mediump vec3 uLightPosition;\n
+  uniform mediump vec3 lightPosition;\n
+  uniform mediump vec2 uStageOffset;\n
 
   void main()
   {\n
-    vec4 vertexPosition = vec4( aPosition * min( uSize.x, uSize.y ), 1.0 );\n
-    vertexPosition = uObjectMatrix * vertexPosition;\n
+    vec4 normalisedVertexPosition = vec4( aPosition * min( uSize.x, uSize.y ), 1.0 );\n
+    vec4 vertexPosition = uObjectMatrix * normalisedVertexPosition;\n
     vertexPosition = uMvpMatrix * vertexPosition;\n
 
     //Illumination in Model-View space - Transform attributes and uniforms\n
-    vec4 vertPos = uModelView * vec4( aPosition.xyz, 1.0 );\n
-    vec4 centre = uModelView * vec4( 0.0, 0.0, 0.0, 1.0 );\n
-    vec4 lightPos = vec4( centre.x, centre.y, uLightPosition.z, 1.0 );\n
+    vec4 mvVertexPosition = uModelView * normalisedVertexPosition;\n
     vec3 normal = normalize( uNormalMatrix * mat3( uObjectMatrix ) * aNormal );\n
 
-    vec3 vecToLight = normalize( lightPos.xyz - vertPos.xyz );\n
-    vec3 viewDir = normalize( -vertPos.xyz );
+    vec4 mvLightPosition = vec4( ( lightPosition.xy - uStageOffset ), lightPosition.z, 1.0 );\n
+    mvLightPosition = uViewMatrix * mvLightPosition;\n
+    vec3 vectorToLight = normalize( mvLightPosition.xyz - mvVertexPosition.xyz );\n
 
-    vec3 halfVector = normalize( viewDir + vecToLight );
+    vec3 viewDirection = normalize( -mvVertexPosition.xyz );
 
-    float lightDiffuse = dot( vecToLight, normal );\n
+    float lightDiffuse = dot( vectorToLight, normal );\n
     lightDiffuse = max( 0.0,lightDiffuse );\n
     vIllumination = vec3( lightDiffuse * 0.5 + 0.5 );\n
 
-    vec3 reflectDir = reflect( -vecToLight, normal );
-    vSpecular = pow( max( dot( reflectDir, viewDir ), 0.0 ), 4.0 );
+    vec3 reflectDirection = reflect( -vectorToLight, normal );
+    vSpecular = pow( max( dot( reflectDirection, viewDirection ), 0.0 ), 4.0 );
 
     vTexCoord = aTexCoord;\n
     gl_Position = vertexPosition;\n
@@ -209,31 +214,32 @@ const char* NORMAL_MAP_VERTEX_SHADER = DALI_COMPOSE_SHADER(
   uniform mediump vec3 uSize;\n
   uniform mediump mat4 uMvpMatrix;\n
   uniform mediump mat4 uModelView;
+  uniform mediump mat4 uViewMatrix;\n
   uniform mediump mat3 uNormalMatrix;
   uniform mediump mat4 uObjectMatrix;\n
-  uniform mediump vec3 uLightPosition;\n
-
+  uniform mediump vec3 lightPosition;\n
+  uniform mediump vec2 uStageOffset;\n
   void main()
   {\n
-    vec4 vertexPosition = vec4( aPosition * min( uSize.x, uSize.y ), 1.0 );\n
-    vertexPosition = uObjectMatrix * vertexPosition;\n
+    vec4 normalisedVertexPosition = vec4( aPosition * min( uSize.x, uSize.y ), 1.0 );\n
+    vec4 vertexPosition = uObjectMatrix * normalisedVertexPosition;\n
     vertexPosition = uMvpMatrix * vertexPosition;\n
 
-    vec4 vertPos = uModelView * vec4( aPosition.xyz, 1.0 );\n
-    vec4 centre = uModelView * vec4( 0.0, 0.0, 0.0, 1.0 );\n
-    vec4 lightPos = vec4( centre.x, centre.y, uLightPosition.z, 1.0 );\n
+    vec4 mvVertexPosition = uModelView * normalisedVertexPosition;\n
 
-    vec3 tangent = normalize( uNormalMatrix * aTangent );
-    vec3 binormal = normalize( uNormalMatrix * aBiNormal );
+    vec3 tangent = normalize( uNormalMatrix * mat3( uObjectMatrix ) * aTangent );
+    vec3 binormal = normalize( uNormalMatrix * mat3( uObjectMatrix ) * aBiNormal );
     vec3 normal = normalize( uNormalMatrix * mat3( uObjectMatrix ) * aNormal );
 
-    vec3 vecToLight = normalize( lightPos.xyz - vertPos.xyz );\n
-    vLightDirection.x = dot( vecToLight, tangent );
-    vLightDirection.y = dot( vecToLight, binormal );
-    vLightDirection.z = dot( vecToLight, normal );
+    vec4 mvLightPosition = vec4( ( lightPosition.xy - uStageOffset ), lightPosition.z, 1.0 );\n
+    mvLightPosition = uViewMatrix * mvLightPosition;\n
+    vec3 vectorToLight = normalize( mvLightPosition.xyz - mvVertexPosition.xyz );\n
+    vLightDirection.x = dot( vectorToLight, tangent );
+    vLightDirection.y = dot( vectorToLight, binormal );
+    vLightDirection.z = dot( vectorToLight, normal );
 
-    vec3 viewDir = normalize( -vertPos.xyz );
-    vec3 halfVector = normalize( viewDir + vecToLight );
+    vec3 viewDirection = normalize( -mvVertexPosition.xyz );
+    vec3 halfVector = normalize( viewDirection + vectorToLight );
     vHalfVector.x = dot( halfVector, tangent );
     vHalfVector.y = dot( halfVector, binormal );
     vHalfVector.z = dot( halfVector, normal );
@@ -275,7 +281,8 @@ MeshRenderer::MeshRenderer( RendererFactoryCache& factoryCache )
 : ControlRenderer( factoryCache ),
   mShaderType( ALL_TEXTURES ),
   mUseTexture( true ),
-  mUseMipmapping( true )
+  mUseMipmapping( true ),
+  mUseSoftNormals( true )
 {
 }
 
@@ -292,7 +299,6 @@ void MeshRenderer::DoInitialize( Actor& actor, const Property::Map& propertyMap
   }
 
   Property::Value* materialUrl = propertyMap.Find( MATERIAL_URL );
-
   if( !materialUrl || !materialUrl->Get( mMaterialUrl ) || mMaterialUrl.empty() )
   {
     mUseTexture = false;
@@ -306,32 +312,60 @@ void MeshRenderer::DoInitialize( Actor& actor, const Property::Map& propertyMap
     mTexturesPath.clear();
   }
 
+  Property::Value* shaderType = propertyMap.Find( SHADER_TYPE );
+  if( shaderType )
+  {
+    std::string shaderTypeString;
+    if( shaderType->Get( shaderTypeString ) )
+    {
+      if( shaderTypeString == SHADER_TYPE_TEXTURELESS )
+      {
+        mShaderType = TEXTURELESS;
+      }
+      else if( shaderTypeString == SHADER_TYPE_DIFFUSE_TEXTURE )
+      {
+        mShaderType = DIFFUSE_TEXTURE;
+      }
+      else if( shaderTypeString == SHADER_TYPE_ALL_TEXTURES )
+      {
+        mShaderType = ALL_TEXTURES;
+      }
+      else
+      {
+        DALI_LOG_ERROR( "Unknown shader type provided to the MeshRenderer object.\n");
+      }
+    }
+  }
+
   Property::Value* useMipmapping = propertyMap.Find( USE_MIPMAPPING );
   if( useMipmapping )
   {
     useMipmapping->Get( mUseMipmapping );
   }
 
-  Property::Value* shaderType = propertyMap.Find( SHADER_TYPE );
-  if( shaderType && shaderType->Get( mShaderTypeString ) )
+  Property::Value* useSoftNormals = propertyMap.Find( USE_SOFT_NORMALS );
+  if( useSoftNormals )
   {
-    if( mShaderTypeString == "textureless" )
-    {
-      mShaderType = TEXTURELESS;
-    }
-    else if( mShaderTypeString == "diffuseTexture" )
-    {
-      mShaderType = DIFFUSE_TEXTURE;
-    }
-    else if( mShaderTypeString == "allTextures" )
-    {
-      mShaderType = ALL_TEXTURES;
-    }
-    else
+    useSoftNormals->Get( mUseSoftNormals );
+  }
+
+  Property::Value* lightPosition = propertyMap.Find( LIGHT_POSITION_UNIFORM_NAME );
+  if( lightPosition )
+  {
+    if( !lightPosition->Get( mLightPosition ) )
     {
-      DALI_LOG_ERROR( "Unknown shader type provided to the MeshRenderer object.\n");
+      DALI_LOG_ERROR( "Invalid value passed for light position in MeshRenderer object.\n" );
+      mLightPosition = Vector3::ZERO;
     }
   }
+  else
+  {
+    //Default behaviour is to place the light directly in front of the object,
+    // at a reasonable distance to light everything on screen.
+    Stage stage = Stage::GetCurrent();
+
+    mLightPosition = Vector3( stage.GetSize().width / 2, stage.GetSize().height / 2, stage.GetSize().width * 5 );
+  }
 }
 
 void MeshRenderer::SetSize( const Vector2& size )
@@ -361,11 +395,37 @@ void MeshRenderer::DoSetOnStage( Actor& actor )
 void MeshRenderer::DoCreatePropertyMap( Property::Map& map ) const
 {
   map.Clear();
-  map.Insert( RENDERER_TYPE, RENDERER_TYPE_VALUE );
+  map.Insert( RENDERER_TYPE, MESH_RENDERER );
   map.Insert( OBJECT_URL, mObjectUrl );
   map.Insert( MATERIAL_URL, mMaterialUrl );
   map.Insert( TEXTURES_PATH, mTexturesPath );
-  map.Insert( SHADER_TYPE, mShaderTypeString );
+
+  std::string shaderTypeString;
+  switch( mShaderType )
+  {
+    case ALL_TEXTURES:
+    {
+      shaderTypeString = SHADER_TYPE_ALL_TEXTURES;
+      break;
+    }
+
+    case DIFFUSE_TEXTURE:
+    {
+      shaderTypeString = SHADER_TYPE_DIFFUSE_TEXTURE;
+      break;
+    }
+
+    case TEXTURELESS:
+    {
+      shaderTypeString = SHADER_TYPE_TEXTURELESS;
+      break;
+    }
+  }
+  map.Insert( SHADER_TYPE, shaderTypeString );
+
+  map.Insert( USE_MIPMAPPING, mUseMipmapping );
+  map.Insert( USE_SOFT_NORMALS, mUseSoftNormals );
+  map.Insert( LIGHT_POSITION_UNIFORM_NAME, mLightPosition );
 }
 
 void MeshRenderer::InitializeRenderer()
@@ -420,13 +480,15 @@ void MeshRenderer::SupplyEmptyGeometry()
 void MeshRenderer::UpdateShaderUniforms()
 {
   Stage stage = Stage::GetCurrent();
-
-  Vector3 lightPosition( 0, 0, stage.GetSize().width );
-  mShader.RegisterProperty( LIGHT_POSITION, lightPosition );
+  float width = stage.GetSize().width;
+  float height = stage.GetSize().height;
 
   Matrix scaleMatrix;
   scaleMatrix.SetIdentityAndScale( Vector3( 1.0, -1.0, 1.0 ) );
-  mShader.RegisterProperty( OBJECT_MATRIX, scaleMatrix );
+
+  mShader.RegisterProperty( STAGE_OFFSET_UNIFORM_NAME, Vector2( width, height ) / 2.0f );
+  mShader.RegisterProperty( LIGHT_POSITION_UNIFORM_NAME, mLightPosition );
+  mShader.RegisterProperty( OBJECT_MATRIX_UNIFORM_NAME, scaleMatrix );
 }
 
 void MeshRenderer::CreateShader()
@@ -473,7 +535,7 @@ bool MeshRenderer::CreateGeometry()
   }
 
   //Create geometry with attributes required by shader.
-  mGeometry = mObjLoader.CreateGeometry( objectProperties );
+  mGeometry = mObjLoader.CreateGeometry( objectProperties, mUseSoftNormals );
 
   if( mGeometry )
   {