//---------------------------------------------------------------------
	void TerrainMaterialGeneratorC::SM2Profile::ShaderHelper::defaultFpParams(
		const SM2Profile* prof, const Terrain* terrain, TechniqueType tt, const HighLevelGpuProgramPtr& prog)
	{
		GpuProgramParametersSharedPtr params = prog->getDefaultParameters();
		params->setIgnoreMissingParams(true);
		params->setNamedAutoConstant("fogColour", GpuProgramParameters::ACT_FOG_COLOUR);
		params->setNamedAutoConstant("cFarDistance", Ogre::GpuProgramParameters::ACT_FAR_CLIP_DISTANCE);
		params->setNamedAutoConstant("viewMatrix", GpuProgramParameters::ACT_WORLDVIEW_MATRIX); // tout sauf Z : VIEW_MATRIX
	}
Beispiel #2
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;
}
Beispiel #3
0
void WaterMaterialGenerator::vertexProgramParams(Ogre::HighLevelGpuProgramPtr program)
{
	GpuProgramParametersSharedPtr params = program->getDefaultParameters();
	
	params->setIgnoreMissingParams(true);

	params->setNamedAutoConstant("wMat", GpuProgramParameters::ACT_WORLD_MATRIX);
	params->setNamedAutoConstant("wvpMat", GpuProgramParameters::ACT_WORLDVIEWPROJ_MATRIX);
	params->setNamedAutoConstant("fogParams", GpuProgramParameters::ACT_FOG_PARAMS);
	
	individualVertexProgramParams(params);
}
    void setUpBaseParameters(const GpuProgramParametersSharedPtr& params)
    {
        assert(params.isNull()==false);

        struct AutoParamPair { String name; GpuProgramParameters::AutoConstantType type; };

        //A list of auto params that might be present in the shaders generated
        static const AutoParamPair AUTO_PARAMS[] = {
            { "vpWidth",            GpuProgramParameters::ACT_VIEWPORT_WIDTH },
            { "vpHeight",           GpuProgramParameters::ACT_VIEWPORT_HEIGHT },
            { "worldView",          GpuProgramParameters::ACT_WORLDVIEW_MATRIX },
            { "invProj",            GpuProgramParameters::ACT_INVERSE_PROJECTION_MATRIX },
            { "invView",            GpuProgramParameters::ACT_INVERSE_VIEW_MATRIX },
            { "flip",               GpuProgramParameters::ACT_RENDER_TARGET_FLIPPING },
            { "lightDiffuseColor",  GpuProgramParameters::ACT_LIGHT_DIFFUSE_COLOUR },
            { "lightSpecularColor", GpuProgramParameters::ACT_LIGHT_SPECULAR_COLOUR },
            { "lightFalloff",       GpuProgramParameters::ACT_LIGHT_ATTENUATION },
            { "lightPos",           GpuProgramParameters::ACT_LIGHT_POSITION_VIEW_SPACE },
            { "lightDir",           GpuProgramParameters::ACT_LIGHT_DIRECTION_VIEW_SPACE },
            { "spotParams",         GpuProgramParameters::ACT_SPOTLIGHT_PARAMS },
            { "farClipDistance",    GpuProgramParameters::ACT_FAR_CLIP_DISTANCE },
            { "shadowViewProjMat",  GpuProgramParameters::ACT_TEXTURE_VIEWPROJ_MATRIX }
        };
        int numParams = sizeof(AUTO_PARAMS) / sizeof(AutoParamPair);
        
        for (int i=0; i<numParams; i++)
        {
            if (params->_findNamedConstantDefinition(AUTO_PARAMS[i].name))
            {
                params->setNamedAutoConstant(AUTO_PARAMS[i].name, AUTO_PARAMS[i].type);
            }
        }
    }
//-----------------------------------------------------------------------------
void ProgramProcessor::bindAutoParameters(Program* pCpuProgram, GpuProgramPtr pGpuProgram)
{
	GpuProgramParametersSharedPtr pGpuParams = pGpuProgram->getDefaultParameters();
	const UniformParameterList& progParams = pCpuProgram->getParameters();
	UniformParameterConstIterator itParams;

	for (itParams=progParams.begin(); itParams != progParams.end(); ++itParams)
	{
		const UniformParameterPtr pCurParam = *itParams;
		const GpuConstantDefinition* gpuConstDef = pGpuParams->_findNamedConstantDefinition(pCurParam->getName());
	
		if (gpuConstDef != NULL)
		{
			// Handle auto parameters.
			if (pCurParam->isAutoConstantParameter())
			{
				if (pCurParam->isAutoConstantRealParameter())
				{					
					pGpuParams->setNamedAutoConstantReal(pCurParam->getName(), 
						pCurParam->getAutoConstantType(), 
						pCurParam->getAutoConstantRealData());
										
				}
				else if (pCurParam->isAutoConstantIntParameter())
				{					
					pGpuParams->setNamedAutoConstant(pCurParam->getName(), 
						pCurParam->getAutoConstantType(), 
						pCurParam->getAutoConstantIntData());									
				}						
			}

			// Case this is not auto constant - we have to update its variability ourself.
			else
			{							
				gpuConstDef->variability |= pCurParam->getVariability();

				// Update variability in the float map.
				if (gpuConstDef->isSampler() == false)
				{
					GpuLogicalBufferStructPtr floatLogical = pGpuParams->getFloatLogicalBufferStruct();
					if (floatLogical.get())
					{
						for (GpuLogicalIndexUseMap::const_iterator i = floatLogical->map.begin(); i != floatLogical->map.end(); ++i)
						{
							if (i->second.physicalIndex == gpuConstDef->physicalIndex)
							{
								i->second.variability |= gpuConstDef->variability;
								break;
							}
						}
					}
				}											
			}		
		}			
	}
}
Beispiel #6
0
void MaterialGenerator::vertexProgramParams(HighLevelGpuProgramPtr program)
{
	GpuProgramParametersSharedPtr params = program->getDefaultParameters();
	
	//#ifndef _DEBUG
	params->setIgnoreMissingParams(true);
	//#endif
		
	if (vpNeedWMat())
		params->setNamedAutoConstant("wMat", GpuProgramParameters::ACT_WORLD_MATRIX);
	params->setNamedAutoConstant("wvpMat", GpuProgramParameters::ACT_WORLDVIEWPROJ_MATRIX);
	if (vpNeedWvMat())
		params->setNamedAutoConstant("wvMat", GpuProgramParameters::ACT_WORLDVIEW_MATRIX);
	if (fpNeedEyeVector() || mShader->wind == 1)
		params->setNamedAutoConstant("eyePosition", GpuProgramParameters::ACT_CAMERA_POSITION);
	
	params->setNamedAutoConstant("fogParams", GpuProgramParameters::ACT_FOG_PARAMS);
			
	if (mShader->wind == 2)
		params->setNamedConstant("enableWind", Real(1.0));
	
	if(MRTSupported())
	{
		params->setNamedAutoConstant("far", GpuProgramParameters::ACT_FAR_CLIP_DISTANCE);
	}	
	individualVertexProgramParams(params);
}
Beispiel #7
0
void WaterMaterialGenerator::fragmentProgramParams(Ogre::HighLevelGpuProgramPtr program)
{
	GpuProgramParametersSharedPtr params = program->getDefaultParameters();
	
	params->setIgnoreMissingParams(true);

	params->setNamedAutoConstant("iTWMat", GpuProgramParameters::ACT_INVERSE_TRANSPOSE_WORLD_MATRIX);
	params->setNamedAutoConstant("fogColor", GpuProgramParameters::ACT_FOG_COLOUR);
	params->setNamedAutoConstant("lightSpec0", GpuProgramParameters::ACT_LIGHT_SPECULAR_COLOUR, 0);
	params->setNamedAutoConstant("lightPos0", GpuProgramParameters::ACT_LIGHT_POSITION, 0);
	params->setNamedAutoConstant("camPos", GpuProgramParameters::ACT_CAMERA_POSITION);
	params->setNamedAutoConstant("time", GpuProgramParameters::ACT_TIME);
	params->setNamedAutoConstant("ambient", GpuProgramParameters::ACT_AMBIENT_LIGHT_COLOUR);
	params->setNamedAutoConstant("lightDiff", GpuProgramParameters::ACT_LIGHT_DIFFUSE_COLOUR, 0);
	params->setNamedAutoConstant("inverseProjection", GpuProgramParameters::ACT_RENDER_TARGET_FLIPPING);
	params->setNamedConstantFromTime("time", 1);
	individualFragmentProgramParams(params);
}
	//---------------------------------------------------------------------
	void TerrainMaterialGeneratorC::SM2Profile::ShaderHelper::defaultVpParams(
		const SM2Profile* prof, const Terrain* terrain, TechniqueType tt, const HighLevelGpuProgramPtr& prog)
	{
		GpuProgramParametersSharedPtr params = prog->getDefaultParameters();
		params->setIgnoreMissingParams(true);
		params->setNamedAutoConstant("worldMatrix", GpuProgramParameters::ACT_WORLD_MATRIX);
		params->setNamedAutoConstant("viewMatrix", GpuProgramParameters::ACT_WORLDVIEW_MATRIX);
		params->setNamedAutoConstant("viewProjMatrix", GpuProgramParameters::ACT_VIEWPROJ_MATRIX);
		params->setNamedAutoConstant("lodMorph", GpuProgramParameters::ACT_CUSTOM, 
			Terrain::LOD_MORPH_CUSTOM_PARAM);
		params->setNamedAutoConstant("fogParams", GpuProgramParameters::ACT_FOG_PARAMS);
 
		if (terrain->_getUseVertexCompression() && tt != RENDER_COMPOSITE_MAP)
		{
			Matrix4 posIndexToObjectSpace;
			terrain->getPointTransform(&posIndexToObjectSpace);
			params->setNamedConstant("posIndexToObjectSpace", posIndexToObjectSpace);
		}
 
 
 
	}
