#include #include #include "vectors.h" #include "environment.h" #include "entities.h" #include "textures.h" #include "renderframe.h" #include "roads.h" #include "collision.h" #include "config.h" #include "stencil.h" #define kLightOffset 0.6 #define kLightReflectionOffset 15 void RenderEntityLights(tGameEntity *entity,int numLights,int lightFlags,float reflectionDim,tLightDefinition *lights) { glPushAttrib(GL_DEPTH_BUFFER_BIT+GL_CURRENT_BIT+GL_LIGHTING_BIT+GL_COLOR_BUFFER_BIT+GL_FOG_BIT); glDepthMask(false); glDisable(GL_LIGHTING); glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA,GL_ONE); glDisable(GL_FOG); TexturesSelectTex(FileGetReference("Particle.pct")); for(int i=0;idir**MatrixGetZVector(gCameraEntity->dir); //is the light pointing towards the camera? if(lights[i].type==kLightTypeDirectionlessDot||lights[i].type==kLightTypeDirectionlessDotReflective) visibility=1; else if(lights[i].type==kLightTypeSpecularDot) visibility=sign(visibility)*powf(visibility*!((lights[i].pos*entity->dir+entity->pos)-gCameraEntity->pos)**MatrixGetZVector(gCameraEntity->dir),100); if(visibility>0){ if(visibility>1)visibility=1; float size=lights[i].size; //draw particle texture tVector3 lightPos=lights[i].pos*entity->dir+entity->pos; float camDist=~(lightPos-gCameraEntity->pos); tVector3 drawlightPos=lightPos-(lightPos-gCameraEntity->pos)*kLightOffset/camDist; size*=(camDist-kLightOffset)/camDist; SetupTranslation(drawlightPos,gCameraEntity->dir); glColor4f(lights[i].rgb.x,lights[i].rgb.y,lights[i].rgb.z,visibility); glBegin(GL_TRIANGLE_STRIP); glTexCoord2d(1,1); glVertex2f(size,size); glTexCoord2d(1,0); glVertex2f(size,-size); glTexCoord2d(0,1); glVertex2f(-size,size); glTexCoord2d(0,0); glVertex2f(-size,-size); glEnd(); //does the light reflect on the ground? if(lights[i].type==kLightTypeDotRefelective||lights[i].type==kLightTypeDirectionlessDotReflective) { int lastRoadIndex=entity->lastRoadIndex; int surface=-1; lightPos=lightPos-Vector(0,GetGroundOffset(lightPos,&lastRoadIndex,NULL,&surface),0); float camDist=~(lightPos-gCameraEntity->pos); float size=lights[i].size; if(camDist>2*kLightReflectionOffset) { drawlightPos=lightPos-(lightPos-gCameraEntity->pos)*kLightReflectionOffset/camDist; size*=(camDist-kLightReflectionOffset)/camDist; } else drawlightPos=lightPos; //is the ground reflective if(surface!=-1) if(gSurfaceTypes->types[surface].reflectionEnable) { //draw reflection texture SetupTranslation(drawlightPos,gCameraEntity->dir); if(camDist<=2*kLightReflectionOffset) glDisable(GL_DEPTH_TEST); visibility*=1-reflectionDim*0.6; glColor4f(lights[i].rgb.x,lights[i].rgb.y,lights[i].rgb.z,visibility); TexturesSelectTex(FileGetReference("lightreflection.pct")); glBegin(GL_TRIANGLE_STRIP); glTexCoord2d(1,1); glVertex2f(size,size); glTexCoord2d(1,0); glVertex2f(size,-5*size); glTexCoord2d(0,1); glVertex2f(-size,size); glTexCoord2d(0,0); glVertex2f(-size,-5*size); glEnd(); TexturesSelectTex(FileGetReference("Particle.pct")); #ifdef __POLYCOUNT gPolyCount+=2; #endif glEnable(GL_DEPTH_TEST); } } #ifdef __POLYCOUNT gPolyCount+=2; #endif } } glPopAttrib(); } #define kConeSections 16 #define kConeLength 6.5 void DrawLightCone(float scale) { tVector3 c[kConeSections]; for(int i=0;i0) { float cClipPos=(1-(cClipDist/(cClipDist-baseClipDist))); if(cClipPos<=0)return; c[i]=c[i]*cClipPos; } for(int i=0;istencil&&gEnvironment->spotLightEnable) { //translate to draw the light cone tVector3 lightPos=lights[i].pos*entity->dir+entity->pos; tMatrix3 m; MatrixIdentity(m); *MatrixGetZVector(m)=lights[i].dir; *MatrixGetXVector(m)=!(lights[i].dir%Vector(0,1,0)); *MatrixGetYVector(m)=(lights[i].dir%*MatrixGetXVector(m)); MatrixMult(m,entity->dir,m); SetupTranslation(lightPos,m); //setup stencil buffer //drawing light cones works just like stencil buffer shadow volumes glDepthMask(GL_FALSE); glEnable(GL_STENCIL_TEST); glColorMask(0, 0, 0, 0); glStencilFunc(GL_ALWAYS, 1, 0xffffffff); tVector3 camDir=*MatrixGetZVector(gCameraEntity->dir); float clip1=(lightPos-gCameraEntity->pos)*camDir; float clip2=((lightPos+(lights[i].dir*kConeLength*lights[i].size)*entity->dir)-gCameraEntity->pos)*camDir; //test if the light cone volume intersects the clipping volume if(clip1>ClipDistance()&&clip2>ClipDistance()) {//clip near and far (not implemented) } else if(clip1>ClipDistance()) {//clip near (not implemented) } else if(clip2>ClipDistance()-20) {//clip far tMatrix3 mInv; MatrixTranspose(m,mInv); tVector3 clipPlaneDir=camDir*mInv; glFrontFace(GL_CW); glStencilOp(GL_KEEP, GL_INCR, GL_KEEP); DrawLightConeClippedFar(lights[i].size*gStencilZoom,(ClipDistance()-20-clip1)/(clip2-clip1),clipPlaneDir); glFrontFace(GL_CCW); glStencilOp(GL_KEEP, GL_DECR, GL_KEEP); DrawLightConeClippedFar(lights[i].size*gStencilZoom,(ClipDistance()-20-clip1)/(clip2-clip1),clipPlaneDir); } else {//no clip glFrontFace(GL_CW); glStencilOp(GL_KEEP, GL_INCR, GL_KEEP); DrawLightCone(lights[i].size*gStencilZoom); glFrontFace(GL_CCW); glStencilOp(GL_KEEP, GL_DECR, GL_KEEP); DrawLightCone(lights[i].size*gStencilZoom); } } glPopAttrib(); }