Refactored shader effect implementation. 17/24817/3
authorDavid Steele <david.steele@partner.samsung.com>
Tue, 22 Jul 2014 16:05:31 +0000 (17:05 +0100)
committerDavid Steele <david.steele@partner.samsung.com>
Wed, 30 Jul 2014 16:07:11 +0000 (17:07 +0100)
ShaderEffect code was hard to follow, with many methods having the same name
yet performing different functions.

Have refactored the code to use SetProgram() for it's public api, moved and re-wrote
SetPrograms() and SetWrappedProgram() methods from anonymous namespace to private methods
and added a new method called SetProgramImpl() which actually sends the program to the shader
object in the scene graph.

Change-Id: Ic2eaf72a17d337dead1b14746d75f30ffd8ce3f3
Signed-off-by: David Steele <david.steele@partner.samsung.com>
dali/internal/event/effects/shader-effect-impl.cpp
dali/internal/event/effects/shader-effect-impl.h
dali/internal/event/effects/shader-factory.cpp
dali/internal/render/shader-source/custom-mesh-prefix.txt
dali/internal/render/shader-source/mesh-color-no-texture.txt
dali/internal/render/shader-source/mesh.txt

index 163a15c..648675d 100644 (file)
@@ -47,6 +47,7 @@ using Dali::Internal::SceneGraph::AnimatableProperty;
 using Dali::Internal::SceneGraph::PropertyBase;
 using Dali::Internal::SceneGraph::PropertyBase;
 using Dali::Internal::SceneGraph::RenderQueue;
