//----------------------------------------------------------------------------- /// 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); }
//--------------------------------------------------------------------- void TerrainMaterialGeneratorC::SM2Profile::addTechnique( const MaterialPtr& mat, const Terrain* terrain, TechniqueType tt) { Technique* tech = mat->createTechnique(); tech->setSchemeName("GBuffer"); // Only supporting one pass Pass* pass = tech->createPass(); //pass->setName("NO_DEFERRED"); GpuProgramManager& gmgr = GpuProgramManager::getSingleton(); HighLevelGpuProgramManager& hmgr = HighLevelGpuProgramManager::getSingleton(); if (!mShaderGen) { if (hmgr.isLanguageSupported("cg")) mShaderGen = OGRE_NEW ShaderHelperCg(); else { // todo } // check SM3 features mSM3Available = GpuProgramManager::getSingleton().isSyntaxSupported("ps_3_0"); mSM4Available = GpuProgramManager::getSingleton().isSyntaxSupported("ps_4_0"); } HighLevelGpuProgramPtr vprog = mShaderGen->generateVertexProgram(this, terrain, tt); HighLevelGpuProgramPtr fprog = mShaderGen->generateFragmentProgram(this, terrain, tt); pass->setVertexProgram(vprog->getName()); pass->setFragmentProgram(fprog->getName()); if (tt == HIGH_LOD || tt == RENDER_COMPOSITE_MAP) { // global normal map TextureUnitState* tu = pass->createTextureUnitState(); tu->setTextureName(terrain->getTerrainNormalMap()->getName()); tu->setTextureAddressingMode(TextureUnitState::TAM_CLAMP); // global colour map if (terrain->getGlobalColourMapEnabled() && isGlobalColourMapEnabled()) { tu = pass->createTextureUnitState(terrain->getGlobalColourMap()->getName()); tu->setTextureAddressingMode(TextureUnitState::TAM_CLAMP); } // light map if (isLightmapEnabled()) { tu = pass->createTextureUnitState(terrain->getLightmap()->getName()); tu->setTextureAddressingMode(TextureUnitState::TAM_CLAMP); } // blend maps uint maxLayers = getMaxLayers(terrain); uint numBlendTextures = std::min(terrain->getBlendTextureCount(maxLayers), terrain->getBlendTextureCount()); uint numLayers = std::min(maxLayers, static_cast<uint>(terrain->getLayerCount())); for (uint i = 0; i < numBlendTextures; ++i) { tu = pass->createTextureUnitState(terrain->getBlendTextureName(i)); tu->setTextureAddressingMode(TextureUnitState::TAM_CLAMP); } // layer textures for (uint i = 0; i < numLayers; ++i) { // diffuse / specular pass->createTextureUnitState(terrain->getLayerTextureName(i, 0)); // normal / height pass->createTextureUnitState(terrain->getLayerTextureName(i, 1)); } } else { // LOW_LOD textures // composite map TextureUnitState* tu = pass->createTextureUnitState(); tu->setTextureName(terrain->getCompositeMap()->getName()); tu->setTextureAddressingMode(TextureUnitState::TAM_CLAMP); // That's it! } }
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); } }
//--------------------------------------------------------------------- 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 GLSLProgramProcessor::bindSubShaders(Program* program, GpuProgramPtr pGpuProgram) { if (program->getDependencyCount() > 0) { // Get all attached shaders so we do not attach shaders twice. // maybe GLSLProgram should take care of that ( prevent add duplicate shaders ) String attachedShaders = pGpuProgram->getParameter("attach"); String subShaderDef = ""; for (unsigned int i=0; i < program->getDependencyCount(); ++i) { // Here we append _VS and _FS to the library shaders (so max each lib shader // is compiled twice once as vertex and once as fragment shader) String subShaderName = program->getDependency(i); if (program->getType() == GPT_VERTEX_PROGRAM) { subShaderName += "_VS"; } else { subShaderName += "_FS"; } // Check if the library shader already compiled if(!HighLevelGpuProgramManager::getSingleton().resourceExists(subShaderName)) { // Create the library shader HighLevelGpuProgramPtr pSubGpuProgram = HighLevelGpuProgramManager::getSingleton().createProgram(subShaderName, ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, TargetLanguage, program->getType()); // Set the source name String sourceName = program->getDependency(i) + "." + TargetLanguage; pSubGpuProgram->setSourceFile(sourceName); pSubGpuProgram->load(); // Prepend the current GLSL version String versionLine = "#version " + StringConverter::toString(Root::getSingleton().getRenderSystem()->getNativeShadingLanguageVersion()) + "\n"; pSubGpuProgram->setSource(versionLine + pSubGpuProgram->getSource()); // If we have compile errors than stop processing if (pSubGpuProgram->hasCompileError()) { OGRE_EXCEPT(Exception::ERR_INTERNAL_ERROR, "Could not compile shader library from the source file: " + sourceName, "GLSLProgramProcessor::bindSubShaders" ); } mLibraryPrograms.push_back(subShaderName); } // Check if the lib shader already attached to this shader if (attachedShaders.find(subShaderName) == String::npos) { // Append the shader name to subShaders subShaderDef += subShaderName + " "; } } // Check if we have something to attach if (subShaderDef.length() > 0) { pGpuProgram->setParameter("attach", subShaderDef); } } }
//----------------------------------------------------------------------------- GpuProgramPtr ProgramManager::createGpuProgram(Program* shaderProgram, ProgramWriter* programWriter, const String& language, const String& profiles, const StringVector& profilesList, const String& cachePath) { stringstream sourceCodeStringStream; // Generate source code. programWriter->writeSourceCode(sourceCodeStringStream, shaderProgram); String source = sourceCodeStringStream.str(); // Generate program name. String programName = generateHash(source); if (shaderProgram->getType() == GPT_VERTEX_PROGRAM) { programName += "_VS"; } else if (shaderProgram->getType() == GPT_FRAGMENT_PROGRAM) { programName += "_FS"; } // Try to get program by name. HighLevelGpuProgramPtr pGpuProgram = HighLevelGpuProgramManager::getSingleton().getByName( programName, ResourceGroupManager::INTERNAL_RESOURCE_GROUP_NAME); if(pGpuProgram) { return static_pointer_cast<GpuProgram>(pGpuProgram); } // Case the program doesn't exist yet. // Create new GPU program. pGpuProgram = HighLevelGpuProgramManager::getSingleton().createProgram(programName, ResourceGroupManager::INTERNAL_RESOURCE_GROUP_NAME, language, shaderProgram->getType()); // Case cache directory specified -> create program from file. if (!cachePath.empty()) { const String programFullName = programName + "." + language; const String programFileName = cachePath + programFullName; std::ifstream programFile; // Check if program file already exist. programFile.open(programFileName.c_str()); // Case we have to write the program to a file. if (!programFile) { std::ofstream outFile(programFileName.c_str()); if (!outFile) return GpuProgramPtr(); outFile << source; outFile.close(); } else { // use program file version StringStream buffer; programFile >> buffer.rdbuf(); source = buffer.str(); } } pGpuProgram->setSource(source); pGpuProgram->setParameter("entry_point", shaderProgram->getEntryPointFunction()->getName()); if (language == "hlsl") { // HLSL program requires specific target profile settings - we have to split the profile string. StringVector::const_iterator it = profilesList.begin(); StringVector::const_iterator itEnd = profilesList.end(); for (; it != itEnd; ++it) { if (GpuProgramManager::getSingleton().isSyntaxSupported(*it)) { pGpuProgram->setParameter("target", *it); break; } } pGpuProgram->setParameter("enable_backwards_compatibility", "true"); pGpuProgram->setParameter("column_major_matrices", StringConverter::toString(shaderProgram->getUseColumnMajorMatrices())); } pGpuProgram->setParameter("profiles", profiles); pGpuProgram->load(); // Case an error occurred. if (pGpuProgram->hasCompileError()) { //! [debug_break] pGpuProgram.reset(); //! [debug_break] return GpuProgramPtr(pGpuProgram); } // Add the created GPU program to local cache. if (pGpuProgram->getType() == GPT_VERTEX_PROGRAM) { mVertexShaderMap[programName] = pGpuProgram; } else if (pGpuProgram->getType() == GPT_FRAGMENT_PROGRAM) { mFragmentShaderMap[programName] = pGpuProgram; } return static_pointer_cast<GpuProgram>(pGpuProgram); }
GpuProgramPtr GBufferMaterialGeneratorImpl::generateVertexShader(MaterialGenerator::Perm permutation) { StringStream ss; if(mIsGLSL) { ss << "#version 150" << std::endl; ss << "in vec4 vertex;" << std::endl; ss << "in vec3 normal;" << std::endl; uint32 numTexCoords = (permutation & GBufferMaterialGenerator::GBP_TEXCOORD_MASK) >> 8; for (uint32 i=0; i<numTexCoords; i++) { ss << "in vec2 uv" << i << ';' << std::endl; } if (permutation & GBufferMaterialGenerator::GBP_NORMAL_MAP) { ss << "in vec3 tangent;" << std::endl; } //TODO : Skinning inputs ss << std::endl; #ifdef WRITE_LINEAR_DEPTH ss << "out vec3 oViewPos;" << std::endl; #else ss << "out float oDepth;" << std::endl; #endif ss << "out vec3 oNormal;" << std::endl; if (permutation & GBufferMaterialGenerator::GBP_NORMAL_MAP) { ss << "out vec3 oTangent;" << std::endl; ss << "out vec3 oBiNormal;" << std::endl; } for (uint32 i=0; i<numTexCoords; i++) { ss << "out vec2 oUv" << i << ";" << std::endl; } ss << std::endl; ss << "uniform mat4 cWorldViewProj;" << std::endl; ss << "uniform mat4 cWorldView;" << std::endl; ss << "void main()" << std::endl; ss << "{" << std::endl; ss << " gl_Position = cWorldViewProj * vertex;" << std::endl; ss << " oNormal = (cWorldView * vec4(normal,0)).xyz;" << std::endl; if (permutation & GBufferMaterialGenerator::GBP_NORMAL_MAP) { ss << " oTangent = (cWorldView * vec4(tangent,0)).xyz;" << std::endl; ss << " oBiNormal = cross(oNormal, oTangent);" << std::endl; } #ifdef WRITE_LINEAR_DEPTH ss << " oViewPos = (cWorldView * vertex).xyz;" << std::endl; #else ss << " oDepth = gl_Position.w;" << std::endl; #endif for (uint32 i=0; i<numTexCoords; i++) { ss << " oUv" << i << " = uv" << i << ';' << std::endl; } ss << "}" << std::endl; String programSource = ss.str(); String programName = mBaseName + "VP_" + StringConverter::toString(permutation); #if OGRE_DEBUG_MODE LogManager::getSingleton().getDefaultLog()->logMessage(programSource); #endif // Create shader object HighLevelGpuProgramPtr ptrProgram = HighLevelGpuProgramManager::getSingleton().createProgram(programName, ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, "glsl", GPT_VERTEX_PROGRAM); ptrProgram->setSource(programSource); ptrProgram->setParameter("syntax", "glsl150"); const GpuProgramParametersSharedPtr& params = ptrProgram->getDefaultParameters(); params->setNamedAutoConstant("cWorldViewProj", GpuProgramParameters::ACT_WORLDVIEWPROJ_MATRIX); params->setNamedAutoConstant("cWorldView", GpuProgramParameters::ACT_WORLDVIEW_MATRIX); ptrProgram->load(); return GpuProgramPtr(ptrProgram); } else {
void Shader::prepare() { // determining shader level and generating a part of the level string std::string levelString = "_basic"; if (shaderLevel == LEVEL_INTERMEDIATE) { levelString = "_intermediate"; } else if (shaderLevel == LEVEL_ADVANCED) { levelString = "_advanced"; } std::string vertexString; std::string geometryString; std::string fragmentString; // trying to use actual shader level, choosing basic as default/backup if (ResourceGroupManager::getSingleton() .resourceExistsInAnyGroup(shaderName + levelString + ".vert")) { vertexString = shaderName + levelString + ".vert"; } else { vertexString = shaderName + "_basic.vert"; } if (ResourceGroupManager::getSingleton() .resourceExistsInAnyGroup(shaderName + levelString + ".geom")) { geometryString = shaderName + levelString + ".geom"; } else { geometryString = shaderName + "_basic.geom"; } if (ResourceGroupManager::getSingleton() .resourceExistsInAnyGroup(shaderName + levelString + ".frag")) { fragmentString = shaderName + levelString + ".frag"; } else { fragmentString = shaderName + "_basic.frag"; } // creating new material material = MaterialManager::getSingletonPtr()->create(materialName + shaderName, ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME); pass = material->getTechnique(0)->getPass(0); // with dynamic lighting only geometry with normals will be displayed pass->setLightingEnabled(true); material->setReceiveShadows(true); // loading vertex shader if there is one if (ResourceGroupManager::getSingleton() .resourceExistsInAnyGroup(vertexString)) { HighLevelGpuProgramPtr vertex = HighLevelGpuProgramManager::getSingletonPtr()->createProgram( shaderName + "_v", ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, "glsl", GpuProgramType::GPT_VERTEX_PROGRAM); vertex->setSourceFile(vertexString); pass->setVertexProgram(vertex->getName()); } // loading geometry shader if there is one if (ResourceGroupManager::getSingleton() .resourceExistsInAnyGroup(geometryString)) { geometry = HighLevelGpuProgramManager::getSingletonPtr()->createProgram( shaderName + "_g", ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, "glsl", GpuProgramType::GPT_GEOMETRY_PROGRAM); geometry->setSourceFile(geometryString); pass->setGeometryProgram(geometry->getName()); } // loading fragment shader if there is one if (ResourceGroupManager::getSingleton() .resourceExistsInAnyGroup(fragmentString)) { HighLevelGpuProgramPtr fragment = HighLevelGpuProgramManager:: getSingletonPtr()->createProgram(shaderName + "_f", ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, "glsl", GpuProgramType::GPT_FRAGMENT_PROGRAM); fragment->setSourceFile(fragmentString); pass->setFragmentProgram(fragment->getName()); } entity->getOgreEntity()->setMaterialName(material->getName()); }
//----------------------------------------------------------------------------- /// Constructor StaticBillboardSet::StaticBillboardSet(SceneManager *mgr, SceneNode *rootSceneNode, BillboardMethod method) : mVisible (true), mFadeEnabled (false), mRenderMethod (method), mpSceneMgr (mgr), mpSceneNode (NULL), mpEntity (NULL), mfUFactor (1.f), mfVFactor (1.f), mpFallbackBillboardSet (NULL), mBBOrigin (BBO_CENTER), mFadeVisibleDist (0.f), mFadeInvisibleDist (0.f) { assert(rootSceneNode); //Fall back to BB_METHOD_COMPATIBLE if vertex shaders are not available if (method == BB_METHOD_ACCELERATED) { const RenderSystemCapabilities *caps = Root::getSingleton().getRenderSystem()->getCapabilities(); if (!caps->hasCapability(RSC_VERTEX_PROGRAM)) mRenderMethod = BB_METHOD_COMPATIBLE; } mpSceneNode = rootSceneNode->createChildSceneNode(); mEntityName = getUniqueID("SBSentity"); if (mRenderMethod == BB_METHOD_ACCELERATED) { //Load vertex shader to align billboards to face the camera (if not loaded already) if (s_nSelfInstances == 0) { const Ogre::String &renderName = Root::getSingleton().getRenderSystem()->getName(); s_isGLSL = renderName == "OpenGL Rendering Subsystem" ? true : false; Ogre::String shaderLanguage = s_isGLSL ? "glsl" : renderName == "Direct3D9 Rendering Subsystem" ? "hlsl" : "cg"; //First shader, simple camera-alignment String vertexProg; if (!s_isGLSL) // DirectX HLSL or nVidia CG { vertexProg = "void Sprite_vp( \n" " float4 position : POSITION, \n" " float3 normal : NORMAL, \n" " float4 color : COLOR, \n" " float2 uv : TEXCOORD0, \n" " out float4 oPosition : POSITION, \n" " out float2 oUv : TEXCOORD0, \n" " out float4 oColor : COLOR, \n" " out float oFog : FOG, \n" " uniform float4x4 worldViewProj, \n" " uniform float uScroll, \n" " uniform float vScroll, \n" " uniform float4 preRotatedQuad[4] ) \n" "{ \n" //Face the camera " float4 vCenter = float4( position.x, position.y, position.z, 1.0f ); \n" " float4 vScale = float4( normal.x, normal.y, normal.x, 1.0f ); \n" " oPosition = mul( worldViewProj, vCenter + (preRotatedQuad[normal.z] * vScale) ); \n" //Color " oColor = color; \n" //UV Scroll " oUv = uv; \n" " oUv.x += uScroll; \n" " oUv.y += vScroll; \n" //Fog " oFog = oPosition.z; \n" "}"; } else // OpenGL GLSL { vertexProg = "uniform float uScroll; \n" "uniform float vScroll; \n" "uniform vec4 preRotatedQuad[4]; \n" "void main() { \n" //Face the camera " vec4 vCenter = vec4( gl_Vertex.x, gl_Vertex.y, gl_Vertex.z, 1.0 ); \n" " vec4 vScale = vec4( gl_Normal.x, gl_Normal.y, gl_Normal.x , 1.0 ); \n" " gl_Position = gl_ModelViewProjectionMatrix * (vCenter + (preRotatedQuad[int(gl_Normal.z)] * vScale) ); \n" //Color " gl_FrontColor = gl_Color; \n" //UV Scroll " gl_TexCoord[0] = gl_MultiTexCoord0; \n" " gl_TexCoord[0].x += uScroll; \n" " gl_TexCoord[0].y += vScroll; \n" //Fog " gl_FogFragCoord = gl_Position.z; \n" "}"; } #if OGRE_VERSION_MAJOR <= 1 #if OGRE_VERSION_MINOR <= 8 HighLevelGpuProgramPtr vertexShader = HighLevelGpuProgramManager::getSingleton().getByName("Sprite_vp"); #else HighLevelGpuProgramPtr vertexShader = HighLevelGpuProgramManager::getSingleton().getByName("Sprite_vp").staticCast<HighLevelGpuProgram>(); #endif #endif assert(vertexShader.isNull() && "Sprite_vp already exist"); vertexShader = HighLevelGpuProgramManager::getSingleton().createProgram( "Sprite_vp", ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, shaderLanguage, GPT_VERTEX_PROGRAM); vertexShader->setSource(vertexProg); // Set entry point for vertex program. GLSL can only have one entry point "main". if (!s_isGLSL) { if (shaderLanguage == "hlsl") { vertexShader->setParameter("target", "vs_1_1"); vertexShader->setParameter("entry_point", "Sprite_vp"); } else if(shaderLanguage == "cg") { vertexShader->setParameter("profiles", "vs_1_1 arbvp1"); vertexShader->setParameter("entry_point", "Sprite_vp"); } else { assert(false && "Unknown shader language"); } } // compile vertex shader vertexShader->load(); //==================================================================== //Second shader, camera alignment and distance based fading String vertexProg2; if (!s_isGLSL) // DirectX HLSL or nVidia CG { vertexProg2 = "void SpriteFade_vp( \n" " float4 position : POSITION, \n" " float3 normal : NORMAL, \n" " float4 color : COLOR, \n" " float2 uv : TEXCOORD0, \n" " out float4 oPosition : POSITION, \n" " out float2 oUv : TEXCOORD0, \n" " out float4 oColor : COLOR, \n" " out float oFog : FOG, \n" " uniform float4x4 worldViewProj, \n" " uniform float3 camPos, \n" " uniform float fadeGap, \n" " uniform float invisibleDist, \n" " uniform float uScroll, \n" " uniform float vScroll, \n" " uniform float4 preRotatedQuad[4] ) \n" "{ \n" //Face the camera " float4 vCenter = float4( position.x, position.y, position.z, 1.0f ); \n" " float4 vScale = float4( normal.x, normal.y, normal.x, 1.0f ); \n" " oPosition = mul( worldViewProj, vCenter + (preRotatedQuad[normal.z] * vScale) ); \n" " oColor.rgb = color.rgb; \n" //Fade out in the distance " float dist = distance(camPos.xz, position.xz); \n" " oColor.a = (invisibleDist - dist) / fadeGap; \n" //UV scroll " oUv = uv; \n" " oUv.x += uScroll; \n" " oUv.y += vScroll; \n" //Fog " oFog = oPosition.z; \n" "}"; } else // OpenGL GLSL { vertexProg2 = "uniform vec3 camPos; \n" "uniform float fadeGap; \n" "uniform float invisibleDist; \n" "uniform float uScroll; \n" "uniform float vScroll; \n" "uniform vec4 preRotatedQuad[4]; \n" "void main() { \n" //Face the camera " vec4 vCenter = vec4( gl_Vertex.x, gl_Vertex.y, gl_Vertex.z, 1.0 ); \n" " vec4 vScale = vec4( gl_Normal.x, gl_Normal.y, gl_Normal.x , 1.0 ); \n" " gl_Position = gl_ModelViewProjectionMatrix * (vCenter + (preRotatedQuad[int(gl_Normal.z)] * vScale) ); \n" " gl_FrontColor.xyz = gl_Color.xyz; \n" //Fade out in the distance " vec4 position = gl_Vertex; \n" " float dist = distance(camPos.xz, position.xz); \n" " gl_FrontColor.w = (invisibleDist - dist) / fadeGap; \n" //UV scroll " gl_TexCoord[0] = gl_MultiTexCoord0; \n" " gl_TexCoord[0].x += uScroll; \n" " gl_TexCoord[0].y += vScroll; \n" //Fog " gl_FogFragCoord = gl_Position.z; \n" "}"; } #if OGRE_VERSION_MAJOR <= 1 #if OGRE_VERSION_MINOR <= 8 HighLevelGpuProgramPtr vertexShader2 = HighLevelGpuProgramManager::getSingleton().getByName("SpriteFade_vp"); #else HighLevelGpuProgramPtr vertexShader2 = HighLevelGpuProgramManager::getSingleton().getByName("SpriteFade_vp").staticCast<HighLevelGpuProgram>(); #endif #endif assert(vertexShader2.isNull() && "SpriteFade_vp already exist"); vertexShader2 = HighLevelGpuProgramManager::getSingleton().createProgram("SpriteFade_vp", ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, shaderLanguage, GPT_VERTEX_PROGRAM); vertexShader2->setSource(vertexProg2); // Set entry point. GLSL can only have one entry point "main". if (!s_isGLSL) { if (shaderLanguage == "hlsl") { vertexShader2->setParameter("target", "vs_1_1"); vertexShader2->setParameter("entry_point", "SpriteFade_vp"); } else if(shaderLanguage == "cg") { vertexShader2->setParameter("profiles", "vs_1_1 arbvp1"); vertexShader2->setParameter("entry_point", "SpriteFade_vp"); } } // compile it vertexShader2->load(); } } else { //Compatible billboard method mpFallbackBillboardSet = mgr->createBillboardSet(getUniqueID("SBS"), 100); mpSceneNode->attachObject(mpFallbackBillboardSet); mfUFactor = mfVFactor = Ogre::Real(0.); } ++s_nSelfInstances; }
void BillboardObject::init(const String& textureName, const float initialSize, const Vector3& position, SceneNode* rootNode) { SceneManager* sceneMgr = rootNode->getCreator(); Vector3 finalPosition = position.normalisedCopy() * 1000.f; static unsigned int bodyCount=0; /// \todo These billboards are not 100% correct, might want to revisit them later mBBSet = sceneMgr->createBillboardSet("SkyBillboardSet"+StringConverter::toString(bodyCount), 1); mBBSet->setDefaultDimensions(550.f*initialSize, 550.f*initialSize); mBBSet->setBillboardType(BBT_PERPENDICULAR_COMMON); mBBSet->setCommonDirection( -position.normalisedCopy() ); mBBSet->setVisibilityFlags(RV_Sky); mNode = rootNode->createChildSceneNode(); mNode->setPosition(finalPosition); mNode->attachObject(mBBSet); mBBSet->createBillboard(0,0,0); mBBSet->setCastShadows(false); mMaterial = MaterialManager::getSingleton().create("BillboardMaterial"+StringConverter::toString(bodyCount), ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME); mMaterial->removeAllTechniques(); Pass* p = mMaterial->createTechnique()->createPass(); p->setSceneBlending(SBT_TRANSPARENT_ALPHA); p->setDepthCheckEnabled(false); p->setDepthWriteEnabled(false); p->setSelfIllumination(1.0,1.0,1.0); p->setDiffuse(0.0,0.0,0.0,1.0); p->setAmbient(0.0,0.0,0.0); p->setPolygonModeOverrideable(false); p->createTextureUnitState(textureName); mBBSet->setMaterialName("BillboardMaterial"+StringConverter::toString(bodyCount)); HighLevelGpuProgramManager& mgr = HighLevelGpuProgramManager::getSingleton(); HighLevelGpuProgramPtr vshader; if (mgr.resourceExists("BBO_VP")) vshader = mgr.getByName("BBO_VP"); else vshader = mgr.createProgram("BBO_VP", ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, "cg", GPT_VERTEX_PROGRAM); vshader->setParameter("profiles", "vs_2_x arbvp1"); vshader->setParameter("entry_point", "main_vp"); StringUtil::StrStreamType outStream; outStream << "void main_vp( \n" " float4 position : POSITION, \n" " in float2 uv : TEXCOORD0, \n" " out float2 oUV : TEXCOORD0, \n" " out float4 oPosition : POSITION, \n" " uniform float4x4 worldViewProj \n" ") \n" "{ \n" " oUV = uv; \n" " oPosition = mul( worldViewProj, position ); \n" "}"; vshader->setSource(outStream.str()); vshader->load(); vshader->getDefaultParameters()->setNamedAutoConstant("worldViewProj", GpuProgramParameters::ACT_WORLDVIEWPROJ_MATRIX); mMaterial->getTechnique(0)->getPass(0)->setVertexProgram(vshader->getName()); HighLevelGpuProgramPtr fshader; if (mgr.resourceExists("BBO_FP")) fshader = mgr.getByName("BBO_FP"); else fshader = mgr.createProgram("BBO_FP", ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, "cg", GPT_FRAGMENT_PROGRAM); fshader->setParameter("profiles", "ps_2_x arbfp1"); fshader->setParameter("entry_point", "main_fp"); StringUtil::StrStreamType outStream2; outStream2 << "void main_fp( \n" " in float2 uv : TEXCOORD0, \n" " out float4 oColor : COLOR, \n"; if (RenderingManager::useMRT()) outStream2 << " out float4 oColor1 : COLOR1, \n"; outStream2 << " uniform sampler2D texture : TEXUNIT0, \n" " uniform float4 diffuse, \n" " uniform float4 emissive \n" ") \n" "{ \n" " float4 tex = tex2D(texture, uv); \n" " oColor = float4(emissive.xyz,1) * tex * float4(1,1,1,diffuse.a); \n"; if (RenderingManager::useMRT()) outStream2 << " oColor1 = float4(1, 0, 0, 1); \n"; outStream2 << "}"; fshader->setSource(outStream2.str()); fshader->load(); fshader->getDefaultParameters()->setNamedAutoConstant("diffuse", GpuProgramParameters::ACT_SURFACE_DIFFUSE_COLOUR); fshader->getDefaultParameters()->setNamedAutoConstant("emissive", GpuProgramParameters::ACT_SURFACE_EMISSIVE_COLOUR); mMaterial->getTechnique(0)->getPass(0)->setFragmentProgram(fshader->getName()); bodyCount++; }
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 SkyManager::create() { /// \todo preload all the textures and meshes that are used for sky rendering // Create overlay used for thunderstorm MaterialPtr material = MaterialManager::getSingleton().create( "ThunderMaterial", ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME ); Pass* pass = material->getTechnique(0)->getPass(0); pass->setSceneBlending(SBT_TRANSPARENT_ALPHA); mThunderTextureUnit = pass->createTextureUnitState(); mThunderTextureUnit->setColourOperationEx(LBX_SOURCE1, LBS_MANUAL, LBS_CURRENT, ColourValue(1.f, 1.f, 1.f)); mThunderTextureUnit->setAlphaOperation(LBX_SOURCE1, LBS_MANUAL, LBS_CURRENT, 0.5f); OverlayManager& ovm = OverlayManager::getSingleton(); mThunderOverlay = ovm.create( "ThunderOverlay" ); OverlayContainer* overlay_panel; overlay_panel = (OverlayContainer*)ovm.createOverlayElement("Panel", "ThunderPanel"); overlay_panel->_setPosition(0, 0); overlay_panel->_setDimensions(1, 1); overlay_panel->setMaterialName( "ThunderMaterial" ); overlay_panel->show(); mThunderOverlay->add2D(overlay_panel); mThunderOverlay->hide(); mSecunda = new Moon("textures\\tx_secunda_full.dds", 0.5, Vector3(-0.4, 0.4, 0.5), mRootNode); mSecunda->setType(Moon::Type_Secunda); mSecunda->setRenderQueue(RQG_SkiesEarly+4); mMasser = new Moon("textures\\tx_masser_full.dds", 0.75, Vector3(-0.4, 0.4, 0.5), mRootNode); mMasser->setRenderQueue(RQG_SkiesEarly+3); mMasser->setType(Moon::Type_Masser); mSun = new BillboardObject("textures\\tx_sun_05.dds", 1, Vector3(0.4, 0.4, 0.4), mRootNode); mSun->setRenderQueue(RQG_SkiesEarly+4); mSunGlare = new BillboardObject("textures\\tx_sun_flash_grey_05.dds", 3, Vector3(0.4, 0.4, 0.4), mRootNode); mSunGlare->setRenderQueue(RQG_SkiesLate); mSunGlare->setVisibilityFlags(RV_Glare); HighLevelGpuProgramManager& mgr = HighLevelGpuProgramManager::getSingleton(); // Stars /// \todo sky_night_02.nif (available in Bloodmoon) MeshPtr mesh = NifOgre::NIFLoader::load("meshes\\sky_night_01.nif"); Entity* night1_ent = mSceneMgr->createEntity("meshes\\sky_night_01.nif"); night1_ent->setRenderQueueGroup(RQG_SkiesEarly+1); night1_ent->setVisibilityFlags(RV_Sky); night1_ent->setCastShadows(false); mAtmosphereNight = mRootNode->createChildSceneNode(); mAtmosphereNight->attachObject(night1_ent); // Stars vertex shader HighLevelGpuProgramPtr stars_vp = mgr.createProgram("Stars_VP", ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, "cg", GPT_VERTEX_PROGRAM); stars_vp->setParameter("profiles", "vs_2_x arbvp1"); stars_vp->setParameter("entry_point", "main_vp"); StringUtil::StrStreamType outStream4; outStream4 << "void main_vp( \n" " float4 position : POSITION, \n" " in float2 uv : TEXCOORD0, \n" " out float2 oUV : TEXCOORD0, \n" " out float oFade : TEXCOORD1, \n" " out float4 oPosition : POSITION, \n" " uniform float4x4 worldViewProj \n" ") \n" "{ \n" " oUV = uv; \n" " oFade = (position.z > 50) ? 1.f : 0.f; \n" " oPosition = mul( worldViewProj, position ); \n" "}"; stars_vp->setSource(outStream4.str()); stars_vp->load(); stars_vp->getDefaultParameters()->setNamedAutoConstant("worldViewProj", GpuProgramParameters::ACT_WORLDVIEWPROJ_MATRIX); // Stars fragment shader HighLevelGpuProgramPtr stars_fp = mgr.createProgram("Stars_FP", ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, "cg", GPT_FRAGMENT_PROGRAM); stars_fp->setParameter("profiles", "ps_2_x arbfp1"); stars_fp->setParameter("entry_point", "main_fp"); StringUtil::StrStreamType outStream5; outStream5 << "void main_fp( \n" " in float2 uv : TEXCOORD0, \n" " out float4 oColor : COLOR, \n"; if (RenderingManager::useMRT()) outStream5 << " out float4 oColor1 : COLOR1, \n"; outStream5 << " in float fade : TEXCOORD1, \n" " uniform sampler2D texture : TEXUNIT0, \n" " uniform float opacity, \n" " uniform float4 diffuse, \n" " uniform float4 emissive \n" ") \n" "{ \n" " oColor = tex2D(texture, uv) * float4(emissive.xyz, 1) * float4(1,1,1,fade*diffuse.a); \n"; if (RenderingManager::useMRT()) outStream5 << " oColor1 = float4(1, 0, 0, 1); \n"; outStream5 << "}"; stars_fp->setSource(outStream5.str()); stars_fp->load(); stars_fp->getDefaultParameters()->setNamedAutoConstant("emissive", GpuProgramParameters::ACT_SURFACE_EMISSIVE_COLOUR); stars_fp->getDefaultParameters()->setNamedAutoConstant("diffuse", GpuProgramParameters::ACT_SURFACE_DIFFUSE_COLOUR); for (unsigned int i=0; i<night1_ent->getNumSubEntities(); ++i) { MaterialPtr mp = night1_ent->getSubEntity(i)->getMaterial(); mp->getTechnique(0)->getPass(0)->setSelfIllumination(1.0, 1.0, 1.0); mp->getTechnique(0)->getPass(0)->setAmbient(0.0, 0.0, 0.0); mp->getTechnique(0)->getPass(0)->setDiffuse(0.0, 0.0, 0.0, 1.0); mp->getTechnique(0)->getPass(0)->setDepthWriteEnabled(false); mp->getTechnique(0)->getPass(0)->setDepthCheckEnabled(false); mp->getTechnique(0)->getPass(0)->setSceneBlending(SBT_TRANSPARENT_ALPHA); mp->getTechnique(0)->getPass(0)->setVertexProgram(stars_vp->getName()); mp->getTechnique(0)->getPass(0)->setFragmentProgram(stars_fp->getName()); mp->getTechnique(0)->getPass(0)->setPolygonModeOverrideable(false); mStarsMaterials[i] = mp; } // Atmosphere (day) mesh = NifOgre::NIFLoader::load("meshes\\sky_atmosphere.nif"); Entity* atmosphere_ent = mSceneMgr->createEntity("meshes\\sky_atmosphere.nif"); atmosphere_ent->setCastShadows(false); ModVertexAlpha(atmosphere_ent, 0); atmosphere_ent->setRenderQueueGroup(RQG_SkiesEarly); atmosphere_ent->setVisibilityFlags(RV_Sky); mAtmosphereDay = mRootNode->createChildSceneNode(); mAtmosphereDay->attachObject(atmosphere_ent); mAtmosphereMaterial = atmosphere_ent->getSubEntity(0)->getMaterial(); mAtmosphereMaterial->getTechnique(0)->getPass(0)->setPolygonModeOverrideable(false); // Atmosphere shader HighLevelGpuProgramPtr vshader = mgr.createProgram("Atmosphere_VP", ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, "cg", GPT_VERTEX_PROGRAM); vshader->setParameter("profiles", "vs_2_x arbvp1"); vshader->setParameter("entry_point", "main_vp"); StringUtil::StrStreamType outStream; outStream << "void main_vp( \n" " float4 position : POSITION, \n" " in float4 color : COLOR, \n" " out float4 oPosition : POSITION, \n" " out float4 oVertexColor : TEXCOORD0, \n" " uniform float4x4 worldViewProj \n" ") \n" "{ \n" " oPosition = mul( worldViewProj, position ); \n" " oVertexColor = color; \n" "}"; vshader->setSource(outStream.str()); vshader->load(); vshader->getDefaultParameters()->setNamedAutoConstant("worldViewProj", GpuProgramParameters::ACT_WORLDVIEWPROJ_MATRIX); mAtmosphereMaterial->getTechnique(0)->getPass(0)->setVertexProgram(vshader->getName()); HighLevelGpuProgramPtr fshader = mgr.createProgram("Atmosphere_FP", ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, "cg", GPT_FRAGMENT_PROGRAM); fshader->setParameter("profiles", "ps_2_x arbfp1"); fshader->setParameter("entry_point", "main_fp"); StringUtil::StrStreamType _outStream; _outStream << "void main_fp( \n" " in float4 iVertexColor : TEXCOORD0, \n" " out float4 oColor : COLOR, \n"; if (RenderingManager::useMRT()) _outStream << " out float4 oColor1 : COLOR1, \n"; _outStream << " uniform float4 emissive \n" ") \n" "{ \n" " oColor = iVertexColor * emissive; \n"; if (RenderingManager::useMRT()) _outStream << " oColor1 = float4(1, 0, 0, 1); \n"; _outStream << "}"; fshader->setSource(_outStream.str()); fshader->load(); fshader->getDefaultParameters()->setNamedAutoConstant("emissive", GpuProgramParameters::ACT_SURFACE_EMISSIVE_COLOUR); mAtmosphereMaterial->getTechnique(0)->getPass(0)->setFragmentProgram(fshader->getName()); // Clouds NifOgre::NIFLoader::load("meshes\\sky_clouds_01.nif"); Entity* clouds_ent = mSceneMgr->createEntity("meshes\\sky_clouds_01.nif"); clouds_ent->setVisibilityFlags(RV_Sky); clouds_ent->setRenderQueueGroup(RQG_SkiesEarly+5); SceneNode* clouds_node = mRootNode->createChildSceneNode(); clouds_node->attachObject(clouds_ent); mCloudMaterial = clouds_ent->getSubEntity(0)->getMaterial(); mCloudMaterial->getTechnique(0)->getPass(0)->setPolygonModeOverrideable(false); clouds_ent->setCastShadows(false); // Clouds vertex shader HighLevelGpuProgramPtr vshader2 = mgr.createProgram("Clouds_VP", ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, "cg", GPT_VERTEX_PROGRAM); vshader2->setParameter("profiles", "vs_2_x arbvp1"); vshader2->setParameter("entry_point", "main_vp"); StringUtil::StrStreamType outStream3; outStream3 << "void main_vp( \n" " float4 position : POSITION, \n" " in float4 color : COLOR, \n" " out float4 oColor : TEXCOORD1, \n" " in float2 uv : TEXCOORD0, \n" " out float2 oUV : TEXCOORD0, \n" " out float4 oPosition : POSITION, \n" " uniform float4x4 worldViewProj \n" ") \n" "{ \n" " oUV = uv; \n" " oColor = color; \n" " oPosition = mul( worldViewProj, position ); \n" "}"; vshader2->setSource(outStream3.str()); vshader2->load(); vshader2->getDefaultParameters()->setNamedAutoConstant("worldViewProj", GpuProgramParameters::ACT_WORLDVIEWPROJ_MATRIX); mCloudMaterial->getTechnique(0)->getPass(0)->setVertexProgram(vshader2->getName()); // Clouds fragment shader mCloudFragmentShader = mgr.createProgram("Clouds_FP", ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, "cg", GPT_FRAGMENT_PROGRAM); mCloudFragmentShader->setParameter("profiles", "ps_2_x arbfp1"); mCloudFragmentShader->setParameter("entry_point", "main_fp"); StringUtil::StrStreamType outStream2; outStream2 << "void main_fp( \n" " in float2 uv : TEXCOORD0, \n" " in float4 color : TEXCOORD1, \n" " out float4 oColor : COLOR, \n"; if (RenderingManager::useMRT()) outStream2 << " out float4 oColor1 : COLOR1, \n"; outStream2 << " uniform sampler2D texture : TEXUNIT0, \n" " uniform sampler2D secondTexture : TEXUNIT1, \n" " uniform float transitionFactor, \n" " uniform float time, \n" " uniform float speed, \n" " uniform float opacity, \n" " uniform float4 emissive \n" ") \n" "{ \n" " uv += float2(0,1) * time * speed * 0.003; \n" // Scroll in y direction " float4 tex = lerp(tex2D(texture, uv), tex2D(secondTexture, uv), transitionFactor); \n" " oColor = color * float4(emissive.xyz,1) * tex * float4(1,1,1,opacity); \n"; if (RenderingManager::useMRT()) outStream2 << " oColor1 = float4(1, 0, 0, 1); \n"; outStream2 << "}"; mCloudFragmentShader->setSource(outStream2.str()); mCloudFragmentShader->load(); mCloudFragmentShader->getDefaultParameters()->setNamedAutoConstant("emissive", GpuProgramParameters::ACT_SURFACE_EMISSIVE_COLOUR); mCloudMaterial->getTechnique(0)->getPass(0)->setFragmentProgram(mCloudFragmentShader->getName()); setCloudsOpacity(0.75); ModVertexAlpha(clouds_ent, 1); // I'm not sure if the materials are being used by any other objects // Make a unique "modifiable" copy of the materials to be sure mCloudMaterial = mCloudMaterial->clone("Clouds"); clouds_ent->getSubEntity(0)->setMaterial(mCloudMaterial); mAtmosphereMaterial = mAtmosphereMaterial->clone("Atmosphere"); atmosphere_ent->getSubEntity(0)->setMaterial(mAtmosphereMaterial); mAtmosphereMaterial->getTechnique(0)->getPass(0)->setSelfIllumination(1.0, 1.0, 1.0); mAtmosphereMaterial->getTechnique(0)->getPass(0)->setDiffuse(0.0, 0.0, 0.0, 0.0); mAtmosphereMaterial->getTechnique(0)->getPass(0)->setAmbient(0.0, 0.0, 0.0); mCloudMaterial->getTechnique(0)->getPass(0)->setSelfIllumination(1.0, 1.0, 1.0); mCloudMaterial->getTechnique(0)->getPass(0)->setDepthWriteEnabled(false); mAtmosphereMaterial->getTechnique(0)->getPass(0)->setDepthWriteEnabled(false); mAtmosphereMaterial->getTechnique(0)->getPass(0)->setSceneBlending(SBT_TRANSPARENT_ALPHA); mCloudMaterial->getTechnique(0)->getPass(0)->setSceneBlending(SBT_TRANSPARENT_ALPHA); mCloudMaterial->getTechnique(0)->getPass(0)->removeAllTextureUnitStates(); mCloudMaterial->getTechnique(0)->getPass(0)->createTextureUnitState("textures\\tx_sky_cloudy.dds"); mCloudMaterial->getTechnique(0)->getPass(0)->createTextureUnitState(""); mCreated = true; }
Moon::Moon( const String& textureName, const float initialSize, const Vector3& position, SceneNode* rootNode) { init(textureName, initialSize, position, rootNode); HighLevelGpuProgramManager& mgr = HighLevelGpuProgramManager::getSingleton(); HighLevelGpuProgramPtr vshader; if (mgr.resourceExists("Moon_VP")) vshader = mgr.getByName("Moon_VP"); else vshader = mgr.createProgram("Moon_VP", ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, "cg", GPT_VERTEX_PROGRAM); vshader->setParameter("profiles", "vs_2_x arbvp1"); vshader->setParameter("entry_point", "main_vp"); StringUtil::StrStreamType outStream; outStream << "void main_vp( \n" " float4 position : POSITION, \n" " in float2 uv : TEXCOORD0, \n" " out float2 oUV : TEXCOORD0, \n" " out float4 oPosition : POSITION, \n" " uniform float4x4 worldViewProj \n" ") \n" "{ \n" " oUV = uv; \n" " oPosition = mul( worldViewProj, position ); \n" "}"; vshader->setSource(outStream.str()); vshader->load(); vshader->getDefaultParameters()->setNamedAutoConstant("worldViewProj", GpuProgramParameters::ACT_WORLDVIEWPROJ_MATRIX); mMaterial->getTechnique(0)->getPass(0)->setVertexProgram(vshader->getName()); HighLevelGpuProgramPtr fshader; if (mgr.resourceExists("Moon_FP")) fshader = mgr.getByName("Moon_FP"); else fshader = mgr.createProgram("Moon_FP", ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, "cg", GPT_FRAGMENT_PROGRAM); fshader->setParameter("profiles", "ps_2_x arbfp1"); fshader->setParameter("entry_point", "main_fp"); StringUtil::StrStreamType outStream2; outStream2 << "void main_fp( \n" " in float2 uv : TEXCOORD0, \n" " out float4 oColor : COLOR, \n"; if (RenderingManager::useMRT()) outStream2 << " out float4 oColor1 : COLOR1, \n"; outStream2 << " uniform sampler2D texture : TEXUNIT0, \n" " uniform float4 skyColour, \n" " uniform float4 diffuse, \n" " uniform float4 emissive \n" ") \n" "{ \n" " float4 tex = tex2D(texture, uv); \n" " oColor = float4(emissive.xyz,1) * tex; \n"; if (RenderingManager::useMRT()) outStream2 << " oColor1 = float4(1, 0, 0, 1); \n"; outStream2 << // use a circle for the alpha (compute UV distance to center) // looks a bit bad because its not filtered on the edges, // but it's cheaper than a seperate alpha texture. " float sqrUVdist = pow(uv.x-0.5,2) + pow(uv.y-0.5, 2); \n" " oColor.a = diffuse.a * (sqrUVdist >= 0.24 ? 0 : 1); \n" " oColor.rgb += (1-tex.a) * oColor.a * skyColour.rgb; \n"//fill dark side of moon with skycolour " oColor.rgb += (1-diffuse.a) * skyColour.rgb; \n"//fade bump "}"; fshader->setSource(outStream2.str()); fshader->load(); fshader->getDefaultParameters()->setNamedAutoConstant("diffuse", GpuProgramParameters::ACT_SURFACE_DIFFUSE_COLOUR); fshader->getDefaultParameters()->setNamedAutoConstant("emissive", GpuProgramParameters::ACT_SURFACE_EMISSIVE_COLOUR); mMaterial->getTechnique(0)->getPass(0)->setFragmentProgram(fshader->getName()); setVisibility(1.0); mPhase = Moon::Phase_Full; }
//--------------------------------------------------------------------- FixedFuncPrograms * FixedFuncEmuShaderManager::_createShaderPrograms( const String & generatorName, const VertexBufferDeclaration & vertexBufferDeclaration, FixedFuncState & fixedFuncState ) { const String vertexProgramName = "VS"; const String fragmentProgramName = "FP"; FixedFuncEmuShaderGenerator * fixedFuncEmuShaderGenerator = mFixedFuncEmuShaderGeneratorMap[generatorName]; String shaderSource = fixedFuncEmuShaderGenerator->getShaderSource( vertexProgramName, fragmentProgramName, vertexBufferDeclaration, fixedFuncState ); // Vertex program details GpuProgramUsage * vertexProgramUsage = new GpuProgramUsage(GPT_VERTEX_PROGRAM); // Fragment program details GpuProgramUsage * fragmentProgramUsage = new GpuProgramUsage(GPT_FRAGMENT_PROGRAM); HighLevelGpuProgramPtr vs; HighLevelGpuProgramPtr fs; class LoadFromSourceGpuProgram : public HighLevelGpuProgram { public: void doLoadFromSource(void) { loadFromSource(); }; }; static size_t shaderCount = 0; shaderCount++; vs = HighLevelGpuProgramManager::getSingleton(). createProgram("VS_" + StringConverter::toString(shaderCount), ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, fixedFuncEmuShaderGenerator->getLanguageName(), GPT_VERTEX_PROGRAM); vs->setSource(shaderSource); vs->setParameter("entry_point",vertexProgramName); vs->setParameter("target",fixedFuncEmuShaderGenerator->getVpTarget()); static_cast<LoadFromSourceGpuProgram *>(vs.get())->doLoadFromSource(); vertexProgramUsage->setProgram(GpuProgramPtr(vs)); vertexProgramUsage->setParameters(vs->createParameters()); fs = HighLevelGpuProgramManager::getSingleton(). createProgram("FS_" + StringConverter::toString(shaderCount), ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, fixedFuncEmuShaderGenerator->getLanguageName(), GPT_FRAGMENT_PROGRAM); fs->setSource(shaderSource); fs->setParameter("entry_point",fragmentProgramName); fs->setParameter("target",fixedFuncEmuShaderGenerator->getFpTarget()); static_cast<LoadFromSourceGpuProgram *>(fs.get())->doLoadFromSource(); fragmentProgramUsage->setProgram(GpuProgramPtr(fs)); fragmentProgramUsage->setParameters(fs->createParameters()); FixedFuncPrograms * newPrograms = fixedFuncEmuShaderGenerator->createFixedFuncPrograms(); mLanguage2State2Declaration2ProgramsMap[generatorName][fixedFuncState][vertexBufferDeclaration] = newPrograms; newPrograms->setVertexProgramUsage(vertexProgramUsage); newPrograms->setFragmentProgramUsage(fragmentProgramUsage); newPrograms->setFixedFuncState(fixedFuncState); mProgramsToDeleteAtTheEnd.push_back(newPrograms); return newPrograms; }
//----------------------------------------------------------------------------- GpuProgramPtr ProgramManager::createGpuProgram(Program* shaderProgram, ProgramWriter* programWriter, const String& language, const String& profiles, const StringVector& profilesList, const String& cachePath) { #if OGRE_PLATFORM == OGRE_PLATFORM_ANDROID Ogre::StringSerialiser sourceCodeStringStream; #else std::stringstream sourceCodeStringStream; #endif _StringHash stringHash; uint32 programHashCode; String programName; // Generate source code. programWriter->writeSourceCode(sourceCodeStringStream, shaderProgram); // Generate program hash code. programHashCode = static_cast<uint32>(stringHash(sourceCodeStringStream.str())); // Generate program name. programName = StringConverter::toString(programHashCode); if (shaderProgram->getType() == GPT_VERTEX_PROGRAM) { programName += "_VS"; } else if (shaderProgram->getType() == GPT_FRAGMENT_PROGRAM) { programName += "_FS"; } HighLevelGpuProgramPtr pGpuProgram; // Try to get program by name. pGpuProgram = HighLevelGpuProgramManager::getSingleton().getByName(programName); // Case the program doesn't exist yet. if (pGpuProgram.isNull()) { // Create new GPU program. pGpuProgram = HighLevelGpuProgramManager::getSingleton().createProgram(programName, ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, language, shaderProgram->getType()); // Case cache directory specified -> create program from file. if (cachePath.empty() == false) { const String programFullName = programName + "." + language; const String programFileName = cachePath + programFullName; std::ifstream programFile; bool writeFile = true; // Check if program file already exist. programFile.open(programFileName.c_str()); // Case no matching file found -> we have to write it. if (!programFile) { writeFile = true; } else { writeFile = false; programFile.close(); } // Case we have to write the program to a file. if (writeFile) { std::ofstream outFile(programFileName.c_str()); if (!outFile) return GpuProgramPtr(); outFile << sourceCodeStringStream.str(); outFile.close(); } pGpuProgram->setSourceFile(programFullName); } // No cache directory specified -> create program from system memory. else { pGpuProgram->setSource(sourceCodeStringStream.str()); } pGpuProgram->setParameter("entry_point", shaderProgram->getEntryPointFunction()->getName()); // HLSL program requires specific target profile settings - we have to split the profile string. if (language == "hlsl") { StringVector::const_iterator it = profilesList.begin(); StringVector::const_iterator itEnd = profilesList.end(); for (; it != itEnd; ++it) { if (GpuProgramManager::getSingleton().isSyntaxSupported(*it)) { pGpuProgram->setParameter("target", *it); break; } } } pGpuProgram->setParameter("profiles", profiles); pGpuProgram->load(); // Case an error occurred. if (pGpuProgram->hasCompileError()) { pGpuProgram.setNull(); return GpuProgramPtr(pGpuProgram); } // Add the created GPU program to local cache. if (pGpuProgram->getType() == GPT_VERTEX_PROGRAM) { mVertexShaderMap[programName] = pGpuProgram; } else if (pGpuProgram->getType() == GPT_FRAGMENT_PROGRAM) { mFragmentShaderMap[programName] = pGpuProgram; } } return GpuProgramPtr(pGpuProgram); }
//----------------------------------------------------------------------------------- Ogre::GpuProgramPtr ShaderManager::getGpuProgram(HlmsDatablock* dataBlock) { Ogre::uint32 hash = dataBlock->getHash(); std::map<Ogre::uint32, Ogre::GpuProgramPtr>::iterator it = mShaderCache.find(hash); if (it != mShaderCache.end()) { return (*it).second; } else { Ogre::String typeStr = FilePatterns[dataBlock->getShaderType()]; std::stringstream sstream; sstream << std::hex << hash; std::string hashString = sstream.str(); Ogre::String name = hashString + typeStr; // generate the shader code Ogre::String code = dataBlock->getTemplate()->getTemplate(); code = ShaderGenerator::parse(code, *(dataBlock->getPropertyMap()), mShaderPiecesManager->getPieces(dataBlock->getLanguarge(), dataBlock->getShaderType())); HighLevelGpuProgramPtr gpuProgram = Ogre::HighLevelGpuProgramManager::getSingleton().createProgram(name, Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, dataBlock->getLanguarge(), dataBlock->getShaderType()); gpuProgram->setSource(code); gpuProgram->setParameter("entry_point", "main"); if (dataBlock->getLanguarge() == "hlsl") { // HLSL program requires specific target profile settings - we have to split the profile string. const Ogre::StringVector& profilesList = dataBlock->getProfileList(); Ogre::StringVector::const_iterator it = profilesList.begin(); Ogre::StringVector::const_iterator itEnd = profilesList.end(); for (; it != itEnd; ++it) { if (Ogre::GpuProgramManager::getSingleton().isSyntaxSupported(*it)) { gpuProgram->setParameter("target", *it); break; } } //gpuProgram->setParameter("enable_backwards_compatibility", "false"); //gpuProgram->setParameter("column_major_matrices", Ogre::StringConverter::toString(shaderProgram->getUseColumnMajorMatrices())); } //gpuProgram->setParameter("profiles", profiles); gpuProgram->load(); // Case an error occurred. if (gpuProgram->hasCompileError()) { gpuProgram.setNull(); return Ogre::GpuProgramPtr(gpuProgram); } mShaderCache[hash] = gpuProgram; return gpuProgram; } }
//--------------------------------------------------------------------- //--------------------------------------------------------------------- void ShadowVolumeExtrudeProgram::initialise(void) { if (!mInitialised) { String syntax; bool vertexProgramFinite[OGRE_NUM_SHADOW_EXTRUDER_PROGRAMS] = { false, false, false, false, true, true, true, true }; bool vertexProgramDebug[OGRE_NUM_SHADOW_EXTRUDER_PROGRAMS] = { false, true, false, true, false, true, false, true }; Light::LightTypes vertexProgramLightTypes[OGRE_NUM_SHADOW_EXTRUDER_PROGRAMS] = { Light::LT_POINT, Light::LT_POINT, Light::LT_DIRECTIONAL, Light::LT_DIRECTIONAL, Light::LT_POINT, Light::LT_POINT, Light::LT_DIRECTIONAL, Light::LT_DIRECTIONAL }; // load hardware extrusion programs for point & dir lights if (GpuProgramManager::getSingleton().isSyntaxSupported("arbvp1")) { // ARBvp1 syntax = "arbvp1"; } else if (GpuProgramManager::getSingleton().isSyntaxSupported("vs_1_1")) { syntax = "vs_1_1"; } else if (GpuProgramManager::getSingleton().isSyntaxSupported("vs_4_0")) { syntax = "vs_4_0"; } else { OGRE_EXCEPT(Exception::ERR_INTERNAL_ERROR, "Vertex programs are supposedly supported, but neither " "arbvp1, vs_1_1 nor vs_4_0 syntaxes are present.", "SceneManager::initShadowVolumeMaterials"); } // Create all programs for (unsigned short v = 0; v < OGRE_NUM_SHADOW_EXTRUDER_PROGRAMS; ++v) { // Create debug extruders if (GpuProgramManager::getSingleton().getByName( programNames[v]).isNull()) { if (syntax == "vs_4_0") { HighLevelGpuProgramPtr vp = HighLevelGpuProgramManager::getSingleton().createProgram( programNames[v], ResourceGroupManager::INTERNAL_RESOURCE_GROUP_NAME, "hlsl", GPT_VERTEX_PROGRAM); vp->setSource(ShadowVolumeExtrudeProgram::getProgramSource( vertexProgramLightTypes[v], syntax, vertexProgramFinite[v], vertexProgramDebug[v])); vp->setParameter("target", syntax); vp->setParameter("entry_point", "vs_main"); vp->load(); if (frgProgramName.empty()) { frgProgramName = "Ogre/ShadowFrgProgram"; HighLevelGpuProgramPtr fp = HighLevelGpuProgramManager::getSingleton().createProgram( frgProgramName, ResourceGroupManager::INTERNAL_RESOURCE_GROUP_NAME, "hlsl", GPT_FRAGMENT_PROGRAM); fp->setSource(mGeneralFs_4_0); fp->setParameter("target", "ps_4_0"); fp->setParameter("entry_point", "fs_main"); fp->load(); } } else { GpuProgramPtr vp = GpuProgramManager::getSingleton().createProgramFromString( programNames[v], ResourceGroupManager::INTERNAL_RESOURCE_GROUP_NAME, ShadowVolumeExtrudeProgram::getProgramSource( vertexProgramLightTypes[v], syntax, vertexProgramFinite[v], vertexProgramDebug[v]), GPT_VERTEX_PROGRAM, syntax); vp->load(); } } } mInitialised = true; } }
//--------------------------------------------------------------------- void TerrainMaterialGeneratorA::SM2Profile::addTechnique( const MaterialPtr& mat, const Terrain* terrain, TechniqueType tt) { Technique* tech = mat->createTechnique(); // Only supporting one pass Pass* pass = tech->createPass(); GpuProgramManager& gmgr = GpuProgramManager::getSingleton(); HighLevelGpuProgramManager& hmgr = HighLevelGpuProgramManager::getSingleton(); if (!mShaderGen) { bool check2x = mLayerNormalMappingEnabled || mLayerParallaxMappingEnabled; if (hmgr.isLanguageSupported("cg")) { mShaderGen = OGRE_NEW ShaderHelperCg(); } else if (hmgr.isLanguageSupported("hlsl") && ((check2x && gmgr.isSyntaxSupported("ps_4_0")) || (check2x && gmgr.isSyntaxSupported("ps_2_x")) || (!check2x && gmgr.isSyntaxSupported("ps_2_0")))) { mShaderGen = OGRE_NEW ShaderHelperHLSL(); } else if (hmgr.isLanguageSupported("glsl")) { mShaderGen = OGRE_NEW ShaderHelperGLSL(); } else if (hmgr.isLanguageSupported("glsles")) { mShaderGen = OGRE_NEW ShaderHelperGLSLES(); } // check SM3 features mSM3Available = GpuProgramManager::getSingleton().isSyntaxSupported("ps_3_0"); mSM4Available = GpuProgramManager::getSingleton().isSyntaxSupported("ps_4_0"); } HighLevelGpuProgramPtr vprog = mShaderGen->generateVertexProgram(this, terrain, tt); HighLevelGpuProgramPtr fprog = mShaderGen->generateFragmentProgram(this, terrain, tt); pass->setVertexProgram(vprog->getName()); pass->setFragmentProgram(fprog->getName()); if (tt == HIGH_LOD || tt == RENDER_COMPOSITE_MAP) { // global normal map TextureUnitState* tu = pass->createTextureUnitState(); tu->setTextureName(terrain->getTerrainNormalMap()->getName()); tu->setTextureAddressingMode(TextureUnitState::TAM_CLAMP); // global colour map if (terrain->getGlobalColourMapEnabled() && isGlobalColourMapEnabled()) { tu = pass->createTextureUnitState(terrain->getGlobalColourMap()->getName()); tu->setTextureAddressingMode(TextureUnitState::TAM_CLAMP); } // light map if (isLightmapEnabled()) { tu = pass->createTextureUnitState(terrain->getLightmap()->getName()); tu->setTextureAddressingMode(TextureUnitState::TAM_CLAMP); } // blend maps uint maxLayers = getMaxLayers(terrain); uint numBlendTextures = std::min(terrain->getBlendTextureCount(maxLayers), terrain->getBlendTextureCount()); uint numLayers = std::min(maxLayers, static_cast<uint>(terrain->getLayerCount())); for (uint i = 0; i < numBlendTextures; ++i) { tu = pass->createTextureUnitState(terrain->getBlendTextureName(i)); tu->setTextureAddressingMode(TextureUnitState::TAM_CLAMP); } // layer textures for (uint i = 0; i < numLayers; ++i) { // diffuse / specular pass->createTextureUnitState(terrain->getLayerTextureName(i, 0)); // normal / height pass->createTextureUnitState(terrain->getLayerTextureName(i, 1)); } } else { // LOW_LOD textures // composite map TextureUnitState* tu = pass->createTextureUnitState(); tu->setTextureName(terrain->getCompositeMap()->getName()); tu->setTextureAddressingMode(TextureUnitState::TAM_CLAMP); // That's it! } // Add shadow textures (always at the end) if (isShadowingEnabled(tt, terrain)) { uint numTextures = 1; if (getReceiveDynamicShadowsPSSM()) { numTextures = (uint)getReceiveDynamicShadowsPSSM()->getSplitCount(); } for (uint i = 0; i < numTextures; ++i) { TextureUnitState* tu = pass->createTextureUnitState(); tu->setContentType(TextureUnitState::CONTENT_SHADOW); tu->setTextureAddressingMode(TextureUnitState::TAM_BORDER); tu->setTextureBorderColour(ColourValue::White); } } }
void GrassLayer::_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; HighLevelGpuProgramPtr vertexShader = HighLevelGpuProgramManager::getSingleton().getByName(vsName); if (vertexShader.isNull()) { if (Root::getSingleton().getRenderSystem()->getName() == "Direct3D9 Rendering Subsystem") shaderLanguage = "hlsl"; else if(Root::getSingleton().getRenderSystem()->getName() == "OpenGL Rendering Subsystem") shaderLanguage = "glsl"; else shaderLanguage = "cg"; //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" " gl_FogFragCoord = gl_Position.z; \n" "}"; } 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). //Apply the shader to the material Pass *pass = tmpMat->getTechnique(0)->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->setNamedAutoConstant("time", GpuProgramParameters::ACT_CUSTOM, 1); params->setNamedAutoConstant("frequency", GpuProgramParameters::ACT_CUSTOM, 1); params->setNamedAutoConstant("direction", GpuProgramParameters::ACT_CUSTOM, 4); } 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->setNamedAutoConstant("grassHeight", GpuProgramParameters::ACT_CUSTOM, 1); 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; } } }
void ImpostorMaterialGenerator::generate() { //! // note that we only create the shaders (Sprite_vp, Sprite_fp) here. // the rest (material creation, shader parameters, ...) is done by paged-geom for convenience. HighLevelGpuProgramManager& mgr = HighLevelGpuProgramManager::getSingleton(); // ---------------- VERTEX ----------------------------------------------- // ensure shader does not exist already. HighLevelGpuProgramPtr vshader = mgr.getByName("Sprite_vp"); if (vshader.isNull()) { vshader = mgr.createProgram("Sprite_vp", ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, "cg", GPT_VERTEX_PROGRAM); if(MRTSupported()) { vshader->setParameter("profiles", "vs_4_0 vs_3_0 vp40"); } else { vshader->setParameter("profiles", "vs_4_0 vs_2_x arbvp1"); } vshader->setParameter("entry_point", "Sprite_vp"); StringUtil::StrStreamType outStream; outStream << "void Sprite_vp( \n" " float4 position : POSITION, \n" " float3 normal : NORMAL, \n" " float4 color : COLOR, \n" " float2 uv : TEXCOORD0, \n" " out float4 oPosition : POSITION, \n" " out float2 oUv : TEXCOORD0, \n" " out float4 oColor : COLOR, \n" " out float oFog : TEXCOORD1, \n" " uniform float4 fogParams, \n" " uniform float4x4 worldViewProj, \n" " uniform float uScroll, \n" " uniform float vScroll, \n" " uniform float4 preRotatedQuad[4] ) \n" "{ \n" //Face the camera " float4 vCenter = float4( position.x, position.y, position.z, 1.0f ); \n" " float4 vScale = float4( normal.x, normal.y, normal.x, 1.0f ); \n" " oPosition = mul( worldViewProj, vCenter + (preRotatedQuad[normal.z] * vScale) ); \n" //Color " oColor = color; \n" //UV Scroll " oUv = uv; \n" " oUv.x += uScroll; \n" " oUv.y += vScroll; \n" //Fog " oFog = saturate(fogParams.x * (oPosition.z - fogParams.y) * fogParams.w); \n" "}"; vshader->setSource(outStream.str()); vshader->load(); vshader->getDefaultParameters()->setNamedAutoConstant("fogParams", GpuProgramParameters::ACT_FOG_PARAMS); } // ------------- FRAGMENT ----------------------------------------------- // ensure shader does not exist already. HighLevelGpuProgramPtr fshader = mgr.getByName("Sprite_fp"); if (fshader.isNull()) { fshader = mgr.createProgram("Sprite_fp", ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, "cg", GPT_FRAGMENT_PROGRAM); if(MRTSupported()) { fshader->setParameter("profiles", "ps_4_0 ps_3_0 fp40"); } else { fshader->setParameter("profiles", "ps_4_0 ps_2_x arbfp1"); } fshader->setParameter("entry_point", "Sprite_fp"); // simple pixel shader that only reads texture and fog StringUtil::StrStreamType outStream; outStream << "void Sprite_fp( \n" " uniform sampler2D texture, \n" " float4 iPosition : POSITION, \n" " float2 texCoord : TEXCOORD0, \n" " float4 iColor : COLOR, \n" " float fog : TEXCOORD1, \n" " uniform float4 fogColor, \n" " out float4 oColor : COLOR \n" ") \n" "{ \n" " float4 texColor = tex2D(texture, texCoord); \n" " oColor = float4(lerp(texColor.xyz, fogColor.xyz, fog), texColor.a); \n" " clip( oColor.a > 0.0f ? 1:-1); \n" "} \n"; fshader->setSource(outStream.str()); fshader->load(); fshader->getDefaultParameters()->setNamedAutoConstant("fogColor", GpuProgramParameters::ACT_FOG_COLOUR); } }