void CarModel::UpdateBraking()
{
	if (brakes)
		brakes->setVisible(bBraking && mbVisible);

	std::string texName = sDirname + (bBraking ? "_body00_brake.png" : "_body00_add.png");

	MaterialPtr mtr = MaterialManager::getSingleton().getByName(sMtr[Mtr_CarBody]);
	if (!mtr.isNull())
	{	Material::TechniqueIterator techIt = mtr->getTechniqueIterator();
		while (techIt.hasMoreElements())
		{	Technique* tech = techIt.getNext();
			Technique::PassIterator passIt = tech->getPassIterator();
			while (passIt.hasMoreElements())
			{	Pass* pass = passIt.getNext();
				Pass::TextureUnitStateIterator tusIt = pass->getTextureUnitStateIterator();
				while (tusIt.hasMoreElements())
				{
					TextureUnitState* tus = tusIt.getNext();
					if (tus->getName() == "diffuseMap")
					{	tus->setTextureName( texName );  return;  }
	}	}	}	}
}
    //-----------------------------------------------------------------------
    void Technique::_compileIlluminationPasses(void)
    {
        clearIlluminationPasses();

		if (!checkManuallyOrganisedIlluminationPasses())
		{
			// Build based on our own heuristics

			Passes::iterator i, iend;
			iend = mPasses.end();
			i = mPasses.begin();

			IlluminationStage iStage = IS_AMBIENT;

			bool haveAmbient = false;
			while (i != iend)
			{
				IlluminationPass* iPass;
				Pass* p = *i;
				switch(iStage)
				{
				case IS_AMBIENT:
					// Keep looking for ambient only
					if (p->isAmbientOnly())
					{
						// Add this pass wholesale
						iPass = OGRE_NEW IlluminationPass();
						iPass->destroyOnShutdown = false;
						iPass->originalPass = iPass->pass = p;
						iPass->stage = iStage;
						mIlluminationPasses.push_back(iPass);
						haveAmbient = true;
						// progress to next pass
						++i;
					}
					else
					{
						// Split off any ambient part
						if (p->getAmbient() != ColourValue::Black ||
							p->getSelfIllumination() != ColourValue::Black ||
							p->getAlphaRejectFunction() != CMPF_ALWAYS_PASS)
						{
							// Copy existing pass
							Pass* newPass = OGRE_NEW Pass(this, p->getIndex(), *p);
							if (newPass->getAlphaRejectFunction() != CMPF_ALWAYS_PASS)
							{
								// Alpha rejection passes must retain their transparency, so
								// we allow the texture units, but override the colour functions
								Pass::TextureUnitStateIterator tusi = newPass->getTextureUnitStateIterator();
								while (tusi.hasMoreElements())
								{
									TextureUnitState* tus = tusi.getNext();
									tus->setColourOperationEx(LBX_SOURCE1, LBS_CURRENT);
								}
							}
							else
							{
								// Remove any texture units
								newPass->removeAllTextureUnitStates();
							}
							// Remove any fragment program
							if (newPass->hasFragmentProgram())
								newPass->setFragmentProgram("");
							// We have to leave vertex program alone (if any) and
							// just trust that the author is using light bindings, which
							// we will ensure there are none in the ambient pass
							newPass->setDiffuse(0, 0, 0, newPass->getDiffuse().a);  // Preserving alpha
							newPass->setSpecular(ColourValue::Black);

							// Calculate hash value for new pass, because we are compiling
							// illumination passes on demand, which will loss hash calculate
							// before it add to render queue first time.
							newPass->_recalculateHash();

							iPass = OGRE_NEW IlluminationPass();
							iPass->destroyOnShutdown = true;
							iPass->originalPass = p;
							iPass->pass = newPass;
							iPass->stage = iStage;

							mIlluminationPasses.push_back(iPass);
							haveAmbient = true;

						}

						if (!haveAmbient)
						{
							// Make up a new basic pass
							Pass* newPass = OGRE_NEW Pass(this, p->getIndex());
							newPass->setAmbient(ColourValue::Black);
							newPass->setDiffuse(ColourValue::Black);

							// Calculate hash value for new pass, because we are compiling
							// illumination passes on demand, which will loss hash calculate
							// before it add to render queue first time.
							newPass->_recalculateHash();

							iPass = OGRE_NEW IlluminationPass();
							iPass->destroyOnShutdown = true;
							iPass->originalPass = p;
							iPass->pass = newPass;
							iPass->stage = iStage;
							mIlluminationPasses.push_back(iPass);
							haveAmbient = true;
						}
						// This means we're done with ambients, progress to per-light
						iStage = IS_PER_LIGHT;
					}
					break;
				case IS_PER_LIGHT:
					if (p->getIteratePerLight())
					{
						// If this is per-light already, use it directly
						iPass = OGRE_NEW IlluminationPass();
						iPass->destroyOnShutdown = false;
						iPass->originalPass = iPass->pass = p;
						iPass->stage = iStage;
						mIlluminationPasses.push_back(iPass);
						// progress to next pass
						++i;
					}
					else
					{
						// Split off per-light details (can only be done for one)
						if (p->getLightingEnabled() &&
							(p->getDiffuse() != ColourValue::Black ||
							p->getSpecular() != ColourValue::Black))
						{
							// Copy existing pass
							Pass* newPass = OGRE_NEW Pass(this, p->getIndex(), *p);
							if (newPass->getAlphaRejectFunction() != CMPF_ALWAYS_PASS)
							{
								// Alpha rejection passes must retain their transparency, so
								// we allow the texture units, but override the colour functions
								Pass::TextureUnitStateIterator tusi = newPass->getTextureUnitStateIterator();
								while (tusi.hasMoreElements())
								{
									TextureUnitState* tus = tusi.getNext();
									tus->setColourOperationEx(LBX_SOURCE1, LBS_CURRENT);
								}
							}
							else
							{
								// remove texture units
								newPass->removeAllTextureUnitStates();
							}
							// remove fragment programs
							if (newPass->hasFragmentProgram())
								newPass->setFragmentProgram("");
							// Cannot remove vertex program, have to assume that
							// it will process diffuse lights, ambient will be turned off
							newPass->setAmbient(ColourValue::Black);
							newPass->setSelfIllumination(ColourValue::Black);
							// must be additive
							newPass->setSceneBlending(SBF_ONE, SBF_ONE);

							// Calculate hash value for new pass, because we are compiling
							// illumination passes on demand, which will loss hash calculate
							// before it add to render queue first time.
							newPass->_recalculateHash();

							iPass = OGRE_NEW IlluminationPass();
							iPass->destroyOnShutdown = true;
							iPass->originalPass = p;
							iPass->pass = newPass;
							iPass->stage = iStage;

							mIlluminationPasses.push_back(iPass);

						}
						// This means the end of per-light passes
						iStage = IS_DECAL;
					}
					break;
				case IS_DECAL:
					// We just want a 'lighting off' pass to finish off
					// and only if there are texture units
					if (p->getNumTextureUnitStates() > 0)
					{
						if (!p->getLightingEnabled())
						{
							// we assume this pass already combines as required with the scene
							iPass = OGRE_NEW IlluminationPass();
							iPass->destroyOnShutdown = false;
							iPass->originalPass = iPass->pass = p;
							iPass->stage = iStage;
							mIlluminationPasses.push_back(iPass);
						}
						else
						{
							// Copy the pass and tweak away the lighting parts
							Pass* newPass = OGRE_NEW Pass(this, p->getIndex(), *p);
							newPass->setAmbient(ColourValue::Black);
							newPass->setDiffuse(0, 0, 0, newPass->getDiffuse().a);  // Preserving alpha
							newPass->setSpecular(ColourValue::Black);
							newPass->setSelfIllumination(ColourValue::Black);
							newPass->setLightingEnabled(false);
							newPass->setIteratePerLight(false, false);
							// modulate
							newPass->setSceneBlending(SBF_DEST_COLOUR, SBF_ZERO);

							// Calculate hash value for new pass, because we are compiling
							// illumination passes on demand, which will loss hash calculate
							// before it add to render queue first time.
							newPass->_recalculateHash();

							// NB there is nothing we can do about vertex & fragment
							// programs here, so people will just have to make their
							// programs friendly-like if they want to use this technique
							iPass = OGRE_NEW IlluminationPass();
							iPass->destroyOnShutdown = true;
							iPass->originalPass = p;
							iPass->pass = newPass;
							iPass->stage = iStage;
							mIlluminationPasses.push_back(iPass);

						}
					}
					++i; // always increment on decal, since nothing more to do with this pass

					break;
                case IS_UNKNOWN:
                    break;
				}
			}
		}

    }
	//---------------------------------------------------------------------
	bool Technique::checkHardwareSupport(bool autoManageTextureUnits, StringUtil::StrStreamType& compileErrors)
	{
		// Go through each pass, checking requirements
		Passes::iterator i;
		unsigned short passNum = 0;
		const RenderSystemCapabilities* caps =
			Root::getSingleton().getRenderSystem()->getCapabilities();
		unsigned short numTexUnits = caps->getNumTextureUnits();
		for (i = mPasses.begin(); i != mPasses.end(); ++i, ++passNum)
		{
			Pass* currPass = *i;
			// Adjust pass index
			currPass->_notifyIndex(passNum);
			// Check for advanced blending operation support
			if((currPass->getSceneBlendingOperation() != SBO_ADD || currPass->getSceneBlendingOperationAlpha() != SBO_ADD) && 
				!caps->hasCapability(RSC_ADVANCED_BLEND_OPERATIONS))
			{
				return false;		
			}
			// Check texture unit requirements
			size_t numTexUnitsRequested = currPass->getNumTextureUnitStates();
			// Don't trust getNumTextureUnits for programmable
			if(!currPass->hasFragmentProgram())
			{
#if defined(OGRE_PRETEND_TEXTURE_UNITS) && OGRE_PRETEND_TEXTURE_UNITS > 0
				if (numTexUnits > OGRE_PRETEND_TEXTURE_UNITS)
					numTexUnits = OGRE_PRETEND_TEXTURE_UNITS;
#endif
				if (numTexUnitsRequested > numTexUnits)
				{
					if (!autoManageTextureUnits)
					{
						// The user disabled auto pass split
						compileErrors << "Pass " << passNum << 
							": Too many texture units for the current hardware and no splitting allowed."
							<< std::endl;
						return false;
					}
					else if (currPass->hasVertexProgram())
					{
						// Can't do this one, and can't split a programmable pass
						compileErrors << "Pass " << passNum << 
							": Too many texture units for the current hardware and "
							"cannot split programmable passes."
							<< std::endl;
						return false;
					}
				}
			}

			if (currPass->hasVertexProgram())
			{
				// Check vertex program version
				if (!currPass->getVertexProgram()->isSupported() )
				{
					// Can't do this one
					compileErrors << "Pass " << passNum << 
						": Vertex program " << currPass->getVertexProgram()->getName()
						<< " cannot be used - ";
					if (currPass->getVertexProgram()->hasCompileError())
						compileErrors << "compile error.";
					else
						compileErrors << "not supported.";

					compileErrors << std::endl;
					return false;
				}
			}
			if (currPass->hasGeometryProgram())
			{
				// Check geometry program version
				if (!currPass->getGeometryProgram()->isSupported() )
				{
					// Can't do this one
					compileErrors << "Pass " << passNum << 
						": Geometry program " << currPass->getGeometryProgram()->getName()
						<< " cannot be used - ";
					if (currPass->getGeometryProgram()->hasCompileError())
						compileErrors << "compile error.";
					else
						compileErrors << "not supported.";

					compileErrors << std::endl;
					return false;
				}
			}
			if (currPass->hasFragmentProgram())
			{
				// Check fragment program version
				if (!currPass->getFragmentProgram()->isSupported())
				{
					// Can't do this one
					compileErrors << "Pass " << passNum << 
						": Fragment program " << currPass->getFragmentProgram()->getName()
						<< " cannot be used - ";
					if (currPass->getFragmentProgram()->hasCompileError())
						compileErrors << "compile error.";
					else
						compileErrors << "not supported.";

					compileErrors << std::endl;
					return false;
				}
			}
			else
			{
				// Check a few fixed-function options in texture layers
				Pass::TextureUnitStateIterator texi = currPass->getTextureUnitStateIterator();
				size_t texUnit = 0;
				while (texi.hasMoreElements())
				{
					TextureUnitState* tex = texi.getNext();
					// Any Cube textures? NB we make the assumption that any
					// card capable of running fragment programs can support
					// cubic textures, which has to be true, surely?
					if (tex->is3D() && !caps->hasCapability(RSC_CUBEMAPPING))
					{
						// Fail
						compileErrors << "Pass " << passNum << 
							" Tex " << texUnit <<
							": Cube maps not supported by current environment."
							<< std::endl;
						return false;
					}
					// Any 3D textures? NB we make the assumption that any
					// card capable of running fragment programs can support
					// 3D textures, which has to be true, surely?
					if (tex->getTextureType() == TEX_TYPE_3D && !caps->hasCapability(RSC_TEXTURE_3D))
					{
						// Fail
						compileErrors << "Pass " << passNum << 
							" Tex " << texUnit <<
							": Volume textures not supported by current environment."
							<< std::endl;
						return false;
					}
					// Any Dot3 blending?
					if (tex->getColourBlendMode().operation == LBX_DOTPRODUCT &&
						!caps->hasCapability(RSC_DOT3))
					{
						// Fail
						compileErrors << "Pass " << passNum << 
							" Tex " << texUnit <<
							": DOT3 blending not supported by current environment."
							<< std::endl;
						return false;
					}
					++texUnit;
				}

				// We're ok on operations, now we need to check # texture units
				if (!currPass->hasFragmentProgram())
				{
					// Keep splitting this pass so long as units requested > gpu units
					while (numTexUnitsRequested > numTexUnits)
					{
						// chop this pass into many passes
						currPass = currPass->_split(numTexUnits);
						numTexUnitsRequested = currPass->getNumTextureUnitStates();
						// Advance pass number
						++passNum;
						// Reset iterator
						i = mPasses.begin() + passNum;
						// Move the new pass to the right place (will have been created
						// at the end, may be other passes in between)
						assert(mPasses.back() == currPass);
						std::copy_backward(i, (mPasses.end()-1), mPasses.end());
						*i = currPass;
						// Adjust pass index
						currPass->_notifyIndex(passNum);
					}
				}
			}

		}
		// If we got this far, we're ok
		return true;
	}