Beispiel #9
0
void MaterialGenerator::individualVertexProgramParams(GpuProgramParametersSharedPtr params)
{
	//#ifndef _DEBUG
	params->setIgnoreMissingParams(true);
	//#endif
	
	if (needShadows())
	for (int i=0; i<mParent->getNumShadowTex(); ++i)
	{
		params->setNamedAutoConstant("texWorldViewProjMatrix"+toStr(i), GpuProgramParameters::ACT_TEXTURE_WORLDVIEWPROJ_MATRIX, i);
	}
	
	params->setNamedConstant("enableFog", mDef->mProps->fog ? Real(1.0) : Real(0.0));
}
	//---------------------------------------------------------------------
	void TerrainMaterialGeneratorA::SM2Profile::ShaderHelper::defaultVpParams(
		const SM2Profile* prof, const Terrain* terrain, TechniqueType tt, const HighLevelGpuProgramPtr& prog)
	{
		GpuProgramParametersSharedPtr params = prog->getDefaultParameters();
		params->setIgnoreMissingParams(true);
		params->setNamedAutoConstant("worldMatrix", GpuProgramParameters::ACT_WORLD_MATRIX);
		params->setNamedAutoConstant("viewProjMatrix", GpuProgramParameters::ACT_VIEWPROJ_MATRIX);
		params->setNamedAutoConstant("lodMorph", GpuProgramParameters::ACT_CUSTOM, 
			Terrain::LOD_MORPH_CUSTOM_PARAM);
		params->setNamedAutoConstant("fogParams", GpuProgramParameters::ACT_FOG_PARAMS);

		if (prof->isShadowingEnabled(tt, terrain))
		{
			uint numTextures = 1;
			if (prof->getReceiveDynamicShadowsPSSM())
			{
				numTextures = (uint)prof->getReceiveDynamicShadowsPSSM()->getSplitCount();
			}
			for (uint i = 0; i < numTextures; ++i)
			{
				params->setNamedAutoConstant("texViewProjMatrix" + StringConverter::toString(i), 
					GpuProgramParameters::ACT_TEXTURE_VIEWPROJ_MATRIX, i);
				if (prof->getReceiveDynamicShadowsDepth())
				{
					params->setNamedAutoConstant("depthRange" + StringConverter::toString(i), 
						GpuProgramParameters::ACT_SHADOW_SCENE_DEPTH_RANGE, i);
				}
			}
		}

		if (terrain->_getUseVertexCompression() && tt != RENDER_COMPOSITE_MAP)
		{
			Matrix4 posIndexToObjectSpace;
			terrain->getPointTransform(&posIndexToObjectSpace);
			params->setNamedConstant("posIndexToObjectSpace", posIndexToObjectSpace);
		}

		
		
	}
	//---------------------------------------------------------------------
	void TerrainMaterialGeneratorA::SM2Profile::ShaderHelper::defaultFpParams(
		const SM2Profile* prof, const Terrain* terrain, TechniqueType tt, const HighLevelGpuProgramPtr& prog)
	{
		GpuProgramParametersSharedPtr params = prog->getDefaultParameters();
		params->setIgnoreMissingParams(true);

		params->setNamedAutoConstant("ambient", GpuProgramParameters::ACT_AMBIENT_LIGHT_COLOUR);
		params->setNamedAutoConstant("lightPosObjSpace", GpuProgramParameters::ACT_LIGHT_POSITION_OBJECT_SPACE, 0);
		params->setNamedAutoConstant("lightDiffuseColour", GpuProgramParameters::ACT_LIGHT_DIFFUSE_COLOUR, 0);
		params->setNamedAutoConstant("lightSpecularColour", GpuProgramParameters::ACT_LIGHT_SPECULAR_COLOUR, 0);
		params->setNamedAutoConstant("eyePosObjSpace", GpuProgramParameters::ACT_CAMERA_POSITION_OBJECT_SPACE);
		params->setNamedAutoConstant("fogColour", GpuProgramParameters::ACT_FOG_COLOUR);

		if (prof->isShadowingEnabled(tt, terrain))
		{
			uint numTextures = 1;
			if (prof->getReceiveDynamicShadowsPSSM())
			{
				PSSMShadowCameraSetup* pssm = prof->getReceiveDynamicShadowsPSSM();
				numTextures = (uint)pssm->getSplitCount();
				Vector4 splitPoints;
				const PSSMShadowCameraSetup::SplitPointList& splitPointList = pssm->getSplitPoints();
				// Populate from split point 1, not 0, since split 0 isn't useful (usually 0)
				for (uint i = 1; i < numTextures; ++i)
				{
					splitPoints[i-1] = splitPointList[i];
				}
				params->setNamedConstant("pssmSplitPoints", splitPoints);
			}

			if (prof->getReceiveDynamicShadowsDepth())
			{
				size_t samplerOffset = (tt == HIGH_LOD) ? mShadowSamplerStartHi : mShadowSamplerStartLo;
				for (uint i = 0; i < numTextures; ++i)
				{
					params->setNamedAutoConstant("inverseShadowmapSize" + StringConverter::toString(i), 
						GpuProgramParameters::ACT_INVERSE_TEXTURE_SIZE, i + samplerOffset);
				}
			}
		}

        // Explicitly bind samplers for GLSL
        if ((prof->_getShaderLanguage() == "glsl") || (prof->_getShaderLanguage() == "glsles"))
        {
            int numSamplers = 0;
            if (tt == LOW_LOD)
            {
                params->setNamedConstant("compositeMap", (int)numSamplers++);
            }
            else
            {
                params->setNamedConstant("globalNormal", (int)numSamplers++);

                if (terrain->getGlobalColourMapEnabled() && prof->isGlobalColourMapEnabled())
                {
                    params->setNamedConstant("globalColourMap", (int)numSamplers++);
                }
                if (prof->isLightmapEnabled())
                {
                    params->setNamedConstant("lightMap", (int)numSamplers++);
                }

                uint maxLayers = prof->getMaxLayers(terrain);
                uint numBlendTextures = std::min(terrain->getBlendTextureCount(maxLayers), terrain->getBlendTextureCount());
                uint numLayers = std::min(maxLayers, static_cast<uint>(terrain->getLayerCount()));
                // Blend textures - sampler definitions
                for (uint i = 0; i < numBlendTextures; ++i)
                {
                    params->setNamedConstant("blendTex" + StringConverter::toString(i), (int)numSamplers++);
                }

                // Layer textures - sampler definitions & UV multipliers
                for (uint i = 0; i < numLayers; ++i)
                {
                    params->setNamedConstant("difftex" + StringConverter::toString(i), (int)numSamplers++);
                    params->setNamedConstant("normtex" + StringConverter::toString(i), (int)numSamplers++);
                }

                uint numShadowTextures = 1;
                if (prof->getReceiveDynamicShadowsPSSM())
                    numShadowTextures = (uint)prof->getReceiveDynamicShadowsPSSM()->getSplitCount();

                for (uint i = 0; i < numShadowTextures; ++i)
                {
                    if (prof->isShadowingEnabled(tt, terrain))
                        params->setNamedConstant("shadowMap" + StringConverter::toString(i), (int)numSamplers++);
                }
            }
        }
	}
    //-----------------------------------------------------------------------
    void PagingLandScapeTexture_Splatting5::_loadMaterial()
    {
	    if (mMaterial.isNull() )
	    {
            // Create a new texture using the base image
            const String commonName = StringConverter::toString(mDataZ) + String(".") + StringConverter::toString(mDataX);
            //const String prefilename = PagingLandScapeOptions::getSingleton().landscape_filename;
            //const String postfilename = commonName + "." + PagingLandScapeOptions::getSingleton().TextureExtension;


            String Materialname;
            if (PagingLandScapeOptions::getSingleton().VertexCompression)
            {
                mMaterial = (MaterialManager::getSingleton().getByName("SplattingMaterial5Decompress"));


                GpuProgramParametersSharedPtr params = mMaterial->getTechnique(0)->getPass(0)->getVertexProgramParameters();
	            params->setNamedConstant("splatSettings", Vector4(PagingLandScapeOptions::getSingleton().matHeight[1], 
                                                                    PagingLandScapeOptions::getSingleton().matHeight[2], 
                                                                    PagingLandScapeOptions::getSingleton().maxValue, 
                                                                    0.0));
    //            params->setNamedConstant("compressionSettings", Vector4(PagingLandScapeOptions::getSingleton().scale.x * PagingLandScapeOptions::getSingleton().PageSize, 
    //                                                                PagingLandScapeOptions::getSingleton().scale.y / 65535, 
    //                                                                PagingLandScapeOptions::getSingleton().scale.z * PagingLandScapeOptions::getSingleton().PageSize, 
    //                                                                0.0));
                // Check to see if custom param is already there
                GpuProgramParameters::AutoConstantIterator aci = params->getAutoConstantIterator();
                bool found = false;
                while (aci.hasMoreElements())
                {
                    const GpuProgramParameters::AutoConstantEntry& ace = aci.getNext();
                    if (ace.paramType == GpuProgramParameters::ACT_CUSTOM && 
                        ace.data == MORPH_CUSTOM_PARAM_ID)
                    {
                        found = true;
                    }
                }
                if (!found)
                {                        
                    params->setNamedAutoConstant("compressionSettings", 
                        GpuProgramParameters::ACT_CUSTOM, MORPH_CUSTOM_PARAM_ID);                       
                }
            }
            else
            {
                mMaterial = MaterialManager::getSingleton().getByName("SplattingMaterial5");


                GpuProgramParametersSharedPtr params = mMaterial->getTechnique(0)->getPass(0)->getVertexProgramParameters();
	            params->setNamedConstant("splatSettings", Vector4(PagingLandScapeOptions::getSingleton().matHeight[1], 
                                                                    PagingLandScapeOptions::getSingleton().matHeight[2], 
                                                                    PagingLandScapeOptions::getSingleton().maxValue, 
                                                                    0.0));
                    
            }

            //  should really be done only once...
    //        GpuProgramParametersSharedPtr params = mMaterial->getTechnique(0)->getPass(0)->getVertexProgramParameters();
    //	    params->setNamedConstant("configSettings", Vector4(PagingLandScapeOptions::getSingleton().matHeight[0], 
    //                                                            PagingLandScapeOptions::getSingleton().matHeight[1], 
    //                                                            PagingLandScapeOptions::getSingleton().maxValue, 
    //                                                            0.0));

            // Now that we have all the resources in place, we load the material
            mMaterial->load(); 
	    }
    }