+using std::string;
 
 namespace Dali
 {
@@ -64,6 +65,30 @@ ShaderEffect::DefaultPropertyLookup* ShaderEffect::mDefaultPropertyLookup = NULL
 namespace
 {
 
+struct WrapperStrings
+{
+  const char* vertexShaderPrefix;
+  const char* fragmentShaderPrefix;
+  const char* vertexShaderPostfix;
+  const char* fragmentShaderPostfix;
+};
+
+WrapperStrings customShaderWrappers [] =
+{
+  {
+    CustomImagePrefixVertex.c_str(), CustomImagePrefixFragment.c_str(),
+    CustomImagePostfixVertex.c_str(), CustomImagePostfixFragment.c_str()
+  },
+  {
+    CustomFontPrefixVertex.c_str(), CustomFontPrefixFragment.c_str(),
+    CustomFontPostfixVertex.c_str(), CustomFontPostfixFragment.c_str()
+  },
+  {
+    CustomMeshPrefixVertex.c_str(), CustomMeshPrefixFragment.c_str(),
+    MeshVertex.c_str(), MeshFragment.c_str()
+  }
+};
+
 BaseHandle Create()
 {
   Internal::ShaderEffectPtr internal = Internal::ShaderEffect::New( );
@@ -92,175 +117,6 @@ const Property::Type DEFAULT_PROPERTY_TYPES[DEFAULT_PROPERTY_COUNT] =
   Property::INTEGER,  // "geometry-hints",
 };
 
-void SetShaderProgram( const std::string& imageVertexSnippet, const std::string& imageFragmentSnippet,
-                       const std::string& textVertexSnippet, const std::string& textFragmentSnippet,
-                       const std::string& texturedMeshVertexSnippet, const std::string& texturedMeshFragmentSnippet,
-                       const std::string& meshVertexSnippet, const std::string& meshFragmentSnippet,
-                       const std::string& vertexShaderPrefix, const std::string& fragmentShaderPrefix,
-                       ShaderEffectPtr shaderEffect )
-{
-  DALI_ASSERT_DEBUG(shaderEffect);
-
-  // create complete shader program strings for GEOMETRY_TYPE_IMAGE
-  std::string vertexSource = vertexShaderPrefix + CustomImagePrefixVertex;
-  std::string fragmentSource = fragmentShaderPrefix + CustomImagePrefixFragment;
-
-  // Append the custom vertex shader code if supplied, otherwise append the default
-  if ( imageVertexSnippet.length() > 0 )
-  {
-    vertexSource.append( imageVertexSnippet );
-  }
-  else
-  {
-    vertexSource.append( CustomImagePostfixVertex );
-  }
-
-  // Append the custom fragment shader code if supplied, otherwise append the default
-  if ( imageFragmentSnippet.length() > 0 )
-  {
-    fragmentSource.append( imageFragmentSnippet );
-  }
-  else
-  {
-    fragmentSource.append( CustomImagePostfixFragment );
-  }
-
-  // Add the program
-  shaderEffect->SetProgram( GEOMETRY_TYPE_IMAGE, SHADER_SUBTYPE_ALL, vertexSource, fragmentSource );
-
-
-  // create complete shader program strings for GEOMETRY_TYPE_TEXT
-  vertexSource = CustomFontPrefixVertex;
-  fragmentSource = CustomFontPrefixFragment;
-
-  // Append the custom vertex shader code if supplied, otherwise append the default
-  if ( textVertexSnippet.length() > 0 )
-  {
-    vertexSource.append( textVertexSnippet );
-  }
-  else
-  {
-    vertexSource.append( CustomFontPostfixVertex );
-  }
-
-  // Append the custom fragment shader code if supplied, otherwise append the default
-  if ( textFragmentSnippet.length() > 0 )
-  {
-    fragmentSource.append( textFragmentSnippet );
-  }
-  else
-  {
-    fragmentSource.append( CustomFontPostfixFragment );
-  }
-
-  // Add Program. Note, we only change the default program here, and leave the other sub-types as-is
-  shaderEffect->SetProgram(GEOMETRY_TYPE_TEXT, SHADER_DEFAULT, vertexSource, fragmentSource);
-
-  // create complete shader program strings for GEOMETRY_TYPE_TEXTURED_MESH
-  if( texturedMeshVertexSnippet.length() > 0 )
-  {
-    vertexSource = CustomMeshPrefixVertex;
-    vertexSource.append( texturedMeshVertexSnippet );
-  }
-  else
-  {
-    vertexSource = MeshVertex;
-  }
-
-  if( texturedMeshFragmentSnippet.length() > 0 )
-  {
-    fragmentSource = CustomMeshPrefixFragment;
-    fragmentSource.append( texturedMeshFragmentSnippet );
-  }
-  else
-  {
-    fragmentSource = MeshFragment;
-  }
-
-  // Add Program
-  shaderEffect->SetProgram( GEOMETRY_TYPE_TEXTURED_MESH, SHADER_SUBTYPE_ALL, vertexSource, fragmentSource );
-
-  // create complete shader program strings for GEOMETRY_TYPE_MESH
-  if( meshVertexSnippet.length() > 0 )
-  {
-    vertexSource = CustomMeshPrefixVertex;
-    vertexSource.append( meshVertexSnippet );
-  }
-  else
-  {
-    vertexSource = MeshVertex;
-  }
-
-  if( meshFragmentSnippet.length() > 0 )
-  {
-    fragmentSource = CustomMeshPrefixFragment;
-    fragmentSource.append( meshFragmentSnippet );
-  }
-  else
-  {
-    fragmentSource = MeshFragment;
-  }
-
-  // Add Program
-  shaderEffect->SetProgram( GEOMETRY_TYPE_MESH, SHADER_SUBTYPE_ALL, vertexSource, fragmentSource );
-}
-
-void SetShaderProgram( const std::string& vertexShaderPrefix, const std::string& vertexShader,
-                       const std::string& fragmentShaderPrefix, const std::string& fragmentShader,
-                       GeometryType geometryTypes,
-                       ShaderEffectPtr shaderEffect )
-{
-  DALI_ASSERT_DEBUG(shaderEffect);
-
-  if( geometryTypes & GEOMETRY_TYPE_IMAGE )
-  {
-    shaderEffect->SetProgram( GEOMETRY_TYPE_IMAGE, SHADER_SUBTYPE_ALL,
-                              vertexShaderPrefix + CustomImagePrefixVertex + ( !vertexShader.empty() ? vertexShader : CustomImagePostfixVertex ),
-                              fragmentShaderPrefix + CustomImagePrefixFragment + ( !fragmentShader.empty() ? fragmentShader : CustomImagePostfixFragment ) );
-  }
-  else
-  {
-    shaderEffect->SetProgram( GEOMETRY_TYPE_IMAGE, SHADER_SUBTYPE_ALL,
-                              CustomImagePrefixVertex + CustomImagePostfixVertex,
-                              CustomImagePrefixFragment + CustomImagePostfixFragment );
-  }
-
-  if( geometryTypes & GEOMETRY_TYPE_TEXT )
-  {
-    shaderEffect->SetProgram( GEOMETRY_TYPE_TEXT, SHADER_DEFAULT,
-                              vertexShaderPrefix + CustomFontPrefixVertex + ( !vertexShader.empty() ? vertexShader : CustomFontPostfixVertex ),
-                              fragmentShaderPrefix + CustomFontPrefixFragment + ( !fragmentShader.empty() ? fragmentShader : CustomFontPostfixFragment ) );
-  }
-  else
-  {
-    shaderEffect->SetProgram( GEOMETRY_TYPE_TEXT, SHADER_DEFAULT,
-                              CustomFontPrefixVertex + CustomFontPostfixVertex,
-                              CustomFontPrefixFragment + CustomFontPostfixFragment );
-  }
-
-  if( geometryTypes & GEOMETRY_TYPE_TEXTURED_MESH )
-  {
-    shaderEffect->SetProgram( GEOMETRY_TYPE_TEXTURED_MESH, SHADER_SUBTYPE_ALL,
-                              vertexShaderPrefix + ( !vertexShader.empty() ? CustomMeshPrefixVertex + vertexShader : MeshVertex ),
-                              fragmentShaderPrefix + ( !fragmentShader.empty() ? CustomMeshPrefixFragment + fragmentShader : MeshFragment ) );
-  }
-  else
-  {
-    shaderEffect->SetProgram( GEOMETRY_TYPE_TEXTURED_MESH, SHADER_SUBTYPE_ALL, MeshVertex, MeshFragment );
-  }
-
-  if( geometryTypes & GEOMETRY_TYPE_MESH )
-  {
-    shaderEffect->SetProgram( GEOMETRY_TYPE_MESH, SHADER_SUBTYPE_ALL,
-                              vertexShaderPrefix + ( !vertexShader.empty() ? CustomMeshPrefixVertex + vertexShader : MeshColorNoTextureVertex ),
-                              fragmentShaderPrefix + ( !fragmentShader.empty() ? CustomMeshPrefixFragment + fragmentShader : MeshColorNoTextureFragment ) );
-  }
-  else
-  {
-    shaderEffect->SetProgram( GEOMETRY_TYPE_MESH, SHADER_SUBTYPE_ALL, MeshColorNoTextureVertex, MeshColorNoTextureFragment );
-  }
-}
-
 std::string GetFileContents( const std::string& filename )
 {
   std::ifstream input( filename.c_str() );
@@ -289,7 +145,6 @@ std::string GetShader(const std::string& field, const Property::Value& property)
     }
   }
 
-  // if we got here
   return std::string();
 }
 
