示例#1
0
//-----------------------------------------------------------------------------
bool Platform::dumpPath(const char *path, Vector<Platform::FileInfo>& fileVector, S32 depth)
{
	if (isCachePath(path))
	{
		PROFILE_START(dumpPath);
		const S32 len = dStrlen(path) + 1;
	    char newpath[255];

		strcpy(newpath, path);

	   if(newpath[len - 2] == '/')
		  newpath[len - 2] = '\0'; // cut off the trailing slash, if there is one

	   bool ret = recurseDumpPathCache( newpath, fileVector, depth);
	   PROFILE_END();

	   return ret;
	}

   PROFILE_START(dumpPath);
   bool ret = android_DumpPath( path, fileVector, depth);
   PROFILE_END();
   
   return ret;
}
示例#2
0
//-----------------------------------------------------------------------------
bool Platform::dumpDirectories(const char *path, Vector<StringTableEntry> &directoryVector, S32 depth, bool noBasePath)
{
	if (isCachePath(path))
	{
	   PROFILE_START(dumpDirectories);

	   ResourceManager->initExcludedDirectories();

	   const S32 len = dStrlen(path)+1;
	   char newpath[len];
	   dSprintf(newpath, len, "%s", path);
	   if(newpath[len - 1] == '/')
		  newpath[len - 1] = '\0'; // cut off the trailing slash, if there is one

		// Insert base path to follow what Windows does.
		if ( !noBasePath )
			directoryVector.push_back(StringTable->insert(newpath));

		bool ret = recurseDumpDirectoriesCache(newpath, "", directoryVector, depth, noBasePath);
	   PROFILE_END();

	   return ret;
	}

   PROFILE_START(dumpDirectories);
   ResourceManager->initExcludedDirectories();
   bool ret = android_DumpDirectories(path, "", directoryVector, depth, noBasePath);
   PROFILE_END();
   
   return ret;
}
示例#3
0
void TerrainRenderer::RenderTerrainShader(const CShaderDefines& context, ShadowMap* shadow, bool filtered)
{
	ENSURE(m->phase == Phase_Render);

	std::vector<CPatchRData*>& visiblePatches = filtered ? m->filteredPatches : m->visiblePatches;
	std::vector<CDecalRData*>& visibleDecals = filtered ? m->filteredDecals : m->visibleDecals;
	if (visiblePatches.empty() && visibleDecals.empty())
		return;

	// render the solid black sides of the map first
	CShaderTechniquePtr techSolid = g_Renderer.GetShaderManager().LoadEffect(str_gui_solid);
	techSolid->BeginPass();
	CShaderProgramPtr shaderSolid = techSolid->GetShader();
	shaderSolid->Uniform(str_transform, g_Renderer.GetViewCamera().GetViewProjection());
	shaderSolid->Uniform(str_color, 0.0f, 0.0f, 0.0f, 1.0f);

	PROFILE_START("render terrain sides");
	for (size_t i = 0; i < visiblePatches.size(); ++i)
		visiblePatches[i]->RenderSides(shaderSolid);
	PROFILE_END("render terrain sides");

	techSolid->EndPass();

	PROFILE_START("render terrain base");
	CPatchRData::RenderBases(visiblePatches, context, shadow);
	PROFILE_END("render terrain base");

	// no need to write to the depth buffer a second time
	glDepthMask(0);

	// render blend passes for each patch
	PROFILE_START("render terrain blends");
	CPatchRData::RenderBlends(visiblePatches, context, shadow, false);
	PROFILE_END("render terrain blends");

	PROFILE_START("render terrain decals");
	CDecalRData::RenderDecals(visibleDecals, context, shadow, false);
	PROFILE_END("render terrain decals");

	// restore OpenGL state
	g_Renderer.BindTexture(1, 0);
	g_Renderer.BindTexture(2, 0);
	g_Renderer.BindTexture(3, 0);

	glDepthMask(1);
	glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
	glDisable(GL_BLEND);
}
示例#4
0
void SceneRenderState::renderObjects( SceneObject** objects, U32 numObjects )
{
   // Let the objects batch their stuff.

   PROFILE_START( SceneRenderState_prepRenderImages );
   for( U32 i = 0; i < numObjects; ++ i )
   {
      SceneObject* object = objects[ i ];
      object->prepRenderImage( this );
   }

#ifdef TORQUE_EXPERIMENTAL_EC
   U32 interfaceCount = RenderComponentInterface::all.size();
   for (U32 i = 0; i < RenderComponentInterface::all.size(); i++)
   {
      Component* comp = dynamic_cast<Component*>(RenderComponentInterface::all[i]);

      if (comp->isClientObject() && comp->isActive())
      {
         RenderComponentInterface::all[i]->prepRenderImage(this);
      }
   }
#endif

   PROFILE_END();

   // Render what the objects have batched.

   getRenderPass()->renderPass( this );
}
示例#5
0
void SortModelRenderer::PrepareModels()
{
    CMatrix3D worldToCam;

    if (m->models.size() == 0)
        return;

    g_Renderer.GetViewCamera().m_Orientation.GetInverse(worldToCam);

    for(std::vector<SModel*>::iterator it = m->models.begin(); it != m->models.end(); ++it)
    {
        SModel* smdl = *it;
        CModel* model = smdl->GetModel();

        ENSURE(model->GetRenderData() == smdl);

        m->vertexRenderer->UpdateModelData(model, smdl->m_Data, smdl->m_UpdateFlags);
        smdl->m_UpdateFlags = 0;

        CVector3D modelpos = model->GetTransform().GetTranslation();

        modelpos = worldToCam.Transform(modelpos);

        smdl->m_Distance = modelpos.Z;
    }

    PROFILE_START( "sorting transparent" );
    std::sort(m->models.begin(), m->models.end(), SortModelsByDist());
    PROFILE_END( "sorting transparent" );
}
示例#6
0
文件: AvHTurret.cpp 项目: Arkshine/NS
// This function takes a lot of CPU, so make sure it's not called often!  Don't call this function directly, use UpdateEnemy instead whenever possible.
CBaseEntity* AvHTurret::FindBestEnemy()
{
    PROFILE_START()
	CBaseEntity* theEntityList[100];
	
	int theMaxRange = this->GetXYRange();
	
	Vector delta = Vector(theMaxRange, theMaxRange, theMaxRange);
	CBaseEntity* theCurrentEntity = NULL;
	CBaseEntity* theBestPlayer = NULL;
	CBaseEntity* theBestStructure = NULL;

	float theCurrentEntityRange = 100000;
	
	// Find only monsters/clients in box, NOT limited to PVS
	int theCount = UTIL_EntitiesInBox(theEntityList, 100, this->pev->origin - delta, this->pev->origin + delta, FL_CLIENT | FL_MONSTER);
	for(int i = 0; i < theCount; i++ )
	{
		theCurrentEntity = theEntityList[i];
		if((theCurrentEntity != this) && theCurrentEntity->IsAlive())
		{
			// the looker will want to consider this entity
			// don't check anything else about an entity that can't be seen, or an entity that you don't care about.
			if(this->IRelationship(theCurrentEntity ) != R_NO && FInViewCone(theCurrentEntity) && !FBitSet(theCurrentEntity->pev->flags, FL_NOTARGET))
			{
				AvHPlayer* thePlayer = dynamic_cast<AvHPlayer*>(theCurrentEntity);
				if(!thePlayer || thePlayer->GetCanBeAffectedByEnemies())
				{
					if(this->GetIsValidTarget(theCurrentEntity))
					{
						// Find nearest enemy
						float theRangeToTarget = VectorDistance2D(this->pev->origin, theCurrentEntity->pev->origin);
						if(theRangeToTarget < theCurrentEntityRange)
						{
                            // FVisible is expensive, so defer until necessary
                            if(!this->GetRequiresLOS() || FVisible(theCurrentEntity))
                            {
                                theCurrentEntityRange = theRangeToTarget;
								if ( thePlayer ) 
								{
									theBestPlayer = theCurrentEntity;
								}
								else
								{
									theBestStructure = theCurrentEntity;
								}
                            }
						}
					}
				}
			}
		}
	}
    PROFILE_END(kAvHTurretFindBestEnemy);

	return (theBestPlayer != NULL ) ? theBestPlayer : theBestStructure;
}
示例#7
0
void SceneObject::setRenderTransform(const MatrixF& mat)
{
   PROFILE_START(SceneObj_setRenderTransform);
   mRenderObjToWorld = mRenderWorldToObj = mat;
   mRenderWorldToObj.affineInverse();

   AssertFatal(mObjBox.isValidBox(), "Bad object box!");
   resetRenderWorldBox();
   PROFILE_END();
}
示例#8
0
void AtlasClipMapBatcher::sort()
{
   PROFILE_START(AtlasClipMapBatcher_sort);

   // Sort our elements. The other lists are already good to go, and there's
   // no benefit to drawing them in a specific order as this pass (the first
   // pass) will already set up the Z buffer.
   for(S32 i=1; i<4; i++)
      dQsort(mRenderList[i].address(),mRenderList[i].size(),sizeof(RenderNote*),cmpRenderNote);

   PROFILE_END();
}
bool WindEmitter::findBest(   const Point3F& cameraPos, 
                              const VectorF& cameraDir,
                              F32 viewDistance,
                              U32 maxResults,
                              WindEmitterList* results )
{
   PROFILE_START(WindEmitter_findBest);

   // Build a sphere from the camera point.
	SphereF cameraSphere;
   cameraSphere.center = cameraPos;
   cameraSphere.radius = viewDistance;

   // Collect the active spheres within the camera space and score them.
   WindEmitterList best;
   WindEmitterList::iterator iter = smAllEmitters.begin();
   for ( ; iter != smAllEmitters.end(); iter++ )
   {        
      const SphereF& sphere = *(*iter);

      // Skip any spheres outside of our camera range or that are disabled.
      if ( !(*iter)->mEnabled || !cameraSphere.isIntersecting( sphere ) )
         continue;

      // Simple score calculation...
      //
      // score = ( radius / distance to camera ) * dot( cameraDir, vector from camera to sphere )
      //
      Point3F vect = sphere.center - cameraSphere.center;
      F32 dist = vect.len();
      (*iter)->mScore = dist * sphere.radius;
      vect /= getMax( dist, 0.001f );
      (*iter)->mScore *= mDot( vect, cameraDir );

      best.push_back( *iter );
   }

   // Sort the results by score!
   dQsort( best.address(), best.size(), sizeof(WindEmitter*), &WindEmitter::_sortByScore );

   // Clip the results to the max requested.
   if ( best.size() > maxResults )
      best.setSize( maxResults );

   // Merge the results and return.
   results->merge( best );

   PROFILE_END(); // WindEmitter_findBest

   return best.size() > 0;
}
示例#10
0
void AtlasClipMapBatcher::renderClipMap( SceneGraphData& sgData, BaseMatInstance* overrideMat )
{
   PROFILE_START(AtlasClipMapBatcher_renderClipMap);

   for(S32 curBin=1; curBin<4; curBin++)
   {
      // If bin is empty, skip.
      if(mRenderList[curBin].size() == 0)
         continue;

      for(S32 i=0; i<mRenderList[curBin].size(); i++)
      {
         // Grab the render note.
         const RenderNote *rn = mRenderList[curBin][i];

         // Set up clipmap levels.
         if( !mFixedFunction )
         {
            BaseMatInstance* material = overrideMat;
            if( !material )
               switch( rn->levelCount )
               {
               case 2:     material = mClipMap->getMaterialAndTextures( rn->levelEnd, rn->levelStart, -1, -1, false ); break;
               case 3:     material = mClipMap->getMaterialAndTextures( rn->levelEnd, rn->levelStart + 1, rn->levelStart, -1, false ); break;
               case 4:     material = mClipMap->getMaterialAndTextures( rn->levelEnd, rn->levelStart + 2, rn->levelStart + 1, rn->levelStart, false ); break;
               default:    material = MaterialManager::get()->getWarningMatInstance();
               }

            while( material->setupPass( mState, sgData ) )
               rn->chunk->render();
         }
         else
         {
            Point4F clipmapMapping;
            for( U32 curLayer = rn->levelEnd; curLayer >= rn->levelStart; -- curLayer )
            {
               BaseMatInstance* material = overrideMat;
               if( !material )
                  material = mClipMap->bindTexturesFF( curLayer, clipmapMapping, curLayer == rn->levelEnd, false );

               while( material->setupPass( mState, sgData ) )
                  rn->chunk->render();
            }
         }
      }
   }

   PROFILE_END();
}
示例#11
0
// Updated transforms
void PolygonSortModelRenderer::UpdateModelData(CModel* model, void* data, int updateflags)
{
    PSModel* psmdl = (PSModel*)data;

    if (updateflags & (RENDERDATA_UPDATE_VERTICES|RENDERDATA_UPDATE_COLOR))
    {
        CModelDefPtr mdef = model->GetModelDef();
        size_t numVertices = mdef->GetNumVertices();

        // build vertices

        // allocate working space for computing normals
        if (numVertices > m->normalsNumVertices)
        {
            rtl_FreeAligned(m->normals);

            size_t newSize = round_up_to_pow2(numVertices);
            m->normals = (char*)rtl_AllocateAligned(newSize*16, 16);
            m->normalsNumVertices = newSize;
        }

        VertexArrayIterator<CVector3D> Position = psmdl->m_Position.GetIterator<CVector3D>();
        VertexArrayIterator<CVector3D> Normal = VertexArrayIterator<CVector3D>(m->normals, 16);

        ModelRenderer::BuildPositionAndNormals(model, Position, Normal);

        VertexArrayIterator<SColor4ub> Color = psmdl->m_Color.GetIterator<SColor4ub>();

        ModelRenderer::BuildColor4ub(model, Normal, Color);

        // upload everything to vertex buffer
        psmdl->m_Array.Upload();
    }

    // resort model indices from back to front, according to the view camera position - and store
    // the returned sqrd distance to the centre of the nearest triangle
    // Use the view camera instead of the cull camera because:
    //  a) polygon sorting implicitly uses the view camera (and changing that would be costly)
    //  b) using the cull camera is likely not interesting from a debugging POV
    PROFILE_START( "sorting transparent" );

    CMatrix3D worldToCam;
    g_Renderer.GetViewCamera().m_Orientation.GetInverse(worldToCam);

    psmdl->BackToFrontIndexSort(worldToCam);
    PROFILE_END( "sorting transparent" );
}
void GFXD3D9QueryFence::issue()
{
   PROFILE_START( GFXD3D9QueryFence_issue );

   // Create the query if we need to
   if( mQuery == NULL )
   {
      HRESULT hRes = static_cast<GFXD3D9Device *>( mDevice )->getDevice()->CreateQuery( D3DQUERYTYPE_EVENT, &mQuery );

      AssertFatal( hRes != D3DERR_NOTAVAILABLE, "Hardware does not support D3D9 Queries, this should be caught before this fence type is created" );
      AssertISV( hRes != E_OUTOFMEMORY, "Out of memory" );
   }

   // Issue the query
   mQuery->Issue( D3DISSUE_END );

   PROFILE_END();
}
示例#13
0
		ReturnValue GraphicsService::Render()
		{
			PostEffect::Begin();

			Render::SetOrthoMode();
			Render::EnableOrthoMode();
			Render::EnableAlphaBlend();

			GL_CHECK( glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT) );

			PROFILE_BEGIN("Batcher");
			Batcher::FlushAll();
			PROFILE_END();

			PostEffect::End();

			Debug::OpenGL::FlushErrors("GraphicsService::Render()");
			return RETURN_VALUE_OK;
		}
