Browse Source

Shaders/Materials

Marko Pintera 13 years ago
parent
commit
71c60add08

+ 6 - 0
CamelotRenderer/CamelotRenderer.vcxproj

@@ -121,6 +121,7 @@
     <ClInclude Include="Include\CmMesh.h" />
     <ClInclude Include="Include\CmMesh.h" />
     <ClInclude Include="Include\CmMeshData.h" />
     <ClInclude Include="Include\CmMeshData.h" />
     <ClInclude Include="Include\CmMeshDataRTTI.h" />
     <ClInclude Include="Include\CmMeshDataRTTI.h" />
+    <ClInclude Include="Include\CmPass.h" />
     <ClInclude Include="Include\CmPrerequisites.h" />
     <ClInclude Include="Include\CmPrerequisites.h" />
     <ClInclude Include="Include\CmRenderable.h" />
     <ClInclude Include="Include\CmRenderable.h" />
     <ClInclude Include="Include\CmRenderableRTTI.h" />
     <ClInclude Include="Include\CmRenderableRTTI.h" />
@@ -147,9 +148,11 @@
     <ClInclude Include="Include\CmResourceRTTI.h" />
     <ClInclude Include="Include\CmResourceRTTI.h" />
     <ClInclude Include="Include\CmGameObject.h" />
     <ClInclude Include="Include\CmGameObject.h" />
     <ClInclude Include="Include\CmComponent.h" />
     <ClInclude Include="Include\CmComponent.h" />
+    <ClInclude Include="Include\CmShader.h" />
     <ClInclude Include="Include\stdafx.h" />
     <ClInclude Include="Include\stdafx.h" />
     <ClInclude Include="Include\targetver.h" />
     <ClInclude Include="Include\targetver.h" />
     <ClInclude Include="Include\CmVertexDeclarationRTTI.h" />
     <ClInclude Include="Include\CmVertexDeclarationRTTI.h" />
+    <ClInclude Include="Include\CmTechnique.h" />
     <ClInclude Include="Source\CmMeshRTTI.h" />
     <ClInclude Include="Source\CmMeshRTTI.h" />
   </ItemGroup>
   </ItemGroup>
   <ItemGroup>
   <ItemGroup>
@@ -174,6 +177,7 @@
     <ClCompile Include="Source\CmInput.cpp" />
     <ClCompile Include="Source\CmInput.cpp" />
     <ClCompile Include="Source\CmMesh.cpp" />
     <ClCompile Include="Source\CmMesh.cpp" />
     <ClCompile Include="Source\CmMeshData.cpp" />
     <ClCompile Include="Source\CmMeshData.cpp" />
+    <ClCompile Include="Source\CmPass.cpp" />
     <ClCompile Include="Source\CmRenderable.cpp" />
     <ClCompile Include="Source\CmRenderable.cpp" />
     <ClCompile Include="Source\CmRenderSystem.cpp" />
     <ClCompile Include="Source\CmRenderSystem.cpp" />
     <ClCompile Include="Source\CmRenderSystemCapabilities.cpp" />
     <ClCompile Include="Source\CmRenderSystemCapabilities.cpp" />
@@ -184,6 +188,8 @@
     <ClCompile Include="Source\CmResource.cpp" />
     <ClCompile Include="Source\CmResource.cpp" />
     <ClCompile Include="Source\CmResources.cpp" />
     <ClCompile Include="Source\CmResources.cpp" />
     <ClCompile Include="Source\CmSceneManager.cpp" />
     <ClCompile Include="Source\CmSceneManager.cpp" />
+    <ClCompile Include="Source\CmShader.cpp" />
+    <ClCompile Include="Source\CmTechnique.cpp" />
     <ClCompile Include="Source\CmTexture.cpp" />
     <ClCompile Include="Source\CmTexture.cpp" />
     <ClCompile Include="Source\CmTextureManager.cpp" />
     <ClCompile Include="Source\CmTextureManager.cpp" />
     <ClCompile Include="Source\CmTextureState.cpp" />
     <ClCompile Include="Source\CmTextureState.cpp" />

+ 27 - 3
CamelotRenderer/CamelotRenderer.vcxproj.filters

@@ -55,9 +55,6 @@
     <Filter Include="Header Files\RTTI">
     <Filter Include="Header Files\RTTI">
       <UniqueIdentifier>{75249db9-4f2e-43c3-8df4-37250c4b60a2}</UniqueIdentifier>
       <UniqueIdentifier>{75249db9-4f2e-43c3-8df4-37250c4b60a2}</UniqueIdentifier>
     </Filter>
     </Filter>
-    <Filter Include="Header Files\Input">
-      <UniqueIdentifier>{724588b9-04e2-4e9b-9467-b064ed44f05e}</UniqueIdentifier>
-    </Filter>
     <Filter Include="Source Files\Input">
     <Filter Include="Source Files\Input">
       <UniqueIdentifier>{7f8e94f3-6990-4723-965a-2b4f9346a7ee}</UniqueIdentifier>
       <UniqueIdentifier>{7f8e94f3-6990-4723-965a-2b4f9346a7ee}</UniqueIdentifier>
     </Filter>
     </Filter>
@@ -67,6 +64,15 @@
     <Filter Include="Source Files\MOVETODLL">
     <Filter Include="Source Files\MOVETODLL">
       <UniqueIdentifier>{677211c0-a3d1-4e6a-8acf-f457349f1777}</UniqueIdentifier>
       <UniqueIdentifier>{677211c0-a3d1-4e6a-8acf-f457349f1777}</UniqueIdentifier>
     </Filter>
     </Filter>
+    <Filter Include="Header Files\Input">
+      <UniqueIdentifier>{724588b9-04e2-4e9b-9467-b064ed44f05e}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="Header Files\Material">
+      <UniqueIdentifier>{299ec378-4e67-4818-92f6-ab5ffb9aa9ad}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="Source Files\Material">
+      <UniqueIdentifier>{96caf3fa-c267-4fb4-aaa8-83519666d079}</UniqueIdentifier>
+    </Filter>
   </ItemGroup>
   </ItemGroup>
   <ItemGroup>
   <ItemGroup>
     <Text Include="TODO.txt" />
     <Text Include="TODO.txt" />
