//-----------------------------------------------------------------------
    void UnifiedHighLevelGpuProgram::chooseDelegate() const
    {
        OGRE_LOCK_AUTO_MUTEX;

        mChosenDelegate.setNull();

        HighLevelGpuProgramPtr tmpDelegate;
        tmpDelegate.setNull();
        int tmpPriority = -1;

        for (StringVector::const_iterator i = mDelegateNames.begin(); i != mDelegateNames.end(); ++i)
        {
            HighLevelGpuProgramPtr deleg = HighLevelGpuProgramManager::getSingleton().getByName(*i, mGroup);

            //recheck with auto resource group
            if (deleg.isNull())
              deleg = HighLevelGpuProgramManager::getSingleton().getByName(*i);

            // Silently ignore missing links
            if(!deleg.isNull() && deleg->isSupported())
            {
                int priority = getPriority(deleg->getLanguage());
                //Find the delegate with the highest prioriry
                if (priority >= tmpPriority)
                {
                    tmpDelegate = deleg;
                    tmpPriority = priority;
                }
            }

        }

        mChosenDelegate = tmpDelegate;
    }
	//---------------------------------------------------------------------
	HighLevelGpuProgramPtr
		TerrainMaterialGeneratorA::SM2Profile::ShaderHelperCg::createFragmentProgram(
			const SM2Profile* prof, const Terrain* terrain, TechniqueType tt)
	{
		HighLevelGpuProgramManager& mgr = HighLevelGpuProgramManager::getSingleton();
		String progName = getFragmentProgramName(prof, terrain, tt);

		HighLevelGpuProgramPtr ret = mgr.getByName(progName);
		if (ret.isNull())
		{
			ret = mgr.createProgram(progName, ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, 
				"cg", GPT_FRAGMENT_PROGRAM);
		}
		else
		{
			ret->unload();
		}
		
		if(prof->isLayerNormalMappingEnabled() || prof->isLayerParallaxMappingEnabled())
			ret->setParameter("profiles", "ps_4_0 ps_3_0 ps_2_x fp40 arbfp1");
		else
			ret->setParameter("profiles", "ps_4_0 ps_3_0 ps_2_0 fp30 arbfp1");
		ret->setParameter("entry_point", "main_fp");

		return ret;

	}
Exemplo n.º 3
0
HighLevelGpuProgramPtr WaterMaterialGenerator::createVertexProgram()
{
	HighLevelGpuProgramManager& mgr = HighLevelGpuProgramManager::getSingleton();
	std::string progName = mDef->getName() + "_VP";

	HighLevelGpuProgramPtr ret = mgr.getByName(progName);
	if (!ret.isNull())
		mgr.remove(progName);

	ret = mgr.createProgram(progName, ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, 
		"cg", GPT_VERTEX_PROGRAM);

	if(MRTSupported())
	{
		ret->setParameter("profiles", "vs_4_0 vs_3_0 vp40");
	}
	else
	{
		ret->setParameter("profiles", "vs_4_0 vs_2_x vp40 arbvp1");
	}
	ret->setParameter("entry_point", "main_vp");

	StringUtil::StrStreamType outStream;
	generateVertexProgramSource(outStream);
	ret->setSource(outStream.str());
	ret->load();

	vertexProgramParams(ret);
	
	return ret;
}
Exemplo n.º 4
0
HighLevelGpuProgramPtr WaterMaterialGenerator::createFragmentProgram()
{
	HighLevelGpuProgramManager& mgr = HighLevelGpuProgramManager::getSingleton();
	std::string progName = mDef->getName() + "_FP";

	HighLevelGpuProgramPtr ret = mgr.getByName(progName);
	if (!ret.isNull())
		mgr.remove(progName);

	ret = mgr.createProgram(progName, ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, 
			"cg", GPT_FRAGMENT_PROGRAM);

	if(MRTSupported())
		ret->setParameter("profiles", "ps_4_0 ps_3_0 fp40");
	else
		ret->setParameter("profiles", "ps_4_0 ps_3_0 fp40 arbfp1");	

	ret->setParameter("entry_point", "main_fp");

	StringUtil::StrStreamType outStream;
	generateFragmentProgramSource(outStream);
	ret->setSource(outStream.str());
	ret->load();

	GpuProgramParametersSharedPtr params = ret->getDefaultParameters();
	fragmentProgramParams(ret);
	
	return ret;
}
Exemplo n.º 5
0
	//-----------------------------------------------------------------------
    void GLSLProgram::attachChildShader(const String& name)
	{
		// is the name valid and already loaded?
		// check with the high level program manager to see if it was loaded
		HighLevelGpuProgramPtr hlProgram = HighLevelGpuProgramManager::getSingleton().getByName(name);
		if (!hlProgram.isNull())
		{
			if (hlProgram->getSyntaxCode() == "glsl")
			{
				// make sure attached program source gets loaded and compiled
				// don't need a low level implementation for attached shader objects
				// loadHighLevelImpl will only load the source and compile once
				// so don't worry about calling it several times
				GLSLProgram* childShader = static_cast<GLSLProgram*>(hlProgram.getPointer());
				// load the source and attach the child shader only if supported
				if (isSupported())
				{
					childShader->loadHighLevelImpl();
					// add to the container
					mAttachedGLSLPrograms.push_back( childShader );
					mAttachedShaderNames += name + " ";
				}
			}
		}
	}
Exemplo n.º 6
0
HighLevelGpuProgramPtr ParticleMaterialGenerator::createSoftParticleVertexProgram()
{
	HighLevelGpuProgramManager& mgr = HighLevelGpuProgramManager::getSingleton();
	std::string progName = mDef->getName() + "_ambient_VP";

	HighLevelGpuProgramPtr ret = mgr.getByName(progName);
	if (!ret.isNull())
		mgr.remove(progName);

	ret = mgr.createProgram(progName, ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, 
		"cg", GPT_VERTEX_PROGRAM);

	ret->setParameter("profiles", "vs_4_0 vs_1_1 arbvp1");
	ret->setParameter("entry_point", "main_vp");

	StringUtil::StrStreamType sourceStr;
	
	sourceStr <<
	"void main_vp( 	float4 position 					: POSITION, \n"
	"	float4 color 						: COLOR,  \n"
	"	float2 texCoord 					: TEXCOORD0,  \n"
	"	out float4 oPosition			 	: POSITION,  \n"
	"	out float4 objectPos				: COLOR,  \n"
	"	out float4 oTexCoord				: TEXCOORD0,  \n"
	"	out float4 oVertexColour				: TEXCOORD1,  \n"
	"	out float4 oScreenPosition				: TEXCOORD2,  \n"
	"	out float4 oWorldPosition				: TEXCOORD3,  \n"
	"	uniform float enableFog,  \n"
	"	uniform float4 fogParams,  \n"
	"	uniform float4x4 wvpMat,  \n"
	"	uniform float4x4 wMat  \n"
	")  \n"
	"{  \n"
	"	oVertexColour = color;  \n"
	"	oPosition = mul(wvpMat, position);  \n"
	"	oWorldPosition = mul(wMat, position);  \n"
	"	oScreenPosition = oPosition; \n"
	"	oTexCoord = float4(texCoord.x, texCoord.y, 1, 1);  \n"
	"	objectPos = position;  \n"
	"	objectPos.w = enableFog * saturate(fogParams.x * (oPosition.z - fogParams.y) * fogParams.w);  \n"
	"} \n";
	
	ret->setSource(sourceStr.str());
	ret->load();
	
	// params
	GpuProgramParametersSharedPtr params = ret->getDefaultParameters();
	params->setIgnoreMissingParams(true);
	params->setNamedAutoConstant("wvpMat", GpuProgramParameters::ACT_WORLDVIEWPROJ_MATRIX);
	params->setNamedAutoConstant("wMat", GpuProgramParameters::ACT_WORLD_MATRIX);
	params->setNamedAutoConstant("fogParams", GpuProgramParameters::ACT_FOG_PARAMS);
	params->setNamedConstant("enableFog", mDef->mProps->fog ? Real(1.0) : Real(0.0));
	
	return ret;
}
	//---------------------------------------------------------------------
	//---------------------------------------------------------------------
	HighLevelGpuProgramPtr
	TerrainMaterialGeneratorA::SM2Profile::ShaderHelperCg::createVertexProgram(
		const SM2Profile* prof, const Terrain* terrain, TechniqueType tt)
	{
		HighLevelGpuProgramManager& mgr = HighLevelGpuProgramManager::getSingleton();
		String progName = getVertexProgramName(prof, terrain, tt);
		HighLevelGpuProgramPtr ret = mgr.getByName(progName);
		if (ret.isNull())
		{
			ret = mgr.createProgram(progName, ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, 
				"cg", GPT_VERTEX_PROGRAM);
		}
		else
		{
			ret->unload();
		}

		ret->setParameter("profiles", "vs_4_0 vs_3_0 vs_2_0 arbvp1");
		ret->setParameter("entry_point", "main_vp");

		return ret;

	}
	//-----------------------------------------------------------------------
	void UnifiedHighLevelGpuProgram::chooseDelegate() const
	{
            OGRE_LOCK_AUTO_MUTEX;

		mChosenDelegate.setNull();

		for (StringVector::const_iterator i = mDelegateNames.begin();
			i != mDelegateNames.end(); ++i)
		{
			HighLevelGpuProgramPtr deleg = 
				HighLevelGpuProgramManager::getSingleton().getByName(*i);

			// Silently ignore missing links
			if(!deleg.isNull()
				&& deleg->isSupported())
			{
				mChosenDelegate = deleg;
				break;
			}

		}

	}
