Proper lit water on TyrUtils' light.exe
Moderator: InsideQC Admins
4 posts
• Page 1 of 1
Proper lit water on TyrUtils' light.exe
Simple copypaste. Liquid surfaces must be lit not only from the front, but also from the back.
This code includes a hack to force liquid surfaces' lightmaps to always be saved, otherwise fully dark liquids would remain fullbright.
This code includes a hack to force liquid surfaces' lightmaps to always be saved, otherwise fully dark liquids would remain fullbright.
- Code: Select all
static int backwater; // mankrip
static void
LightFace_Entity(const entity_t *entity, const lightsample_t *light,
const lightsurf_t *lightsurf, lightmap_t *lightmaps)
{
const modelinfo_t *modelinfo = lightsurf->modelinfo;
const plane_t *plane = &lightsurf->plane;
const dmodel_t *shadowself;
const vec_t *surfpoint;
int i;
qboolean hit;
vec_t dist, add, angle, spotscale;
lightsample_t *sample;
lightmap_t *lightmap;
vec3_t anormal; // mankrip
dist = DotProduct(entity->origin, plane->normal) - plane->dist;
VectorCopy (plane->normal, anormal); // mankrip
/* don't bother with lights behind the surface */
if (dist < 0)
// mankrip - begin
{
if (!backwater)
// mankrip - end
return;
// mankrip - begin
VectorInverse (anormal);
}
// mankrip - end
/* don't bother with light too far away */
if (dist > entity->fadedist)
if (!backwater) // mankrip
return;
/*
* Check it for real
*/
hit = false;
hit = backwater; // mankrip
lightmap = Lightmap_ForStyle(lightmaps, entity->style);
shadowself = modelinfo->shadowself ? modelinfo->model : NULL;
sample = lightmap->samples;
surfpoint = lightsurf->points[0];
for (i = 0; i < lightsurf->numpoints; i++, sample++, surfpoint += 3) {
vec3_t ray;
VectorSubtract(entity->origin, surfpoint, ray);
dist = VectorLength(ray);
/* Quick distance check first */
if (dist > entity->fadedist)
continue;
/* Check spotlight cone */
VectorScale(ray, 1.0 / dist, ray);
angle = DotProduct(ray, anormal); // mankrip - edited
[...]
}
void
LightFace(bsp2_dface_t *face, const modelinfo_t *modelinfo,
const bsp2_t *bsp)
{
int i, j, k;
const entity_t *entity;
lightsample_t *sample;
lightsurf_t lightsurf;
sun_t *sun;
/* One extra lightmap is allocated to simplify handling overflow */
lightmap_t lightmaps[MAXLIGHTMAPS + 1];
/* some surfaces don't need lightmaps */
face->lightofs = -1;
for (i = 0; i < MAXLIGHTMAPS; i++)
face->styles[i] = 255;
if (bsp->texinfo[face->texinfo].flags & TEX_SPECIAL)
return;
// mankrip - begin
{
const texinfo_t *tex = &bsp->texinfo[face->texinfo];
const int offset = bsp->dtexdata.header->dataofs[tex->miptex];
const miptex_t *miptex = (const miptex_t *)(bsp->dtexdata.base + offset);
backwater = (miptex->name[0] == '*');
}
// mankrip - end
[...]
}
-

mankrip - Posts: 906
- Joined: Fri Jul 04, 2008 3:02 am
Re: Proper lit water on TyrUtils' light.exe
Holy smokes! This has been on wish-lists forever. Surfaces must be lit from both sides because lighting will stop at the surface?
-
qbism - Posts: 1230
- Joined: Thu Nov 04, 2004 5:51 am
Re: Proper lit water on TyrUtils' light.exe
technically the light coming up from a water surface should be relative to the average light level within the water volume beneath the surface, combined with the light hitting that paritcular part of the surface (spread out a lot without any harsh shadows, representing the amount of light bouncing locally between impurities before being bounced back out of the volume itself - note that this part won't be all that significant, as it would take quite a lot of impurities to completely reflect it all).
the other way around is muuuuch harder to describe, on account of quake not actually having any of those impurities that I just described that give the water itself any colour...
so yeah, just make it accept light from both sides so that a light under the surface doesn't brighten up a wall next to the water without also making the water surface visible too.
just get the lighting tool to completely ignore the surface normal for fully diffuse lighting, because there really isn't any other sane way to deal with it.
which is what I believe mankrip has done.
the other way around is muuuuch harder to describe, on account of quake not actually having any of those impurities that I just described that give the water itself any colour...
so yeah, just make it accept light from both sides so that a light under the surface doesn't brighten up a wall next to the water without also making the water surface visible too.
just get the lighting tool to completely ignore the surface normal for fully diffuse lighting, because there really isn't any other sane way to deal with it.
which is what I believe mankrip has done.
- Spike
- Posts: 2806
- Joined: Fri Nov 05, 2004 3:12 am
- Location: UK
Re: Proper lit water on TyrUtils' light.exe
qbism wrote:Surfaces must be lit from both sides because lighting will stop at the surface?
On the contrary; they won't.
As Spike described, by default a light under the water will brighten any nearby walls all the way without stopping, so the water surface must properly indicate that there's light crossing it.
Spike: No, this code doesn't ignore the normals, it just inverts the normals of backfaced surfaces. This way the lighting on the water surface will match the lighting on the nearby floors.
-

mankrip - Posts: 906
- Joined: Fri Jul 04, 2008 3:02 am
4 posts
• Page 1 of 1
Return to Programming Tutorials
Who is online
Users browsing this forum: No registered users and 1 guest