示例#14
0
CDbDataReader CDbCommand::_queryInternal(const CCommandParameterMap & params) throw (CDbException)
{
	mergeParametersWith(params);
	string parametersDump = _makeParametersDump(_params);
#ifdef CWS_DEBUG
	Cws::trace("Executing SQL: " + _text + parametersDump, "system.db.CDbCommand");
#endif

	try {
		SAConnection * connection = _connection->getConnection();
		_saCommand = new SACommand(connection, _text.c_str(), SA_CmdSQLStmt);
		if (connection->Client() == SA_MySQL_Client) {
			_saCommand->setOption("UseStatement") = "TRUE";
		}
		for (CCommandParameterMap::const_iterator iter = _params.begin(); iter != _params.end(); ++iter) {
			iter->second.get()->bind(_saCommand);
		}
		PROFILE_BEGIN("Executing SQL: " + _text + parametersDump);
		_saCommand->Execute();
		PROFILE_END();
		return CDbDataReader(_saCommand);

	} catch (const SAException & e) {

		string message = e.ErrText().GetMultiByteChars();
		stringstream ss;
		ss << "CDbCommand::_queryInternal() failed: " << message
		   << ". Code: " << (int)e.ErrNativeCode();
		Cws::log(
			"CDbCommand::_queryInternal() failed: " + ss.str()
			+ ". The SQL statement executed was: " + _text + "."
		);
#ifdef CWS_DEBUG
		message += ". The SQL statement executed was: " + _text + parametersDump;
#endif
		throw CDbException(
			"CDbCommand failed to execute the SQL statement: " + message,
			(int)e.ErrNativeCode()
		);
	}
}
示例#15
0
void AtlasClipMapBatcher::init(ClipMap *acm, SceneState *state, AtlasInstance *renderer)
{
   PROFILE_START(AtlasClipMapBatcher_init);

   // Note our render state.
   mClipMap = acm;
   mState = state;
   mObject = renderer;
   
   // Empty the render lists...
   for(S32 i=1; i<4; i++)
      mRenderList[i].clear();
   mDetailList.clear();
   mLightList.clear();
   mFogList.clear();

   // And clear the render notes.
   mRenderNoteAlloc.freeBlocks();

   PROFILE_END();
}
示例#16
0
void ProcessList::advanceObjects()
{
   PROFILE_START(ProcessList_AdvanceObjects);

   // A little link list shuffling is done here to avoid problems
   // with objects being deleted from within the process method.
   ProcessObject list;
   list.plLinkBefore(mHead.mProcessLink.next);
   mHead.plUnlink();
   for (ProcessObject * pobj = list.mProcessLink.next; pobj != &list; pobj = list.mProcessLink.next)
   {
      pobj->plUnlink();
      pobj->plLinkBefore(&mHead);
      
      onTickObject(pobj);
   }

   mTotalTicks++;

   PROFILE_END();
}
示例#17
0
   void vertexBufferCopy(vertexType vtype)
   {
      PROFILE_SCOPE(Terrain_vbufferCopy);

      // Do vertexes
      if (vtype == vertexTypeFullClipMapping)
      {
         GVertexBufferHandle<GAtlasVert2>  v(GRAPHIC, mCurVertex, GBufferTypeVolatile);
         PROFILE_START(Terrain_bufferCopy_lockV);
         v.lock();
         PROFILE_END();

         dMemcpy(&v[0], &mVertexStore[0], sizeof(GAtlasVert2) * mCurVertex);

         PROFILE_START(Terrain_bufferCopy_unlockV);
         v.unlock();
         PROFILE_END();
         GRAPHIC->setVertexBuffer(v);
      }
      else if (vtype == vertexTypeDLight)
      {
         GVertexBufferHandle<GVertexPCNTT> vPCNTT(GRAPHIC, mCurVertex, GBufferTypeVolatile);
         PROFILE_START(Terrain_bufferCopy_lockVPCNTT);
         vPCNTT.lock();
         PROFILE_END();

         dMemcpy(&vPCNTT[0], &mVertexStorePCNTT[0], sizeof(GVertexPCNTT) * mCurVertex);

         PROFILE_START(Terrain_bufferCopy_unlockVPCNTT);
         vPCNTT.unlock();
         PROFILE_END();
         GRAPHIC->setVertexBuffer(vPCNTT);
      }
      else
      {
         GVertexBufferHandle<GVertexPCNT> vPCNT(GRAPHIC, mCurVertex, GBufferTypeVolatile);
         PROFILE_START(Terrain_bufferCopy_lockVPCNT);
         vPCNT.lock();
         PROFILE_END();

         dMemcpy(&vPCNT[0], &mVertexStorePCNT[0], sizeof(GVertexPCNT) * mCurVertex);

         PROFILE_START(Terrain_bufferCopy_unlockVPCNT);
         vPCNT.unlock();
         PROFILE_END();
         GRAPHIC->setVertexBuffer(vPCNT);
      }
   }
