int GameScript::getSafeTextureUnitState(TextureUnitState **tu, const String materialName, int techniqueNum, int passNum, int textureUnitNum) { try { MaterialPtr m = MaterialManager::getSingleton().getByName(materialName); if (m.isNull()) return 1; // verify technique if (techniqueNum < 0 || techniqueNum > m->getNumTechniques()) return 2; Technique *t = m->getTechnique(techniqueNum); if (!t) return 2; //verify pass if (passNum < 0 || passNum > t->getNumPasses()) return 3; Pass *p = t->getPass(passNum); if (!p) return 3; //verify texture unit if (textureUnitNum < 0 || textureUnitNum > p->getNumTextureUnitStates()) return 4; TextureUnitState *tut = p->getTextureUnitState(textureUnitNum); if (!tut) return 4; *tu = tut; return 0; } catch(Exception e) { SLOG("Exception in getSafeTextureUnitState(): " + e.getFullDescription()); } return 1; }
//----------------------------------------------------------------------------- /// void BatchPage::build() { m_pBatchGeom->build(); BatchedGeometry::TSubBatchIterator it = m_pBatchGeom->getSubBatchIterator(); while (it.hasMoreElements()) { BatchedGeometry::SubBatch *subBatch = it.getNext(); const MaterialPtr &ptrMat = subBatch->getMaterial(); //Disable specular unless a custom shader is being used. //This is done because the default shader applied by BatchPage //doesn't support specular, and fixed-function needs to look //the same as the shader (for computers with no shader support) for (unsigned short t = 0, tCnt = ptrMat->getNumTechniques(); t < tCnt; ++t) { Technique *tech = ptrMat->getTechnique(t); for (unsigned short p = 0, pCnt = tech->getNumPasses(); p < pCnt; ++p) { Pass *pass = tech->getPass(p); //if (pass->getVertexProgramName() == "") // pass->setSpecular(0, 0, 0, 1); if (!pass->hasVertexProgram()) pass->setSpecular(0.f, 0.f, 0.f, 1.f); } } //Store the original materials m_vecUnfadedMaterials.push_back(subBatch->getMaterial()); } _updateShaders(); }
void BatchPage::build() { batch->build(); BatchedGeometry::SubBatchIterator it = batch->getSubBatchIterator(); while (it.hasMoreElements()){ BatchedGeometry::SubBatch *subBatch = it.getNext(); MaterialPtr mat = subBatch->getMaterial(); //Disable specular unless a custom shader is being used. //This is done because the default shader applied by BatchPage //doesn't support specular, and fixed-function needs to look //the same as the shader (for computers with no shader support) for (int t = 0; t < mat->getNumTechniques(); ++t){ Technique *tech = mat->getTechnique(t); for (int p = 0; p < tech->getNumPasses(); ++p){ Pass *pass = tech->getPass(p); if (pass->getVertexProgramName() == "") pass->setSpecular(0, 0, 0, 1); } } //Store the original materials unfadedMaterials.push_back(subBatch->getMaterial()); } _updateShaders(); }
//-------------------------------------------------------------------------------- void MaterialUtil::setColor(const MaterialPtr& _material, const ColourValue& _color) { Technique* technique = _material->getTechnique(0); Pass* pass = technique->getPass(0); pass->setDiffuse( _color ); pass->setAmbient( _color ); }
//----------------------------------------------------------------------- void DeferredLightRenderOperation::execute(SceneManager *sm, RenderSystem *rs) { Ogre::Camera* cam = mViewport->getCamera(); mAmbientLight->updateFromCamera(cam); Technique* tech = mAmbientLight->getMaterial()->getBestTechnique(); injectTechnique(sm, tech, mAmbientLight, 0); const LightList& lightList = sm->_getLightsAffectingFrustum(); for (LightList::const_iterator it = lightList.begin(); it != lightList.end(); it++) { Light* light = *it; Ogre::LightList ll; ll.push_back(light); //if (++i != 2) continue; //if (light->getType() != Light::LT_DIRECTIONAL) continue; //if (light->getDiffuseColour() != ColourValue::Red) continue; LightsMap::iterator dLightIt = mLights.find(light); DLight* dLight = 0; if (dLightIt == mLights.end()) { dLight = createDLight(light); } else { dLight = dLightIt->second; dLight->updateFromParent(); } dLight->updateFromCamera(cam); tech = dLight->getMaterial()->getBestTechnique(); //Update shadow texture if (dLight->getCastChadows()) { SceneManager::RenderContext* context = sm->_pauseRendering(); sm->prepareShadowTextures(cam, mViewport, &ll); sm->_resumeRendering(context); Pass* pass = tech->getPass(0); TextureUnitState* tus = pass->getTextureUnitState("ShadowMap"); assert(tus); const TexturePtr& shadowTex = sm->getShadowTexture(0); if (tus->_getTexturePtr() != shadowTex) { tus->_setTexturePtr(shadowTex); } } injectTechnique(sm, tech, dLight, &ll); } }
//-------------------------------------------------------------------------------- static void setTextureAndTexAniFPS(const MaterialPtr& _material, const String& _texture, Real _texAniFPS) { Technique* technique = _material->getTechnique(0); Pass* pass = technique->getPass(0); if(_texture.empty()) { pass->removeAllTextureUnitStates(); } else { TextureManager& tmgr = TextureManager::getSingleton(); Ogre::TextureUnitState* tus = pass->getNumTextureUnitStates() ? pass->getTextureUnitState(0) : pass->createTextureUnitState(); if(_texAniFPS == 0) { TexturePtr ogreTexture = tmgr.createOrRetrieve(_texture).first; const String& ogreTexName = ogreTexture->getName(); tus->setTextureName(ogreTexName); } else { vector<String>::type ogreTexNames; TexturePtr ogreTexture = tmgr.createOrRetrieve(_texture).first; ogreTexNames.push_back(ogreTexture->getName()); size_t dotpos = _texture.rfind('.'); if(dotpos != String::npos && dotpos >= 1 && '0' <= _texture[dotpos-1] && _texture[dotpos-1] < '9') { String tmpname = _texture; char& dig0 = tmpname[dotpos - 1]; ++dig0; while(!tmgr.getByName(tmpname).isNull() || tmgr.canLoadResource(tmpname, TextureManager::GROUP_NAME)) { TexturePtr ogreTexture = tmgr.createOrRetrieve(tmpname).first; ogreTexNames.push_back(ogreTexture->getName()); ++dig0; if(dig0 > '9') { if(dotpos >= 2 && '0' <= _texture[dotpos-2] && _texture[dotpos-2] < '9') { char& dig1 = tmpname[dotpos-2]; ++dig1; dig0 = '0'; } else break; } } } Real duration = ogreTexNames.size() / _texAniFPS; tus->setAnimatedTextureName(&ogreTexNames[0], ogreTexNames.size(), duration); } } }
void LightInstanceBatchHW::injectRender() { if( (mRenderOperation.numberOfInstances = updateVertexBuffer( mCurrentCamera )) ) { Technique* tech = mMaterial->getBestTechnique(); for (size_t i=0; i<tech->getNumPasses(); ++i) { mManager->_injectRenderWithPass(tech->getPass(i), this, false); } } }
//! [schemenotfound] Technique* GBufferSchemeHandler::handleSchemeNotFound(unsigned short schemeIndex, const String& schemeName, Material* originalMaterial, unsigned short lodIndex, const Renderable* rend) { Ogre::MaterialManager& matMgr = Ogre::MaterialManager::getSingleton(); String curSchemeName = matMgr.getActiveScheme(); matMgr.setActiveScheme(MaterialManager::DEFAULT_SCHEME_NAME); Technique* originalTechnique = originalMaterial->getBestTechnique(lodIndex, rend); matMgr.setActiveScheme(curSchemeName); Technique* gBufferTech = originalMaterial->createTechnique(); gBufferTech->removeAllPasses(); gBufferTech->setSchemeName(schemeName); #ifdef OGRE_BUILD_COMPONENT_RTSHADERSYSTEM RTShader::ShaderGenerator& rtShaderGen = RTShader::ShaderGenerator::getSingleton(); rtShaderGen.createShaderBasedTechnique(originalTechnique, "NoGBuffer"); #else Technique* noGBufferTech = originalMaterial->createTechnique(); noGBufferTech->removeAllPasses(); noGBufferTech->setSchemeName("NoGBuffer"); #endif for (unsigned short i=0; i<originalTechnique->getNumPasses(); i++) { Pass* originalPass = originalTechnique->getPass(i); PassProperties props = inspectPass(originalPass, lodIndex, rend); if (!props.isDeferred) { #ifdef OGRE_BUILD_COMPONENT_RTSHADERSYSTEM rtShaderGen.validateMaterial("NoGBuffer", originalMaterial->getName(), originalMaterial->getGroup()); #else //Just copy the technique so it gets rendered regularly Pass* clonePass = noGBufferTech->createPass(); *clonePass = *originalPass; #endif continue; } Pass* newPass = gBufferTech->createPass(); MaterialGenerator::Perm perm = getPermutation(props); const Ogre::MaterialPtr& templateMat = mMaterialGenerator.getMaterial(perm); //We assume that the GBuffer technique contains only one pass. But its true. *newPass = *(templateMat->getTechnique(0)->getPass(0)); fillPass(newPass, originalPass, props); } return gBufferTech; }
// 把地形的障碍区域显示Pass移除 void TerrainEditorPlugin::removeTerrainBlockerPass(ETTerrain *terrain) { MaterialPtr mat = terrain->getTerrainImpl()->getMaterial(); Technique *tech = mat->getTechnique(0); // 看有没有这个Blocker的Pass,如果有就删除之 for(size_t i = 0 ; i < tech->getNumPasses() ; i ++) { if(tech->getPass(i)->getName() == "Blocker") { tech->removePass(i); return; } } }
// 替换指定纹理层的纹理 bool TerrainImpl::setPaintTexutreName(size_t nPaintChannel , const String &strTextureName) { Technique *pTech = mMaterial->getTechnique(0); Pass *pass = pTech->getPass(nPaintChannel / SPLATTING_TEXTURE_NUM); if(pass) { TextureUnitState *texture = pass->getTextureUnitState(COVERAGE_TEXTURE_NUM + (nPaintChannel % SPLATTING_TEXTURE_NUM)); if(texture) { texture->setTextureName(strTextureName); return texture->getTextureName() == strTextureName && !texture->_getTexturePtr().isNull() && texture->_getTexturePtr()->isLoaded(); } } return false; }
static int lua_Technique_getPass(lua_State* state) { // Get the number of parameters. int paramCount = lua_gettop(state); // Attempt to match the parameters to a valid binding. switch (paramCount) { case 2: { if ((lua_type(state, 1) == LUA_TUSERDATA) && (lua_type(state, 2) == LUA_TSTRING || lua_type(state, 2) == LUA_TNIL)) { // Get parameter 1 off the stack. const char* param1 = gameplay::ScriptUtil::getString(2, false); Technique* instance = getInstance(state); void* returnPtr = ((void*)instance->getPass(param1)); if (returnPtr) { gameplay::ScriptUtil::LuaObject* object = (gameplay::ScriptUtil::LuaObject*)lua_newuserdata(state, sizeof(gameplay::ScriptUtil::LuaObject)); object->instance = returnPtr; object->owns = false; luaL_getmetatable(state, "Pass"); lua_setmetatable(state, -2); } else { lua_pushnil(state); } return 1; } lua_pushstring(state, "lua_Technique_getPass - Failed to match the given parameters to a valid function signature."); lua_error(state); break; } default: { lua_pushstring(state, "Invalid number of parameters (expected 2)."); lua_error(state); break; } } return 0; }
//=========================================================================== // MaterialPassAction //=========================================================================== void IMaterialPassAction::subEntityAction( SubEntityMaterial* subEntity ) const { if( !subEntity->getMaterial().isNull() ) { unsigned short i = 0 ; for( Material::TechniqueIterator techniqueIt = subEntity->getMaterial()->getTechniqueIterator() ; techniqueIt.hasMoreElements() ; techniqueIt.moveNext(), ++i ) { Technique* techniqueScr = subEntity->getMaterial()->getTechnique( i ) ; unsigned short j = 0; for( Technique::PassIterator passIt = techniqueIt.peekNext()->getPassIterator (); passIt.hasMoreElements() ; passIt.moveNext(), ++j ) { passAction( subEntity, passIt.peekNext(), techniqueScr->getPass( j ) ) ; } } } }
//----------------------------------------------------------------------------- void SGMaterialSerializerListener::createSGPassList(Material* mat, SGPassList& passList) { for (unsigned short techniqueIndex = 0; techniqueIndex < mat->getNumTechniques(); ++techniqueIndex) { Technique* curTechnique = mat->getTechnique(techniqueIndex); for (unsigned short passIndex = 0; passIndex < curTechnique->getNumPasses(); ++passIndex) { Pass* curPass = curTechnique->getPass(passIndex); const Any& passUserData = curPass->getUserObjectBindings().getUserAny(ShaderGenerator::SGPass::UserKey); // Case this pass created by the shader generator. if (passUserData.isEmpty() == false) { ShaderGenerator::SGPass* passEntry = any_cast<ShaderGenerator::SGPass*>(passUserData); passList.push_back(passEntry); } } } }
const MaterialPtr &MaterialGenerator::getMaterial(Perm permutation) { /// Check input validity size_t totalBits = bitNames.size(); size_t totalPerms = 1<<totalBits; assert(permutation < totalPerms); /// Check if material/shader permutation already was generated MaterialMap::iterator i = mMaterials.find(permutation); if(i != mMaterials.end()) { return i->second; } else { /// Create it MaterialPtr templ = getTemplateMaterial(permutation & matMask); GpuProgramPtr vs = getVertexShader(permutation & vsMask); GpuProgramPtr fs = getFragmentShader(permutation & fsMask); /// Create material name String name=materialBaseName; for(size_t bit=0; bit<totalBits; ++bit) if(permutation & (1<<bit)) name += bitNames[bit]; std::cerr << name << " " << vs->getName() << " " << fs->getName() << std::endl; /// Create material from template, and set shaders MaterialPtr mat = templ->clone(name); Technique *tech = mat->getTechnique(0); Pass *pass = tech->getPass(0); pass->setFragmentProgram(fs->getName()); pass->setVertexProgram(vs->getName()); /// And store it mMaterials[permutation] = mat; return mMaterials[permutation]; } }
void Model::setMaterialNodeBinding(Material *material) { if (_node) { material->setNodeBinding(_node); unsigned int techniqueCount = material->getTechniqueCount(); for (unsigned int i = 0; i < techniqueCount; ++i) { Technique* technique = material->getTechnique(i); technique->setNodeBinding(_node); unsigned int passCount = technique->getPassCount(); for (unsigned int j = 0; j < passCount; ++j) { Pass* pass = technique->getPass(j); pass->setNodeBinding(_node); } } } }
// 为地形添加一个障碍区域的显示Pass void TerrainEditorPlugin::addTerrainBlockerPass(ETTerrain *terrain) { MaterialPtr mat = terrain->getTerrainImpl()->getMaterial(); Technique *tech = mat->getTechnique(0); // 看有没有这个Blocker的Pass,如果有就不用添加了 for(size_t i = 0 ; i < tech->getNumPasses() ; i ++) { if(tech->getPass(i)->getName() == "Blocker") return; } Pass *blockerPass = mat->getTechnique(0)->createPass(); blockerPass->setName("Blocker"); // 使用透明渲染 blockerPass->setSceneBlending(SBT_TRANSPARENT_ALPHA); blockerPass->setVertexProgram("ET/Programs/VSLodMorph2"); //blockerPass->setPolygonMode(PM_WIREFRAME); //blockerPass->setLightingEnabled(false); blockerPass->setCullingMode(CULL_ANTICLOCKWISE); //blockerPass->setDepthCheckEnabled(false); // 创建个贴图 TextureUnitState *state = blockerPass->createTextureUnitState(terrain->getBlockerTexture()->getName()); state->setTextureFiltering(TFO_NONE); }
void Model::setMaterial(Material* material, int partIndex) { assert(partIndex == -1 || (partIndex >= 0 && partIndex < (int)getMeshPartCount())); Material* oldMaterial = NULL; if (partIndex == -1) { oldMaterial = _material; // Set new shared material. if (material) { _material = material; _material->addRef(); } } else if (partIndex >= 0 && partIndex < (int)getMeshPartCount()) { // Ensure mesh part count is up-to-date. validatePartCount(); // Release existing part material and part binding. if (_partMaterials) { oldMaterial = _partMaterials[partIndex]; } else { // Allocate part arrays for the first time. if (_partMaterials == NULL) { _partMaterials = new Material*[_partCount]; memset(_partMaterials, 0, sizeof(Material*) * _partCount); } } // Set new part material. if (material) { _partMaterials[partIndex] = material; material->addRef(); } } // Release existing material and binding. if (oldMaterial) { for (unsigned int i = 0, tCount = material->getTechniqueCount(); i < tCount; ++i) { Technique* t = material->getTechnique(i); for (unsigned int j = 0, pCount = t->getPassCount(); j < pCount; ++j) { t->getPass(j)->setVertexAttributeBinding(NULL); } } SAFE_RELEASE(oldMaterial); } if (material) { // Hookup vertex attribute bindings for all passes in the new material. for (unsigned int i = 0, tCount = material->getTechniqueCount(); i < tCount; ++i) { Technique* t = material->getTechnique(i); for (unsigned int j = 0, pCount = t->getPassCount(); j < pCount; ++j) { Pass* p = t->getPass(j); VertexAttributeBinding* b = VertexAttributeBinding::create(_mesh, p->getEffect()); p->setVertexAttributeBinding(b); SAFE_RELEASE(b); } } // Apply node binding for the new material. if (_node) { setMaterialNodeBinding(material); } } }
void Model::draw(bool wireframe) { unsigned int partCount = _mesh->getPartCount(); if (partCount == 0) { // No mesh parts (index buffers). if (_material) { Technique* technique = _material->getTechnique(); unsigned int passCount = technique->getPassCount(); for (unsigned int i = 0; i < passCount; ++i) { Pass* pass = technique->getPass(i); pass->bind(); GL_ASSERT( glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0) ); if (wireframe && (_mesh->getPrimitiveType() == Mesh::TRIANGLES || _mesh->getPrimitiveType() == Mesh::TRIANGLE_STRIP)) { unsigned int vertexCount = _mesh->getVertexCount(); for (unsigned int j = 0; j < vertexCount; j += 3) { GL_ASSERT( glDrawArrays(GL_LINE_LOOP, j, 3) ); } } else { GL_ASSERT( glDrawArrays(_mesh->getPrimitiveType(), 0, _mesh->getVertexCount()) ); } pass->unbind(); } } } else { for (unsigned int i = 0; i < partCount; ++i) { MeshPart* part = _mesh->getPart(i); // Get the material for this mesh part. Material* material = getMaterial(i); if (material) { Technique* technique = material->getTechnique(); unsigned int passCount = technique->getPassCount(); for (unsigned int j = 0; j < passCount; ++j) { Pass* pass = technique->getPass(j); pass->bind(); GL_ASSERT( glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, part->_indexBuffer) ); if (wireframe && (_mesh->getPrimitiveType() == Mesh::TRIANGLES || _mesh->getPrimitiveType() == Mesh::TRIANGLE_STRIP)) { unsigned int indexCount = part->getIndexCount(); unsigned int indexSize = 0; switch (part->getIndexFormat()) { case Mesh::INDEX8: indexSize = 1; break; case Mesh::INDEX16: indexSize = 2; break; case Mesh::INDEX32: indexSize = 4; break; } for (unsigned int k = 0; k < indexCount; k += 3) { GL_ASSERT( glDrawElements(GL_LINE_LOOP, 3, part->getIndexFormat(), ((const GLvoid*)(k*indexSize))) ); } } else { GL_ASSERT( glDrawElements(part->getPrimitiveType(), part->getIndexCount(), part->getIndexFormat(), 0) ); } pass->unbind(); } } } } }
//----------------------------------------------------------------------------- /// 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"; ///T removed code for shader creation (we have our own shader) //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 std::cout << ptrMat->getName() << std::endl; sh::MaterialInstance* m = sh::Factory::getInstance ().createMaterialInstance (materialSignature.str(), ptrMat->getName()); //generatedMaterial = ptrMat->clone(materialSignature.str()); //And apply the fade shader } */ //Apply the material Ogre::MaterialPtr m = ptrMat; subBatch->setMaterial(m); } }
//-------------------------------------------------------------------------------- const ColourValue& MaterialUtil::getColor(const MaterialPtr& _material) { Technique* technique = _material->getTechnique(0); Pass* pass = technique->getPass(0); return pass->getDiffuse(); }
//----------------------------------------------------------------------------- /// MaterialPtr StaticBillboardSet::getFadeMaterial(const Ogre::MaterialPtr &protoMaterial, Real visibleDist_, Real invisibleDist_) { assert(!protoMaterial.isNull()); StringUtil::StrStreamType materialSignature; materialSignature << mEntityName << "|"; materialSignature << visibleDist_ << "|"; materialSignature << invisibleDist_ << "|"; materialSignature << protoMaterial->getTechnique(0)->getPass(0)->getTextureUnitState(0)->getTextureUScroll() << "|"; materialSignature << protoMaterial->getTechnique(0)->getPass(0)->getTextureUnitState(0)->getTextureVScroll() << "|"; FadedMaterialMap::iterator it = s_mapFadedMaterial.find(materialSignature.str()); if (it != s_mapFadedMaterial.end()) return it->second; //Use the existing fade material else { MaterialPtr fadeMaterial = protoMaterial->clone(getUniqueID("ImpostorFade")); bool isglsl = Root::getSingleton().getRenderSystem()->getName() == "OpenGL Rendering Subsystem" ? true : false; //And apply the fade shader for (unsigned short t = 0; t < fadeMaterial->getNumTechniques(); ++t) { Technique *tech = fadeMaterial->getTechnique(t); for (unsigned short p = 0; p < tech->getNumPasses(); ++p) { Pass *pass = tech->getPass(p); //Setup vertex program pass->setVertexProgram("SpriteFade_vp"); GpuProgramParametersSharedPtr params = pass->getVertexProgramParameters(); //glsl can use the built in gl_ModelViewProjectionMatrix if (!isglsl) params->setNamedAutoConstant("worldViewProj", GpuProgramParameters::ACT_WORLDVIEWPROJ_MATRIX); static const Ogre::String uScroll = "uScroll", vScroll = "vScroll", preRotatedQuad0 = "preRotatedQuad[0]", preRotatedQuad1 = "preRotatedQuad[1]", preRotatedQuad2 = "preRotatedQuad[2]", preRotatedQuad3 = "preRotatedQuad[3]", camPos = "camPos", fadeGap = "fadeGap", invisibleDist = "invisibleDist"; params->setNamedAutoConstant(uScroll, GpuProgramParameters::ACT_CUSTOM); params->setNamedAutoConstant(vScroll, GpuProgramParameters::ACT_CUSTOM); params->setNamedAutoConstant(preRotatedQuad0, GpuProgramParameters::ACT_CUSTOM); params->setNamedAutoConstant(preRotatedQuad1, GpuProgramParameters::ACT_CUSTOM); params->setNamedAutoConstant(preRotatedQuad2, GpuProgramParameters::ACT_CUSTOM); params->setNamedAutoConstant(preRotatedQuad3, GpuProgramParameters::ACT_CUSTOM); params->setNamedAutoConstant(camPos, GpuProgramParameters::ACT_CAMERA_POSITION_OBJECT_SPACE); params->setNamedAutoConstant(fadeGap, GpuProgramParameters::ACT_CUSTOM); params->setNamedAutoConstant(invisibleDist, GpuProgramParameters::ACT_CUSTOM); //Set fade ranges params->setNamedConstant(invisibleDist, invisibleDist_); params->setNamedConstant(fadeGap, invisibleDist_ - visibleDist_); pass->setSceneBlending(SBT_TRANSPARENT_ALPHA); //pass->setAlphaRejectFunction(CMPF_ALWAYS_PASS); //pass->setDepthWriteEnabled(false); } // for Pass } // for Technique //Add it to the list so it can be reused later s_mapFadedMaterial.insert(std::pair<String, MaterialPtr>(materialSignature.str(), fadeMaterial)); return fadeMaterial; } }
//----------------------------------------------------------------------------- ShadowCaster::ShadowRenderableListIterator ManualObject::getShadowVolumeRenderableIterator( ShadowTechnique shadowTechnique, const Light* light, HardwareIndexBufferSharedPtr* indexBuffer, bool extrude, Real extrusionDistance, unsigned long flags) { assert(indexBuffer && "Only external index buffers are supported right now"); EdgeData* edgeList = getEdgeList(); if (!edgeList) { return ShadowRenderableListIterator( mShadowRenderables.begin(), mShadowRenderables.end()); } // Calculate the object space light details Vector4 lightPos = light->getAs4DVector(); Matrix4 world2Obj = mParentNode->_getFullTransform().inverseAffine(); lightPos = world2Obj.transformAffine(lightPos); // Init shadow renderable list if required (only allow indexed) bool init = mShadowRenderables.empty() && mAnyIndexed; EdgeData::EdgeGroupList::iterator egi; ShadowRenderableList::iterator si, siend; ManualObjectSectionShadowRenderable* esr = 0; SectionList::iterator seci; if (init) mShadowRenderables.resize(edgeList->edgeGroups.size()); siend = mShadowRenderables.end(); egi = edgeList->edgeGroups.begin(); seci = mSectionList.begin(); for (si = mShadowRenderables.begin(); si != siend; ++seci) { // Skip non-indexed geometry if (!(*seci)->getRenderOperation()->useIndexes) { continue; } if (init) { // Create a new renderable, create a separate light cap if // we're using a vertex program (either for this model, or // for extruding the shadow volume) since otherwise we can // get depth-fighting on the light cap MaterialPtr mat = (*seci)->getMaterial(); mat->load(); bool vertexProgram = false; Technique* t = mat->getBestTechnique(0, *seci); for (unsigned short p = 0; p < t->getNumPasses(); ++p) { Pass* pass = t->getPass(p); if (pass->hasVertexProgram()) { vertexProgram = true; break; } } *si = OGRE_NEW ManualObjectSectionShadowRenderable(this, indexBuffer, egi->vertexData, vertexProgram || !extrude); } // Get shadow renderable esr = static_cast<ManualObjectSectionShadowRenderable*>(*si); HardwareVertexBufferSharedPtr esrPositionBuffer = esr->getPositionBuffer(); // Extrude vertices in software if required if (extrude) { extrudeVertices(esrPositionBuffer, egi->vertexData->vertexCount, lightPos, extrusionDistance); } ++si; ++egi; } // Calc triangle light facing updateEdgeListLightFacing(edgeList, lightPos); // Generate indexes and update renderables generateShadowVolume(edgeList, *indexBuffer, light, mShadowRenderables, flags); return ShadowRenderableListIterator( mShadowRenderables.begin(), mShadowRenderables.end()); }
//----------------------------------------------------------------------------- /// 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 TerrainSceneManager::setupTerrainMaterial(void) { if (mCustomMaterialName == "") { // define our own material mOptions.terrainMaterial = MaterialManager::getSingleton().getByName(TERRAIN_MATERIAL_NAME); // Make unique terrain material name StringUtil::StrStreamType s; s << mName << "/Terrain"; mOptions.terrainMaterial = MaterialManager::getSingleton().getByName(s.str()); if (mOptions.terrainMaterial.isNull()) { mOptions.terrainMaterial = MaterialManager::getSingleton().create( s.str(), ResourceGroupManager::getSingleton().getWorldResourceGroupName()); } else { mOptions.terrainMaterial->getTechnique(0)->getPass(0)->removeAllTextureUnitStates(); } Pass* pass = mOptions.terrainMaterial->getTechnique(0)->getPass(0); if ( mWorldTextureName != "" ) { pass->createTextureUnitState( mWorldTextureName, 0 ); } if ( mDetailTextureName != "" ) { pass->createTextureUnitState( mDetailTextureName, 1 ); } mOptions.terrainMaterial -> setLightingEnabled( mOptions.lit ); if (mOptions.lodMorph && mDestRenderSystem->getCapabilities()->hasCapability(RSC_VERTEX_PROGRAM) && GpuProgramManager::getSingleton().getByName("Terrain/VertexMorph").isNull()) { // Create & assign LOD morphing vertex program String syntax; if (GpuProgramManager::getSingleton().isSyntaxSupported("arbvp1")) { syntax = "arbvp1"; } else { syntax = "vs_1_1"; } // Get source, and take into account current fog mode FogMode fm = getFogMode(); const String& source = TerrainVertexProgram::getProgramSource( fm, syntax); GpuProgramPtr prog = GpuProgramManager::getSingleton().createProgramFromString( "Terrain/VertexMorph", ResourceGroupManager::getSingleton().getWorldResourceGroupName(), source, GPT_VERTEX_PROGRAM, syntax); // Attach pass->setVertexProgram("Terrain/VertexMorph"); // Get params GpuProgramParametersSharedPtr params = pass->getVertexProgramParameters(); // worldviewproj params->setAutoConstant(0, GpuProgramParameters::ACT_WORLDVIEWPROJ_MATRIX); // morph factor params->setAutoConstant(4, GpuProgramParameters::ACT_CUSTOM, MORPH_CUSTOM_PARAM_ID); // fog exp density(if relevant) if (fm == FOG_EXP || fm == FOG_EXP2) { params->setConstant(5, Vector3(getFogDensity(), 0, 0)); // Override scene fog since otherwise it's applied twice // Set to linear and we derive [0,1] fog value in the shader pass->setFog(true, FOG_LINEAR, getFogColour(), 0, 1, 0); } // Also set shadow receiver program const String& source2 = TerrainVertexProgram::getProgramSource( fm, syntax, true); prog = GpuProgramManager::getSingleton().createProgramFromString( "Terrain/VertexMorphShadowReceive", ResourceGroupManager::getSingleton().getWorldResourceGroupName(), source2, GPT_VERTEX_PROGRAM, syntax); pass->setShadowReceiverVertexProgram("Terrain/VertexMorphShadowReceive"); params = pass->getShadowReceiverVertexProgramParameters(); // worldviewproj params->setAutoConstant(0, GpuProgramParameters::ACT_WORLDVIEWPROJ_MATRIX); // world params->setAutoConstant(4, GpuProgramParameters::ACT_WORLD_MATRIX); // texture view / proj params->setAutoConstant(8, GpuProgramParameters::ACT_TEXTURE_VIEWPROJ_MATRIX); // morph factor params->setAutoConstant(12, GpuProgramParameters::ACT_CUSTOM, MORPH_CUSTOM_PARAM_ID); if (mDetailTextureName != "") { pass->getTextureUnitState(1)->setTextureCoordSet(1); } // Set param index mLodMorphParamName = ""; mLodMorphParamIndex = 4; } mOptions.terrainMaterial->load(); } else { // Custom material mOptions.terrainMaterial = MaterialManager::getSingleton().getByName(mCustomMaterialName); if (mOptions.terrainMaterial.isNull()){ OGRE_EXCEPT(Exception::ERR_ITEM_NOT_FOUND, "Material " + mCustomMaterialName + " not found.", "TerrainSceneManager::setupTerrainMaterial"); } mOptions.terrainMaterial->load(); } // now set up the linkage between vertex program and LOD morph param if (mOptions.lodMorph) { Technique* t = mOptions.terrainMaterial->getBestTechnique(); for (ushort i = 0; i < t->getNumPasses(); ++i) { Pass* p = t->getPass(i); if (p->hasVertexProgram()) { // we have to assume vertex program includes LOD morph capability GpuProgramParametersSharedPtr params = p->getVertexProgramParameters(); // Check to see if custom param is already there GpuProgramParameters::AutoConstantIterator aci = params->getAutoConstantIterator(); bool found = false; while (aci.hasMoreElements()) { const GpuProgramParameters::AutoConstantEntry& ace = aci.getNext(); if (ace.paramType == GpuProgramParameters::ACT_CUSTOM && ace.data == MORPH_CUSTOM_PARAM_ID) { found = true; } } if (!found) { if(mLodMorphParamName != "") { params->setNamedAutoConstant(mLodMorphParamName, GpuProgramParameters::ACT_CUSTOM, MORPH_CUSTOM_PARAM_ID); } else { params->setAutoConstant(mLodMorphParamIndex, GpuProgramParameters::ACT_CUSTOM, MORPH_CUSTOM_PARAM_ID); } } } } } }
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); } }
//----------------------------------------------------------------------- size_t InstanceBatchShader::calculateMaxNumInstances( const SubMesh *baseSubMesh, uint16 flags ) const { const size_t numBones = std::max<size_t>( 1, baseSubMesh->blendIndexToBoneIndexMap.size() ); mMaterial->load(); Technique *technique = mMaterial->getBestTechnique(); if( technique ) { GpuProgramParametersSharedPtr vertexParam = technique->getPass(0)->getVertexProgramParameters(); GpuConstantDefinitionIterator itor = vertexParam->getConstantDefinitionIterator(); while( itor.hasMoreElements() ) { const GpuConstantDefinition &constDef = itor.getNext(); if(((constDef.constType == GCT_MATRIX_3X4 || constDef.constType == GCT_MATRIX_4X3 || //OGL GLSL bitches without this constDef.constType == GCT_MATRIX_2X4 || constDef.constType == GCT_FLOAT4) //OGL GLSL bitches without this && constDef.isFloat()) || ((constDef.constType == GCT_MATRIX_DOUBLE_3X4 || constDef.constType == GCT_MATRIX_DOUBLE_4X3 || //OGL GLSL bitches without this constDef.constType == GCT_MATRIX_DOUBLE_2X4 || constDef.constType == GCT_DOUBLE4) //OGL GLSL bitches without this && constDef.isDouble()) ) { const GpuProgramParameters::AutoConstantEntry *entry = vertexParam->_findRawAutoConstantEntryFloat( constDef.physicalIndex ); if( entry && (entry->paramType == GpuProgramParameters::ACT_WORLD_MATRIX_ARRAY_3x4 || entry->paramType == GpuProgramParameters::ACT_WORLD_DUALQUATERNION_ARRAY_2x4)) { //Material is correctly done! size_t arraySize = constDef.arraySize; //Deal with GL "hacky" way of doing 4x3 matrices if(entry->paramType == GpuProgramParameters::ACT_WORLD_MATRIX_ARRAY_3x4 && constDef.constType == GCT_FLOAT4) arraySize /= 3; else if(entry->paramType == GpuProgramParameters::ACT_WORLD_DUALQUATERNION_ARRAY_2x4 && constDef.constType == GCT_FLOAT4) arraySize /= 2; //Check the num of arrays size_t retVal = arraySize / numBones; if( flags & IM_USE16BIT ) { if( baseSubMesh->vertexData->vertexCount * retVal > 0xFFFF ) retVal = 0xFFFF / baseSubMesh->vertexData->vertexCount; } if((retVal < 3 && entry->paramType == GpuProgramParameters::ACT_WORLD_MATRIX_ARRAY_3x4) || (retVal < 2 && entry->paramType == GpuProgramParameters::ACT_WORLD_DUALQUATERNION_ARRAY_2x4)) { LogManager::getSingleton().logMessage( "InstanceBatchShader: Mesh " + mMeshReference->getName() + " using material " + mMaterial->getName() + " contains many bones. The amount of " "instances per batch is very low. Performance benefits will " "be minimal, if any. It might be even slower!", LML_NORMAL ); } return retVal; } } } //Reaching here means material is supported, but malformed OGRE_EXCEPT( Exception::ERR_INVALIDPARAMS, "Material '" + mMaterial->getName() + "' is malformed for this instancing technique", "InstanceBatchShader::calculateMaxNumInstances"); } //Reaching here the material is just unsupported. return 0; }
void MeshObject::loadMesh() { try { Ogre::String resourceGroup = Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME; mesh = static_cast<Ogre::MeshPtr>(Ogre::MeshManager::getSingleton().create(meshName, resourceGroup)); if(backgroundLoading) { mesh->setBackgroundLoaded(true); mesh->addListener(this); ticket = Ogre::ResourceBackgroundQueue::getSingleton().load( Ogre::MeshManager::getSingletonPtr()->getResourceType(), mesh->getName(), resourceGroup, false, 0, 0, 0); // try to load its textures in the background for(int i=0; i<mesh->getNumSubMeshes(); i++) { SubMesh *sm = mesh->getSubMesh(i); String materialName = sm->getMaterialName(); Ogre::MaterialPtr mat = static_cast<Ogre::MaterialPtr>(Ogre::MaterialManager::getSingleton().getByName(materialName)); //, resourceGroup)); if(mat.isNull()) continue; for(int tn=0; tn<mat->getNumTechniques(); tn++) { Technique *t = mat->getTechnique(tn); for(int pn=0; pn<t->getNumPasses(); pn++) { Pass *p = t->getPass(pn); for(int tun=0; tun<p->getNumTextureUnitStates(); tun++) { TextureUnitState *tu = p->getTextureUnitState(tun); String textureName = tu->getTextureName(); // now add this texture to the background loading queue Ogre::TexturePtr tex = static_cast<Ogre::TexturePtr>(Ogre::TextureManager::getSingleton().create(textureName, resourceGroup)); tex->setBackgroundLoaded(true); tex->addListener(this); ticket = Ogre::ResourceBackgroundQueue::getSingleton().load( Ogre::TextureManager::getSingletonPtr()->getResourceType(), tex->getName(), resourceGroup, false, 0, 0, 0); } } } } } if(!backgroundLoading) postProcess(); } catch (Ogre::Exception* e) { LOG("exception while loading mesh: " + e->getFullDescription()); } }