2011-05-09 22:00:00 +02:00
|
|
|
/*
|
|
|
|
gl_rlight.c - dynamic and static lights
|
|
|
|
Copyright (C) 2010 Uncle Mike
|
|
|
|
|
|
|
|
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 3 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.
|
|
|
|
*/
|
2010-12-02 22:00:00 +01:00
|
|
|
|
|
|
|
#include "common.h"
|
|
|
|
#include "client.h"
|
2010-12-22 22:00:00 +01:00
|
|
|
#include "mathlib.h"
|
2010-12-02 22:00:00 +01:00
|
|
|
#include "gl_local.h"
|
2010-12-25 22:00:00 +01:00
|
|
|
#include "pm_local.h"
|
2010-12-16 22:00:00 +01:00
|
|
|
#include "studio.h"
|
2010-12-02 22:00:00 +01:00
|
|
|
|
2010-12-06 22:00:00 +01:00
|
|
|
/*
|
|
|
|
=============================================================================
|
|
|
|
|
|
|
|
DYNAMIC LIGHTS
|
|
|
|
|
|
|
|
=============================================================================
|
|
|
|
*/
|
2010-12-11 22:00:00 +01:00
|
|
|
/*
|
|
|
|
==================
|
|
|
|
R_AnimateLight
|
|
|
|
|
|
|
|
==================
|
|
|
|
*/
|
|
|
|
void R_AnimateLight( void )
|
|
|
|
{
|
|
|
|
int i, k, flight, clight;
|
2010-12-16 22:00:00 +01:00
|
|
|
float l, c, lerpfrac, backlerp;
|
2011-04-12 22:00:00 +02:00
|
|
|
float scale;
|
2010-12-11 22:00:00 +01:00
|
|
|
lightstyle_t *ls;
|
|
|
|
|
2010-12-22 22:00:00 +01:00
|
|
|
if( !RI.drawWorld || !cl.worldmodel )
|
|
|
|
return;
|
|
|
|
|
2011-04-12 22:00:00 +02:00
|
|
|
scale = r_lighting_modulate->value;
|
|
|
|
|
2010-12-11 22:00:00 +01:00
|
|
|
// light animations
|
|
|
|
// 'm' is normal light, 'a' is no light, 'z' is double bright
|
|
|
|
flight = (int)floor( cl.time * 10 );
|
|
|
|
clight = (int)ceil( cl.time * 10 );
|
|
|
|
lerpfrac = ( cl.time * 10 ) - flight;
|
|
|
|
backlerp = 1.0f - lerpfrac;
|
|
|
|
|
|
|
|
for( i = 0, ls = cl.lightstyles; i < MAX_LIGHTSTYLES; i++, ls++ )
|
|
|
|
{
|
|
|
|
if( r_fullbright->integer || !cl.worldmodel->lightdata )
|
|
|
|
{
|
|
|
|
RI.lightstylevalue[i] = 256 * 256;
|
2011-04-12 22:00:00 +02:00
|
|
|
RI.lightcache[i] = 3.0f;
|
2010-12-11 22:00:00 +01:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
if( !ls->length )
|
|
|
|
{
|
2011-04-12 22:00:00 +02:00
|
|
|
RI.lightstylevalue[i] = 256 * scale;
|
|
|
|
RI.lightcache[i] = 3.0f * scale;
|
2010-12-11 22:00:00 +01:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
else if( ls->length == 1 )
|
|
|
|
{
|
|
|
|
// single length style so don't bother interpolating
|
2011-04-12 22:00:00 +02:00
|
|
|
RI.lightstylevalue[i] = ls->map[0] * 22 * scale;
|
|
|
|
RI.lightcache[i] = ( ls->map[0] / 12.0f ) * 3.0f * scale;
|
2010-12-11 22:00:00 +01:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
else if( !ls->interp || !cl_lightstyle_lerping->integer )
|
|
|
|
{
|
2011-04-12 22:00:00 +02:00
|
|
|
RI.lightstylevalue[i] = ls->map[flight%ls->length] * 22 * scale;
|
|
|
|
RI.lightcache[i] = ( ls->map[flight%ls->length] / 12.0f ) * 3.0f * scale;
|
2010-12-11 22:00:00 +01:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
// interpolate animating light
|
|
|
|
// frame just gone
|
|
|
|
k = ls->map[flight % ls->length];
|
2011-04-12 22:00:00 +02:00
|
|
|
l = (float)( k * 22.0f ) * backlerp;
|
|
|
|
c = (float)( k / 12.0f ) * backlerp;
|
2010-12-11 22:00:00 +01:00
|
|
|
|
|
|
|
// upcoming frame
|
|
|
|
k = ls->map[clight % ls->length];
|
2011-04-12 22:00:00 +02:00
|
|
|
l += (float)( k * 22.0f ) * lerpfrac;
|
|
|
|
c += (float)( k / 12.0f ) * lerpfrac;
|
2010-12-11 22:00:00 +01:00
|
|
|
|
2011-04-12 22:00:00 +02:00
|
|
|
RI.lightstylevalue[i] = (int)l * scale;
|
|
|
|
RI.lightcache[i] = c * 3.0f * scale;
|
2010-12-11 22:00:00 +01:00
|
|
|
}
|
|
|
|
}
|
2010-12-06 22:00:00 +01:00
|
|
|
|
|
|
|
/*
|
|
|
|
=============
|
|
|
|
R_MarkLights
|
|
|
|
=============
|
|
|
|
*/
|
|
|
|
void R_MarkLights( dlight_t *light, int bit, mnode_t *node )
|
2010-12-02 22:00:00 +01:00
|
|
|
{
|
2010-12-06 22:00:00 +01:00
|
|
|
float dist;
|
|
|
|
msurface_t *surf;
|
|
|
|
int i;
|
|
|
|
|
|
|
|
if( node->contents < 0 )
|
|
|
|
return;
|
|
|
|
|
2010-12-11 22:00:00 +01:00
|
|
|
dist = PlaneDiff( light->origin, node->plane );
|
|
|
|
|
2010-12-06 22:00:00 +01:00
|
|
|
if( dist > light->radius )
|
|
|
|
{
|
|
|
|
R_MarkLights( light, bit, node->children[0] );
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if( dist < -light->radius )
|
|
|
|
{
|
|
|
|
R_MarkLights( light, bit, node->children[1] );
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// mark the polygons
|
2011-07-07 22:00:00 +02:00
|
|
|
surf = RI.currentmodel->surfaces + node->firstsurface;
|
2010-12-06 22:00:00 +01:00
|
|
|
|
|
|
|
for( i = 0; i < node->numsurfaces; i++, surf++ )
|
|
|
|
{
|
2011-07-07 22:00:00 +02:00
|
|
|
mextrasurf_t *info = SURF_INFO( surf, RI.currentmodel );
|
2011-04-12 22:00:00 +02:00
|
|
|
|
|
|
|
if( !BoundsAndSphereIntersect( info->mins, info->maxs, light->origin, light->radius ))
|
|
|
|
continue; // no intersection
|
|
|
|
|
2010-12-06 22:00:00 +01:00
|
|
|
if( surf->dlightframe != tr.dlightframecount )
|
|
|
|
{
|
|
|
|
surf->dlightbits = 0;
|
|
|
|
surf->dlightframe = tr.dlightframecount;
|
|
|
|
}
|
|
|
|
surf->dlightbits |= bit;
|
|
|
|
}
|
|
|
|
|
|
|
|
R_MarkLights( light, bit, node->children[0] );
|
|
|
|
R_MarkLights( light, bit, node->children[1] );
|
2010-12-02 22:00:00 +01:00
|
|
|
}
|
|
|
|
|
2010-12-06 22:00:00 +01:00
|
|
|
/*
|
|
|
|
=============
|
|
|
|
R_PushDlights
|
|
|
|
=============
|
|
|
|
*/
|
|
|
|
void R_PushDlights( void )
|
|
|
|
{
|
|
|
|
dlight_t *l;
|
|
|
|
int i;
|
|
|
|
|
2011-08-14 22:00:00 +02:00
|
|
|
tr.dlightframecount = tr.framecount;
|
2010-12-06 22:00:00 +01:00
|
|
|
l = cl_dlights;
|
|
|
|
|
2011-07-07 22:00:00 +02:00
|
|
|
RI.currententity = clgame.entities;
|
|
|
|
RI.currentmodel = RI.currententity->model;
|
|
|
|
|
2010-12-06 22:00:00 +01:00
|
|
|
for( i = 0; i < MAX_DLIGHTS; i++, l++ )
|
|
|
|
{
|
|
|
|
if( l->die < cl.time || !l->radius )
|
|
|
|
continue;
|
2011-04-12 22:00:00 +02:00
|
|
|
|
|
|
|
if( R_CullSphere( l->origin, l->radius, 15 ))
|
|
|
|
continue;
|
|
|
|
|
2011-07-07 22:00:00 +02:00
|
|
|
R_MarkLights( l, 1<<i, RI.currentmodel->nodes );
|
2010-12-06 22:00:00 +01:00
|
|
|
}
|
|
|
|
}
|
2010-12-16 22:00:00 +01:00
|
|
|
|
2011-11-02 21:00:00 +01:00
|
|
|
/*
|
|
|
|
=============
|
|
|
|
R_CountDlights
|
|
|
|
=============
|
|
|
|
*/
|
|
|
|
int R_CountDlights( void )
|
|
|
|
{
|
|
|
|
dlight_t *l;
|
|
|
|
int i, numDlights = 0;
|
|
|
|
|
|
|
|
for( i = 0, l = cl_dlights; i < MAX_DLIGHTS; i++, l++ )
|
|
|
|
{
|
|
|
|
if( l->die < cl.time || !l->radius )
|
|
|
|
continue;
|
|
|
|
|
|
|
|
numDlights++;
|
|
|
|
}
|
|
|
|
|
|
|
|
return numDlights;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
=============
|
|
|
|
R_CountSurfaceDlights
|
|
|
|
=============
|
|
|
|
*/
|
|
|
|
int R_CountSurfaceDlights( msurface_t *surf )
|
|
|
|
{
|
|
|
|
dlight_t *l;
|
|
|
|
int i, numDlights = 0;
|
|
|
|
|
|
|
|
for( i = 0, l = cl_dlights; i < MAX_DLIGHTS; i++, l++ )
|
|
|
|
{
|
|
|
|
if(!( surf->dlightbits & BIT( i )))
|
|
|
|
continue; // not lit by this light
|
|
|
|
|
|
|
|
numDlights++;
|
|
|
|
}
|
|
|
|
|
|
|
|
return numDlights;
|
|
|
|
}
|
|
|
|
|
2010-12-16 22:00:00 +01:00
|
|
|
/*
|
|
|
|
=======================================================================
|
|
|
|
|
2011-03-03 22:00:00 +01:00
|
|
|
AMBIENT LIGHTING
|
2010-12-16 22:00:00 +01:00
|
|
|
|
|
|
|
=======================================================================
|
|
|
|
*/
|
|
|
|
static uint r_pointColor[3];
|
2011-08-14 22:00:00 +02:00
|
|
|
static vec3_t r_lightSpot;
|
2010-12-16 22:00:00 +01:00
|
|
|
|
|
|
|
/*
|
|
|
|
=================
|
|
|
|
R_RecursiveLightPoint
|
|
|
|
=================
|
|
|
|
*/
|
|
|
|
static qboolean R_RecursiveLightPoint( model_t *model, mnode_t *node, const vec3_t start, const vec3_t end )
|
|
|
|
{
|
|
|
|
float front, back, frac;
|
|
|
|
int i, map, side, size, s, t;
|
|
|
|
msurface_t *surf;
|
|
|
|
mtexinfo_t *tex;
|
|
|
|
color24 *lm;
|
|
|
|
vec3_t mid;
|
|
|
|
|
|
|
|
// didn't hit anything
|
2011-03-31 22:00:00 +02:00
|
|
|
if( !node || node->contents < 0 )
|
2010-12-16 22:00:00 +01:00
|
|
|
return false;
|
|
|
|
|
|
|
|
// calculate mid point
|
|
|
|
front = PlaneDiff( start, node->plane );
|
|
|
|
back = PlaneDiff( end, node->plane );
|
|
|
|
|
|
|
|
side = front < 0;
|
|
|
|
if(( back < 0 ) == side )
|
|
|
|
return R_RecursiveLightPoint( model, node->children[side], start, end );
|
|
|
|
|
|
|
|
frac = front / ( front - back );
|
|
|
|
|
|
|
|
VectorLerp( start, frac, end, mid );
|
|
|
|
|
|
|
|
// co down front side
|
|
|
|
if( R_RecursiveLightPoint( model, node->children[side], start, mid ))
|
|
|
|
return true; // hit something
|
|
|
|
|
|
|
|
if(( back < 0 ) == side )
|
|
|
|
return false;// didn't hit anything
|
|
|
|
|
2011-08-14 22:00:00 +02:00
|
|
|
VectorCopy( mid, r_lightSpot );
|
|
|
|
|
2010-12-16 22:00:00 +01:00
|
|
|
// check for impact on this node
|
|
|
|
surf = model->surfaces + node->firstsurface;
|
|
|
|
|
|
|
|
for( i = 0; i < node->numsurfaces; i++, surf++ )
|
|
|
|
{
|
|
|
|
tex = surf->texinfo;
|
|
|
|
|
2010-12-25 22:00:00 +01:00
|
|
|
if( surf->flags & ( SURF_DRAWSKY|SURF_DRAWTURB ))
|
2010-12-16 22:00:00 +01:00
|
|
|
continue; // no lightmaps
|
|
|
|
|
|
|
|
s = DotProduct( mid, tex->vecs[0] ) + tex->vecs[0][3] - surf->texturemins[0];
|
|
|
|
t = DotProduct( mid, tex->vecs[1] ) + tex->vecs[1][3] - surf->texturemins[1];
|
|
|
|
|
|
|
|
if(( s < 0 || s > surf->extents[0] ) || ( t < 0 || t > surf->extents[1] ))
|
|
|
|
continue;
|
|
|
|
|
|
|
|
s >>= 4;
|
|
|
|
t >>= 4;
|
|
|
|
|
|
|
|
if( !surf->samples )
|
|
|
|
return true;
|
|
|
|
|
|
|
|
VectorClear( r_pointColor );
|
|
|
|
|
|
|
|
lm = surf->samples + (t * ((surf->extents[0] >> 4) + 1) + s);
|
|
|
|
size = ((surf->extents[0] >> 4) + 1) * ((surf->extents[1] >> 4) + 1);
|
|
|
|
|
|
|
|
for( map = 0; map < MAXLIGHTMAPS && surf->styles[map] != 255; map++ )
|
|
|
|
{
|
|
|
|
uint scale = RI.lightstylevalue[surf->styles[map]];
|
|
|
|
|
2011-10-06 22:00:00 +02:00
|
|
|
r_pointColor[0] += TextureToTexGamma( lm->r ) * scale;
|
|
|
|
r_pointColor[1] += TextureToTexGamma( lm->g ) * scale;
|
|
|
|
r_pointColor[2] += TextureToTexGamma( lm->b ) * scale;
|
2010-12-16 22:00:00 +01:00
|
|
|
|
|
|
|
lm += size; // skip to next lightmap
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
// go down back side
|
|
|
|
return R_RecursiveLightPoint( model, node->children[!side], mid, end );
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
=================
|
|
|
|
R_LightForPoint
|
|
|
|
=================
|
|
|
|
*/
|
2011-07-07 22:00:00 +02:00
|
|
|
void R_LightForPoint( const vec3_t point, color24 *ambientLight, qboolean invLight, qboolean useAmbient, float radius )
|
2010-12-16 22:00:00 +01:00
|
|
|
{
|
2010-12-25 22:00:00 +01:00
|
|
|
dlight_t *dl;
|
|
|
|
pmtrace_t trace;
|
|
|
|
cl_entity_t *m_pGround;
|
2011-03-30 22:00:00 +02:00
|
|
|
vec3_t start, end, dir;
|
2010-12-25 22:00:00 +01:00
|
|
|
float dist, add;
|
|
|
|
model_t *pmodel;
|
|
|
|
mnode_t *pnodes;
|
|
|
|
|
|
|
|
if( !RI.refdef.movevars )
|
2010-12-16 22:00:00 +01:00
|
|
|
{
|
|
|
|
ambientLight->r = 255;
|
|
|
|
ambientLight->g = 255;
|
|
|
|
ambientLight->b = 255;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2010-12-25 22:00:00 +01:00
|
|
|
// set to full bright if no light data
|
|
|
|
if( !cl.worldmodel || !cl.worldmodel->lightdata )
|
|
|
|
{
|
2011-10-06 22:00:00 +02:00
|
|
|
ambientLight->r = TextureToTexGamma( RI.refdef.movevars->skycolor_r );
|
|
|
|
ambientLight->g = TextureToTexGamma( RI.refdef.movevars->skycolor_g );
|
|
|
|
ambientLight->b = TextureToTexGamma( RI.refdef.movevars->skycolor_b );
|
2010-12-25 22:00:00 +01:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2010-12-16 22:00:00 +01:00
|
|
|
// Get lighting at this point
|
2011-03-30 22:00:00 +02:00
|
|
|
VectorCopy( point, start );
|
2010-12-16 22:00:00 +01:00
|
|
|
VectorCopy( point, end );
|
2011-03-30 22:00:00 +02:00
|
|
|
if( invLight )
|
|
|
|
{
|
2011-04-15 22:00:00 +02:00
|
|
|
start[2] = point[2] - 64;
|
2011-03-30 22:00:00 +02:00
|
|
|
end[2] = point[2] + 8192;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2011-04-15 22:00:00 +02:00
|
|
|
start[2] = point[2] + 64;
|
2011-03-30 22:00:00 +02:00
|
|
|
end[2] = point[2] - 8192;
|
|
|
|
}
|
2010-12-16 22:00:00 +01:00
|
|
|
|
2010-12-25 22:00:00 +01:00
|
|
|
// always have valid model
|
|
|
|
pmodel = cl.worldmodel;
|
|
|
|
pnodes = pmodel->nodes;
|
|
|
|
m_pGround = NULL;
|
|
|
|
|
2011-02-25 22:00:00 +01:00
|
|
|
if( r_lighting_extended->integer )
|
2010-12-25 22:00:00 +01:00
|
|
|
{
|
2011-03-30 22:00:00 +02:00
|
|
|
trace = PM_PlayerTrace( clgame.pmove, start, end, PM_STUDIO_IGNORE, 0, -1, NULL );
|
2010-12-25 22:00:00 +01:00
|
|
|
m_pGround = CL_GetEntityByIndex( pfnIndexFromTrace( &trace ));
|
|
|
|
}
|
|
|
|
|
2011-03-30 22:00:00 +02:00
|
|
|
if( m_pGround && m_pGround->model )
|
2010-12-25 22:00:00 +01:00
|
|
|
{
|
2011-04-09 22:00:00 +02:00
|
|
|
matrix4x4 matrix;
|
|
|
|
hull_t *hull;
|
|
|
|
vec3_t start_l, end_l;
|
|
|
|
vec3_t offset;
|
|
|
|
|
2010-12-25 22:00:00 +01:00
|
|
|
pmodel = m_pGround->model;
|
|
|
|
pnodes = &pmodel->nodes[pmodel->hulls[0].firstclipnode];
|
2010-12-16 22:00:00 +01:00
|
|
|
|
2011-04-09 22:00:00 +02:00
|
|
|
hull = &pmodel->hulls[0];
|
|
|
|
VectorSubtract( hull->clip_mins, vec3_origin, offset );
|
|
|
|
VectorAdd( offset, m_pGround->origin, offset );
|
|
|
|
|
|
|
|
VectorSubtract( start, offset, start_l );
|
|
|
|
VectorSubtract( end, offset, end_l );
|
|
|
|
|
|
|
|
// rotate start and end into the models frame of reference
|
|
|
|
if( !VectorIsNull( m_pGround->angles ))
|
|
|
|
{
|
|
|
|
matrix4x4 imatrix;
|
|
|
|
|
|
|
|
Matrix4x4_CreateFromEntity( matrix, m_pGround->angles, offset, 1.0f );
|
|
|
|
Matrix4x4_Invert_Simple( imatrix, matrix );
|
|
|
|
|
|
|
|
Matrix4x4_VectorTransform( imatrix, start, start_l );
|
|
|
|
Matrix4x4_VectorTransform( imatrix, end, end_l );
|
|
|
|
}
|
|
|
|
|
|
|
|
// copy transformed pos back
|
|
|
|
VectorCopy( start_l, start );
|
|
|
|
VectorCopy( end_l, end );
|
2011-03-03 22:00:00 +01:00
|
|
|
}
|
2010-12-25 22:00:00 +01:00
|
|
|
|
2011-04-15 22:00:00 +02:00
|
|
|
VectorClear( r_pointColor );
|
2011-04-09 22:00:00 +02:00
|
|
|
|
2011-03-30 22:00:00 +02:00
|
|
|
if( R_RecursiveLightPoint( pmodel, pnodes, start, end ))
|
2010-12-25 22:00:00 +01:00
|
|
|
{
|
|
|
|
ambientLight->r = min((r_pointColor[0] >> 7), 255 );
|
|
|
|
ambientLight->g = min((r_pointColor[1] >> 7), 255 );
|
|
|
|
ambientLight->b = min((r_pointColor[2] >> 7), 255 );
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2011-03-03 22:00:00 +01:00
|
|
|
float ambient;
|
|
|
|
|
|
|
|
// R_RecursiveLightPoint didn't hit anything, so use default value
|
|
|
|
ambient = bound( 0.1f, r_lighting_ambient->value, 1.0f );
|
2011-07-07 22:00:00 +02:00
|
|
|
if( !useAmbient ) ambient = 0.0f; // clear ambient
|
2011-03-03 22:00:00 +01:00
|
|
|
ambientLight->r = 255 * ambient;
|
|
|
|
ambientLight->g = 255 * ambient;
|
|
|
|
ambientLight->b = 255 * ambient;
|
2010-12-25 22:00:00 +01:00
|
|
|
}
|
2010-12-16 22:00:00 +01:00
|
|
|
|
|
|
|
// add dynamic lights
|
2010-12-20 22:00:00 +01:00
|
|
|
if( radius && r_dynamic->integer )
|
2010-12-16 22:00:00 +01:00
|
|
|
{
|
2011-03-01 22:00:00 +01:00
|
|
|
int lnum, total;
|
|
|
|
float f;
|
|
|
|
|
|
|
|
VectorClear( r_pointColor );
|
|
|
|
|
|
|
|
for( total = lnum = 0, dl = cl_dlights; lnum < MAX_DLIGHTS; lnum++, dl++ )
|
2010-12-16 22:00:00 +01:00
|
|
|
{
|
|
|
|
if( dl->die < cl.time || !dl->radius )
|
|
|
|
continue;
|
|
|
|
|
|
|
|
VectorSubtract( dl->origin, point, dir );
|
|
|
|
dist = VectorLength( dir );
|
|
|
|
|
2010-12-20 22:00:00 +01:00
|
|
|
if( !dist || dist > dl->radius + radius )
|
2010-12-16 22:00:00 +01:00
|
|
|
continue;
|
|
|
|
|
2011-03-01 22:00:00 +01:00
|
|
|
add = 1.0f - (dist / ( dl->radius + radius ));
|
2011-10-06 22:00:00 +02:00
|
|
|
r_pointColor[0] += TextureToTexGamma( dl->color.r ) * add;
|
|
|
|
r_pointColor[1] += TextureToTexGamma( dl->color.g ) * add;
|
|
|
|
r_pointColor[2] += TextureToTexGamma( dl->color.b ) * add;
|
2011-03-01 22:00:00 +01:00
|
|
|
total++;
|
|
|
|
}
|
|
|
|
|
|
|
|
if( total != 0 )
|
|
|
|
{
|
|
|
|
r_pointColor[0] += ambientLight->r;
|
|
|
|
r_pointColor[1] += ambientLight->g;
|
|
|
|
r_pointColor[2] += ambientLight->b;
|
|
|
|
|
|
|
|
f = max( max( r_pointColor[0], r_pointColor[1] ), r_pointColor[2] );
|
|
|
|
if( f > 1.0f ) VectorScale( r_pointColor, ( 255.0f / f ), r_pointColor );
|
|
|
|
|
|
|
|
ambientLight->r = r_pointColor[0];
|
|
|
|
ambientLight->g = r_pointColor[1];
|
|
|
|
ambientLight->b = r_pointColor[2];
|
2010-12-16 22:00:00 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-08-14 22:00:00 +02:00
|
|
|
/*
|
|
|
|
=================
|
|
|
|
R_GetLightSpot
|
|
|
|
|
|
|
|
NOTE: must call R_LightForPoint first
|
|
|
|
=================
|
|
|
|
*/
|
|
|
|
void R_GetLightSpot( vec3_t lightspot )
|
|
|
|
{
|
|
|
|
if( lightspot ) VectorCopy( r_lightSpot, lightspot );
|
|
|
|
}
|
|
|
|
|
2010-12-16 22:00:00 +01:00
|
|
|
/*
|
|
|
|
=================
|
|
|
|
R_LightDir
|
|
|
|
=================
|
|
|
|
*/
|
|
|
|
void R_LightDir( const vec3_t origin, vec3_t lightDir, float radius )
|
|
|
|
{
|
|
|
|
dlight_t *dl;
|
|
|
|
vec3_t dir;
|
|
|
|
float dist;
|
|
|
|
int lnum;
|
|
|
|
|
|
|
|
// add dynamic lights
|
2011-03-03 22:00:00 +01:00
|
|
|
if( radius > 0.0f && r_dynamic->integer )
|
2010-12-16 22:00:00 +01:00
|
|
|
{
|
|
|
|
for( lnum = 0, dl = cl_dlights; lnum < MAX_DLIGHTS; lnum++, dl++ )
|
|
|
|
{
|
|
|
|
if( dl->die < cl.time || !dl->radius )
|
|
|
|
continue;
|
|
|
|
|
2011-03-03 22:00:00 +01:00
|
|
|
VectorSubtract( dl->origin, origin, dir );
|
2010-12-16 22:00:00 +01:00
|
|
|
dist = VectorLength( dir );
|
|
|
|
|
|
|
|
if( !dist || dist > dl->radius + radius )
|
|
|
|
continue;
|
2011-03-03 22:00:00 +01:00
|
|
|
VectorAdd( lightDir, dir, lightDir );
|
2010-12-16 22:00:00 +01:00
|
|
|
}
|
2011-03-20 22:00:00 +01:00
|
|
|
|
|
|
|
for( lnum = 0, dl = cl_elights; lnum < MAX_ELIGHTS; lnum++, dl++ )
|
|
|
|
{
|
|
|
|
if( dl->die < cl.time || !dl->radius )
|
|
|
|
continue;
|
|
|
|
|
|
|
|
VectorSubtract( dl->origin, origin, dir );
|
|
|
|
dist = VectorLength( dir );
|
|
|
|
|
|
|
|
if( !dist || dist > dl->radius + radius )
|
|
|
|
continue;
|
|
|
|
VectorAdd( lightDir, dir, lightDir );
|
|
|
|
}
|
2010-12-16 22:00:00 +01:00
|
|
|
}
|
2010-12-02 22:00:00 +01:00
|
|
|
}
|