Commits

Assaf Raman committed 63a0198

A patch by Mattan F.: Added a texture atlas extension to the RTSS.

Comments (0)

Files changed (11)

Components/RTShaderSystem/CMakeLists.txt

   include/OgreShaderHLSLProgramWriter.h
   include/OgreShaderExLayeredBlending.h
   include/OgreShaderExHardwareSkinning.h
+  include/OgreShaderExTextureAtlasSampler.h
 )
 
 set (SOURCE_FILES
   src/OgreShaderHLSLProgramWriter.cpp
   src/OgreShaderExLayeredBlending.cpp
   src/OgreShaderExHardwareSkinning.cpp
+  src/OgreShaderExTextureAtlasSampler.cpp
 )
 
 

Components/RTShaderSystem/include/OgreShaderExTextureAtlasSampler.h

+/*
+-----------------------------------------------------------------------------
+This source file is part of OGRE
+(Object-oriented Graphics Rendering Engine)
+For the latest info, see http://www.ogre3d.org
+
+Copyright (c) 2000-2009 Torus Knot Software Ltd
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+-----------------------------------------------------------------------------
+*/
+#ifndef _ShaderSGXAtlasTexture_
+#define _ShaderSGXAtlasTexture_
+
+#include "OgreShaderPrerequisites.h"
+#ifdef RTSHADER_SYSTEM_BUILD_EXT_SHADERS
+#include "OgreShaderSubRenderState.h"
+#include "OgreShaderParameter.h"
+
+#define TAS_MAX_TEXTURES 4
+namespace Ogre {
+namespace RTShader {
+
+/** \addtogroup Core
+*  @{
+*/
+/** \addtogroup RTShader
+*  @{
+*/
+struct _OgreRTSSExport TextureAtlasRecord
+{
+	TextureAtlasRecord(const String & texOriginalName, const String & texAtlasName, 
+					   const float texPosU, const float texPosV, const float texWidth, const float texHeight,
+					   const size_t texIndexInAtlas) :
+				originalTextureName(texOriginalName)
+				, atlasTextureName(texAtlasName)
+				, posU(texPosU)
+				, posV(texPosV)
+				, width(texWidth)
+				, height(texHeight)
+				, indexInAtlas(texIndexInAtlas)
+	{ }
+
+	float posU;
+	float posV;
+	float width;
+	float height;
+	String originalTextureName;
+	String atlasTextureName;
+	size_t indexInAtlas;
+};
+
+
+typedef vector<TextureAtlasRecord>::type TextureAtlasTable;
+typedef SharedPtr<TextureAtlasTable> TextureAtlasTablePtr;
+typedef map<String, TextureAtlasTablePtr>::type TextureAtlasMap;
+
+/** Implements texture atlas sampling.
+
+This class implements a sub render state which allows sampling of a texture
+from a texture atlas. 
+
+Note: This class does not implement the entire texture sub-render state. It
+only implement the sampling of textures. This class needs to work in conjunction
+with the default FFPTexturing to work.
+
+\par Using the TextureAtlasSampler
+There are 2 pieces of information that are need to be provided for this sub
+render state to work. 
+
+The first is the texture atlas table. This table consists of several records
+containing the position and size of each texture in the in the texture atlas. 
+This information needs to be provided per atlas texture. The information is 
+entered to the system though the TextureAtlasSamplerFactory using the
+functions setTextureAtlasTable and removeTextureAtlasTable.
+
+The second information is the index of the record in the texture atlas table
+to which a given texture is associated with. This information is provided
+through an extra texture coordinate in the vertex buffer. This texture coordinate
+might can be placed either relative or in absolute position. 
+
+For example:
+ - given 3 texture sand a relative position of 2, the shader will search assume 
+	that the indexes exist in texture coordinate 5 (2+3)
+ - given an absolute position of 2, the shader will search for the indexes in 
+	texture coordinate 2, regardless of the amount of textures
+
+The position of the indexes can be controlled globally through the 
+TextureAtlasSamplerFactory class using the function setTableIndexPosition
+The default index position is set to relative + 1.
+
+\par Preparing atlas textures
+When preparing the atlas texture to be used in this system you should make sure
+that all texture with in the atlas have power-of-2 dimensions. And also that
+the inserted textures will be padded with 1 pixel of their own border color.
+This will prevent visual artifacts caused when sampling textures at their borders.
+
+You can use the NVidia "Texture Atlas Tools" to create the texture. 
+*/
+class _OgreRTSSExport TextureAtlasSampler : public SubRenderState
+{
+public:
+
+// Interface.
+public:
+
+	/** Class default constructor */
+	TextureAtlasSampler();
+
+	/** 
+	@see SubRenderState::getType.
+	*/
+	virtual const String& getType() const;
+
+	/** 
+	@see SubRenderState::getType.
+	*/
+	virtual int getExecutionOrder() const;
+
+	/** 
+	@see SubRenderState::copyFrom.
+	*/
+	virtual void copyFrom(const SubRenderState& rhs);
+
+	/** 
+	@see SubRenderState::updateGpuProgramsParams.
+	*/
+	virtual void updateGpuProgramsParams(Renderable* rend, Pass* pass,  const AutoParamDataSource* source, 	const LightList* pLightList);
+
+	/** 
+	@see SubRenderState::preAddToRenderState.
+	*/
+	virtual bool preAddToRenderState(const RenderState* renderState, Pass* srcPass, Pass* dstPass);
+	
+	static String Type;
+
+// Protected methods
+protected:	
+	virtual bool			resolveParameters		(ProgramSet* programSet);	
+	virtual bool			resolveDependencies		(ProgramSet* programSet);
+	virtual bool			addFunctionInvocations	(ProgramSet* programSet);
+
+	/** 
+	Given an address mode returns the function name which calculates the UV values for that addressing mode
+	*/
+	const char* getAdressingFunctionName(TextureUnitState::TextureAddressingMode mode);
+
+
+// Attributes.
+protected:
+	ParameterPtr mVSInpTextureTableIndex; // The index of the information on the texture in the table
+	
+	TextureUnitState::UVWAddressingMode mTextureAddressings[TAS_MAX_TEXTURES]; // The addressing mode for each texture
+	ParameterPtr mVSOutTextureDatas[TAS_MAX_TEXTURES]; // The position and size of the texture in the atlas 
+	ParameterPtr mPSInpTextureDatas[TAS_MAX_TEXTURES]; // The position and size of the texture in the atlas
+	UniformParameterPtr mVSTextureTable; // The table containing information on the textures in the atlas
+
+	//The position of the texture coordinates containing the index information 
+	ushort mAtlasTexcoordPos; 
+	//The first texture number which use atlas texture
+	ushort mAtlasTextureStart;
+	//The number of indexes which use atlas texture 
+	ushort mAtlasTextureCount;
+	//The texture atlas table data
+	TextureAtlasTablePtr mAtlasTableData;
+	//Tells if the data in mAtlasTableData has been uploaded to the corresponding mVSTextureTable parameter
+	bool mIsTableDataUpdated;
+};
+
+
+
+/** 
+A factory that enables creation of TextureAtlasSampler instances.
+@remarks Sub class of SubRenderStateFactory
+*/
+class _OgreRTSSExport TextureAtlasSamplerFactory : public SubRenderStateFactory, public Singleton<TextureAtlasSamplerFactory>
+{
+public:
+	enum IndexPositionMode
+	{
+		ipmRelative,
+		ipmAbsolute
+	};
+public:
+
+	//TextureAtlasSamplerFactory c_tor
+	TextureAtlasSamplerFactory();
+
+	/** 
+	@see SubRenderStateFactory::getType.
+	*/
+	virtual const String& getType() const;
+
+	/** 
+	@see SubRenderStateFactory::createInstance.
+	*/
+	virtual SubRenderState* createInstance(ScriptCompiler* compiler, PropertyAbstractNode* prop, Pass* pass, SGScriptTranslator* translator);
+
+	/** 
+	@see SubRenderStateFactory::writeInstance.
+	*/
+	virtual void writeInstance(MaterialSerializer* ser, SubRenderState* subRenderState, Pass* srcPass, Pass* dstPass);
+	
+	/**
+		Adds a texture atlas definition from a stream. 
+
+		This function loads a texture atlas definition file from a stream. The accepted format for
+		this file is the NVidia Texture Atlas Tools ".tai" file format. This file as
+	
+		The ".tai" format consist of lines, where each line corresponds to a specific texture
+		in the texture atlas. Each line has the following format:
+		# <original texture filename>/t/t<atlas filename>, <atlas idx>, <atlas type>, <woffset>, <hoffset>, <depth offset>, <width>, <height>
+	*/
+	bool addTexutreAtlasDefinition( DataStreamPtr stream, TextureAtlasTable * textureAtlasTable = 0 );
+	
+	/**
+		Set the texture atlas information for a given texture
+		@param textureName Name of an atlas texture
+		@param atlasData a list of records containing the position and size of each 
+			texture in the atlas
+	*/
+	void setTextureAtlasTable(const String& textureName, const TextureAtlasTablePtr& atlasData);
+	
+	/** 
+		Removes the texture atlas information from a given texture
+		@param textureName Name of an atlas texture
+	*/
+	void removeTextureAtlasTable(const String& textureName);
+
+	/** 
+		Removes all texture atlas table information
+	*/
+	void removeAllTextureAtlasTables();
+
+	/** 
+		Retrieve the texture atlas information for a given texture
+		@param textureName Name of an atlas texture
+	*/
+	const TextureAtlasTablePtr& getTextureAtlasTable(const String& textureName) const;
+
+	/**
+		Set the position of the atlas table indexes within the texcoords of the vertex data
+		@see TextureAtlasSampler
+	*/
+	void setTableIndexPosition(IndexPositionMode mode, ushort offset);
+
+	/**
+		Get the positioning mode of the atlas table indexes within the texcoords of the vertex data
+		@see TextureAtlasSampler
+		*/
+	IndexPositionMode getTableIndexPositionMode() const;
+
+	/**
+		Get the offset of the atlas table indexes within the texcoords of the vertex data
+		@see TextureAtlasSampler
+		*/
+	ushort getTableIndexPositionOffset() const;
+
+	
+protected:
+
+	/** 
+	@see SubRenderStateFactory::createInstanceImpl.
+	*/
+	virtual SubRenderState*	createInstanceImpl();
+
+private:
+
+	//Holds a mapping of texture names and the atlas table information associated with them
+	TextureAtlasMap mAtlases;
+
+	//The positioning mode of the atlas table indexes within the texcoords of the vertex data
+	IndexPositionMode mIndexPositionMode;
+	
+	//The offset of the atlas table indexes within the texcoords of the vertex data
+	ushort mIndexPositionOffset;
+};
+
+/** @} */
+/** @} */
+
+}
+}
+
+#endif
+#endif