@@ -312,53 +167,46 @@ ShaderEffectPtr ShaderEffect::New( Dali::ShaderEffect::GeometryHints hints )
   return shaderEffect;
 }
 
-ShaderEffectPtr ShaderEffect::New( const std::string& vertexShader,
-                                   const std::string& fragmentShader,
+ShaderEffectPtr ShaderEffect::New( const string& vertexShader,
+                                   const string& fragmentShader,
                                    GeometryType geometryType,
                                    Dali::ShaderEffect::GeometryHints hints )
 {
   return NewWithPrefix( "", vertexShader, "", fragmentShader, geometryType, hints);
 }
 
-ShaderEffectPtr ShaderEffect::NewWithPrefix( const std::string& vertexShaderPrefix,
-                                             const std::string& vertexShader,
-                                             const std::string& fragmentShaderPrefix,
-                                             const std::string& fragmentShader,
+ShaderEffectPtr ShaderEffect::NewWithPrefix( const string& vertexShaderPrefix,
+                                             const string& vertexShader,
+                                             const string& fragmentShaderPrefix,
+                                             const string& fragmentShader,
                                              GeometryType geometryTypes,
                                              Dali::ShaderEffect::GeometryHints hints )
 {
   ShaderEffectPtr shaderEffect( New(hints) );
-
   ShaderFactory::LoadTextSubtypeShaders(shaderEffect);
 
-  SetShaderProgram( vertexShaderPrefix, vertexShader,
-                    fragmentShaderPrefix, fragmentShader,
-                    geometryTypes,
-                    shaderEffect );
-
+  shaderEffect->SetPrograms( geometryTypes, vertexShaderPrefix, vertexShader, fragmentShaderPrefix, fragmentShader );
   return shaderEffect;
 }
 
-ShaderEffectPtr ShaderEffect::New( const std::string& imageVertexShader,
-                                   const std::string& imageFragmentShader,
-                                   const std::string& textVertexShader,
-                                   const std::string& textFragmentShader,
-                                   const std::string& texturedMeshVertexShader,
-                                   const std::string& texturedMeshFragmentShader,
-                                   const std::string& meshVertexShader,
-                                   const std::string& meshFragmentShader,
+ShaderEffectPtr ShaderEffect::New( const string& imageVertexShader,
+                                   const string& imageFragmentShader,
+                                   const string& textVertexShader,
+                                   const string& textFragmentShader,
+                                   const string& texturedMeshVertexShader,
+                                   const string& texturedMeshFragmentShader,
+                                   const string& meshVertexShader,
+                                   const string& meshFragmentShader,
                                    Dali::ShaderEffect::GeometryHints hints )
 {
   ShaderEffectPtr shaderEffect( New(hints) );
 
   ShaderFactory::LoadTextSubtypeShaders(shaderEffect);
 
-  SetShaderProgram( imageVertexShader, imageFragmentShader,
-                    textVertexShader,  textFragmentShader,
-                    texturedMeshVertexShader, texturedMeshFragmentShader,
-                    meshVertexShader,  meshFragmentShader,
-                    "", "",
-                    shaderEffect );
+  shaderEffect->SetWrappedProgram( GEOMETRY_TYPE_IMAGE, SHADER_SUBTYPE_ALL, "", "", imageVertexShader, imageFragmentShader );
+  shaderEffect->SetWrappedProgram( GEOMETRY_TYPE_TEXT, SHADER_DEFAULT, "", "", textVertexShader, textFragmentShader );
+  shaderEffect->SetWrappedProgram( GEOMETRY_TYPE_TEXTURED_MESH, SHADER_SUBTYPE_ALL, "", "", texturedMeshVertexShader, texturedMeshFragmentShader );
+  shaderEffect->SetWrappedProgram( GEOMETRY_TYPE_MESH, SHADER_SUBTYPE_ALL, "", "", meshVertexShader, meshFragmentShader );
 
   return shaderEffect;
 }
@@ -454,25 +302,12 @@ const Dali::ShaderEffect::Extension& ShaderEffect::GetExtension() const
 }
 
 void ShaderEffect::SetProgram( GeometryType geometryType, ShaderSubTypes subType,
-                               const std::string& vertexSource, const std::string& fragmentSource,
+                               const string& vertexSource, const string& fragmentSource,
                                ShaderEffect::FixedVertexShader fixedShader )
 {
-  // Load done asynchronously in update thread. SetProgram message below must be processed afterwards.
-  // Therefore, resource manager cannot farm out the loading to the adaptor resource threads,
-  // but must instead use synchronous loading via PlatformAbstraction::LoadFile()
-  size_t shaderHash;
-  ResourceTicketPtr ticket( mShaderFactory.Load(vertexSource, fragmentSource, shaderHash) );
-
-  DALI_LOG_INFO( Debug::Filter::gShader, Debug::General, "ShaderEffect: SetProgram(geometryType %d subType:%d ticket.id:%d)\n", geometryType, subType, ticket->GetId() );
-
-  bool areVerticesFixed = (fixedShader == ShaderEffect::FIXED);
-  // Add shader program to scene-object using a message to the UpdateManager
-  SetShaderProgramMessage( mUpdateManager, *mSceneObject, geometryType, subType, ticket->GetId(), shaderHash, areVerticesFixed );
-
-  mTickets.push_back(ticket);       // add ticket to collection to keep it alive.
+  SetProgramImpl(geometryType, subType, vertexSource, fragmentSource, fixedShader);
 }
 
-
 void ShaderEffect::SetProgram( GeometryType geometryType, ShaderSubTypes subType,
                                const std::string& vertexPrefix, const std::string& fragmentPrefix,
                                const std::string& vertexSource, const std::string& fragmentSource,
@@ -480,7 +315,7 @@ void ShaderEffect::SetProgram( GeometryType geometryType, ShaderSubTypes subType
 {
   const std::string vertex( vertexPrefix + vertexSource );
   const std::string fragment( fragmentPrefix + fragmentSource );
-  SetProgram( geometryType, subType, vertex, fragment, fixedShader );
+  SetProgramImpl( geometryType, subType, vertex, fragment, fixedShader );
 }
 
 void ShaderEffect::Connect()
@@ -655,7 +490,7 @@ void ShaderEffect::SetDefaultProperty( Property::Index index, const Property::Va
           DALI_ASSERT_ALWAYS(!"Geometry type unknown" );
         }
       }
-      SetShaderProgram( vertexPrefix, vertex, fragmentPrefix, fragment, geometryType, ShaderEffectPtr(this) );
+      SetPrograms( geometryType, vertexPrefix, vertex, fragmentPrefix, fragment );
       break;
     }
 
@@ -756,6 +591,131 @@ const PropertyInputImpl* ShaderEffect::GetSceneObjectInputProperty( Property::In
   return entry->second.GetSceneGraphProperty();
 }
 
+void ShaderEffect::SetPrograms( GeometryType  geometryTypes,
+                                const std::string& vertexShaderPrefix,
+                                const std::string& vertexShader,
+                                const std::string& fragmentShaderPrefix,
+                                const std::string& fragmentShader )
+{
+  static std::string emptyStr;
+
+  if( geometryTypes & GEOMETRY_TYPE_IMAGE )
+  {
+    SetWrappedProgram( GEOMETRY_TYPE_IMAGE, SHADER_SUBTYPE_ALL, vertexShaderPrefix, fragmentShaderPrefix, vertexShader, fragmentShader );
+  }
+  else
+  {
+    SetWrappedProgram( GEOMETRY_TYPE_IMAGE, SHADER_SUBTYPE_ALL, emptyStr, emptyStr, emptyStr, emptyStr );
+  }
+
+  if( geometryTypes & GEOMETRY_TYPE_TEXT )
+  {
+    // Only change the default program, leaving the other sub-types as-is.
+    SetWrappedProgram( GEOMETRY_TYPE_TEXT, SHADER_DEFAULT, vertexShaderPrefix, fragmentShaderPrefix, vertexShader, fragmentShader );
+  }
+  else
+  {
+    SetWrappedProgram( GEOMETRY_TYPE_TEXT, SHADER_DEFAULT, emptyStr, emptyStr, emptyStr, emptyStr );
+  }
+
+  if( geometryTypes & GEOMETRY_TYPE_TEXTURED_MESH )
+  {
+    SetWrappedProgram( GEOMETRY_TYPE_TEXTURED_MESH, SHADER_SUBTYPE_ALL, vertexShaderPrefix, fragmentShaderPrefix, vertexShader, fragmentShader );
+  }
+  else
+  {
+    SetWrappedProgram( GEOMETRY_TYPE_TEXTURED_MESH, SHADER_SUBTYPE_ALL, emptyStr, emptyStr, emptyStr, emptyStr );
+  }
+
+  if( geometryTypes & GEOMETRY_TYPE_MESH )
+  {
+    SetWrappedProgram( GEOMETRY_TYPE_MESH, SHADER_SUBTYPE_ALL, vertexShaderPrefix, fragmentShaderPrefix, vertexShader, fragmentShader );
+  }
+  else
+  {
+    SetWrappedProgram( GEOMETRY_TYPE_MESH, SHADER_SUBTYPE_ALL, emptyStr, emptyStr, emptyStr, emptyStr );
+  }
+}
+
+void ShaderEffect::SetWrappedProgram( GeometryType geometryType, ShaderSubTypes subType,
+                                      const string& vertexPrefix, const string& fragmentPrefix,
+                                      const string& vertexSnippet, const string& fragmentSnippet )
+{
+  // create complete shader program strings for the given geometry type
+  unsigned int index = 0;
+  switch( geometryType )
+  {
+    case GEOMETRY_TYPE_IMAGE:
+    {
+      index = 0;
+      break;
+    }
+    case GEOMETRY_TYPE_TEXT:
+    {
+      index = 1;
+      break;
+    }
+    case GEOMETRY_TYPE_MESH:
+    case GEOMETRY_TYPE_TEXTURED_MESH:
+    {
+      index = 2;
+      break;
+    }
+    case GEOMETRY_TYPE_LAST:
+    {
+      DALI_ASSERT_DEBUG(0 && "Wrong geometry type");
+      break;
+    }
+  }
+
+  string vertexSource = vertexPrefix + customShaderWrappers[index].vertexShaderPrefix;
+  string fragmentSource = fragmentPrefix + customShaderWrappers[index].fragmentShaderPrefix;
+
+  // Append the custom vertex shader code if supplied, otherwise append the default
+  if ( vertexSnippet.length() > 0 )
+  {
+    vertexSource.append( vertexSnippet );
+  }
+  else
+  {
+    vertexSource.append( customShaderWrappers[index].vertexShaderPostfix );
+  }
+
+  // Append the custom fragment shader code if supplied, otherwise append the default
+  if ( fragmentSnippet.length() > 0 )
+  {
+    fragmentSource.append( fragmentSnippet );
+  }
+  else
+  {
+    fragmentSource.append( customShaderWrappers[index].fragmentShaderPostfix );
+  }
+
+  // Add the program
+  SetProgramImpl( geometryType, subType, vertexSource, fragmentSource, ShaderEffect::FLEXIBLE );
+}
+
+void ShaderEffect::SetProgramImpl( GeometryType geometryType, ShaderSubTypes subType,
+                                   const string& vertexSource, const string& fragmentSource,
+                                   ShaderEffect::FixedVertexShader fixedShader )
+{
+  // Load done asynchronously in update thread. SetProgram message below must be processed afterwards.
+  // Therefore, resource manager cannot farm out the loading to the adaptor resource threads,
+  // but must instead use synchronous loading via PlatformAbstraction::LoadFile()
+  size_t shaderHash;
+  ResourceTicketPtr ticket( mShaderFactory.Load(vertexSource, fragmentSource, shaderHash) );
+
+  DALI_LOG_INFO( Debug::Filter::gShader, Debug::General, "ShaderEffect: SetProgram(geometryType %d subType:%d ticket.id:%d)\n", geometryType, subType, ticket->GetId() );
+
+  bool areVerticesFixed = (fixedShader == ShaderEffect::FIXED);
+
+  // Add shader program to scene-object using a message to the UpdateManager
+  SetShaderProgramMessage( mUpdateManager, *mSceneObject, geometryType, subType, ticket->GetId(), shaderHash, areVerticesFixed );
+
+  mTickets.push_back(ticket);       // add ticket to collection to keep it alive.
+}
+
+
 } // namespace Internal
 
 } // namespace Dali