//-----------------------------------------------------------------------
void PagingLandScapeTexture_InstantBaseTextureEdit::_loadMaterial()
{
    if (mMaterial.isNull())
    {
        const String filename  = PagingLandScapeOptions::getSingleton().landscape_filename;
        const String extname   = PagingLandScapeOptions::getSingleton().TextureExtension;
        const String groupName = PagingLandScapeOptions::getSingleton().groupName;

        const String commonName = StringConverter::toString(mDataZ) +
                                  String(".") +
                                  StringConverter::toString(mDataX);
        const String matname = String("InstantBaseMaterial.") + commonName + filename;
        const String texname = filename + ".Base." + commonName + ".";

        String finalTexName;
        if (PagingLandScapeOptions::getSingleton().Deformable &&
                ResourceGroupManager::getSingleton().resourceExists(groupName,
                        texname + "modif." +extname))
        {
            finalTexName = texname + "modif." + extname;
        }
        else
        {
            finalTexName = texname + extname;
        }

        if (!mBaseData)
        {
            mImage.load (finalTexName, groupName);
            mBaseData = mImage.getData();
        }

        // check need of material loading
        mMaterial = MaterialManager::getSingleton().getByName(matname);
        if (mMaterial.isNull())
        {
            MaterialPtr templateMaterial;
            if (PagingLandScapeOptions::getSingleton ().VertexCompression)
            {
                templateMaterial = MaterialManager::getSingleton().getByName(String ("InstantBaseMaterialVertexPixelShaded"));

                // Create a new texture using the base image
                mMaterial = templateMaterial->clone(matname, true, groupName);

                GpuProgramParametersSharedPtr params = mMaterial->getTechnique(0)->getPass(0)->getVertexProgramParameters();

//                    params->setNamedConstant("FogSettings", Vector4(PagingLandScapeOptions::getSingleton().scale.x * PagingLandScapeOptions::getSingleton().PageSize,
//                                                                    PagingLandScapeOptions::getSingleton().scale.y / 65535,
//                                                                    PagingLandScapeOptions::getSingleton().scale.z * PagingLandScapeOptions::getSingleton().PageSize,
//                                                                    0.0f));
                // Check to see if custom param is already there
                GpuProgramParameters::AutoConstantIterator aci = params->getAutoConstantIterator();
                bool found = false;
                while (aci.hasMoreElements())
                {
                    const GpuProgramParameters::AutoConstantEntry& ace = aci.getNext();
                    if (ace.paramType == GpuProgramParameters::ACT_CUSTOM &&
                            ace.data == MORPH_CUSTOM_PARAM_ID)
                    {
                        found = true;
                    }
                }
                if (!found)
                {
                    params->setNamedAutoConstant("compressionSettings",
                                                 GpuProgramParameters::ACT_CUSTOM, MORPH_CUSTOM_PARAM_ID);
                }

            }
            else
            {
                templateMaterial = MaterialManager::getSingleton().getByName(String ("InstantBaseMaterial"));
                // Create a new texture using the base image
                mMaterial = templateMaterial->clone(matname, true, groupName);
            }

            // assign this texture to the material
            _LoadTexture(finalTexName, groupName);
            mMaterial->getTechnique(0)->getPass(0)->getTextureUnitState(0)->setTextureName (finalTexName);

            mMaterial->load();
            mMaterial->setLightingEnabled( PagingLandScapeOptions::getSingleton().lit );
        }
        else
            _LoadTexture(finalTexName, groupName);

    }
}
//-----------------------------------------------------------------------------
///
void WindBatchPage::_updateShaders()
{
	if (!m_bShadersSupported)
		return;

	unsigned int i = 0;
	BatchedGeometry::TSubBatchIterator it = m_pBatchGeom->getSubBatchIterator();
	while (it.hasMoreElements())
   {
      BatchedGeometry::SubBatch *subBatch = it.getNext();
		const MaterialPtr &ptrMat = m_vecUnfadedMaterials[i++];

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

			if (lightingEnabled)
            break;
		}

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

		for (unsigned short i = 0; i < subBatch->m_pVertexData->vertexDeclaration->getElementCount(); ++i)
      {
			const VertexElement *el = subBatch->m_pVertexData->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;
		if (Root::getSingleton().getRenderSystem()->getName() == "Direct3D9 Rendering Subsystem")
			shaderLanguage = "hlsl";
		else if(Root::getSingleton().getRenderSystem()->getName() == "OpenGL Rendering Subsystem")
			shaderLanguage = "glsl";
		else
			shaderLanguage = "cg";

		//If the shader hasn't been created yet, create it
		if (HighLevelGpuProgramManager::getSingleton().getByName(vertexProgName).isNull())
		{
			Pass *pass = ptrMat->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->m_pVertexData->vertexDeclaration->findElementBySemantic(VES_DIFFUSE) != NULL)
				{
					vertexProgSource += 
						"	float4 iColor	 : COLOR, \n";
				}

				int texNum = 0;

				unsigned short texCoordCount = 0;
				for (unsigned short j = 0; j < subBatch->m_pVertexData->vertexDeclaration->getElementCount(); ++j) 
				{
					const VertexElement *el = subBatch->m_pVertexData->vertexDeclaration->getElement(j);
					if (el->getSemantic() == VES_TEXTURE_COORDINATES) 
					{
						++ texCoordCount;
					}
				}

				for (unsigned short i = 0; i < subBatch->m_pVertexData->vertexDeclaration->getElementCount(); ++i)
				{
					const VertexElement *el = subBatch->m_pVertexData->vertexDeclaration->getElement(i);
					if (el->getSemantic() == VES_TEXTURE_COORDINATES)
					{
						if (el->getIndex() == texCoordCount - 2)
						{
							vertexProgSource += 
								"	float4 params 	: TEXCOORD" + StringConverter::toString(texCoordCount-2) + ", \n";
						}
						else
						{
							if (el->getIndex() == texCoordCount - 1)
							{
								vertexProgSource += 
									"	float4 originPos 	: TEXCOORD" + StringConverter::toString(texCoordCount-1) + ", \n";
							}
							else
							{
								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";

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

				if (m_bFadeEnabled)
				{
					vertexProgSource +=
						"	uniform float3 camPos, \n"
						"	uniform float fadeGap, \n"
						"	uniform float invisibleDist, \n";
				}

				vertexProgSource +=
					"	uniform float4x4 worldViewProj,\n"
					"	uniform float time) \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->m_pVertexData->vertexDeclaration->findElementBySemantic(VES_DIFFUSE) != NULL)
					{
						vertexProgSource +=
							"	oColor = (lightAmbient + diffuseFactor * lightDiffuse) * iColor; \n";
					}
					else
					{
						vertexProgSource +=
							"	oColor = (lightAmbient + diffuseFactor * lightDiffuse); \n";
					}
				}
				else
				{
					if (subBatch->m_pVertexData->vertexDeclaration->findElementBySemantic(VES_DIFFUSE) != NULL)
					{
						vertexProgSource +=
							"	oColor = iColor; \n";
					}
					else
					{
						vertexProgSource +=
							"	oColor = float4(1, 1, 1, 1); \n";
					}
				}

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

				for (unsigned short i = 0; i < texCoordCount - 2; ++i)
				{
					vertexProgSource += 
						"	oUV" + StringConverter::toString(i) + " = iUV" + StringConverter::toString(i) + "; \n";
				}

				vertexProgSource +=
					"	float radiusCoeff = params.x; \n"
					"	float heightCoeff = params.y; \n"
					"	float factorX = params.z; \n"
					"	float factorY = params.w; \n"
					"	float4 tmpPos = iPosition; \n"

					/* 
					2 different methods are used to for the sin calculation :
					- the first one gives a better effect but at the cost of a few fps because of the 2 sines
					- the second one uses less ressources but is a bit less realistic

						a sin approximation could be use to optimize performances
					*/
	#if 0
					"	tmpPos.y += sin(time + originPos.z + tmpPos.y + tmpPos.x) * radiusCoeff * radiusCoeff * factorY; \n"
					"	tmpPos.x += sin(time + originPos.z ) * heightCoeff * heightCoeff * factorX ; \n"
	#else
					"	float sinval = sin(time + originPos.z ); \n"
					"	tmpPos.y += sinval * radiusCoeff * radiusCoeff * factorY; \n"
					"	tmpPos.x += sinval * heightCoeff * heightCoeff * factorX ; \n"
	#endif
					"	oPosition = mul(worldViewProj, tmpPos); \n"
					"	oFog = oPosition.z; \n"
					"}";
			}

			if(!shaderLanguage.compare("glsl"))
			{
				unsigned short texCoordCount = 0;
				for (unsigned short j = 0; j < subBatch->m_pVertexData->vertexDeclaration->getElementCount(); ++j) 
				{
					const VertexElement *el = subBatch->m_pVertexData->vertexDeclaration->getElement(j);
					if (el->getSemantic() == VES_TEXTURE_COORDINATES) 
					{
						++ texCoordCount;
					}
				}

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

				if (m_bFadeEnabled)
				{
					 vertexProgSource +=
						"uniform vec3 camPos; \n"
						"uniform float fadeGap; \n"
						"uniform float invisibleDist; \n";
				}

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

				int texNum = 0;

				for (unsigned short i = 0; i < subBatch->m_pVertexData->vertexDeclaration->getElementCount(); ++i)
				{
					const VertexElement *el = subBatch->m_pVertexData->vertexDeclaration->getElement(i);
					if (el->getSemantic() == VES_TEXTURE_COORDINATES)
					{
						if (el->getIndex() == texCoordCount - 2)
						{
							vertexProgSource += 
								"	vec4 params = gl_MultiTexCoord" + StringConverter::toString(texCoordCount-2) + "; \n";
						}
						else
						{
							if (el->getIndex() == texCoordCount - 1)
							{
								vertexProgSource += 
									"	vec4 originPos = gl_MultiTexCoord" + StringConverter::toString(texCoordCount-1) + "; \n";
							}
							else
							{
								vertexProgSource += 
								"	gl_TexCoord[" + StringConverter::toString(texNum) + "]	= gl_MultiTexCoord" + StringConverter::toString(texNum) + "; \n";
							}
							++texNum;
						}
					}
				}

				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.xyz, light), 0.0); \n";

					if (subBatch->m_pVertexData->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->m_pVertexData->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 (m_bFadeEnabled)
				{
					//Fade out in the distance
					vertexProgSource +=
						"	float dist = distance(camPos.xz, gl_Vertex.xz);	\n"
						"	gl_FrontColor.a *= (invisibleDist - dist) / fadeGap; \n";
				}

				vertexProgSource +=
					"	float radiusCoeff = params.x; \n"
					"	float heightCoeff = params.y; \n"
					"	float factorX = params.z; \n"
					"	float factorY = params.w; \n"
					"	vec4 tmpPos = gl_Vertex; \n"
					
					/* 
					2 different methods are used to for the sin calculation :
					- the first one gives a better effect but at the cost of a few fps because of the 2 sines
					- the second one uses less ressources but is a bit less realistic

					a sin approximation could be use to optimize performances
					*/
	#if 1
					"	tmpPos.y += sin(time + originPos.z + tmpPos.y + tmpPos.x) * radiusCoeff * radiusCoeff * factorY; \n"
					"	tmpPos.x += sin(time + originPos.z ) * heightCoeff * heightCoeff * factorX; \n"
	#else
	 				
					"	float sinval = sin(time + originPos.z ); \n"
					"	tmpPos.y += sinval * radiusCoeff * radiusCoeff * factorY; \n"
					"	tmpPos.x += sinval * heightCoeff * heightCoeff * factorX; \n"
	#endif
					"	gl_Position = gl_ModelViewProjectionMatrix * tmpPos; \n"
					"	gl_FogFragCoord = gl_Position.z; \n"
					"}";
			}

			// test for shader source
			//std::ofstream shaderOutput;
			//shaderOutput.open((vertexProgName+std::string(".cg")).c_str());
			//shaderOutput << vertexProgSource;
			//shaderOutput.close();

			// end test for shader source

			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();
		}

		//Now that the shader is ready to be applied, apply it
		StringUtil::StrStreamType materialSignature;
		materialSignature << "BatchMat|";
		materialSignature << ptrMat->getName() << "|";
		if (m_bFadeEnabled)
      {
			materialSignature << m_fVisibleDist << "|";
			materialSignature << m_fInvisibleDist << "|";
		}

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

			//And apply the fade shader
			for (unsigned short t = 0; t < generatedMaterial->getNumTechniques(); ++t){
				Technique *tech = generatedMaterial->getTechnique(t);
				for (unsigned short p = 0; p < tech->getNumPasses(); ++p){
					Pass *pass = tech->getPass(p);

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

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

						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);
						}

						params->setNamedConstantFromTime("time", 1);

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

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

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

							params->setNamedAutoConstant("fadeGap", GpuProgramParameters::ACT_CUSTOM);
							params->setNamedConstant("fadeGap", m_fInvisibleDist - m_fVisibleDist);

							if (pass->getAlphaRejectFunction() == CMPF_ALWAYS_PASS)
								pass->setSceneBlending(SBT_TRANSPARENT_ALPHA);
						}
					}
					catch (const Ogre::Exception &e)
					{
						// test for shader source	
						std::ofstream shaderOutput;
						shaderOutput.open("exception.log");
						shaderOutput << e.getDescription();
						shaderOutput.close();
					}
					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);
	}
