Fixing dynamic light shine through

 

Copyright info

All code in this tutorial is protected by the [GPL License].
All text in this tutorial is protected by the [FDL License].

 

Tutorial by: Discolada

Mailto: Discoloda@planetquake.com

Have you ever noticed how the dynamic lights always seem to show on everything? even on the other side of walls? well im here to fix that. wat we are going to do is stop quake2 from aplying light to a surface when it shouldnt.

so open up gl_light.c and find the function R_MarkLights. and locate these lines here:

 
 
// mark the polygons
          surf = r_worldmodel->surfaces + node->firstsurface;
          for (i=0 ; i < node->numsurfaces ; i++, surf++)
 
     

this is going thru each surface of the node that we are in. and then asignes a bit that the dynamic light was given. it is here were its best to stop the light. so right after the above code we add:

 
 
                   dist = DotProduct (light->origin, surf->plane->normal) - surf->plane->dist;
 
     

this finds the distance from the current surface to the light. if this returns a negative value then the point (light->origin in this case) is behind the plane... but the plane could be turned up side down in the map so we have:

 
 
                   if (dist >= 0)
                             sidebit = 0;
                   else
                             sidebit = SURF_PLANEBACK;
 
                   if ( (surf->flags & SURF_PLANEBACK) != sidebit )                                   //Discoloda
                             continue;                                                                //Discoloda
 
     

this will skip the current surface if the plane is not looking at the light. this is about it... next time i will show you how to skip surfaces that cant be seen by the light (a wall or a piller in the way). and dont forget to add "int sidebit;"to the top of the function:

for all you copy-paste fools out there here is the new R_MarkLights function:

 
 
void R_MarkLights (dlight_t *light, int bit, mnode_t *node)
{
          cplane_t  *splitplane;
          float              dist;
          msurface_t         *surf;
          int                i, sidebit;
          float              dot;
          
          if (node->contents != -1)
                   return;
 
          splitplane = node->plane;
          dist = DotProduct (light->origin, splitplane->normal) - splitplane->dist;
 
          if (dist > light->intensity-DLIGHT_CUTOFF) {
                   R_MarkLights (light, bit, node->children[0]);
                   return;
          }
          if (dist < -light->intensity+DLIGHT_CUTOFF) {
                   R_MarkLights (light, bit, node->children[1]);
                   return;
          }
 
// mark the polygons
          surf = r_worldmodel->surfaces + node->firstsurface;
          for (i=0 ; i<node->numsurfaces ; i++, surf++)
          {
                   dist = DotProduct (light->origin, surf->plane->normal) - surf->plane->dist;         //Discoloda
                   if (dist >= 0)                                                                              //Discoloda
                             sidebit = 0;                                                                      //Discoloda
                   else                                                                                        //Discoloda
                             sidebit = SURF_PLANEBACK;                                                //Discoloda
 
                   if ( (surf->flags & SURF_PLANEBACK) != sidebit )                                   //Discoloda
                             continue;                                                                //Discoloda
 
                   if (surf->dlightframe != r_dlightframecount)
                   {
                             surf->dlightbits = bit;
                             surf->dlightframe = r_dlightframecount;
                   } else
                             surf->dlightbits |= bit;
          }
 
          R_MarkLights (light, bit, node->children[0]);
          R_MarkLights (light, bit, node->children[1]);
}
     

 

 

Tutorial Originally found at: