Detecting maps compiled with lit liquids

Post tutorials on how to do certain tasks within game or engine code here.
Post Reply
mankrip
Posts: 924
Joined: Fri Jul 04, 2008 3:02 am

Detecting maps compiled with lit liquids

Post by mankrip »

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
Post Reply