示例#18
0
bool ProcessList::advanceTime(SimTime timeDelta)
{
   PROFILE_START(ProcessList_AdvanceTime);

   // some drivers change the FPU control state, which will break our control object simulation
   // (leading to packet mismatch errors due to small FP differences).  So set it to the known 
   // state before advancing.
   // TODO: revisit this.
   //U32 mathState = Platform::getMathControlState();
   //Platform::setMathControlStateKnown();

   if (mDirty) 
      orderList();

   SimTime targetTime = mLastTime + timeDelta;
   SimTime targetTick = targetTime - (targetTime % TickMs);
   SimTime tickDelta = targetTick - mLastTick;
   bool tickPass = mLastTick != targetTick;

   if ( tickPass )
      mPreTick.trigger();

   // Advance all the objects.
   for (; mLastTick != targetTick; mLastTick += TickMs)
      onAdvanceObjects();

   mLastTime = targetTime;
   mLastDelta = ((TickMs - ((targetTime+1) % TickMs)) % TickMs) / F32(TickMs);

   if ( tickPass )
      mPostTick.trigger( tickDelta );

   // restore math control state in case others are relying on it being a certain value
   // TODO: revisit this.
   //Platform::setMathControlState(mathState);

   PROFILE_END();
   return tickPass;
}
示例#19
0
文件: unicode.cpp 项目: fr1tz/alux3d
//-----------------------------------------------------------------------------
U32 convertUTF16toUTF8( const UTF16 *unistring, UTF8  *outbuffer, U32 len)
{
   AssertFatal(len >= 1, "Buffer for unicode conversion must be large enough to hold at least the null terminator.");
   PROFILE_START(convertUTF16toUTF8);
   U32 walked, nCodeunits, codeunitLen;
   UTF32 middleman;
   
   nCodeunits=0;
   while( *unistring != '\0' && nCodeunits + 3 < len )
   {
      walked = 1;
      middleman  = oneUTF16toUTF32(unistring,&walked);
      codeunitLen = oneUTF32toUTF8(middleman, &outbuffer[nCodeunits]);
      unistring += walked;
      nCodeunits += codeunitLen;
   }

   nCodeunits = getMin(nCodeunits,len - 1);
   outbuffer[nCodeunits] = '\0';
   
   PROFILE_END();
   return nCodeunits;
}
示例#20
0
long unsigned int CDbCommand::execute(const CCommandParameterMap & params) throw (CDbException)
{
	mergeParametersWith(params);
	string parametersDump = _makeParametersDump(_params);
#ifdef CWS_DEBUG
	Cws::trace("Executing SQL: " + _text + parametersDump, "system.db.CDbCommand");
#endif
	try {
		SAConnection * connection = _connection->getConnection();
		_saCommand = new SACommand(connection);
		_saCommand->setCommandText(_text.c_str());
		for (CCommandParameterMap::const_iterator iter = _params.begin(); iter != _params.end(); ++iter) {
			iter->second.get()->bind(_saCommand);
		}
		PROFILE_BEGIN("Executing SQL: " + _text + parametersDump);
		_saCommand->Execute();
		connection->Commit();
		PROFILE_END();
		return _saCommand->RowsAffected();

	} catch (const SAException & e) {

		string message = e.ErrText().GetMultiByteChars();
		Cws::log(
			"CDbCommand::execute() failed: " + message
			+ ". The SQL statement executed was: " + _text + "."
		);
#ifdef CWS_DEBUG
		message += ". The SQL statement executed was: " + _text + parametersDump;
#endif
		throw CDbException(
			"CDbCommand failed to execute the SQL statement: " + message,
			(int)e.ErrNativeCode()
		);
	}
	return 0;
}
示例#21
0
// Process a time event and update all sub-processes
void processTimeEvent(S32 elapsedTime)
{
   PROFILE_START(ProcessTimeEvent);

   // If recording a video and not playinb back a journal, override the elapsedTime
   if (VIDCAP->isRecording() && !Journal::IsPlaying())
      elapsedTime = VIDCAP->getMsPerFrame();   
   
   // cap the elapsed time to one second
   // if it's more than that we're probably in a bad catch-up situation
   if(elapsedTime > 1024)
      elapsedTime = 1024;
   
   U32 timeDelta;
   if(ATTS(gTimeAdvance))
      timeDelta = ATTS(gTimeAdvance);
   else
      timeDelta = (U32) (elapsedTime * ATTS(gTimeScale));
   
   Platform::advanceTime(elapsedTime);
   
   // Don't build up more time than a single tick... this makes the sim
   // frame rate dependent but is a useful hack for singleplayer.
   if ( ATTS(gFrameSkip) )
      if ( timeDelta > TickMs )
         timeDelta = TickMs;

   bool tickPass;
   
   PROFILE_START(ServerProcess);
   tickPass = serverProcess(timeDelta);
   PROFILE_END();
   
   PROFILE_START(ServerNetProcess);
   // only send packets if a tick happened
   if(tickPass)
      GNet->processServer();
   // Used to indicate if server was just ticked.
   Con::setBoolVariable( "$pref::hasServerTicked", tickPass );
   PROFILE_END();

   
   PROFILE_START(SimAdvanceTime);
   Sim::advanceTime(timeDelta);
   PROFILE_END();
   
   PROFILE_START(ClientProcess);
   tickPass = clientProcess(timeDelta);
   // Used to indicate if client was just ticked.
   Con::setBoolVariable( "$pref::hasClientTicked", tickPass );
   PROFILE_END_NAMED(ClientProcess);
   
   PROFILE_START(ClientNetProcess);
   if(tickPass)
      GNet->processClient();
   PROFILE_END();
   
   GNet->checkTimeouts();
   
   gFPS.update();

   // Give the texture manager a chance to cleanup any
   // textures that haven't been referenced for a bit.
   if( GFX )
      TEXMGR->cleanupCache( 5 );

   PROFILE_END();
   
   // Update the console time
   Con::setFloatVariable("Sim::Time",F32(Platform::getVirtualMilliseconds()) / 1000);
}
示例#22
0
void ClipMap::initClipStack()
{
   PROFILE_START(ClipMap_initClipStack);

   // Clear out all the levels.
   while(mLevels.size())
   {
      mLevels.last().mDebugTex = NULL;
      mLevels.last().mTex = NULL;
      mLevels.pop_back();
   }

   // What texture profile are we going to be using?
   AssertFatal(mImageCache, "ClipMap::initClipStack - must have image cache by this point.");
   GTextureProfile *texProfile = mImageCache->isRenderToTargetCache() 
                                    ? &ClipMapTextureRTProfile : &ClipMapTextureProfile;

   // Figure out how many clipstack textures we'll have.
   mClipStackDepth = getBinLog2(mTextureSize) - getBinLog2(mClipMapSize) + 1;
   mLevels.setSize(mClipStackDepth);

   // Print a little report on our allocation.
   Con::printf("Allocating a %d px clipmap for a %dpx source texture.", mClipMapSize, mTextureSize);
   Con::printf("   - %d base clipstack entries, + 1 cap.", mClipStackDepth - 1);

   U32 baseTexSize = (mClipMapSize * mClipMapSize * 4);
   Con::printf("   - Using approximately %fMB of texture memory.", 
      (F32(baseTexSize * mClipStackDepth) * 1.33) / (1024.0*1024.0));

   // First do our base textures - they are not mipped.
   // We rely on auto-mipmapping, but if the device/card doesn't support it, we should just not ask for it.
   U32 numMips = GRAPHIC->getCardProfiler()->queryProfile("autoMipMapLevel", true) ? 0 : 1;
   for(S32 i=0; i<mClipStackDepth; i++)
   {
      mLevels[i].mScale = (F32)BIT(mClipStackDepth - (1 + i));
      mLevels[i].mTex.set(mClipMapSize, mClipMapSize, GFormatR8G8B8X8, texProfile, avar("%s() - mLevels[%d].mTex (line %d)", __FUNCTION__, i, __LINE__), numMips);
   }

   // Some stuff can get skipped once we're set up.
   if(mTexCallbackHandle != -1)
      return;

   // Don't forget to allocate our debug textures...

   for(S32 i=0; i<mClipStackDepth; i++)
      mLevels[i].initDebugTexture(i);

   GAtlasVert2* vert = NULL;

   if (GRAPHIC->getPixelShaderVersion() > 0)
   {   
      // Do shader lookup for 2,3,4 level shaders.
      for(S32 i=2; i<5; i++)
      {
         // Init materials
         const String matname = String::ToString("AtlasMaterial%d", i);
         const U32 arrayOffset = i-1;
         mClipmapMat[arrayOffset] = MaterialManager::get()->createMatInstance(matname, (GVertexFlags)getGVertFlags(vert));
         if (!mClipmapMat[arrayOffset])
         {
            Con::errorf("Could not find material: %s", matname.c_str());
            continue;
         }
         else
         {
            if (mMapInfoConst.getElementSize() == 0)
               mMapInfoConst.setCapacity(4, mClipmapMat[arrayOffset]->getMaterialParameters()->getAlignmentValue(GSCT_Float4));
         }
         BaseMatInstance* matParams = mClipmapMat[arrayOffset];
         mMorphTSC[arrayOffset] = matParams->getMaterialParameterHandle("$morphT");
         mMapInfoTC[arrayOffset] = matParams->getMaterialParameterHandle("$mapInfo");
         mDiffuseMap0TC[arrayOffset] = matParams->getMaterialParameterHandle("$diffuseMap0");
         mDiffuseMap1TC[arrayOffset] = matParams->getMaterialParameterHandle("$diffuseMap1");
         mDiffuseMap2TC[arrayOffset] = matParams->getMaterialParameterHandle("$diffuseMap2");
         mDiffuseMap3TC[arrayOffset] = matParams->getMaterialParameterHandle("$diffuseMap3");
      }
   } else {
      mClipmapMatBasePassFF = MaterialManager::get()->createMatInstance("AtlasMaterialFFBasePass", (GVertexFlags)getGVertFlags(vert));
      mClipmapMatAddPassFF = MaterialManager::get()->createMatInstance("AtlasMaterialFFAddPass", (GVertexFlags)getGVertFlags(vert));
   }
   
   // Grab a callback from the texture manager to deal with zombification.
   GRAPHIC->getTextureManager()->registerTexCallback(texCB, this, mTexCallbackHandle);

   // Ok, everything is ready to go.
   PROFILE_END();
}
示例#23
0
void ClipMap::calculateClipMapLevels(const F32 near, const F32 far, 
                                          const RectF &texBounds, 
                                          S32 &outStartLevel, S32 &outEndLevel)
{
   PROFILE_START(ClipMap_calculateClipMapLevels);

   // We also have to deal w/ the available data. So let's figure out if our
   // desired TCs are in the loaded textureset.

   // Adjust the specified TC range into a texel range.
   F32 ftexsize = F32(mTextureSize);
   RectF tcR(Point2F(texBounds.point.y * ftexsize, texBounds.point.x * ftexsize), ftexsize * texBounds.extent);

   // If we're tiling, make sure we're only insetting away from the clipmap bounds.
   // This avoids making bad LOD selections at clipmap boundaries.
   // Note: compress several compares into one since a*b=0 iff a==0 or b==0
   bool doInset = true;//mTile || (tcR.point.x * tcR.point.y * (tcR.extent.x+tcR.point.x-mTextureSize) * (tcR.extent.y+tcR.point.y-mTextureSize) != 0); 

   if(doInset)
      tcR.inset(-1, -1);

   // Put some safe defaults in for starters.
   outEndLevel   = mClipStackDepth-1;
   outStartLevel = getMax(outEndLevel-3, S32(0));

   // Now iterate over every clipstack entry and find the smallest that contains
   // the relevant TCs.
   S32 minLevelOverlap = mClipStackDepth - 1;
   S32 maxLevelOverlap = mClipStackDepth - 1;

   for(S32 i=mClipStackDepth-2; i>=0; i--)
   {
      // Find region for entry at this level.
      RectF r;
      F32 biti = F32(BIT(i));
      F32 biticms = F32(BIT(i) * mClipMapSize);
      r.point = Point2F(
         biti * mLevels[i].mToroidalOffset.x, 
         biti * mLevels[i].mToroidalOffset.y);
      r.extent.set(biticms,biticms);

      // Is our tex region fully contained?
      if(r.contains(tcR))
      {
         // If we're fully contained, then this is our new max.
         maxLevelOverlap = i;
         minLevelOverlap = i;
         continue;
      }

      // Or else maybe we've got overlap?
      if (!r.overlaps(tcR))
         break;

      // If we're overlapping then this is our new min...
      minLevelOverlap = getMin(minLevelOverlap, i);
   }

   // Given our level range, do a best fit. We ALWAYS have to have
   // enough for the minimum detail, so we fit that constraint then
   // do our best to give additional detail on top of that.

   // bias the minimum detail to allow smooth transitions to work properly,
   // this avoids a LOT of texture popping.
   maxLevelOverlap++;

   outEndLevel   = mClamp(maxLevelOverlap, 0, mClipStackDepth-1);
   outStartLevel = mClamp(minLevelOverlap, outEndLevel - 3, outEndLevel - 1);

   // Make sure we're not exceeding our max delta.
   const S32 delta = outEndLevel - outStartLevel;
   AssertFatal(delta >= 1 && delta <= 4, 
      "ClipMap::calculateClipMapLevels - range in levels outside of 2..4 range!");

   PROFILE_END();
}
bool QuadTreeTracer::castRay(const Point3F &start, const Point3F &end, RayInfo *info)
{
   PROFILE_START(QuadTreeTracer_castRay);

   // Do some precalculations we'll use for the rest of this routine.
   // Set up our intercept calculation methods.
   F32 invDeltaX;
   if(end.x == start.x)
   {
      calcInterceptX = calcInterceptNone;
      invDeltaX = 0;
   }
   else
   {
      invDeltaX = 1.f / (end.x - start.x);
      calcInterceptX = calcInterceptV;
   }

   F32 invDeltaY;
   if(end.y == start.y)
   {
      calcInterceptY = calcInterceptNone;
      invDeltaY = 0;
   }
   else
   {
      invDeltaY = 1.f / (end.y - start.y);
      calcInterceptY = calcInterceptV;
   }

   // Subdivide our space based on the size of the lowest level of the tree...
   const F32 invSize   = 1.f / F32(BIT(mTreeDepth-1));

   // Grab this off the frame allocator, we don't want to do a proper alloc
   // on every ray!
   FrameAllocatorMarker stackAlloc;
   RayStackNode *stack = (RayStackNode*)stackAlloc.alloc(sizeof(RayStackNode) * (mTreeDepth * 3 + 1));

   U32 stackSize = 1;

   // Kick off the stack with the root node.
   stack[0].startT   = 0;
   stack[0].endT     = 1;
   stack[0].squarePos.set(0,0);
   stack[0].level    = mTreeDepth - 1;

   //Con::printf("QuadTreeTracer::castRay(%x)", this);

   // Aright, now let's do some raycasting!
   while(stackSize--)
   {
      // Get the current node for easy access...
      RayStackNode *sn = stack + stackSize;

      const U32 level         = sn->level;
      const F32 startT        = sn->startT;
      const F32 endT          = sn->endT;
      const Point2I squarePos = sn->squarePos;

      AssertFatal((startT >= 0.f) && (startT <= 1.f),  "QuadTreeTracer::castRay - out of range startT on stack!");
      AssertFatal((endT >= 0.f) && (endT <= 1.f),     "QuadTreeTracer::castRay - out of range endT   on stack!");

      //Con::printf(" -- node(%d, %d @ %d), sT=%f, eT=%f", squarePos.x, squarePos.y, level, startT, endT);

      // Figure our start and end Z.
      const F32 startZ = startT * (end.z - start.z) + start.z;
      const F32 endZ   = endT   * (end.z - start.z) + start.z;

      // Ok, now let's see if we hit the lower bound
      const F32 squareMin = getSquareMin(level, squarePos);

      if(startZ < squareMin && endZ < squareMin)
         continue; //Nope, skip out.

      // Hmm, let's check the upper bound.
      const F32 squareMax = getSquareMax(level, squarePos);

      if(startZ > squareMax && endZ > squareMax)
         continue; //Nope, skip out.

      // We might be intersecting something... If we've hit
      // the tree depth let's deal with the leaf intersection.
      if(level == 0)
      {
         //Con::printf(" ++ check node(%d, %d @ %d), sT=%f, eT=%f", squarePos.x, squarePos.y, level, startT, endT);

         if(castLeafRay(squarePos, start, end, startT, endT, info))
         {
            PROFILE_END();
            return true; // We hit, tell 'em so!
         }
         continue; // Otherwise, keep looking.
      }
      else
      {
         // Ok, we have to push our children as we're an inner node.

         // First, figure out some widths...
         U32 subSqSize  = BIT(level - 1);

         // Now, calculate intercepts so we know how to deal with this
         // situation... (intercept = position, int = t value for that pos)

         const F32 xIntercept = (squarePos.x + subSqSize) * invSize;
         F32 xInt = calcInterceptX(start.x, invDeltaX, xIntercept);

         const F32 yIntercept = (squarePos.y + subSqSize) * invSize;
         F32 yInt = calcInterceptY(start.y, invDeltaY, yIntercept);

         // Our starting position for this subray...
         const F32 startX = startT * (end.x - start.x) + start.x;
         const F32 startY = startT * (end.y - start.y) + start.y;

         // Deal with squares that might be "behind" the ray.
         if(xInt < startT) xInt = F32_MAX;
         if(yInt < startT) yInt = F32_MAX;

         // Do a little magic to calculate our next checks...
         const U32 x0 = (startX > xIntercept) * subSqSize;
         const U32 y0 = (startY > yIntercept) * subSqSize;

         const U32 x1 = subSqSize - x0;
         const U32 y1 = subSqSize - y0;

         const U32 nextLevel = level - 1;

         // Ok, now let's figure out what nodes, in what order, need to go
         // on the stack. We push things on in reverse order of processing.
         if(xInt > endT && yInt > endT)
         {
            stack[stackSize].squarePos.set(squarePos.x + x0, squarePos.y + y0);
            stack[stackSize].level = nextLevel;
            stackSize++;
         }
         else if(xInt < yInt)
         {
            F32 nextIntersect = endT;

            if(yInt <= endT)
            {
               stack[stackSize].squarePos.set(squarePos.x + x1, squarePos.y + y1);
               stack[stackSize].startT = yInt;
               stack[stackSize].endT   = endT;
               stack[stackSize].level  = nextLevel;
               nextIntersect = yInt;
               stackSize++;
            }

            // Do middle two, order doesn't matter.
            stack[stackSize].squarePos.set(squarePos.x + x1, squarePos.y + y0);
            stack[stackSize].startT = xInt;
            stack[stackSize].endT   = nextIntersect;
            stack[stackSize].level  = nextLevel;

            stack[stackSize+1].squarePos.set(squarePos.x + x0, squarePos.y + y0);
            stack[stackSize+1].startT = startT;
            stack[stackSize+1].endT   = xInt;
            stack[stackSize+1].level  = nextLevel;
            stackSize += 2;
         }
         else if(yInt < xInt)
         {
            F32 nextIntersect = endT;
            if(xInt <= endT)
            {
               stack[stackSize].squarePos.set(squarePos.x + x1, squarePos.y + y1);
               stack[stackSize].startT = xInt;
               stack[stackSize].endT   = endT;
               stack[stackSize].level  = nextLevel;
               nextIntersect = xInt;
               stackSize++;
            }
            stack[stackSize].squarePos.set(squarePos.x + x0, squarePos.y + y1);
            stack[stackSize].startT  = yInt;
            stack[stackSize].endT    = nextIntersect;
            stack[stackSize].level   = nextLevel;

            stack[stackSize+1].squarePos.set(squarePos.x + x0, squarePos.y + y0);
            stack[stackSize+1].startT = startT;
            stack[stackSize+1].endT   = yInt;
            stack[stackSize+1].level  = nextLevel;
            stackSize += 2;
         }
         else
         {
            stack[stackSize].squarePos.set(squarePos.x + x1, squarePos.y + y1);
            stack[stackSize].startT = xInt;
            stack[stackSize].endT   = endT;
            stack[stackSize].level  = nextLevel;

            stack[stackSize+1].squarePos.set(squarePos.x + x0, squarePos.y + y0);
            stack[stackSize+1].startT = startT;
            stack[stackSize+1].endT   = xInt;
            stack[stackSize+1].level  = nextLevel;
            stackSize += 2;
         }
      }
   }

   // Nothing found, so give up.
   PROFILE_END();
   return false;
}
示例#25
0
void ClipMap::recenter(Point2F center)
{
   bool wantCompleteRefill = false;
   if(mNeedRefill || mForceClipmapPurge || Con::getBoolVariable("$forceFullClipmapPurgeEveryFrame", false))
      wantCompleteRefill = true;

   PROFILE_START(ClipMap_recenter);

   // Reset our budget.
   mMaxTexelUploadPerRecenter = mClipMapSize * mClipMapSize * 2;

   AssertFatal(isPow2(mClipMapSize), 
      "ClipMap::recenter - require pow2 clipmap size!");

   // Clamp the center to the unit square.

   /*
   if(!mTile)
   {
      center.x = mClampF(center.x, 0.f, 1.f);
      center.y = mClampF(center.y, 0.f, 1.f);
   }
   */

   // Ok, we're going to do toroidal updates on each entry of the clipstack
   // (except for the cap, which covers the whole texture), based on this
   // new center point.
   if( !wantCompleteRefill )
   {
      // Calculate the new texel at most detailed level.
      Point2F texelCenterF = center * F32(mClipMapSize) * mLevels[0].mScale;
      Point2I texelCenter((S32)mFloor(texelCenterF.y), (S32)mFloor(texelCenterF.x));
      
      // Update interest region.
      mImageCache->setInterestCenter(texelCenter);
   }

   // Note how many we were at so we can cut off at the right time.
   S32 lastTexelsUpdated = mTexelsUpdated;

   // For each texture...
   for(S32 i=mClipStackDepth-2; i>=0; i--)
   {
      ClipStackEntry &cse = mLevels[i];

      // Calculate new center point for this texture.
      Point2F texelCenterF = center * F32(mClipMapSize) * cse.mScale;

      const S32 texelMin = mClipMapSize/2;
      //const S32 texelMax = S32(F32(mClipMapSize) * cse.mScale) - texelMin;

      Point2I texelTopLeft;

      //if(mTile)
      //{
         texelTopLeft.x = S32(mFloor(texelCenterF.y)) - texelMin;
         texelTopLeft.y = S32(mFloor(texelCenterF.x)) - texelMin;
      //}
      //else
      //{
      //   texelTopLeft.x = mClamp(S32(mFloor(texelCenterF.y)), texelMin, texelMax) - texelMin;
      //   texelTopLeft.y = mClamp(S32(mFloor(texelCenterF.x)), texelMin, texelMax) - texelMin;
      //}

      // Also, prevent very small updates - the RT changes are costly.
      Point2I d = cse.mToroidalOffset - texelTopLeft;
      if(mAbs(d.x) <= 2 && mAbs(d.y) <= 2)
      {
         // Update the center; otherwise we get some weird conditions around
         // edges of the clipmap space.
         cse.mClipCenter = center;
         continue;
      }

      // This + current toroid offset tells us what regions have to be blasted.
      RectI oldData(cse.mToroidalOffset,  Point2I(mClipMapSize, mClipMapSize));
      RectI newData(texelTopLeft,         Point2I(mClipMapSize, mClipMapSize));

      // Update clipstack level.
      cse.mClipCenter      = center;
      cse.mToroidalOffset  = texelTopLeft;

      // If we're refilling, that's all we want; continue with next level.
      if( wantCompleteRefill )
         continue;

      // Make sure we have available data...
      if(!mImageCache->isDataAvailable(getMipLevel(cse.mScale), newData))
		  continue;

      // Alright, determine the set of data we actually need to upload.
      S32   rectCount = 0;
      RectI buffer[8];

      calculateModuloDeltaBounds(oldData, newData, buffer, &rectCount);
      AssertFatal(rectCount < 8, "ClipMap::recenter - got too many rects back!");

      /*if(rectCount)
         Con::printf("    issuing %d updates to clipmap level %d (offset=%dx%d)", 
                        rectCount, i, texelTopLeft.x, texelTopLeft.y); */

      if(rectCount)
      {
         if (!mImageCache->beginRectUpdates(cse))
         {
            mForceClipmapPurge = true;
            return;
         }
         //Con::errorf("layer %x, %d updates", &cse,  rectCount);

         // And GO!
         for(S32 j=0; j<rectCount; j++)
         {
            PROFILE_START(ClipMap_recenter_upload);

            AssertFatal(buffer[j].isValidRect(),"ClipMap::recenter - got invalid rect!");

            // Note the rect, so we can then wrap and let the image cache do its thing.
            RectI srcRegion = buffer[j];
            buffer[j].point.x = srcRegion.point.x % mClipMapSize;
            buffer[j].point.y = srcRegion.point.y % mClipMapSize;

            AssertFatal(newData.contains(srcRegion), 
               "ClipMap::recenter - got update buffer outside of expected new data bounds.");

            mTotalUpdates++;
            mTexelsUpdated += srcRegion.extent.x  * srcRegion.extent.y;

            //Con::printf("updating (%d %d %d %d)",
            //   buffer[j].point.x, buffer[j].point.y, buffer[j].extent.x, buffer[j].extent.y);

            mImageCache->doRectUpdate(getMipLevel(cse.mScale), cse, srcRegion, buffer[j]);

            PROFILE_END();
         }

         mImageCache->finishRectUpdates(cse);
      }

      // Check if we've overrun our budget.
      if((mTexelsUpdated - lastTexelsUpdated) > mMaxTexelUploadPerRecenter)
      {
         //Con::warnf("ClipMap::recenter - exceeded budget for this frame, deferring till next frame.");
         break;
      }

   }

   if( wantCompleteRefill )
   {
      fillWithTextureData();
      mNeedRefill = false;
   }

   PROFILE_END();
}
示例#26
0
void TerrainRenderer::RenderTerrainShader(ShadowMap* shadow, bool filtered)
{
	ENSURE(m->phase == Phase_Render);

	std::vector<CPatchRData*>& visiblePatches = filtered ? m->filteredPatches : m->visiblePatches;
	std::vector<CDecalRData*>& visibleDecals = filtered ? m->filteredDecals : m->visibleDecals;
	if (visiblePatches.empty() && visibleDecals.empty())
		return;

	CShaderManager& shaderManager = g_Renderer.GetShaderManager();

	typedef std::map<CStr, CStr> Defines;
	Defines defBasic;
	if (shadow)
	{
		defBasic["USE_SHADOW"] = "1";
		if (g_Renderer.m_Caps.m_ARBProgramShadow && g_Renderer.m_Options.m_ARBProgramShadow)
			defBasic["USE_FP_SHADOW"] = "1";
		if (g_Renderer.m_Options.m_ShadowPCF)
			defBasic["USE_SHADOW_PCF"] = "1";
#if !CONFIG2_GLES
		defBasic["USE_SHADOW_SAMPLER"] = "1";
#endif
	}

	defBasic["LIGHTING_MODEL_" + g_Renderer.GetLightEnv().GetLightingModel()] = "1";

	CShaderTechniquePtr techBase(shaderManager.LoadEffect("terrain_base", defBasic));
	CShaderTechniquePtr techBlend(shaderManager.LoadEffect("terrain_blend", defBasic));
	CShaderTechniquePtr techDecal(shaderManager.LoadEffect("terrain_decal", defBasic));

	// render the solid black sides of the map first
	CShaderTechniquePtr techSolid = g_Renderer.GetShaderManager().LoadEffect("gui_solid");
	techSolid->BeginPass();
	CShaderProgramPtr shaderSolid = techSolid->GetShader();
	shaderSolid->Uniform("transform", g_Renderer.GetViewCamera().GetViewProjection());
	shaderSolid->Uniform("color", 0.0f, 0.0f, 0.0f, 1.0f);

	PROFILE_START("render terrain sides");
	for (size_t i = 0; i < visiblePatches.size(); ++i)
		visiblePatches[i]->RenderSides(shaderSolid);
	PROFILE_END("render terrain sides");

	techSolid->EndPass();

	techBase->BeginPass();
	PrepareShader(techBase->GetShader(), shadow);

	PROFILE_START("render terrain base");
	CPatchRData::RenderBases(visiblePatches, techBase->GetShader(), false);
	PROFILE_END("render terrain base");

	techBase->EndPass();

	// render blends

	techBlend->BeginPass();
	PrepareShader(techBlend->GetShader(), shadow);

	// switch on blending
	glEnable(GL_BLEND);
	glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

	// no need to write to the depth buffer a second time
	glDepthMask(0);

	// render blend passes for each patch
	PROFILE_START("render terrain blends");
	CPatchRData::RenderBlends(visiblePatches, techBlend->GetShader(), false);
	PROFILE_END("render terrain blends");

	techBlend->EndPass();

	// Render terrain decals

	techDecal->BeginPass();
	PrepareShader(techDecal->GetShader(), shadow);

	PROFILE_START("render terrain decals");
	for (size_t i = 0; i < visibleDecals.size(); ++i)
		visibleDecals[i]->Render(techDecal->GetShader(), false);
	PROFILE_END("render terrain decals");

	techDecal->EndPass();

	// restore OpenGL state
	g_Renderer.BindTexture(1, 0);
	g_Renderer.BindTexture(2, 0);
	g_Renderer.BindTexture(3, 0);

	glDepthMask(1);
	glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
	glDisable(GL_BLEND);
}
示例#27
0
///////////////////////////////////////////////////////////////////
// Full-featured terrain rendering with blending and everything
void TerrainRenderer::RenderTerrain(bool filtered)
{
#if CONFIG2_GLES
	UNUSED2(filtered);
#else
	ENSURE(m->phase == Phase_Render);

	std::vector<CPatchRData*>& visiblePatches = filtered ? m->filteredPatches : m->visiblePatches;
	std::vector<CDecalRData*>& visibleDecals = filtered ? m->filteredDecals : m->visibleDecals;
	if (visiblePatches.empty() && visibleDecals.empty())
		return;

	CShaderProgramPtr dummyShader = g_Renderer.GetShaderManager().LoadProgram("fixed:dummy");
	dummyShader->Bind();

	// render the solid black sides of the map first
	g_Renderer.BindTexture(0, 0);
	glEnableClientState(GL_VERTEX_ARRAY);
	glColor3f(0, 0, 0);
	PROFILE_START("render terrain sides");
	for (size_t i = 0; i < visiblePatches.size(); ++i)
		visiblePatches[i]->RenderSides(dummyShader);
	PROFILE_END("render terrain sides");

	// switch on required client states
	glEnableClientState(GL_TEXTURE_COORD_ARRAY);
	
	// render everything fullbright
	// set up texture environment for base pass
	pglActiveTextureARB(GL_TEXTURE0);
	pglClientActiveTextureARB(GL_TEXTURE0);
	glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
	glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_REPLACE);
	glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_TEXTURE);
	glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_ARB, GL_SRC_COLOR);

	// Set alpha to 1.0
	glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, GL_REPLACE);
	glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB, GL_CONSTANT);
	glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_ARB, GL_SRC_ALPHA);
	static const float one[4] = { 1.f, 1.f, 1.f, 1.f };
	glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, one);
	
	PROFILE_START("render terrain base");
	CPatchRData::RenderBases(visiblePatches, dummyShader, true);
	PROFILE_END("render terrain base");

	// render blends
	// switch on the composite alpha map texture
	(void)ogl_tex_bind(g_Renderer.m_hCompositeAlphaMap, 1);

	// switch on second uv set
	pglClientActiveTextureARB(GL_TEXTURE1);
	glEnableClientState(GL_TEXTURE_COORD_ARRAY);

	// setup additional texenv required by blend pass
	pglActiveTextureARB(GL_TEXTURE1);
	glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
	glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_REPLACE);
	glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_PREVIOUS);
	glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_ARB, GL_SRC_COLOR);
	glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, GL_REPLACE);
	glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB, GL_TEXTURE);
	glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_ARB, GL_ONE_MINUS_SRC_ALPHA);

	// switch on blending
	glEnable(GL_BLEND);
	glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);

	// no need to write to the depth buffer a second time
	glDepthMask(0);
	
	// The decal color array contains lighting data, which we don't want in this non-shader mode
	glDisableClientState(GL_COLOR_ARRAY);

	// render blend passes for each patch
	PROFILE_START("render terrain blends");
	CPatchRData::RenderBlends(visiblePatches, dummyShader, true);
	PROFILE_END("render terrain blends");

	// Disable second texcoord array
	pglClientActiveTextureARB(GL_TEXTURE1);
	glDisableClientState(GL_TEXTURE_COORD_ARRAY);


	// Render terrain decals

	g_Renderer.BindTexture(1, 0);
	pglActiveTextureARB(GL_TEXTURE0);
	pglClientActiveTextureARB(GL_TEXTURE0);
	glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
	glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_MODULATE);
	glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_PREVIOUS);
	glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_ARB, GL_SRC_COLOR);
	glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_TEXTURE);
	glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB_ARB, GL_SRC_COLOR);
	glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, GL_REPLACE);
	glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB, GL_TEXTURE);
	glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_ARB, GL_SRC_ALPHA);

	PROFILE_START("render terrain decals");
	for (size_t i = 0; i < visibleDecals.size(); ++i)
		visibleDecals[i]->Render(dummyShader, true);
	PROFILE_END("render terrain decals");


	// Now apply lighting
	const CLightEnv& lightEnv = g_Renderer.GetLightEnv();

	pglClientActiveTextureARB(GL_TEXTURE0);
	glEnableClientState(GL_COLOR_ARRAY); // diffuse lighting colours

	glBlendFunc(GL_DST_COLOR, GL_ZERO);

	// GL_TEXTURE_ENV_COLOR requires four floats, so we shouldn't use the RGBColor directly
	float terrainAmbientColor[4] = {
		lightEnv.m_TerrainAmbientColor.X,
		lightEnv.m_TerrainAmbientColor.Y,
		lightEnv.m_TerrainAmbientColor.Z,
		1.f
	};

	CLOSTexture& losTexture = g_Renderer.GetScene().GetLOSTexture();

	int streamflags = STREAM_POS|STREAM_COLOR;

	pglActiveTextureARB(GL_TEXTURE0);
	// We're not going to use a texture here, but we have to have a valid texture
	// bound else the texture unit will be disabled.
	// We should still have a bound splat texture from some earlier rendering,
	// so assume that's still valid to use.
	// (TODO: That's a bit of an ugly hack.)

	// No shadows: (Ambient + Diffuse) * LOS
	glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
	glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_ADD);
	glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_PREVIOUS);
	glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_ARB, GL_SRC_COLOR);
	glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_CONSTANT);
	glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB_ARB, GL_SRC_COLOR);
	glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, GL_REPLACE);
	glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB, GL_PREVIOUS);
	glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_ARB, GL_SRC_ALPHA);

	glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, terrainAmbientColor);

	losTexture.BindTexture(1);
	pglClientActiveTextureARB(GL_TEXTURE1);
	glEnableClientState(GL_TEXTURE_COORD_ARRAY);
	streamflags |= STREAM_POSTOUV1;

	glMatrixMode(GL_TEXTURE);
	glLoadMatrixf(&losTexture.GetTextureMatrix()._11);
	glMatrixMode(GL_MODELVIEW);

	glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
	glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_MODULATE);
	glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_PREVIOUS);
	glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_ARB, GL_SRC_COLOR);
	glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_TEXTURE);
	glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB_ARB, GL_SRC_ALPHA);
	glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, GL_REPLACE);
	glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB, GL_PREVIOUS);
	glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_ARB, GL_SRC_ALPHA);

	pglActiveTextureARB(GL_TEXTURE0);
	pglClientActiveTextureARB(GL_TEXTURE0);

	PROFILE_START("render terrain streams");
	CPatchRData::RenderStreams(visiblePatches, dummyShader, streamflags);
	PROFILE_END("render terrain streams");

	glMatrixMode(GL_TEXTURE);
	glLoadIdentity();
	glMatrixMode(GL_MODELVIEW);

	// restore OpenGL state
	g_Renderer.BindTexture(1, 0);

	pglClientActiveTextureARB(GL_TEXTURE1);
	glDisableClientState(GL_TEXTURE_COORD_ARRAY);
	glMatrixMode(GL_TEXTURE);
	glLoadIdentity();
	glMatrixMode(GL_MODELVIEW);

	pglClientActiveTextureARB(GL_TEXTURE0);
	pglActiveTextureARB(GL_TEXTURE0);
	glDepthMask(1);
	glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
	glDisable(GL_BLEND);
	glDisableClientState(GL_COLOR_ARRAY);
	glDisableClientState(GL_VERTEX_ARRAY);
	glDisableClientState(GL_TEXTURE_COORD_ARRAY);

	dummyShader->Unbind();
