Merge common lighting code. Still some lightmap-related code in *_rsurf.c that might be mergable. This is the first step towards 3 component lighting for the sw32 renderer.

Note that gl_lightmap_components is now r_lightmap_components, and gl_dlight_lightmaps is now r_dlight_lightmaps.
This commit is contained in:
Ragnvald Maartmann-Moe IV 2001-08-25 23:23:14 +00:00
parent c6ec43d659
commit 06dd45bdb1
13 changed files with 280 additions and 971 deletions

View file

@ -15,7 +15,6 @@ extern struct cvar_s *gl_clear;
extern struct cvar_s *gl_conalpha; extern struct cvar_s *gl_conalpha;
extern struct cvar_s *gl_conspin; extern struct cvar_s *gl_conspin;
extern struct cvar_s *gl_constretch; extern struct cvar_s *gl_constretch;
extern struct cvar_s *gl_dlight_lightmap;
extern struct cvar_s *gl_dlight_polyblend; extern struct cvar_s *gl_dlight_polyblend;
extern struct cvar_s *gl_dlight_smooth; extern struct cvar_s *gl_dlight_smooth;
extern struct cvar_s *gl_fb_bmodels; extern struct cvar_s *gl_fb_bmodels;
@ -25,7 +24,6 @@ extern struct cvar_s *gl_keeptjunctions;
extern struct cvar_s *gl_lerp_anim; extern struct cvar_s *gl_lerp_anim;
extern struct cvar_s *gl_libgl; extern struct cvar_s *gl_libgl;
extern struct cvar_s *gl_lightmap_align; extern struct cvar_s *gl_lightmap_align;
extern struct cvar_s *gl_lightmap_components;
extern struct cvar_s *gl_lightmap_subimage; extern struct cvar_s *gl_lightmap_subimage;
extern struct cvar_s *gl_max_size; extern struct cvar_s *gl_max_size;
extern struct cvar_s *gl_multitexture; extern struct cvar_s *gl_multitexture;
@ -47,6 +45,7 @@ extern struct cvar_s *r_aliastransadj;
extern struct cvar_s *r_aliastransbase; extern struct cvar_s *r_aliastransbase;
extern struct cvar_s *r_ambient; extern struct cvar_s *r_ambient;
extern struct cvar_s *r_clearcolor; extern struct cvar_s *r_clearcolor;
extern struct cvar_s *r_dlight_lightmap;
extern struct cvar_s *r_drawentities; extern struct cvar_s *r_drawentities;
extern struct cvar_s *r_drawflat; extern struct cvar_s *r_drawflat;
extern struct cvar_s *r_draworder; extern struct cvar_s *r_draworder;
@ -57,6 +56,7 @@ extern struct cvar_s *r_firecolor;
extern struct cvar_s *r_fullbright; extern struct cvar_s *r_fullbright;
extern struct cvar_s *r_graphheight; extern struct cvar_s *r_graphheight;
extern struct cvar_s *r_lightmap; extern struct cvar_s *r_lightmap;
extern struct cvar_s *r_lightmap_components;
extern struct cvar_s *r_maxedges; extern struct cvar_s *r_maxedges;
extern struct cvar_s *r_maxsurfs; extern struct cvar_s *r_maxsurfs;
extern struct cvar_s *r_mirroralpha; extern struct cvar_s *r_mirroralpha;

View file

@ -21,7 +21,8 @@ endif
lib_LTLIBRARIES = $(RENDERER_GL) $(RENDERER_SW) $(RENDERER_SW32) lib_LTLIBRARIES = $(RENDERER_GL) $(RENDERER_SW) $(RENDERER_SW32)
common_SOURCES = r_cvar.c r_efrag.c r_ent.c r_graph.c r_main.c r_part.c common_SOURCES = r_cvar.c r_efrag.c r_ent.c r_graph.c r_light.c r_main.c \
r_part.c
libQFrenderer_gl_la_LDFLAGS = -version-info 1:0:0 libQFrenderer_gl_la_LDFLAGS = -version-info 1:0:0
libQFrenderer_gl_la_LIBADD = gl/libgl.la libQFrenderer_gl_la_LIBADD = gl/libgl.la

View file

@ -10,7 +10,7 @@ endif
noinst_LTLIBRARIES = $(GL) noinst_LTLIBRARIES = $(GL)
libgl_la_LDFLAGS = -version-info 1:0:0 libgl_la_LDFLAGS = -version-info 1:0:0
libgl_la_SOURCES = gl_draw.c gl_dyn_fires.c gl_dyn_part.c gl_dyn_textures.c \ libgl_la_SOURCES = gl_draw.c gl_dyn_fires.c gl_dyn_part.c gl_dyn_lights.c \
gl_graph.c gl_rlight.c gl_rmain.c gl_rmisc.c gl_rsurf.c gl_screen.c \ gl_dyn_textures.c gl_graph.c gl_rmain.c gl_rmisc.c gl_rsurf.c \
gl_skin.c gl_sky.c gl_sky_clip.c gl_textures.c gl_warp.c gl_funcs.c \ gl_screen.c gl_skin.c gl_sky.c gl_sky_clip.c gl_textures.c gl_warp.c \
noisetextures.c gl_funcs.c noisetextures.c

View file

@ -59,10 +59,12 @@
#include "sbar.h" #include "sbar.h"
extern byte *vid_basepal; extern byte *vid_basepal;
extern cvar_t *crosshair, *cl_crossx, *cl_crossy, *crosshaircolor, extern cvar_t *crosshair, *cl_crossx, *cl_crossy, *crosshaircolor,
*gl_lightmap_components; *r_lightmap_components;
byte *draw_chars; // 8*8 graphic characters byte *draw_chars; // 8*8 graphic characters
qpic_t *draw_backtile; qpic_t *draw_backtile;
static int translate_texture; static int translate_texture;
@ -109,7 +111,8 @@ Draw_PicFromWad (const char *name)
p = W_GetLumpName (name); p = W_GetLumpName (name);
gl = (glpic_t *) p->data; gl = (glpic_t *) p->data;
gl->texnum = GL_LoadTexture (name, p->width, p->height, p->data, false, true, 1); gl->texnum = GL_LoadTexture (name, p->width, p->height, p->data, false,
true, 1);
return p; return p;
} }

View file