Beispiel #15
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;
}
	//-----------------------------------------------------------------------------------
	void PbsMaterial::updateUniforms(const Pass* pass, const AutoParamDataSource* source, const LightList* pLightList)
	{
		// Vertex program
		GpuProgramParametersSharedPtr vertexParams = pass->getVertexProgramParameters();
		vertexParams->setIgnoreMissingParams(true);

		vertexParams->setNamedAutoConstant("mvpMat", GpuProgramParameters::ACT_WORLDVIEWPROJ_MATRIX);
		vertexParams->setNamedAutoConstant("mvMat", GpuProgramParameters::ACT_WORLDVIEW_MATRIX);

		// Fragment program
		GpuProgramParametersSharedPtr fragmentParams = pass->getFragmentProgramParameters();
		
		fragmentParams->setNamedAutoConstant("ivMat", GpuProgramParameters::ACT_INVERSE_VIEW_MATRIX);
		
		fragmentParams->setNamedConstant("in_albedo", mAlbedo);
		fragmentParams->setNamedConstant("in_f0", mF0);
		fragmentParams->setNamedConstant("in_roughness", mRoughness);
		fragmentParams->setNamedConstant("in_light_roughness_offset", mLightRoughnessOffset);

		fragmentParams->setNamedConstant("in_offset_main", mMainOffset);
		fragmentParams->setNamedConstant("in_scale_main", mMainScale);

		fragmentParams->setNamedConstant("in_offset_d1", mD1Offset);
		fragmentParams->setNamedConstant("in_scale_d1", mD1Scale);

		fragmentParams->setNamedConstant("in_offset_d2", mD2Offset);
		fragmentParams->setNamedConstant("in_scale_d2", mD2Scale);

		// Set light uniforms
		unsigned int count = std::min(mDirectionalLightCount + mPointLightCount + mSpotLightCount, maxLightCount);
		if (count)
		{
			Matrix4 viewMatrix = source->getViewMatrix();
			Quaternion viewMatrixQuat = viewMatrix.extractQuaternion();

			int directionalLightIndex = 0;
			int pointLightLightIndex = 0;
			int spotLightIndex = 0;

			for (unsigned int i = 0; i < count; i++)
			{
				Light* light = (*pLightList)[i];

				int index;
				if (light->getType() == Light::LT_DIRECTIONAL)
				{
					index = directionalLightIndex;
					directionalLightIndex++;
				}
				else if (light->getType() == Light::LT_POINT)
				{
					index = mDirectionalLightCount + pointLightLightIndex;
					pointLightLightIndex++;
				}
				else
				{
					index = mDirectionalLightCount + mPointLightCount + spotLightIndex;
					spotLightIndex++;
				}

				Vector3 pos = viewMatrix * light->getDerivedPosition();
				mLightPositions_es[index * 4 + 0] = pos.x;
				mLightPositions_es[index * 4 + 1] = pos.y;
				mLightPositions_es[index * 4 + 2] = pos.z;

				Vector3 dir = -(viewMatrixQuat * light->getDerivedDirection()).normalisedCopy();
				mLightDirections_es[index * 4 + 0] = dir.x;
				mLightDirections_es[index * 4 + 1] = dir.y;
				mLightDirections_es[index * 4 + 2] = dir.z;

				ColourValue color = light->getDiffuseColour();
				mLightColors[index * 4 + 0] = color.r;
				mLightColors[index* 4 + 1] = color.g;
				mLightColors[index* 4 + 2] = color.b;

				mLightParameters[index * 4 + 0] = light->getAttenuationRange();
				mLightParameters[index * 4 + 1] = Math::Cos(light->getSpotlightOuterAngle() / 2.0);
				mLightParameters[index * 4 + 2] = light->getSpotlightFalloff();
			}

			fragmentParams->setNamedConstant("lightPositions_es", &(mLightPositions_es[0]), count);
			fragmentParams->setNamedConstant("lightDirections_es", &(mLightDirections_es[0]), count);
			fragmentParams->setNamedConstant("lightColors", &(mLightColors[0]), count);
			fragmentParams->setNamedConstant("lightParameters", &(mLightParameters[0]), count);
		}

		// update the textures
		if (_hasSamplerChanged)
		{
			for (int i = 0; i < ST_COUNT; i++)
			{
				SamplerContainer& s = _samplers[i];
				if (s.status == SS_UPDATED)
				{
					updateTexturUnits(s.textureUnitState, fragmentParams, s, i);
					s.status = SS_ACTIVE;
				}
			}

			_hasSamplerChanged = false;
		}
	}
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;
		if (Root::getSingleton().getRenderSystem()->getName() == "Direct3D9 Rendering Subsystem")
			shaderLanguage = "hlsl";
		else if(Root::getSingleton().getRenderSystem()->getName() == "OpenGL Rendering Subsystem")
			shaderLanguage = "glsl";
		else
			shaderLanguage = "cg";

		//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";

				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"
					"	oFog = oPosition.z; \n"
					"}";
			}

			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"
					"   gl_FogFragCoord = gl_Position.z; \n"
					"}";
			}


			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();
		}

		//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
			for (unsigned short t = 0; t < generatedMaterial->getNumTechniques(); ++t){
				Technique *tech = generatedMaterial->getTechnique(t);
				for (unsigned short p = 0; p < tech->getNumPasses(); ++p){
					Pass *pass = tech->getPass(p);

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

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

						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"))
						{
							//glsl can use the built in gl_ModelViewProjectionMatrix
							params->setNamedAutoConstant("worldViewProj", GpuProgramParameters::ACT_WORLDVIEWPROJ_MATRIX);
						}

						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);
						}
					}
					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);
	}

}
//-----------------------------------------------------------------------------
///
MaterialPtr StaticBillboardSet::getFadeMaterial(const Ogre::MaterialPtr &protoMaterial,
                                                Real visibleDist_, Real invisibleDist_)
{
   assert(!protoMaterial.isNull());

   StringUtil::StrStreamType materialSignature;
   materialSignature << mEntityName << "|";
   materialSignature << visibleDist_ << "|";
   materialSignature << invisibleDist_ << "|";
   materialSignature << protoMaterial->getTechnique(0)->getPass(0)->getTextureUnitState(0)->getTextureUScroll() << "|";
   materialSignature << protoMaterial->getTechnique(0)->getPass(0)->getTextureUnitState(0)->getTextureVScroll() << "|";

   FadedMaterialMap::iterator it = s_mapFadedMaterial.find(materialSignature.str());
   if (it != s_mapFadedMaterial.end())
      return it->second; //Use the existing fade material
   else
   {
      MaterialPtr fadeMaterial = protoMaterial->clone(getUniqueID("ImpostorFade"));

      bool isglsl = Root::getSingleton().getRenderSystem()->getName() == "OpenGL Rendering Subsystem" ? true : false;

      //And apply the fade shader
      for (unsigned short t = 0; t < fadeMaterial->getNumTechniques(); ++t)
      {
         Technique *tech = fadeMaterial->getTechnique(t);
         for (unsigned short p = 0; p < tech->getNumPasses(); ++p)
         {
            Pass *pass = tech->getPass(p);

            //Setup vertex program
            pass->setVertexProgram("SpriteFade_vp");
            GpuProgramParametersSharedPtr params = pass->getVertexProgramParameters();

            //glsl can use the built in gl_ModelViewProjectionMatrix
            if (!isglsl)
               params->setNamedAutoConstant("worldViewProj", GpuProgramParameters::ACT_WORLDVIEWPROJ_MATRIX);

            static const Ogre::String uScroll = "uScroll", vScroll = "vScroll",
               preRotatedQuad0 = "preRotatedQuad[0]", preRotatedQuad1 = "preRotatedQuad[1]",
               preRotatedQuad2 = "preRotatedQuad[2]", preRotatedQuad3 = "preRotatedQuad[3]",
               camPos = "camPos", fadeGap = "fadeGap", invisibleDist = "invisibleDist";

            params->setNamedAutoConstant(uScroll, GpuProgramParameters::ACT_CUSTOM);
            params->setNamedAutoConstant(vScroll, GpuProgramParameters::ACT_CUSTOM);
            params->setNamedAutoConstant(preRotatedQuad0, GpuProgramParameters::ACT_CUSTOM);
            params->setNamedAutoConstant(preRotatedQuad1, GpuProgramParameters::ACT_CUSTOM);
            params->setNamedAutoConstant(preRotatedQuad2, GpuProgramParameters::ACT_CUSTOM);
            params->setNamedAutoConstant(preRotatedQuad3, GpuProgramParameters::ACT_CUSTOM);

            params->setNamedAutoConstant(camPos, GpuProgramParameters::ACT_CAMERA_POSITION_OBJECT_SPACE);
            params->setNamedAutoConstant(fadeGap, GpuProgramParameters::ACT_CUSTOM);
            params->setNamedAutoConstant(invisibleDist, GpuProgramParameters::ACT_CUSTOM);

            //Set fade ranges
            params->setNamedConstant(invisibleDist, invisibleDist_);
            params->setNamedConstant(fadeGap, invisibleDist_ - visibleDist_);

            pass->setSceneBlending(SBT_TRANSPARENT_ALPHA);
            //pass->setAlphaRejectFunction(CMPF_ALWAYS_PASS);
            //pass->setDepthWriteEnabled(false);

         }  // for Pass

      }  // for Technique

      //Add it to the list so it can be reused later
      s_mapFadedMaterial.insert(std::pair<String, MaterialPtr>(materialSignature.str(), fadeMaterial));

      return fadeMaterial;
   }
}
//-----------------------------------------------------------------------------
///
void StaticBillboardSet::updateAll(const Vector3 &cameraDirection)
{
   // s_nSelfInstances will only be greater than 0 if one or more StaticBillboardSet's are using BB_METHOD_ACCELERATED
   if (s_nSelfInstances == 0)
      return;

   //Set shader parameter so material will face camera
   Vector3 forward = cameraDirection;
   Vector3 vRight = forward.crossProduct(Vector3::UNIT_Y);
   Vector3 vUp = forward.crossProduct(vRight);
   vRight.normalise();
   vUp.normalise();

   //Even if camera is upside down, the billboards should remain upright
   if (vUp.y < 0)
      vUp *= -1;

   // Precompute preRotatedQuad for both cases (BBO_CENTER, BBO_BOTTOM_CENTER)
   
   Vector3 vPoint0 = (-vRight + vUp);
   Vector3 vPoint1 = ( vRight + vUp);
   Vector3 vPoint2 = (-vRight - vUp);
   Vector3 vPoint3 = ( vRight - vUp);

   float preRotatedQuad_BBO_CENTER[16] = // single prerotated quad oriented towards the camera
   {
      (float)vPoint0.x, (float)vPoint0.y, (float)vPoint0.z, 0.0f,
      (float)vPoint1.x, (float)vPoint1.y, (float)vPoint1.z, 0.0f,
      (float)vPoint2.x, (float)vPoint2.y, (float)vPoint2.z, 0.0f,
      (float)vPoint3.x, (float)vPoint3.y, (float)vPoint3.z, 0.0f
   };

   vPoint0 = (-vRight + vUp + vUp);
   vPoint1 = ( vRight + vUp + vUp);
   vPoint2 = (-vRight);
   vPoint3 = ( vRight);
   float preRotatedQuad_BBO_BOTTOM_CENTER[16] =
   {
      (float)vPoint0.x, (float)vPoint0.y, (float)vPoint0.z, 0.0f,
      (float)vPoint1.x, (float)vPoint1.y, (float)vPoint1.z, 0.0f,
      (float)vPoint2.x, (float)vPoint2.y, (float)vPoint2.z, 0.0f,
      (float)vPoint3.x, (float)vPoint3.y, (float)vPoint3.z, 0.0f
   };

   // Shaders uniform variables
   static const Ogre::String uScroll = "uScroll", vScroll = "vScroll", preRotatedQuad0 = "preRotatedQuad[0]",
      preRotatedQuad1 = "preRotatedQuad[1]", preRotatedQuad2 = "preRotatedQuad[2]", preRotatedQuad3 = "preRotatedQuad[3]";

   // SVA for Ogre::Material hack
   const GpuConstantDefinition *pGPU_ConstDef_preRotatedQuad0 = 0,
      *pGPU_ConstDef_uScroll = 0, *pGPU_ConstDef_vScroll = 0;

   // For each material in use by the billboard system..
   SBMaterialRefList::iterator i1 = SBMaterialRef::getList().begin(), iend = SBMaterialRef::getList().end();
   while (i1 != iend)
   {
      Ogre::Material *mat = i1->second->getMaterial();

      // Ensure material is set up with the vertex shader
      Pass *p = mat->getTechnique(0)->getPass(0);
      if (!p->hasVertexProgram())
      {
         static const Ogre::String Sprite_vp = "Sprite_vp";
         p->setVertexProgram(Sprite_vp);

         // glsl can use the built in gl_ModelViewProjectionMatrix
         if (!s_isGLSL)
            p->getVertexProgramParameters()->setNamedAutoConstant("worldViewProj", GpuProgramParameters::ACT_WORLDVIEWPROJ_MATRIX);

         GpuProgramParametersSharedPtr params = p->getVertexProgramParameters();
         params->setNamedAutoConstant(uScroll, GpuProgramParameters::ACT_CUSTOM);
         params->setNamedAutoConstant(vScroll, GpuProgramParameters::ACT_CUSTOM);
         params->setNamedAutoConstant(preRotatedQuad0, GpuProgramParameters::ACT_CUSTOM);
         params->setNamedAutoConstant(preRotatedQuad1, GpuProgramParameters::ACT_CUSTOM);
         params->setNamedAutoConstant(preRotatedQuad2, GpuProgramParameters::ACT_CUSTOM);
         params->setNamedAutoConstant(preRotatedQuad3, GpuProgramParameters::ACT_CUSTOM);
      }

      // Which prerotated quad use
      const float *pQuad = i1->second->getOrigin() == BBO_CENTER ? preRotatedQuad_BBO_CENTER : preRotatedQuad_BBO_BOTTOM_CENTER;

      // Update the vertex shader parameters
      GpuProgramParametersSharedPtr params = p->getVertexProgramParameters();
      //params->setNamedConstant(preRotatedQuad0, pQuad, 4);
      //params->setNamedConstant(uScroll, p->getTextureUnitState(0)->getTextureUScroll());
      //params->setNamedConstant(vScroll, p->getTextureUnitState(0)->getTextureVScroll());

      // SVA some hack of Ogre::Material.
      // Since material are cloned and use same vertex shader "Sprite_vp" hardware GPU indices
      // must be same. I don`t know planes of Ogre Team to change this behaviour.
      // Therefore this may be unsafe code. Instead of 3 std::map lookups(map::find(const Ogre::String&)) do only 1
      {
         const GpuConstantDefinition *def = params->_findNamedConstantDefinition(preRotatedQuad0, true);
         if (def != pGPU_ConstDef_preRotatedQuad0) // new material, reread
         {
            pGPU_ConstDef_preRotatedQuad0 = def;
            pGPU_ConstDef_uScroll         = params->_findNamedConstantDefinition(uScroll, true);
            pGPU_ConstDef_vScroll         = params->_findNamedConstantDefinition(vScroll, true);
         }
      }

      float fUScroll = (float)p->getTextureUnitState(0)->getTextureUScroll(),
         fVScroll = (float)p->getTextureUnitState(0)->getTextureVScroll();
      params->_writeRawConstants(pGPU_ConstDef_preRotatedQuad0->physicalIndex, pQuad, 16);
      params->_writeRawConstants(pGPU_ConstDef_uScroll->physicalIndex, &fUScroll, 1);
      params->_writeRawConstants(pGPU_ConstDef_vScroll->physicalIndex, &fVScroll, 1);
      
      ++i1; // next material in billboard system
   }
}
    //-----------------------------------------------------------------------
    void PagingLandScapeTexture_Image::_loadMaterial()
    {
	    if ( mMaterial.isNull() )
	    {
            if (PagingLandScapeOptions::getSingleton().ImageNameLoad)
            {  
                const String filename = PagingLandScapeOptions::getSingleton().image_filename;
                const String commonName = StringConverter::toString(mDataZ) + 
                                            String(".") +
                                            StringConverter::toString(mDataX);
                const String matname = String("ImageTexture.") + commonName + filename;
                mMaterial = MaterialManager::getSingleton().getByName(matname);
                if (mMaterial.isNull())
                {
                    MaterialPtr templateMaterial;
                    if (PagingLandScapeOptions::getSingleton ().VertexCompression)
                    {
                        templateMaterial = MaterialManager::getSingleton().getByName(String ("PagingLandScape.Template.VertexPixelShaded"));
                        mMaterial = templateMaterial->clone(matname);    

                        GpuProgramParametersSharedPtr params = mMaterial->getTechnique(0)->getPass(0)->getVertexProgramParameters();
    	                
    //                    params->setNamedConstant("compressionSettings", Vector4(PagingLandScapeOptions::getSingleton().scale.x * PagingLandScapeOptions::getSingleton().PageSize, 
    //                                                                        PagingLandScapeOptions::getSingleton().scale.y / 65535, 
    //                                                                        PagingLandScapeOptions::getSingleton().scale.z * PagingLandScapeOptions::getSingleton().PageSize, 
    //                                                                        0.0));
                        // Check to see if custom param is already there
                        GpuProgramParameters::AutoConstantIterator aci = params->getAutoConstantIterator();
                        bool found = false;
                        while (aci.hasMoreElements())
                        {
                            const GpuProgramParameters::AutoConstantEntry& ace = aci.getNext();
                            if (ace.paramType == GpuProgramParameters::ACT_CUSTOM && 
                                ace.data == MORPH_CUSTOM_PARAM_ID)
                            {
                                found = true;
                            }
                        }
                        if (!found)
                        {                        
                            params->setNamedAutoConstant("compressionSettings", 
                                GpuProgramParameters::ACT_CUSTOM, MORPH_CUSTOM_PARAM_ID);                       
                        }
                    }
                    else
                    {
                        templateMaterial = MaterialManager::getSingleton().getByName(String ("PagingLandScape.Template"));
                        mMaterial = templateMaterial->clone(matname);
                    }   
          
                }
                const String texname = filename + "." +
                    commonName + "." + PagingLandScapeOptions::getSingleton().TextureExtension;       
                // assign this texture to the material
                mMaterial->getTechnique(0)->getPass(0)->getTextureUnitState(0)->setTextureName(texname);
            }
            else
            {
                // JEFF - all material settings configured through material script
                mMaterial = (MaterialManager::getSingleton().getByName("PagingLandScape." +
                    StringConverter::toString( mDataZ ) + "." + 
                    StringConverter::toString( mDataX )));
            }
               
		    mMaterial->load(); 
            mMaterial->setLightingEnabled( PagingLandScapeOptions::getSingleton().lit );
	    }
    }
