This repository has been archived on 2022-06-27. You can view files and clone it, but cannot push or open issues or pull requests.
Xash3DArchive/render/r_light.c

700 lines
17 KiB
C
Raw Normal View History

2008-08-25 22:00:00 +02:00
//=======================================================================
// Copyright XashXT Group 2007 <20>
// r_light.c - scene lighting
//=======================================================================
#include "r_local.h"
#include "mathlib.h"
#include "matrixlib.h"
#include "const.h"
/*
2008-10-19 22:00:00 +02:00
=======================================================================
2008-08-25 22:00:00 +02:00
2008-10-19 22:00:00 +02:00
DYNAMIC LIGHTS
2008-08-25 22:00:00 +02:00
2008-10-19 22:00:00 +02:00
=======================================================================
2008-08-25 22:00:00 +02:00
*/
/*
2008-10-19 22:00:00 +02:00
=======================================================================
2008-08-25 22:00:00 +02:00
2008-10-19 22:00:00 +02:00
AMBIENT & DIFFUSE LIGHTING
2008-08-25 22:00:00 +02:00
2008-10-19 22:00:00 +02:00
=======================================================================
2008-08-25 22:00:00 +02:00
*/
2008-10-19 22:00:00 +02:00
static vec3_t r_pointColor;
static vec3_t r_lightColors[MAX_VERTICES];
2008-08-25 22:00:00 +02:00
/*
=================
2008-10-19 22:00:00 +02:00
R_RecursiveLightPoint
2008-08-25 22:00:00 +02:00
=================
*/
2008-10-19 22:00:00 +02:00
static bool R_RecursiveLightPoint( node_t *node, const vec3_t start, const vec3_t end )
2008-08-25 22:00:00 +02:00
{
2008-10-19 22:00:00 +02:00
#if 0
float front, back, frac;
int i, map, size, s, t;
vec3_t mid;
int side;
cplane_t *plane;
surface_t *surf;
mipTex_t *tex;
byte *lm;
vec3_t scale;
if( node->contents != -1 ) return false; // didn't hit anything
// Calculate mid point
plane = node->plane;
if( plane->type < 3 )
{
front = start[plane->type] - plane->dist;
back = end[plane->type] - plane->dist;
2008-08-25 22:00:00 +02:00
}
2008-10-19 22:00:00 +02:00
else
2008-10-12 22:00:00 +02:00
{
2008-10-19 22:00:00 +02:00
front = DotProduct( start, plane->normal ) - plane->dist;
back = DotProduct( end, plane->normal ) - plane->dist;
2008-10-12 22:00:00 +02:00
}
2008-08-25 22:00:00 +02:00
2008-10-19 22:00:00 +02:00
side = front < 0;
if((back < 0) == side ) return R_RecursiveLightPoint( node->children[side], start, end );
2008-08-25 22:00:00 +02:00
2008-10-19 22:00:00 +02:00
frac = front / (front - back);
2008-08-25 22:00:00 +02:00
2008-10-19 22:00:00 +02:00
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;
2008-08-25 22:00:00 +02:00
2008-10-19 22:00:00 +02:00
// Go down front side
if( R_RecursiveLightPoint( node->children[side], start, mid ))
return true; // hit something
2008-08-25 22:00:00 +02:00
2008-10-19 22:00:00 +02:00
if((back < 0) == side ) return false; // didn't hit anything
2008-08-25 22:00:00 +02:00
2008-10-19 22:00:00 +02:00
// check for impact on this node
surf = r_worldModel->surfaces + node->firstSurface;
for( i = 0; i < node->numSurfaces; i++, surf++ )
{
tex = surf->texInfo;
2008-08-25 22:00:00 +02:00
2008-10-19 22:00:00 +02:00
if( tex->flags & (SURF_SKY|SURF_WARP|SURF_NODRAW|SURF_NOLIGHTMAP))
continue; // no lightmaps
2008-08-25 22:00:00 +02:00
2008-10-19 22:00:00 +02:00
s = DotProduct(mid, surf->lmVecs[0]) + surf->lmVecs[0][3] - surf->textureMins[0];
t = DotProduct(mid, surf->lmVecs[1]) + surf->lmVecs[1][3] - surf->textureMins[1];
2008-08-25 22:00:00 +02:00
2008-10-19 22:00:00 +02:00
if((s < 0 || s > surf->extents[0]) || (t < 0 || t > surf->extents[1]))
continue;
2008-08-25 22:00:00 +02:00
2008-10-19 22:00:00 +02:00
s >>= 4;
t >>= 4;
2008-08-25 22:00:00 +02:00
2008-10-19 22:00:00 +02:00
if( !surf->lmSamples )
return true;
2008-08-25 22:00:00 +02:00
2008-10-19 22:00:00 +02:00
VectorClear( r_pointColor );
2008-08-25 22:00:00 +02:00
2008-10-19 22:00:00 +02:00
lm = surf->lmSamples + 3 * (t * surf->lmWidth + s);
size = surf->lmWidth * surf->lmHeight * 3;
for( map = 0; map < surf->numStyles; map++ )
2008-08-25 22:00:00 +02:00
{
2008-10-19 22:00:00 +02:00
VectorScale( r_lightStyles[surf->styles[map]].rgb, r_modulate->value, scale );
2008-08-25 22:00:00 +02:00
2008-10-19 22:00:00 +02:00
r_pointColor[0] += lm[0] * scale[0];
r_pointColor[1] += lm[1] * scale[1];
r_pointColor[2] += lm[2] * scale[2];
2008-08-25 22:00:00 +02:00
2008-10-19 22:00:00 +02:00
lm += size; // skip to next lightmap
2008-08-25 22:00:00 +02:00
}
2008-10-19 22:00:00 +02:00
return true;
2008-08-25 22:00:00 +02:00
}
2008-10-19 22:00:00 +02:00
// go down back side
return R_RecursiveLightPoint( node->children[!side], mid, end );
#endif
return true;
2008-08-25 22:00:00 +02:00
}
/*
=================
2008-10-19 22:00:00 +02:00
R_LightForPoint
2008-08-25 22:00:00 +02:00
=================
*/
2008-10-19 22:00:00 +02:00
void R_LightForPoint( const vec3_t point, vec3_t ambientLight )
2008-08-25 22:00:00 +02:00
{
2008-10-19 22:00:00 +02:00
dlight_t *dl;
vec3_t end, dir;
float dist, add;
int l;
2008-08-25 22:00:00 +02:00
2008-10-19 22:00:00 +02:00
// Set to full bright if no light data
if( !r_worldModel || !r_worldModel->lightMaps )
{
VectorSet( ambientLight, 1, 1, 1 );
return;
}
2008-08-25 22:00:00 +02:00
2008-10-19 22:00:00 +02:00
// Get lighting at this point
VectorSet( end, point[0], point[1], point[2] - MAX_WORLD_COORD );
VectorSet( r_pointColor, 1, 1, 1 );
2008-08-25 22:00:00 +02:00
2008-10-19 22:00:00 +02:00
R_RecursiveLightPoint( r_worldModel->nodes, point, end );
2008-08-25 22:00:00 +02:00
2008-10-19 22:00:00 +02:00
VectorCopy( r_pointColor, ambientLight );
2008-08-25 22:00:00 +02:00
2008-10-19 22:00:00 +02:00
// add dynamic lights
if( r_dynamiclights->integer )
{
for( l = 0, dl = r_dlights; l < r_numDLights; l++, dl++ )
{
VectorSubtract(dl->origin, point, dir);
dist = VectorLength(dir);
if( !dist || dist > dl->intensity )
continue;
2008-08-25 22:00:00 +02:00
2008-10-19 22:00:00 +02:00
add = (dl->intensity - dist);
VectorMA( ambientLight, add, dl->color, ambientLight );
}
2008-08-25 22:00:00 +02:00
}
}
/*
2008-10-19 22:00:00 +02:00
=================
R_ReadLightGrid
=================
2008-08-25 22:00:00 +02:00
*/
2008-10-19 22:00:00 +02:00
static void R_ReadLightGrid( const vec3_t origin, vec3_t lightDir )
2008-08-25 22:00:00 +02:00
{
2008-10-19 22:00:00 +02:00
vec3_t vf1, vf2;
float scale[8];
int vi[3], index[4];
int i;
if( !r_worldModel->lightGrid )
2008-08-25 22:00:00 +02:00
{
2008-10-19 22:00:00 +02:00
VectorSet( lightDir, 1, 0, -1 );
return;
2008-08-25 22:00:00 +02:00
}
for( i = 0; i < 3; i++ )
{
2008-10-19 22:00:00 +02:00
vf1[i] = (origin[i] - r_worldModel->gridMins[i]) / r_worldModel->gridSize[i];
vi[i] = (int)vf1[i];
vf1[i] = vf1[i] - floor(vf1[i]);
vf2[i] = 1.0 - vf1[i];
2008-08-25 22:00:00 +02:00
}
2008-10-19 22:00:00 +02:00
index[0] = vi[2] * r_worldModel->gridBounds[3] + vi[1] * r_worldModel->gridBounds[0] + vi[0];
index[1] = index[0] + r_worldModel->gridBounds[0];
index[2] = index[0] + r_worldModel->gridBounds[3];
index[3] = index[2] + r_worldModel->gridBounds[0];
2008-08-25 22:00:00 +02:00
for( i = 0; i < 4; i++ )
{
2008-10-19 22:00:00 +02:00
if( index[i] < 0 || index[i] >= r_worldModel->gridPoints -1 )
2008-08-25 22:00:00 +02:00
{
2008-10-19 22:00:00 +02:00
VectorSet( lightDir, 1, 0, -1 );
return;
2008-08-25 22:00:00 +02:00
}
}
2008-10-19 22:00:00 +02:00
scale[0] = vf2[0] * vf2[1] * vf2[2];
scale[1] = vf1[0] * vf2[1] * vf2[2];
scale[2] = vf2[0] * vf1[1] * vf2[2];
scale[3] = vf1[0] * vf1[1] * vf2[2];
scale[4] = vf2[0] * vf2[1] * vf1[2];
scale[5] = vf1[0] * vf2[1] * vf1[2];
scale[6] = vf2[0] * vf1[1] * vf1[2];
scale[7] = vf1[0] * vf1[1] * vf1[2];
2008-08-25 22:00:00 +02:00
2008-10-19 22:00:00 +02:00
VectorClear(lightDir);
2008-08-25 22:00:00 +02:00
for( i = 0; i < 4; i++ )
{
2008-10-19 22:00:00 +02:00
VectorMA( lightDir, scale[i*2+0], r_worldModel->lightGrid[index[i]+0].lightDir, lightDir );
VectorMA( lightDir, scale[i*2+1], r_worldModel->lightGrid[index[i]+1].lightDir, lightDir );
}
}
2008-08-25 22:00:00 +02:00
2008-10-19 22:00:00 +02:00
/*
=================
R_LightDir
=================
*/
void R_LightDir( const vec3_t origin, vec3_t lightDir )
{
dlight_t *dl;
vec3_t dir;
float dist;
int l;
// Get light direction from light grid
R_ReadLightGrid( origin, lightDir );
// Add dynamic lights
if( r_dynamiclights->integer )
{
for( l = 0, dl = r_dlights; l < r_numDLights; l++, dl++ )
2008-08-25 22:00:00 +02:00
{
2008-10-19 22:00:00 +02:00
VectorSubtract( dl->origin, origin, dir );
dist = VectorLength( dir );
if( !dist || dist > dl->intensity )
continue;
VectorAdd( lightDir, dir, lightDir );
2008-08-25 22:00:00 +02:00
}
}
2008-10-19 22:00:00 +02:00
}
/*
=================
R_LightingAmbient
=================
*/
void R_LightingAmbient( void )
{
dlight_t *dl;
vec3_t end, dir;
float add, dist, radius;
int i, l;
vec3_t ambientLight;
2008-08-25 22:00:00 +02:00
2008-10-19 22:00:00 +02:00
// Set to full bright if no light data
if(( r_refdef.rdflags & RDF_NOWORLDMODEL) || !r_worldModel->lightMaps )
2008-08-25 22:00:00 +02:00
{
2008-11-04 22:00:00 +01:00
for( i = 0; i < ref.numVertex; i++ )
2008-08-25 22:00:00 +02:00
{
2008-11-04 22:00:00 +01:00
ref.vertsArray[i].color[0] = 1.0f;
ref.vertsArray[i].color[1] = 1.0f;
ref.vertsArray[i].color[2] = 1.0f;
ref.vertsArray[i].color[3] = 1.0f;
2008-10-12 22:00:00 +02:00
}
2008-10-19 22:00:00 +02:00
return;
}
// Get lighting at this point
VectorSet( end, m_pCurrentEntity->origin[0], m_pCurrentEntity->origin[1], m_pCurrentEntity->origin[2] - MAX_WORLD_COORD );
VectorSet( r_pointColor, 1, 1, 1 );
R_RecursiveLightPoint( r_worldModel->nodes, m_pCurrentEntity->origin, end );
VectorScale( r_pointColor, r_ambientscale->value, ambientLight );
// Always have some light
if( m_pCurrentEntity->renderfx & RF_MINLIGHT )
{
for( i = 0; i < 3; i++ )
2008-10-12 22:00:00 +02:00
{
2008-10-19 22:00:00 +02:00
if( ambientLight[i] > 0.1 )
break;
2008-08-25 22:00:00 +02:00
}
2008-10-19 22:00:00 +02:00
if( i == 3 ) VectorSet( ambientLight, 0.1, 0.1, 0.1 );
2008-08-25 22:00:00 +02:00
}
// add dynamic lights
2008-10-19 22:00:00 +02:00
if( r_dynamiclights->integer )
2008-08-25 22:00:00 +02:00
{
2008-10-19 22:00:00 +02:00
if( m_pCurrentEntity->ent_type == ED_NORMAL )
radius = m_pCurrentEntity->model->radius;
else radius = m_pCurrentEntity->radius;
2008-08-25 22:00:00 +02:00
2008-10-19 22:00:00 +02:00
for( l = 0, dl = r_dlights; l < r_numDLights; l++, dl++ )
2008-08-25 22:00:00 +02:00
{
2008-10-19 22:00:00 +02:00
VectorSubtract( dl->origin, m_pCurrentEntity->origin, dir );
dist = VectorLength( dir );
2008-08-25 22:00:00 +02:00
if( !dist || dist > dl->intensity + radius )
continue;
2008-10-19 22:00:00 +02:00
add = (dl->intensity - dist);
VectorMA( ambientLight, add, dl->color, ambientLight );
2008-08-25 22:00:00 +02:00
}
}
2008-10-19 22:00:00 +02:00
// normalize and convert to byte
ColorNormalize( ambientLight, ambientLight );
2008-08-25 22:00:00 +02:00
2008-11-04 22:00:00 +01:00
for( i = 0; i < ref.numVertex; i++ )
2008-08-25 22:00:00 +02:00
{
2008-11-04 22:00:00 +01:00
ref.vertsArray[i].color[0] = ambientLight[0];
ref.vertsArray[i].color[1] = ambientLight[1];
ref.vertsArray[i].color[2] = ambientLight[2];
ref.vertsArray[i].color[3] = 1.0f;
2008-08-25 22:00:00 +02:00
}
}
/*
2008-10-19 22:00:00 +02:00
=================
R_LightingDiffuse
=================
2008-08-25 22:00:00 +02:00
*/
2008-10-19 22:00:00 +02:00
void R_LightingDiffuse( void )
2008-08-25 22:00:00 +02:00
{
dlight_t *dl;
2008-10-19 22:00:00 +02:00
int i, l;
vec3_t end, dir;
float add, dot, dist, intensity, radius;
vec3_t ambientLight, directedLight, lightDir;
2008-08-25 22:00:00 +02:00
2008-10-19 22:00:00 +02:00
// Set to full bright if no light data
if((r_refdef.rdflags & RDF_NOWORLDMODEL) || !r_worldModel->lightMaps )
{
2008-11-04 22:00:00 +01:00
for( i = 0; i < ref.numVertex; i++ )
2008-10-19 22:00:00 +02:00
{
2008-11-04 22:00:00 +01:00
ref.vertsArray[i].color[0] = 1.0f;
ref.vertsArray[i].color[1] = 1.0f;
ref.vertsArray[i].color[2] = 1.0f;
ref.vertsArray[i].color[3] = 1.0f;
2008-10-19 22:00:00 +02:00
}
2008-08-25 22:00:00 +02:00
return;
2008-10-19 22:00:00 +02:00
}
2008-08-25 22:00:00 +02:00
2008-10-19 22:00:00 +02:00
// Get lighting at this point
VectorSet( end, m_pCurrentEntity->origin[0], m_pCurrentEntity->origin[1], m_pCurrentEntity->origin[2] - MAX_WORLD_COORD );
VectorSet( r_pointColor, 1, 1, 1 );
2008-08-25 22:00:00 +02:00
2008-10-19 22:00:00 +02:00
R_RecursiveLightPoint( r_worldModel->nodes, m_pCurrentEntity->origin, end );
2008-08-25 22:00:00 +02:00
2008-10-19 22:00:00 +02:00
VectorScale( r_pointColor, r_ambientscale->value, ambientLight );
VectorScale( r_pointColor, r_directedscale->value, directedLight );
2008-08-25 22:00:00 +02:00
2008-10-19 22:00:00 +02:00
R_ReadLightGrid( m_pCurrentEntity->origin, lightDir );
2008-08-25 22:00:00 +02:00
2008-10-19 22:00:00 +02:00
// Always have some light
if( m_pCurrentEntity->renderfx & RF_MINLIGHT )
2008-08-25 22:00:00 +02:00
{
2008-10-19 22:00:00 +02:00
for( i = 0; i < 3; i++ )
2008-08-25 22:00:00 +02:00
{
2008-10-19 22:00:00 +02:00
if( ambientLight[i] > 0.1 )
break;
2008-10-12 22:00:00 +02:00
}
2008-10-19 22:00:00 +02:00
if( i == 3 ) VectorSet( ambientLight, 0.1, 0.1, 0.1 );
2008-08-25 22:00:00 +02:00
}
2008-10-19 22:00:00 +02:00
// Compute lighting at each vertex
VectorRotate( lightDir, m_pCurrentEntity->axis, dir );
VectorNormalizeFast( dir );
2008-10-12 22:00:00 +02:00
2008-11-04 22:00:00 +01:00
for( i = 0; i < ref.numVertex; i++ )
2008-10-19 22:00:00 +02:00
{
2008-11-04 22:00:00 +01:00
dot = DotProduct( ref.vertsArray[i].normal, dir );
2008-10-19 22:00:00 +02:00
if( dot <= 0 )
2008-08-25 22:00:00 +02:00
{
2008-10-19 22:00:00 +02:00
VectorCopy( ambientLight, r_lightColors[i] );
continue;
2008-08-25 22:00:00 +02:00
}
2008-10-19 22:00:00 +02:00
VectorMA( ambientLight, dot, directedLight, r_lightColors[i] );
2008-08-25 22:00:00 +02:00
}
2008-10-19 22:00:00 +02:00
// add dynamic lights
if( r_dynamiclights->integer )
{
if( m_pCurrentEntity->ent_type == ED_NORMAL )
radius = m_pCurrentEntity->model->radius;
else radius = m_pCurrentEntity->radius;
2008-10-12 22:00:00 +02:00
2008-10-19 22:00:00 +02:00
for( l = 0, dl = r_dlights; l < r_numDLights; l++, dl++ )
2008-10-12 22:00:00 +02:00
{
2008-10-19 22:00:00 +02:00
VectorSubtract( dl->origin, m_pCurrentEntity->origin, dir );
dist = VectorLength( dir );
if( !dist || dist > dl->intensity + radius )
2008-08-25 22:00:00 +02:00
continue;
2008-10-19 22:00:00 +02:00
VectorRotate( dir, m_pCurrentEntity->axis, lightDir );
intensity = dl->intensity * 8;
2008-08-25 22:00:00 +02:00
2008-10-19 22:00:00 +02:00
// compute lighting at each vertex
2008-11-04 22:00:00 +01:00
for( i = 0; i < ref.numVertex; i++ )
2008-08-25 22:00:00 +02:00
{
2008-11-04 22:00:00 +01:00
VectorSubtract( lightDir, ref.vertsArray[i].point, dir );
add = DotProduct( ref.vertsArray[i].normal, dir );
2008-10-19 22:00:00 +02:00
if( add <= 0 ) continue;
2008-08-25 22:00:00 +02:00
2008-10-19 22:00:00 +02:00
dot = DotProduct( dir, dir );
add *= (intensity / dot) * rsqrt( dot );
VectorMA( r_lightColors[i], add, dl->color, r_lightColors[i] );
2008-08-25 22:00:00 +02:00
}
}
2008-10-19 22:00:00 +02:00
}
// Normalize and convert to byte
2008-11-04 22:00:00 +01:00
for (i = 0; i < ref.numVertex; i++)
2008-10-19 22:00:00 +02:00
{
ColorNormalize( r_lightColors[i], r_lightColors[i] );
2008-11-04 22:00:00 +01:00
ref.vertsArray[i].color[0] = r_lightColors[i][0];
ref.vertsArray[i].color[1] = r_lightColors[i][1];
ref.vertsArray[i].color[2] = r_lightColors[i][2];
ref.vertsArray[i].color[3] = 1.0f;
2008-08-25 22:00:00 +02:00
}
}
2008-10-19 22:00:00 +02:00
2008-08-25 22:00:00 +02:00
/*
2008-10-19 22:00:00 +02:00
=======================================================================
2008-08-25 22:00:00 +02:00
2008-10-19 22:00:00 +02:00
LIGHT SAMPLING
2008-08-25 22:00:00 +02:00
2008-10-19 22:00:00 +02:00
=======================================================================
2008-08-25 22:00:00 +02:00
*/
2008-10-19 22:00:00 +02:00
static vec3_t r_blockLights[128*128];
2008-08-25 22:00:00 +02:00
/*
2008-10-19 22:00:00 +02:00
=================
R_SetCacheState
=================
2008-08-25 22:00:00 +02:00
*/
2008-10-19 22:00:00 +02:00
static void R_SetCacheState( surface_t *surf )
2008-08-25 22:00:00 +02:00
{
2008-10-19 22:00:00 +02:00
int map;
2008-08-25 22:00:00 +02:00
2008-10-19 22:00:00 +02:00
for( map = 0; map < surf->numStyles; map++ )
surf->cachedLight[map] = r_lightStyles[surf->styles[map]].white;
}
/*
=================
R_AddDynamicLights
=================
*/
static void R_AddDynamicLights( surface_t *surf )
{
#if 0
int l;
int s, t, sd, td;
float sl, tl, sacc, tacc;
float dist, rad, scale;
cplane_t *plane;
vec3_t origin, tmp, impact;
mipTex_t *tex = surf->texInfo;
dlight_t *dl;
float *bl;
for( l = 0, dl = r_dlights; l < r_numDLights; l++, dl++ )
2008-08-25 22:00:00 +02:00
{
2008-10-19 22:00:00 +02:00
if(!(surf->dlightBits & (1<<l)))
continue; // not lit by this light
if( !AxisCompare( m_pCurrentEntity->axis, axisDefault ))
2008-08-25 22:00:00 +02:00
{
2008-10-19 22:00:00 +02:00
VectorSubtract( dl->origin, m_pCurrentEntity->origin, tmp );
VectorRotate( tmp, m_pCurrentEntity->axis, origin );
2008-08-25 22:00:00 +02:00
}
2008-10-19 22:00:00 +02:00
else VectorSubtract( dl->origin, m_pCurrentEntity->origin, origin );
plane = surf->plane;
if( plane->type < 3 ) dist = origin[plane->type] - plane->dist;
else dist = DotProduct( origin, plane->normal ) - plane->dist;
// rad is now the highest intensity on the plane
rad = dl->intensity - fabs(dist);
if( rad < 0 ) continue;
if( plane->type < 3 )
2008-08-25 22:00:00 +02:00
{
2008-10-19 22:00:00 +02:00
VectorCopy( origin, impact );
impact[plane->type] -= dist;
2008-08-25 22:00:00 +02:00
}
2008-10-19 22:00:00 +02:00
else VectorMA( origin, -dist, plane->normal, impact );
2008-08-25 22:00:00 +02:00
2008-10-19 22:00:00 +02:00
sl = DotProduct(impact, tex->vecs[0]) + tex->vecs[0][3] - surf->textureMins[0];
tl = DotProduct(impact, tex->vecs[1]) + tex->vecs[1][3] - surf->textureMins[1];
2008-08-25 22:00:00 +02:00
2008-10-19 22:00:00 +02:00
bl = (float *)r_blockLights;
for( t = 0, tacc = 0; t < surf->lmHeight; t++, tacc += 16 )
2008-08-25 22:00:00 +02:00
{
2008-10-19 22:00:00 +02:00
td = tl - tacc;
if( td < 0 ) td = -td;
for( s = 0, sacc = 0; s < surf->lmWidth; s++, sacc += 16 )
2008-08-25 22:00:00 +02:00
{
2008-10-19 22:00:00 +02:00
sd = sl - sacc;
if( sd < 0 ) sd = -sd;
if( sd > td ) dist = sd + (td >> 1);
else dist = td + (sd >> 1);
2008-08-25 22:00:00 +02:00
2008-10-19 22:00:00 +02:00
if( dist < rad )
2008-08-25 22:00:00 +02:00
{
2008-10-19 22:00:00 +02:00
scale = rad - dist;
bl[0] += dl->color[0] * scale;
bl[1] += dl->color[1] * scale;
bl[2] += dl->color[2] * scale;
2008-08-25 22:00:00 +02:00
}
2008-10-19 22:00:00 +02:00
bl += 3;
2008-08-25 22:00:00 +02:00
}
}
}
2008-10-19 22:00:00 +02:00
#endif
2008-08-25 22:00:00 +02:00
}
/*
2008-10-19 22:00:00 +02:00
=================
R_BuildLightmap
Combine and scale multiple lightmaps into the floating format in r_blockLights
=================
2008-08-25 22:00:00 +02:00
*/
2008-10-19 22:00:00 +02:00
static void R_BuildLightmap( surface_t *surf, byte *dest, int stride )
2008-08-25 22:00:00 +02:00
{
2008-11-06 22:00:00 +01:00
#if 0
2008-10-19 22:00:00 +02:00
int i, map, size, s, t;
vec3_t scale;
float *bl;
byte *lm;
2008-08-25 22:00:00 +02:00
2008-10-19 22:00:00 +02:00
lm = surf->lmSamples;
size = surf->lmWidth * surf->lmHeight;
2008-08-25 22:00:00 +02:00
2008-10-19 22:00:00 +02:00
if( !lm )
{
// set to full bright if no light data
for( i = 0, bl = (float *)r_blockLights; i < size; i++, bl += 3 )
2008-08-25 22:00:00 +02:00
{
2008-10-19 22:00:00 +02:00
bl[0] = 255;
bl[1] = 255;
bl[2] = 255;
2008-08-25 22:00:00 +02:00
}
}
else
{
2008-10-19 22:00:00 +02:00
// add all the lightmaps
VectorScale( r_lightStyles[surf->styles[0]].rgb, r_modulate->value, scale );
2008-10-12 22:00:00 +02:00
2008-10-19 22:00:00 +02:00
for( i = 0, bl = (float *)r_blockLights; i < size; i++, bl += 3, lm += 3 )
2008-08-25 22:00:00 +02:00
{
2008-10-19 22:00:00 +02:00
bl[0] = lm[0] * scale[0];
bl[1] = lm[1] * scale[1];
bl[2] = lm[2] * scale[2];
}
2008-10-12 22:00:00 +02:00
2008-10-19 22:00:00 +02:00
if( surf->numStyles > 1 )
{
for( map = 1; map < surf->numStyles; map++ )
2008-08-25 22:00:00 +02:00
{
2008-10-19 22:00:00 +02:00
VectorScale( r_lightStyles[surf->styles[map]].rgb, r_modulate->value, scale );
for( i = 0, bl = (float *)r_blockLights; i < size; i++, bl += 3, lm += 3 )
{
bl[0] += lm[0] * scale[0];
bl[1] += lm[1] * scale[1];
bl[2] += lm[2] * scale[2];
}
2008-08-25 22:00:00 +02:00
}
}
2008-10-19 22:00:00 +02:00
// add all the dynamic lights
if( surf->dlightFrame == r_frameCount )
R_AddDynamicLights( surf );
2008-08-25 22:00:00 +02:00
}
2008-10-19 22:00:00 +02:00
// put into texture format
stride -= (surf->lmWidth<<2);
bl = (float *)r_blockLights;
2008-08-25 22:00:00 +02:00
2008-10-19 22:00:00 +02:00
for( t = 0; t < surf->lmHeight; t++ )
2008-08-25 22:00:00 +02:00
{
2008-10-19 22:00:00 +02:00
for( s = 0; s < surf->lmWidth; s++ )
{
ColorNormalize( bl, bl );
Vector4Set( dest, bl[0], bl[1], bl[2], 255 );
bl += 3;
dest += 4;
}
dest += stride;
2008-08-25 22:00:00 +02:00
}
2008-11-06 22:00:00 +01:00
#endif
2008-08-25 22:00:00 +02:00
}
2008-10-19 22:00:00 +02:00
2008-10-12 22:00:00 +02:00
/*
2008-10-19 22:00:00 +02:00
=======================================================================
LIGHTMAP ALLOCATION
=======================================================================
2008-10-12 22:00:00 +02:00
*/
2008-10-19 22:00:00 +02:00
typedef struct
2008-10-12 22:00:00 +02:00
{
2008-10-19 22:00:00 +02:00
int currentNum;
int allocated[LIGHTMAP_WIDTH];
byte buffer[LIGHTMAP_WIDTH*LIGHTMAP_HEIGHT*4];
} lmState_t;
2008-10-12 22:00:00 +02:00
2008-10-19 22:00:00 +02:00
static lmState_t r_lmState;
2008-10-12 22:00:00 +02:00
2008-08-25 22:00:00 +02:00
/*
2008-10-19 22:00:00 +02:00
=================
R_BeginBuildingLightmaps
=================
2008-08-25 22:00:00 +02:00
*/
2008-10-19 22:00:00 +02:00
void R_BeginBuildingLightmaps( void )
2008-08-25 22:00:00 +02:00
{
int i;
2008-10-19 22:00:00 +02:00
// setup the base lightstyles so the lightmaps
// won't have to be regenerated the first time they're seen
2008-08-25 22:00:00 +02:00
for( i = 0; i < MAX_LIGHTSTYLES; i++ )
{
2008-10-19 22:00:00 +02:00
r_lightStyles[i].white = 3;
2008-08-29 22:00:00 +02:00
r_lightStyles[i].rgb[0] = 1;
r_lightStyles[i].rgb[1] = 1;
r_lightStyles[i].rgb[2] = 1;
2008-08-25 22:00:00 +02:00
}
2008-10-19 22:00:00 +02:00
r_lmState.currentNum = -1;
2008-10-29 22:00:00 +01:00
Mem_Set( r_lmState.allocated, 0, sizeof( r_lmState.allocated ));
Mem_Set( r_lmState.buffer, 255, sizeof( r_lmState.buffer ));
2008-08-25 22:00:00 +02:00
}
/*
2008-10-19 22:00:00 +02:00
=================
R_EndBuildingLightmaps
=================
2008-08-25 22:00:00 +02:00
*/
2008-10-19 22:00:00 +02:00
void R_EndBuildingLightmaps( void )
2008-08-25 22:00:00 +02:00
{
}
/*
2008-10-19 22:00:00 +02:00
=================
R_BuildSurfaceLightmap
=================
2008-08-25 22:00:00 +02:00
*/
2008-10-19 22:00:00 +02:00
void R_BuildSurfaceLightmap( surface_t *surf )
2008-08-25 22:00:00 +02:00
{
2008-11-08 22:00:00 +01:00
byte *base = NULL;
2008-08-25 22:00:00 +02:00
2008-11-08 22:00:00 +01:00
if(!( surf->texInfo->flags & SHADER_HASLIGHTMAP ))
2008-10-19 22:00:00 +02:00
return; // no lightmaps
2008-10-12 22:00:00 +02:00
2008-11-06 22:00:00 +01:00
r_lmState.currentNum = surf->lmNum;
2008-10-19 22:00:00 +02:00
R_SetCacheState( surf );
R_BuildLightmap( surf, base, LIGHTMAP_WIDTH * 4 );
2008-08-25 22:00:00 +02:00
}
/*
2008-10-19 22:00:00 +02:00
=================
R_UpdateSurfaceLightmap
=================
2008-08-25 22:00:00 +02:00
*/
2008-10-19 22:00:00 +02:00
void R_UpdateSurfaceLightmap( surface_t *surf )
2008-08-25 22:00:00 +02:00
{
2008-10-19 22:00:00 +02:00
if( surf->dlightFrame == r_frameCount )
GL_BindTexture( r_dlightTexture );
else
{
2008-11-06 22:00:00 +01:00
GL_BindTexture( r_worldModel->lightMaps[surf->lmNum] );
2008-10-19 22:00:00 +02:00
R_SetCacheState( surf );
}
2008-11-07 22:00:00 +01:00
// R_BuildLightmap( surf, r_lmState.buffer, surf->lmWidth * 4 );
// pglTexSubImage2D( GL_TEXTURE_2D, 0, surf->lmS, surf->lmT, surf->lmWidth, surf->lmHeight, GL_RGBA, GL_UNSIGNED_BYTE, r_lmState.buffer );
2008-08-25 22:00:00 +02:00
}