@ -0,0 +1,156 @@
/*
gl_dyn_lights.c
polyblended dynamic lights
Copyright (C) 1996-1997 Id Software, Inc.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to:
Free Software Foundation, Inc.
59 Temple Place - Suite 330
Boston, MA 02111-1307, USA
$Id$
*/
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#ifdef HAVE_STRING_H
# include <string.h>
#endif
#ifdef HAVE_STRINGS_H
# include <strings.h>
#endif
#include <math.h>
#include <stdio.h>
#include "QF/cvar.h"
#include "QF/render.h"
#include "QF/GL/defines.h"
#include "QF/GL/funcs.h"
#include "r_cvar.h"
#include "r_local.h"
#include "r_shared.h"
float bubble_sintable[33], bubble_costable[33];
extern float v_blend[4];
void
AddLightBlend (float r, float g, float b, float a2)
{
float a;
v_blend[3] = a = v_blend[3] + a2 * (1 - v_blend[3]);
a2 = a2 / a;
v_blend[0] = v_blend[0] * (1 - a2) + r * a2;
v_blend[1] = v_blend[1] * (1 - a2) + g * a2;
v_blend[2] = v_blend[2] * (1 - a2) + b * a2;
}
void
R_InitBubble ()
{
int i;
float a;
float *bub_sin, *bub_cos;
bub_sin = bubble_sintable;
bub_cos = bubble_costable;
for (i = 32; i >= 0; i--) {
a = i / 32.0 * M_PI * 2;
*bub_sin++ = sin (a);
*bub_cos++ = cos (a);
}
}
void
R_RenderDlight (dlight_t *light)
{
int i, j;
vec3_t v;
float rad;
float *bub_sin, *bub_cos;
bub_sin = bubble_sintable;
bub_cos = bubble_costable;
rad = light->radius * 0.35;
VectorSubtract (light->origin, r_origin, v);
if (Length (v) < rad) { // view is inside the dlight
return;
}
qfglBegin (GL_TRIANGLE_FAN);
qfglColor3fv (light->color);
VectorSubtract (r_origin, light->origin, v);
VectorNormalize (v);
for (i = 0; i < 3; i++)
v[i] = light->origin[i] + v[i] * rad;
qfglVertex3fv (v);
qfglColor3f (0, 0, 0);
for (i = 16; i >= 0; i--) {
for (j = 0; j < 3; j++)
v[j] = light->origin[j] + (vright[j] * (*bub_cos) +
vup[j] * (*bub_sin)) * rad;
bub_sin += 2;
bub_cos += 2;
qfglVertex3fv (v);
}
qfglEnd ();
}
void
R_RenderDlights (void)
{
int i;
dlight_t *l;
if (!gl_dlight_polyblend->int_val)
return;
qfglDepthMask (GL_FALSE);
qfglDisable (GL_TEXTURE_2D);
qfglBlendFunc (GL_ONE, GL_ONE);
qfglShadeModel (GL_SMOOTH);
l = r_dlights;
for (i = 0; i < MAX_DLIGHTS; i++, l++) {
if (l->die < r_realtime || !l->radius)
continue;
R_RenderDlight (l);
}
if (!gl_dlight_smooth->int_val)
qfglShadeModel (GL_FLAT);
qfglColor3ubv (lighthalf_v);
qfglEnable (GL_TEXTURE_2D);
qfglBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
qfglDepthMask (GL_TRUE);
}

View file

@ -222,7 +222,6 @@ R_ParticleExplosion (vec3_t org)
{ {
if (!r_particles->int_val) if (!r_particles->int_val)
return; return;
particle_new_random (pt_smokecloud, part_tex_smoke[rand () & 7], org, 4, particle_new_random (pt_smokecloud, part_tex_smoke[rand () & 7], org, 4,
30, 8, r_realtime + 5, (rand () & 7) + 8, 30, 8, r_realtime + 5, (rand () & 7) + 8,
128 + (rand () & 63)); 128 + (rand () & 63));
@ -275,9 +274,9 @@ R_RunSparkEffect (vec3_t org, int count, int ofuzz)
(ofuzz / 8) * .75, vec3_origin, r_realtime + 99, (ofuzz / 8) * .75, vec3_origin, r_realtime + 99,
12 + (rand () & 3), 96, vec3_origin, vec3_origin); 12 + (rand () & 3), 96, vec3_origin, vec3_origin);
while (count--) while (count--)
particle_new_random (pt_fallfadespark, part_tex_spark, org, ofuzz * .75, particle_new_random (pt_fallfadespark, part_tex_spark, org,
1, 96, r_realtime + 5, ramp[rand () % 6], ofuzz * .75, 1, 96, r_realtime + 5,
lhrandom (0, 255)); ramp[rand () % 6], lhrandom (0, 255));
} }
static void static void
@ -532,7 +531,6 @@ R_RocketTrail (int type, entity_t *ent)
} }
break; break;
case 6: // voor trail case 6: // voor trail
// Use smoke ring effects here, once merged with nq? --Despair
dist = 3; dist = 3;
pcolor = 9 * 16 + 8 + (rand () & 3); pcolor = 9 * 16 + 8 + (rand () & 3);
ptype = pt_static; ptype = pt_static;
@ -680,13 +678,13 @@ R_DrawParticles (void)
if ((part->alpha -= r_frametime * 90) < 1) if ((part->alpha -= r_frametime * 90) < 1)
part->die = -1; part->die = -1;
part->scale += r_frametime * 6; part->scale += r_frametime * 6;
// part->org[2] += r_frametime * 30; // part->org[2] += r_frametime * 30 - grav;
break; break;
case pt_smokering: case pt_smokering:
if ((part->alpha -= r_frametime * 130) < 1) if ((part->alpha -= r_frametime * 130) < 1)
part->die = -1; part->die = -1;
part->scale += r_frametime * 10; part->scale += r_frametime * 10;
// part->org[2] += r_frametime * 30; // part->org[2] += r_frametime * 30 - grav;
break; break;
case pt_smokecloud: case pt_smokecloud:
if ((part->alpha -= r_frametime * 128) < 1) if ((part->alpha -= r_frametime * 128) < 1)

View file

