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