//----------------------------------------------------------------------------- String Technique::_compile(bool autoManageTextureUnits) { StringUtil::StrStreamType errors; mIsSupported = checkGPURules(errors); if (mIsSupported) { mIsSupported = checkHardwareSupport(autoManageTextureUnits, errors); } // Compile for categorised illumination on demand clearIlluminationPasses(); mIlluminationPassesCompilationPhase = IPS_NOT_COMPILED; return errors.str(); }
SimpleRenderable::SimpleRenderable() { m_matWorldTransform = Matrix4::IDENTITY; m_strMatName = "BaseWhite"; m_pMaterial = MaterialManager::getSingleton().getByName("BaseWhite"); m_pParentSceneManager = NULL; mParentNode = NULL; m_pCamera = NULL; // Generate name StringUtil::StrStreamType name; name << _TO_CHAR("SimpleRenderable") << ms_uGenNameCount++; mName = name.str(); }
//----------------------------------------------------------------------- String ParticleScriptSerializer::toString(vector<Real> vector, bool applySqrt) { StringUtil::StrStreamType stream; if (!vector.empty()) { for (size_t i = 0; i < vector.size(); ++i) { if (applySqrt) { stream << Math::Sqrt(vector[i]) << " "; } else { stream << vector[i] << " "; } } } return stream.str(); }
//--------------------------------------------------------------------- HighLevelGpuProgramPtr TerrainMaterialGeneratorC::SM2Profile::ShaderHelper::generateFragmentProgram( const SM2Profile* prof, const Terrain* terrain, TechniqueType tt) { HighLevelGpuProgramPtr ret = createFragmentProgram(prof, terrain, tt); StringUtil::StrStreamType sourceStr; generateFragmentProgramSource(prof, terrain, tt, sourceStr); ret->setSource(sourceStr.str()); ret->load(); defaultFpParams(prof, terrain, tt, ret); #if 1 LogManager::getSingleton().stream(LML_TRIVIAL) << "*** Terrain Fragment Program: " << ret->getName() << " ***\n" << ret->getSource() << "\n*** ***"; #endif return ret; }
//----------------------------------------------------------------------- SceneManager* SceneManagerEnumerator::createSceneManager( SceneTypeMask typeMask, const String& instanceName) { if (mInstances.find(instanceName) != mInstances.end()) { OGRE_EXCEPT(Exception::ERR_DUPLICATE_ITEM, "SceneManager instance called '" + instanceName + "' already exists", "SceneManagerEnumerator::createSceneManager"); } SceneManager* inst = 0; String name = instanceName; if (name.empty()) { // generate a name StringUtil::StrStreamType s; s << "SceneManagerInstance" << ++mInstanceCreateCount; name = s.str(); } // Iterate backwards to find the matching factory registered last for(Factories::reverse_iterator i = mFactories.rbegin(); i != mFactories.rend(); ++i) { if ((*i)->getMetaData().sceneTypeMask & typeMask) { inst = (*i)->createInstance(name); break; } } // use default factory if none if (!inst) inst = mDefaultFactory.createInstance(name); /// assign rs if already configured if (mCurrentRenderSystem) inst->_setDestinationRenderSystem(mCurrentRenderSystem); mInstances[inst->getName()] = inst; return inst; }
Animation::RotationInterpolationMode OgreMaxUtilities::ParseAnimationRotationInterpolationMode(const String& mode) { String modeLower = mode; StringUtil::toLowerCase(modeLower); if (modeLower == "linear") return Animation::RIM_LINEAR; else if (modeLower == "spherical") return Animation::RIM_SPHERICAL; StringUtil::StrStreamType errorMessage; errorMessage << "Invalid animation rotation interpolation mode specified: " << mode; OGRE_EXCEPT ( Exception::ERR_INVALIDPARAMS, errorMessage.str(), "OgreMaxUtilities::ParseAnimationRotationInterpolationMode" ); }
UpAxis OgreMaxUtilities::ParseUpAxis(const String& upAxis) { String upAxisLower = upAxis; StringUtil::toLowerCase(upAxisLower); if (upAxisLower == "y") return UP_AXIS_Y; else if (upAxisLower == "z") return UP_AXIS_Z; StringUtil::StrStreamType errorMessage; errorMessage << "Invalid up axis specified: " << upAxis; OGRE_EXCEPT ( Exception::ERR_INVALIDPARAMS, errorMessage.str(), "OgreMaxUtilities::ParseUpAxis" ); }
//--------------------------------------------------------------------- StreamSerialiser* PageManager::_readPageStream(PageID pageID, PagedWorldSection* section) { StreamSerialiser* ser = 0; if (mPageProvider) ser = mPageProvider->readPageStream(pageID, section); if (!ser) { // use default implementation StringUtil::StrStreamType nameStr; nameStr << section->getWorld()->getName() << "_" << section->getName() << "_" << pageID << ".page"; DataStreamPtr stream = ResourceGroupManager::getSingleton().openResource(nameStr.str()); ser = OGRE_NEW StreamSerialiser(stream); } return ser; }
BillboardRotationType OgreMaxUtilities::ParseBillboardRotationType(const String& rotationType) { String rotationTypeLower = rotationType; StringUtil::toLowerCase(rotationTypeLower); if (rotationTypeLower == "vertex") return BBR_VERTEX; else if (rotationTypeLower == "texcoord") return BBR_TEXCOORD; StringUtil::StrStreamType errorMessage; errorMessage << "Invalid billboard rotation type specified: " << rotationType; OGRE_EXCEPT ( Exception::ERR_INVALIDPARAMS, errorMessage.str(), "OgreMaxUtilities::ParseBillboardRotationType" ); }
ProjectionType OgreMaxUtilities::ParseProjectionType(const String& type) { String typeLower = type; StringUtil::toLowerCase(typeLower); if (typeLower == "perspective") return PT_PERSPECTIVE; else if (typeLower == "orthographic") return PT_ORTHOGRAPHIC; StringUtil::StrStreamType errorMessage; errorMessage << "Invalid projection type specified: " << type; OGRE_EXCEPT ( Exception::ERR_INVALIDPARAMS, errorMessage.str(), "OgreMaxUtilities::ParseProjectionType" ); }
RenderTarget::~RenderTarget() { // Delete viewports for (ViewportList::iterator i = mViewportList.begin(); i != mViewportList.end(); ++i) { fireViewportRemoved(i->second); delete (*i).second; } // Write closing message StringUtil::StrStreamType msg; msg << "Render Target '" << mName << "' " << "Average FPS: " << mStats.avgFPS << " " << "Best FPS: " << mStats.bestFPS << " " << "Worst FPS: " << mStats.worstFPS; LogManager::getSingleton().logMessage(msg.str()); }
//----------------------------------------------------------------------- void Material::compile(bool autoManageTextureUnits) { // Compile each technique, then add it to the list of supported techniques mSupportedTechniques.clear(); clearBestTechniqueList(); mUnsupportedReasons.clear(); Techniques::iterator i, iend; iend = mTechniques.end(); size_t techNo = 0; for (i = mTechniques.begin(); i != iend; ++i, ++techNo) { String compileMessages = (*i)->_compile(autoManageTextureUnits); if ( (*i)->isSupported() ) { insertSupportedTechnique(*i); } else { // Log informational StringUtil::StrStreamType str; str << "Material " << mName << " Technique " << techNo; if (!(*i)->getName().empty()) str << "(" << (*i)->getName() << ")"; str << " is not supported. " << compileMessages; LogManager::getSingleton().logMessage(str.str(), LML_TRIVIAL); mUnsupportedReasons += compileMessages; } } mCompilationRequired = false; // Did we find any? if (mSupportedTechniques.empty()) { LogManager::getSingleton().stream() << "WARNING: material " << mName << " has no supportable " << "Techniques and will be blank. Explanation: \n" << mUnsupportedReasons; } }
const String& Exception::getFullDescription(void) const { if (fullDesc.empty()) { StringUtil::StrStreamType desc; //字符串流 desc << "SAPPHIRE EXCEPTION(" << number << ":" << typeName << "): " << description << " in " << source; if (line > 0) { desc << " at " << file << " (line " << line << ")"; } fullDesc = desc.str(); } return fullDesc; }
//----------------------------------------------------------------------- String StringConverter::toString(const Matrix4& val) { StringUtil::StrStreamType stream; stream << val[0][0] << " " << val[0][1] << " " << val[0][2] << " " << val[0][3] << " " << val[1][0] << " " << val[1][1] << " " << val[1][2] << " " << val[1][3] << " " << val[2][0] << " " << val[2][1] << " " << val[2][2] << " " << val[2][3] << " " << val[3][0] << " " << val[3][1] << " " << val[3][2] << " " << val[3][3]; return stream.str(); }
//------------------------------------------------------ Ogre::MaterialPtr MaterialService::getWorldMaterialInstance(unsigned int idx, int tag) { if (tag < 0) { MaterialPtr mat = getWorldMaterialTemplate(idx); return mat; } else { MaterialPtr tmat = getWorldMaterialTemplate(idx); MaterialPtr imat; // have to look for it and clone WorldMaterialInstanceMap::iterator it = mWorldMaterials.find(idx); if (it == mWorldMaterials.end()) { // no slot for the idx. have to clone std::pair<WorldMaterialInstanceMap::iterator, bool> res = mWorldMaterials.insert(make_pair(idx, SlotMaterialMap())); it = res.first; } // now search SlotMaterialMap::iterator sit = it->second.find(tag); if (sit == it->second.end()) { StringUtil::StrStreamType tmp; tmp << "Shader" << idx << "#" << tag; imat = tmat->clone(tmp.str()); prepareMaterialInstance(imat, idx, tag); it->second.insert(make_pair(tag, imat)); } else { imat = sit->second; } return imat; } }
//----------------------------------------------------------------------- void TextureUnitState::setAnimatedTextureName( const String& name, unsigned int numFrames, Real duration) { setContentType(CONTENT_NAMED); mTextureLoadFailed = false; String ext; String baseName; size_t pos = name.find_last_of("."); baseName = name.substr(0, pos); ext = name.substr(pos); mFrames.resize(numFrames); // resize pointers, but don't populate until needed mFramePtrs.resize(numFrames); mAnimDuration = duration; mCurrentFrame = 0; mCubic = false; for (unsigned int i = 0; i < mFrames.size(); ++i) { StringUtil::StrStreamType str; str << baseName << "_" << i << ext; mFrames[i] = str.str(); mFramePtrs[i].setNull(); } // Load immediately if Material loaded if (isLoaded()) { _load(); } // Tell parent to recalculate hash if( Pass::getHashFunction() == Pass::getBuiltinHashFunction( Pass::MIN_TEXTURE_CHANGE ) ) { mParent->_dirtyHash(); } }
Light::LightTypes OgreMaxUtilities::ParseLightType(const String& type) { String typeLower = type; StringUtil::toLowerCase(typeLower); if (typeLower == "point") return Light::LT_POINT; else if (typeLower == "directional") return Light::LT_DIRECTIONAL; else if (typeLower == "spot") return Light::LT_SPOTLIGHT; StringUtil::StrStreamType errorMessage; errorMessage << "Invalid light type specified: " << type; OGRE_EXCEPT ( Exception::ERR_INVALIDPARAMS, errorMessage.str(), "OgreMaxUtilities::ParseLightType" ); }
Node::TransformSpace OgreMaxUtilities::ParseTransformSpace(const String& space) { String spaceLower = space; StringUtil::toLowerCase(spaceLower); if (spaceLower == "local") return Node::TS_LOCAL; else if (spaceLower == "parent") return Node::TS_PARENT; else if (spaceLower == "world") return Node::TS_WORLD; StringUtil::StrStreamType errorMessage; errorMessage << "Invalid transform space specified: " << space; OGRE_EXCEPT ( Exception::ERR_INVALIDPARAMS, errorMessage.str(), "OgreMaxUtilities::ParseTransformSpace" ); }
BoundingVolume::Type OgreMaxUtilities::ParseBoundingVolumeType(const String& type) { String typeLower = type; StringUtil::toLowerCase(typeLower); if (typeLower == "sphere") return BoundingVolume::SPHERE; else if (typeLower == "box") return BoundingVolume::BOX; else if (typeLower == "mesh") return BoundingVolume::MESH; StringUtil::StrStreamType errorMessage; errorMessage << "Invalid bounding volume type specified: " << type; OGRE_EXCEPT ( Exception::ERR_INVALIDPARAMS, errorMessage.str(), "OgreMaxUtilities::ParseBoundingVolumeType" ); }
//--------------------------------------------------------------------- StreamSerialiser* PageManager::_writePageStream(PageID pageID, PagedWorldSection* section) { StreamSerialiser* ser = 0; if (mPageProvider) ser = mPageProvider->writePageStream(pageID, section); if (!ser) { // use default implementation StringUtil::StrStreamType nameStr; nameStr << section->getWorld()->getName() << "_" << section->getName() << "_" << pageID << ".page"; // create file, overwrite if necessary DataStreamPtr stream = ResourceGroupManager::getSingleton().createResource( nameStr.str(), mPageResourceGroup, true); ser = OGRE_NEW StreamSerialiser(stream); } return ser; }
void PixelFormatTests::testCase(PixelFormat srcFormat, PixelFormat dstFormat) { setupBoxes(srcFormat, dstFormat); // Check end of buffer unsigned int eob = dst1.getWidth()*PixelUtil::getNumElemBytes(dstFormat); temp[eob] = (unsigned char)0x56; temp[eob+1] = (unsigned char)0x23; //std::cerr << "["+PixelUtil::getFormatName(srcFormat)+"->"+PixelUtil::getFormatName(dstFormat)+"]" << " " << eob << std::endl; // Do pack/unpacking with both naive and optimized version PixelUtil::bulkPixelConversion(src, dst1); naiveBulkPixelConversion(src, dst2); CPPUNIT_ASSERT_EQUAL(temp[eob], (unsigned char)0x56); CPPUNIT_ASSERT_EQUAL(temp[eob+1], (unsigned char)0x23); std::stringstream s; int x; s << "src="; for(x=0; x<16; x++) s << std::hex << std::setw(2) << std::setfill('0') << (unsigned int) randomData[x]; s << " dst="; for(x=0; x<16; x++) s << std::hex << std::setw(2) << std::setfill('0') << (unsigned int) temp[x]; s << " dstRef="; for(x=0; x<16; x++) s << std::hex << std::setw(2) << std::setfill('0') << (unsigned int) temp2[x]; s << " "; // Compare result StringUtil::StrStreamType msg; msg << "Conversion mismatch [" << PixelUtil::getFormatName(srcFormat) << "->" << PixelUtil::getFormatName(dstFormat) << "] " << s.str(); CPPUNIT_ASSERT_MESSAGE(msg.str().c_str(), memcmp(dst1.data, dst2.data, eob) == 0); }
FogMode OgreMaxUtilities::ParseFogMode(const String& mode) { String modeLower = mode; StringUtil::toLowerCase(modeLower); if (modeLower == "exp") return FOG_EXP; else if (modeLower == "exp2") return FOG_EXP2; else if (modeLower == "linear") return FOG_LINEAR; else return FOG_NONE; StringUtil::StrStreamType errorMessage; errorMessage << "Invalid fog mode specified: " << mode; OGRE_EXCEPT ( Exception::ERR_INVALIDPARAMS, errorMessage.str(), "OgreMaxUtilities::ParseFogMode" ); }
TextureType OgreMaxUtilities::ParseTextureType(const String& textureType) { String textureTypeLower = textureType; StringUtil::toLowerCase(textureTypeLower); if (textureTypeLower == "1d") return TEX_TYPE_1D; else if (textureTypeLower == "2d") return TEX_TYPE_2D; else if (textureTypeLower == "3d") return TEX_TYPE_3D; else if (textureTypeLower == "cubic") return TEX_TYPE_CUBE_MAP; StringUtil::StrStreamType errorMessage; errorMessage << "Invalid texture type specified: " << textureType; OGRE_EXCEPT ( Exception::ERR_INVALIDPARAMS, errorMessage.str(), "OgreMaxUtilities::ParseTextureType" ); }
//----------------------------------------------------------------------------- void XsiSkeletonExporter::createAnimations(Skeleton* pSkel, DeformerMap& deformers, float fps, AnimationList& animList, AxisAlignedBox& AABBPadding) { for (AnimationList::iterator ai = animList.begin(); ai != animList.end(); ++ai) { AnimationEntry& animEntry = *ai; // Note that we don't know if this time period includes bone animation // but we sample it anyway just in case; animation optimisation will // eliminate anything that's redundant // A little wasteful perhaps, but it's the only guaranteed way to pick // up all the potentially derived effects on deformers float animLength = (float)(animEntry.endFrame - animEntry.startFrame) / fps; StringUtil::StrStreamType str; str << "Creating animation " << animEntry.animationName << " with length " << animLength << " seconds"; LogOgreAndXSI(str.str()); Animation* anim = pSkel->createAnimation(animEntry.animationName, animLength); createAnimationTracksSampled(anim, animEntry, deformers, fps, AABBPadding); } }
Viewport* RenderTarget::addViewport(Camera* cam, int ZOrder, float left, float top , float width , float height) { // Check no existing viewport with this Z-order ViewportList::iterator it = mViewportList.find(ZOrder); if (it != mViewportList.end()) { StringUtil::StrStreamType str; str << "Can't create another viewport for " << mName << " with Z-Order " << ZOrder << " because a viewport exists with this Z-Order already."; OGRE_EXCEPT(Exception::ERR_INVALIDPARAMS, str.str(), "RenderTarget::addViewport"); } // Add viewport to list // Order based on Z-Order Viewport* vp = new Viewport(cam, this, left, top, width, height, ZOrder); mViewportList.insert(ViewportList::value_type(ZOrder, vp)); fireViewportAdded(vp); return vp; }
//--------------------------------------------------------------------- void Skeleton::loadImpl(void) { SkeletonSerializer serializer; StringUtil::StrStreamType msg; msg << "Skeleton: Loading " << mName; LogManager::getSingleton().logMessage(msg.str()); DataStreamPtr stream = ResourceGroupManager::getSingleton().openResource( mName, mGroup, true, this); serializer.importSkeleton(stream, this); // Load any linked skeletons LinkedSkeletonAnimSourceList::iterator i; for (i = mLinkedSkeletonAnimSourceList.begin(); i != mLinkedSkeletonAnimSourceList.end(); ++i) { i->pSkeleton = SkeletonManager::getSingleton().load( i->skeletonName, mGroup); } }
//--------------------------------------------------------------------- bool Technique::checkGPURules(StringUtil::StrStreamType& errors) { const RenderSystemCapabilities* caps = Root::getSingleton().getRenderSystem()->getCapabilities(); StringUtil::StrStreamType includeRules; bool includeRulesPresent = false; bool includeRuleMatched = false; // Check vendors first for (GPUVendorRuleList::const_iterator i = mGPUVendorRules.begin(); i != mGPUVendorRules.end(); ++i) { if (i->includeOrExclude == INCLUDE) { includeRulesPresent = true; includeRules << caps->vendorToString(i->vendor) << " "; if (i->vendor == caps->getVendor()) includeRuleMatched = true; } else // EXCLUDE { if (i->vendor == caps->getVendor()) { errors << "Excluded GPU vendor: " << caps->vendorToString(i->vendor) << std::endl; return false; } } } if (includeRulesPresent && !includeRuleMatched) { errors << "Failed to match GPU vendor: " << includeRules.str( ) << std::endl; return false; } // now check device names includeRules.str(StringUtil::BLANK); includeRulesPresent = false; includeRuleMatched = false; for (GPUDeviceNameRuleList::const_iterator i = mGPUDeviceNameRules.begin(); i != mGPUDeviceNameRules.end(); ++i) { if (i->includeOrExclude == INCLUDE) { includeRulesPresent = true; includeRules << i->devicePattern << " "; if (StringUtil::match(caps->getDeviceName(), i->devicePattern, i->caseSensitive)) includeRuleMatched = true; } else // EXCLUDE { if (StringUtil::match(caps->getDeviceName(), i->devicePattern, i->caseSensitive)) { errors << "Excluded GPU device: " << i->devicePattern << std::endl; return false; } } } if (includeRulesPresent && !includeRuleMatched) { errors << "Failed to match GPU device: " << includeRules.str( ) << std::endl; return false; } // passed return true; }
void GrassLayerBase::_updateShaders() { if (shaderNeedsUpdate) { shaderNeedsUpdate = false; //Proceed only if there is no custom vertex shader and the user's computer supports vertex shaders const RenderSystemCapabilities *caps = Root::getSingleton().getRenderSystem()->getCapabilities(); if (caps->hasCapability(RSC_VERTEX_PROGRAM) && geom->getShadersEnabled()) { //Calculate fade range float farViewDist = geom->getDetailLevels().front()->getFarRange(); float fadeRange = farViewDist / 1.2247449f; //Note: 1.2247449 ~= sqrt(1.5), which is necessary since the far view distance is measured from the centers //of pages, while the vertex shader needs to fade grass completely out (including the closest corner) //before the page center is out of range. //Generate a string ID that identifies the current set of vertex shader options StringUtil::StrStreamType tmpName; tmpName << "GrassVS_"; if (animate) tmpName << "anim_"; if (blend) tmpName << "blend_"; if (lighting) tmpName << "lighting_"; tmpName << renderTechnique << "_"; tmpName << fadeTechnique << "_"; if (fadeTechnique == FADETECH_GROW || fadeTechnique == FADETECH_ALPHAGROW) tmpName << maxHeight << "_"; tmpName << farViewDist << "_"; tmpName << "vp"; const String vsName = tmpName.str(); //Generate a string ID that identifies the material combined with the vertex shader const String matName = material->getName() + "_" + vsName; //Check if the desired material already exists (if not, create it) MaterialPtr tmpMat = MaterialManager::getSingleton().getByName(matName); if (tmpMat.isNull()) { //Clone the original material tmpMat = material->clone(matName); //Disable lighting tmpMat->setLightingEnabled(false); //tmpMat->setReceiveShadows(false); //Check if the desired shader already exists (if not, compile it) String shaderLanguage = ShaderHelper::getShaderLanguage(); HighLevelGpuProgramPtr vertexShader = HighLevelGpuProgramManager::getSingleton().getByName(vsName); if (vertexShader.isNull()) { //Generate the grass shader String vertexProgSource; if (!shaderLanguage.compare("hlsl") || !shaderLanguage.compare("cg")) { vertexProgSource = "void main( \n" " float4 iPosition : POSITION, \n" " float4 iColor : COLOR, \n" " float2 iUV : TEXCOORD0, \n" " out float4 oPosition : POSITION, \n" " out float4 oColor : COLOR, \n" " out float2 oUV : TEXCOORD0, \n"; if (lighting) vertexProgSource += " uniform float4 objSpaceLight, \n" " uniform float4 lightDiffuse, \n" " uniform float4 lightAmbient, \n"; if (animate) vertexProgSource += " uniform float time, \n" " uniform float frequency, \n" " uniform float4 direction, \n"; if (fadeTechnique == FADETECH_GROW || fadeTechnique == FADETECH_ALPHAGROW) vertexProgSource += " uniform float grassHeight, \n"; if (renderTechnique == GRASSTECH_SPRITE || lighting) vertexProgSource += " float4 iNormal : NORMAL, \n"; vertexProgSource += " uniform float4x4 worldViewProj, \n" " uniform float3 camPos, \n" " uniform float fadeRange ) \n" "{ \n" " oColor.rgb = iColor.rgb; \n" " float4 position = iPosition; \n" " float dist = distance(camPos.xz, position.xz); \n"; if (lighting) { vertexProgSource += " float3 light = normalize(objSpaceLight.xyz - (iPosition.xyz * objSpaceLight.w)); \n" " float diffuseFactor = max(dot(float4(0,1,0,0), light), 0); \n" " oColor = (lightAmbient + diffuseFactor * lightDiffuse) * iColor; \n"; } else { vertexProgSource += " oColor.rgb = iColor.rgb; \n"; } if (fadeTechnique == FADETECH_ALPHA || fadeTechnique == FADETECH_ALPHAGROW) vertexProgSource += //Fade out in the distance " oColor.a = 2.0f - (2.0f * dist / fadeRange); \n"; else vertexProgSource += " oColor.a = 1.0f; \n"; vertexProgSource += " float oldposx = position.x; \n"; if (renderTechnique == GRASSTECH_SPRITE) vertexProgSource += //Face the camera " float3 dirVec = (float3)position - (float3)camPos; \n" " float3 p = normalize(cross(float4(0,1,0,0), dirVec)); \n" " position += float4(p.x * iNormal.x, iNormal.y, p.z * iNormal.x, 0); \n"; if (animate) vertexProgSource += " if (iUV.y == 0.0f){ \n" //Wave grass in breeze " float offset = sin(time + oldposx * frequency); \n" " position += direction * offset; \n" " } \n"; if (blend && animate) vertexProgSource += " else { \n"; else if (blend) vertexProgSource += " if (iUV.y != 0.0f){ \n"; if (blend) vertexProgSource += //Blend the base of nearby grass into the terrain " oColor.a = clamp(oColor.a, 0, 1) * 4.0f * ((dist / fadeRange) - 0.1f); \n" " } \n"; if (fadeTechnique == FADETECH_GROW || fadeTechnique == FADETECH_ALPHAGROW) vertexProgSource += " float offset = (2.0f * dist / fadeRange) - 1.0f; \n" " position.y -= grassHeight * clamp(offset, 0, 1); "; vertexProgSource += " oPosition = mul(worldViewProj, position); \n"; vertexProgSource += " oUV = iUV;\n" "}"; } else { //Must be glsl if (lighting) { vertexProgSource = "uniform vec4 objSpaceLight; \n" "uniform vec4 lightDiffuse; \n" "uniform vec4 lightAmbient; \n"; } if (animate) { vertexProgSource += "uniform float time; \n" "uniform float frequency; \n" "uniform vec4 direction; \n"; } if (fadeTechnique == FADETECH_GROW || fadeTechnique == FADETECH_ALPHAGROW) { vertexProgSource += "uniform float grassHeight; \n"; } vertexProgSource += "uniform vec3 camPos; \n" "uniform float fadeRange; \n" "\n" "void main()" "{ \n" " vec4 color = gl_Color; \n" " vec4 position = gl_Vertex; \n" " float dist = distance(camPos.xz, position.xz); \n"; if (lighting) { vertexProgSource += " vec3 light = normalize(objSpaceLight.xyz - (gl_Vertex.xyz * objSpaceLight.w)); \n" " float diffuseFactor = max( dot( vec3(0.0,1.0,0.0), light), 0.0); \n" " color = (lightAmbient + diffuseFactor * lightDiffuse) * gl_Color; \n"; } else { vertexProgSource += " color.xyz = gl_Color.xyz; \n"; } if (fadeTechnique == FADETECH_ALPHA || fadeTechnique == FADETECH_ALPHAGROW) { vertexProgSource += //Fade out in the distance " color.w = 2.0 - (2.0 * dist / fadeRange); \n"; } else { vertexProgSource += " color.w = 1.0; \n"; } if (renderTechnique == GRASSTECH_SPRITE) { vertexProgSource += //Face the camera " vec3 dirVec = position.xyz - camPos.xyz; \n" " vec3 p = normalize(cross(vec3(0.0,1.0,0.0), dirVec)); \n" " position += vec4(p.x * gl_Normal.x, gl_Normal.y, p.z * gl_Normal.x, 0.0); \n"; } if (animate) { vertexProgSource += " if (gl_MultiTexCoord0.y == 0.0) \n" " { \n" //Wave grass in breeze " position += direction * sin(time + gl_Vertex.x * frequency); \n" " } \n"; } if (blend && animate) { vertexProgSource += " else \n" " { \n"; } else if (blend) { vertexProgSource += " if (gl_MultiTexCoord0.y != 0.0) \n" " { \n"; } if (blend) { vertexProgSource += //Blend the base of nearby grass into the terrain " color.w = clamp(color.w, 0.0, 1.0) * 4.0 * ((dist / fadeRange) - 0.1); \n" " } \n"; } if (fadeTechnique == FADETECH_GROW || fadeTechnique == FADETECH_ALPHAGROW) { vertexProgSource += " position.y -= grassHeight * clamp((2.0 * dist / fadeRange) - 1.0, 0.0, 1.0); \n"; } vertexProgSource += " gl_Position = gl_ModelViewProjectionMatrix * position; \n" " gl_FrontColor = color; \n" " gl_TexCoord[0] = gl_MultiTexCoord0; \n"; if (geom->getSceneManager()->getFogMode() == Ogre::FOG_EXP2) { vertexProgSource += " gl_FogFragCoord = clamp(exp(- gl_Fog.density * gl_Fog.density * gl_Position.z * gl_Position.z), 0.0, 1.0); \n"; } else { vertexProgSource += " gl_FogFragCoord = gl_Position.z; \n"; } vertexProgSource += "}"; } vertexShader = HighLevelGpuProgramManager::getSingleton().createProgram(vsName, ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, shaderLanguage, GPT_VERTEX_PROGRAM); vertexShader->setSource(vertexProgSource); if (shaderLanguage == "hlsl") { vertexShader->setParameter("target", "vs_1_1"); vertexShader->setParameter("entry_point", "main"); } else if (shaderLanguage == "cg") { vertexShader->setParameter("profiles", "vs_1_1 arbvp1"); vertexShader->setParameter("entry_point", "main"); } // GLSL can only have one entry point "main". vertexShader->load(); } //Now the vertex shader (vertexShader) has either been found or just generated //(depending on whether or not it was already generated). tmpMat->load(); Ogre::Material::TechniqueIterator techIterator = tmpMat->getSupportedTechniqueIterator(); while (techIterator.hasMoreElements()) { Ogre::Technique* tech = techIterator.getNext(); //Apply the shader to the material Pass *pass = tech->getPass(0); pass->setVertexProgram(vsName); GpuProgramParametersSharedPtr params = pass->getVertexProgramParameters(); if (shaderLanguage.compare("glsl")) //glsl can use the built in gl_ModelViewProjectionMatrix params->setNamedAutoConstant("worldViewProj", GpuProgramParameters::ACT_WORLDVIEWPROJ_MATRIX); params->setNamedAutoConstant("camPos", GpuProgramParameters::ACT_CAMERA_POSITION_OBJECT_SPACE); params->setNamedAutoConstant("fadeRange", GpuProgramParameters::ACT_CUSTOM, 1); if (animate) { params->setNamedConstant("time", 1.0f); params->setNamedConstant("frequency", 1.0f); params->setNamedConstant("direction", Ogre::Vector4::ZERO); } if (lighting) { params->setNamedAutoConstant("objSpaceLight", GpuProgramParameters::ACT_LIGHT_POSITION_OBJECT_SPACE); params->setNamedAutoConstant("lightDiffuse", GpuProgramParameters::ACT_DERIVED_LIGHT_DIFFUSE_COLOUR); params->setNamedAutoConstant("lightAmbient", GpuProgramParameters::ACT_DERIVED_AMBIENT_LIGHT_COLOUR); } if (fadeTechnique == FADETECH_GROW || fadeTechnique == FADETECH_ALPHAGROW) { params->setNamedConstant("grassHeight", maxHeight * 1.05f); } pass->getVertexProgramParameters()->setNamedConstant("fadeRange", fadeRange); } } //Now the material (tmpMat) has either been found or just created (depending on whether or not it was already //created). The appropriate vertex shader should be applied and the material is ready for use. //Apply the new material material = tmpMat; } Ogre::Technique* tech = material->getBestTechnique(); if (tech && tech->getNumPasses()) { Ogre::Pass* pass = tech->getPass(0); if (pass->hasVertexProgram()) { Ogre::GpuProgramParametersSharedPtr params = pass->getVertexProgramParameters(); if (!params.isNull()) { params->setIgnoreMissingParams(true); } } } } }
//----------------------------------------------------------------------- MaterialPtr Quake3Shader::createAsMaterial(int lightmapNumber) { String matName; StringUtil::StrStreamType str; String resourceGroup = ResourceGroupManager::getSingleton().getWorldResourceGroupName(); str << mName << "#" << lightmapNumber; matName = str.str(); MaterialPtr mat = MaterialManager::getSingleton().create(matName, resourceGroup); Ogre::Pass* ogrePass = mat->getTechnique(0)->getPass(0); LogManager::getSingleton().logMessage("Using Q3 shader " + mName, LML_CRITICAL); for (int p = 0; p < numPasses; ++p) { TextureUnitState* t; // Create basic texture if (pass[p].textureName == "$lightmap") { StringUtil::StrStreamType str2; str2 << "@lightmap" << lightmapNumber; t = ogrePass->createTextureUnitState(str2.str()); } // Animated texture support else if (pass[p].animNumFrames > 0) { Real sequenceTime = pass[p].animNumFrames / pass[p].animFps; /* Pre-load textures We need to know if each one was loaded OK since extensions may change for each Quake3 can still include alternate extension filenames e.g. jpg instead of tga Pain in the arse - have to check for each frame as letters<n>.tga for example is different per frame! */ for (unsigned int alt = 0; alt < pass[p].animNumFrames; ++alt) { if (!ResourceGroupManager::getSingleton().resourceExists( resourceGroup, pass[p].frames[alt])) { // Try alternate extension pass[p].frames[alt] = getAlternateName(pass[p].frames[alt]); if (!ResourceGroupManager::getSingleton().resourceExists( resourceGroup, pass[p].frames[alt])) { // stuffed - no texture continue; } } } t = ogrePass->createTextureUnitState(""); t->setAnimatedTextureName(pass[p].frames, pass[p].animNumFrames, sequenceTime); } else { // Quake3 can still include alternate extension filenames e.g. jpg instead of tga // Pain in the arse - have to check for failure if (!ResourceGroupManager::getSingleton().resourceExists( resourceGroup, pass[p].textureName)) { // Try alternate extension pass[p].textureName = getAlternateName(pass[p].textureName); if (!ResourceGroupManager::getSingleton().resourceExists( resourceGroup, pass[p].textureName)) { // stuffed - no texture continue; } } t = ogrePass->createTextureUnitState(pass[p].textureName); } // Blending if (p == 0) { // scene blend mat->setSceneBlending(pass[p].blendSrc, pass[p].blendDest); if (mat->isTransparent()) mat->setDepthWriteEnabled(false); t->setColourOperation(LBO_REPLACE); // Alpha mode ogrePass->setAlphaRejectSettings( pass[p].alphaFunc, pass[p].alphaVal); } else { if (pass[p].customBlend) { // Fallback for now t->setColourOperation(LBO_MODULATE); } else { // simple layer blend t->setColourOperation(pass[p].blend); } // Alpha mode, prefer 'most alphary' CompareFunction currFunc = ogrePass->getAlphaRejectFunction(); unsigned char currVal = ogrePass->getAlphaRejectValue(); if (pass[p].alphaFunc > currFunc || (pass[p].alphaFunc == currFunc && pass[p].alphaVal < currVal)) { ogrePass->setAlphaRejectSettings( pass[p].alphaFunc, pass[p].alphaVal); } } // Tex coords if (pass[p].texGen == TEXGEN_BASE) { t->setTextureCoordSet(0); } else if (pass[p].texGen == TEXGEN_LIGHTMAP) { t->setTextureCoordSet(1); } else if (pass[p].texGen == TEXGEN_ENVIRONMENT) { t->setEnvironmentMap(true, TextureUnitState::ENV_PLANAR); } // Tex mod // Scale t->setTextureUScale(pass[p].tcModScale[0]); t->setTextureVScale(pass[p].tcModScale[1]); // Procedural mods // Custom - don't use mod if generating environment // Because I do env a different way it look horrible if (pass[p].texGen != TEXGEN_ENVIRONMENT) { if (pass[p].tcModRotate) { t->setRotateAnimation(pass[p].tcModRotate); } if (pass[p].tcModScroll[0] || pass[p].tcModScroll[1]) { if (pass[p].tcModTurbOn) { // Turbulent scroll if (pass[p].tcModScroll[0]) { t->setTransformAnimation(TextureUnitState::TT_TRANSLATE_U, WFT_SINE, pass[p].tcModTurb[0], pass[p].tcModTurb[3], pass[p].tcModTurb[2], pass[p].tcModTurb[1]); } if (pass[p].tcModScroll[1]) { t->setTransformAnimation(TextureUnitState::TT_TRANSLATE_V, WFT_SINE, pass[p].tcModTurb[0], pass[p].tcModTurb[3], pass[p].tcModTurb[2], pass[p].tcModTurb[1]); } } else { // Constant scroll t->setScrollAnimation(pass[p].tcModScroll[0], pass[p].tcModScroll[1]); } } if (pass[p].tcModStretchWave != SHADER_FUNC_NONE) { WaveformType wft; switch(pass[p].tcModStretchWave) { case SHADER_FUNC_SIN: wft = WFT_SINE; break; case SHADER_FUNC_TRIANGLE: wft = WFT_TRIANGLE; break; case SHADER_FUNC_SQUARE: wft = WFT_SQUARE; break; case SHADER_FUNC_SAWTOOTH: wft = WFT_SAWTOOTH; break; case SHADER_FUNC_INVERSESAWTOOTH: wft = WFT_INVERSE_SAWTOOTH; break; default: break; } // Create wave-based stretcher t->setTransformAnimation(TextureUnitState::TT_SCALE_U, wft, pass[p].tcModStretchParams[3], pass[p].tcModStretchParams[0], pass[p].tcModStretchParams[2], pass[p].tcModStretchParams[1]); t->setTransformAnimation(TextureUnitState::TT_SCALE_V, wft, pass[p].tcModStretchParams[3], pass[p].tcModStretchParams[0], pass[p].tcModStretchParams[2], pass[p].tcModStretchParams[1]); } } // Address mode t->setTextureAddressingMode(pass[p].addressMode); //assert(!t->isBlank()); } // Do farbox (create new material) // Set culling mode and lighting to defaults mat->setCullingMode(CULL_NONE); mat->setManualCullingMode(cullMode); mat->setLightingEnabled(false); mat->load(); return mat; }
void ReloadMaterial(const std::string& materialName, const std::string& groupName, const std::string& filename, bool parseMaterialScript) { if (materialName.empty()) { Ogre::LogManager::getSingleton().logMessage("Material name is empty."); return; } if (groupName.empty()) { Ogre::LogManager::getSingleton().logMessage("Group name is empty."); return; } if (filename.empty()) { Ogre::LogManager::getSingleton().logMessage("Filename is empty."); return; } UnloadMaterials(filename); UnloadVertexPrograms(filename); UnloadFragmentPrograms(filename); if (parseMaterialScript) { Ogre::DataStreamPtr stream = Ogre::ResourceGroupManager::getSingleton().openResource(filename); if(!stream.isNull()) { try { Ogre::MaterialManager::getSingleton().parseScript(stream, groupName); Ogre::MaterialPtr materialPtr = Ogre::MaterialManager::getSingleton().getByName(materialName); if (!materialPtr.isNull()) { materialPtr->compile(); materialPtr->load(); } } catch (Ogre::Exception &e) { StringUtil::StrStreamType msg; msg << "Exception: FILE: " << __FILE__ << " LINE: " << __LINE__ << " DESC: " << e.getFullDescription() << std::endl; Ogre::LogManager::getSingleton().logMessage(msg.str()); } } stream->close(); /// /// RELOAD MATERIAL SCRIPT CONTENTS /// stream = Ogre::ResourceGroupManager::getSingleton().openResource(filename); if(!stream.isNull()) { try { /// /// RELOAD ALL MATERIAL CONTENTS IN FILE /// while(!stream->eof()) { std::string line = stream->getLine(); StringUtil::trim(line); /// /// RELOAD MATERIALS /// if (StringUtil::startsWith(line, "material")) { Ogre::vector<Ogre::String>::type vec = StringUtil::split(line," \t:"); bool skipFirst = true; for (Ogre::vector<Ogre::String>::type::iterator it = vec.begin(); it < vec.end(); ++it) { if (skipFirst) { skipFirst = false; continue; } std::string match = (*it); StringUtil::trim(match); if (!match.empty()) { LoadResource(Ogre::MaterialManager::getSingletonPtr(), match, groupName); break; } } } /// /// RELOAD VERTEX PROGRAMS /// if (StringUtil::startsWith(line, "vertex_program") && !StringUtil::startsWith(line, "vertex_program_ref")) { Ogre::vector<Ogre::String>::type vec = StringUtil::split(line," \t"); bool skipFirst = true; for (Ogre::vector<Ogre::String>::type::iterator it = vec.begin(); it < vec.end(); ++it) { if (skipFirst) { skipFirst = false; continue; } std::string match = (*it); StringUtil::trim(match); if (!match.empty()) { LoadResource(Ogre::HighLevelGpuProgramManager::getSingletonPtr(), match, groupName); break; } } } /// /// RELOAD FRAGMENT PROGRAMS /// if (StringUtil::startsWith(line, "fragment_program") && !StringUtil::startsWith(line, "fragment_program_ref")) { Ogre::vector<Ogre::String>::type vec = StringUtil::split(line," \t"); bool skipFirst = true; for (Ogre::vector<Ogre::String>::type::iterator it = vec.begin(); it < vec.end(); ++it) { if (skipFirst) { skipFirst = false; continue; } std::string match = (*it); StringUtil::trim(match); if (!match.empty()) { LoadResource(Ogre::HighLevelGpuProgramManager::getSingletonPtr(), match, groupName); break; } } } } } catch (Ogre::Exception &e) { StringUtil::StrStreamType msg; msg << "Exception: FILE: " << __FILE__ << " LINE: " << __LINE__ << " DESC: " << e.getFullDescription() << std::endl; Ogre::LogManager::getSingleton().logMessage(msg.str()); } } stream->close(); try { // Do a render test if it fails, leave materials unloaded Ogre::Root::getSingleton().renderOneFrame(); return; } catch (Ogre::Exception &e) { UnloadVertexPrograms(filename); StringUtil::StrStreamType msg; msg << "Render test failed. Unloading vertex programs." << std::endl; msg << "Exception: FILE: " << __FILE__ << " LINE: " << __LINE__ << " DESC: " << e.getFullDescription() << std::endl; Ogre::LogManager::getSingleton().logMessage(msg.str()); } try { // Do a render test if it fails, leave materials unloaded Ogre::Root::getSingleton().renderOneFrame(); } catch (Ogre::Exception &e) { // Don't load the script this time ReloadMaterial(materialName, groupName, filename, false); StringUtil::StrStreamType msg; msg << "Render test failed. Unloading materials." << std::endl; msg << "Exception: FILE: " << __FILE__ << " LINE: " << __LINE__ << " DESC: " << e.getFullDescription() << std::endl; Ogre::LogManager::getSingleton().logMessage(msg.str()); } } }