index fcd62df..82acf80 100644 (file)
@@ -285,7 +285,48 @@ private:
   ShaderEffect( const ShaderEffect& );
   ShaderEffect& operator=( const ShaderEffect& rhs );
 
-  void OnImageLoaded( Dali::Image image ); ///< just a helper for image loaded callback
+  /**
+   * Set the given program for all shader types set in the geometryType bitfield.
+   * @param[in] geometryType         A GeometryType bitfield
+   * @param[in] vertexShaderPrefix   The prefix source code for the vertex shader
+   * @param[in] vertexShader         The source code for the vertex shader
+   * @param[in] fragmentShaderPrefix The prefix source code for the fragment shader
+   * @param[in] fragmentShader       The source code for the fragment shader
+   */
+  void SetPrograms( GeometryType  geometryTypes,
+                    const std::string& vertexShaderPrefix,
+                    const std::string& vertexShader,
+                    const std::string& fragmentShaderPrefix,
+                    const std::string& fragmentShader );
+
+  /**
+   * Wrap the given prefix and body code around the predefined prefix source for the
+   * given geometry type. Specifying an empty string for the body code means that the
+   * predefined body code is used instead.
+   *
+   * @param[in] geometryType    The GeometryType rendered by the shader program
+   * @param[in] subType         The subtype, one of ShaderSubTypes.
+   * @param[in] vertexPrefix    The prefix source code for the vertex shader
+   * @param[in] fragmentPrefix  The prefix source code for the fragment shader
+   * @param[in] vertexSource    The source code for the vertex shader
+   * @param[in] fragmentSource  The source code for the fragment shader
+   */
+  void SetWrappedProgram( GeometryType geometryType, ShaderSubTypes subType,
+                          const std::string& vertexPrefix, const std::string& fragmentPrefix,
+                          const std::string& vertexSource, const std::string& fragmentSource );
+
+  /**
+   * Send shader program to scene-graph object.
+   * Uses the shader hints to determine whether the vertices are fixed.
+   * @param[in] geometryType    The GeometryType rendered by the shader program
+   * @param[in] subType         The subtype, one of ShaderSubTypes.
+   * @param[in] vertexSource    The source code for the vertex shader
+   * @param[in] fragmentSource  The source code for the fragment shader
+   * @param[in] fixedVertexShader True if this shader doesn't change the vertices
+   */
+  void SetProgramImpl( GeometryType geometryType, ShaderSubTypes subType,
+                       const std::string& vertexSource, const std::string& fragmentSource,
+                       FixedVertexShader fixedVertexShader );
 
 private: // Data
 
