Redline/source/renderframe.cpp

733 lines
21 KiB
C++
Raw Permalink Normal View History

//renderframe.cpp
//renders one graphics frame
#include <OpenGL/gl.h>
#include <math.h>
#include "entities.h"
#include "environment.h"
#include "fileio.h"
#include "sky.h"
#include "models.h"
#include "roads.h"
#include "text.h"
#include "screen.h"
#include "renderframe.h"
#include "rendercar.h"
#include "particles.h"
#include "tracks.h"
#include "stencil.h"
#include "config.h"
#include "transparency.h"
#include "gamemem.h"
#include "collision.h"
#include "gameinitexit.h"
#include "carphysics.h"
#include "random.h"
#include "gameframe.h"
#include "textures.h"
#include "lights.h"
2016-04-04 21:17:52 +00:00
#include "mVertex.h"
#ifdef __POLYCOUNT
int gPolyCount;
#endif
int gCameraMode,gCameraReverse,gClipEnable=true;
tMatrix3 gTransformDir;
tVector3 gTransformPos;
void Beer(tMatrix4 m)
{
MatrixRotX(m,0.1*sin(gFrameCount*0.01));
MatrixRotY(m,0.02*sin(gFrameCount*0.1));
MatrixRotZ(m,0.3*sin(gFrameCount*0.008));
MatrixScale(m,1+0.1*sin(gFrameCount*0.01),1+0.4*cos(gFrameCount*0.001),1-0.15*sin(gFrameCount*0.02));
tMatrix4 mt;
MatrixIdentity(mt);
MatrixRotX(mt,0.01*sin(gFrameCount*0.01));
MatrixRotY(mt,0.002*sin(gFrameCount*0.1));
MatrixRotZ(mt,0.03*sin(gFrameCount*0.008));
glMatrixMode(GL_TEXTURE);
glLoadMatrixf((float*)mt);
glMatrixMode(GL_MODELVIEW);
}
//Set up the Modelview matrix to draw the object at objPos, rotated by objDir
void SetupTranslation(tVector3 objPos,tMatrix3 objDir)
{
tMatrix4 m1,m2;
tMatrix3 m,r,invTransformDir;
MatrixIdentity(m1);
MatrixMult(m1,objDir,m2);
MatrixTranslateVector(m2,objPos-gCameraEntity->pos);
MatrixTranspose(gCameraEntity->dir,m);
r[0][0]=-1;r[0][1]=0;r[0][2]=0;
r[1][0]=0; r[1][1]=1;r[1][2]=0;
r[2][0]=0; r[2][1]=0;r[2][2]=-1;
MatrixMult(m,r,m);
MatrixMult(m2,m,m1);
#ifndef __TARGET_TOOLAPP
if(gGameInfo)
if(gGameInfo->carsOnSpeed)
Beer(m1);
#endif
glLoadMatrixf((float*)m1);
MatrixCopy(objDir,gTransformDir);
gTransformPos=objPos;
MatrixTranspose(objDir,invTransformDir);
GLfloat globalLightPosition[4];
*(tVector3*)globalLightPosition=gEnvironment->lightDir*invTransformDir;
if(gMapEnv)
if(!VectorZero(gMapEnv->lightDir))
*(tVector3*)globalLightPosition=gMapEnv->lightDir*invTransformDir;
globalLightPosition[3]=0;
glLightfv(GL_LIGHT0,GL_POSITION,globalLightPosition);
if(gViewedEntity)
{
float objDist=~(objPos-gViewedEntity->pos);
if(objDist==0)
gShineFactor=0;
else
{
gShineFactor=(objPos-gViewedEntity->pos)*(1/objDist)**MatrixGetZVector(gViewedEntity->dir);
// gShineFactor=sqr(sqr(sqr(sqr(gShineFactor))))*gShineFactor;
if(objDist>100)
gShineFactor-=(objDist-100)*0.005;
if(gShineFactor<0)gShineFactor=0;
}
}
}
//Set up the Modelview matrix to draw objects at world coordinates
void SetupWorldTranslation()
{
tMatrix4 m1,m2;
tMatrix3 m,r;
MatrixIdentity(m1);
MatrixTranslateVector(m1,-gCameraEntity->pos);
MatrixTranspose(gCameraEntity->dir,m);
r[0][0]=-1;r[0][1]=0;r[0][2]=0;
r[1][0]=0; r[1][1]=1;r[1][2]=0;
r[2][0]=0; r[2][1]=0;r[2][2]=-1;
MatrixMult(m,r,m);
MatrixMult(m1,m,m2);
#ifndef __TARGET_TOOLAPP
if(gGameInfo)
if(gGameInfo->carsOnSpeed)
Beer(m2);
#endif
glLoadMatrixf((float*)m2);
GLfloat globalLightPosition[4];
*(tVector3*)globalLightPosition=gEnvironment->lightDir;
if(gMapEnv)
if(!VectorZero(gMapEnv->lightDir))
*(tVector3*)globalLightPosition=gMapEnv->lightDir;
globalLightPosition[3]=0;
glLightfv(GL_LIGHT0,GL_POSITION,globalLightPosition);
MatrixIdentity(gTransformDir);
gTransformPos=Vector(0,0,0);
}
//calculates the clipping planes from the camera position and rotation
void SetupClipPlanes(tGameEntity *camera,tVector3 *clipPlanes)
{
clipPlanes[kClipBasePoint]=Vector(0,0,-kClipSaveDistance);
clipPlanes[kClipFarPoint]=Vector(0,0,ClipDistance()-kClipSaveDistance);
clipPlanes[kClipXPlane]=Vector(1,0,0);
clipPlanes[kClipYPlane]=Vector(0,1,0);
clipPlanes[kClipRearPlane]=Vector(0,0,1);
clipPlanes[kClipRightPlane]=Vector(-cos(gFOVX*0.5),0,sin(gFOVX*0.5));
clipPlanes[kClipLeftPlane]=Vector(-clipPlanes[kClipRightPlane].x,0,clipPlanes[kClipRightPlane].z);
clipPlanes[kClipTopPlane]=Vector(0,cos(gFOVY*0.5),sin(gFOVY*0.5));
clipPlanes[kClipBotPlane]=Vector(0,-clipPlanes[kClipTopPlane].y,clipPlanes[kClipTopPlane].z);
for(int i=0;i<kNumClipPlanes;i++)
{
clipPlanes[i]=clipPlanes[i]*camera->dir;
}
clipPlanes[kClipBasePoint]=clipPlanes[kClipBasePoint]+camera->pos;
}
//tests if the a point is inside the clipping volume given by clipPlanes
int ClipPoint(tVector3 *clipPlanes,tVector3 *point)
{
if(!gClipEnable)
return false;
tVector3 relPoint=*point-clipPlanes[kClipBasePoint];
int clip=0;
for(int plane=kClipRearPlane;plane<kNumClipPlanes;plane++)
if(relPoint*clipPlanes[plane]<0)
clip+=1<<plane;
relPoint=relPoint-clipPlanes[kClipFarPoint];
if(relPoint*clipPlanes[kClipRearPlane]>0)
clip+=1<<kClipFarPoint;
return clip;
}
//tests if the a point is inside the clipping volume given by clipPlanes,
//or within distance of it (useful as the objects we want to clip are usually bigger
//than a single point in space)
int ClipPointDistanced(tVector3 *clipPlanes,tVector3 *point,float distance)
{
if(!gClipEnable)
return false;
tVector3 relPoint=*point-clipPlanes[kClipBasePoint];
int clip=0;
for(int plane=kClipRearPlane;plane<kNumClipPlanes;plane++)
if(relPoint*clipPlanes[plane]<-distance)
clip+=1<<plane;
relPoint=relPoint-clipPlanes[kClipFarPoint];
if(relPoint*clipPlanes[kClipRearPlane]>distance)
clip+=1<<kClipFarPoint;
return clip;
}
//swap the position of two entities in the gmae entity list
void SwitchEntities(tGameEntity* obj1,tGameEntity* obj2)
{
((tGameEntity*)obj1->prev)->next=obj2;
((tGameEntity*)obj2->next)->prev=obj1;
obj1->next=obj2->next;
obj2->prev=obj1->prev;
obj1->prev=obj2;
obj2->next=obj1;
}
void SortEntities()
{
tGameEntity *entity=(tGameEntity*)gFirstEntity->next;
while(entity!=gFirstEntity)
{
if(entity->renderType==kRenderTypeModel||entity->renderType==kRenderTypeCar||entity->renderType==kRenderTypeGhost)
{
tVector3 center=ModelGetCenter(entity->renderData);
center=center*entity->dir;
center=center+entity->pos;
entity->zDist=(center-gCameraEntity->pos)**MatrixGetZVector(gCameraEntity->dir);
}
else
entity->zDist=(entity->pos-gCameraEntity->pos)**MatrixGetZVector(gCameraEntity->dir);
entity=(tGameEntity*)entity->next;
}
tGameEntity *start=(tGameEntity*)gFirstEntity->next;
tGameEntity *end=gFirstEntity;
int change;
do{ //since in most cases there wont be much change a shaking sort is often the fastest
entity=start;
change=false;
while(entity->next!=end)
{
tGameEntity *next=(tGameEntity*)entity->next;
if(next->zDist>entity->zDist)
{SwitchEntities(entity,next);change=true;}
else
entity=next;
}
if(change)
{
end=(tGameEntity*)end->prev;
entity=end;
while(entity->prev!=start)
{
tGameEntity *prev=(tGameEntity*)entity->prev;
if(prev->zDist<entity->zDist)
SwitchEntities(prev,entity);
else
entity=prev;
}
start=(tGameEntity*)start->next;
if(start==end) change=false;
}
}while(change);
}
void RenderObjectPass(tVector3 *clipPlanes)
{
glPushAttrib(GL_LIGHTING_BIT+GL_TEXTURE_BIT+GL_POLYGON_BIT+GL_COLOR_BUFFER_BIT);
tGameEntity *drawEntity=(tGameEntity*)gFirstEntity->prev;
while(drawEntity!=gFirstEntity)
{
if(drawEntity->renderType==kRenderTypeModel||drawEntity->renderType==kRenderTypeCar||drawEntity->renderType==kRenderTypeGhost)
{
float distance=ModelGetCenterMaxExtends(drawEntity->renderData);
tVector3 center=ModelGetCenter(drawEntity->renderData);
center=center*drawEntity->dir;
center=center+drawEntity->pos;
if(drawEntity->zDist>-distance||!gClipEnable)
if(!ClipPointDistanced(clipPlanes,&center,distance))
{
SetupTranslation(drawEntity->pos,drawEntity->dir);
switch(drawEntity->renderType)
{
case kRenderTypeModel:
DrawModel(drawEntity->renderData,true,*((int*)drawEntity->physics));
break;
case kRenderTypeCar:
{
if(gCameraMode==kCameraCockpitCarHidden&&drawEntity==gCarEntities[gReplayViewedEntityID]&&sqr(gCameraEntity->pos-drawEntity->pos)<sqr(1.5))
break;
int drawInterior=drawEntity==gViewedEntity;
float clipInteriorDist=gConfig->gfxDynamics*200.0f;
if(drawEntity->zDist<clipInteriorDist)
drawInterior=true;
if(!gConfig->interiorDisplay)
drawInterior=false;
CarRenderEntity(drawEntity,drawInterior,drawEntity->controlType!=kControlTypeNone&&!(drawEntity==gViewedEntity&&gCameraMode==kCameraCockpit));
if(gConfig->showPlayerNames&&gGameInfo->network&&(drawEntity!=gCarEntities[gReplayViewedEntityID]))
{
tVector3 pos=drawEntity->pos+Vector(0,3,0);
pos=pos-gCameraEntity->pos;
tMatrix3 inv;
MatrixTranspose(gCameraEntity->dir,inv);
pos=pos*inv;
float size=0.8+pos.z*0.005;
for(int i=0;i<gGameInfo->numPlayers;i++)
if(gCarEntities[i]==drawEntity)
TextPrintfToBufferFormatedVector3(pos,size,kTextAlignMiddle,gGameInfo->playerNames[i]);
}
}
break;
case kRenderTypeGhost:
if(!gConfig->noGhost)
CarRenderEntityGhost(drawEntity);
break;
}
}
}
drawEntity=(tGameEntity*)drawEntity->prev;
}
glPopAttrib();
}
#define kEntMinShadow 6
void RenderShadowPass(tVector3 *clipPlanes,int highQual)
{
glPushAttrib(GL_ENABLE_BIT+GL_POLYGON_BIT);
tGameEntity *drawEntity=(tGameEntity*)gFirstEntity->next;
while(drawEntity!=gFirstEntity&&drawEntity->zDist>-200)
{
if(gConfig->gfxDynamics>=0.2||drawEntity==gViewedEntity)
if(drawEntity->renderType==kRenderTypeModel||drawEntity->renderType==kRenderTypeCar)
if((sqr(drawEntity->pos-gCameraEntity->pos)<sqr(30))==highQual)
{
int shad=true;
if(drawEntity->renderType==kRenderTypeModel)
if(drawEntity->physicsType!=kPhysicsTypeSolid)
shad=false;
else
{
tSolidEntityPhysics *ent=(tSolidEntityPhysics*)gFileTable[drawEntity->physicsData].parsedData;
if(ent->shadowModel==kFileErr)
shad=false;
}
if(shad)
{
float shadowLength=GetGroundOffset(drawEntity->pos,&drawEntity->lastRoadIndex,0,0)+kEntMinShadow;
shadowLength/=gEnvironment->lightDir.y;
float distance=ModelGetMaxExtends(drawEntity->renderData)+shadowLength;
if(drawEntity->zDist>-distance&&drawEntity->zDist<ClipDistance()-distance)
if(!ClipPointDistanced(clipPlanes,&drawEntity->pos,distance))
{
SetupTranslation(drawEntity->pos,drawEntity->dir);
switch(drawEntity->renderType)
{
case kRenderTypeCar:
if(gCameraMode!=kCameraCockpitCarHidden||drawEntity!=gCarEntities[gReplayViewedEntityID])
CarRenderEntityShadow(drawEntity,0);
break;
case kRenderTypeModel:
tSolidEntityPhysics *ent=(tSolidEntityPhysics*)gFileTable[drawEntity->physicsData].parsedData;
DrawModelShadow(ent->shadowModel,shadowLength);
break;
}
}
}
}
drawEntity=(tGameEntity*)drawEntity->next;
}
glPopAttrib();
}
#define kLightConeClip 200
void RenderLightConesPass(tVector3 *clipPlanes)
{
tGameEntity *drawEntity=(tGameEntity*)gFirstEntity->next;
while(drawEntity!=gFirstEntity&&drawEntity->zDist>-25)
{
if(!ClipPointDistanced(clipPlanes,&drawEntity->pos,kLightConeClip))
{
switch(drawEntity->renderType)
{
case kRenderTypeCar:
if(drawEntity==gViewedEntity)
{
tCarPhysics *phys=(tCarPhysics*)drawEntity->physics;
tCarDefinition *car=&(phys->car);
RenderEntityLightCones(drawEntity,car->numLights,phys->lightFlags,car->lights);
}
break;
case kRenderTypeModel:
if(drawEntity->physicsType==kPhysicsTypeSolid)
{
tSolidEntityPhysics *ent=(tSolidEntityPhysics*)gFileTable[drawEntity->physicsData].parsedData;
RenderEntityLightCones(drawEntity,ent->numLights,0xffff,ent->lights);
}
break;
}
}
drawEntity=(tGameEntity*)drawEntity->next;
}
}
void RenderLightsPass(tVector3 *clipPlanes)
{
gTexturesQualityModifier=-255;
tGameEntity *drawEntity=(tGameEntity*)gFirstEntity->next;
while(drawEntity!=gFirstEntity)
{
SetupTranslation(drawEntity->pos,drawEntity->dir);
switch(drawEntity->renderType)
{
case kRenderTypeCar:{
tCarPhysics *phys=(tCarPhysics*)drawEntity->physics;
tCarDefinition *car=&(phys->car);
RenderEntityLights(drawEntity,car->numLights,phys->lightFlags,phys->echo,car->lights);
}break;
case kRenderTypeModel:
if(drawEntity->physicsType==kPhysicsTypeSolid)
{
int objFrameCount=gFrameCount+10*((drawEntity->id*31)%17);
int allLightEnable=gEnvironment->spotLightEnable;
if(gMapEnv)
if(gMapEnv->lightEnable)
allLightEnable=true;
int objLightFlags=0x1
|(((int)(objFrameCount/(2*kFPS))%2)?0x2:0)
|(((int)(objFrameCount/(1*kFPS))%2)?0x4:0)
|(((int)(objFrameCount/(0.5*kFPS))%2)?0x8:0)
|(((int)(objFrameCount/(0.3*kFPS))%4)?0:0x10)
|(allLightEnable?0x20:0);
tSolidEntityPhysics *ent=(tSolidEntityPhysics*)gFileTable[drawEntity->physicsData].parsedData;
RenderEntityLights(drawEntity,ent->numLights,objLightFlags,0,ent->lights);
}
break;
}
drawEntity=(tGameEntity*)drawEntity->next;
}
gTexturesQualityModifier=0;
}
void SetupLighting()
{
if(gCameraEntity)
SetupWorldTranslation();
GLfloat globalLightAmbient[4];
*(tVector3*)globalLightAmbient=gEnvironment->ambient;
globalLightAmbient[3]=1;
GLfloat globalLightDiffuse[4];
*(tVector3*)globalLightDiffuse=gEnvironment->diffuse;
globalLightDiffuse[3]=1;
GLfloat globalLightSpecular[4];
*(tVector3*)globalLightSpecular=gEnvironment->specular;
globalLightSpecular[3]=1;
GLfloat globalLightPosition[4];
*(tVector3*)globalLightPosition=gEnvironment->lightDir;
if(gMapEnv)
if(!VectorZero(gMapEnv->lightDir))
*(tVector3*)globalLightPosition=gMapEnv->lightDir;
globalLightPosition[3]=0;
if(gLightning)
{
globalLightAmbient[0]=1;
globalLightAmbient[1]=1;
globalLightAmbient[2]=1;
globalLightDiffuse[0]=1;
globalLightDiffuse[1]=1;
globalLightDiffuse[2]=1;
globalLightSpecular[0]=1;
globalLightSpecular[1]=1;
globalLightSpecular[2]=1;
}
glEnable(GL_LIGHT0);
glLightfv(GL_LIGHT0,GL_AMBIENT,globalLightAmbient);
glLightfv(GL_LIGHT0,GL_DIFFUSE,globalLightDiffuse);
glLightfv(GL_LIGHT0,GL_SPECULAR,globalLightSpecular);
glLightfv(GL_LIGHT0,GL_POSITION,globalLightPosition);
if(gMapEnv)
if(gMapEnv->fogBegin)
{
GLfloat fogColor[4];
*(tVector3*)fogColor=gMapEnv->fogColor;
fogColor[3]=1;
glFogfv(GL_FOG_COLOR,fogColor);
glFogf(GL_FOG_START,gMapEnv->fogBegin*(1+0.3*gMapEnv->fogOscillation*sin(gFrameCount*kFrameTime*0.7*gMapEnv->fogOscillationSpeed)));
glFogf(GL_FOG_END,gMapEnv->fogEnd*(1+0.5*gMapEnv->fogOscillation*sin(gFrameCount*kFrameTime*0.3*gMapEnv->fogOscillationSpeed)));
}
}
void DrawFlare(tFileRef texture,float x,float y,float size,float alpha)
{
glPushAttrib(GL_DEPTH_BUFFER_BIT+GL_LIGHTING_BIT+GL_COLOR_BUFFER_BIT+GL_TEXTURE_BIT+GL_CURRENT_BIT);
glDisable(GL_DEPTH_TEST);
glDisable(GL_LIGHTING);
glEnable(GL_BLEND);
glBlendFunc(GL_ONE,GL_ONE);
glLoadIdentity();
glTranslatef(0.0f,0.0f,-1.0f);
glTranslatef(x,y,0);
glScalef(size*0.5,size*0.5,0);
glColor4f(1,1,1,alpha);
TexturesSelectTex(texture);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_CLAMP);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_CLAMP);
glBegin(GL_TRIANGLE_STRIP);
glTexCoord2d(1,1); glVertex2f(1,-1);
glTexCoord2d(1,0); glVertex2f(1,1);
glTexCoord2d(0,1); glVertex2f(-1,-1);
glTexCoord2d(0,0); glVertex2f(-1,1);
glEnd();
glPopAttrib();
}
void FlaresDraw1()
{
if(gEnvironment->flaresEnable)
{
tMatrix3 cameraInverse;
MatrixTranspose(gCameraEntity->dir,cameraInverse);
tVector3 flarePos=gEnvironment->flareDir*cameraInverse;
if(gMapEnv)
if(!VectorZero(gMapEnv->flareDir))
flarePos=gMapEnv->flareDir*cameraInverse;
if(flarePos.z<=0)return;
tVector2 flarePosProjected=Vector(flarePos.x/flarePos.z,-flarePos.y/flarePos.z);
DrawFlare(FileGetReference("flare1.tif"),-flarePosProjected.x*0.5,-flarePosProjected.y*0.5,0.6,1.0);
}
}
void FlaresDraw2()
{
if(gEnvironment->flaresEnable)
{
tMatrix3 cameraInverse;
MatrixTranspose(gCameraEntity->dir,cameraInverse);
tVector3 flarePos=gEnvironment->flareDir*cameraInverse;
if(gMapEnv)
if(!VectorZero(gMapEnv->flareDir))
flarePos=gMapEnv->flareDir*cameraInverse;
if(flarePos.z<=0)return;
tVector2 flarePosProjected=Vector(flarePos.x/flarePos.z,-flarePos.y/flarePos.z);
DrawFlare(FileGetReference("flare5.tif"),flarePosProjected.x*1.5,flarePosProjected.y*1.5,0.6,1.0);
DrawFlare(FileGetReference("flare4.tif"),flarePosProjected.x*0.5,flarePosProjected.y*0.5,0.6,1.0);
DrawFlare(FileGetReference("flare3.tif"),flarePosProjected.x*0.25,flarePosProjected.y*0.25,0.6,1.0);
DrawFlare(FileGetReference("flare2.tif"),-flarePosProjected.x*0.1,-flarePosProjected.y*0.1,0.6,1.0);
}
}
void GameShowInfo();
void RenderVisWalls()
{
SetupWorldTranslation();
glColorMask(0,0,0,0);
glDisable(GL_CULL_FACE);
for(int i=0;i<gMapInfo->numVisWalls;i++)
{
glBegin(GL_TRIANGLES);
glVertex3fv(&(gMapInfo->visWalls[i].a.x));
glVertex3fv(&(gMapInfo->visWalls[i].b.x));
glVertex3fv(&(gMapInfo->visWalls[i].c.x));
glVertex3fv(&(gMapInfo->visWalls[i].b.x));
glVertex3fv(&(gMapInfo->visWalls[i].c.x));
2016-04-04 21:17:52 +00:00
mVertex3fv(((gMapInfo->visWalls[i].c+(gMapInfo->visWalls[i].b-gMapInfo->visWalls[i].a))));
glEnd();
}
glEnable(GL_CULL_FACE);
glColorMask(1,1,1,1);
}
int gLastFrameBlur=false;
int gLastGraphFrame=0;
#define kMaxBlur 0.925
void MotionBlur()
{
float blur;
if(gConfig->carsOnSpeed)
//blur=0.9+0.25*sin(gFrameCount*kFrameTime*0.2);
blur=1;
else
{
if(!gConfig->motionBlur)
return;
blur=((~gCameraEntity->velo-30)/55.0);
}
int blurExp=gFrameCount-gLastGraphFrame-1;
if(blurExp>10)blurExp=10;
if(blurExp<0)blurExp=0;
blur*=pow(kMaxBlur,blurExp);
if(blur>0&&(gGameInfo->arcade==kGameModeArcade||gGameInfo->arcade==kGameModeTurbo||gConfig->carsOnSpeed)&&gConfig->motionBlur)
{
if(blur>1)
blur=1;
glPushAttrib(GL_ENABLE_BIT+GL_CURRENT_BIT);
glDisable(GL_CULL_FACE);
glDisable(GL_LIGHTING);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
glLoadIdentity();
glColor4f(1,1,1,kMaxBlur*blur);
glMatrixMode(GL_PROJECTION);
glPushMatrix();
glLoadIdentity();
glOrtho(0,gConfig->screenXSize,0,gConfig->screenYSize,-1,2);
for(int i=0;i<4;i++)
if(gScreenTextures[i].xSize)
{
glBindTexture(GL_TEXTURE_2D,gScreenTextures[i].texture);
if(gLastFrameBlur)
{
glBegin(GL_TRIANGLE_STRIP);
glTexCoord2d(1,1); glVertex3f(gScreenTextures[i].xSize+gScreenTextures[i].xOffset, gScreenTextures[i].ySize+gScreenTextures[i].yOffset,1);
glTexCoord2d(1,0); glVertex3f(gScreenTextures[i].xSize+gScreenTextures[i].xOffset, gScreenTextures[i].yOffset,1);
glTexCoord2d(0,1); glVertex3f(0+gScreenTextures[i].xOffset, gScreenTextures[i].ySize+gScreenTextures[i].yOffset,1);
glTexCoord2d(0,0); glVertex3f(0+gScreenTextures[i].xOffset, gScreenTextures[i].yOffset,1);
glEnd();
}
glCopyTexImage2D(GL_TEXTURE_2D,0,GL_RGBA,gScreenTextures[i].xOffset,gScreenTextures[i].yOffset,gScreenTextures[i].xSize,gScreenTextures[i].ySize,0);
}
glPopMatrix();
glPopAttrib();
glMatrixMode(GL_MODELVIEW);
gLastFrameBlur=true;
}
else
gLastFrameBlur=false;
}
void RenderFrame(int screenUpdate)
{
#ifdef __POLYCOUNT
gPolyCount=0;
#endif
//gClipEnable=false;
// SetupAspect(kNormalFOVY+~gCameraEntity->velo*0.002*gGameInfo->arcade);
float fov=1.0;
if(gGameInfo->arcade==kGameModeArcade||gGameInfo->arcade==kGameModeTurbo)
fov+=~gCameraEntity->velo*0.0015*(gGameInfo->arcade+1);
if(fov>1.6)fov=1.6;
SetupAspect(fov);
tVector3 clipPlanes[kNumClipPlanes];
SetupClipPlanes(gCameraEntity,clipPlanes);
SetupLighting();
SkyRender();
FlaresDraw1();
RenderVisWalls();
SortEntities();
RenderObjectPass(clipPlanes); //first pass: objects
if(!gMapInfo->dontDrawRoad)
RoadRender(clipPlanes);
TracksRender(clipPlanes);
if(gConfig->stencil)//second pass: shadows/light Cones
{
int stencil=4.0f*gConfig->gfxDynamics;
if(stencil<=0)
stencil=1;
if(gEnvironment->shadowEnable)
{
for(int i=1;i<=stencil;i++)
{
gStencilZoom=0.9+0.1*i/(float)(stencil);
RenderShadowPass(clipPlanes,true);
RenderStencilLayer(true,stencil);
}
gStencilZoom=1.0;
RenderShadowPass(clipPlanes,false);
RenderStencilLayer(true,1);
}
if(gEnvironment->spotLightEnable)
{
for(int i=1;i<=stencil*1.5;i++)
{
gStencilZoom=0.75+0.25*i/((float)stencil*1.5);
RenderLightConesPass(clipPlanes);
RenderStencilLayer(false,stencil);
}
}
}
DrawTransparentPolys(clipPlanes);//third pass: transparent stuff
RenderLightsPass(clipPlanes); //fourth pass: lights
ParticlesDraw();
SetupAspect(kNormalFOVY);
FlaresDraw2();
if(!gBackgroundReplay)
{
GameShowInfo();
MotionBlur();
if(screenUpdate)
ScreenBlit();
}
gLastGraphFrame=gFrameCount;
}