@ -1,532 +0,0 @@
/*
gl_rlight.c
@description@
Copyright (C) 1996-1997 Id Software, Inc.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to:
Free Software Foundation, Inc.
59 Temple Place - Suite 330
Boston, MA 02111-1307, USA
$Id$
*/
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#ifdef HAVE_STRING_H
# include <string.h>
#endif
#ifdef HAVE_STRINGS_H
# include <strings.h>
#endif
#include <math.h>
#include <stdio.h>
#include "QF/cvar.h"
#include "QF/render.h"
#include "QF/GL/defines.h"
#include "QF/GL/funcs.h"
#include "r_cvar.h"
#include "r_local.h"
#include "r_shared.h"
extern float v_blend[4];
void
R_AnimateLight (void)
{
int i, j, k;
// light animations
// 'm' is normal light, 'a' is no light, 'z' is double bright
i = (int) (r_realtime * 10);
for (j = 0; j < MAX_LIGHTSTYLES; j++) {
if (!r_lightstyle[j].length) {
d_lightstylevalue[j] = 256;
continue;
}
k = i % r_lightstyle[j].length;
k = r_lightstyle[j].map[k] - 'a';
k = k * 22;
d_lightstylevalue[j] = k;
}
}
/*
DYNAMIC LIGHTS BLEND RENDERING
*/
void
AddLightBlend (float r, float g, float b, float a2)
{
float a;
v_blend[3] = a = v_blend[3] + a2 * (1 - v_blend[3]);
a2 = a2 / a;
v_blend[0] = v_blend[0] * (1 - a2) + r * a2;
v_blend[1] = v_blend[1] * (1 - a2) + g * a2;
v_blend[2] = v_blend[2] * (1 - a2) + b * a2;
}
float bubble_sintable[33], bubble_costable[33];
void
R_InitBubble ()
{
int i;
float a;
float *bub_sin, *bub_cos;
bub_sin = bubble_sintable;
bub_cos = bubble_costable;
for (i = 32; i >= 0; i--) {
a = i / 32.0 * M_PI * 2;
*bub_sin++ = sin (a);
*bub_cos++ = cos (a);
}
}
void
R_RenderDlight (dlight_t *light)
{
int i, j;
vec3_t v;
float rad;
float *bub_sin, *bub_cos;
bub_sin = bubble_sintable;
bub_cos = bubble_costable;
rad = light->radius * 0.35;
VectorSubtract (light->origin, r_origin, v);
if (Length (v) < rad) { // view is inside the dlight
return;
}
qfglBegin (GL_TRIANGLE_FAN);
qfglColor3fv (light->color);
VectorSubtract (r_origin, light->origin, v);
VectorNormalize (v);
for (i = 0; i < 3; i++)
v[i] = light->origin[i] + v[i] * rad;
qfglVertex3fv (v);
qfglColor3f (0, 0, 0);
for (i = 16; i >= 0; i--) {
for (j = 0; j < 3; j++)
v[j] = light->origin[j] + (vright[j] * (*bub_cos) +
vup[j] * (*bub_sin)) * rad;
bub_sin += 2;
bub_cos += 2;
qfglVertex3fv (v);
}
qfglEnd ();
}
void
R_RenderDlights (void)
{
int i;
dlight_t *l;
if (!gl_dlight_polyblend->int_val)
return;
qfglDepthMask (GL_FALSE);
qfglDisable (GL_TEXTURE_2D);
qfglBlendFunc (GL_ONE, GL_ONE);
qfglShadeModel (GL_SMOOTH);
l = r_dlights;
for (i = 0; i < MAX_DLIGHTS; i++, l++) {
if (l->die < r_realtime || !l->radius)
continue;
R_RenderDlight (l);
}
if (!gl_dlight_smooth->int_val)
qfglShadeModel (GL_FLAT);
qfglColor3ubv (lighthalf_v);
qfglEnable (GL_TEXTURE_2D);
qfglBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
qfglDepthMask (GL_TRUE);
}
/*
DYNAMIC LIGHTS
*/
// LordHavoc: heavily modified, to eliminate unnecessary texture uploads,
// and support bmodel lighting better
void
R_RecursiveMarkLights (vec3_t lightorigin, dlight_t *light, int bit,
mnode_t *node)
{
mplane_t *splitplane;
float ndist, maxdist;
msurface_t *surf;
int i;
maxdist = light->radius * light->radius;
loc0:
if (node->contents < 0)
return;
splitplane = node->plane;
ndist = DotProduct (lightorigin, splitplane->normal) - splitplane->dist;
if (ndist > light->radius) {
// Save time by not pushing another stack frame.
if (node->children[0]->contents >= 0) {
node = node->children[0];
goto loc0;
}
return;
}
if (ndist < -light->radius) {
// Save time by not pushing another stack frame.
if (node->children[1]->contents >= 0) {
node = node->children[1];
goto loc0;
}
return;
}
// mark the polygons
surf = r_worldentity.model->surfaces + node->firstsurface;
for (i = 0; i < node->numsurfaces; i++, surf++) {
int s, t;
float l, dist, dist2;
vec3_t impact;
dist = ndist;
dist2 = dist * dist;
if (dist2 >= maxdist)
continue;
impact[0] = light->origin[0] - surf->plane->normal[0] * dist;
impact[1] = light->origin[1] - surf->plane->normal[1] * dist;
impact[2] = light->origin[2] - surf->plane->normal[2] * dist;
l = DotProduct (impact, surf->texinfo->vecs[0]) +
surf->texinfo->vecs[0][3] - surf->texturemins[0];
s = l + 0.5;
if (s < 0)
s = 0;
else if (s > surf->extents[0])
s = surf->extents[0];
s = l - s;
l = DotProduct (impact, surf->texinfo->vecs[1]) +
surf->texinfo->vecs[1][3] - surf->texturemins[1];
t = l + 0.5;
if (t < 0)
t = 0;
else if (t > surf->extents[1])
t = surf->extents[1];
t = l - t;
if ((s * s + t * t + dist * dist) < maxdist) {
if (surf->dlightframe != r_framecount) {
surf->dlightframe = r_framecount;
surf->dlightbits = bit;
} else {
surf->dlightbits |= bit;
}
}
}
if (node->children[0]->contents >= 0) {
if (node->children[1]->contents >= 0)
R_RecursiveMarkLights (lightorigin, light, bit, node->children[1]);
node = node->children[0];
goto loc0;
} else if (node->children[1]->contents >= 0) {
node = node->children[1];
goto loc0;
}
}
static void
mark_surfaces (msurface_t *surf, vec3_t lightorigin, dlight_t *light,
int bit)
{
float dist;
#if 1
float dist2, d;
float maxdist = light->radius * light->radius;
vec3_t impact;
#endif
dist = PlaneDiff(lightorigin, surf->plane);
if (surf->flags & SURF_PLANEBACK)
dist = -dist;
if ((dist < -0.25f && !(surf->flags & SURF_LIGHTBOTHSIDES))
|| dist > light->radius)
return;
#if 1
dist2 = dist * dist;
dist = -dist;
VectorMA (light->origin, dist, surf->plane->normal, impact);
d = DotProduct (impact, surf->texinfo->vecs[0])
+ surf->texinfo->vecs[0][3] - surf->texturemins[0];
if (d < 0) {
dist2 += d * d;
if (dist2 >= maxdist)
return;
} else {
d -= surf->extents[0] + 16;
if (d > 0) {
dist2 += d * d;
if (dist2 >= maxdist)
return;
}
}
d = DotProduct (impact, surf->texinfo->vecs[1])
+ surf->texinfo->vecs[1][3] - surf->texturemins[1];
if (d < 0) {
dist2 += d * d;
if (dist2 >= maxdist)
return;
} else {
d -= surf->extents[1] + 16;
if (d > 0) {
dist2 += d * d;
if (dist2 >= maxdist)
return;
}
}
#endif
if (surf->dlightframe != r_framecount) {
surf->dlightbits = 0;
surf->dlightframe = r_framecount;
}
surf->dlightbits |= bit;
}
void
R_MarkLights (vec3_t lightorigin, dlight_t *light, int bit, model_t *model)
{
mleaf_t *pvsleaf = Mod_PointInLeaf (lightorigin, model);
if (!pvsleaf->compressed_vis) {
mnode_t *node = model->nodes + model->hulls[0].firstclipnode;
R_RecursiveMarkLights (lightorigin, light, bit, node);
} else {
float radius = light->radius;
vec3_t mins, maxs;
int leafnum = 0;
byte *in = pvsleaf->compressed_vis;
byte vis_bits;
mins[0] = lightorigin[0] - radius;
mins[1] = lightorigin[1] - radius;
mins[2] = lightorigin[2] - radius;
maxs[0] = lightorigin[0] + radius;
maxs[1] = lightorigin[1] + radius;
maxs[2] = lightorigin[2] + radius;
while (leafnum < model->numleafs) {
int i;
if (!(vis_bits = *in++)) {
leafnum += (*in++) * 8;
continue;
}
for (i = 0; i < 8 && leafnum < model->numleafs; i++, leafnum++) {
int m;
mleaf_t *leaf = &model->leafs[leafnum + 1];
if (!(vis_bits & (1 << i)))
continue;
if (leaf->visframe != r_visframecount)
continue;
if (leaf->mins[0] > maxs[0] || leaf->maxs[0] < mins[0]
|| leaf->mins[1] > maxs[1] || leaf->maxs[1] < mins[1]
|| leaf->mins[2] > maxs[2] || leaf->maxs[2] < mins[2])
continue;
if (leaf->dlightframe != r_framecount) {
leaf->dlightbits = 0;
leaf->dlightframe = r_framecount;
}
leaf->dlightbits |= bit;
for (m = 0; m < leaf->nummarksurfaces; m++) {
msurface_t *surf = leaf->firstmarksurface[m];
if (surf->visframe != r_visframecount)
continue;
mark_surfaces (surf, lightorigin, light, bit);
}
}
}
}
}
void
R_PushDlights (vec3_t entorigin)
{
int i;
dlight_t *l;
vec3_t lightorigin;
if (!gl_dlight_lightmap->int_val)
return;
l = r_dlights;
for (i = 0; i < MAX_DLIGHTS; i++, l++) {
if (l->die < r_realtime || !l->radius)
continue;
VectorSubtract (l->origin, entorigin, lightorigin);
R_MarkLights (lightorigin, l, 1 << i, r_worldentity.model);
}
}
/*
LIGHT SAMPLING
*/
mplane_t *lightplane;
vec3_t lightspot;
int
RecursiveLightPoint (mnode_t *node, vec3_t start, vec3_t end)
{
int r;
float front, back, frac;
int side;
mplane_t *plane;
vec3_t mid;
msurface_t *surf;
int s, t, ds, dt;
int i;
mtexinfo_t *tex;
byte *lightmap;
unsigned int scale;
int maps;
if (node->contents < 0)
return -1; // didn't hit anything
// calculate mid point
// FIXME: optimize for axial
plane = node->plane;
front = DotProduct (start, plane->normal) - plane->dist;
back = DotProduct (end, plane->normal) - plane->dist;
side = front < 0;
if ((back < 0) == side)
return RecursiveLightPoint (node->children[side], start, end);
frac = front / (front - back);
mid[0] = start[0] + (end[0] - start[0]) * frac;
mid[1] = start[1] + (end[1] - start[1]) * frac;
mid[2] = start[2] + (end[2] - start[2]) * frac;
// go down front side
r = RecursiveLightPoint (node->children[side], start, mid);
if (r >= 0)
return r; // hit something
if ((back < 0) == side)
return -1; // didn't hit anything
// check for impact on this node
VectorCopy (mid, lightspot);
lightplane = plane;
surf = r_worldentity.model->surfaces + node->firstsurface;
for (i = 0; i < node->numsurfaces; i++, surf++) {
if (surf->flags & SURF_DRAWTILED)
continue; // no lightmaps
tex = surf->texinfo;
s = DotProduct (mid, tex->vecs[0]) + tex->vecs[0][3];
t = DotProduct (mid, tex->vecs[1]) + tex->vecs[1][3];;
if (s < surf->texturemins[0] || t < surf->texturemins[1])
continue;
ds = s - surf->texturemins[0];
dt = t - surf->texturemins[1];
if (ds > surf->extents[0] || dt > surf->extents[1])
continue;
if (!surf->samples)
return 0;
ds >>= 4;
dt >>= 4;
lightmap = surf->samples;
r = 0;
if (lightmap) {
lightmap += dt * ((surf->extents[0] >> 4) + 1) + ds;
for (maps = 0; maps < MAXLIGHTMAPS && surf->styles[maps] != 255;
maps++) {
scale = d_lightstylevalue[surf->styles[maps]];
r += *lightmap * scale;
lightmap += ((surf->extents[0] >> 4) + 1) *
((surf->extents[1] >> 4) + 1);
}
r >>= 8;
}
return r;
}
// go down back side
return RecursiveLightPoint (node->children[!side], mid, end);
}
int
R_LightPoint (vec3_t p)
{
vec3_t end;
int r;
if (!r_worldentity.model->lightdata)
return 255;
end[0] = p[0];
end[1] = p[1];
end[2] = p[2] - 2048;
r = RecursiveLightPoint (r_worldentity.model->nodes, p, end);
if (r == -1)
r = 0;
return r;
}