index 24ae9f2..8d69fa0 100644 (file)
@@ -123,72 +123,83 @@ void ShaderFactory::LoadDefaultShaders()
   mDefaultShader->SetProgram( GEOMETRY_TYPE_MESH, SHADER_DEFAULT,
                               "", // Vertex shader defs
                               SHADER_DEF_USE_LIGHTING, // fragment shader defs
-                              MeshColorNoTextureVertex, MeshColorNoTextureFragment,
+                              CustomMeshPrefixVertex + MeshColorNoTextureVertex,
+                              CustomMeshPrefixFragment + MeshColorNoTextureFragment,
                               ShaderEffect::FIXED );
 
-  mDefaultShader->SetProgram(GEOMETRY_TYPE_MESH, SHADER_EVENLY_LIT,
-                             "", // Vertex shader defs
-                             "", // fragment shader defs
-                             MeshColorNoTextureVertex, MeshColorNoTextureFragment,
-                             ShaderEffect::FIXED );
-
-  mDefaultShader->SetProgram(GEOMETRY_TYPE_MESH, SHADER_RIGGED_AND_LIT,
-                             SHADER_DEF_USE_BONES,    // vertex shader defs
-                             SHADER_DEF_USE_LIGHTING, // fragment shader defs
-                             MeshColorNoTextureVertex, MeshColorNoTextureFragment,
-                             ShaderEffect::FLEXIBLE);
-
-  mDefaultShader->SetProgram(GEOMETRY_TYPE_MESH, SHADER_RIGGED_AND_EVENLY_LIT,
-                             SHADER_DEF_USE_BONES, // Vertex shader defs
-                             "",                   // Fragment shader defs
-                             MeshColorNoTextureVertex, MeshColorNoTextureFragment,
-                             ShaderEffect::FLEXIBLE);
-
-  mDefaultShader->SetProgram(GEOMETRY_TYPE_MESH, SHADER_RIGGED_AND_VERTEX_COLOR,
-                             (SHADER_DEF_USE_BONES SHADER_DEF_USE_COLOR), // Vertex shader defs
-                             SHADER_DEF_USE_COLOR,                        // Fragment shader defs
-                             MeshColorNoTextureVertex, MeshColorNoTextureFragment,
-                             ShaderEffect::FLEXIBLE);
-
-  mDefaultShader->SetProgram(GEOMETRY_TYPE_MESH, SHADER_VERTEX_COLOR,
-                             SHADER_DEF_USE_COLOR,  // Vertex shader defs
-                             SHADER_DEF_USE_COLOR,  // Fragment shader defs
-                             MeshColorNoTextureVertex, MeshColorNoTextureFragment,
-                             ShaderEffect::FIXED);
+  mDefaultShader->SetProgram( GEOMETRY_TYPE_MESH, SHADER_EVENLY_LIT,
+                              "", // Vertex shader defs
+                              "", // fragment shader defs
+                              CustomMeshPrefixVertex + MeshColorNoTextureVertex,
+                              CustomMeshPrefixFragment + MeshColorNoTextureFragment,
+                              ShaderEffect::FIXED );
+
+  mDefaultShader->SetProgram( GEOMETRY_TYPE_MESH, SHADER_RIGGED_AND_LIT,
+                              SHADER_DEF_USE_BONES,    // vertex shader defs
+                              SHADER_DEF_USE_LIGHTING, // fragment shader defs
+                              CustomMeshPrefixVertex + MeshColorNoTextureVertex,
+                              CustomMeshPrefixFragment + MeshColorNoTextureFragment,
+                              ShaderEffect::FLEXIBLE);
+
+  mDefaultShader->SetProgram( GEOMETRY_TYPE_MESH, SHADER_RIGGED_AND_EVENLY_LIT,
+                              SHADER_DEF_USE_BONES, // Vertex shader defs
+                              "",                   // Fragment shader defs
+                              CustomMeshPrefixVertex + MeshColorNoTextureVertex,
+                              CustomMeshPrefixFragment + MeshColorNoTextureFragment,
+                              ShaderEffect::FLEXIBLE);
+
+  mDefaultShader->SetProgram( GEOMETRY_TYPE_MESH, SHADER_RIGGED_AND_VERTEX_COLOR,
+                              (SHADER_DEF_USE_BONES SHADER_DEF_USE_COLOR), // Vertex shader defs
+                              SHADER_DEF_USE_COLOR,                        // Fragment shader defs
+                              CustomMeshPrefixVertex + MeshColorNoTextureVertex,
+                              CustomMeshPrefixFragment + MeshColorNoTextureFragment,
+                              ShaderEffect::FLEXIBLE);
+
+  mDefaultShader->SetProgram( GEOMETRY_TYPE_MESH, SHADER_VERTEX_COLOR,
+                              SHADER_DEF_USE_COLOR,  // Vertex shader defs
+                              SHADER_DEF_USE_COLOR,  // Fragment shader defs
+                              CustomMeshPrefixVertex + MeshColorNoTextureVertex,
+                              CustomMeshPrefixFragment + MeshColorNoTextureFragment,
+                              ShaderEffect::FIXED);
 
   // Textured meshes
   mDefaultShader->SetProgram( GEOMETRY_TYPE_TEXTURED_MESH, SHADER_DEFAULT,
                               "",                      // Vertex shader defs
                               SHADER_DEF_USE_LIGHTING, // fragment shader defs
-                              MeshVertex, MeshFragment,
+                              CustomMeshPrefixVertex + MeshVertex,
+                              CustomMeshPrefixFragment + MeshFragment,
                               ShaderEffect::FIXED);
 
 
