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);
}
}