Beispiel #4
0
///  Shadows config
//---------------------------------------------------------------------------------------------------
void App::changeShadows()
{	
	QTimer ti;  ti.update();  /// time
	
	//  get settings
	bool enabled = pSet->shadow_type != 0;
	bool bDepth = pSet->shadow_type == 3;
	
	pSet->shadow_size = std::max(0,std::min(ciShadowNumSizes-1, pSet->shadow_size));
	int fTex = /*2048*/ ciShadowSizesA[pSet->shadow_size], fTex2 = fTex/2;
	int num = /*3*/ pSet->shadow_count;
	
	// disable 4 shadow textures (does not work because no texcoord's left in shader)
	if (num == 4) num = 3;

	TerrainMaterialGeneratorB::SM2Profile* matProfile = 0;
	
	if (mTerrainGlobals)
	{
		matProfile = (TerrainMaterialGeneratorB::SM2Profile*) mTerrainGlobals->getDefaultMaterialGenerator()->getActiveProfile();
				
		matProfile->setReceiveDynamicShadowsEnabled(enabled);
		matProfile->setReceiveDynamicShadowsLowLod(true);
		matProfile->setGlobalColourMapEnabled(false);

		matProfile->setLayerSpecularMappingEnabled(pSet->ter_mtr >= 1);  // ter mtr
		matProfile->setLayerNormalMappingEnabled(  pSet->ter_mtr >= 2);
		matProfile->setLayerParallaxMappingEnabled(pSet->ter_mtr >= 3);
	}
	
	//  shadows old-
	if (pSet->shadow_type == 1)
	{
		//mSceneMgr->setShadowTechnique(SHADOWTYPE_TEXTURE_ADDITIVE);
		mSceneMgr->setShadowTechnique(SHADOWTYPE_TEXTURE_MODULATIVE);
		//mSceneMgr->setShadowTextureCount(2);
		//mSceneMgr->setShadowTexturePixelFormat(PF_L8);
		//mSceneMgr->setShadowTextureCasterMaterial(StringUtil::BLANK);
		//mSceneMgr->setShadowTextureSelfShadow(true);
		mSceneMgr->setShadowCasterRenderBackFaces(true);

		mSceneMgr->setShadowTextureSettings(fTex, 1, PF_L8);
		mSceneMgr->setShadowColour(ColourValue(0.4, 0.4, 0.4));
		mSceneMgr->setShadowFarDistance(pSet->shadow_dist / 50.f);  // 36 72
		mSceneMgr->setShadowDirLightTextureOffset(0.5);
		//-ShadowCameraSetupPtr mShadowCameraSetup = ShadowCameraSetupPtr(new PlaneOptimalShadowCameraSetup(mPlane));
			ShadowCameraSetupPtr mShadowCameraSetup = ShadowCameraSetupPtr(new LiSPSMShadowCameraSetup());
			mSceneMgr->setShadowCameraSetup(mShadowCameraSetup);/**/
		mSceneMgr->setShadowTextureCountPerLightType(Light::LT_DIRECTIONAL, 1);
		mSceneMgr->setShadowTextureCount(1);
		//return;  // !
	}


	if (!enabled)  {
		mSceneMgr->setShadowTechnique(SHADOWTYPE_NONE);  /*return;*/ }

	else
	{
		// General scene setup
		//mSceneMgr->setShadowTechnique(SHADOWTYPE_TEXTURE_ADDITIVE_INTEGRATED);
		mSceneMgr->setShadowTechnique(SHADOWTYPE_TEXTURE_MODULATIVE_INTEGRATED);
		mSceneMgr->setShadowFarDistance(pSet->shadow_dist);  // 3000
		mSceneMgr->setShadowTextureCountPerLightType(Light::LT_DIRECTIONAL, num);

		if (mPSSMSetup.isNull())
		{
			// shadow camera setup
			PSSMShadowCameraSetup* pssmSetup = new PSSMShadowCameraSetup();
			#ifndef ROAD_EDITOR
			pssmSetup->setSplitPadding(mSplitMgr->mCameras.front()->getNearClipDistance());
			//pssmSetup->setSplitPadding(10);
			pssmSetup->calculateSplitPoints(num, mSplitMgr->mCameras.front()->getNearClipDistance(), mSceneMgr->getShadowFarDistance());
			#else
			pssmSetup->setSplitPadding(mCamera->getNearClipDistance());
			//pssmSetup->setSplitPadding(10);
			pssmSetup->calculateSplitPoints(num, mCamera->getNearClipDistance(), mSceneMgr->getShadowFarDistance());
			#endif
			for (int i=0; i < num; ++i)
			{	int size = i==0 ? fTex : fTex2;
				const Real cAdjfA[5] = {2, 1, 0.5, 0.25, 0.125};
				pssmSetup->setOptimalAdjustFactor(i, cAdjfA[std::min(i, 4)]);
			}
			mPSSMSetup.bind(pssmSetup);
		}
		mSceneMgr->setShadowCameraSetup(mPSSMSetup);

		mSceneMgr->setShadowTextureCount(num);
		for (int i=0; i < num; ++i)
		{	int size = i==0 ? fTex : fTex2;
			mSceneMgr->setShadowTextureConfig(i, size, size, bDepth ? PF_FLOAT32_R : PF_X8B8G8R8);
		}
		
		mSceneMgr->setShadowTextureSelfShadow(bDepth ? true : false);  //-?
		mSceneMgr->setShadowCasterRenderBackFaces(bDepth ? true : false);
		mSceneMgr->setShadowTextureCasterMaterial(bDepth ? "PSSM/shadow_caster" : StringUtil::BLANK);

		if (matProfile && terrain)  {
			matProfile->setReceiveDynamicShadowsDepth(bDepth);
			matProfile->setReceiveDynamicShadowsPSSM(static_cast<PSSMShadowCameraSetup*>(mPSSMSetup.get()));
			MaterialPtr mtr = matProfile->generateForCompositeMap(terrain);
			//LogO(mtr->getBestTechnique()->getPass(0)->getTextureUnitState(0)->getName());
			//LogO(String("Ter mtr: ") + mtr->getName());

		}
		
		#if 0	// shadow tex overlay
		// add the overlay elements to show the shadow maps:
		// init overlay elements
		OverlayManager& mgr = OverlayManager::getSingleton();
		Overlay* overlay;
		
		// destroy if already exists
		if (overlay = mgr.getByName("DebugOverlay"))
			mgr.destroy(overlay);
			
		overlay = mgr.create("DebugOverlay");
		
		for (size_t i = 0; i < num; ++i) {
			TexturePtr tex = mSceneMgr->getShadowTexture(i);

			// Set up a debug panel to display the shadow
			
			if (MaterialManager::getSingleton().resourceExists("Ogre/DebugTexture" + toStr(i)))
				MaterialManager::getSingleton().remove("Ogre/DebugTexture" + toStr(i));
			MaterialPtr debugMat = MaterialManager::getSingleton().create(
				"Ogre/DebugTexture" + toStr(i), 
				ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME);
				
			debugMat->getTechnique(0)->getPass(0)->setLightingEnabled(false);
			TextureUnitState *t = debugMat->getTechnique(0)->getPass(0)->createTextureUnitState(tex->getName());
			t->setTextureAddressingMode(TextureUnitState::TAM_CLAMP);

			OverlayContainer* debugPanel;
			
			// destroy container if exists
			try
			{
				if (debugPanel = 
					static_cast<OverlayContainer*>(
						mgr.getOverlayElement("Ogre/DebugTexPanel" + toStr(i)
					)))
					mgr.destroyOverlayElement(debugPanel);
			}
			catch (Ogre::Exception&) {}
			
			debugPanel = (OverlayContainer*)
				(OverlayManager::getSingleton().createOverlayElement("Panel", "Ogre/DebugTexPanel" + StringConverter::toString(i)));
			debugPanel->_setPosition(0.8, i*0.25);
			debugPanel->_setDimensions(0.2, 0.24);
			debugPanel->setMaterialName(debugMat->getName());
			debugPanel->show();
			overlay->add2D(debugPanel);
			overlay->show();
		}
		#endif
	}
	
	materialFactory->setNumShadowTex(num);
	materialFactory->setShadows(pSet->shadow_type != 0);
	materialFactory->setShadowsDepth(bDepth);
	materialFactory->generate();
	
	// set terrain lightmap texture and terrainWorldSize for all materials that need it
	if (terrain) // naive check if a game has been started already
	{
		for (std::vector<std::string>::const_iterator it = materialFactory->terrainLightMapMtrs.begin();
			it != materialFactory->terrainLightMapMtrs.end(); ++it)
		{
			MaterialPtr mtr = MaterialManager::getSingleton().getByName( (*it) );
			
			if (!mtr.isNull())
			{	Material::TechniqueIterator techIt = mtr->getTechniqueIterator();
				while (techIt.hasMoreElements())
				{	Technique* tech = techIt.getNext();
					Technique::PassIterator passIt = tech->getPassIterator();
					while (passIt.hasMoreElements())
					{	Pass* pass = passIt.getNext();
						Pass::TextureUnitStateIterator tusIt = pass->getTextureUnitStateIterator();
						while (tusIt.hasMoreElements())
						{
							TextureUnitState* tus = tusIt.getNext();
							if (tus->getName() == "terrainLightMap")
							{
								tus->setTextureName( terrain->getLightmap()->getName() );
								pass->getFragmentProgramParameters()->setNamedConstant( "terrainWorldSize", Real( sc.td.fTerWorldSize ) );
							}
						}
			}	}	}
		}
	}
	
	// -------------------   update the paged-geom materials
	
	// grass is not cloned, just need to set new shader parameters
	if (grass)
	{
		GrassLoader *grassLoader = static_cast<GrassLoader*>(grass->getPageLoader());
		for (std::list<GrassLayer*>::iterator it= grassLoader->getLayerList().begin();
			it != grassLoader->getLayerList().end(); ++it)
		{
			GrassLayer* layer = (*it);
			layer->applyShader();
		}
	}
	
	// trees are more complicated since they are cloned
	if(trees)
	{
		trees->reloadGeometry();
		std::vector<ResourcePtr> reosurceToDelete;
		ResourceManager::ResourceMapIterator it = MaterialManager::getSingleton().getResourceIterator();
		while (it.hasMoreElements())
		{
			ResourcePtr material = it.getNext();
			String materialName = material->getName();
			std::string::size_type pos =materialName.find("BatchMat|");
			if( pos != std::string::npos ) {
				reosurceToDelete.push_back(material);
			}
		}
		for(int i=0;i<reosurceToDelete.size();i++)
		{
			MaterialManager::getSingleton().remove(reosurceToDelete[i]);
		}
	}
	UpdPSSMMaterials();

	ti.update();	/// time
	float dt = ti.dt * 1000.f;
	LogO(String("::: Time Shadows: ") + toStr(dt) + " ms");
}
Beispiel #5
0
void CarReflection::Create()
{
	bFirstFrame = true;
	if (pSet->refl_mode == "single")  cubetexName = "ReflectionCube"; // single: use 1st cubemap
	else if (pSet->refl_mode == "full")
	{
		cubetexName = "ReflectionCube" + toStr(iIndex);
		// first cubemap: no index
		if (cubetexName == "ReflectionCube0")
			cubetexName = "ReflectionCube";
	}
	else /* static */
		cubetexName = "ReflectionCube";
	
	TextureManager* tm = TextureManager::getSingletonPtr();
	int size = ciShadowSizesA[pSet->refl_size];  // /2 ?

	//  create cube render texture
	if (! (pSet->refl_mode == "single" && iIndex != 0) )
	{
		cubetex = tm->createManual(cubetexName, 
			ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, TEX_TYPE_CUBE_MAP, 
			size,size, 0/*mips*/, PF_R8G8B8, TU_RENDERTARGET);
			//LogO("created rt cube");

		for (int face = 0; face < 6; face++)
		{
			Camera* mCam = pSceneMgr->createCamera("Reflect_" + toStr(iIndex) + "_" + toStr(face));
			mCam->setAspectRatio(1.0f);  mCam->setFOVy(Degree(90));
			mCam->setNearClipDistance(0.1);
			//mCam->setFarClipDistance(pSet->refl_dist);  //sky-

			RenderTarget* mRT = cubetex->getBuffer(face)->getRenderTarget();
			//LogO( "rt face Name: " + mRT->getName() );
			mRT->removeAllViewports();
			Viewport* vp = mRT->addViewport(mCam);
			vp->setOverlaysEnabled(false);
			vp->setVisibilityMask(RV_MaskReflect);
			mRT->setAutoUpdated(false);
			//mRT->addListener(this);  //-
			mCam->setPosition(Vector3::ZERO);

			Vector3 lookAt(0,0,0), up(0,0,0), right(0,0,0);  switch(face)
			{
				case 0:  lookAt.x =-1;  up.y = 1;  right.z = 1;  break;  // +X
				case 1:  lookAt.x = 1;  up.y = 1;  right.z =-1;  break;	 // -X
				case 2:  lookAt.y =-1;  up.z = 1;  right.x = 1;  break;	 // +Y
				case 3:  lookAt.y = 1;  up.z =-1;  right.x = 1;  break;	 // -Y
				case 4:  lookAt.z = 1;  up.y = 1;  right.x =-1;  break;	 // +Z
				case 5:  lookAt.z =-1;  up.y = 1;  right.x =-1;  break;	 // -Z
			}
			Quaternion orient( right, up, lookAt );  mCam->setOrientation( orient );
			pCams[face] = mCam;
			pRTs[face] = mRT;
		}
	}
	
	// Iterate through our materials and add an index to ReflectionCube texture reference
	for (int i=0; i < NumMaterials; i++)
	{
		MaterialPtr mtr = MaterialManager::getSingleton().getByName(sMtr[i]);
		if (!mtr.isNull())
		{	Material::TechniqueIterator techIt = mtr->getTechniqueIterator();
			while (techIt.hasMoreElements())
			{	Technique* tech = techIt.getNext();
				Technique::PassIterator passIt = tech->getPassIterator();
				while (passIt.hasMoreElements())
				{	Pass* pass = passIt.getNext();
					Pass::TextureUnitStateIterator tusIt = pass->getTextureUnitStateIterator();
					while (tusIt.hasMoreElements())
					{	
						TextureUnitState* tus = tusIt.getNext();
						if (tus->getTextureName() == "ReflectionCube")
							tus->setTextureName(cubetexName);
	}	}	}	}	}
}
void MaterialFactory::setShaderParams(MaterialPtr mat)
{
	if (mat.isNull()) return;
		
	Material::TechniqueIterator techIt = mat->getTechniqueIterator();
	while (techIt.hasMoreElements())
	{
		Technique* tech = techIt.getNext();
		Technique::PassIterator passIt = tech->getPassIterator();
		while (passIt.hasMoreElements())
		{
			Pass* pass = passIt.getNext();
								
			if (pass->hasFragmentProgram())
			{
				// shadow fading parameters
				if ( getShadowsFade()
					&& pass->getFragmentProgramParameters()->_findNamedConstantDefinition("fadeStart_farDist", false)
					&& mSceneMgr
				)
				{
					float fadeDist;
					if (mSceneMgr->getShadowFarDistance() != 0)
						fadeDist = getShadowsFadeDistance()/mSceneMgr->getShadowFarDistance();
					else
						fadeDist = 0.f;
														
					pass->getFragmentProgramParameters()->setNamedConstant("fadeStart_farDist", Vector3(
						fadeDist,
						mSceneMgr->getShadowFarDistance(),
						float(getShadowsFade())
					));
				}
				// terrain lightmap name & size
				if ( mTerrain && !mTerrain->getLightmap().isNull() )
				{
					if (pass->getFragmentProgramParameters()->_findNamedConstantDefinition("terrainWorldSize", false))
						pass->getFragmentProgramParameters()->setNamedConstant( "terrainWorldSize", Real( mTerrain->getWorldSize() ) );
					
					Pass::TextureUnitStateIterator tusIt = pass->getTextureUnitStateIterator();
					while (tusIt.hasMoreElements())
					{
						TextureUnitState* tus = tusIt.getNext();
						if (tus->getName() == "terrainLightMap")
						{
							tus->setTextureName( mTerrain->getLightmap()->getName() );
						}
					}
				}
				
				if (pass->getFragmentProgramParameters()->_findNamedConstantDefinition("invTerSize", false))
					pass->getFragmentProgramParameters()->setNamedConstant("invTerSize", 1.f / Real(pApp->sc.td.fTerWorldSize));

				// pssm split points
				if ( pass->getFragmentProgramParameters()->_findNamedConstantDefinition("pssmSplitPoints", false) && mPSSM)
				{
					const PSSMShadowCameraSetup::SplitPointList& splitPointList = mPSSM->getSplitPoints();
					Vector4 splitPoints;
					for (size_t i = 0; i < splitPointList.size(); ++i)
						splitPoints[i] = splitPointList[i];
						
					pass->getFragmentProgramParameters()->setNamedConstant("pssmSplitPoints", splitPoints);
				}
			}
		}
	}
}