Components/RTShaderSystem/include/OgreShaderFFPRenderState.h

 {
 	FFP_PS_PRE_PROCESS					= 0,	
 	FFP_PS_COLOUR_BEGIN					= 100,
+	FFP_PS_SAMPLING						= 150,
 	FFP_PS_TEXTURING					= 200,	
 	FFP_PS_COLOUR_END					= 300,
 	FFP_PS_FOG							= 400,

Components/RTShaderSystem/include/OgreShaderFFPTexturing.h

 	*/
 	bool					addPSFunctionInvocations(TextureUnitParams* textureUnitParams, Function* psMain, int& internalCounter);
 
+	/** 
+	Adds the fragment shader code which samples the texel color in the texture
+	*/
+	virtual void					addPSSampleTexelInvocation(TextureUnitParams* textureUnitParams, Function* psMain, 
+		const ParameterPtr& texel, int groupOrder, int& internalCounter);
+
 	virtual void					addPSArgumentInvocations(Function* psMain, 
 													 ParameterPtr arg,
 													 ParameterPtr texel,

Components/RTShaderSystem/src/OgreShaderExTextureAtlasSampler.cpp

+/*
+-----------------------------------------------------------------------------
+This source file is part of OGRE
+(Object-oriented Graphics Rendering Engine)
+For the latest info, see http://www.ogre3d.org
+
+Copyright (c) 2000-2009 Torus Knot Software Ltd
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+-----------------------------------------------------------------------------
+*/
+#include "OgreShaderExTextureAtlasSampler.h"
+
+#ifdef RTSHADER_SYSTEM_BUILD_EXT_SHADERS
+#include "OgreShaderFFPRenderState.h"
+#include "OgreShaderProgram.h"
+#include "OgreShaderParameter.h"
+#include "OgreShaderProgramSet.h"
+
+#define SGX_LIB_TEXTURE_ATLAS "SGXLib_TextureAtlas"
+
+#define SGX_FUNC_ATLAS_SAMPLE "SGX_Atlas_Sample"
+
+#define SGX_FUNC_ATLAS_WRAP "SGX_Atlas_Wrap"
+#define SGX_FUNC_ATLAS_MIRROR "SGX_Atlas_Mirror"
+#define SGX_FUNC_ATLAS_CLAMP "SGX_Atlas_Clamp"
+#define SGX_FUNC_ATLAS_BORDER "SGX_Atlas_Border"
+
+namespace Ogre {
+template<> RTShader::TextureAtlasSamplerFactory* Singleton<RTShader::TextureAtlasSamplerFactory>::ms_Singleton = 0;
+
+namespace RTShader {
+
+
+
+const TextureAtlasTablePtr c_BlankAtlasTable;
+const String c_ParamTexel("texel_");
+String TextureAtlasSampler::Type = "SGX_TextureAtlasSampler";
+
+//-----------------------------------------------------------------------
+TextureAtlasSampler::TextureAtlasSampler() :
+	mAtlasTexcoordPos(0),
+	mAtlasTextureStart(0),
+	mAtlasTextureCount(0),
+	mIsTableDataUpdated(false)
+{
+
+}
+
+//-----------------------------------------------------------------------
+const String& TextureAtlasSampler::getType() const
+{
+	return Type;
+}
+
+
+//-----------------------------------------------------------------------
+int	TextureAtlasSampler::getExecutionOrder() const
+{
+	return FFP_TEXTURING + 25;
+}
+
+//-----------------------------------------------------------------------
+bool TextureAtlasSampler::resolveParameters(ProgramSet* programSet)
+{
+	Program* vsProgram = programSet->getCpuVertexProgram();
+	Program* psProgram = programSet->getCpuFragmentProgram();
+	Function* vsMain   = vsProgram->getEntryPointFunction();
+	Function* psMain   = psProgram->getEntryPointFunction();	
+
+
+	//
+	// Define vertex shader parameters used to find the position of the textures in the atlas
+	//
+	Parameter::Content indexContent = (Parameter::Content)((int)Parameter::SPC_TEXTURE_COORDINATE0 + mAtlasTexcoordPos);
+	GpuConstantType indexType = (GpuConstantType)((ushort)GCT_FLOAT1 + std::min<ushort>(mAtlasTextureCount,4) - 1);
+
+	mVSInpTextureTableIndex = vsMain->resolveInputParameter(Parameter::SPS_TEXTURE_COORDINATES, 
+				mAtlasTexcoordPos, indexContent, indexType);
+		
+	mVSTextureTable = vsProgram->resolveParameter(GCT_FLOAT4, -1, (uint16)GPV_GLOBAL, "AtlasData", mAtlasTableData->size());
+	
+	//
+	// Define parameters to carry the information on the location of the texture from the vertex to
+	// the pixel shader
+	//
+	for(ushort i = 0 ; i < mAtlasTextureCount ; ++ i)
+	{
+		mVSOutTextureDatas[i] = vsMain->resolveOutputParameter(Parameter::SPS_TEXTURE_COORDINATES,
+				-1, Parameter::SPC_UNKNOWN, GCT_FLOAT4);
+		mPSInpTextureDatas[i] = psMain->resolveInputParameter(Parameter::SPS_TEXTURE_COORDINATES, 
+			mVSOutTextureDatas[i]->getIndex(), Parameter::SPC_UNKNOWN, GCT_FLOAT4);
+	}
+	return true;
+}
+
+
+//-----------------------------------------------------------------------
+bool TextureAtlasSampler::resolveDependencies(ProgramSet* programSet)
+{
+	Program* vsProgram = programSet->getCpuVertexProgram();
+	Program* psProgram = programSet->getCpuFragmentProgram();
+	vsProgram->addDependency(FFP_LIB_COMMON);
+	psProgram->addDependency(SGX_LIB_TEXTURE_ATLAS);
+
+	return true;
+}
+
+//-----------------------------------------------------------------------
+bool TextureAtlasSampler::addFunctionInvocations(ProgramSet* programSet)
+{
+	Program* vsProgram = programSet->getCpuVertexProgram();
+	Function* vsMain   = vsProgram->getEntryPointFunction();	
+	Program* psProgram = programSet->getCpuFragmentProgram();
+	Function* psMain   = psProgram->getEntryPointFunction();	
+	FunctionInvocation* curFuncInvocation = NULL;	
+
+	//
+	// Calculate the position and size of the texture in the atlas in the vertex shader
+	//
+	int groupOrder = (FFP_VS_TEXTURING - FFP_VS_LIGHTING) / 2;
+	int internalCounter = 0;
+
+	for(ushort i = 0 ; i < mAtlasTextureCount ; ++i)
+	{
+		Operand::OpMask textureIndexMask = Operand::OPM_X;
+		switch (i)
+		{
+		case 1: textureIndexMask = Operand::OPM_Y; break;
+		case 2: textureIndexMask = Operand::OPM_Z; break;
+		case 3: textureIndexMask = Operand::OPM_W; break;
+		}
+		
+		curFuncInvocation = OGRE_NEW FunctionInvocation(FFP_FUNC_ASSIGN, groupOrder, internalCounter++);
+		curFuncInvocation->pushOperand(mVSTextureTable, Operand::OPS_IN);
+		curFuncInvocation->pushOperand(mVSInpTextureTableIndex, Operand::OPS_IN, textureIndexMask, 1);
+		curFuncInvocation->pushOperand(mVSOutTextureDatas[i], Operand::OPS_OUT);
+		vsMain->addAtomInstance(curFuncInvocation);
+	}
+
+	//
+	// sample the texture in the fragment shader given the extracted data in the pixel shader
+	//
+
+
+	groupOrder = (FFP_PS_SAMPLING + FFP_PS_TEXTURING) / 2;
+
+	internalCounter = 0;
+
+	const ShaderParameterList& inpParams = psMain->getInputParameters();
+	const ShaderParameterList& localParams = psMain->getLocalParameters();
+	
+	ParameterPtr psAtlasTextureCoord = psMain->resolveLocalParameter(Parameter::SPS_UNKNOWN, 
+		-1, "atlasCoord", GCT_FLOAT2);
+
+	for(ushort j = 0 ; j < mAtlasTextureCount ; ++j)
+	{
+		int texNum = mAtlasTextureStart + j;
+		
+		//Find the texture coordinates texel and sampler from the original FFPTexturing
+		ParameterPtr texcoord = psMain->getParameterBySemantic(inpParams, Parameter::SPS_TEXTURE_COORDINATES, texNum);
+		ParameterPtr texel = psMain->getParameterByName(localParams, c_ParamTexel + Ogre::StringConverter::toString(texNum));
+		UniformParameterPtr sampler = psProgram->getParameterByType(GCT_SAMPLER2D, texNum);
+			
+		const char* addressUFuncName = getAdressingFunctionName(mTextureAddressings[j].u);
+		const char* addressVFuncName = getAdressingFunctionName(mTextureAddressings[j].v);
+		
+		//Create a function which will replace the texel with the texture texel
+		if ((texcoord.isNull() == false) && (texel.isNull() == false) && 
+			(sampler.isNull() == false) && (addressUFuncName != NULL) && (addressVFuncName != NULL))
+		{
+			//calculate the U value due to addressing mode
+			curFuncInvocation = OGRE_NEW FunctionInvocation(addressUFuncName, groupOrder, internalCounter++);
+			curFuncInvocation->pushOperand(texcoord, Operand::OPS_IN, Operand::OPM_X);
+			curFuncInvocation->pushOperand(psAtlasTextureCoord, Operand::OPS_OUT, Operand::OPM_X);
+			psMain->addAtomInstance(curFuncInvocation);
+
+			//calculate the V value due to addressing mode
+			curFuncInvocation = OGRE_NEW FunctionInvocation(addressVFuncName, groupOrder, internalCounter++);
+			curFuncInvocation->pushOperand(texcoord, Operand::OPS_IN, Operand::OPM_Y);
+			curFuncInvocation->pushOperand(psAtlasTextureCoord, Operand::OPS_OUT, Operand::OPM_Y);
+			psMain->addAtomInstance(curFuncInvocation);
+
+			//sample the texel color
+			curFuncInvocation = OGRE_NEW FunctionInvocation(SGX_FUNC_ATLAS_SAMPLE, groupOrder, internalCounter++);
+			curFuncInvocation->pushOperand(sampler, Operand::OPS_IN);
+			curFuncInvocation->pushOperand(texcoord, Operand::OPS_IN, Operand::OPM_X | Operand::OPM_Y);
+			curFuncInvocation->pushOperand(psAtlasTextureCoord, Operand::OPS_IN);
+			curFuncInvocation->pushOperand(mPSInpTextureDatas[j], Operand::OPS_IN);
+			curFuncInvocation->pushOperand(texel, Operand::OPS_OUT);
+			psMain->addAtomInstance(curFuncInvocation);
+		}
+	}
+	return true;
+}
+
+//-----------------------------------------------------------------------
+const char* TextureAtlasSampler::getAdressingFunctionName(TextureUnitState::TextureAddressingMode mode)
+{
+	switch (mode)
+	{
+	case TextureUnitState::TAM_WRAP: return SGX_FUNC_ATLAS_WRAP; 
+	case TextureUnitState::TAM_MIRROR: return SGX_FUNC_ATLAS_MIRROR; 
+	case TextureUnitState::TAM_CLAMP: return SGX_FUNC_ATLAS_CLAMP; 
+	case TextureUnitState::TAM_BORDER: return SGX_FUNC_ATLAS_BORDER; 
+	}
+	return NULL;
+}
+
+
+//-----------------------------------------------------------------------
+void TextureAtlasSampler::copyFrom(const SubRenderState& rhs)
+{
+	const TextureAtlasSampler& rhsColour = static_cast<const TextureAtlasSampler&>(rhs);
+
+	mAtlasTexcoordPos = rhsColour.mAtlasTexcoordPos;
+	mAtlasTextureStart = rhsColour.mAtlasTextureStart;
+	mAtlasTextureCount = rhsColour.mAtlasTextureCount;
+	mAtlasTableData = rhsColour.mAtlasTableData;
+}
+
+//-----------------------------------------------------------------------
+void TextureAtlasSampler::updateGpuProgramsParams(Renderable* rend, Pass* pass,  const AutoParamDataSource* source, const LightList* pLightList)
+{
+	if (mIsTableDataUpdated == false)
+	{
+		mIsTableDataUpdated = true;
+		GpuProgramParametersSharedPtr vsGpuParams = pass->getVertexProgramParameters();
+		vector<float>::type buffer(mAtlasTableData->size() * 4);
+		for(size_t i = 0 ; i < mAtlasTableData->size() ; ++i)
+		{
+			buffer[i*4] = (*mAtlasTableData)[i].posU;
+			buffer[i*4 + 1] = (*mAtlasTableData)[i].posV;
+			buffer[i*4 + 2] = (*mAtlasTableData)[i].width;
+			buffer[i*4 + 3] = (*mAtlasTableData)[i].height;
+		}
+				
+
+		vsGpuParams->setNamedConstant(mVSTextureTable->getName(), (const float*)(&(buffer[0])), mAtlasTableData->size()); 
+	}
+}
+
+//-----------------------------------------------------------------------
+bool TextureAtlasSampler::preAddToRenderState(const RenderState* renderState, Pass* srcPass, Pass* dstPass)
+{
+	mAtlasTexcoordPos = 0; 
+	mAtlasTextureStart = 0;
+	mAtlasTextureCount = 0;
+	mAtlasTableData.setNull();
+
+	const TextureAtlasSamplerFactory& factory = TextureAtlasSamplerFactory::getSingleton();
+
+	bool hasError = false;
+	unsigned short texCount = srcPass->getNumTextureUnitStates();
+	for(unsigned short i = 0 ; i < texCount ; ++i)
+	{
+		TextureUnitState* pState = srcPass->getTextureUnitState(i);
+		
+		const TextureAtlasTablePtr& table = factory.getTextureAtlasTable(pState->getTextureName()); 
+		if (table.isNull() == false)
+		{
+			//atlas texture only support 2d textures
+			assert(pState->getTextureType() == TEX_TYPE_2D);
+			if (pState->getTextureType() != TEX_TYPE_2D)
+			{
+				mAtlasTextureCount = 0;
+				break;
+			}
+
+			if (mAtlasTableData.isNull())
+			{
+				mAtlasTableData = table;
+				mAtlasTextureStart = i;
+			}
+			
+			assert(mAtlasTableData == table);
+			mTextureAddressings[mAtlasTextureCount] = pState->getTextureAddressingMode();
+			++mAtlasTextureCount;
+
+			if (mAtlasTextureCount == TAS_MAX_TEXTURES)
+			{
+				//At this time the shader does not support more than TAS_MAX_TEXTURES (4) atlas textures
+				break;
+			}
+		}
+		else if (mAtlasTableData.isNull() == false)
+		{
+			//only support consecutive textures in texture atlas
+			break;
+		}
+	}
+	
+	//calculate the postiion of the indexes 
+	mAtlasTexcoordPos = factory.getTableIndexPositionOffset();
+	if (factory.getTableIndexPositionMode() == TextureAtlasSamplerFactory::ipmRelative)
+	{
+		mAtlasTexcoordPos += texCount - 1;
+	}
+	
+	return mAtlasTextureCount != 0;
+}
+
+TextureAtlasSamplerFactory::TextureAtlasSamplerFactory() :
+	mIndexPositionMode(ipmRelative),
+	mIndexPositionOffset(1)
+{
+
+}
+
+//-----------------------------------------------------------------------
+const String& TextureAtlasSamplerFactory::getType() const
+{
+	return TextureAtlasSampler::Type;
+}
+
+//-----------------------------------------------------------------------
+SubRenderState*	TextureAtlasSamplerFactory::createInstance(ScriptCompiler* compiler, 
+													PropertyAbstractNode* prop, Pass* pass, SGScriptTranslator* translator)
+{
+	return NULL;
+}
+
+//-----------------------------------------------------------------------
+void TextureAtlasSamplerFactory::writeInstance(MaterialSerializer* ser, SubRenderState* subRenderState, 
+										Pass* srcPass, Pass* dstPass)
+{
+}
+
+//-----------------------------------------------------------------------
+bool TextureAtlasSamplerFactory::addTexutreAtlasDefinition( DataStreamPtr stream, TextureAtlasTable * textureAtlasTable )
+{
+	stream->seek(0);
+
+	bool isSucess = false;
+	if (stream->isReadable() == true)
+	{
+		TextureAtlasMap tmpMap;
+		
+		while (stream->eof() == false)
+		{
+			String line = stream->getLine(true);
+			size_t nonWhiteSpacePos = line.find_first_not_of(" \t\r\n");
+			//check this is a line with information
+			if ((nonWhiteSpacePos != String::npos) && (line[nonWhiteSpacePos] != '#'))
+			{
+				//parse the line
+				vector<String>::type strings = StringUtil::split(line, ",\t");
+				
+				if (strings.size() > 8)
+				{
+					String textureName = strings[1];
+
+					TextureAtlasMap::iterator it = tmpMap.find(textureName);
+					if (tmpMap.find(textureName) == tmpMap.end())
+					{
+						it = tmpMap.insert(TextureAtlasMap::value_type(textureName, TextureAtlasTablePtr(new TextureAtlasTable))).first;
+					}
+					
+					// file line format:  <original texture filename>/t/t<atlas filename>, <atlas idx>, <atlas type>, <woffset>, <hoffset>, <depth offset>, <width>, <height>
+					//                              0                           1              2            3             4          5          6               7        8
+					TextureAtlasRecord newRecord(
+						strings[0], // original texture filename
+						strings[1], // atlas filename
+						(float)StringConverter::parseReal(strings[4]), // woffset
+						(float)StringConverter::parseReal(strings[5]), // hoffset
+						(float)StringConverter::parseReal(strings[7]), // width
+						(float)StringConverter::parseReal(strings[8]), // height
+						it->second->size() // texture index in atlas texture
+						);
+
+					it->second->push_back(newRecord);
+					if (textureAtlasTable != NULL)
+					{
+						textureAtlasTable->push_back(newRecord);
+					}
+
+					isSucess = true;
+				}
+			}
+		}
+
+		//place the information in the main texture
+		TextureAtlasMap::const_iterator it = tmpMap.begin();
+		TextureAtlasMap::const_iterator itEnd = tmpMap.end();
+		for(;it != itEnd; ++it)
+		{
+			mAtlases[it->first] = it->second;
+		}
+	}
+	return isSucess;
+}
+
+//-----------------------------------------------------------------------
+void TextureAtlasSamplerFactory::setTextureAtlasTable(const String& textureName, const TextureAtlasTablePtr& atlasData)
+{
+	if ((atlasData.isNull() == true) || (atlasData->empty()))
+		removeTextureAtlasTable(textureName);
+	else mAtlases.insert(TextureAtlasMap::value_type(textureName, atlasData));
+}
+
+//-----------------------------------------------------------------------
+void TextureAtlasSamplerFactory::removeTextureAtlasTable(const String& textureName)
+{
+	mAtlases.erase(textureName);
+}
+
+//-----------------------------------------------------------------------
+void TextureAtlasSamplerFactory::removeAllTextureAtlasTables()
+{
+	mAtlases.clear();
+}
+
+//-----------------------------------------------------------------------
+const TextureAtlasTablePtr& TextureAtlasSamplerFactory::getTextureAtlasTable(const String& textureName) const
+{
+	TextureAtlasMap::const_iterator it = mAtlases.find(textureName);
+	if (it != mAtlases.end())
+	{
+		return it->second;
+	}
+	else return c_BlankAtlasTable;
+}
+
+
+///Set the position of the atlas table indexes within the texcoords of the vertex data
+void TextureAtlasSamplerFactory::setTableIndexPosition(IndexPositionMode mode, ushort offset)
+{
+	//It is illogical for offset to be 0. Go read the explanation in the h file.
+	assert(offset > 0);
+	mIndexPositionMode = mode;
+	mIndexPositionOffset = offset;
+}
+
+///Get the positioning mode of the atlas table indexes within the texcoords of the vertex data
+TextureAtlasSamplerFactory::IndexPositionMode TextureAtlasSamplerFactory::getTableIndexPositionMode() const
+{
+	return mIndexPositionMode;
+}
+
+///Get the offset of the atlas table indexes within the texcoords of the vertex data
+ushort TextureAtlasSamplerFactory::getTableIndexPositionOffset() const
+{
+	return mIndexPositionOffset;
+}
+
+//-----------------------------------------------------------------------
+SubRenderState*	TextureAtlasSamplerFactory::createInstanceImpl()
+{
+	return OGRE_NEW TextureAtlasSampler;
+}
+
+
+}
+}
+
+#endif

Components/RTShaderSystem/src/OgreShaderFFPTexturing.cpp

 String FFPTexturing::Type = "FFP_Texturing";
 #define _INT_VALUE(f) (*(int*)(&(f)))
 
+const String c_ParamTexel("texel_");
+
 //-----------------------------------------------------------------------
 FFPTexturing::FFPTexturing()
 {	
 	
 			
 	// Add texture sampling code.
-	ParameterPtr texel = psMain->resolveLocalParameter(Parameter::SPS_UNKNOWN, 0, "texel", GCT_FLOAT4);
-	FunctionInvocation* curFuncInvocation = NULL;
-	
-	if (textureUnitParams->mTexCoordCalcMethod == TEXCALC_PROJECTIVE_TEXTURE)
-		curFuncInvocation = OGRE_NEW FunctionInvocation(FFP_FUNC_SAMPLE_TEXTURE_PROJ, groupOrder, internalCounter++);
-	else	
-		curFuncInvocation = OGRE_NEW FunctionInvocation(FFP_FUNC_SAMPLE_TEXTURE, groupOrder, internalCounter++);
-
-	curFuncInvocation->pushOperand(textureUnitParams->mTextureSampler, Operand::OPS_IN);
-	curFuncInvocation->pushOperand(textureUnitParams->mPSInputTexCoord, Operand::OPS_IN);
-	curFuncInvocation->pushOperand(texel, Operand::OPS_OUT);
-	psMain->addAtomInstance(curFuncInvocation);
+	ParameterPtr texel = psMain->resolveLocalParameter(Parameter::SPS_UNKNOWN, 0, c_ParamTexel + StringConverter::toString(textureUnitParams->mTextureSamplerIndex), GCT_FLOAT4);
+	addPSSampleTexelInvocation(textureUnitParams, psMain, texel, FFP_PS_SAMPLING, internalCounter);
 
 	// Build colour argument for source1.
 	source1 = psMain->resolveLocalParameter(Parameter::SPS_UNKNOWN, 0, "source1", GCT_FLOAT4);
 }
 
 //-----------------------------------------------------------------------
+void FFPTexturing::addPSSampleTexelInvocation(TextureUnitParams* textureUnitParams, Function* psMain, 
+											  const ParameterPtr& texel, int groupOrder, int& internalCounter)
+{
+	FunctionInvocation* curFuncInvocation = NULL;
+
+	if (textureUnitParams->mTexCoordCalcMethod == TEXCALC_PROJECTIVE_TEXTURE)
+		curFuncInvocation = OGRE_NEW FunctionInvocation(FFP_FUNC_SAMPLE_TEXTURE_PROJ, groupOrder, internalCounter++);
+	else	
+		curFuncInvocation = OGRE_NEW FunctionInvocation(FFP_FUNC_SAMPLE_TEXTURE, groupOrder, internalCounter++);
+
+	curFuncInvocation->pushOperand(textureUnitParams->mTextureSampler, Operand::OPS_IN);
+	curFuncInvocation->pushOperand(textureUnitParams->mPSInputTexCoord, Operand::OPS_IN);
+	curFuncInvocation->pushOperand(texel, Operand::OPS_OUT);
+	psMain->addAtomInstance(curFuncInvocation);
+}
+
+
+//-----------------------------------------------------------------------
 void FFPTexturing::addPSArgumentInvocations(Function* psMain, 
 											 ParameterPtr arg,
 											 ParameterPtr texel,

Components/RTShaderSystem/src/OgreShaderGenerator.cpp

 #include "OgreShaderMaterialSerializerListener.h"
 #include "OgreShaderProgramWriterManager.h"
 #include "OgreHighLevelGpuProgramManager.h"
+#include "OgreShaderExTextureAtlasSampler.h"
 
 namespace Ogre {
 
 	addSubRenderStateFactory(curFactory);
 	mSubRenderStateExFactories[curFactory->getType()] = (curFactory);
 
+	curFactory = new TextureAtlasSamplerFactory;
+	addSubRenderStateFactory(curFactory);
+	mSubRenderStateExFactories[curFactory->getType()] = (curFactory);
 #endif
 }
 

Samples/Media/RTShaderLib/SGXLib_TextureAtlas.cg

+//-----------------------------------------------------------------------------
+// Program Name: SGXLib_IntegratedPSSM
+// Program Desc: Texture Atlas functions.
+// Program Type: Vertex/Pixel shader
+// Language: CG
+//-----------------------------------------------------------------------------
+
+//-----------------------------------------------------------------------------
+void SGX_Atlas_Sample(in sampler2D sample, in float2 origTexcoord, in float2 atlasTexcoord, in float4 textureData, out float4 texel)
+{
+	//texcoord contain:
+	// x = texture atlas u
+	// y = texture atlas v
+	// z = derivative of original u
+	// w = derivative of original v
+	origTexcoord = textureData.xy + origTexcoord * textureData.zw;
+	atlasTexcoord = textureData.xy + atlasTexcoord * textureData.zw;
+	texel = tex2D(sample, atlasTexcoord, ddx(origTexcoord), ddy(origTexcoord));
+}
+
+//-----------------------------------------------------------------------------
+void SGX_Atlas_Wrap(in float inpCoord, out float outCoord)
+{
+	outCoord = frac(inpCoord);
+}
+
+//-----------------------------------------------------------------------------
+void SGX_Atlas_Clamp(in float inpCoord, out float outCoord)
+{
+	outCoord = saturate(inpCoord);
+}
+//-----------------------------------------------------------------------------
+void SGX_Atlas_Mirror(in float inpCoord, out float outCoord)
+{
+	outCoord = (inpCoord + 1) * 0.5;
+	outCoord = abs(frac(outCoord) * 2 - 1);
+}
+
+//-----------------------------------------------------------------------------
+void SGX_Atlas_Border(in float inpCoord, out float outCoord)
+{
+	//
+	//The shader needs to check whether the original texcoord are beyond the 0,1 range.
+	//The shader attempts to do so without using if statments which are complicated for shaders
+	//
+	
+	//if texcoord is in the 0,1 range then check will equal 0, 
+	//Otherwise it will equal the number 1 or greater
+	float check = step(inpCoord, 0) + step(1, inpCoord);
+	
+	//using the check value transport the value of the texcoord beyond the 0,1 range so it will
+	//recive the border color
+	outCoord = abs(inpCoord) + check * 2;
+}

Samples/Media/RTShaderLib/SGXLib_TextureAtlas.glsl

+//-----------------------------------------------------------------------------
+// Program Name: SGXLib_IntegratedPSSM
+// Program Desc: Texture Atlas functions.
+// Program Type: Vertex/Pixel shader
+// Language: GLSL
+//-----------------------------------------------------------------------------
+
+//-----------------------------------------------------------------------------
+void SGX_Atlas_Sample(in sampler2D sample, in vec2 origTexcoord, in vec2 atlasTexcoord, in vec4 textureData, out vec4 texel)
+{
+	origTexcoord = textureData.xy + origTexcoord * textureData.zw;
+	atlasTexcoord = textureData.xy + atlasTexcoord * textureData.zw;
+	texel = texture2DGrad(sample, atlasTexcoord, dFdx(origTexcoord), dFdy(origTexcoord));
+}
+
+//-----------------------------------------------------------------------------
+void SGX_Atlas_Wrap(in float inpCoord, out float outCoord)
+{
+	outCoord = frac(inpCoord);
+}
+
+//-----------------------------------------------------------------------------
+void SGX_Atlas_Clamp(in float inpCoord, out float outCoord)
+{
+	outCoord = clamp(inpCoord, 0.0, 1.0);
+}
+//-----------------------------------------------------------------------------
+void SGX_Atlas_Mirror(in float inpCoord, out float outCoord)
+{
+	outCoord = (inpCoord + 1) * 0.5;
+	outCoord = abs(frac(outCoord) * 2 - 1);
+}
+
+//-----------------------------------------------------------------------------
+void SGX_Atlas_Border(in float inpCoord, out float outCoord)
+{
+	//
+	//The shader needs to check whether the original texcoord are beyond the 0,1 range.
+	//The shader attempts to do so without using if statments which are complicated for shaders
+	//
+	
+	//if texcoord is in the 0,1 range then check will equal 0, 
+	//Otherwise it will equal the number 1 or greater
+	float check = step(inpCoord, 0) + step(1, inpCoord);
+	
+	//using the check value transport the value of the texcoord beyond the 0,1 range so it will
+	//recive the border color
+	outCoord = abs(inpCoord) + check * 2;
+}

Samples/Media/RTShaderLib/SGXLib_TextureAtlas.glsles

+//-----------------------------------------------------------------------------
+// Program Name: SGXLib_IntegratedPSSM
+// Program Desc: Texture Atlas functions.
+// Program Type: Vertex/Pixel shader
+// Language: GLSLES
+//-----------------------------------------------------------------------------
+
+//-----------------------------------------------------------------------------
+void SGX_Atlas_Sample(in sampler2D sample, in vec2 origTexcoord, in vec2 atlasTexcoord, in vec4 textureData, out vec4 texel)
+{
+	origTexcoord = textureData.xy + origTexcoord * textureData.zw;
+	atlasTexcoord = textureData.xy + atlasTexcoord * textureData.zw;
+	texel = texture2DGrad(sample, atlasTexcoord, dFdx(origTexcoord), dFdy(origTexcoord));
+}
+
+//-----------------------------------------------------------------------------
+void SGX_Atlas_Wrap(in float inpCoord, out float outCoord)
+{
+	outCoord = frac(inpCoord);
+}
+
+//-----------------------------------------------------------------------------
+void SGX_Atlas_Clamp(in float inpCoord, out float outCoord)
+{
+	outCoord = clamp(inpCoord, 0.0, 1.0);
+}
+//-----------------------------------------------------------------------------
+void SGX_Atlas_Mirror(in float inpCoord, out float outCoord)
+{
+	outCoord = (inpCoord + 1) * 0.5;
+	outCoord = abs(frac(outCoord) * 2 - 1);
+}
+
+//-----------------------------------------------------------------------------
+void SGX_Atlas_Border(in float inpCoord, out float outCoord)
+{
+	//
+	//The shader needs to check whether the original texcoord are beyond the 0,1 range.
+	//The shader attempts to do so without using if statments which are complicated for shaders
+	//
+	
+	//if texcoord is in the 0,1 range then check will equal 0, 
+	//Otherwise it will equal the number 1 or greater
+	float check = step(inpCoord, 0) + step(1, inpCoord);
+	
+	//using the check value transport the value of the texcoord beyond the 0,1 range so it will
+	//recive the border color
+	outCoord = abs(inpCoord) + check * 2;
+}

Samples/Media/RTShaderLib/SGXLib_TextureAtlas.hlsl

+//-----------------------------------------------------------------------------
+// Program Name: SGXLib_IntegratedPSSM
+// Program Desc: Texture Atlas functions.
+// Program Type: Vertex/Pixel shader
+// Language: HLSL
+//-----------------------------------------------------------------------------
+
+//-----------------------------------------------------------------------------
+void SGX_Atlas_Sample(in sampler2D sample, in float2 origTexcoord, in float2 atlasTexcoord, in float4 textureData, out float4 texel)
+{
+	//texcoord contain:
+	// x = texture atlas u
+	// y = texture atlas v
+	// z = derivative of original u
+	// w = derivative of original v
+	origTexcoord = textureData.xy + origTexcoord * textureData.zw;
+	atlasTexcoord = textureData.xy + atlasTexcoord * textureData.zw;
+	texel = tex2D(sample, atlasTexcoord, ddx(origTexcoord), ddy(origTexcoord));
+}
+
+//-----------------------------------------------------------------------------
+void SGX_Atlas_Wrap(in float inpCoord, out float outCoord)
+{
+	outCoord = frac(inpCoord);
+}
+
+//-----------------------------------------------------------------------------
+void SGX_Atlas_Clamp(in float inpCoord, out float outCoord)
+{
+	outCoord = saturate(inpCoord);
+}
+//-----------------------------------------------------------------------------
+void SGX_Atlas_Mirror(in float inpCoord, out float outCoord)
+{
+	outCoord = (inpCoord + 1) * 0.5;
+	outCoord = abs(frac(outCoord) * 2 - 1);
+}
+
+//-----------------------------------------------------------------------------
+void SGX_Atlas_Border(in float inpCoord, out float outCoord)
+{
+	//
+	//The shader needs to check whether the original texcoord are beyond the 0,1 range.
+	//The shader attempts to do so without using if statments which are complicated for shaders
+	//
+	
+	//if texcoord is in the 0,1 range then check will equal 0, 
+	//Otherwise it will equal the number 1 or greater
+	float check = step(inpCoord, 0) + step(1, inpCoord);
+	
+	//using the check value transport the value of the texcoord beyond the 0,1 range so it will
+	//recive the border color
+	outCoord = abs(inpCoord) + check * 2;
+}