@@ -244,6 +250,15 @@
     <ClInclude Include="Include\CmRenderableRTTI.h">
     <ClInclude Include="Include\CmRenderableRTTI.h">
       <Filter>Header Files\RTTI</Filter>
       <Filter>Header Files\RTTI</Filter>
     </ClInclude>
     </ClInclude>
+    <ClInclude Include="Include\CmTechnique.h">
+      <Filter>Header Files\Material</Filter>
+    </ClInclude>
+    <ClInclude Include="Include\CmPass.h">
+      <Filter>Header Files\Material</Filter>
+    </ClInclude>
+    <ClInclude Include="Include\CmShader.h">
+      <Filter>Header Files\Material</Filter>
+    </ClInclude>
   </ItemGroup>
   </ItemGroup>
   <ItemGroup>
   <ItemGroup>
     <ClCompile Include="Source\CamelotRenderer.cpp">
     <ClCompile Include="Source\CamelotRenderer.cpp">
@@ -366,5 +381,14 @@
     <ClCompile Include="Source\CmRenderable.cpp">
     <ClCompile Include="Source\CmRenderable.cpp">
       <Filter>Source Files</Filter>
       <Filter>Source Files</Filter>
     </ClCompile>
     </ClCompile>
+    <ClCompile Include="Source\CmPass.cpp">
+      <Filter>Source Files\Material</Filter>
+    </ClCompile>
+    <ClCompile Include="Source\CmShader.cpp">
+      <Filter>Source Files\Material</Filter>
+    </ClCompile>
+    <ClCompile Include="Source\CmTechnique.cpp">
+      <Filter>Source Files\Material</Filter>
+    </ClCompile>
   </ItemGroup>
   </ItemGroup>
 </Project>
 </Project>

+ 490 - 0
CamelotRenderer/Include/CmPass.h

@@ -0,0 +1,490 @@
+#pragma once
+
+#include "CmPrerequisites.h"
+#include "CmCommon.h"
+#include "CmColor.h"
+
+namespace CamelotEngine
+{
+	/** Class defining a single pass of a Technique (of a Material), i.e.
+        a single rendering call.
+    @remarks
+        Rendering can be repeated with many passes for more complex effects.
+        Each pass is a programmable pass (meaning it does
+        use either a vertex and fragment program, or both).
+    */
+	class CM_EXPORT Pass
+    {
+    protected:
+        Technique* mParent;
+        unsigned short mIndex; // pass index
+        String mName; // optional name for the pass
+        //-------------------------------------------------------------------------
+        // Blending factors
+        SceneBlendFactor mSourceBlendFactor;
+        SceneBlendFactor mDestBlendFactor;
+		SceneBlendFactor mSourceBlendFactorAlpha;
+		SceneBlendFactor mDestBlendFactorAlpha;
+
+		// Used to determine if separate alpha blending should be used for color and alpha channels
+		bool mSeparateBlend;
+
+		//-------------------------------------------------------------------------
+		// Blending operations
+		SceneBlendOperation mBlendOperation;
+		SceneBlendOperation mAlphaBlendOperation;
+
+		// Determines if we should use separate blending operations for color and alpha channels
+		bool mSeparateBlendOperation;
+
+        //-------------------------------------------------------------------------
+        // Depth buffer settings
+        bool mDepthCheck;
+        bool mDepthWrite;
+        CompareFunction mDepthFunc;
+        float mDepthBiasConstant;
+		float mDepthBiasSlopeScale;
+		float mDepthBiasPerIteration;
+
+        // Colour buffer settings
+        bool mColourWrite;
+
+		// Alpha reject settings
+		CompareFunction mAlphaRejectFunc;
+		unsigned char mAlphaRejectVal;
+		bool mAlphaToCoverageEnabled;
+
+		// Transparent depth sorting
+		bool mTransparentSorting;
+		// Transparent depth sorting forced
+		bool mTransparentSortingForced;
+        //-------------------------------------------------------------------------
+
+        //-------------------------------------------------------------------------
+        // Culling mode
+        CullingMode mCullMode;
+
+        //-------------------------------------------------------------------------
+		/// Polygon mode
+		PolygonMode mPolygonMode;
+        //-------------------------------------------------------------------------
+
+		// Vertex program
+		GpuProgramPtr mVertexProgram;
+		// Fragment program
+		GpuProgramPtr mFragmentProgram;
+		// Geometry program
+		GpuProgramPtr mGeometryProgram;
+
+        // number of pass iterations to perform
+        size_t mPassIterationCount;
+		// point size, applies when not using per-vertex point size
+		float mPointSize;
+		float mPointMinSize;
+		float mPointMaxSize;
+	public:
+		typedef set<Pass*>::type PassSet;
+    public:
+		CM_MUTEX(mGpuProgramChangeMutex)
+        /// Default constructor
+		Pass(Technique* parent, unsigned short index);
+        /// Copy constructor
+        Pass(Technique* parent, unsigned short index, const Pass& oth );
+        /// Operator = overload
+        Pass& operator=(const Pass& oth);
+        virtual ~Pass();
+
+        /// Returns true if this pass uses a programmable vertex pipeline
+        bool hasVertexProgram(void) const { return mVertexProgram != nullptr; }
+        /// Returns true if this pass uses a programmable fragment pipeline
+        bool hasFragmentProgram(void) const { return mFragmentProgram != nullptr; }
+        /// Returns true if this pass uses a programmable geometry pipeline
+        bool hasGeometryProgram(void) const { return mGeometryProgram != nullptr; }
+
+        /// Gets the index of this Pass in the parent Technique
+        unsigned short getIndex(void) const { return mIndex; }
+        /* Set the name of the pass
+        @remarks
+        The name of the pass is optional.  Its useful in material scripts where a material could inherit
+        from another material and only want to modify a particular pass.
+        */
+        void setName(const String& name);
+        /// get the name of the pass
+        const String& getName(void) const { return mName; }
+
+        /** Gets the point size of the pass.
+		@remarks
+			This property determines what point size is used to render a point
+			list.
+        */
+        float getPointSize(void) const;
+
+		/** Sets the point size of this pass.
+		@remarks
+			This setting allows you to change the size of points when rendering
+			a point list, or a list of point sprites. The interpretation of this
+			command depends on the Pass::setPointSizeAttenuation option - if it
+			is off (the default), the point size is in screen pixels, if it is on,
+			it expressed as normalised screen coordinates (1.0 is the height of
+			the screen) when the point is at the origin.
+		@note
+			Some drivers have an upper limit on the size of points they support
+			- this can even vary between APIs on the same card! Don't rely on
+			point sizes that cause the point sprites to get very large on screen,
+			since they may get clamped on some cards. Upper sizes can range from
+			64 to 256 pixels.
+		*/
+		void setPointSize(float ps);
+
+		/** Set the minimum point size, when point attenuation is in use. */
+		void setPointMinSize(float min);
+		/** Get the minimum point size, when point attenuation is in use. */
+		float getPointMinSize(void) const;
+		/** Set the maximum point size, when point attenuation is in use.
+		@remarks Setting this to 0 indicates the max size supported by the card.
+		*/
+		void setPointMaxSize(float max);
+		/** Get the maximum point size, when point attenuation is in use.
+		@remarks 0 indicates the max size supported by the card.
+		*/
+		float getPointMaxSize(void) const;
+
+        /** Allows very fine control of blending this Pass with the existing contents of the scene.
+        @remarks
+        Whereas the texture blending operations seen in the TextureUnitState class are concerned with
+        blending between texture layers, this blending is about combining the output of the material
+        as a whole with the existing contents of the rendering target. This blending therefore allows
+        object transparency and other special effects.
+        @par
+        This version of the method allows complete control over the blending operation, by specifying the
+        source and destination blending factors. The result of the blending operation is:
+        <span align="center">
+        final = (texture * sourceFactor) + (pixel * destFactor)
+        </span>
+        @par
+        Each of the factors is specified as one of a number of options, as specified in the SceneBlendFactor
+        enumerated type.
+        @param
+        sourceFactor The source factor in the above calculation, i.e. multiplied by the texture colour components.
+        @param
+        destFactor The destination factor in the above calculation, i.e. multiplied by the pixel colour components.
+        @note
+        This method is applicable for both the fixed-function and programmable pipelines.
+        */
+        void setSceneBlending( const SceneBlendFactor sourceFactor, const SceneBlendFactor destFactor);
+
+        /** Allows very fine control of blending this Pass with the existing contents of the scene.
+        @remarks
+        Wheras the texture blending operations seen in the TextureUnitState class are concerned with
+        blending between texture layers, this blending is about combining the output of the material
+        as a whole with the existing contents of the rendering target. This blending therefore allows
+        object transparency and other special effects.
+        @par
+        This version of the method allows complete control over the blending operation, by specifying the
+        source and destination blending factors. The result of the blending operation is:
+        <span align="center">
+        final = (texture * sourceFactor) + (pixel * destFactor)
+        </span>
+        @par
+        Each of the factors is specified as one of a number of options, as specified in the SceneBlendFactor
+        enumerated type.
+        @param
+        sourceFactor The source factor in the above calculation, i.e. multiplied by the texture colour components.
+        @param
+        destFactor The destination factor in the above calculation, i.e. multiplied by the pixel colour components.
+        @param
+        sourceFactorAlpha The alpha source factor in the above calculation, i.e. multiplied by the texture alpha component.
+        @param
+        destFactorAlpha The alpha destination factor in the above calculation, i.e. multiplied by the pixel alpha component.
+		@note
+        This method is applicable for both the fixed-function and programmable pipelines.
+        */
+		void setSeparateSceneBlending( const SceneBlendFactor sourceFactor, const SceneBlendFactor destFactor, const SceneBlendFactor sourceFactorAlpha, const SceneBlendFactor destFactorAlpha );
+
+		/** Return true if this pass uses separate scene blending */
+		bool hasSeparateSceneBlending() const;
+
+        /** Retrieves the source blending factor for the material (as set using Materiall::setSceneBlending).
+        */
+        SceneBlendFactor getSourceBlendFactor() const;
+
+        /** Retrieves the destination blending factor for the material (as set using Materiall::setSceneBlending).
+        */
+        SceneBlendFactor getDestBlendFactor() const;
+
+	    /** Retrieves the alpha source blending factor for the material (as set using Materiall::setSeparateSceneBlending).
+        */
+		SceneBlendFactor getSourceBlendFactorAlpha() const;
+
+	    /** Retrieves the alpha destination blending factor for the material (as set using Materiall::setSeparateSceneBlending).
+        */
+		SceneBlendFactor getDestBlendFactorAlpha() const;
+
+		/** Sets the specific operation used to blend source and destination pixels together.
+			@remarks 
+			By default this operation is +, which creates this equation
+			<span align="center">
+			final = (texture * sourceFactor) + (pixel * destFactor)
+			</span>
+			By setting this to something other than SBO_ADD you can change the operation to achieve
+			a different effect.
+			@param op The blending operation mode to use for this pass
+		*/
+		void setSceneBlendingOperation(SceneBlendOperation op);
+
+		/** Sets the specific operation used to blend source and destination pixels together.
+			@remarks 
+			By default this operation is +, which creates this equation
+			<span align="center">
+			final = (texture * sourceFactor) + (pixel * destFactor)
+			</span>
+			By setting this to something other than SBO_ADD you can change the operation to achieve
+			a different effect.
+			This function allows more control over blending since it allows you to select different blending
+			modes for the color and alpha channels
+			@param op The blending operation mode to use for color channels in this pass
+			@param op The blending operation mode to use for alpha channels in this pass
+		*/
+		void setSeparateSceneBlendingOperation(SceneBlendOperation op, SceneBlendOperation alphaOp);
+
+		/** Returns true if this pass uses separate scene blending operations. */
+		bool hasSeparateSceneBlendingOperations() const;
+
+		/** Returns the current blending operation */
+		SceneBlendOperation getSceneBlendingOperation() const;
+
+		/** Returns the current alpha blending operation */
+		SceneBlendOperation getSceneBlendingOperationAlpha() const;
+
+		/** Returns true if this pass has some element of transparency. */
+		bool isTransparent(void) const;
+
+		/** Sets whether or not this pass renders with depth-buffer checking on or not.
+        @remarks
+        If depth-buffer checking is on, whenever a pixel is about to be written to the frame buffer
+        the depth buffer is checked to see if the pixel is in front of all other pixels written at that
+        point. If not, the pixel is not written.
+        @par
+        If depth checking is off, pixels are written no matter what has been rendered before.
+        Also see setDepthFunction for more advanced depth check configuration.
+        @see
+        setDepthFunction
+        */
+        void setDepthCheckEnabled(bool enabled);
+
+        /** Returns whether or not this pass renders with depth-buffer checking on or not.
+        @see
+        setDepthCheckEnabled
+        */
+        bool getDepthCheckEnabled(void) const;
+
+        /** Sets whether or not this pass renders with depth-buffer writing on or not.
+        @remarks
+        If depth-buffer writing is on, whenever a pixel is written to the frame buffer
+        the depth buffer is updated with the depth value of that new pixel, thus affecting future
+        rendering operations if future pixels are behind this one.
+        @par
+        If depth writing is off, pixels are written without updating the depth buffer Depth writing should
+        normally be on but can be turned off when rendering static backgrounds or when rendering a collection
+        of transparent objects at the end of a scene so that they overlap each other correctly.
+        */
+        void setDepthWriteEnabled(bool enabled);
+
+        /** Returns whether or not this pass renders with depth-buffer writing on or not.
+        @see
+        setDepthWriteEnabled
+        */
+        bool getDepthWriteEnabled(void) const;
+
+        /** Sets the function used to compare depth values when depth checking is on.
+        @remarks
+        If depth checking is enabled (see setDepthCheckEnabled) a comparison occurs between the depth
+        value of the pixel to be written and the current contents of the buffer. This comparison is
+        normally CMPF_LESS_EQUAL, i.e. the pixel is written if it is closer (or at the same distance)
+        than the current contents. If you wish you can change this comparison using this method.
+        */
+        void setDepthFunction( CompareFunction func );
+        /** Returns the function used to compare depth values when depth checking is on.
+        @see
+        setDepthFunction
+        */
+        CompareFunction getDepthFunction(void) const;
+
+		/** Sets whether or not colour buffer writing is enabled for this Pass.
+		@remarks
+			For some effects, you might wish to turn off the colour write operation
+			when rendering geometry; this means that only the depth buffer will be
+			updated (provided you have depth buffer writing enabled, which you
+			probably will do, although you may wish to only update the stencil
+			buffer for example - stencil buffer state is managed at the RenderSystem
+			level only, not the Material since you are likely to want to manage it
+			at a higher level).
+		*/
+		void setColourWriteEnabled(bool enabled);
+		/** Determines if colour buffer writing is enabled for this pass. */
+		bool getColourWriteEnabled(void) const;
+
+        /** Sets the culling mode for this pass  based on the 'vertex winding'.
+        @remarks
+        A typical way for the rendering engine to cull triangles is based on the 'vertex winding' of
+        triangles. Vertex winding refers to the direction in which the vertices are passed or indexed
+        to in the rendering operation as viewed from the camera, and will wither be clockwise or
+        anticlockwise (that's 'counterclockwise' for you Americans out there ;) The default is
+        CULL_CLOCKWISE i.e. that only triangles whose vertices are passed/indexed in anticlockwise order
+        are rendered - this is a common approach and is used in 3D studio models for example. You can
+        alter this culling mode if you wish but it is not advised unless you know what you are doing.
+        @par
+        You may wish to use the CULL_NONE option for mesh data that you cull yourself where the vertex
+        winding is uncertain.
+        */
+        void setCullingMode( CullingMode mode );
+
+        /** Returns the culling mode for geometry rendered with this pass. See setCullingMode for more information.
+        */
+        CullingMode getCullingMode(void) const;
+
+		/** Sets the type of polygon rendering required
+		@note
+		The default shading method is Solid
+		*/
+		void setPolygonMode( PolygonMode mode );
+
+		/** Returns the type of light shading to be used.
+		*/
+		PolygonMode getPolygonMode(void) const;
+
+        /** Sets the depth bias to be used for this material.
+        @remarks
+        When polygons are coplanar, you can get problems with 'depth fighting' where
+        the pixels from the two polys compete for the same screen pixel. This is particularly
+        a problem for decals (polys attached to another surface to represent details such as
+        bulletholes etc.).
+        @par
+        A way to combat this problem is to use a depth bias to adjust the depth buffer value
+        used for the decal such that it is slightly higher than the true value, ensuring that
+        the decal appears on top. There are two aspects to the biasing, a constant
+		bias value and a slope-relative biasing value, which varies according to the
+		maximum depth slope relative to the camera, ie:
+		<pre>finalBias = maxSlope * slopeScaleBias + constantBias</pre>
+		Note that slope scale bias, whilst more accurate, may be ignored by old hardware.
+        @param constantBias The constant bias value, expressed as a factor of the
+			minimum observable depth
+		@param slopeScaleBias The slope-relative bias value, expressed as a factor
+			of the depth slope
+		*/
+        void setDepthBias(float constantBias, float slopeScaleBias = 0.0f);
+
+        /** Retrieves the const depth bias value as set by setDepthBias. */
+        float getDepthBiasConstant(void) const;
+		/** Retrieves the slope-scale depth bias value as set by setDepthBias. */
+		float getDepthBiasSlopeScale(void) const;
+		/** Sets a factor which derives an additional depth bias from the number 
+			of times a pass is iterated.
+		@remarks
+			The Final depth bias will be the constant depth bias as set through
+			setDepthBias, plus this value times the iteration number. 
+		*/
+		void setIterationDepthBias(float biasPerIteration);
+		/** Gets a factor which derives an additional depth bias from the number 
+			of times a pass is iterated.
+		*/
+		float getIterationDepthBias() const;
+
+        /** Sets the way the pass will have use alpha to totally reject pixels from the pipeline.
+        @remarks
+			The default is CMPF_ALWAYS_PASS i.e. alpha is not used to reject pixels.
+        @param func The comparison which must pass for the pixel to be written.
+        @param value 1 byte value against which alpha values will be tested(0-255)
+		@param alphaToCoverageEnabled Whether to enable alpha to coverage support
+        @note
+			This option applies in both the fixed function and the programmable pipeline.
+        */
+        void setAlphaRejectSettings(CompareFunction func, unsigned char value, bool alphaToCoverageEnabled = false);
+
+		/** Sets the alpha reject function. See setAlphaRejectSettings for more information.
+		*/
+		void setAlphaRejectFunction(CompareFunction func);
+
+		/** Gets the alpha reject value. See setAlphaRejectSettings for more information.
+		*/
+		void setAlphaRejectValue(unsigned char val);
+
+		/** Gets the alpha reject function. See setAlphaRejectSettings for more information.
+        */
+		CompareFunction getAlphaRejectFunction(void) const { return mAlphaRejectFunc; }
+
+        /** Gets the alpha reject value. See setAlphaRejectSettings for more information.
+        */
+		unsigned char getAlphaRejectValue(void) const { return mAlphaRejectVal; }
+
+		/** Sets whether to use alpha to coverage (A2C) when blending alpha rejected values. 
+		@remarks
+			Alpha to coverage performs multisampling on the edges of alpha-rejected
+			textures to produce a smoother result. It is only supported when multisampling
+			is already enabled on the render target, and when the hardware supports
+			alpha to coverage (see RenderSystemCapabilities). 
+		*/
+		void setAlphaToCoverageEnabled(bool enabled);
+
+		/** Gets whether to use alpha to coverage (A2C) when blending alpha rejected values. 
+		*/
+		bool isAlphaToCoverageEnabled() const { return mAlphaToCoverageEnabled; }
+
+        /** Sets whether or not transparent sorting is enabled.
+        @param enabled
+			If false depth sorting of this material will be disabled.
+        @remarks
+			By default all transparent materials are sorted such that renderables furthest
+			away from the camera are rendered first. This is usually the desired behaviour
+			but in certain cases this depth sorting may be unnecessary and undesirable. If
+			for example it is necessary to ensure the rendering order does not change from
+			one frame to the next.
+		@note
+			This will have no effect on non-transparent materials.
+        */
+        void setTransparentSortingEnabled(bool enabled);
+
+        /** Returns whether or not transparent sorting is enabled.
+        */
+		bool getTransparentSortingEnabled(void) const;
+
+        /** Sets whether or not transparent sorting is forced.
+        @param enabled
+			If true depth sorting of this material will be depend only on the value of
+            getTransparentSortingEnabled().
+        @remarks
+			By default even if transparent sorting is enabled, depth sorting will only be
+            performed when the material is transparent and depth write/check are disabled.
+            This function disables these extra conditions.
+        */
+        void setTransparentSortingForced(bool enabled);
+
+        /** Returns whether or not transparent sorting is forced.
+        */
+		bool getTransparentSortingForced(void) const;
+
+		/// Gets the parent Technique
+        Technique* getParent(void) const { return mParent; }
+
+		/** Sets the details of the vertex program to use.
+		*/
+		void setVertexProgram(GpuProgramPtr gpuProgram);
+
+		/** Gets the vertex program used by this pass, only available after _load(). */
+		const GpuProgramPtr& getVertexProgram(void) const;
+
+		/** Sets the details of the fragment program to use.
+		*/
+		void setFragmentProgram(GpuProgramPtr gpuProgram);
+		
+		/** Gets the fragment program used by this pass, only available after _load(). */
+		const GpuProgramPtr& getFragmentProgram(void) const;
+
+		/** Sets the details of the geometry program to use.
+		*/
+		void setGeometryProgram(GpuProgramPtr gpuProgram);
+		
+		/** Gets the geometry program used by this pass, only available after _load(). */
+		const GpuProgramPtr& getGeometryProgram(void) const;
+    };
+}