//-----------------------------------------------------------------------------
GpuProgramPtr ProgramManager::createGpuProgram(Program* shaderProgram, 
											   ProgramWriter* programWriter,
											   const String& language,
											   const String& profiles,
											   const StringVector& profilesList,
											   const String& cachePath)
{

	
#if OGRE_PLATFORM == OGRE_PLATFORM_ANDROID
	Ogre::StringSerialiser sourceCodeStringStream;
#else
	std::stringstream sourceCodeStringStream;
#endif
	_StringHash stringHash;
	uint32 programHashCode;
	String programName;

	// Generate source code.
	programWriter->writeSourceCode(sourceCodeStringStream, shaderProgram);

	// Generate program hash code.
	programHashCode = static_cast<uint32>(stringHash(sourceCodeStringStream.str()));

	// Generate program name.
	programName = StringConverter::toString(programHashCode);
	
	if (shaderProgram->getType() == GPT_VERTEX_PROGRAM)
	{
		programName += "_VS";
	}
	else if (shaderProgram->getType() == GPT_FRAGMENT_PROGRAM)
	{
		programName += "_FS";
	}

	HighLevelGpuProgramPtr pGpuProgram;

	// Try to get program by name.
	pGpuProgram = HighLevelGpuProgramManager::getSingleton().getByName(programName);

	// Case the program doesn't exist yet.
	if (pGpuProgram.isNull())
	{
		// Create new GPU program.
		pGpuProgram = HighLevelGpuProgramManager::getSingleton().createProgram(programName,
			ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, language, shaderProgram->getType());

		// Case cache directory specified -> create program from file.
		if (cachePath.empty() == false)
		{
			const String  programFullName = programName + "." + language;
			const String  programFileName = cachePath + programFullName;	
			std::ifstream programFile;
			bool		  writeFile = true;


			// Check if program file already exist.
			programFile.open(programFileName.c_str());

			// Case no matching file found -> we have to write it.
			if (!programFile)
			{			
				writeFile = true;
			}
			else
			{
				writeFile = false;
				programFile.close();
			}

			// Case we have to write the program to a file.
			if (writeFile)
			{
				std::ofstream outFile(programFileName.c_str());

				if (!outFile)
					return GpuProgramPtr();

				outFile << sourceCodeStringStream.str();
				outFile.close();
			}

			pGpuProgram->setSourceFile(programFullName);
		}

		// No cache directory specified -> create program from system memory.
		else
		{
			pGpuProgram->setSource(sourceCodeStringStream.str());
		}
		
		
		pGpuProgram->setParameter("entry_point", shaderProgram->getEntryPointFunction()->getName());

		// HLSL program requires specific target profile settings - we have to split the profile string.
		if (language == "hlsl")
		{
			StringVector::const_iterator it = profilesList.begin();
			StringVector::const_iterator itEnd = profilesList.end();
			
			for (; it != itEnd; ++it)
			{
				if (GpuProgramManager::getSingleton().isSyntaxSupported(*it))
				{
					pGpuProgram->setParameter("target", *it);
					break;
				}
			}
		}
		
		pGpuProgram->setParameter("profiles", profiles);
		pGpuProgram->load();
	
		// Case an error occurred.
		if (pGpuProgram->hasCompileError())
		{
			pGpuProgram.setNull();
			return GpuProgramPtr(pGpuProgram);
		}

		// Add the created GPU program to local cache.
		if (pGpuProgram->getType() == GPT_VERTEX_PROGRAM)
		{
			mVertexShaderMap[programName] = pGpuProgram;			
		}
		else if (pGpuProgram->getType() == GPT_FRAGMENT_PROGRAM)
		{
			mFragmentShaderMap[programName] = pGpuProgram;	
		}				
	}
	
	return GpuProgramPtr(pGpuProgram);
}
Exemplo n.º 10
0
void GrassLayerBase::_updateShaders()
{
  if (shaderNeedsUpdate) {
    shaderNeedsUpdate = false;

    //Proceed only if there is no custom vertex shader and the user's computer supports vertex shaders
    const RenderSystemCapabilities *caps = Root::getSingleton().getRenderSystem()->getCapabilities();
    if (caps->hasCapability(RSC_VERTEX_PROGRAM) && geom->getShadersEnabled()) {
      //Calculate fade range
      float farViewDist = geom->getDetailLevels().front()->getFarRange();
      float fadeRange = farViewDist / 1.2247449f;
      //Note: 1.2247449 ~= sqrt(1.5), which is necessary since the far view distance is measured from the centers
      //of pages, while the vertex shader needs to fade grass completely out (including the closest corner)
      //before the page center is out of range.

      //Generate a string ID that identifies the current set of vertex shader options
      StringUtil::StrStreamType tmpName;
      tmpName << "GrassVS_";
      if (animate)
        tmpName << "anim_";
      if (blend)
        tmpName << "blend_";
      if (lighting)
        tmpName << "lighting_";
      tmpName << renderTechnique << "_";
      tmpName << fadeTechnique << "_";
      if (fadeTechnique == FADETECH_GROW || fadeTechnique == FADETECH_ALPHAGROW)
        tmpName << maxHeight << "_";
      tmpName << farViewDist << "_";
      tmpName << "vp";
      const String vsName = tmpName.str();

      //Generate a string ID that identifies the material combined with the vertex shader
      const String matName = material->getName() + "_" + vsName;

      //Check if the desired material already exists (if not, create it)
      MaterialPtr tmpMat = MaterialManager::getSingleton().getByName(matName);
      if (tmpMat.isNull()) {
        //Clone the original material
        tmpMat = material->clone(matName);

        //Disable lighting
        tmpMat->setLightingEnabled(false);
        //tmpMat->setReceiveShadows(false);

        //Check if the desired shader already exists (if not, compile it)
        String shaderLanguage = ShaderHelper::getShaderLanguage();
        HighLevelGpuProgramPtr vertexShader = HighLevelGpuProgramManager::getSingleton().getByName(vsName);
        if (vertexShader.isNull()) {

          //Generate the grass shader
          String vertexProgSource;

          if (!shaderLanguage.compare("hlsl") || !shaderLanguage.compare("cg")) {

            vertexProgSource = "void main( \n"
                "	float4 iPosition : POSITION, \n"
                "	float4 iColor : COLOR, \n"
                "	float2 iUV       : TEXCOORD0,	\n"
                "	out float4 oPosition : POSITION, \n"
                "	out float4 oColor : COLOR, \n"
                "	out float2 oUV       : TEXCOORD0,	\n";

            if (lighting)
              vertexProgSource += "   uniform float4   objSpaceLight,   \n"
                  "   uniform float4   lightDiffuse,   \n"
                  "   uniform float4   lightAmbient,   \n";

            if (animate)
              vertexProgSource += "	uniform float time,	\n"
                  "	uniform float frequency,	\n"
                  "	uniform float4 direction,	\n";

            if (fadeTechnique == FADETECH_GROW || fadeTechnique == FADETECH_ALPHAGROW)
              vertexProgSource += "	uniform float grassHeight,	\n";

            if (renderTechnique == GRASSTECH_SPRITE || lighting)
              vertexProgSource += "   float4 iNormal : NORMAL, \n";

            vertexProgSource += "	uniform float4x4 worldViewProj,	\n"
                "	uniform float3 camPos, \n"
                "	uniform float fadeRange ) \n"
                "{	\n"
                "	oColor.rgb = iColor.rgb;   \n"
                "	float4 position = iPosition;	\n"
                "	float dist = distance(camPos.xz, position.xz);	\n";

            if (lighting) {
              vertexProgSource += "   float3 light = normalize(objSpaceLight.xyz - (iPosition.xyz * objSpaceLight.w)); \n"
                  "   float diffuseFactor = max(dot(float4(0,1,0,0), light), 0); \n"
                  "   oColor = (lightAmbient + diffuseFactor * lightDiffuse) * iColor; \n";
            } else {
              vertexProgSource += "   oColor.rgb = iColor.rgb;               \n";
            }

            if (fadeTechnique == FADETECH_ALPHA || fadeTechnique == FADETECH_ALPHAGROW)
              vertexProgSource +=
              //Fade out in the distance
                  "	oColor.a = 2.0f - (2.0f * dist / fadeRange);   \n";
            else
              vertexProgSource += "	oColor.a = 1.0f;   \n";

            vertexProgSource += "	float oldposx = position.x;	\n";

            if (renderTechnique == GRASSTECH_SPRITE)
              vertexProgSource +=
              //Face the camera
                  "	float3 dirVec = (float3)position - (float3)camPos;		\n"
                      "	float3 p = normalize(cross(float4(0,1,0,0), dirVec));	\n"
                      "	position += float4(p.x * iNormal.x, iNormal.y, p.z * iNormal.x, 0);	\n";

            if (animate)
              vertexProgSource += "	if (iUV.y == 0.0f){	\n"
              //Wave grass in breeze
                      "		float offset = sin(time + oldposx * frequency);	\n"
                      "		position += direction * offset;	\n"
                      "	}	\n";

            if (blend && animate)
              vertexProgSource += "	else {	\n";
            else if (blend)
              vertexProgSource += "	if (iUV.y != 0.0f){	\n";

            if (blend)
              vertexProgSource +=
              //Blend the base of nearby grass into the terrain
                  "		oColor.a = clamp(oColor.a, 0, 1) * 4.0f * ((dist / fadeRange) - 0.1f);	\n"
                      "	}	\n";

            if (fadeTechnique == FADETECH_GROW || fadeTechnique == FADETECH_ALPHAGROW)
              vertexProgSource += "	float offset = (2.0f * dist / fadeRange) - 1.0f; \n"
                  "	position.y -= grassHeight * clamp(offset, 0, 1); ";

            vertexProgSource += "	oPosition = mul(worldViewProj, position);  \n";

            vertexProgSource += "	oUV = iUV;\n"
                "}";
          } else {
            //Must be glsl
            if (lighting) {
              vertexProgSource = "uniform vec4 objSpaceLight; \n"
                  "uniform vec4 lightDiffuse; \n"
                  "uniform vec4 lightAmbient; \n";
            }

            if (animate) {
              vertexProgSource += "uniform float time; \n"
                  "uniform float frequency; \n"
                  "uniform vec4 direction; \n";
            }

            if (fadeTechnique == FADETECH_GROW || fadeTechnique == FADETECH_ALPHAGROW) {
              vertexProgSource += "uniform float grassHeight;	\n";
            }

            vertexProgSource += "uniform vec3 camPos; \n"
                "uniform float fadeRange; \n"
                "\n"
                "void main()"
                "{ \n"
                "    vec4 color = gl_Color; \n"
                "    vec4 position = gl_Vertex;	\n"
                "    float dist = distance(camPos.xz, position.xz);	\n";

            if (lighting) {
              vertexProgSource += "    vec3 light = normalize(objSpaceLight.xyz - (gl_Vertex.xyz * objSpaceLight.w)); \n"
                  "    float diffuseFactor = max( dot( vec3(0.0,1.0,0.0), light), 0.0); \n"
                  "    color = (lightAmbient + diffuseFactor * lightDiffuse) * gl_Color; \n";
            } else {
              vertexProgSource += "    color.xyz = gl_Color.xyz; \n";
            }

            if (fadeTechnique == FADETECH_ALPHA || fadeTechnique == FADETECH_ALPHAGROW) {
              vertexProgSource +=
              //Fade out in the distance
                  "    color.w = 2.0 - (2.0 * dist / fadeRange); \n";
            } else {
              vertexProgSource += "    color.w = 1.0; \n";
            }

            if (renderTechnique == GRASSTECH_SPRITE) {
              vertexProgSource +=
              //Face the camera
                  "    vec3 dirVec = position.xyz - camPos.xyz; \n"
                      "    vec3 p = normalize(cross(vec3(0.0,1.0,0.0), dirVec)); \n"
                      "    position += vec4(p.x * gl_Normal.x, gl_Normal.y, p.z * gl_Normal.x, 0.0); \n";
            }

            if (animate) {
              vertexProgSource += "    if (gl_MultiTexCoord0.y == 0.0) \n"
                  "    { \n"
                  //Wave grass in breeze
                  "        position += direction * sin(time + gl_Vertex.x * frequency); \n"
                  "    } \n";
            }

            if (blend && animate) {
              vertexProgSource += "    else \n"
                  "    { \n";
            } else if (blend) {
              vertexProgSource += "    if (gl_MultiTexCoord0.y != 0.0) \n"
                  "    { \n";
            }

            if (blend) {
              vertexProgSource +=
              //Blend the base of nearby grass into the terrain
                  "        color.w = clamp(color.w, 0.0, 1.0) * 4.0 * ((dist / fadeRange) - 0.1); \n"
                      "    } \n";
            }

            if (fadeTechnique == FADETECH_GROW || fadeTechnique == FADETECH_ALPHAGROW) {
              vertexProgSource += "    position.y -= grassHeight * clamp((2.0 * dist / fadeRange) - 1.0, 0.0, 1.0); \n";
            }

            vertexProgSource += "    gl_Position = gl_ModelViewProjectionMatrix * position; \n"
                "    gl_FrontColor = color; \n"
                "    gl_TexCoord[0] = gl_MultiTexCoord0; \n";
            if (geom->getSceneManager()->getFogMode() == Ogre::FOG_EXP2) {
              vertexProgSource += "	gl_FogFragCoord = clamp(exp(- gl_Fog.density * gl_Fog.density * gl_Position.z * gl_Position.z), 0.0, 1.0); \n";
            } else {
              vertexProgSource += "	gl_FogFragCoord = gl_Position.z; \n";
            }

            vertexProgSource += "}";
          }

          vertexShader = HighLevelGpuProgramManager::getSingleton().createProgram(vsName, ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, shaderLanguage, GPT_VERTEX_PROGRAM);

          vertexShader->setSource(vertexProgSource);

          if (shaderLanguage == "hlsl") {
            vertexShader->setParameter("target", "vs_1_1");
            vertexShader->setParameter("entry_point", "main");
          } else if (shaderLanguage == "cg") {
            vertexShader->setParameter("profiles", "vs_1_1 arbvp1");
            vertexShader->setParameter("entry_point", "main");
          }
          // GLSL can only have one entry point "main".

          vertexShader->load();
        }
        //Now the vertex shader (vertexShader) has either been found or just generated
        //(depending on whether or not it was already generated).

        tmpMat->load();
        Ogre::Material::TechniqueIterator techIterator = tmpMat->getSupportedTechniqueIterator();
        while (techIterator.hasMoreElements()) {
          Ogre::Technique* tech = techIterator.getNext();
          //Apply the shader to the material
          Pass *pass = tech->getPass(0);
          pass->setVertexProgram(vsName);
          GpuProgramParametersSharedPtr params = pass->getVertexProgramParameters();

          if (shaderLanguage.compare("glsl"))
            //glsl can use the built in gl_ModelViewProjectionMatrix
            params->setNamedAutoConstant("worldViewProj", GpuProgramParameters::ACT_WORLDVIEWPROJ_MATRIX);
          params->setNamedAutoConstant("camPos", GpuProgramParameters::ACT_CAMERA_POSITION_OBJECT_SPACE);
          params->setNamedAutoConstant("fadeRange", GpuProgramParameters::ACT_CUSTOM, 1);

          if (animate) {
            params->setNamedConstant("time", 1.0f);
            params->setNamedConstant("frequency", 1.0f);
            params->setNamedConstant("direction", Ogre::Vector4::ZERO);
          }

          if (lighting) {
            params->setNamedAutoConstant("objSpaceLight", GpuProgramParameters::ACT_LIGHT_POSITION_OBJECT_SPACE);
            params->setNamedAutoConstant("lightDiffuse", GpuProgramParameters::ACT_DERIVED_LIGHT_DIFFUSE_COLOUR);
            params->setNamedAutoConstant("lightAmbient", GpuProgramParameters::ACT_DERIVED_AMBIENT_LIGHT_COLOUR);
          }

          if (fadeTechnique == FADETECH_GROW || fadeTechnique == FADETECH_ALPHAGROW) {
            params->setNamedConstant("grassHeight", maxHeight * 1.05f);
          }

          pass->getVertexProgramParameters()->setNamedConstant("fadeRange", fadeRange);
        }
      }
      //Now the material (tmpMat) has either been found or just created (depending on whether or not it was already
      //created). The appropriate vertex shader should be applied and the material is ready for use.

      //Apply the new material
      material = tmpMat;
    }

    Ogre::Technique* tech = material->getBestTechnique();
    if (tech && tech->getNumPasses()) {
      Ogre::Pass* pass = tech->getPass(0);
      if (pass->hasVertexProgram()) {
        Ogre::GpuProgramParametersSharedPtr params = pass->getVertexProgramParameters();
        if (!params.isNull()) {
          params->setIgnoreMissingParams(true);
        }
      }
    }
  }
}
Exemplo n.º 11
0
//-----------------------------------------------------------------------------
/// Constructor
StaticBillboardSet::StaticBillboardSet(SceneManager *mgr, SceneNode *rootSceneNode, BillboardMethod method) :
mVisible                (true),
mFadeEnabled            (false),
mRenderMethod           (method),
mpSceneMgr              (mgr),
mpSceneNode             (NULL),
mpEntity                (NULL),
mfUFactor               (1.f),
mfVFactor               (1.f),
mpFallbackBillboardSet  (NULL),
mBBOrigin               (BBO_CENTER),
mFadeVisibleDist        (0.f),
mFadeInvisibleDist      (0.f)
{
   assert(rootSceneNode);

   //Fall back to BB_METHOD_COMPATIBLE if vertex shaders are not available
   if (method == BB_METHOD_ACCELERATED)
   {
      const RenderSystemCapabilities *caps = Root::getSingleton().getRenderSystem()->getCapabilities();
      if (!caps->hasCapability(RSC_VERTEX_PROGRAM))
         mRenderMethod = BB_METHOD_COMPATIBLE;
   }

   mpSceneNode = rootSceneNode->createChildSceneNode();
   mEntityName = getUniqueID("SBSentity");

   if (mRenderMethod == BB_METHOD_ACCELERATED)
   {
      //Load vertex shader to align billboards to face the camera (if not loaded already)
      if (s_nSelfInstances == 0)
      {
         const Ogre::String &renderName = Root::getSingleton().getRenderSystem()->getName();
         s_isGLSL = renderName == "OpenGL Rendering Subsystem" ? true : false;
         Ogre::String shaderLanguage = s_isGLSL ? "glsl" : renderName == "Direct3D9 Rendering Subsystem" ? "hlsl" : "cg";

         //First shader, simple camera-alignment
         String vertexProg;
         if (!s_isGLSL) // DirectX HLSL or nVidia CG
         {
            vertexProg =
               "void Sprite_vp(	\n"
               "	float4 position : POSITION,	\n"
               "	float3 normal   : NORMAL,	\n"
               "	float4 color	: COLOR,	\n"
               "	float2 uv       : TEXCOORD0,	\n"
               "	out float4 oPosition : POSITION,	\n"
               "	out float2 oUv       : TEXCOORD0,	\n"
               "	out float4 oColor    : COLOR, \n"
               "	out float oFog       : FOG,	\n"
               "	uniform float4x4 worldViewProj,	\n"
               "	uniform float    uScroll, \n"
               "	uniform float    vScroll, \n"
               "	uniform float4   preRotatedQuad[4] )	\n"
               "{	\n"
               //Face the camera
               "	float4 vCenter = float4( position.x, position.y, position.z, 1.0f );	\n"
               "	float4 vScale = float4( normal.x, normal.y, normal.x, 1.0f );	\n"
               "	oPosition = mul( worldViewProj, vCenter + (preRotatedQuad[normal.z] * vScale) );  \n"

               //Color
               "	oColor = color;   \n"

               //UV Scroll
               "	oUv = uv;	\n"
               "	oUv.x += uScroll; \n"
               "	oUv.y += vScroll; \n"

               //Fog
               "	oFog = oPosition.z; \n"
               "}";
         }
         else     // OpenGL GLSL
         {
            vertexProg =
               "uniform float uScroll; \n"
               "uniform float vScroll; \n"
               "uniform vec4  preRotatedQuad[4]; \n"

               "void main() { \n"
               //Face the camera
               "	vec4 vCenter = vec4( gl_Vertex.x, gl_Vertex.y, gl_Vertex.z, 1.0 ); \n"
               "	vec4 vScale = vec4( gl_Normal.x, gl_Normal.y, gl_Normal.x , 1.0 ); \n"
               "	gl_Position = gl_ModelViewProjectionMatrix * (vCenter + (preRotatedQuad[int(gl_Normal.z)] * vScale) ); \n"

               //Color
               "	gl_FrontColor = gl_Color; \n"

               //UV Scroll
               "	gl_TexCoord[0] = gl_MultiTexCoord0; \n"
               "	gl_TexCoord[0].x += uScroll; \n"
               "	gl_TexCoord[0].y += vScroll; \n"

               //Fog
               "	gl_FogFragCoord = gl_Position.z; \n"
               "}";
         }
		#if OGRE_VERSION_MAJOR <= 1
			#if OGRE_VERSION_MINOR <= 8
				  HighLevelGpuProgramPtr vertexShader = HighLevelGpuProgramManager::getSingleton().getByName("Sprite_vp");
			#else
				HighLevelGpuProgramPtr vertexShader = HighLevelGpuProgramManager::getSingleton().getByName("Sprite_vp").staticCast<HighLevelGpuProgram>();
			#endif
		#endif
		 
         assert(vertexShader.isNull() && "Sprite_vp already exist");

         vertexShader = HighLevelGpuProgramManager::getSingleton().createProgram(
            "Sprite_vp", ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, shaderLanguage, GPT_VERTEX_PROGRAM);
         vertexShader->setSource(vertexProg);

         // Set entry point for vertex program. GLSL can only have one entry point "main".
         if (!s_isGLSL)
         {
            if (shaderLanguage == "hlsl")
            {
               vertexShader->setParameter("target", "vs_1_1");
               vertexShader->setParameter("entry_point", "Sprite_vp");
            }
            else if(shaderLanguage == "cg")
            {
               vertexShader->setParameter("profiles", "vs_1_1 arbvp1");
               vertexShader->setParameter("entry_point", "Sprite_vp");
            }
            else
            {
               assert(false && "Unknown shader language");
            }
         }

         // compile vertex shader
         vertexShader->load();


         //====================================================================
         //Second shader, camera alignment and distance based fading
         String vertexProg2;
         if (!s_isGLSL) // DirectX HLSL or nVidia CG
         {
            vertexProg2 =
               "void SpriteFade_vp(	\n"
               "	float4 position : POSITION,	\n"
               "	float3 normal   : NORMAL,	\n"
               "	float4 color	: COLOR,	\n"
               "	float2 uv       : TEXCOORD0,	\n"
               "	out float4 oPosition : POSITION,	\n"
               "	out float2 oUv       : TEXCOORD0,	\n"
               "	out float4 oColor    : COLOR, \n"
               "	out float oFog       : FOG,	\n"
               "	uniform float4x4 worldViewProj,	\n"

               "	uniform float3 camPos, \n"
               "	uniform float fadeGap, \n"
               "   uniform float invisibleDist, \n"

               "	uniform float    uScroll, \n"
               "	uniform float    vScroll, \n"
               "	uniform float4   preRotatedQuad[4] )	\n"
               "{	\n"
               //Face the camera
               "	float4 vCenter = float4( position.x, position.y, position.z, 1.0f );	\n"
               "	float4 vScale = float4( normal.x, normal.y, normal.x, 1.0f );	\n"
               "	oPosition = mul( worldViewProj, vCenter + (preRotatedQuad[normal.z] * vScale) );  \n"

               "	oColor.rgb = color.rgb;   \n"

               //Fade out in the distance
               "	float dist = distance(camPos.xz, position.xz);	\n"
               "	oColor.a = (invisibleDist - dist) / fadeGap;   \n"

               //UV scroll
               "	oUv = uv;	\n"
               "	oUv.x += uScroll; \n"
               "	oUv.y += vScroll; \n"

               //Fog
               "	oFog = oPosition.z; \n"
               "}";
         }
         else        // OpenGL GLSL
         {
            vertexProg2 =
               "uniform vec3  camPos; \n"
               "uniform float fadeGap; \n"
               "uniform float invisibleDist; \n"
               "uniform float uScroll; \n"
               "uniform float vScroll; \n"
               "uniform vec4  preRotatedQuad[4]; \n"

               "void main() { \n"
               //Face the camera
               "	vec4 vCenter = vec4( gl_Vertex.x, gl_Vertex.y, gl_Vertex.z, 1.0 ); \n"
               "	vec4 vScale = vec4( gl_Normal.x, gl_Normal.y, gl_Normal.x , 1.0 ); \n"
               "	gl_Position = gl_ModelViewProjectionMatrix * (vCenter + (preRotatedQuad[int(gl_Normal.z)] * vScale) ); \n"

               "	gl_FrontColor.xyz = gl_Color.xyz; \n"

               //Fade out in the distance
               "	vec4 position = gl_Vertex; \n"
               "	float dist = distance(camPos.xz, position.xz); \n"
               "	gl_FrontColor.w = (invisibleDist - dist) / fadeGap; \n"

               //UV scroll
               "	gl_TexCoord[0] = gl_MultiTexCoord0; \n"
               "	gl_TexCoord[0].x += uScroll; \n"
               "	gl_TexCoord[0].y += vScroll; \n"

               //Fog
               "	gl_FogFragCoord = gl_Position.z; \n"
               "}";
         }
		#if OGRE_VERSION_MAJOR <= 1
			#if OGRE_VERSION_MINOR <= 8
				  HighLevelGpuProgramPtr vertexShader2 = HighLevelGpuProgramManager::getSingleton().getByName("SpriteFade_vp");
			#else
				HighLevelGpuProgramPtr vertexShader2 = HighLevelGpuProgramManager::getSingleton().getByName("SpriteFade_vp").staticCast<HighLevelGpuProgram>();
			#endif
		#endif
		 
         assert(vertexShader2.isNull() && "SpriteFade_vp already exist");
         vertexShader2 = HighLevelGpuProgramManager::getSingleton().createProgram("SpriteFade_vp",
            ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, shaderLanguage, GPT_VERTEX_PROGRAM);
         vertexShader2->setSource(vertexProg2);

         // Set entry point. GLSL can only have one entry point "main".
         if (!s_isGLSL)
         {

            if (shaderLanguage == "hlsl")
            {
               vertexShader2->setParameter("target", "vs_1_1");
               vertexShader2->setParameter("entry_point", "SpriteFade_vp");
            }
            else if(shaderLanguage == "cg")
            {
               vertexShader2->setParameter("profiles", "vs_1_1 arbvp1");
               vertexShader2->setParameter("entry_point", "SpriteFade_vp");
            }
         }
         // compile it
         vertexShader2->load();
      }
   }
   else
   {
      //Compatible billboard method
      mpFallbackBillboardSet = mgr->createBillboardSet(getUniqueID("SBS"), 100);
      mpSceneNode->attachObject(mpFallbackBillboardSet);
      mfUFactor = mfVFactor = Ogre::Real(0.);
   }


   ++s_nSelfInstances;
}
Exemplo n.º 12
0
HighLevelGpuProgramPtr ParticleMaterialGenerator::createSoftParticleFragmentProgram()
{
	HighLevelGpuProgramManager& mgr = HighLevelGpuProgramManager::getSingleton();
	std::string progName = mDef->getName() + "_ambient_FP";

	HighLevelGpuProgramPtr ret = mgr.getByName(progName);
	if (!ret.isNull())
		mgr.remove(progName);

	ret = mgr.createProgram(progName, ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, 
		"cg", GPT_FRAGMENT_PROGRAM);

	ret->setParameter("profiles", "ps_4_0 ps_3_0 ps_2_0 arbfp1");
	ret->setParameter("entry_point", "main_fp");

	StringUtil::StrStreamType sourceStr;
	
	sourceStr <<
	"	void main_fp(	in float4 iPosition : POSITION,  \n"
	"	in float4 position : COLOR,  \n"
	"	in float4 texCoord : TEXCOORD0,  \n"
	"	in float4 vertexColour : TEXCOORD1,  \n"
	"	in float4 positionScreen : TEXCOORD2,  \n"
	"	in float4 positionWorld : TEXCOORD3,  \n"
	"	uniform sampler2D diffuseMap : TEXUNIT0,  \n";
	
	if(MRTSupported())
	{
		sourceStr <<
			"	uniform sampler2D depthMap : TEXUNIT1, \n"
			"	uniform float useSoftParticles, \n";
	}
	
	sourceStr <<
	"	out float4 oColor : COLOR0,  \n"
	"	uniform float3 fogColor  \n";
	
	if(MRTSupported())
	{
		sourceStr <<
		",	uniform	float4 viewportSize \n"
		",	uniform float4 cameraPositionWorld	//world space \n"
		",	uniform float far  \n"	
		",  uniform half flip \n";
	}
	
	sourceStr <<
	")  \n"
	"{  \n"
	"	float4 diffuseTex = tex2D(diffuseMap, texCoord.xy);  \n"
	"	float4 color1 = diffuseTex;  \n"
	"	color1 *= vertexColour;  \n"
	"	oColor = lerp(color1, float4(fogColor,1), position.w);  \n";

	if(MRTSupported())
	{
		sourceStr <<
		"	//calculate depth at the real position \n"
		"	positionScreen /= positionScreen.w; \n"
		"	float2 depthTexCoord = float2(positionScreen) * float2(0.5f, -0.5f) + float2(0.5f, 0.5f); \n"
		"	float2 uvOffset= (viewportSize.zw)*0.5; \n"
		"	depthTexCoord += uvOffset; \n"
		"	depthTexCoord.y =(1-saturate(flip))+flip*depthTexCoord.y; \n"
        "	float depth = tex2D(depthMap, depthTexCoord).x; \n"
		"	if(useSoftParticles > 0) \n"	
		"	{ \n"	
		"	float distanceToPixel = length(positionWorld.xyz-cameraPositionWorld.xyz); \n"	
		"	float thickness = 0.5;//position_scale[3] * thicknessColour[0]; \n"
		"	float tNear = distanceToPixel - thickness; \n"
		"	float tFar = distanceToPixel + thickness; \n"
		"	depth *= far; \n"
		"	float depthAlpha = saturate(depth - distanceToPixel); \n"
		//these are debug values for the effect ,please don't remove
		//"	depthAlpha*=depthAlpha; \n"
		//"	//modify depth to get a good looking fog effect \n"
		//"	depthAlpha = log(depthAlpha) * 0.7f; \n"
		//"	oColor = float4(depth/20,depth/20,depth/20,1); \n"
		//"	oColor = float4(distanceToPixel,distanceToPixel,distanceToPixel,1); \n"
		//"	oColor = float4(depthAlpha,depthAlpha,depthAlpha,1); \n"
		"	oColor.a *=depthAlpha; \n"
		"	} \n";
	}

	sourceStr << "}  \n";

	
	ret->setSource(sourceStr.str());
	ret->load();
	
	// params
	GpuProgramParametersSharedPtr params = ret->getDefaultParameters();
	params->setNamedAutoConstant("fogColor", GpuProgramParameters::ACT_FOG_COLOUR);
	if(MRTSupported())
	{
		params->setNamedAutoConstant("far", GpuProgramParameters::ACT_FAR_CLIP_DISTANCE);
		params->setNamedAutoConstant("flip", GpuProgramParameters::ACT_RENDER_TARGET_FLIPPING);
		//depth
		params->setNamedAutoConstant("viewportSize", GpuProgramParameters::ACT_VIEWPORT_SIZE);
		//depthAlpha
		params->setNamedAutoConstant("cameraPositionWorld", GpuProgramParameters::ACT_CAMERA_POSITION);
	}
	return ret;
}
Exemplo n.º 13
0
void ImpostorMaterialGenerator::generate()
{
	//!
	// note that we only create the shaders (Sprite_vp, Sprite_fp) here. 
	// the rest (material creation, shader parameters, ...) is done by paged-geom for convenience.
	
	HighLevelGpuProgramManager& mgr = HighLevelGpuProgramManager::getSingleton();
	
	// ---------------- VERTEX -----------------------------------------------
	
	// ensure shader does not exist already.
	HighLevelGpuProgramPtr vshader = mgr.getByName("Sprite_vp");
	if (vshader.isNull())
	{
		vshader = mgr.createProgram("Sprite_vp", ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, 
			"cg", GPT_VERTEX_PROGRAM);

		if(MRTSupported())
		{
			vshader->setParameter("profiles", "vs_4_0 vs_3_0 vp40");
		}
		else
		{
			vshader->setParameter("profiles", "vs_4_0 vs_2_x arbvp1");
		}
		vshader->setParameter("entry_point", "Sprite_vp");
		
		StringUtil::StrStreamType outStream;
		
		outStream <<
		"void Sprite_vp(	\n"
		"	float4 position : POSITION,	\n"
		"	float3 normal   : NORMAL,	\n"
		"	float4 color	: COLOR,	\n"
		"	float2 uv       : TEXCOORD0,	\n"
		"	out float4 oPosition : POSITION,	\n"
		"	out float2 oUv       : TEXCOORD0,	\n"
		"	out float4 oColor    : COLOR, \n"
		"	out float oFog       : TEXCOORD1,	\n"
		"	uniform float4 fogParams, \n"
		"	uniform float4x4 worldViewProj,	\n"
		"	uniform float    uScroll, \n"
		"	uniform float    vScroll, \n"
		"	uniform float4   preRotatedQuad[4] )	\n"
		"{	\n"
		//Face the camera
		"	float4 vCenter = float4( position.x, position.y, position.z, 1.0f );	\n"
		"	float4 vScale = float4( normal.x, normal.y, normal.x, 1.0f );	\n"
		"	oPosition = mul( worldViewProj, vCenter + (preRotatedQuad[normal.z] * vScale) );  \n"

		//Color
		"	oColor = color;   \n"

		//UV Scroll
		"	oUv = uv;	\n"
		"	oUv.x += uScroll; \n"
		"	oUv.y += vScroll; \n"

		//Fog
		"	oFog = saturate(fogParams.x * (oPosition.z - fogParams.y) * fogParams.w); \n"
		"}";
		
		vshader->setSource(outStream.str());
		vshader->load();
		
		vshader->getDefaultParameters()->setNamedAutoConstant("fogParams", GpuProgramParameters::ACT_FOG_PARAMS);
	}
	
	
	// ------------- FRAGMENT -----------------------------------------------
	
	// ensure shader does not exist already.
	HighLevelGpuProgramPtr fshader = mgr.getByName("Sprite_fp");
	if (fshader.isNull())
	{
		fshader = mgr.createProgram("Sprite_fp", ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, 
			"cg", GPT_FRAGMENT_PROGRAM);
			
		if(MRTSupported())
		{
			fshader->setParameter("profiles", "ps_4_0 ps_3_0 fp40");
		}
		else
		{
			fshader->setParameter("profiles", "ps_4_0 ps_2_x arbfp1");	
		}
		fshader->setParameter("entry_point", "Sprite_fp");
		
		// simple pixel shader that only reads texture and fog
		StringUtil::StrStreamType outStream;
		outStream <<
		"void Sprite_fp( 	\n"
		"	uniform sampler2D texture, \n"
		"	float4 iPosition : POSITION,	\n"
		"	float2 texCoord : TEXCOORD0, \n"
		"	float4 iColor : COLOR,	\n"
		"	float fog : TEXCOORD1, \n"
		"	uniform float4 fogColor, \n"
		"	out float4 oColor : COLOR \n"
		") \n"
		"{ \n"
		"	float4 texColor = tex2D(texture, texCoord); \n"
		"	oColor = float4(lerp(texColor.xyz, fogColor.xyz, fog), texColor.a); \n"
		"	clip( oColor.a > 0.0f ? 1:-1); \n"
		"} \n";
		
		fshader->setSource(outStream.str());
		fshader->load();
		
		fshader->getDefaultParameters()->setNamedAutoConstant("fogColor", GpuProgramParameters::ACT_FOG_COLOUR);
	}
}
Exemplo n.º 14
0
void BatchPage::_updateShaders()
{
	if (!shadersSupported)
		return;

	uint32 i = 0;
	BatchedGeometry::SubBatchIterator it = batch->getSubBatchIterator();
	while (it.hasMoreElements()){
		BatchedGeometry::SubBatch *subBatch = it.getNext();
		MaterialPtr mat = unfadedMaterials[i++];

		//Check if lighting should be enabled
		bool lightingEnabled = false;
		for (unsigned short t = 0; t < mat->getNumTechniques(); ++t){
			Technique *tech = mat->getTechnique(t);
			for (unsigned short p = 0; p < tech->getNumPasses(); ++p){
				Pass *pass = tech->getPass(p);
				if (pass->getLightingEnabled()) {
					lightingEnabled = true;
					break;
				}
			}
			if (lightingEnabled)
				break;
		}

		//Compile the CG shader script based on various material / fade options
		StringUtil::StrStreamType tmpName;
		tmpName << "BatchPage_";
		if (fadeEnabled)
			tmpName << "fade_";
		if (lightingEnabled)
			tmpName << "lit_";
		if (subBatch->vertexData->vertexDeclaration->findElementBySemantic(VES_DIFFUSE) != NULL)
			tmpName << "clr_";

		for (unsigned short i = 0; i < subBatch->vertexData->vertexDeclaration->getElementCount(); ++i)
		{
			const VertexElement *el = subBatch->vertexData->vertexDeclaration->getElement(i);
			if (el->getSemantic() == VES_TEXTURE_COORDINATES) {
				String uvType = "";
				switch (el->getType()) {
						case VET_FLOAT1: uvType = "1"; break;
						case VET_FLOAT2: uvType = "2"; break;
						case VET_FLOAT3: uvType = "3"; break;
						case VET_FLOAT4: uvType = "4"; break;
				}
				tmpName << uvType << '_';
			}
		}

		tmpName << "vp";

		const String vertexProgName = tmpName.str();

		String shaderLanguage = ShaderHelper::getShaderLanguage();

		//If the shader hasn't been created yet, create it
		if (HighLevelGpuProgramManager::getSingleton().getByName(vertexProgName).isNull())
		{
			Pass *pass = mat->getTechnique(0)->getPass(0);
			String vertexProgSource;

			if(!shaderLanguage.compare("hlsl") || !shaderLanguage.compare("cg"))
			{

				vertexProgSource =
					"void main( \n"
					"	float4 iPosition : POSITION, \n"
					"	float3 normal    : NORMAL,	\n"
					"	out float4 oPosition : POSITION, \n";

				if (subBatch->vertexData->vertexDeclaration->findElementBySemantic(VES_DIFFUSE) != NULL) vertexProgSource +=
					"	float4 iColor    : COLOR, \n";

				unsigned texNum = 0;
				for (unsigned short i = 0; i < subBatch->vertexData->vertexDeclaration->getElementCount(); ++i) {
					const VertexElement *el = subBatch->vertexData->vertexDeclaration->getElement(i);
					if (el->getSemantic() == VES_TEXTURE_COORDINATES) {
						String uvType = "";
						switch (el->getType()) {
							case VET_FLOAT1: uvType = "float"; break;
							case VET_FLOAT2: uvType = "float2"; break;
							case VET_FLOAT3: uvType = "float3"; break;
							case VET_FLOAT4: uvType = "float4"; break;
						}

						vertexProgSource +=
						"	" + uvType + " iUV" + StringConverter::toString(texNum) + "			: TEXCOORD" + StringConverter::toString(texNum) + ",	\n"
						"	out " + uvType + " oUV" + StringConverter::toString(texNum) + "		: TEXCOORD" + StringConverter::toString(texNum) + ",	\n";

						++texNum;
					}
				}

				vertexProgSource +=
					"	out float oFog : FOG,	\n"
				"	out float4 oColor : COLOR, \n"
			    "	uniform float4 iFogParams,	\n";

				if (lightingEnabled) vertexProgSource +=
					"	uniform float4 objSpaceLight,	\n"
					"	uniform float4 lightDiffuse,	\n"
					"	uniform float4 lightAmbient,	\n";

				if (fadeEnabled) vertexProgSource +=
					"	uniform float3 camPos, \n";

				vertexProgSource +=
					"	uniform float4x4 worldViewProj,	\n"
					"	uniform float fadeGap, \n"
					"   uniform float invisibleDist )\n"
					"{	\n";

				if (lightingEnabled) {
					//Perform lighting calculations (no specular)
					vertexProgSource +=
					"	float3 light = normalize(objSpaceLight.xyz - (iPosition.xyz * objSpaceLight.w)); \n"
					"	float diffuseFactor = max(dot(normal, light), 0); \n";
					if (subBatch->vertexData->vertexDeclaration->findElementBySemantic(VES_DIFFUSE) != NULL)
						vertexProgSource += "oColor = (lightAmbient + diffuseFactor * lightDiffuse) * iColor; \n";
					else
						vertexProgSource += "oColor = (lightAmbient + diffuseFactor * lightDiffuse); \n";
				} else {
					if (subBatch->vertexData->vertexDeclaration->findElementBySemantic(VES_DIFFUSE) != NULL)
						vertexProgSource += "oColor = iColor; \n";
					else
						vertexProgSource += "oColor = float4(1, 1, 1, 1); \n";
				}

				if (fadeEnabled) vertexProgSource +=
					//Fade out in the distance
					"	float dist = distance(camPos.xz, iPosition.xz);	\n"
					"	oColor.a *= (invisibleDist - dist) / fadeGap;   \n";

				texNum = 0;
				for (unsigned short i = 0; i < subBatch->vertexData->vertexDeclaration->getElementCount(); ++i) {
					const VertexElement *el = subBatch->vertexData->vertexDeclaration->getElement(i);
					if (el->getSemantic() == VES_TEXTURE_COORDINATES) {
						vertexProgSource +=
						"	oUV" + StringConverter::toString(texNum) + " = iUV" + StringConverter::toString(texNum) + ";	\n";
						++texNum;
					}
				}
				vertexProgSource +=
					"	oPosition = mul(worldViewProj, iPosition);  \n";
				if (sceneMgr->getFogMode() == Ogre::FOG_EXP2) {
					vertexProgSource +=
						"	oFog = 1 - clamp (pow (2.71828, -oPosition.z * iFogParams.x), 0, 1); \n";
				} else {
					vertexProgSource +=
						"	oFog = oPosition.z; \n";
				}
				vertexProgSource += "}";
			}

			if(!shaderLanguage.compare("glsl"))
			{
				vertexProgSource =
					"uniform float fadeGap;        \n"
					"uniform float invisibleDist;   \n";

				if (lightingEnabled) vertexProgSource +=
					"uniform vec4 objSpaceLight;   \n"
					"uniform vec4 lightDiffuse;	   \n"
					"uniform vec4 lightAmbient;	   \n";

				if (fadeEnabled) vertexProgSource +=
					"uniform vec3 camPos;          \n";

				vertexProgSource +=
					"void main() \n"
					"{ \n";

				if (lightingEnabled)
				{
					//Perform lighting calculations (no specular)
					vertexProgSource +=
					"   vec3 light = normalize(objSpaceLight.xyz - (gl_Vertex.xyz * objSpaceLight.w)); \n"
					"   float diffuseFactor = max(dot(gl_Normal, light), 0.0); \n";
					if (subBatch->vertexData->vertexDeclaration->findElementBySemantic(VES_DIFFUSE) != NULL)
					{
						vertexProgSource += "   gl_FrontColor = (lightAmbient + diffuseFactor * lightDiffuse) * gl_Color; \n";
					}
					else
					{
						vertexProgSource += "   gl_FrontColor = (lightAmbient + diffuseFactor * lightDiffuse); \n";
					}
				}
				else
				{
					if (subBatch->vertexData->vertexDeclaration->findElementBySemantic(VES_DIFFUSE) != NULL)
					{
						vertexProgSource += "   gl_FrontColor = gl_Color; \n";
					}
					else
					{
						vertexProgSource += "   gl_FrontColor = vec4(1.0, 1.0, 1.0, 1.0); \n";
					}
				}

				if (fadeEnabled)
				{
					vertexProgSource +=
					//Fade out in the distance
					"   float dist = distance(camPos.xz, gl_Vertex.xz);	\n"
					"   gl_FrontColor.a *= (invisibleDist - dist) / fadeGap;   \n";
				}

				unsigned texNum = 0;
				for (unsigned short i = 0; i < subBatch->vertexData->vertexDeclaration->getElementCount(); ++i)
				{
					const VertexElement *el = subBatch->vertexData->vertexDeclaration->getElement(i);
					if (el->getSemantic() == VES_TEXTURE_COORDINATES)
					{
						vertexProgSource +=
						"   gl_TexCoord[" + StringConverter::toString(texNum) + "] = gl_MultiTexCoord" + StringConverter::toString(texNum) + ";	\n";
						++texNum;
					}
				}

				vertexProgSource +=
					"   gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;  \n";
				if (sceneMgr->getFogMode() == Ogre::FOG_EXP2) {
					vertexProgSource +=
						"	gl_FogFragCoord = clamp(exp(- gl_Fog.density * gl_Fog.density * gl_Position.z * gl_Position.z), 0.0, 1.0); \n";
				} else {
					vertexProgSource +=
						"	gl_FogFragCoord = gl_Position.z; \n";
				}

				vertexProgSource +=	"}";
			}


			HighLevelGpuProgramPtr vertexShader = HighLevelGpuProgramManager::getSingleton().createProgram(
				vertexProgName,
				ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME,
				shaderLanguage, GPT_VERTEX_PROGRAM);

			vertexShader->setSource(vertexProgSource);

			if (shaderLanguage == "hlsl")
			{
				vertexShader->setParameter("target", "vs_1_1");
				vertexShader->setParameter("entry_point", "main");
			}
			else if(shaderLanguage == "cg")
			{
				vertexShader->setParameter("profiles", "vs_1_1 arbvp1");
				vertexShader->setParameter("entry_point", "main");
			}
			// GLSL can only have one entry point "main".

			vertexShader->load();
			if (vertexShader->hasCompileError()) {
				OGRE_EXCEPT(Exception::ERR_INTERNAL_ERROR, "Error loading the batching vertex shader.", "BatchPage::_updateShaders()");
			}
		}

		std::string fragmentProgramName("BatchFragStandard");
		String fragmentProgSource;
		//We also need a fragment program to go with our vertex program. Especially on ATI cards on Linux where we can't mix shaders and the fixed function pipeline.
		HighLevelGpuProgramPtr fragShader = static_cast<HighLevelGpuProgramPtr>(HighLevelGpuProgramManager::getSingleton().getByName(fragmentProgramName));
		if (fragShader.isNull()){
			Pass *pass = mat->getTechnique(0)->getPass(0);

			if (shaderLanguage == "glsl") {
				fragmentProgSource = "uniform sampler2D diffuseMap;\n"
					"void main()	{"
					"	gl_FragColor = texture2D(diffuseMap, gl_TexCoord[0].st);"
					"	gl_FragColor.rgb = mix(gl_Fog.color, (gl_LightModel.ambient * gl_FragColor + gl_FragColor), gl_FogFragCoord).rgb;"
					"}";

			} else {
				fragmentProgSource = "void main \n"
					"( \n"
					"    float2				iTexcoord		: TEXCOORD0, \n"
					"	 float				iFog 			: FOG, \n"
					"	 out float4         oColour			: COLOR, \n"
					"    uniform sampler2D  diffuseTexture	: TEXUNIT0, \n"
					"    uniform float3		iFogColour \n"
					") \n"
					"{ \n"
					"	oColour = tex2D(diffuseTexture, iTexcoord.xy); \n"
					"   oColour.xyz = lerp(oColour.xyz, iFogColour, iFog);\n"
					"}";
			}

			fragShader = HighLevelGpuProgramManager::getSingleton().createProgram(
				fragmentProgramName,
				ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME,
				shaderLanguage, GPT_FRAGMENT_PROGRAM);

			fragShader->setSource(fragmentProgSource);

			if (shaderLanguage == "hlsl") {
				fragShader->setParameter("entry_point", "main");
				fragShader->setParameter("target", "ps_2_0");
			} else if (shaderLanguage == "cg") {
				fragShader->setParameter("profiles", "ps_2_0 arbfp1");
				fragShader->setParameter("entry_point", "main");
			}

			fragShader->load();
			if (fragShader->hasCompileError()) {
				OGRE_EXCEPT(Exception::ERR_INTERNAL_ERROR, "Error loading the batching fragment shader.", "BatchPage::_updateShaders()");
			}
		}
		//Now that the shader is ready to be applied, apply it
		StringUtil::StrStreamType materialSignature;
		materialSignature << "BatchMat|";
		materialSignature << mat->getName() << "|";
		if (fadeEnabled){
			materialSignature << visibleDist << "|";
			materialSignature << invisibleDist << "|";
		}

		//Search for the desired material
		MaterialPtr generatedMaterial = MaterialManager::getSingleton().getByName(materialSignature.str());
		if (generatedMaterial.isNull()){
			//Clone the material
			generatedMaterial = mat->clone(materialSignature.str());

			//And apply the fade shader
			Ogre::Material::TechniqueIterator I = generatedMaterial->getSupportedTechniqueIterator();
			while (I.hasMoreElements()) {
				Technique *tech = I.getNext();
				for (unsigned short p = 0; p < tech->getNumPasses(); ++p){
					Pass *pass = tech->getPass(p);

					//Setup vertex program
					if (pass->getVertexProgramName() == "")
						pass->setVertexProgram(vertexProgName);

					if (pass->getFragmentProgramName() == "" && fragShader->isSupported())
						pass->setFragmentProgram(fragmentProgramName);

					try{
						GpuProgramParametersSharedPtr params = pass->getVertexProgramParameters();
						params->setIgnoreMissingParams(true);

						if (lightingEnabled) {
							params->setNamedAutoConstant("objSpaceLight", GpuProgramParameters::ACT_LIGHT_POSITION_OBJECT_SPACE);
							params->setNamedAutoConstant("lightDiffuse", GpuProgramParameters::ACT_DERIVED_LIGHT_DIFFUSE_COLOUR);
							params->setNamedAutoConstant("lightAmbient", GpuProgramParameters::ACT_DERIVED_AMBIENT_LIGHT_COLOUR);
							//params->setNamedAutoConstant("matAmbient", GpuProgramParameters::ACT_SURFACE_AMBIENT_COLOUR);
						}

						if (shaderLanguage.compare("glsl") == 0) {
							//glsl can use the built in gl_ModelViewProjectionMatrix
							params->setNamedAutoConstant("worldViewProj", GpuProgramParameters::ACT_WORLDVIEWPROJ_MATRIX);
						} else {
							params->setNamedAutoConstant("iFogParams", GpuProgramParameters::ACT_FOG_PARAMS);
						}

						if (fadeEnabled)
						{
							params->setNamedAutoConstant("camPos", GpuProgramParameters::ACT_CAMERA_POSITION_OBJECT_SPACE);

							//Set fade ranges
							params->setNamedAutoConstant("invisibleDist", GpuProgramParameters::ACT_CUSTOM);
							params->setNamedConstant("invisibleDist", invisibleDist);

							params->setNamedAutoConstant("fadeGap", GpuProgramParameters::ACT_CUSTOM);
							params->setNamedConstant("fadeGap", invisibleDist - visibleDist);

							if (pass->getAlphaRejectFunction() == CMPF_ALWAYS_PASS)
								pass->setSceneBlending(SBT_TRANSPARENT_ALPHA);
						}

						if (pass->hasFragmentProgram()) {
							params = pass->getFragmentProgramParameters();
							params->setIgnoreMissingParams(true);
							params->setNamedAutoConstant("iFogColour", GpuProgramParameters::ACT_FOG_COLOUR);
						}
					}
					catch (...) {
						OGRE_EXCEPT(Exception::ERR_INTERNAL_ERROR, "Error configuring batched geometry transitions. If you're using materials with custom vertex shaders, they will need to implement fade transitions to be compatible with BatchPage.", "BatchPage::_updateShaders()");
					}
				}
			}

		}

		//Apply the material
		subBatch->setMaterial(generatedMaterial);
	}

}