Forum

Detecting maps compiled with lit liquids

Post tutorials on how to do certain tasks within game or engine code here.

Moderator: InsideQC Admins

Detecting maps compiled with lit liquids

Postby mankrip » Mon Feb 20, 2017 8:49 pm

The key to understanding how to detect if liquid surfaces were compiled with lighting is to know that the flag that defines whether specific surfaces were compiled without lighting is not a surface flag, but a texinfo flag.

The map compilers sets TEX_SPECIAL on the texinfo structure for textures that should receive no lighting, but they don't set any flag for that on the surfaces themselves. In vanilla Quake, the TEX_SPECIAL flag is pretty much used only by the map compilers; the engine ignores it and sets SURF_DRAWTILED instead, based solely on the texture naming. Also, the names of those flags can be confusing and doesn't reflect how they're actually used.

So, we'll take care of that. This is the code that the Retroquad engine uses to detect lit liquids while parsing the BSP file:
Code: Select all
#define   TEXINFO_NOLIGHTMAP 1 // was TEX_SPECIAL // no lightmap or 256 subdivision

#define SURF_NOLIGHTMAP (1 << 2) // was SURF_DRAWTILED // mankrip - it's only purpose is to skip lightmaps in RecursiveLightPoint

void Mod_LoadFaces (lump_t *l)
{
...
   for (surfnum = 0 ; surfnum < count ; surfnum++, in++, out++)
   {
      out->firstedge = LittleLong (in->firstedge);
      out->numedges = LittleShort (in->numedges);
      // mankrip - begin
      out->plane = loadmodel->planes + LittleShort (in->planenum);
      out->texinfo = loadmodel->texinfo + LittleShort (in->texinfo);

      out->flags = LittleShort (in->side) ? SURF_PLANEBACK : 0;
      if (out->texinfo->texture->image->flags & TEX_SKY)
         out->flags |= (SURF_DRAWSKY | SURF_NOLIGHTMAP);
      else if (out->texinfo->flags & TEXINFO_NOLIGHTMAP)
         out->flags |= SURF_NOLIGHTMAP; // must be set before CalcSurfaceExtents

      CalcSurfaceExtents (out);

      // lighting info
      if (out->flags & SURF_NOLIGHTMAP)
         continue; // no need to set anything to zero
      out->numlightstylemaps = 0;
      for (i = 0 ; i < MAXLIGHTMAPS ; i++)
      {
         j = in->styles[i];
         if (j < MAX_LIGHTSTYLES && j != 255)
            out->lightadj[out->numlightstylemaps++] = &d_lightstylevalue[j];
      }
      i = LittleLong (in->lightofs);
      out->samples = (i == -1) ? NULL : loadmodel->lightdata + i;
      // mankrip - end
   }
}


void CalcSurfaceExtents (msurface_t *s)
{
...
   for (i = 0 ; i < 2 ; i++)
   {
...
      if (!(s->flags & SURF_NOLIGHTMAP) && s->extents[i] > 256) // mankrip
         Sys_Error ("Bad surface extents");
   }
}



And this is the code used to enable lit liquids during the rendering, which allows the user to switch the lighting on and off. It needs refactoring, but still works perfectly.
Code: Select all
void D_DrawSurfaces (void)
{
...
         // call specific surface type functions
         if (imageflags & TEX_TURBULENT)
         {
            // mankrip - lit water - begin
            lit = 1.0f;
                if (imageflags & TEX_WATER ) { lit = r_water_lit .value; }
            else if (imageflags & TEX_SLIME ) { lit = r_slime_lit .value; }
            else if (imageflags & TEX_LAVA  ) { lit = r_lava_lit  .value; }
            else if (imageflags & TEX_PORTAL) { lit = r_portal_lit.value; }
...
            D_SetDrawing_Turbulence_Texture (pface, transformed_modelorg);
...
            lcachewidth = 0; // FIXME: hack to set the current lighting mode at D_DrawSpans_Opaque_Turb and D_DrawSpans_Translucent_Turb
            if (lit && !(s->flags & SURF_NOLIGHTMAP)) // lightmap found
            {
               D_SetDrawing_Turbulence_Lighting (pface, D_MipLevelForScale_Light (s->nearzi * pface->texinfo->mipadjust), transformed_modelorg);
            }

            (*d_drawturb) (pspans, imageflags);
...
}


void D_DrawSpans_Opaque_Turb (espan_t *pspan, int flags) // TODO: eliminate this
{
   if (!D_Turb_UpdateMaterial (flags))
   {
      if (lcachewidth) // (!(flags & SURF_NOLIGHTMAP)) // checking flags isn't enough, because lighting can be disabled by r_lava_lit and so on
         D_DrawSpans_Opaque_Lit_Turb (pspan);
      else
         D_DrawSpans_Opaque_Unlit_Turb (pspan);
   }
   else
   {
      if (lcachewidth) // (!(flags & SURF_NOLIGHTMAP))
         D_DrawSpans_Opaque_Lit_Fall (pspan);
      else
         D_DrawSpans_Opaque_Unlit_Fall (pspan);
   }
}
Ph'nglui mglw'nafh mankrip Hell's end wgah'nagl fhtagn.
==-=-=-=-=-=-=-=-=-=-==
Dev blog / Twitter / YouTube
User avatar
mankrip
 
Posts: 915
Joined: Fri Jul 04, 2008 3:02 am

Return to Programming Tutorials

Who is online

Users browsing this forum: No registered users and 2 guests