+ 6 - 1
CamelotRenderer/Include/CmPrerequisites.h

@@ -70,7 +70,6 @@ namespace CamelotEngine {
     class Color;
     class Color;
     class GpuProgram;
     class GpuProgram;
     class GpuProgramManager;
     class GpuProgramManager;
-	class GpuProgramUsage;
     class HardwareIndexBuffer;
     class HardwareIndexBuffer;
     class HardwareOcclusionQuery;
     class HardwareOcclusionQuery;
     class HardwareVertexBuffer;
     class HardwareVertexBuffer;
@@ -80,6 +79,9 @@ namespace CamelotEngine {
 	class HighLevelGpuProgramFactory;
 	class HighLevelGpuProgramFactory;
     class IndexData;
     class IndexData;
     class Pass;
     class Pass;
+	class Technique;
+	class Shader;
+	class Material;
     class RenderSystem;
     class RenderSystem;
     class RenderSystemCapabilities;
     class RenderSystemCapabilities;
     class RenderTarget;
     class RenderTarget;
@@ -125,6 +127,9 @@ namespace CamelotEngine
 	typedef std::shared_ptr<Resource> ResourcePtr;
 	typedef std::shared_ptr<Resource> ResourcePtr;
 	typedef std::shared_ptr<Camera> CameraPtr;
 	typedef std::shared_ptr<Camera> CameraPtr;
 	typedef std::shared_ptr<Renderable> RenderablePtr;
 	typedef std::shared_ptr<Renderable> RenderablePtr;
+	typedef std::shared_ptr<Technique> TechniquePtr;
+	typedef std::shared_ptr<Pass> PassPtr;
+	typedef std::shared_ptr<Shader> ShaderPtr;
 
 
 	typedef std::shared_ptr<Component> ComponentPtr;
 	typedef std::shared_ptr<Component> ComponentPtr;
 	typedef std::shared_ptr<GameObject> GameObjectPtr;
 	typedef std::shared_ptr<GameObject> GameObjectPtr;

+ 32 - 0
CamelotRenderer/Include/CmShader.h

@@ -0,0 +1,32 @@
+#pragma once
+
+#include "CmPrerequisites.h"
+
+namespace CamelotEngine
+{
+	/**
+	 * @brief	Shader represents a collection of techniques. They are used in Materials,
+	 * 			which can be considered as instances of a Shader. Multiple materials
+	 * 			may share the same shader but provide different parameters to it.
+	 * 			
+	 *			Shader will always choose the first supported technique based on the current render
+	 *			system, render manager and other properties. So make sure to add most important techniques
+	 *			first so you make sure they are used if they are supported.
+	 */
+	class CM_EXPORT Shader
+	{
+	public:
+		Shader(const String& name);
+
+		void addTechnique(TechniquePtr technique);
+		
+		void removeTechnique(UINT32 idx);
+		void removeTechnique(TechniquePtr technique);
+
+		UINT32 getNumTechniques() const { return mTechniques.size(); }
+
+	private:
+		String mName;
+		vector<TechniquePtr>::type mTechniques;
+	};
+}

+ 23 - 0
CamelotRenderer/Include/CmTechnique.h

@@ -0,0 +1,23 @@
+#pragma once
+
+#include "CmPrerequisites.h"
+
+namespace CamelotEngine
+{
+	class CM_EXPORT Technique
+	{
+	public:
+		Technique(const String& renderSystem, const String& renderManager);
+
+		void addPass(PassPtr pass);
+		void removePass(UINT32 idx);
+
+		UINT32 getNumPassess() const { return mPasses.size(); }
+
+	private:
+		String mRenderSystem;
+		String mRenderManager;
+
+		vector<PassPtr>::type mPasses;
+	};
+}

+ 382 - 0
CamelotRenderer/Source/CmPass.cpp

@@ -0,0 +1,382 @@
+#include "CmPass.h"
+#include "CmException.h"
+
+namespace CamelotEngine
+{
+    //-----------------------------------------------------------------------------
+	Pass::Pass(Technique* parent, unsigned short index)
+        : mParent(parent)
+		, mIndex(index)
+		, mSourceBlendFactor(SBF_ONE)
+		, mDestBlendFactor(SBF_ZERO)
+		, mSourceBlendFactorAlpha(SBF_ONE)
+		, mDestBlendFactorAlpha(SBF_ZERO)
+		, mSeparateBlend(false)
+		, mBlendOperation(SBO_ADD)
+		, mAlphaBlendOperation(SBO_ADD)
+		, mSeparateBlendOperation(false)
+		, mDepthCheck(true)
+		, mDepthWrite(true)
+		, mDepthFunc(CMPF_LESS_EQUAL)
+		, mDepthBiasConstant(0.0f)
+		, mDepthBiasSlopeScale(0.0f)
+		, mDepthBiasPerIteration(0.0f)
+		, mColourWrite(true)
+		, mAlphaRejectFunc(CMPF_ALWAYS_PASS)
+		, mAlphaRejectVal(0)
+		, mAlphaToCoverageEnabled(false)
+		, mTransparentSorting(true)
+		, mTransparentSortingForced(false)
+		, mCullMode(CULL_CLOCKWISE)
+		, mPolygonMode(PM_SOLID)
+		, mPassIterationCount(1)
+		, mPointSize(1.0f)
+		, mPointMinSize(0.0f)
+		, mPointMaxSize(0.0f)	
+    {
+        // default name to index
+        mName = toString(mIndex);
+   }
+
+    //-----------------------------------------------------------------------------
+	Pass::Pass(Technique *parent, unsigned short index, const Pass& oth)
+        :mParent(parent), mIndex(index), mPassIterationCount(1)
+    {
+        *this = oth;
+        mParent = parent;
+        mIndex = index;
+    }
+    //-----------------------------------------------------------------------------
+    Pass::~Pass()
+    {
+	
+    }
+    //-----------------------------------------------------------------------------
+    Pass& Pass::operator=(const Pass& oth)
+    {
+        mName = oth.mName;
+
+	    // Default blending (overwrite)
+	    mSourceBlendFactor = oth.mSourceBlendFactor;
+	    mDestBlendFactor = oth.mDestBlendFactor;
+		mSourceBlendFactorAlpha = oth.mSourceBlendFactorAlpha;
+		mDestBlendFactorAlpha = oth.mDestBlendFactorAlpha;
+		mSeparateBlend = oth.mSeparateBlend;
+
+		mBlendOperation = oth.mBlendOperation;
+		mAlphaBlendOperation = oth.mAlphaBlendOperation;
+		mSeparateBlendOperation = oth.mSeparateBlendOperation;
+
+	    mDepthCheck = oth.mDepthCheck;
+	    mDepthWrite = oth.mDepthWrite;
+		mAlphaRejectFunc = oth.mAlphaRejectFunc;
+		mAlphaRejectVal = oth.mAlphaRejectVal;
+		mAlphaToCoverageEnabled = oth.mAlphaToCoverageEnabled;
+		mTransparentSorting = oth.mTransparentSorting;
+		mTransparentSortingForced = oth.mTransparentSortingForced;
+        mColourWrite = oth.mColourWrite;
+	    mDepthFunc = oth.mDepthFunc;
+        mDepthBiasConstant = oth.mDepthBiasConstant;
+		mDepthBiasSlopeScale = oth.mDepthBiasSlopeScale;
+		mDepthBiasPerIteration = oth.mDepthBiasPerIteration;
+	    mCullMode = oth.mCullMode;
+		mPolygonMode = oth.mPolygonMode;
+        mPassIterationCount = oth.mPassIterationCount;
+		mPointSize = oth.mPointSize;
+		mPointMinSize = oth.mPointMinSize;
+		mPointMaxSize = oth.mPointMaxSize;
+
+		mVertexProgram = oth.mVertexProgram;
+		mFragmentProgram = oth.mFragmentProgram;
+		mGeometryProgram = oth.mGeometryProgram;
+
+		return *this;
+    }
+    //-----------------------------------------------------------------------
+    void Pass::setName(const String& name)
+    {
+        mName = name;
+    }
+    //-----------------------------------------------------------------------
+    void Pass::setPointSize(float ps)
+    {
+	    mPointSize = ps;
+    }
+    //-----------------------------------------------------------------------
+	void Pass::setPointMinSize(float min)
+	{
+		mPointMinSize = min;
+	}
+    //-----------------------------------------------------------------------
+	float Pass::getPointMinSize(void) const
+	{
+		return mPointMinSize;
+	}
+    //-----------------------------------------------------------------------
+	void Pass::setPointMaxSize(float max)
+	{
+		mPointMaxSize = max;
+	}
+    //-----------------------------------------------------------------------
+	float Pass::getPointMaxSize(void) const
+	{
+		return mPointMaxSize;
+	}
+    //-----------------------------------------------------------------------
+    float Pass::getPointSize(void) const
+    {
+	    return mPointSize;
+    }
+    //-----------------------------------------------------------------------
+    void Pass::setSceneBlending(SceneBlendFactor sourceFactor, SceneBlendFactor destFactor)
+    {
+	    mSourceBlendFactor = sourceFactor;
+	    mDestBlendFactor = destFactor;
+
+		mSeparateBlend = false;
+    }
+	//-----------------------------------------------------------------------
+	void Pass::setSeparateSceneBlending( const SceneBlendFactor sourceFactor, const SceneBlendFactor destFactor, const SceneBlendFactor sourceFactorAlpha, const SceneBlendFactor destFactorAlpha )
+	{
+		mSourceBlendFactor = sourceFactor;
+		mDestBlendFactor = destFactor;
+		mSourceBlendFactorAlpha = sourceFactorAlpha;
+		mDestBlendFactorAlpha = destFactorAlpha;
+
+		mSeparateBlend = true;
+	}
+    //-----------------------------------------------------------------------
+    SceneBlendFactor Pass::getSourceBlendFactor(void) const
+    {
+	    return mSourceBlendFactor;
+    }
+    //-----------------------------------------------------------------------
+    SceneBlendFactor Pass::getDestBlendFactor(void) const
+    {
+	    return mDestBlendFactor;
+    }
+    //-----------------------------------------------------------------------
+    SceneBlendFactor Pass::getSourceBlendFactorAlpha(void) const
+    {
+	    return mSourceBlendFactorAlpha;
+    }
+    //-----------------------------------------------------------------------
+    SceneBlendFactor Pass::getDestBlendFactorAlpha(void) const
+    {
+	    return mDestBlendFactorAlpha;
+    }
+	//-----------------------------------------------------------------------
+	bool Pass::hasSeparateSceneBlending() const
+	{
+		return mSeparateBlend;
+	}
+	//-----------------------------------------------------------------------
+	void Pass::setSceneBlendingOperation(SceneBlendOperation op)
+	{
+		mBlendOperation = op;
+		mSeparateBlendOperation = false;
+	}
+	//-----------------------------------------------------------------------
+	void Pass::setSeparateSceneBlendingOperation(SceneBlendOperation op, SceneBlendOperation alphaOp)
+	{
+		mBlendOperation = op;
+		mAlphaBlendOperation = alphaOp;
+		mSeparateBlendOperation = true;
+	}
+	//-----------------------------------------------------------------------
+	SceneBlendOperation Pass::getSceneBlendingOperation() const
+	{
+		return mBlendOperation;
+	}
+	//-----------------------------------------------------------------------
+	SceneBlendOperation Pass::getSceneBlendingOperationAlpha() const
+	{
+		return mAlphaBlendOperation;
+	}
+	//-----------------------------------------------------------------------
+	bool Pass::hasSeparateSceneBlendingOperations() const
+	{
+		return mSeparateBlendOperation;
+	}
+    //-----------------------------------------------------------------------
+    bool Pass::isTransparent(void) const
+    {
+		// Transparent if any of the destination colour is taken into account
+		if (mDestBlendFactor == SBF_ZERO &&
+			mSourceBlendFactor != SBF_DEST_COLOUR &&
+			mSourceBlendFactor != SBF_ONE_MINUS_DEST_COLOUR &&
+			mSourceBlendFactor != SBF_DEST_ALPHA &&
+			mSourceBlendFactor != SBF_ONE_MINUS_DEST_ALPHA)
+		{
+		    return false;
+		}
+	    else
+		{
+		    return true;
+		}
+    }
+    //-----------------------------------------------------------------------
+    void Pass::setDepthCheckEnabled(bool enabled)
+    {
+	    mDepthCheck = enabled;
+    }
+    //-----------------------------------------------------------------------
+    bool Pass::getDepthCheckEnabled(void) const
+    {
+	    return mDepthCheck;
+    }
+    //-----------------------------------------------------------------------
+    void Pass::setDepthWriteEnabled(bool enabled)
+    {
+	    mDepthWrite = enabled;
+    }
+    //-----------------------------------------------------------------------
+    bool Pass::getDepthWriteEnabled(void) const
+    {
+	    return mDepthWrite;
+    }
+    //-----------------------------------------------------------------------
+    void Pass::setDepthFunction( CompareFunction func)
+    {
+	    mDepthFunc = func;
+    }
+    //-----------------------------------------------------------------------
+    CompareFunction Pass::getDepthFunction(void) const
+    {
+	    return mDepthFunc;
+    }
+	//-----------------------------------------------------------------------
+	void Pass::setAlphaRejectSettings(CompareFunction func, unsigned char value, bool alphaToCoverage)
+	{
+		mAlphaRejectFunc = func;
+		mAlphaRejectVal = value;
+		mAlphaToCoverageEnabled = alphaToCoverage;
+	}
+	//-----------------------------------------------------------------------
+	void Pass::setAlphaRejectFunction(CompareFunction func)
+	{
+		mAlphaRejectFunc = func;
+	}
+	//-----------------------------------------------------------------------
+	void Pass::setAlphaRejectValue(unsigned char val)
+	{
+		mAlphaRejectVal = val;
+	}
+	//---------------------------------------------------------------------
+	void Pass::setAlphaToCoverageEnabled(bool enabled)
+	{
+		mAlphaToCoverageEnabled = enabled;
+	}
+	//-----------------------------------------------------------------------
+	void Pass::setTransparentSortingEnabled(bool enabled)
+	{
+		mTransparentSorting = enabled;
+	}
+	//-----------------------------------------------------------------------
+	bool Pass::getTransparentSortingEnabled(void) const
+	{
+		return mTransparentSorting;
+	}
+	//-----------------------------------------------------------------------
+	void Pass::setTransparentSortingForced(bool enabled)
+	{
+		mTransparentSortingForced = enabled;
+	}
+	//-----------------------------------------------------------------------
+	bool Pass::getTransparentSortingForced(void) const
+	{
+		return mTransparentSortingForced;
+	}
+    //-----------------------------------------------------------------------
+	void Pass::setColourWriteEnabled(bool enabled)
+	{
+		mColourWrite = enabled;
+	}
+    //-----------------------------------------------------------------------
+	bool Pass::getColourWriteEnabled(void) const
+	{
+		return mColourWrite;
+	}
+    //-----------------------------------------------------------------------
+    void Pass::setCullingMode( CullingMode mode)
+    {
+	    mCullMode = mode;
+    }
+    //-----------------------------------------------------------------------
+    CullingMode Pass::getCullingMode(void) const
+    {
+	    return mCullMode;
+    }
+	//-----------------------------------------------------------------------
+	void Pass::setPolygonMode(PolygonMode mode)
+	{
+		mPolygonMode = mode;
+	}
+	//-----------------------------------------------------------------------
+	PolygonMode Pass::getPolygonMode(void) const
+	{
+		return mPolygonMode;
+	}
+    //-----------------------------------------------------------------------
+    void Pass::setDepthBias(float constantBias, float slopeScaleBias)
+    {
+       mDepthBiasConstant = constantBias;
+	   mDepthBiasSlopeScale = slopeScaleBias;
+    }
+    //-----------------------------------------------------------------------
+    float Pass::getDepthBiasConstant(void) const
+    {
+        return mDepthBiasConstant;
+    }
+	//-----------------------------------------------------------------------
+	float Pass::getDepthBiasSlopeScale(void) const
+	{
+		return mDepthBiasSlopeScale;
+	}
+	//---------------------------------------------------------------------
+	void Pass::setIterationDepthBias(float biasPerIteration)
+	{
+		mDepthBiasPerIteration = biasPerIteration;
+	}
+	//---------------------------------------------------------------------
+	float Pass::getIterationDepthBias() const
+	{
+		return mDepthBiasPerIteration;
+	}
+    //-----------------------------------------------------------------------
+	void Pass::setVertexProgram(GpuProgramPtr gpuProgram)
+	{
+		CM_LOCK_MUTEX(mGpuProgramChangeMutex)
+		mGeometryProgram = gpuProgram;
+	}
+    //-----------------------------------------------------------------------
+	void Pass::setFragmentProgram(GpuProgramPtr gpuProgram)
+	{
+		CM_LOCK_MUTEX(mGpuProgramChangeMutex)
+		mGeometryProgram = gpuProgram;
+	}
+	//-----------------------------------------------------------------------
+	void Pass::setGeometryProgram(GpuProgramPtr gpuProgram)
+	{
+		CM_LOCK_MUTEX(mGpuProgramChangeMutex)
+		mGeometryProgram = gpuProgram;
+	}
+	//-----------------------------------------------------------------------
+	const GpuProgramPtr& Pass::getVertexProgram(void) const
+	{
+		CM_LOCK_MUTEX(mGpuProgramChangeMutex)
+		return mVertexProgram;
+	}
+	//-----------------------------------------------------------------------
+	const GpuProgramPtr& Pass::getFragmentProgram(void) const
+	{
+		CM_LOCK_MUTEX(mGpuProgramChangeMutex)
+		return mFragmentProgram;
+	}
+	//-----------------------------------------------------------------------
+	const GpuProgramPtr& Pass::getGeometryProgram(void) const
+	{
+		CM_LOCK_MUTEX(mGpuProgramChangeMutex)
+		return mGeometryProgram;
+	}
+}

+ 48 - 0
CamelotRenderer/Source/CmShader.cpp

@@ -0,0 +1,48 @@
+#include "CmShader.h"
+#include "CmException.h"
+#include "CmDebug.h"
+
+namespace CamelotEngine
+{
+	Shader::Shader(const String& name)
+		:mName(name)
+	{
+
+	}
+
+	void Shader::addTechnique(TechniquePtr technique)
+	{
+		auto iterFind = std::find(mTechniques.begin(), mTechniques.end(), technique);
+
+		if(iterFind != mTechniques.end())
+			CM_EXCEPT(InvalidParametersException, "Identical technique already exists in this shader.");
+
+		mTechniques.push_back(technique);
+	}
+
+	void Shader::removeTechnique(UINT32 idx)
+	{
+		if(idx < 0 || idx >= mTechniques.size())
+			CM_EXCEPT(InvalidParametersException, "Index out of range: " + toString(idx));
+
+		int count = 0;
+		auto iter = mTechniques.begin();
+		while(count != idx)
+		{
+			++count;
+			++iter;
+		}
+
+		mTechniques.erase(iter);
+	}
+
+	void Shader::removeTechnique(TechniquePtr technique)
+	{
+		auto iterFind = std::find(mTechniques.begin(), mTechniques.end(), technique);
+
+		if(iterFind == mTechniques.end())
+			CM_EXCEPT(InvalidParametersException, "Cannot remove specified technique because it wasn't found in this shader.");
+
+		mTechniques.erase(iterFind);
+	}
+}

+ 32 - 0
CamelotRenderer/Source/CmTechnique.cpp

@@ -0,0 +1,32 @@
+#include "CmTechnique.h"
+#include "CmException.h"
+
+namespace CamelotEngine
+{
+	Technique::Technique(const String& renderSystem, const String& renderManager)
+		:mRenderSystem(renderSystem), mRenderManager(renderManager)
+	{
+
+	}
+
+	void Technique::addPass(PassPtr pass)
+	{
+		mPasses.push_back(pass);
+	}
+
+	void Technique::removePass(UINT32 idx)
+	{
+		if(idx < 0 || idx >= mPasses.size())
+			CM_EXCEPT(InvalidParametersException, "Index out of range: " + toString(idx));
+
+		int count = 0;
+		auto iter = mPasses.begin();
+		while(count != idx)
+		{
+			++count;
+			++iter;
+		}
+
+		mPasses.erase(iter);
+	}
+}

+ 1 - 0
CamelotRenderer/TODO.txt

@@ -19,6 +19,7 @@ HIGH PRIORITY TODO:
  - HLSL & Cg don't handle include files yet
  - HLSL & Cg don't handle include files yet
 
 
 Mid priority TODO:
 Mid priority TODO:
+ - GpuProgram default parameters might not be needed. The parameters change with each use of the gpu program anyway
  - Mesh loading:
  - Mesh loading:
   - Example Freefall mesh has one index per vertex, and there are 17k+ vertices. I think I need a post-process step that optimizes them.
   - Example Freefall mesh has one index per vertex, and there are 17k+ vertices. I think I need a post-process step that optimizes them.
   - Imported FBX meshes are too big
   - Imported FBX meshes are too big