-  mDefaultShader->SetProgram(GEOMETRY_TYPE_TEXTURED_MESH, SHADER_EVENLY_LIT,
-                             "",                      // Vertex shader defs
-                             "",                      // Fragment shader defs
-                             MeshVertex, MeshFragment,
-                             ShaderEffect::FIXED);
-
-  mDefaultShader->SetProgram(GEOMETRY_TYPE_TEXTURED_MESH, SHADER_RIGGED_AND_LIT,
-                             SHADER_DEF_USE_BONES,    // Vertex shader defs
-                             SHADER_DEF_USE_LIGHTING, // Fragment shader defs
-                             MeshVertex, MeshFragment,
-                             ShaderEffect::FLEXIBLE);
+  mDefaultShader->SetProgram( GEOMETRY_TYPE_TEXTURED_MESH, SHADER_EVENLY_LIT,
+                              "",                      // Vertex shader defs
+                              "",                      // Fragment shader defs
+                              CustomMeshPrefixVertex + MeshVertex,
+                              CustomMeshPrefixFragment + MeshFragment,
+                              ShaderEffect::FIXED);
 
-  mDefaultShader->SetProgram(GEOMETRY_TYPE_TEXTURED_MESH, SHADER_RIGGED_AND_EVENLY_LIT,
-                             SHADER_DEF_USE_BONES, // Vertex shader defs
-                             "",                   // Fragment shader defs
-                             MeshVertex, MeshFragment,
-                             ShaderEffect::FLEXIBLE);
+  mDefaultShader->SetProgram( GEOMETRY_TYPE_TEXTURED_MESH, SHADER_RIGGED_AND_LIT,
+                              SHADER_DEF_USE_BONES,    // Vertex shader defs
+                              SHADER_DEF_USE_LIGHTING, // Fragment shader defs
+                              CustomMeshPrefixVertex + MeshVertex,
+                              CustomMeshPrefixFragment + MeshFragment,
+                              ShaderEffect::FLEXIBLE);
+
+  mDefaultShader->SetProgram( GEOMETRY_TYPE_TEXTURED_MESH, SHADER_RIGGED_AND_EVENLY_LIT,
+                              SHADER_DEF_USE_BONES, // Vertex shader defs
+                              "",                   // Fragment shader defs
+                              CustomMeshPrefixVertex + MeshVertex,
+                              CustomMeshPrefixFragment + MeshFragment,
+                              ShaderEffect::FLEXIBLE);
 }
 
 void ShaderFactory::LoadTextSubtypeShaders(ShaderEffectPtr shaderEffect)
 {
   shaderEffect->SetProgram(GEOMETRY_TYPE_TEXT, SHADER_GRADIENT,
-                             SHADER_DEF_USE_GRADIENT,
-                             SHADER_DEF_USE_GRADIENT,
-                             DistanceFieldFontVertex, DistanceFieldFontFragment);
+                           SHADER_DEF_USE_GRADIENT,
+                           SHADER_DEF_USE_GRADIENT,
+                           DistanceFieldFontVertex, DistanceFieldFontFragment,
+                           ShaderEffect::FIXED);
 
   shaderEffect->SetProgram(GEOMETRY_TYPE_TEXT, SHADER_GRADIENT_GLOW, DistanceFieldFontGlowVertex, DistanceFieldFontGlowFragment, ShaderEffect::FIXED);
 
index 409ec64..a6c2aa7 100644 (file)
@@ -1,21 +1,21 @@
 <VertexShader>
   precision mediump float;
 
-  uniform   mat4    uProjection;
-  uniform   mat4    uModelView;
-  uniform   mat4    uMvpMatrix;
+  uniform   mediump mat4    uProjection;
+  uniform   mediump mat4    uModelView;
+  uniform   mediump mat4    uMvpMatrix;
 
-  uniform   bool    uTextureMapped;
-  uniform   vec4    uCustomTextureCoords;
-  attribute vec2    aTexCoord;
-  varying   vec2    vTexCoord;
+  uniform           bool    uTextureMapped;
+  uniform   mediump vec4    uCustomTextureCoords;
+  attribute mediump vec2    aTexCoord;
+  varying   mediump vec2    vTexCoord;
 
   uniform   mat3    uModelViewIT;
-  attribute vec3    aNormal;
-  varying   vec3    vNormal;
+  attribute mediump vec3    aNormal;
+  varying   mediump vec3    vNormal;
 
-  attribute vec3    aPosition;
-  varying   vec4    vVertex;
+  attribute mediump vec3    aPosition;
+  varying   mediump vec4    vVertex;
 
 </VertexShader>
 
 
   struct Material
   {
-    float      mOpacity;
-    float      mShininess;
-    lowp vec4  mAmbient;
-    lowp vec4  mDiffuse;
-    lowp vec4  mSpecular;
-    lowp vec4  mEmissive;
+    mediump float mOpacity;
+    mediump float mShininess;
+    lowp    vec4  mAmbient;
+    lowp    vec4  mDiffuse;
+    lowp    vec4  mSpecular;
+    lowp    vec4  mEmissive;
   };
 
   uniform sampler2D     sTexture;