View file

@ -130,9 +130,9 @@ R_ForceLightUpdate (void)
} }
/* /*
R_AddDynamicLights R_AddDynamicLights
LordHavoc: completely rewrote this, relies on 64bit integer math... LordHavoc: completely rewrote this, relies on 64bit integer math...
*/ */
void void
R_AddDynamicLights (msurface_t *surf) R_AddDynamicLights (msurface_t *surf)
@ -208,12 +208,12 @@ R_AddDynamicLights (msurface_t *surf)
} }
/* /*
R_BuildLightMap R_BuildLightMap
Combine and scale multiple lightmaps Combine and scale multiple lightmaps.
After talking it over with LordHavoc, I've decided to switch to using After talking it over with LordHavoc, I've decided to switch to using
GL_RGB for colored lights and averaging them out for plain white GL_RGB for colored lights and averaging them out for plain white
lighting if needed. Much cleaner that way. --KB lighting if needed. Much cleaner that way. --KB
*/ */
void void
R_BuildLightMap (msurface_t *surf, byte * dest, int stride) R_BuildLightMap (msurface_t *surf, byte * dest, int stride)
@ -311,9 +311,9 @@ R_BuildLightMap (msurface_t *surf, byte * dest, int stride)
} }
/* /*
R_TextureAnimation R_TextureAnimation
Returns the proper texture for a given time and base texture Returns the proper texture for a given time and base texture
*/ */
texture_t * texture_t *
R_TextureAnimation (texture_t *base) R_TextureAnimation (texture_t *base)
@ -344,7 +344,7 @@ R_TextureAnimation (texture_t *base)
} }
/* /*
BRUSH MODELS BRUSH MODELS
*/ */
extern int solidskytexture; extern int solidskytexture;
@ -699,7 +699,7 @@ R_DrawBrushModel (entity_t *e)
psurf = &clmodel->surfaces[clmodel->firstmodelsurface]; psurf = &clmodel->surfaces[clmodel->firstmodelsurface];
// calculate dynamic lighting for bmodel if it's not an instanced model // calculate dynamic lighting for bmodel if it's not an instanced model
if (clmodel->firstmodelsurface != 0 && gl_dlight_lightmap->int_val) { if (clmodel->firstmodelsurface != 0 && r_dlight_lightmap->int_val) {
vec3_t lightorigin; vec3_t lightorigin;
for (k = 0; k < MAX_DLIGHTS; k++) { for (k = 0; k < MAX_DLIGHTS; k++) {
@ -759,7 +759,7 @@ R_DrawBrushModel (entity_t *e)
} }
/* /*
WORLD MODEL WORLD MODEL
*/ */
void void
@ -1107,9 +1107,9 @@ GL_CreateSurfaceLightmap (msurface_t *surf)
} }
/* /*
GL_BuildLightmaps GL_BuildLightmaps
Builds the lightmap texture with all the surfaces from all brush models Builds the lightmap texture with all the surfaces from all brush models
*/ */
void void
GL_BuildLightmaps (model_t **models, int num_models) GL_BuildLightmaps (model_t **models, int num_models)
@ -1126,7 +1126,7 @@ GL_BuildLightmaps (model_t **models, int num_models)
texture_extension_number += MAX_LIGHTMAPS; texture_extension_number += MAX_LIGHTMAPS;
} }
switch (gl_lightmap_components->int_val) { switch (r_lightmap_components->int_val) {
case 1: case 1:
gl_internalformat = 1; gl_internalformat = 1;
gl_lightmap_format = GL_LUMINANCE; gl_lightmap_format = GL_LUMINANCE;
@ -1156,7 +1156,8 @@ GL_BuildLightmaps (model_t **models, int num_models)
for (i = 0; i < m->numsurfaces; i++) { for (i = 0; i < m->numsurfaces; i++) {
if (m->surfaces[i].flags & SURF_DRAWTURB) if (m->surfaces[i].flags & SURF_DRAWTURB)
continue; continue;
if (gl_sky_divide->int_val && (m->surfaces[i].flags & SURF_DRAWSKY)) if (gl_sky_divide->int_val && (m->surfaces[i].flags &
SURF_DRAWSKY))
continue; continue;
GL_CreateSurfaceLightmap (m->surfaces + i); GL_CreateSurfaceLightmap (m->surfaces + i);
BuildSurfaceDisplayList (m->surfaces + i); BuildSurfaceDisplayList (m->surfaces + i);

View file

@ -55,7 +55,6 @@ cvar_t *gl_clear;
cvar_t *gl_conalpha; cvar_t *gl_conalpha;
cvar_t *gl_conspin; cvar_t *gl_conspin;
cvar_t *gl_constretch; cvar_t *gl_constretch;
cvar_t *gl_dlight_lightmap;
cvar_t *gl_dlight_polyblend; cvar_t *gl_dlight_polyblend;
cvar_t *gl_dlight_smooth; cvar_t *gl_dlight_smooth;
cvar_t *gl_fb_bmodels; cvar_t *gl_fb_bmodels;
@ -65,7 +64,6 @@ cvar_t *gl_keeptjunctions;
cvar_t *gl_lerp_anim; cvar_t *gl_lerp_anim;
cvar_t *gl_libgl; cvar_t *gl_libgl;
cvar_t *gl_lightmap_align; cvar_t *gl_lightmap_align;
cvar_t *gl_lightmap_components;
cvar_t *gl_lightmap_subimage; cvar_t *gl_lightmap_subimage;
cvar_t *gl_max_size; cvar_t *gl_max_size;
cvar_t *gl_nocolors; cvar_t *gl_nocolors;
@ -85,6 +83,7 @@ cvar_t *r_aliastransadj;
cvar_t *r_aliastransbase; cvar_t *r_aliastransbase;
cvar_t *r_ambient; cvar_t *r_ambient;
cvar_t *r_clearcolor; cvar_t *r_clearcolor;
cvar_t *r_dlight_lightmap;
cvar_t *r_drawentities; cvar_t *r_drawentities;
cvar_t *r_drawflat; cvar_t *r_drawflat;
cvar_t *r_drawviewmodel; cvar_t *r_drawviewmodel;
@ -92,6 +91,7 @@ cvar_t *r_dspeeds;
cvar_t *r_dynamic; cvar_t *r_dynamic;
cvar_t *r_firecolor; cvar_t *r_firecolor;
cvar_t *r_graphheight; cvar_t *r_graphheight;
cvar_t *r_lightmap_components;
cvar_t *r_maxedges; cvar_t *r_maxedges;
cvar_t *r_maxsurfs; cvar_t *r_maxsurfs;
cvar_t *r_mirroralpha; cvar_t *r_mirroralpha;
@ -156,9 +156,6 @@ R_Init_Cvars (void)
"speed at which the console spins"); "speed at which the console spins");
gl_constretch = Cvar_Get ("gl_constretch", "0", CVAR_ARCHIVE, NULL, gl_constretch = Cvar_Get ("gl_constretch", "0", CVAR_ARCHIVE, NULL,
"toggle console between slide and stretch"); "toggle console between slide and stretch");
gl_dlight_lightmap = Cvar_Get ("gl_dlight_lightmap", "1", CVAR_ARCHIVE,
NULL, "Set to 1 for high quality dynamic "
"lighting.");
gl_dlight_polyblend = Cvar_Get ("gl_dlight_polyblend", "0", CVAR_ARCHIVE, gl_dlight_polyblend = Cvar_Get ("gl_dlight_polyblend", "0", CVAR_ARCHIVE,
NULL, "Set to 1 to use a dynamic light " NULL, "Set to 1 to use a dynamic light "
"effect faster on GL"); "effect faster on GL");
@ -181,9 +178,6 @@ R_Init_Cvars (void)
"Workaround for nvidia slow path. Set to 4 " "Workaround for nvidia slow path. Set to 4 "
"or 16 if you have an nvidia 3d " "or 16 if you have an nvidia 3d "
"accelerator, set to 1 otherwise."); "accelerator, set to 1 otherwise.");
gl_lightmap_components = Cvar_Get ("gl_lightmap_components", "4", CVAR_ROM,
NULL, "Lightmap texture components. 1 "
"is greyscale, 3 is RGB, 4 is RGBA.");
gl_lightmap_subimage = Cvar_Get ("gl_lightmap_subimage", "1", CVAR_NONE, gl_lightmap_subimage = Cvar_Get ("gl_lightmap_subimage", "1", CVAR_NONE,
NULL, "Lightmap Update method. Default 2 " NULL, "Lightmap Update method. Default 2 "
"updates a minimum 'dirty rectangle' " "updates a minimum 'dirty rectangle' "
@ -234,6 +228,9 @@ R_Init_Cvars (void)
r_clearcolor = Cvar_Get ("r_clearcolor", "2", CVAR_NONE, NULL, r_clearcolor = Cvar_Get ("r_clearcolor", "2", CVAR_NONE, NULL,
"This sets the color for areas outside of the " "This sets the color for areas outside of the "
"current map"); "current map");
r_dlight_lightmap = Cvar_Get ("r_dlight_lightmap", "1", CVAR_ARCHIVE,
NULL, "Set to 1 for high quality dynamic "
"lighting.");
r_drawentities = Cvar_Get ("r_drawentities", "1", CVAR_NONE, NULL, r_drawentities = Cvar_Get ("r_drawentities", "1", CVAR_NONE, NULL,
"Toggles drawing of entities (almost " "Toggles drawing of entities (almost "
"everything but the world)"); "everything but the world)");
@ -250,6 +247,9 @@ R_Init_Cvars (void)
r_graphheight = Cvar_Get ("r_graphheight", "32", CVAR_NONE, NULL, r_graphheight = Cvar_Get ("r_graphheight", "32", CVAR_NONE, NULL,
"Set the number of lines displayed in the " "Set the number of lines displayed in the "
"various graphs"); "various graphs");
r_lightmap_components = Cvar_Get ("r_lightmap_components", "4", CVAR_ROM,
NULL, "Lightmap texture components. 1 "
"is greyscale, 3 is RGB, 4 is RGBA.");
r_maxedges = Cvar_Get ("r_maxedges", "0", CVAR_NONE, NULL, r_maxedges = Cvar_Get ("r_maxedges", "0", CVAR_NONE, NULL,
"Sets the maximum number of edges"); "Sets the maximum number of edges");
r_maxsurfs = Cvar_Get ("r_maxsurfs", "0", CVAR_NONE, NULL, r_maxsurfs = Cvar_Get ("r_maxsurfs", "0", CVAR_NONE, NULL,

View file

@ -1,7 +1,7 @@
/* /*
r_light.c r_light.c
(description) common lightmap code.
Copyright (C) 1996-1997 Id Software, Inc. Copyright (C) 1996-1997 Id Software, Inc.
@ -29,10 +29,22 @@
#ifdef HAVE_CONFIG_H #ifdef HAVE_CONFIG_H
# include "config.h" # include "config.h"
#endif #endif
#ifdef HAVE_STRING_H
# include <string.h>
#endif
#ifdef HAVE_STRINGS_H
# include <strings.h>
#endif
#include <math.h>
#include <stdio.h>
#include "QF/cvar.h"
#include "QF/render.h" #include "QF/render.h"
#include "r_cvar.h"
#include "r_local.h" #include "r_local.h"
#include "r_shared.h"
void void
@ -55,10 +67,8 @@ R_AnimateLight (void)
} }
} }
/* // LordHavoc: heavily modified, to eliminate unnecessary texture uploads,
DYNAMIC LIGHTS // and support bmodel lighting better
*/
void void
R_RecursiveMarkLights (vec3_t lightorigin, dlight_t *light, int bit, R_RecursiveMarkLights (vec3_t lightorigin, dlight_t *light, int bit,
mnode_t *node) mnode_t *node)
@ -69,6 +79,7 @@ R_RecursiveMarkLights (vec3_t lightorigin, dlight_t *light, int bit,
int i; int i;
maxdist = light->radius * light->radius; maxdist = light->radius * light->radius;
loc0: loc0:
if (node->contents < 0) if (node->contents < 0)
return; return;
@ -77,6 +88,7 @@ loc0:
ndist = DotProduct (lightorigin, splitplane->normal) - splitplane->dist; ndist = DotProduct (lightorigin, splitplane->normal) - splitplane->dist;
if (ndist > light->radius) { if (ndist > light->radius) {
// Save time by not pushing another stack frame.
if (node->children[0]->contents >= 0) { if (node->children[0]->contents >= 0) {
node = node->children[0]; node = node->children[0];
goto loc0; goto loc0;
@ -84,20 +96,56 @@ loc0:
return; return;
} }
if (ndist < -light->radius) { if (ndist < -light->radius) {
// Save time by not pushing another stack frame.
if (node->children[1]->contents >= 0) { if (node->children[1]->contents >= 0) {
node = node->children[1]; node = node->children[1];
goto loc0; goto loc0;
} }
return; return;
} }
// mark the polygons // mark the polygons
surf = r_worldentity.model->surfaces + node->firstsurface; surf = r_worldentity.model->surfaces + node->firstsurface;
for (i = 0; i < node->numsurfaces; i++, surf++) { for (i = 0; i < node->numsurfaces; i++, surf++) {
if (surf->dlightframe != r_framecount) { int s, t;
surf->dlightbits = 0; float l, dist, dist2;
surf->dlightframe = r_framecount; vec3_t impact;
dist = ndist;
dist2 = dist * dist;
if (dist2 >= maxdist)
continue;
impact[0] = light->origin[0] - surf->plane->normal[0] * dist;
impact[1] = light->origin[1] - surf->plane->normal[1] * dist;
impact[2] = light->origin[2] - surf->plane->normal[2] * dist;
l = DotProduct (impact, surf->texinfo->vecs[0]) +
surf->texinfo->vecs[0][3] - surf->texturemins[0];
s = l + 0.5;
if (s < 0)
s = 0;
else if (s > surf->extents[0])
s = surf->extents[0];
s = l - s;
l = DotProduct (impact, surf->texinfo->vecs[1]) +
surf->texinfo->vecs[1][3] - surf->texturemins[1];
t = l + 0.5;
if (t < 0)
t = 0;
else if (t > surf->extents[1])
t = surf->extents[1];
t = l - t;
if ((s * s + t * t + dist * dist) < maxdist) {
if (surf->dlightframe != r_framecount) {
surf->dlightframe = r_framecount;
surf->dlightbits = bit;
} else {
surf->dlightbits |= bit;
}
} }
surf->dlightbits |= bit;
} }
if (node->children[0]->contents >= 0) { if (node->children[0]->contents >= 0) {
@ -223,7 +271,6 @@ R_MarkLights (vec3_t lightorigin, dlight_t *light, int bit, model_t *model)
} }
} }
void void
R_PushDlights (vec3_t entorigin) R_PushDlights (vec3_t entorigin)
{ {
@ -231,6 +278,9 @@ R_PushDlights (vec3_t entorigin)
dlight_t *l; dlight_t *l;
vec3_t lightorigin; vec3_t lightorigin;
if (!r_dlight_lightmap->int_val)
return;
l = r_dlights; l = r_dlights;
for (i = 0; i < MAX_DLIGHTS; i++, l++) { for (i = 0; i < MAX_DLIGHTS; i++, l++) {
@ -241,11 +291,12 @@ R_PushDlights (vec3_t entorigin)
} }
} }
/* /*
LIGHT SAMPLING LIGHT SAMPLING
*/ */
mplane_t *lightplane;
vec3_t lightspot;
int int
RecursiveLightPoint (mnode_t *node, vec3_t start, vec3_t end) RecursiveLightPoint (mnode_t *node, vec3_t start, vec3_t end)
@ -266,7 +317,8 @@ RecursiveLightPoint (mnode_t *node, vec3_t start, vec3_t end)
if (node->contents < 0) if (node->contents < 0)
return -1; // didn't hit anything return -1; // didn't hit anything
// calculate mid point // calculate mid point
// FIXME: optimize for axial // FIXME: optimize for axial
plane = node->plane; plane = node->plane;
front = DotProduct (start, plane->normal) - plane->dist; front = DotProduct (start, plane->normal) - plane->dist;
@ -281,7 +333,7 @@ RecursiveLightPoint (mnode_t *node, vec3_t start, vec3_t end)
mid[1] = start[1] + (end[1] - start[1]) * frac; mid[1] = start[1] + (end[1] - start[1]) * frac;
mid[2] = start[2] + (end[2] - start[2]) * frac; mid[2] = start[2] + (end[2] - start[2]) * frac;
// go down front side // go down front side
r = RecursiveLightPoint (node->children[side], start, mid); r = RecursiveLightPoint (node->children[side], start, mid);
if (r >= 0) if (r >= 0)
return r; // hit something return r; // hit something
@ -289,7 +341,10 @@ RecursiveLightPoint (mnode_t *node, vec3_t start, vec3_t end)
if ((back < 0) == side) if ((back < 0) == side)
return -1; // didn't hit anything return -1; // didn't hit anything
// check for impact on this node // check for impact on this node
VectorCopy (mid, lightspot);
lightplane = plane;
surf = r_worldentity.model->surfaces + node->firstsurface; surf = r_worldentity.model->surfaces + node->firstsurface;
for (i = 0; i < node->numsurfaces; i++, surf++) { for (i = 0; i < node->numsurfaces; i++, surf++) {
if (surf->flags & SURF_DRAWTILED) if (surf->flags & SURF_DRAWTILED)
@ -335,11 +390,10 @@ RecursiveLightPoint (mnode_t *node, vec3_t start, vec3_t end)
return r; return r;
} }
// go down back side // go down back side
return RecursiveLightPoint (node->children[!side], mid, end); return RecursiveLightPoint (node->children[!side], mid, end);
} }
int int
R_LightPoint (vec3_t p) R_LightPoint (vec3_t p)
{ {
@ -358,8 +412,5 @@ R_LightPoint (vec3_t p)
if (r == -1) if (r == -1)
r = 0; r = 0;
if (r < r_refdef.ambientlight)
r = r_refdef.ambientlight;
return r; return r;
} }

View file

@ -13,17 +13,14 @@ endif
noinst_LTLIBRARIES = $(SW) $(ASM) noinst_LTLIBRARIES = $(SW) $(ASM)
libasm_la_SOURCES = \ libasm_la_SOURCES = d_draw.S d_draw16.S d_parta.S d_polysa.S d_scana.S \
d_draw.S d_draw16.S d_parta.S d_polysa.S d_scana.S d_spr8.S \ d_spr8.S d_varsa.S surf16.S surf8.S sw_raclipa.S sw_raliasa.S \
d_varsa.S surf16.S surf8.S sw_raclipa.S sw_raliasa.S sw_rdrawa.S \ sw_rdrawa.S sw_redgea.S sw_rvarsa.S transform.S
sw_redgea.S sw_rvarsa.S \
transform.S
libsw_la_LDFLAGS = -version-info 1:0:0 libsw_la_LDFLAGS = -version-info 1:0:0
libsw_la_LIBADD = $(ASM) libsw_la_LIBADD = $(ASM)
libsw_la_SOURCES = d_edge.c d_fill.c d_init.c d_modech.c d_part.c d_polyse.c \ libsw_la_SOURCES = d_edge.c d_fill.c d_init.c d_modech.c d_part.c d_polyse.c \
d_scan.c d_sky.c d_sprite.c d_surf.c d_vars.c d_zpoint.c draw.c \ d_scan.c d_sky.c d_sprite.c d_surf.c d_vars.c d_zpoint.c draw.c \
nonintel.c screen.c \ nonintel.c screen.c sw_graph.c sw_raclip.c sw_ralias.c sw_rbsp.c \
sw_graph.c sw_raclip.c sw_ralias.c sw_rbsp.c sw_rdraw.c sw_redge.c \ sw_rdraw.c sw_redge.c sw_rmain.c sw_rmisc.c sw_rpart.c sw_rsky.c \
sw_rlight.c sw_rmain.c sw_rmisc.c sw_rpart.c sw_rsky.c sw_rsprite.c \ sw_rsprite.c sw_rsurf.c sw_skin.c
sw_rsurf.c sw_skin.c

View file

@ -11,7 +11,6 @@ noinst_LTLIBRARIES = $(SW32)
libsw32_la_LDFLAGS = -version-info 1:0:0 libsw32_la_LDFLAGS = -version-info 1:0:0
libsw32_la_SOURCES = d_edge.c d_fill.c d_init.c d_modech.c d_part.c \ libsw32_la_SOURCES = d_edge.c d_fill.c d_init.c d_modech.c d_part.c \
d_polyse.c d_scan.c d_sky.c d_sprite.c d_surf.c d_vars.c d_zpoint.c \ d_polyse.c d_scan.c d_sky.c d_sprite.c d_surf.c d_vars.c d_zpoint.c \
draw.c screen.c sw32_graph.c sw32_raclip.c sw32_ralias.c \ draw.c screen.c sw32_graph.c sw32_raclip.c sw32_ralias.c sw32_rbsp.c \
sw32_rbsp.c sw32_rdraw.c sw32_redge.c sw32_rlight.c sw32_rmain.c \ sw32_rdraw.c sw32_redge.c sw32_rmain.c sw32_rmisc.c sw32_rpart.c \
sw32_rmisc.c sw32_rpart.c sw32_rsky.c sw32_rsprite.c sw32_rsurf.c \ sw32_rsky.c sw32_rsprite.c sw32_rsurf.c sw32_skin.c
sw32_skin.c

View file

@ -1,365 +0,0 @@
/*
sw32_rlight.c
(description)
Copyright (C) 1996-1997 Id Software, Inc.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to:
Free Software Foundation, Inc.
59 Temple Place - Suite 330
Boston, MA 02111-1307, USA
$Id$
*/
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include "QF/render.h"
#include "r_local.h"
//int r_dlightframecount;
void
R_AnimateLight (void)
{
int i, j, k;
// light animations
// 'm' is normal light, 'a' is no light, 'z' is double bright
i = (int) (r_realtime * 10);
for (j = 0; j < MAX_LIGHTSTYLES; j++) {
if (!r_lightstyle[j].length) {
d_lightstylevalue[j] = 256;
continue;
}
k = i % r_lightstyle[j].length;
k = r_lightstyle[j].map[k] - 'a';
k = k * 22;
d_lightstylevalue[j] = k;
}
}
/*
DYNAMIC LIGHTS
*/
void
R_RecursiveMarkLights (vec3_t lightorigin, dlight_t *light, int bit,
mnode_t *node)
{
mplane_t *splitplane;
float ndist, maxdist;
msurface_t *surf;
int i;
maxdist = light->radius * light->radius;
loc0:
if (node->contents < 0)
return;
splitplane = node->plane;
ndist = DotProduct (lightorigin, splitplane->normal) - splitplane->dist;
if (ndist > light->radius) {
if (node->children[0]->contents >= 0) {
node = node->children[0];
goto loc0;
}
return;
}
if (ndist < -light->radius) {
if (node->children[1]->contents >= 0) {
node = node->children[1];
goto loc0;
}
return;
}
// mark the polygons
surf = r_worldentity.model->surfaces + node->firstsurface;
for (i = 0; i < node->numsurfaces; i++, surf++) {
if (surf->dlightframe != r_framecount) {
surf->dlightbits = 0;
surf->dlightframe = r_framecount;
}
surf->dlightbits |= bit;
}
if (node->children[0]->contents >= 0) {
if (node->children[1]->contents >= 0)
R_RecursiveMarkLights (lightorigin, light, bit, node->children[1]);
node = node->children[0];
goto loc0;
} else if (node->children[1]->contents >= 0) {
node = node->children[1];
goto loc0;
}
}
static void
mark_surfaces (msurface_t *surf, vec3_t lightorigin, dlight_t *light,
int bit)
{
float dist;
#if 1
float dist2, d;
float maxdist = light->radius * light->radius;
vec3_t impact;
#endif
dist = PlaneDiff(lightorigin, surf->plane);
if (surf->flags & SURF_PLANEBACK)
dist = -dist;
if ((dist < -0.25f && !(surf->flags & SURF_LIGHTBOTHSIDES))
|| dist > light->radius)
return;
#if 1
dist2 = dist * dist;
dist = -dist;
VectorMA (light->origin, dist, surf->plane->normal, impact);
d = DotProduct (impact, surf->texinfo->vecs[0])
+ surf->texinfo->vecs[0][3] - surf->texturemins[0];
if (d < 0) {
dist2 += d * d;
if (dist2 >= maxdist)
return;
} else {
d -= surf->extents[0] + 16;
if (d > 0) {
dist2 += d * d;
if (dist2 >= maxdist)
return;
}
}
d = DotProduct (impact, surf->texinfo->vecs[1])
+ surf->texinfo->vecs[1][3] - surf->texturemins[1];
if (d < 0) {
dist2 += d * d;
if (dist2 >= maxdist)
return;
} else {
d -= surf->extents[1] + 16;
if (d > 0) {
dist2 += d * d;
if (dist2 >= maxdist)
return;
}
}
#endif
if (surf->dlightframe != r_framecount) {
surf->dlightbits = 0;
surf->dlightframe = r_framecount;
}
surf->dlightbits |= bit;
}
void
R_MarkLights (vec3_t lightorigin, dlight_t *light, int bit, model_t *model)
{
mleaf_t *pvsleaf = Mod_PointInLeaf (lightorigin, model);
if (!pvsleaf->compressed_vis) {
mnode_t *node = model->nodes + model->hulls[0].firstclipnode;
R_RecursiveMarkLights (lightorigin, light, bit, node);
} else {
float radius = light->radius;
vec3_t mins, maxs;
int leafnum = 0;
byte *in = pvsleaf->compressed_vis;
byte vis_bits;
mins[0] = lightorigin[0] - radius;
mins[1] = lightorigin[1] - radius;
mins[2] = lightorigin[2] - radius;
maxs[0] = lightorigin[0] + radius;
maxs[1] = lightorigin[1] + radius;
maxs[2] = lightorigin[2] + radius;
while (leafnum < model->numleafs) {
int i;
if (!(vis_bits = *in++)) {
leafnum += (*in++) * 8;
continue;
}
for (i = 0; i < 8 && leafnum < model->numleafs; i++, leafnum++) {
int m;
mleaf_t *leaf = &model->leafs[leafnum + 1];
if (!(vis_bits & (1 << i)))
continue;
if (leaf->visframe != r_visframecount)
continue;
if (leaf->mins[0] > maxs[0] || leaf->maxs[0] < mins[0]
|| leaf->mins[1] > maxs[1] || leaf->maxs[1] < mins[1]
|| leaf->mins[2] > maxs[2] || leaf->maxs[2] < mins[2])
continue;
if (leaf->dlightframe != r_framecount) {
leaf->dlightbits = 0;
leaf->dlightframe = r_framecount;
}
leaf->dlightbits |= bit;
for (m = 0; m < leaf->nummarksurfaces; m++) {
msurface_t *surf = leaf->firstmarksurface[m];
if (surf->visframe != r_visframecount)
continue;
mark_surfaces (surf, lightorigin, light, bit);
}
}
}
}
}
void
R_PushDlights (vec3_t entorigin)
{
int i;
dlight_t *l;
vec3_t lightorigin;
l = r_dlights;
for (i = 0; i < MAX_DLIGHTS; i++, l++) {
if (l->die < r_realtime || !l->radius)
continue;
VectorSubtract (l->origin, entorigin, lightorigin);
R_MarkLights (lightorigin, l, 1 << i, r_worldentity.model);
}
}
/*
LIGHT SAMPLING
*/
int
RecursiveLightPoint (mnode_t *node, vec3_t start, vec3_t end)
{
int r;
float front, back, frac;
int side;
mplane_t *plane;
vec3_t mid;
msurface_t *surf;
int s, t, ds, dt;
int i;
mtexinfo_t *tex;
byte *lightmap;
unsigned int scale;
int maps;
if (node->contents < 0)
return -1; // didn't hit anything
// calculate mid point
// FIXME: optimize for axial
plane = node->plane;
front = DotProduct (start, plane->normal) - plane->dist;
back = DotProduct (end, plane->normal) - plane->dist;
side = front < 0;
if ((back < 0) == side)
return RecursiveLightPoint (node->children[side], start, end);
frac = front / (front - back);
mid[0] = start[0] + (end[0] - start[0]) * frac;
mid[1] = start[1] + (end[1] - start[1]) * frac;
mid[2] = start[2] + (end[2] - start[2]) * frac;
// go down front side
r = RecursiveLightPoint (node->children[side], start, mid);
if (r >= 0)
return r; // hit something
if ((back < 0) == side)
return -1; // didn't hit anything
// check for impact on this node
surf = r_worldentity.model->surfaces + node->firstsurface;
for (i = 0; i < node->numsurfaces; i++, surf++) {
if (surf->flags & SURF_DRAWTILED)
continue; // no lightmaps
tex = surf->texinfo;
s = DotProduct (mid, tex->vecs[0]) + tex->vecs[0][3];
t = DotProduct (mid, tex->vecs[1]) + tex->vecs[1][3];;
if (s < surf->texturemins[0] || t < surf->texturemins[1])
continue;
ds = s - surf->texturemins[0];
dt = t - surf->texturemins[1];
if (ds > surf->extents[0] || dt > surf->extents[1])
continue;
if (!surf->samples)
return 0;
ds >>= 4;
dt >>= 4;
lightmap = surf->samples;
r = 0;
if (lightmap) {
lightmap += dt * ((surf->extents[0] >> 4) + 1) + ds;
for (maps = 0; maps < MAXLIGHTMAPS && surf->styles[maps] != 255;
maps++) {
scale = d_lightstylevalue[surf->styles[maps]];
r += *lightmap * scale;
lightmap += ((surf->extents[0] >> 4) + 1) *
((surf->extents[1] >> 4) + 1);
}
r >>= 8;
}
return r;
}
// go down back side
return RecursiveLightPoint (node->children[!side], mid, end);
}
int
R_LightPoint (vec3_t p)
{
vec3_t end;
int r;
if (!r_worldentity.model->lightdata)
return 255;
end[0] = p[0];
end[1] = p[1];
end[2] = p[2] - 2048;
r = RecursiveLightPoint (r_worldentity.model->nodes, p, end);
if (r == -1)
r = 0;
if (r < r_refdef.ambientlight)
r = r_refdef.ambientlight;
return r;
}