#endif
}
示例#28
0
文件: MiniMap.cpp 项目: stev47/0ad
void CMiniMap::Draw()
{
	PROFILE3("render minimap");

	// The terrain isn't actually initialized until the map is loaded, which
	// happens when the game is started, so abort until then.
	if(!(GetGUI() && g_Game && g_Game->IsGameStarted()))
		return;

	CSimulation2* sim = g_Game->GetSimulation2();
	CmpPtr<ICmpRangeManager> cmpRangeManager(*sim, SYSTEM_ENTITY);
	ENSURE(cmpRangeManager);

	// Set our globals in case they hadn't been set before
	m_Camera      = g_Game->GetView()->GetCamera();
	m_Terrain     = g_Game->GetWorld()->GetTerrain();
	m_Width  = (u32)(m_CachedActualSize.right - m_CachedActualSize.left);
	m_Height = (u32)(m_CachedActualSize.bottom - m_CachedActualSize.top);
	m_MapSize = m_Terrain->GetVerticesPerSide();
	m_TextureSize = (GLsizei)round_up_to_pow2((size_t)m_MapSize);
	m_MapScale = (cmpRangeManager->GetLosCircular() ? 1.f : 1.414f);

	if(!m_TerrainTexture || g_GameRestarted)
		CreateTextures();


	// only update 2x / second
	// (note: since units only move a few pixels per second on the minimap,
	// we can get away with infrequent updates; this is slow)
	static double last_time;
	const double cur_time = timer_Time();
	if(cur_time - last_time > 0.5)
	{
		last_time = cur_time;

		if(m_TerrainDirty)
			RebuildTerrainTexture();
	}

	glMatrixMode(GL_PROJECTION);
	glPushMatrix();
	glLoadIdentity();
	glMatrixMode(GL_MODELVIEW);
	glPushMatrix();
	CMatrix3D matrix = GetDefaultGuiMatrix();
	glLoadMatrixf(&matrix._11);

	// Disable depth updates to prevent apparent z-fighting-related issues
	// with some drivers causing units to get drawn behind the texture
	glDepthMask(0);

	const float x = m_CachedActualSize.left, y = m_CachedActualSize.bottom;
	const float x2 = m_CachedActualSize.right, y2 = m_CachedActualSize.top;
	const float z = GetBufferedZ();
	const float texCoordMax = (float)(m_MapSize - 1) / (float)m_TextureSize;
	const float angle = GetAngle();

	// Draw the main textured quad
	g_Renderer.BindTexture(0, m_TerrainTexture);
	glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
	DrawTexture(texCoordMax, angle, x, y, x2, y2, z);


	// Draw territory boundaries
	CTerritoryTexture& territoryTexture = g_Game->GetView()->GetTerritoryTexture();
	territoryTexture.BindTexture(0);
	glEnable(GL_BLEND);
	glMatrixMode(GL_TEXTURE);
	glLoadMatrixf(territoryTexture.GetMinimapTextureMatrix());
	glMatrixMode(GL_MODELVIEW);

	DrawTexture(1.0f, angle, x, y, x2, y2, z);

	glMatrixMode(GL_TEXTURE);
	glLoadIdentity();
	glMatrixMode(GL_MODELVIEW);
	glDisable(GL_BLEND);


	// Draw the LOS quad in black, using alpha values from the LOS texture
	CLOSTexture& losTexture = g_Game->GetView()->GetLOSTexture();
	losTexture.BindTexture(0);
	glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
	glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_REPLACE);
	glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_PRIMARY_COLOR_ARB);
	glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_ARB, GL_SRC_COLOR);
	glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, GL_REPLACE);
	glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB, GL_TEXTURE);
	glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_ARB, GL_ONE_MINUS_SRC_ALPHA);
	glEnable(GL_BLEND);
	glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
	glColor3f(0.0f, 0.0f, 0.0f);

	glMatrixMode(GL_TEXTURE);
	glLoadMatrixf(losTexture.GetMinimapTextureMatrix());
	glMatrixMode(GL_MODELVIEW);

	DrawTexture(1.0f, angle, x, y, x2, y2, z);

	glMatrixMode(GL_TEXTURE);
	glLoadIdentity();
	glMatrixMode(GL_MODELVIEW);

	glDisable(GL_BLEND);

	// Set up the matrix for drawing points and lines
	glPushMatrix();
	glTranslatef(x, y, z);
	// Rotate around the center of the map
	glTranslatef((x2-x)/2.f, (y2-y)/2.f, 0.f);
	// Scale square maps to fit in circular minimap area
	float unitScale = (cmpRangeManager->GetLosCircular() ? 1.f : m_MapScale/2.f);
	glScalef(unitScale, unitScale, 1.f);
	glRotatef(angle * 180.f/M_PI, 0.f, 0.f, 1.f);
	glTranslatef(-(x2-x)/2.f, -(y2-y)/2.f, 0.f);

	PROFILE_START("minimap units");

	// Don't enable GL_POINT_SMOOTH because it's far too slow
	// (~70msec/frame on a GF4 rendering a thousand points)
	glPointSize(3.f);

	float sx = (float)m_Width / ((m_MapSize - 1) * TERRAIN_TILE_SIZE);
	float sy = (float)m_Height / ((m_MapSize - 1) * TERRAIN_TILE_SIZE);

	CSimulation2::InterfaceList ents = sim->GetEntitiesWithInterface(IID_Minimap);

	std::vector<MinimapUnitVertex> vertexArray;
	vertexArray.reserve(ents.size());

	for (CSimulation2::InterfaceList::const_iterator it = ents.begin(); it != ents.end(); ++it)
	{
		MinimapUnitVertex v;
		ICmpMinimap* cmpMinimap = static_cast<ICmpMinimap*>(it->second);
		entity_pos_t posX, posZ;
		if (cmpMinimap->GetRenderData(v.r, v.g, v.b, posX, posZ))
		{
			ICmpRangeManager::ELosVisibility vis = cmpRangeManager->GetLosVisibility(it->first, g_Game->GetPlayerID());
			if (vis != ICmpRangeManager::VIS_HIDDEN)
			{
				v.a = 255;
				v.x = posX.ToFloat()*sx;
				v.y = -posZ.ToFloat()*sy;
				vertexArray.push_back(v);
			}
		}
	}

	if (!vertexArray.empty())
	{
		glEnableClientState(GL_VERTEX_ARRAY);
		glEnableClientState(GL_COLOR_ARRAY);
		glVertexPointer(2, GL_FLOAT, sizeof(MinimapUnitVertex), &vertexArray[0].x);
		glColorPointer(4, GL_UNSIGNED_BYTE, sizeof(MinimapUnitVertex), &vertexArray[0].r);

		glDrawArrays(GL_POINTS, 0, (GLsizei)vertexArray.size());

		glDisableClientState(GL_COLOR_ARRAY);
		glDisableClientState(GL_VERTEX_ARRAY);
	}

	PROFILE_END("minimap units");

	DrawViewRect();

	glPopMatrix();


	glMatrixMode(GL_PROJECTION);
	glPopMatrix();
	glMatrixMode(GL_MODELVIEW);
	glPopMatrix();

	// Reset everything back to normal
	glPointSize(1.0f);
	glEnable(GL_TEXTURE_2D);
	glDepthMask(1);
}
示例#29
0
// TODO: render the minimap in a framebuffer and just draw the frambuffer texture
//	most of the time, updating the framebuffer twice a frame.
// Here it updates as ping-pong either texture or vertex array each sec to lower gpu stalling
// (those operations cause a gpu sync, which slows down the way gpu works)
void CMiniMap::Draw()
{
	PROFILE3("render minimap");

	// The terrain isn't actually initialized until the map is loaded, which
	// happens when the game is started, so abort until then.
	if(!(GetGUI() && g_Game && g_Game->IsGameStarted()))
		return;

	CSimulation2* sim = g_Game->GetSimulation2();
	CmpPtr<ICmpRangeManager> cmpRangeManager(*sim, SYSTEM_ENTITY);
	ENSURE(cmpRangeManager);

	// Set our globals in case they hadn't been set before
	m_Camera      = g_Game->GetView()->GetCamera();
	m_Terrain     = g_Game->GetWorld()->GetTerrain();
	m_Width  = (u32)(m_CachedActualSize.right - m_CachedActualSize.left);
	m_Height = (u32)(m_CachedActualSize.bottom - m_CachedActualSize.top);
	m_MapSize = m_Terrain->GetVerticesPerSide();
	m_TextureSize = (GLsizei)round_up_to_pow2((size_t)m_MapSize);
	m_MapScale = (cmpRangeManager->GetLosCircular() ? 1.f : 1.414f);

	if(!m_TerrainTexture || g_GameRestarted)
		CreateTextures();


	// only update 2x / second
	// (note: since units only move a few pixels per second on the minimap,
	// we can get away with infrequent updates; this is slow)
	// TODO: store frequency in a config file?
	static double last_time;
	const double cur_time = timer_Time();
	const bool doUpdate = cur_time - last_time > 0.5;
	if(doUpdate)
	{	
		last_time = cur_time;
		if(m_TerrainDirty)
			RebuildTerrainTexture();
	}

	glMatrixMode(GL_PROJECTION);
	glPushMatrix();
	glLoadIdentity();
	glMatrixMode(GL_MODELVIEW);
	glPushMatrix();
	CMatrix3D matrix = GetDefaultGuiMatrix();
	glLoadMatrixf(&matrix._11);

	// Disable depth updates to prevent apparent z-fighting-related issues
	// with some drivers causing units to get drawn behind the texture
	glDepthMask(0);
	
	CShaderProgramPtr shader;
	CShaderTechniquePtr tech;
	
	if (g_Renderer.GetRenderPath() == CRenderer::RP_SHADER)
	{
		CShaderDefines defines;
		defines.Add(str_MINIMAP_BASE, str_1);
		tech = g_Renderer.GetShaderManager().LoadEffect(str_minimap, g_Renderer.GetSystemShaderDefines(), defines);
		tech->BeginPass();
		shader = tech->GetShader();
	}

	const float x = m_CachedActualSize.left, y = m_CachedActualSize.bottom;
	const float x2 = m_CachedActualSize.right, y2 = m_CachedActualSize.top;
	const float z = GetBufferedZ();
	const float texCoordMax = (float)(m_MapSize - 1) / (float)m_TextureSize;
	const float angle = GetAngle();

	// Draw the main textured quad
	if (g_Renderer.GetRenderPath() == CRenderer::RP_SHADER)
		shader->BindTexture(str_baseTex, m_TerrainTexture);
	else
		g_Renderer.BindTexture(0, m_TerrainTexture);
	
	glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
	DrawTexture(shader, texCoordMax, angle, x, y, x2, y2, z);


	// Draw territory boundaries
	CTerritoryTexture& territoryTexture = g_Game->GetView()->GetTerritoryTexture();
	
	if (g_Renderer.GetRenderPath() == CRenderer::RP_SHADER)
		shader->BindTexture(str_baseTex, territoryTexture.GetTexture());
	else
		territoryTexture.BindTexture(0);
	
	glEnable(GL_BLEND);
	glMatrixMode(GL_TEXTURE);
	glLoadMatrixf(territoryTexture.GetMinimapTextureMatrix());
	glMatrixMode(GL_MODELVIEW);

	DrawTexture(shader, 1.0f, angle, x, y, x2, y2, z);

	glMatrixMode(GL_TEXTURE);
	glLoadIdentity();
	glMatrixMode(GL_MODELVIEW);
	glDisable(GL_BLEND);


	// Draw the LOS quad in black, using alpha values from the LOS texture
	CLOSTexture& losTexture = g_Game->GetView()->GetLOSTexture();
	
	if (g_Renderer.GetRenderPath() == CRenderer::RP_SHADER)
	{
		tech->EndPass();

		CShaderDefines defines;
		defines.Add(str_MINIMAP_LOS, str_1);
		tech = g_Renderer.GetShaderManager().LoadEffect(str_minimap, g_Renderer.GetSystemShaderDefines(), defines);
		tech->BeginPass();
		shader = tech->GetShader();
		shader->BindTexture(str_baseTex, losTexture.GetTexture());
	}
	else
	{
		losTexture.BindTexture(0);
	}
	
	glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
	glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_REPLACE);
	glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_PRIMARY_COLOR_ARB);
	glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_ARB, GL_SRC_COLOR);
	glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, GL_REPLACE);
	glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB, GL_TEXTURE);
	glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_ARB, GL_ONE_MINUS_SRC_ALPHA);
	glEnable(GL_BLEND);
	glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
	glColor3f(0.0f, 0.0f, 0.0f);

	glMatrixMode(GL_TEXTURE);
	glLoadMatrixf(losTexture.GetMinimapTextureMatrix());
	glMatrixMode(GL_MODELVIEW);

	DrawTexture(shader, 1.0f, angle, x, y, x2, y2, z);

	glMatrixMode(GL_TEXTURE);
	glLoadIdentity();
	glMatrixMode(GL_MODELVIEW);

	glDisable(GL_BLEND);
	
	if (g_Renderer.GetRenderPath() == CRenderer::RP_SHADER)
	{
		tech->EndPass();

		CShaderDefines defines;
		defines.Add(str_MINIMAP_POINT, str_1);
		tech = g_Renderer.GetShaderManager().LoadEffect(str_minimap, g_Renderer.GetSystemShaderDefines(), defines);
		tech->BeginPass();
		shader = tech->GetShader();
	}
	
	// Set up the matrix for drawing points and lines
	glPushMatrix();
	glTranslatef(x, y, z);
	// Rotate around the center of the map
	glTranslatef((x2-x)/2.f, (y2-y)/2.f, 0.f);
	// Scale square maps to fit in circular minimap area
	float unitScale = (cmpRangeManager->GetLosCircular() ? 1.f : m_MapScale/2.f);
	glScalef(unitScale, unitScale, 1.f);
	glRotatef(angle * 180.f/M_PI, 0.f, 0.f, 1.f);
	glTranslatef(-(x2-x)/2.f, -(y2-y)/2.f, 0.f);

	PROFILE_START("minimap units");


	const float sx = (float)m_Width / ((m_MapSize - 1) * TERRAIN_TILE_SIZE);
	const float sy = (float)m_Height / ((m_MapSize - 1) * TERRAIN_TILE_SIZE);

	CSimulation2::InterfaceList ents = sim->GetEntitiesWithInterface(IID_Minimap);

	if (doUpdate)
	{

		VertexArrayIterator<float[2]> attrPos = m_AttributePos.GetIterator<float[2]>();
		VertexArrayIterator<u8[4]> attrColor = m_AttributeColor.GetIterator<u8[4]>();

		m_EntitiesDrawn = 0;
		MinimapUnitVertex v;
		std::vector<MinimapUnitVertex> pingingVertices;
		pingingVertices.reserve(MAX_ENTITIES_DRAWN/2);

		const double time = timer_Time();

		if (time > m_NextBlinkTime)
		{
			m_BlinkState = !m_BlinkState;
			m_NextBlinkTime = time + m_HalfBlinkDuration;
		}

		entity_pos_t posX, posZ;
		for (CSimulation2::InterfaceList::const_iterator it = ents.begin(); it != ents.end(); ++it)
		{
			ICmpMinimap* cmpMinimap = static_cast<ICmpMinimap*>(it->second);
			if (cmpMinimap->GetRenderData(v.r, v.g, v.b, posX, posZ))
			{
				ICmpRangeManager::ELosVisibility vis = cmpRangeManager->GetLosVisibility(it->first, g_Game->GetPlayerID());
				if (vis != ICmpRangeManager::VIS_HIDDEN)
				{
					v.a = 255;
					v.x = posX.ToFloat()*sx;
					v.y = -posZ.ToFloat()*sy;
					
					// Check minimap pinging to indicate something
					if (m_BlinkState && cmpMinimap->CheckPing(time, m_PingDuration))
					{
						v.r = 255; // ping color is white
						v.g = 255;
						v.b = 255;

						pingingVertices.push_back(v);
					}
					else
					{
						addVertex(v, attrColor, attrPos);
						++m_EntitiesDrawn;
					}
				}
			}
		}

		// Add the pinged vertices at the end, so they are drawn on top
		for (size_t v = 0; v < pingingVertices.size(); ++v)
		{
			addVertex(pingingVertices[v], attrColor, attrPos);
			++m_EntitiesDrawn;
		}

		ENSURE(m_EntitiesDrawn < MAX_ENTITIES_DRAWN);
		m_VertexArray.Upload();
	}

	if (m_EntitiesDrawn > 0)
	{		
		// Don't enable GL_POINT_SMOOTH because it's far too slow
		// (~70msec/frame on a GF4 rendering a thousand points)
		glPointSize(3.f);

		u8* indexBase = m_IndexArray.Bind();
		u8* base = m_VertexArray.Bind();
		const GLsizei stride = (GLsizei)m_VertexArray.GetStride();

		if (g_Renderer.GetRenderPath() == CRenderer::RP_SHADER)
		{
			shader->VertexPointer(2, GL_FLOAT, stride, base + m_AttributePos.offset);
			shader->ColorPointer(4, GL_UNSIGNED_BYTE, stride, base + m_AttributeColor.offset);
			shader->AssertPointersBound();
		}
		else
		{	
			glEnableClientState(GL_VERTEX_ARRAY);
			glEnableClientState(GL_COLOR_ARRAY);

			glDisable(GL_TEXTURE_2D);
			glVertexPointer(2, GL_FLOAT, stride, base + m_AttributePos.offset);
			glColorPointer(4, GL_UNSIGNED_BYTE, stride, base + m_AttributeColor.offset);
		}
		
		if (!g_Renderer.m_SkipSubmit)
		{
			glDrawElements(GL_POINTS, (GLsizei)(m_EntitiesDrawn), GL_UNSIGNED_SHORT, indexBase);
		}

		
		g_Renderer.GetStats().m_DrawCalls++;
		CVertexBuffer::Unbind();
	}

	PROFILE_END("minimap units");

	if (g_Renderer.GetRenderPath() == CRenderer::RP_SHADER)
	{
		tech->EndPass();

		CShaderDefines defines;
		defines.Add(str_MINIMAP_LINE, str_1);
		tech = g_Renderer.GetShaderManager().LoadEffect(str_minimap, g_Renderer.GetSystemShaderDefines(), defines);
		tech->BeginPass();
		shader = tech->GetShader();
	}
	else
	{
		glEnable(GL_TEXTURE_2D);
		glDisableClientState(GL_VERTEX_ARRAY);
		glDisableClientState(GL_COLOR_ARRAY);
	}

	DrawViewRect();

	glPopMatrix();
	
	glMatrixMode(GL_PROJECTION);
	glPopMatrix();
	glMatrixMode(GL_MODELVIEW);
	glPopMatrix();
	
	if (g_Renderer.GetRenderPath() == CRenderer::RP_SHADER)
	{
		tech->EndPass();
	}

	// Reset everything back to normal
	glPointSize(1.0f);
	glEnable(GL_TEXTURE_2D);
	glDepthMask(1);
}
示例#30
0
void AtlasClipMapBatcher::queue(const Point3F &camPos, AtlasResourceGeomStub *args)
{
   PROFILE_START(AtlasClipMapBatcher_queue);

   AtlasGeomChunk *agc = args->mChunk;

   Point3F nearPos, farPos;
   Point2F nearTC, farTC;
   agc->calculatePoints(camPos, nearPos, farPos, nearTC, farTC );
   const F32 nearDistance = (camPos - nearPos).len();
   const F32 farDistance = (camPos - farPos).len();

   const RectF texBounds(nearTC, farTC - nearTC);

   // Now, calculate and store levels into a new RenderNote.
   S32 startLevel, endLevel;
   mClipMap->calculateClipMapLevels(nearDistance, farDistance, texBounds, startLevel, endLevel);

   // Allocate a render note.
   RenderNote *rn = mRenderNoteAlloc.alloc();

   // Check if this chunk will get fogged - consider furthest point, and if
   // it'll be fogged then draw a fog pass.
   if(mState->getHazeAndFog(farDistance, farPos.z - camPos.z) > (1.0/256.0)
      || mState->getHazeAndFog(farDistance, -(farPos.z - camPos.z)) > (1.0/256.0))
      mFogList.push_back(rn);

   // Is this chunk within the detail map range?
   if( isDetailMappingEnabled() && nearDistance < mDetailMapFadeEndDistance )
		   mDetailList.push_back(rn);

   // Let our plugins have a shot at the render note.
   for (U32 i = 0; i < mRenderPlugins.size(); i++)
   {
      mRenderPlugins[i]->queue(rn, mObject, args);
   }

   rn->levelStart = startLevel;
   rn->levelEnd   = endLevel;
   rn->levelCount = endLevel - startLevel + 1;
   rn->chunk      = agc;
   rn->nearDist   = nearDistance;

   // Stuff into right list based on shader.
   switch(rn->levelCount)
   {
   case 2:
   case 3:
   case 4:
      mRenderList[rn->levelCount-1].push_back(rn);
      break;

   default:
      Con::errorf("AtlasClipMapBatcher::queue - got unexpected level count of %d", rn->levelCount);
      break;
   }

   AssertFatal(rn->levelCount >= 2 && rn->levelCount <= 4, 
      "AtlasClipMapBatcher::queue - bad level count!");

   PROFILE_END();
}