@@ -41,7 +41,7 @@
   uniform Material      uMaterial;
 
   uniform lowp  vec4    uColor;
-  varying vec4          vVertex;
+  varying highp vec4    vVertex;
   varying highp vec3    vNormal;
 
 </FragmentShader>
index 39e1a61..c4810c9 100644 (file)
@@ -2,10 +2,6 @@
 #define USE_NORMALS
 #define MAX_BONES_PER_MESH  12
 
-  uniform   mediump mat4    uProjection;
-  uniform   mediump mat4    uModelView;
-  uniform   mediump mat4    uMvpMatrix;
-
 #ifdef USE_BONES
   uniform   int             uBoneCount;
   uniform   mediump mat4    uBoneMatrices[MAX_BONES_PER_MESH];
   attribute mediump vec4    aBoneIndices;
 #endif
 
-#ifdef USE_NORMALS
-  uniform   mat3            uModelViewIT;
-  attribute mediump vec3    aNormal;
-  varying   mediump vec3    vNormal;
-#endif
-
-  attribute mediump vec3    aPosition;
-  varying   mediump vec4    vVertex;
-
 #ifdef USE_COLOR
   attribute lowp vec3       aColor;
   varying   mediump vec3    vColor;
 <FragmentShader>
    precision mediump float;
 
-  struct Material
-  {
-    mediump float mOpacity;
-    mediump float mShininess;
-    lowp    vec4  mAmbient;
-    lowp    vec4  mDiffuse;
-    lowp    vec4  mSpecular;
-    lowp    vec4  mEmissive;
-  };
-
 #ifdef USE_LIGHTING
   struct Light
   {
   };
 #endif
 
-  uniform Material      uMaterial;
-
 #ifdef USE_LIGHTING
   uniform         int   uNumberOfLights;
   uniform Light         uLight0;
   uniform Light         uLight2;
 #endif
 
-  uniform lowp    vec4  uColor;
-  varying highp   vec4  vVertex;
-  varying highp   vec3  vNormal;
-
 #ifdef USE_COLOR
   varying mediump vec3  vColor;
 #endif
index 2ea0d37..f8f5148 100644 (file)
@@ -3,10 +3,6 @@
 #define USE_NORMALS
 #define MAX_BONES_PER_MESH  12
 
-  uniform   mediump mat4    uProjection;
-  uniform   mediump mat4    uModelView;
-  uniform   mediump mat4    uMvpMatrix;
-
 #ifdef USE_BONES
   uniform   int             uBoneCount;
   uniform   mediump mat4    uBoneMatrices[MAX_BONES_PER_MESH];
   attribute mediump vec4    aBoneIndices;
 #endif
 
-#ifdef USE_TEXTURES
-  uniform   bool            uTextureMapped;
-  uniform   mediump vec4    uCustomTextureCoords;
-  attribute mediump vec2    aTexCoord;
-  varying   mediump vec2    vTexCoord;
-#endif
-
-#ifdef USE_NORMALS
-  uniform   mat3            uModelViewIT;
-  attribute mediump vec3    aNormal;
-  varying   mediump vec3    vNormal;
-#endif
-
-  attribute mediump vec3    aPosition;
-  varying   mediump vec4    vVertex;
-
   void main()
   {
     mediump vec4 vertexPosition = vec4(aPosition, 1.0);
 </VertexShader>
 
 <FragmentShader>
-   precision mediump float;
-
-  struct Material
-  {
-    mediump float mOpacity;
-    mediump float mShininess;
-    lowp    vec4  mAmbient;
-    lowp    vec4  mDiffuse;
-    lowp    vec4  mSpecular;
-    lowp    vec4  mEmissive;
-  };
 
 #ifdef USE_LIGHTING
   struct Light
     lowp    vec3  mDiffuse;                   // diffuse component of the light's color
     lowp    vec3  mSpecular;                  // specular component of the light's color
   };
-#endif
 
-  uniform sampler2D     sTexture;
-  uniform sampler2D     sOpacityTexture;
-  uniform sampler2D     sNormalMapTexture;
-  varying mediump vec2  vTexCoord;
-  uniform Material      uMaterial;
-#ifdef USE_LIGHTING
   uniform         int   uNumberOfLights;
   uniform Light         uLight0;
-#endif
-  uniform lowp    vec4  uColor;
-  varying highp   vec4  vVertex;
-  varying highp   vec3  vNormal;
 
-#ifdef USE_LIGHTING
   lowp vec3 lightColor;
   lowp vec3 specularColor;