Beispiel #21
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);
        }
      }
    }
  }
}
    //-------------------------------------------------------------------------
    void TerrainSceneManager::setupTerrainMaterial(void)
    {
        if (mCustomMaterialName == "")
        {
            // define our own material
            mOptions.terrainMaterial = 
                MaterialManager::getSingleton().getByName(TERRAIN_MATERIAL_NAME);
			// Make unique terrain material name
			StringUtil::StrStreamType s;
			s << mName << "/Terrain";
			mOptions.terrainMaterial = MaterialManager::getSingleton().getByName(s.str());
            if (mOptions.terrainMaterial.isNull())
            {
                mOptions.terrainMaterial = MaterialManager::getSingleton().create(
                    s.str(),
                    ResourceGroupManager::getSingleton().getWorldResourceGroupName());

            }
            else
            {
                mOptions.terrainMaterial->getTechnique(0)->getPass(0)->removeAllTextureUnitStates();
            }

            Pass* pass = mOptions.terrainMaterial->getTechnique(0)->getPass(0);

            if ( mWorldTextureName != "" )
            {
                pass->createTextureUnitState( mWorldTextureName, 0 );
            }
            if ( mDetailTextureName != "" )
            {
                pass->createTextureUnitState( mDetailTextureName, 1 );
            }

            mOptions.terrainMaterial -> setLightingEnabled( mOptions.lit );

            if (mOptions.lodMorph && 
                mDestRenderSystem->getCapabilities()->hasCapability(RSC_VERTEX_PROGRAM) &&
				GpuProgramManager::getSingleton().getByName("Terrain/VertexMorph").isNull())
            {
                // Create & assign LOD morphing vertex program
                String syntax;
                if (GpuProgramManager::getSingleton().isSyntaxSupported("arbvp1"))
                {
                    syntax = "arbvp1";
                }
                else
                {
                    syntax = "vs_1_1";
                }

                // Get source, and take into account current fog mode
                FogMode fm = getFogMode();
                const String& source = TerrainVertexProgram::getProgramSource(
                    fm, syntax);

                GpuProgramPtr prog = GpuProgramManager::getSingleton().createProgramFromString(
                    "Terrain/VertexMorph", ResourceGroupManager::getSingleton().getWorldResourceGroupName(), 
                    source, GPT_VERTEX_PROGRAM, syntax);

                // Attach
                pass->setVertexProgram("Terrain/VertexMorph");

                // Get params
                GpuProgramParametersSharedPtr params = pass->getVertexProgramParameters();

                // worldviewproj
                params->setAutoConstant(0, GpuProgramParameters::ACT_WORLDVIEWPROJ_MATRIX);
                // morph factor
                params->setAutoConstant(4, GpuProgramParameters::ACT_CUSTOM, MORPH_CUSTOM_PARAM_ID);
                // fog exp density(if relevant)
                if (fm == FOG_EXP || fm == FOG_EXP2)
                {
                    params->setConstant(5, Vector3(getFogDensity(), 0, 0));
                    // Override scene fog since otherwise it's applied twice
                    // Set to linear and we derive [0,1] fog value in the shader
                    pass->setFog(true, FOG_LINEAR, getFogColour(), 0, 1, 0);
                }

				// Also set shadow receiver program
				const String& source2 = TerrainVertexProgram::getProgramSource(
					fm, syntax, true);

				prog = GpuProgramManager::getSingleton().createProgramFromString(
					"Terrain/VertexMorphShadowReceive", 
					ResourceGroupManager::getSingleton().getWorldResourceGroupName(), 
					source2, GPT_VERTEX_PROGRAM, syntax);
				pass->setShadowReceiverVertexProgram("Terrain/VertexMorphShadowReceive");
				params = pass->getShadowReceiverVertexProgramParameters();
				// worldviewproj
				params->setAutoConstant(0, GpuProgramParameters::ACT_WORLDVIEWPROJ_MATRIX);
				// world
				params->setAutoConstant(4, GpuProgramParameters::ACT_WORLD_MATRIX);
				// texture view / proj
				params->setAutoConstant(8, GpuProgramParameters::ACT_TEXTURE_VIEWPROJ_MATRIX);
				// morph factor
				params->setAutoConstant(12, GpuProgramParameters::ACT_CUSTOM, MORPH_CUSTOM_PARAM_ID);
				
				if (mDetailTextureName != "")
				{
					pass->getTextureUnitState(1)->setTextureCoordSet(1);
				}


                // Set param index
                mLodMorphParamName = "";
                mLodMorphParamIndex = 4;
            }

            mOptions.terrainMaterial->load();

        }
        else
        {
            // Custom material
            mOptions.terrainMaterial = 
                MaterialManager::getSingleton().getByName(mCustomMaterialName);
			if (mOptions.terrainMaterial.isNull()){
				OGRE_EXCEPT(Exception::ERR_ITEM_NOT_FOUND, 
					"Material " + mCustomMaterialName + " not found.", 
					"TerrainSceneManager::setupTerrainMaterial");
			}
            mOptions.terrainMaterial->load();

        }

        // now set up the linkage between vertex program and LOD morph param
        if (mOptions.lodMorph)
        {
            Technique* t = mOptions.terrainMaterial->getBestTechnique();
            for (ushort i = 0; i < t->getNumPasses(); ++i)
            {
                Pass* p = t->getPass(i);
                if (p->hasVertexProgram())
                {
                    // we have to assume vertex program includes LOD morph capability
                    GpuProgramParametersSharedPtr params = 
                        p->getVertexProgramParameters();
                    // Check to see if custom param is already there
                    GpuProgramParameters::AutoConstantIterator aci = params->getAutoConstantIterator();
                    bool found = false;
                    while (aci.hasMoreElements())
                    {
                        const GpuProgramParameters::AutoConstantEntry& ace = aci.getNext();
                        if (ace.paramType == GpuProgramParameters::ACT_CUSTOM && 
                            ace.data == MORPH_CUSTOM_PARAM_ID)
                        {
                            found = true;
                        }
                    }
                    if (!found)
                    {
                        if(mLodMorphParamName != "")
                        {
                            params->setNamedAutoConstant(mLodMorphParamName, 
                                GpuProgramParameters::ACT_CUSTOM, MORPH_CUSTOM_PARAM_ID);
                        }
                        else
                        {
                            params->setAutoConstant(mLodMorphParamIndex, 
                                GpuProgramParameters::ACT_CUSTOM, MORPH_CUSTOM_PARAM_ID);
                        }
                    }

                }
            }
        }

    }