2023-05-08 14:33:37 +02:00
|
|
|
/*
|
|
|
|
===========================================================================
|
|
|
|
Copyright (C) 1999-2005 Id Software, Inc.
|
|
|
|
|
|
|
|
This file is part of Quake III Arena source code.
|
|
|
|
|
|
|
|
Quake III Arena source code 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.
|
|
|
|
|
|
|
|
Quake III Arena source code 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 Foobar; if not, write to the Free Software
|
|
|
|
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
|
|
|
===========================================================================
|
|
|
|
*/
|
|
|
|
// tr_light.c
|
|
|
|
|
|
|
|
#include "tr_local.h"
|
|
|
|
|
|
|
|
#define DLIGHT_AT_RADIUS 16
|
|
|
|
// at the edge of a dlight's influence, this amount of light will be added
|
|
|
|
|
|
|
|
#define DLIGHT_MINIMUM_RADIUS 16
|
|
|
|
// never calculate a range less than this to prevent huge light numbers
|
|
|
|
|
2023-05-19 02:11:28 +02:00
|
|
|
typedef struct {
|
|
|
|
dlight_t *dl;
|
|
|
|
float power;
|
|
|
|
vec3_t origin;
|
|
|
|
} incidentLight_t;
|
|
|
|
|
|
|
|
typedef struct {
|
|
|
|
int dlightMap;
|
|
|
|
int allocated[128];
|
|
|
|
byte lightmap_buffer[65536];
|
|
|
|
byte* srcBase;
|
|
|
|
byte* dstBase;
|
|
|
|
incidentLight_t lights[32];
|
|
|
|
int numLights;
|
|
|
|
} dlightInfo_t;
|
|
|
|
|
|
|
|
dlightInfo_t dli;
|
2023-05-08 14:33:37 +02:00
|
|
|
|
2023-05-20 17:01:42 +02:00
|
|
|
void R_SetupEntityLightingGrid(trRefEntity_t* ent);
|
|
|
|
|
2023-05-08 14:33:37 +02:00
|
|
|
/*
|
|
|
|
===============
|
|
|
|
R_TransformDlights
|
|
|
|
|
|
|
|
Transforms the origins of an array of dlights.
|
|
|
|
Used by both the front end (for DlightBmodel) and
|
|
|
|
the back end (before doing the lighting calculation)
|
|
|
|
===============
|
|
|
|
*/
|
2023-05-11 22:48:13 +02:00
|
|
|
void R_TransformDlights( int count, dlight_t *dl, orientationr_t *ori) {
|
2023-05-08 14:33:37 +02:00
|
|
|
int i;
|
|
|
|
vec3_t temp;
|
|
|
|
|
|
|
|
for ( i = 0 ; i < count ; i++, dl++ ) {
|
2023-05-11 22:48:13 +02:00
|
|
|
VectorSubtract( dl->origin, ori->origin, temp );
|
|
|
|
dl->transformed[0] = DotProduct( temp, ori->axis[0] );
|
|
|
|
dl->transformed[1] = DotProduct( temp, ori->axis[1] );
|
|
|
|
dl->transformed[2] = DotProduct( temp, ori->axis[2] );
|
2023-05-08 14:33:37 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
=============
|
|
|
|
R_DlightBmodel
|
|
|
|
|
|
|
|
Determine which dynamic lights may effect this bmodel
|
|
|
|
=============
|
|
|
|
*/
|
|
|
|
void R_DlightBmodel( bmodel_t *bmodel ) {
|
|
|
|
int i, j;
|
|
|
|
dlight_t *dl;
|
|
|
|
int mask;
|
|
|
|
msurface_t *surf;
|
|
|
|
|
|
|
|
// transform all the lights
|
2023-05-11 22:48:13 +02:00
|
|
|
R_TransformDlights( tr.refdef.num_dlights, tr.refdef.dlights, &tr.ori );
|
2023-05-08 14:33:37 +02:00
|
|
|
|
|
|
|
mask = 0;
|
|
|
|
for ( i=0 ; i<tr.refdef.num_dlights ; i++ ) {
|
|
|
|
dl = &tr.refdef.dlights[i];
|
|
|
|
|
|
|
|
// see if the point is close enough to the bounds to matter
|
|
|
|
for ( j = 0 ; j < 3 ; j++ ) {
|
|
|
|
if ( dl->transformed[j] - bmodel->bounds[1][j] > dl->radius ) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if ( bmodel->bounds[0][j] - dl->transformed[j] > dl->radius ) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if ( j < 3 ) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
// we need to check this light
|
|
|
|
mask |= 1 << i;
|
|
|
|
}
|
|
|
|
|
|
|
|
tr.currentEntity->needDlights = (mask != 0);
|
|
|
|
|
|
|
|
// set the dlight bits in all the surfaces
|
|
|
|
for ( i = 0 ; i < bmodel->numSurfaces ; i++ ) {
|
|
|
|
surf = bmodel->firstSurface + i;
|
|
|
|
|
|
|
|
if ( *surf->data == SF_FACE ) {
|
|
|
|
((srfSurfaceFace_t *)surf->data)->dlightBits[ tr.smpFrame ] = mask;
|
|
|
|
} else if ( *surf->data == SF_GRID ) {
|
|
|
|
((srfGridMesh_t *)surf->data)->dlightBits[ tr.smpFrame ] = mask;
|
|
|
|
} else if ( *surf->data == SF_TRIANGLES ) {
|
|
|
|
((srfTriangles_t *)surf->data)->dlightBits[ tr.smpFrame ] = mask;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-05-08 14:57:51 +02:00
|
|
|
static byte* R_GetLightGridPalettedColor(int iColor)
|
|
|
|
{
|
|
|
|
// FIXME: unimplemented
|
|
|
|
}
|
|
|
|
|
2023-05-20 17:01:42 +02:00
|
|
|
void R_GetLightingGridValue(const vec3_t vPos, vec3_t vLight)
|
2023-05-08 14:57:51 +02:00
|
|
|
{
|
2023-05-20 17:01:42 +02:00
|
|
|
if (!tr.world || !tr.world->lightGridData || !tr.world->lightGridOffsets) {
|
|
|
|
vLight[0] = vLight[1] = vLight[2] = tr.identityLightByte;
|
|
|
|
}
|
|
|
|
|
|
|
|
vLight[0] = vLight[1] = vLight[2] = tr.identityLightByte;
|
2023-05-08 14:57:51 +02:00
|
|
|
// FIXME: unimplemented
|
|
|
|
}
|
|
|
|
|
2023-05-20 17:01:42 +02:00
|
|
|
void R_GetLightingGridValueFast(const vec3_t vPos, vec3_t vLight)
|
2023-05-08 14:57:51 +02:00
|
|
|
{
|
|
|
|
// FIXME: unimplemented
|
2023-05-29 15:53:01 +02:00
|
|
|
VectorSet(vLight, 1.f, 1.f, 1.f);
|
2023-05-08 14:57:51 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void R_GetLightingForDecal(vec3_t vLight, vec3_t vFacing, vec3_t vOrigin)
|
|
|
|
{
|
|
|
|
// FIXME: unimplemented
|
2023-05-29 15:53:01 +02:00
|
|
|
VectorSet(vLight, 1.f, 1.f, 1.f);
|
2023-05-08 14:57:51 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void R_GetLightingForSmoke(vec3_t vLight, vec3_t vOrigin)
|
|
|
|
{
|
|
|
|
// FIXME: unimplemented
|
2023-05-29 15:53:01 +02:00
|
|
|
VectorSet(vLight, 1.f, 1.f, 1.f);
|
2023-05-08 14:57:51 +02:00
|
|
|
}
|
|
|
|
|
2023-05-20 17:01:42 +02:00
|
|
|
static int RB_GetEntityGridLighting()
|
|
|
|
{
|
|
|
|
int iColor;
|
|
|
|
int i;
|
|
|
|
dlight_t* dl;
|
|
|
|
float power;
|
|
|
|
vec3_t vLight;
|
|
|
|
vec3_t dir;
|
|
|
|
float d;
|
|
|
|
float* lightOrigin;
|
|
|
|
|
|
|
|
lightOrigin = backEnd.currentSphere->traceOrigin;
|
|
|
|
if (!(backEnd.refdef.rdflags & RDF_NOWORLDMODEL) && tr.world->lightGridData) {
|
|
|
|
R_GetLightingGridValue(backEnd.currentSphere->traceOrigin, vLight);
|
2023-05-08 14:33:37 +02:00
|
|
|
} else {
|
2023-05-20 17:01:42 +02:00
|
|
|
vLight[0] = vLight[1] = vLight[2] = tr.identityLight * 150.0;
|
2023-05-08 14:33:37 +02:00
|
|
|
}
|
|
|
|
|
2023-05-20 17:01:42 +02:00
|
|
|
for (i = 0; i < backEnd.refdef.num_dlights; i++) {
|
|
|
|
dl = &backEnd.refdef.dlights[i];
|
|
|
|
VectorSubtract(dl->origin, lightOrigin, dir);
|
|
|
|
d = VectorLengthSquared(dir);
|
2023-05-08 14:33:37 +02:00
|
|
|
|
2023-05-20 17:01:42 +02:00
|
|
|
power = dl->radius * dl->radius;
|
|
|
|
if (power >= d) {
|
|
|
|
d = dl->radius * 7500.0 / d;
|
|
|
|
VectorMA(vLight, d, dl->color, vLight);
|
2023-05-08 14:33:37 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-05-20 17:01:42 +02:00
|
|
|
if (tr.overbrightShift)
|
|
|
|
{
|
|
|
|
vLight[0] = tr.overbrightMult * vLight[0];
|
|
|
|
vLight[1] = tr.overbrightMult * vLight[1];
|
|
|
|
vLight[2] = tr.overbrightMult * vLight[2];
|
2023-05-08 14:33:37 +02:00
|
|
|
}
|
|
|
|
|
2023-05-20 17:01:42 +02:00
|
|
|
// normalize
|
|
|
|
if (vLight[0] < 255.0 || vLight[1] < 255.0 || vLight[2] < 255.0) {
|
|
|
|
float scale = 255.0 / fmin(vLight[0], fmin(vLight[1], vLight[2]));
|
|
|
|
VectorScale(vLight, scale, vLight);
|
2023-05-08 14:33:37 +02:00
|
|
|
}
|
|
|
|
|
2023-05-20 17:01:42 +02:00
|
|
|
// clamp ambient
|
|
|
|
for (i = 0; i < 3; i++) {
|
|
|
|
if (vLight[i] > tr.identityLightByte) {
|
|
|
|
vLight[i] = tr.identityLightByte;
|
|
|
|
}
|
2023-05-08 14:33:37 +02:00
|
|
|
}
|
|
|
|
|
2023-05-20 17:01:42 +02:00
|
|
|
// save out the byte packet version
|
|
|
|
((byte*)&iColor)[0] = myftol(vLight[0]);
|
|
|
|
((byte*)&iColor)[1] = myftol(vLight[1]);
|
|
|
|
((byte*)&iColor)[2] = myftol(vLight[2]);
|
|
|
|
((byte*)&iColor)[3] = 0xff;
|
2023-05-08 14:33:37 +02:00
|
|
|
|
2023-05-20 17:01:42 +02:00
|
|
|
return iColor;
|
2023-05-08 14:33:37 +02:00
|
|
|
|
2023-05-20 17:01:42 +02:00
|
|
|
#if 0
|
2023-05-08 14:33:37 +02:00
|
|
|
int i;
|
2023-05-20 17:01:42 +02:00
|
|
|
dlight_t* dl;
|
2023-05-08 14:33:37 +02:00
|
|
|
float power;
|
|
|
|
vec3_t dir;
|
|
|
|
float d;
|
|
|
|
vec3_t lightDir;
|
|
|
|
vec3_t lightOrigin;
|
2023-05-20 17:01:42 +02:00
|
|
|
int ambientlightInt = 0;
|
|
|
|
trRefEntity_t *ent = backEnd.currentEntity;
|
|
|
|
trRefdef_t *refdef = &backEnd.refdef;
|
2023-05-08 14:33:37 +02:00
|
|
|
|
|
|
|
//
|
|
|
|
// trace a sample point down to find ambient light
|
|
|
|
//
|
2023-05-20 17:01:42 +02:00
|
|
|
if (ent->e.renderfx & RF_LIGHTING_ORIGIN) {
|
2023-05-08 14:33:37 +02:00
|
|
|
// seperate lightOrigins are needed so an object that is
|
|
|
|
// sinking into the ground can still be lit, and so
|
|
|
|
// multi-part models can be lit identically
|
2023-05-20 17:01:42 +02:00
|
|
|
VectorCopy(ent->e.lightingOrigin, lightOrigin);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
VectorCopy(ent->e.origin, lightOrigin);
|
2023-05-08 14:33:37 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// if NOWORLDMODEL, only use dynamic lights (menu system, etc)
|
2023-05-20 17:01:42 +02:00
|
|
|
if (!(refdef->rdflags & RDF_NOWORLDMODEL)
|
|
|
|
&& tr.world->lightGridData) {
|
|
|
|
R_SetupEntityLightingGrid(ent);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
ent->ambientLight[0] = ent->ambientLight[1] =
|
2023-05-08 14:33:37 +02:00
|
|
|
ent->ambientLight[2] = tr.identityLight * 150;
|
2023-05-20 17:01:42 +02:00
|
|
|
ent->directedLight[0] = ent->directedLight[1] =
|
2023-05-08 14:33:37 +02:00
|
|
|
ent->directedLight[2] = tr.identityLight * 150;
|
2023-05-20 17:01:42 +02:00
|
|
|
VectorCopy(tr.sunDirection, ent->lightDir);
|
2023-05-08 14:33:37 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// bonus items and view weapons have a fixed minimum add
|
2023-05-20 17:01:42 +02:00
|
|
|
if (1 /* ent->e.renderfx & RF_MINLIGHT */) {
|
2023-05-08 14:33:37 +02:00
|
|
|
// give everything a minimum light add
|
|
|
|
ent->ambientLight[0] += tr.identityLight * 32;
|
|
|
|
ent->ambientLight[1] += tr.identityLight * 32;
|
|
|
|
ent->ambientLight[2] += tr.identityLight * 32;
|
|
|
|
}
|
|
|
|
|
|
|
|
//
|
|
|
|
// modify the light by dynamic lights
|
|
|
|
//
|
2023-05-20 17:01:42 +02:00
|
|
|
d = VectorLength(ent->directedLight);
|
|
|
|
VectorScale(ent->lightDir, d, lightDir);
|
2023-05-08 14:33:37 +02:00
|
|
|
|
2023-05-20 17:01:42 +02:00
|
|
|
for (i = 0; i < refdef->num_dlights; i++) {
|
2023-05-08 14:33:37 +02:00
|
|
|
dl = &refdef->dlights[i];
|
2023-05-20 17:01:42 +02:00
|
|
|
VectorSubtract(dl->origin, lightOrigin, dir);
|
|
|
|
d = VectorNormalize(dir);
|
2023-05-08 14:33:37 +02:00
|
|
|
|
2023-05-20 17:01:42 +02:00
|
|
|
power = DLIGHT_AT_RADIUS * (dl->radius * dl->radius);
|
|
|
|
if (d < DLIGHT_MINIMUM_RADIUS) {
|
2023-05-08 14:33:37 +02:00
|
|
|
d = DLIGHT_MINIMUM_RADIUS;
|
|
|
|
}
|
2023-05-20 17:01:42 +02:00
|
|
|
d = power / (d * d);
|
2023-05-08 14:33:37 +02:00
|
|
|
|
2023-05-20 17:01:42 +02:00
|
|
|
VectorMA(ent->directedLight, d, dl->color, ent->directedLight);
|
|
|
|
VectorMA(lightDir, d, dir, lightDir);
|
2023-05-08 14:33:37 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// clamp ambient
|
2023-05-20 17:01:42 +02:00
|
|
|
for (i = 0; i < 3; i++) {
|
|
|
|
if (ent->ambientLight[i] > tr.identityLightByte) {
|
2023-05-08 14:33:37 +02:00
|
|
|
ent->ambientLight[i] = tr.identityLightByte;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// save out the byte packet version
|
2023-05-20 17:01:42 +02:00
|
|
|
((byte*)&ambientlightInt)[0] = myftol(ent->ambientLight[0]);
|
|
|
|
((byte*)&ambientlightInt)[1] = myftol(ent->ambientLight[1]);
|
|
|
|
((byte*)&ambientlightInt)[2] = myftol(ent->ambientLight[2]);
|
|
|
|
((byte*)&ambientlightInt)[3] = 0xff;
|
|
|
|
|
2023-05-08 14:33:37 +02:00
|
|
|
// transform the direction to local space
|
2023-05-20 17:01:42 +02:00
|
|
|
VectorNormalize(lightDir);
|
|
|
|
ent->lightDir[0] = DotProduct(lightDir, ent->e.axis[0]);
|
|
|
|
ent->lightDir[1] = DotProduct(lightDir, ent->e.axis[1]);
|
|
|
|
ent->lightDir[2] = DotProduct(lightDir, ent->e.axis[2]);
|
|
|
|
|
|
|
|
return ambientlightInt;
|
|
|
|
#endif
|
|
|
|
// FIXME: unimplemented
|
|
|
|
}
|
|
|
|
|
|
|
|
void RB_SetupEntityGridLighting()
|
|
|
|
{
|
|
|
|
trRefEntity_t* ent;
|
|
|
|
int iColor;
|
|
|
|
|
|
|
|
if (backEnd.currentEntity->bLightGridCalculated) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (ent = backEnd.currentEntity; ent->e.parentEntity != ENTITYNUM_NONE; ent = &backEnd.refdef.entities[ent->e.parentEntity])
|
|
|
|
{
|
|
|
|
trRefEntity_t* newref = &backEnd.refdef.entities[ent->e.parentEntity];
|
|
|
|
if (newref == ent) {
|
|
|
|
assert(!"backEnd.refdef.entities[ent->e.parentEntity] refers to itself\n");
|
|
|
|
iColor = newref->iGridLighting;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (newref->bLightGridCalculated) {
|
|
|
|
iColor = newref->iGridLighting;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (ent->e.parentEntity == ENTITYNUM_NONE) {
|
|
|
|
iColor = RB_GetEntityGridLighting();
|
|
|
|
}
|
|
|
|
|
|
|
|
ent = backEnd.currentEntity;
|
|
|
|
for (;;)
|
|
|
|
{
|
|
|
|
ent->bLightGridCalculated = 1;
|
|
|
|
ent->iGridLighting = iColor;
|
|
|
|
if (ent->e.parentEntity == ENTITYNUM_NONE) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (ent == &backEnd.refdef.entities[ent->e.parentEntity]) {
|
|
|
|
assert(!"backEnd.refdef.entities[ent->e.parentEntity] refers to itself\n");
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
ent = &backEnd.refdef.entities[ent->e.parentEntity];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void RB_SetupStaticModelGridLighting(trRefdef_t* refdef, cStaticModelUnpacked_t* ent, const vec3_t lightOrigin)
|
|
|
|
{
|
2023-05-21 02:40:12 +02:00
|
|
|
int iColor;
|
|
|
|
int i;
|
|
|
|
dlight_t* dl;
|
|
|
|
float power;
|
|
|
|
vec3_t vLight;
|
|
|
|
vec3_t dir;
|
|
|
|
float d;
|
|
|
|
|
|
|
|
if (ent->bLightGridCalculated) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
ent->bLightGridCalculated = qtrue;
|
|
|
|
|
|
|
|
if (!(refdef->rdflags & RDF_NOWORLDMODEL) && tr.world->lightGridData) {
|
|
|
|
R_GetLightingGridValue(backEnd.currentSphere->traceOrigin, vLight);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
vLight[0] = vLight[1] = vLight[2] = tr.identityLight * 150.0;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (i = 0; i < refdef->num_dlights; i++) {
|
|
|
|
dl = &refdef->dlights[i];
|
|
|
|
VectorSubtract(dl->origin, lightOrigin, dir);
|
|
|
|
d = VectorLengthSquared(dir);
|
|
|
|
|
|
|
|
power = dl->radius * dl->radius;
|
|
|
|
if (power >= d) {
|
|
|
|
d = dl->radius * 7500.0 / d;
|
|
|
|
VectorMA(vLight, d, dl->color, vLight);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (tr.overbrightShift)
|
|
|
|
{
|
|
|
|
vLight[0] = tr.overbrightMult * vLight[0];
|
|
|
|
vLight[1] = tr.overbrightMult * vLight[1];
|
|
|
|
vLight[2] = tr.overbrightMult * vLight[2];
|
|
|
|
}
|
|
|
|
|
|
|
|
// normalize
|
|
|
|
if (vLight[0] < 255.0 || vLight[1] < 255.0 || vLight[2] < 255.0) {
|
|
|
|
float scale = 255.0 / fmin(vLight[0], fmin(vLight[1], vLight[2]));
|
|
|
|
VectorScale(vLight, scale, vLight);
|
|
|
|
}
|
|
|
|
|
|
|
|
// clamp ambient
|
|
|
|
for (i = 0; i < 3; i++) {
|
|
|
|
if (vLight[i] > tr.identityLightByte) {
|
|
|
|
vLight[i] = tr.identityLightByte;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// save out the byte packet version
|
|
|
|
((byte*)&ent->iGridLighting)[0] = myftol(vLight[0]);
|
|
|
|
((byte*)&ent->iGridLighting)[1] = myftol(vLight[1]);
|
|
|
|
((byte*)&ent->iGridLighting)[2] = myftol(vLight[2]);
|
|
|
|
((byte*)&ent->iGridLighting)[3] = 0xff;
|
2023-05-08 14:33:37 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
2023-05-20 17:01:42 +02:00
|
|
|
=============================================================================
|
|
|
|
|
|
|
|
LIGHT SAMPLING
|
|
|
|
|
|
|
|
=============================================================================
|
2023-05-08 14:33:37 +02:00
|
|
|
*/
|
2023-05-20 17:01:42 +02:00
|
|
|
|
|
|
|
extern cvar_t *r_ambientScale;
|
|
|
|
extern cvar_t *r_directedScale;
|
|
|
|
|
|
|
|
/*
|
|
|
|
===============
|
|
|
|
LogLight
|
|
|
|
===============
|
|
|
|
*/
|
|
|
|
static void LogLight( trRefEntity_t *ent ) {
|
|
|
|
int max1, max2;
|
|
|
|
|
|
|
|
if ( !(ent->e.renderfx & RF_FIRST_PERSON ) ) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
max1 = ent->ambientLight[0];
|
|
|
|
if ( ent->ambientLight[1] > max1 ) {
|
|
|
|
max1 = ent->ambientLight[1];
|
|
|
|
} else if ( ent->ambientLight[2] > max1 ) {
|
|
|
|
max1 = ent->ambientLight[2];
|
|
|
|
}
|
|
|
|
|
|
|
|
max2 = ent->directedLight[0];
|
|
|
|
if ( ent->directedLight[1] > max2 ) {
|
|
|
|
max2 = ent->directedLight[1];
|
|
|
|
} else if ( ent->directedLight[2] > max2 ) {
|
|
|
|
max2 = ent->directedLight[2];
|
|
|
|
}
|
|
|
|
|
|
|
|
ri.Printf( PRINT_ALL, "amb:%i dir:%i\n", max1, max2 );
|
2023-05-08 14:33:37 +02:00
|
|
|
}
|
2023-05-19 00:29:13 +02:00
|
|
|
|
2023-05-19 02:11:28 +02:00
|
|
|
void R_ClearRealDlights() {
|
|
|
|
memset(dli.allocated, 0, sizeof(dli.allocated));
|
|
|
|
dli.dlightMap = 0;
|
|
|
|
}
|
|
|
|
|
2023-05-19 00:29:13 +02:00
|
|
|
void R_UploadDlights() {
|
2023-05-19 02:11:28 +02:00
|
|
|
int i, h;
|
|
|
|
|
|
|
|
if (!tr.pc.c_dlightSurfaces) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
h = 0;
|
|
|
|
for (i = 0; i < 128; ++i)
|
|
|
|
{
|
|
|
|
if (h < dli.allocated[i]) {
|
|
|
|
h = dli.allocated[i];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (h)
|
|
|
|
{
|
|
|
|
if (h > 128) {
|
|
|
|
ri.Error(ERR_DROP, "R_UploadDlights: bad allocated height");
|
|
|
|
}
|
|
|
|
|
|
|
|
GL_Bind(tr.dlightImages[dli.dlightMap]);
|
|
|
|
qglTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 128, h, GL_RGBA, GL_UNSIGNED_BYTE, dli.lightmap_buffer);
|
|
|
|
|
|
|
|
tr.pc.c_dlightMaps++;
|
|
|
|
memset(dli.allocated, 0, sizeof(dli.allocated));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
qboolean R_AllocLMBlock(int w, int h, int* x, int* y) {
|
|
|
|
int i, j;
|
|
|
|
int best, best2;
|
|
|
|
|
|
|
|
for (;;)
|
|
|
|
{
|
|
|
|
best = 128;
|
|
|
|
for (i = 0; i < 128 - w; i++)
|
|
|
|
{
|
|
|
|
best2 = 0;
|
|
|
|
|
|
|
|
for (j = 0; j < w && dli.allocated[i] < best; j++)
|
|
|
|
{
|
|
|
|
if (best2 < dli.allocated[i]) {
|
|
|
|
best2 = dli.allocated[i];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (j == w)
|
|
|
|
{
|
|
|
|
*x = i;
|
|
|
|
*y = best2;
|
|
|
|
best = best2;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (h + best <= 128) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (dli.dlightMap == 14) {
|
|
|
|
return qfalse;
|
|
|
|
}
|
|
|
|
|
|
|
|
R_UploadDlights();
|
|
|
|
dli.dlightMap++;
|
|
|
|
}
|
|
|
|
|
|
|
|
return qtrue;
|
2023-05-19 00:29:13 +02:00
|
|
|
}
|