[scene] Move dynamic lights into the scene ECS

While the insertion of dlights into the BSP might wind up being overly
expensive, the automatic management of the component pool cleans up the
various loops in the renderers.

Unfortunately, (current bug) lights on entities cause the entity to
disappear due to how the entity queue system works, and the doubled
efrag chain causes crashes when changing maps, meaning lights should be
on their own entities, not additional components on entities with
visible models.

Also, the vulkan renderer segfaults on dlights (fix incoming, along with
shadows for dlights).
This commit is contained in:
Bill Currie 2023-08-04 14:56:16 +09:00
parent 7537cb8d1c
commit 35ec2ebb4c
34 changed files with 405 additions and 444 deletions

View file

@ -96,22 +96,16 @@ typedef struct subpic_s {
// dynamic lights ===========================================================
typedef struct dlight_s
{
int key; // so entities can reuse same entry
vec3_t origin;
typedef struct dlight_s {
vec4f_t origin;
vec4f_t color;
float radius;
float die; // stop lighting after this time
float decay; // drop this each second
float minlight; // don't add when contributing less
float color[4];
} dlight_t;
extern dlight_t *r_dlights;
extern unsigned int r_maxdlights;
typedef struct
{
typedef struct {
int length;
char map[MAX_STYLESTRING];
char average;
@ -180,8 +174,6 @@ void R_LoadModule (struct vid_internal_s *vid_internal);
struct progs_s;
void R_Progs_Init (struct progs_s *pr);
dlight_t *R_AllocDlight (int key);
void R_DecayLights (double frametime);
void Fog_Update (float density, float red, float green, float blue,
float time);
struct plitem_s;

View file

@ -68,5 +68,8 @@ void Light_ClearLights (lightingdata_t *ldata);
void Light_AddLight (lightingdata_t *ldata, const light_t *light,
uint32_t style);
void Light_EnableSun (lightingdata_t *ldata);
void Light_DecayLights (lightingdata_t *ldata, float frametime,
double realtime);
void Light_LinkLight (lightingdata_t *ldata, uint32_t entid);
#endif//__QF_scene_light_h

View file

@ -49,6 +49,8 @@ enum scene_components {
scene_old_origin, //XXX FIXME XXX should not be here
scene_colormap,
scene_dynlight,
scene_light,
scene_efrags,
scene_lightstyle,

View file

@ -35,13 +35,13 @@
struct entity_s;
struct entity_state_s;
void CL_NewDlight (int key, vec4f_t org, int effects, byte glow_size,
byte glow_color, double time);
void CL_ModelEffects (struct entity_s ent, int num, int glow_color,
void CL_NewDlight (struct entity_s ent, vec4f_t org, int effects,
byte glow_size, byte glow_color, double time);
void CL_ModelEffects (struct entity_s ent, int glow_color,
double time);
void CL_EntityEffects (int num, struct entity_s ent,
struct entity_state_s *state, double time);
void CL_MuzzleFlash (vec4f_t position, vec4f_t fv, float zoffset, int num,
double time);
void CL_EntityEffects (struct entity_s ent, struct entity_state_s *state,
double time);
void CL_MuzzleFlash (struct entity_s ent, vec4f_t position, vec4f_t fv,
float zoffset, double time);
#endif//__client_effects_h

View file

@ -45,7 +45,6 @@ typedef enum {
struct entity_s;
void R_MaxDlightsCheck (int max_dlights);
void R_Particles_Init_Cvars (void);
void R_InitBubble (void);

View file

@ -77,9 +77,6 @@ void R_LoadSkys (const char *);
void R_ClearEfrags (void);
int R_FindNearLights (vec4f_t pos, int count, dlight_t **lights);
dlight_t *R_AllocDlight (int key);
void R_DecayLights (double frametime);
void R_ClearDlights (void);
int R_InitGraphTextures (int base);

View file

@ -42,6 +42,7 @@
#include "QF/plugin/vid_render.h" //FIXME
#include "QF/scene/entity.h"
#include "QF/scene/light.h"
#include "QF/scene/scene.h"
#include "client/entities.h"
@ -50,15 +51,13 @@
#include "client/world.h"
void
CL_NewDlight (int key, vec4f_t org, int effects, byte glow_size,
CL_NewDlight (entity_t ent, vec4f_t org, int effects, byte glow_size,
byte glow_color, double time)
{
float radius;
dlight_t *dl;
static quat_t normal = {0.4, 0.2, 0.05, 0.7};
static quat_t red = {0.5, 0.05, 0.05, 0.7};
static quat_t blue = {0.05, 0.05, 0.5, 0.7};
static quat_t purple = {0.5, 0.05, 0.5, 0.7};
static vec4f_t normal = {0.4, 0.2, 0.05, 0.7};
static vec4f_t red = {0.5, 0.05, 0.05, 0.7};
static vec4f_t blue = {0.05, 0.05, 0.5, 0.7};
static vec4f_t purple = {0.5, 0.05, 0.5, 0.7};
effects &= EF_BLUE | EF_RED | EF_BRIGHTLIGHT | EF_DIMLIGHT;
if (!effects) {
@ -66,60 +65,56 @@ CL_NewDlight (int key, vec4f_t org, int effects, byte glow_size,
return;
}
dl = R_AllocDlight (key);
if (!dl)
return;
VectorCopy (org, dl->origin);
float radius = 0;
float die = time + 0.1;
vec4f_t color = normal;
if (effects & (EF_BLUE | EF_RED | EF_BRIGHTLIGHT | EF_DIMLIGHT)) {
radius = 200 + (rand () & 31);
if (effects & EF_BRIGHTLIGHT) {
radius += 200;
dl->origin[2] += 16;
org[2] += 16;
}
if (effects & EF_DIMLIGHT)
if (effects & ~EF_DIMLIGHT)
radius -= 100;
dl->radius = radius;
dl->die = time + 0.1;
radius = radius;
switch (effects & (EF_RED | EF_BLUE)) {
case EF_RED | EF_BLUE:
QuatCopy (purple, dl->color);
break;
case EF_RED:
QuatCopy (red, dl->color);
break;
case EF_BLUE:
QuatCopy (blue, dl->color);
break;
default:
QuatCopy (normal, dl->color);
break;
case EF_RED | EF_BLUE: color = purple; break;
case EF_RED: color = red; break;
case EF_BLUE: color = blue; break;
default: color = normal; break;
}
}
if (glow_size) {
dl->radius += glow_size < 128 ? glow_size * 8.0 :
(glow_size - 256) * 8.0;
dl->die = time + 0.1;
radius += glow_size < 128 ? glow_size * 8.0 : (glow_size - 256) * 8.0;
if (glow_color) {
if (glow_color == 255) {
dl->color[0] = dl->color[1] = dl->color[2] = 1.0;
color = (vec4f_t) { 1, 1, 1, 0.7 };
} else {
byte *tempcolor;
tempcolor = (byte *) &d_8to24table[glow_color];
VectorScale (tempcolor, 1 / 255.0, dl->color);
VectorScale (tempcolor, 1 / 255.0, color);
color[3] = 0.7;
}
}
}
Ent_SetComponent (ent.id, scene_dynlight, ent.reg, &(dlight_t) {
.origin = org,
.color = color,
.radius = radius,
.die = die,
});
Light_LinkLight (cl_world.scene->lights, ent.id);
}
void
CL_ModelEffects (entity_t ent, int num, int glow_color, double time)
CL_ModelEffects (entity_t ent, int glow_color, double time)
{
dlight_t *dl;
transform_t transform = Entity_Transform (ent);
renderer_t *renderer = Ent_GetComponent (ent.id, scene_renderer, cl_world.scene->reg);
model_t *model = renderer->model;
@ -128,15 +123,14 @@ CL_ModelEffects (entity_t ent, int num, int glow_color, double time)
// add automatic particle trails
if (model->flags & EF_ROCKET) {
dl = R_AllocDlight (num);
if (dl) {
VectorCopy (ent_origin, dl->origin);
dl->radius = 200.0;
dl->die = time + 0.1;
Ent_SetComponent (ent.id, scene_dynlight, ent.reg, &(dlight_t) {
.origin = ent_origin,
//FIXME VectorCopy (r_firecolor, dl->color);
VectorSet (0.9, 0.7, 0.0, dl->color);
dl->color[3] = 0.7;
}
.color = { 0.9, 0.7, 0.0, 0.7 },
.radius = 200,
.die = time + 0.1,
});
Light_LinkLight (cl_world.scene->lights, ent.id);
clp_funcs->RocketTrail (*old_origin, ent_origin);
} else if (model->flags & EF_GRENADE)
clp_funcs->GrenadeTrail (*old_origin, ent_origin);
@ -155,26 +149,21 @@ CL_ModelEffects (entity_t ent, int num, int glow_color, double time)
}
void
CL_MuzzleFlash (vec4f_t position, vec4f_t fv, float zoffset, int num,
CL_MuzzleFlash (entity_t ent, vec4f_t position, vec4f_t fv, float zoffset,
double time)
{
dlight_t *dl = R_AllocDlight (num);
if (dl) {
position += 18 * fv;
VectorCopy (position, dl->origin);
dl->origin[2] += zoffset;
dl->radius = 200 + (rand () & 31);
dl->die = time + 0.1;
dl->minlight = 32;
dl->color[0] = 0.2;
dl->color[1] = 0.1;
dl->color[2] = 0.05;
dl->color[3] = 0.7;
}
Ent_SetComponent (ent.id, scene_dynlight, ent.reg, &(dlight_t) {
.origin = position + 18 * fv + zoffset * (vec4f_t) {0, 0, 1, 0},
.color = { 0.2, 0.1, 0.05, 0.7 },
.radius = 200 + (rand () & 31),
.die = time + 0.1,
.minlight = 32,
});
Light_LinkLight (cl_world.scene->lights, ent.id);
}
void
CL_EntityEffects (int num, entity_t ent, entity_state_t *state, double time)
CL_EntityEffects (entity_t ent, entity_state_t *state, double time)
{
transform_t transform = Entity_Transform (ent);
vec4f_t position = Transform_GetWorldPosition (transform);
@ -182,6 +171,6 @@ CL_EntityEffects (int num, entity_t ent, entity_state_t *state, double time)
clp_funcs->EntityParticles (position);
if (state->effects & EF_MUZZLEFLASH) {
vec4f_t fv = Transform_Forward (transform);
CL_MuzzleFlash (position, fv, 16, num, time);
CL_MuzzleFlash (ent, position, fv, 16, time);
}
}

View file

@ -38,6 +38,7 @@
# include <strings.h>
#endif
#include "QF/darray.h"
#include "QF/msg.h"
#include "QF/progs.h" // for PR_RESMAP
#include "QF/quakefs.h"
@ -47,6 +48,7 @@
#include "QF/plugin/vid_render.h" //FIXME
//
#include "QF/scene/entity.h"
#include "QF/scene/light.h"
#include "QF/scene/scene.h"
#include "client/effects.h"
@ -325,15 +327,55 @@ CL_ParseBeam (qmsg_t *net_message, model_t *m, double time, TEntContext_t *ctx)
}
}
typedef struct tempent_s DARRAY_TYPE (entity_t) tempent_t;
static tempent_t light_entities = DARRAY_STATIC_INIT (32);
static void
free_stale_entities (void)
{
size_t i, j;
for (i = 0, j = 0; i < light_entities.size; i++) {
auto ent = light_entities.a[i];
if (Ent_HasComponent (ent.id, scene_dynlight, ent.reg)) {
if (j != i) {
light_entities.a[j] = ent;
}
j++;
} else {
ECS_DelEntity (ent.reg, ent.id);
}
}
light_entities.size = j;
}
static void
spawn_light (vec4f_t position, vec4f_t color, float radius, float die,
float decay)
{
entity_t ent = {
.reg = cl_world.scene->reg,
.id = ECS_NewEntity (cl_world.scene->reg),
};
DARRAY_APPEND (&light_entities, ent);
Ent_SetComponent (ent.id, scene_dynlight, ent.reg, &(dlight_t) {
.origin = position,
.color = color,
.radius = radius,
.die = die,
.decay = decay,
});
Light_LinkLight (cl_world.scene->lights, ent.id);
}
static void
parse_tent (qmsg_t *net_message, double time, TEntContext_t *ctx,
TE_Effect type)
{
dlight_t *dl;
tent_obj_t *to;
explosion_t *ex;
int colorStart, colorLength;
quat_t color;
vec4f_t color;
vec4f_t position = {0, 0, 0, 1};
int count;
const char *name;
@ -369,23 +411,16 @@ parse_tent (qmsg_t *net_message, double time, TEntContext_t *ctx,
renderer_t *renderer = Ent_GetComponent (ex->tent->ent.id, scene_renderer, cl_world.scene->reg);
renderer->model = cl_spr_explod;
Transform_SetLocalPosition (transform, position);
color = (vec4f_t) {0.86, 0.31, 0.24, 0.7};
goto TE_Explosion_no_sprite;
case TE_Explosion:
MSG_ReadCoordV (net_message, (vec_t*)&position);//FIXME
color = (vec4f_t) {1.0, 0.5, 0.25, 0.7};
TE_Explosion_no_sprite:
// particles
clp_funcs->ParticleExplosion (position);
// light
dl = R_AllocDlight (0);
if (dl) {
VectorCopy (position, dl->origin);
dl->radius = 350;
dl->die = time + 0.5;
dl->decay = 300;
QuatSet (0.86, 0.31, 0.24, 0.7, dl->color);
//FIXME? nq: QuatSet (1.0, 0.5, 0.25, 0.7, dl->color);
}
spawn_light (position, color, 250, time + 0.5, 300);
// sound
S_StartSound (-1, 0, cl_sfx_r_exp3, position, 1, 1);
@ -396,32 +431,20 @@ TE_Explosion_no_sprite:
colorLength = MSG_ReadByte (net_message);
S_StartSound (-1, 0, cl_sfx_r_exp3, position, 1, 1);
clp_funcs->ParticleExplosion2 (position, colorStart, colorLength);
dl = R_AllocDlight (0);
if (!dl)
break;
VectorCopy (position, dl->origin);
dl->radius = 350;
dl->die = time + 0.5;
dl->decay = 300;
colorStart = (colorStart + (rand () % colorLength)) * 3;
VectorScale (&r_data->vid->palette[colorStart], 1.0 / 255.0,
dl->color);
dl->color[3] = 0.7;
VectorScale (&r_data->vid->palette[colorStart], 1.0 / 255.0, color);
color[3] = 0.7;
spawn_light (position, color, 350, time + 0.5, 300);
break;
case TE_Explosion3:
MSG_ReadCoordV (net_message, (vec_t*)&position);//FIXME
MSG_ReadCoordV (net_message, color); // OUCH!
MSG_ReadCoordV (net_message, (vec_t*)&color); //FIXME OUCH!
color[3] = 0.7;
clp_funcs->ParticleExplosion (position);
S_StartSound (-1, 0, cl_sfx_r_exp3, position, 1, 1);
dl = R_AllocDlight (0);
if (dl) {
VectorCopy (position, dl->origin);
dl->radius = 350;
dl->die = time + 0.5;
dl->decay = 300;
QuatCopy (color, dl->color);
}
spawn_light (position, color, 350, time + 0.5, 300);
break;
case TE_Gunshot1:
MSG_ReadCoordV (net_message, (vec_t*)&position);//FIXME
@ -457,15 +480,8 @@ TE_Explosion_no_sprite:
case TE_LightningBlood:
MSG_ReadCoordV (net_message, (vec_t*)&position);//FIXME
// light
dl = R_AllocDlight (0);
if (dl) {
VectorCopy (position, dl->origin);
dl->radius = 150;
dl->die = time + 0.1;
dl->decay = 200;
QuatSet (0.25, 0.40, 0.65, 1, dl->color);
}
color = (vec4f_t) {0.25, 0.40, 0.65, 1};
spawn_light (position, color, 150, time + 0.1, 200);
clp_funcs->LightningBloodEffect (position);
break;
@ -650,6 +666,7 @@ CL_UpdateExplosions (double time, TEntContext_t *ctx)
void
CL_UpdateTEnts (double time, TEntContext_t *ctx)
{
free_stale_entities ();
CL_UpdateBeams (time, ctx);
CL_UpdateExplosions (time, ctx);
}

View file

@ -290,7 +290,6 @@ void
locs_draw (double time, vec4f_t simorg)
{
//FIXME custom ent rendering code would be nice
dlight_t *dl;
location_t *nearloc;
vec4f_t trueloc;
vec4f_t zero = {};
@ -298,16 +297,15 @@ locs_draw (double time, vec4f_t simorg)
nearloc = locs_find (simorg);
if (nearloc) {
dl = R_AllocDlight (4096);
if (dl) {
VectorCopy (nearloc->loc, dl->origin);
dl->radius = 200;
dl->die = time + 0.1;
dl->color[0] = 0;
dl->color[1] = 1;
dl->color[2] = 0;
dl->color[3] = 0.7;
}
#if 0//FIXME
Ent_SetComponent (ent.id, scene_dynlight, ent.reg, &(dlight_t) {
.origin = nearloc->loc,
.color = { 0, 1, 0, 0.7 },
.radius = 200,
.die = time + 0.1,
});
Light_LinkLight (cl_world.scene->lights, ent.id);
#endif
trueloc = nearloc->loc;
clp_funcs->Particle_New (pt_smokecloud, part_tex_smoke, trueloc, 2.0,
zero, time + 9.0, 254,

View file

@ -5,6 +5,7 @@
#include <string.h>
#include "QF/model.h"
#include "QF/render.h"
#include "QF/set.h"
#include "QF/scene/entity.h"
#include "QF/scene/light.h"
@ -84,20 +85,12 @@ test_light_leaf (const light_t *light, const mleaf_t *leaf)
return true;
}
void
Light_AddLight (lightingdata_t *ldata, const light_t *light, uint32_t style)
static void
link_light (lightingdata_t *ldata, const light_t *light, entity_t ent)
{
scene_t *scene = ldata->scene;
model_t *model = scene->worldmodel;
entity_t ent = {
.reg = scene->reg,
.id = ECS_NewEntity (scene->reg),
};
Ent_SetComponent (ent.id, scene_light, ent.reg, light);
Ent_SetComponent (ent.id, scene_lightstyle, ent.reg, &style);
set_t _pvs = SET_STATIC_INIT (model->brush.visleafs, alloca);
set_t *pvs = &_pvs;
uint32_t leafnum = ~0u;
@ -124,9 +117,51 @@ Light_AddLight (lightingdata_t *ldata, const light_t *light, uint32_t style)
lastlink = R_LinkEfrag (leaf, ent, mod_light, lastlink);
}
}
if (Ent_HasComponent (ent.id, scene_efrags, ent.reg)) {
Ent_RemoveComponent (ent.id, scene_efrags, ent.reg);
}
Ent_SetComponent (ent.id, scene_efrags, ent.reg, &efrags);
}
void
Light_AddLight (lightingdata_t *ldata, const light_t *light, uint32_t style)
{
scene_t *scene = ldata->scene;
entity_t ent = {
.reg = scene->reg,
.id = ECS_NewEntity (scene->reg),
};
Ent_SetComponent (ent.id, scene_light, ent.reg, light);
Ent_SetComponent (ent.id, scene_lightstyle, ent.reg, &style);
link_light (ldata, light, ent);
}
void
Light_LinkLight (lightingdata_t *ldata, uint32_t entid)
{
scene_t *scene = ldata->scene;
entity_t ent = {
.reg = scene->reg,
.id = entid,
};
dlight_t *dlight = Ent_GetComponent (ent.id, scene_dynlight, ent.reg);
if (!dlight) {
Sys_Error ("no dlight on entity to link");
}
light_t light = {
.color = dlight->color,
.position = dlight->origin,
.direction = {0, 0, 1, 1},
.attenuation = {0, 0, 1, 1/dlight->radius},
};
link_light (ldata, &light, ent);
}
void
Light_EnableSun (lightingdata_t *ldata)
{
@ -150,3 +185,25 @@ Light_EnableSun (lightingdata_t *ldata)
// can receive shadows from the sun
expand_pvs (ldata->sun_pvs, brush);
}
void
Light_DecayLights (lightingdata_t *ldata, float frametime, double realtime)
{
auto reg = ldata->scene->reg;
auto dlight_pool = &reg->comp_pools[scene_dynlight];
auto dlight_data = (dlight_t *) dlight_pool->data;
for (uint32_t i = 0; i < dlight_pool->count; i++) {
auto dlight = &dlight_data[i];
dlight->radius -= frametime * dlight->decay;
if (dlight->radius <= 0 || dlight->die < realtime) {
uint32_t ent = dlight_pool->dense[i];
Ent_RemoveComponent (ent, scene_dynlight, reg);
if (!Ent_HasComponent (ent, scene_efrags, reg)) {
Sys_Error ("dlight with no efrags");
}
Ent_RemoveComponent (ent, scene_efrags, reg);
i--;
}
}
}

View file

@ -153,6 +153,11 @@ static const component_t scene_components[scene_comp_count] = {
.name = "colormap",
},
[scene_dynlight] = {
.size = sizeof (dlight_t),
.name = "dyn_light",
},
[scene_light] = {
.size = sizeof (light_t),
.name = "light",

View file

@ -84,7 +84,7 @@ R_RenderDlight (dlight_t *light)
qfglBegin (GL_TRIANGLE_FAN);
qfglColor4fv (light->color);
qfglColor4fv ((vec_t*)&light->color);
VectorNormalize (v);
@ -109,9 +109,6 @@ R_RenderDlight (dlight_t *light)
void
gl_R_RenderDlights (void)
{
unsigned int i;
dlight_t *l;
if (!gl_dlight_polyblend)
return;
@ -120,11 +117,11 @@ gl_R_RenderDlights (void)
qfglBlendFunc (GL_ONE, GL_ONE);
qfglShadeModel (GL_SMOOTH);
l = r_dlights;
for (i = 0; i < r_maxdlights; i++, l++) {
if (l->die < vr_data.realtime || !l->radius)
continue;
R_RenderDlight (l);
auto dlight_pool = &r_refdef.registry->comp_pools[scene_dynlight];
auto dlight_data = (dlight_t *) dlight_pool->data;
for (uint32_t i = 0; i < dlight_pool->count; i++) {
auto dlight = &dlight_data[i];
R_RenderDlight (dlight);
}
if (!gl_dlight_smooth)

View file

@ -98,7 +98,7 @@ R_AddDynamicLights_1 (const vec4f_t *transform, msurface_t *surf)
unsigned int maxdist, maxdist2, maxdist3;
int smax, smax_bytes, tmax,
grey, s, t;
unsigned int lnum, td, i, j;
unsigned int td, j;
unsigned int sdtable[18];
unsigned int *bl;
vec3_t impact, local;
@ -113,16 +113,18 @@ R_AddDynamicLights_1 (const vec4f_t *transform, msurface_t *surf)
entorigin = transform[3];
}
for (lnum = 0; lnum < r_maxdlights; lnum++) {
if (!(surf->dlightbits[lnum / 32] & (1 << (lnum % 32))))
auto dlight_pool = &r_refdef.registry->comp_pools[scene_dynlight];
auto dlight_data = (dlight_t *) dlight_pool->data;
for (uint32_t i = 0; i < dlight_pool->count; i++) {
auto dlight = &dlight_data[i];
if (!(surf->dlightbits[i / 32] & (1 << (i % 32))))
continue; // not lit by this light
VectorSubtract (r_dlights[lnum].origin, entorigin, local);
VectorSubtract (dlight->origin, entorigin, local);
dist = DotProduct (local, surf->plane->normal) - surf->plane->dist;
if (dist > min (1024, r_dlights[lnum].radius))
if (dist > min (1024, dlight->radius))
continue;
VectorMultSub (r_dlights[lnum].origin, dist, surf->plane->normal,
impact);
VectorMultSub (dlight->origin, dist, surf->plane->normal, impact);
i = DotProduct (impact, surf->texinfo->vecs[0]) +
surf->texinfo->vecs[0][3] - surf->texturemins[0];
@ -136,7 +138,7 @@ R_AddDynamicLights_1 (const vec4f_t *transform, msurface_t *surf)
surf->texinfo->vecs[1][3] - surf->texturemins[1];
// for comparisons to minimum acceptable light
maxdist = (int) (r_dlights[lnum].radius * r_dlights[lnum].radius);
maxdist = (int) (dlight->radius * dlight->radius);
// clamp radius to avoid exceeding 8192 entry division table
if (maxdist > 1048576)
@ -144,8 +146,8 @@ R_AddDynamicLights_1 (const vec4f_t *transform, msurface_t *surf)
maxdist3 = maxdist - t;
// convert to 8.8 blocklights format
grey = (r_dlights[lnum].color[0] + r_dlights[lnum].color[1] +
r_dlights[lnum].color[2]) * maxdist / 3.0;
grey = (dlight->color[0] + dlight->color[1] + dlight->color[2])
* maxdist / 3.0;
bl = blocklights;
for (t = 0; t < tmax; t++, i -= 16) {
td = i * i;
@ -171,7 +173,7 @@ R_AddDynamicLights_3 (const vec4f_t *transform, msurface_t *surf)
unsigned int maxdist, maxdist2, maxdist3;
int smax, smax_bytes, tmax,
red, green, blue, s, t;
unsigned int lnum, td, i, j;
unsigned int td, j;
unsigned int sdtable[18];
unsigned int *bl;
vec3_t impact, local;
@ -185,18 +187,21 @@ R_AddDynamicLights_3 (const vec4f_t *transform, msurface_t *surf)
entorigin = transform[3];
}
for (lnum = 0; lnum < r_maxdlights; lnum++) {
if (!(surf->dlightbits[lnum / 32] & (1 << (lnum % 32))))
auto dlight_pool = &r_refdef.registry->comp_pools[scene_dynlight];
auto dlight_data = (dlight_t *) dlight_pool->data;
for (uint32_t k = 0; k < dlight_pool->count; k++) {
auto dlight = &dlight_data[k];
if (!(surf->dlightbits[k / 32] & (1 << (k % 32))))
continue; // not lit by this light
VectorSubtract (r_dlights[lnum].origin, entorigin, local);
VectorSubtract (dlight->origin, entorigin, local);
dist = DotProduct (local, surf->plane->normal) - surf->plane->dist;
if (dist > min (1024, r_dlights[lnum].radius))
if (dist > min (1024, dlight->radius))
continue;
VectorMultSub (r_dlights[lnum].origin, dist, surf->plane->normal,
impact);
VectorMultSub (dlight->origin, dist, surf->plane->normal, impact);
i = DotProduct (impact, surf->texinfo->vecs[0]) +
int i;
i = DotProduct (impact, surf->texinfo->vecs[0]) +
surf->texinfo->vecs[0][3] - surf->texturemins[0];
// reduce calculations
@ -204,11 +209,11 @@ R_AddDynamicLights_3 (const vec4f_t *transform, msurface_t *surf)
for (s = 0; s < smax; s++, i -= 16)
sdtable[s] = i * i + t;
i = DotProduct (impact, surf->texinfo->vecs[1]) +
i = DotProduct (impact, surf->texinfo->vecs[1]) +
surf->texinfo->vecs[1][3] - surf->texturemins[1];
// for comparisons to minimum acceptable light
maxdist = (int) (r_dlights[lnum].radius * r_dlights[lnum].radius);
maxdist = (int) (dlight->radius * dlight->radius);
// clamp radius to avoid exceeding 8192 entry division table
if (maxdist > 1048576)
@ -216,9 +221,9 @@ R_AddDynamicLights_3 (const vec4f_t *transform, msurface_t *surf)
maxdist3 = maxdist - t;
// convert to 8.8 blocklights format
red = r_dlights[lnum].color[0] * maxdist;
green = r_dlights[lnum].color[1] * maxdist;
blue = r_dlights[lnum].color[2] * maxdist;
red = dlight->color[0] * maxdist;
green = dlight->color[1] * maxdist;
blue = dlight->color[2] * maxdist;
bl = blocklights;
for (t = 0; t < tmax; t++, i -= 16) {
td = i * i;

View file

@ -408,9 +408,7 @@ gl_R_DrawAliasModel (entity_t e)
int gl_light, texture;
int fb_texture = 0, used_lights = 0;
bool is_fullbright = false;
unsigned lnum;
aliashdr_t *paliashdr;
dlight_t *l;
vec3_t dist, scale;
vec4f_t origin;
vert_order_t *vo;
@ -459,44 +457,45 @@ gl_R_DrawAliasModel (entity_t e)
}
if (gl_vector_light) {
for (l = r_dlights, lnum = 0; lnum < r_maxdlights; lnum++, l++) {
if (l->die >= vr_data.realtime) {
VectorSubtract (l->origin, origin, dist);
if ((d = DotProduct (dist, dist)) > // Out of range
((l->radius + radius) * (l->radius + radius))) {
continue;
}
if (used_lights >= gl_max_lights) {
// For solid lighting, multiply by 0.5 since it's cos
// 60 and 60 is a good guesstimate at the average
// incident angle. Seems to match vector lighting
// best, too.
VectorMultAdd (emission,
0.5 / ((d * 0.01 / l->radius) + 0.5),
l->color, emission);
continue;
}
VectorCopy (l->origin, position);
VectorCopy (l->color, color);
color[3] = 1.0;
gl_light = GL_LIGHT0 + used_lights;
qfglEnable (gl_light);
qfglLightfv (gl_light, GL_POSITION, position);
qfglLightfv (gl_light, GL_AMBIENT, color);
qfglLightfv (gl_light, GL_DIFFUSE, color);
qfglLightfv (gl_light, GL_SPECULAR, color);
// 0.01 is used here because it just seemed to match
// the bmodel lighting best. it's over r instead of r*r
// so that larger-radiused lights will be brighter
qfglLightf (gl_light, GL_QUADRATIC_ATTENUATION,
0.01 / (l->radius));
used_lights++;
auto dlight_pool = &r_refdef.registry->comp_pools[scene_dynlight];
auto dlight_data = (dlight_t *) dlight_pool->data;
for (uint32_t i = 0; i < dlight_pool->count; i++) {
auto l = &dlight_data[i];
VectorSubtract (l->origin, origin, dist);
if ((d = DotProduct (dist, dist)) > // Out of range
((l->radius + radius) * (l->radius + radius))) {
continue;
}
if (used_lights >= gl_max_lights) {
// For solid lighting, multiply by 0.5 since it's cos
// 60 and 60 is a good guesstimate at the average
// incident angle. Seems to match vector lighting
// best, too.
VectorMultAdd (emission,
0.5 / ((d * 0.01 / l->radius) + 0.5),
l->color, emission);
continue;
}
VectorCopy (l->origin, position);
VectorCopy (l->color, color);
color[3] = 1.0;
gl_light = GL_LIGHT0 + used_lights;
qfglEnable (gl_light);
qfglLightfv (gl_light, GL_POSITION, position);
qfglLightfv (gl_light, GL_AMBIENT, color);
qfglLightfv (gl_light, GL_DIFFUSE, color);
qfglLightfv (gl_light, GL_SPECULAR, color);
// 0.01 is used here because it just seemed to match
// the bmodel lighting best. it's over r instead of r*r
// so that larger-radiused lights will be brighter
qfglLightf (gl_light, GL_QUADRATIC_ATTENUATION,
0.01 / (l->radius));
used_lights++;
}
VectorAdd (ambientcolor, emission, emission);
@ -510,22 +509,23 @@ gl_R_DrawAliasModel (entity_t e)
} else {
VectorCopy (ambientcolor, emission);
for (l = r_dlights, lnum = 0; lnum < r_maxdlights; lnum++, l++) {
if (l->die >= vr_data.realtime) {
VectorSubtract (l->origin, origin, dist);
auto dlight_pool = &r_refdef.registry->comp_pools[scene_dynlight];
auto dlight_data = (dlight_t *) dlight_pool->data;
for (uint32_t i = 0; i < dlight_pool->count; i++) {
auto l = &dlight_data[i];
VectorSubtract (l->origin, origin, dist);
if ((d = DotProduct (dist, dist)) > (l->radius + radius) *
(l->radius + radius)) {
continue;
}
// For solid lighting, multiply by 0.5 since it's cos 60
// and 60 is a good guesstimate at the average incident
// angle. Seems to match vector lighting best, too.
VectorMultAdd (emission,
(0.5 / ((d * 0.01 / l->radius) + 0.5)),
l->color, emission);
if ((d = DotProduct (dist, dist)) > (l->radius + radius) *
(l->radius + radius)) {
continue;
}
// For solid lighting, multiply by 0.5 since it's cos 60
// and 60 is a good guesstimate at the average incident
// angle. Seems to match vector lighting best, too.
VectorMultAdd (emission,
(0.5 / ((d * 0.01 / l->radius) + 0.5)),
l->color, emission);
}
d = max (emission[0], max (emission[1], emission[2]));

View file

@ -280,6 +280,5 @@ void
gl_R_ClearState (void)
{
r_refdef.worldmodel = 0;
R_ClearDlights ();
R_ClearParticles ();
}

View file

@ -550,15 +550,14 @@ gl_R_DrawBrushModel (entity_t e)
// calculate dynamic lighting for bmodel if it's not an instanced model
if (brush->firstmodelsurface != 0 && r_dlight_lightmap) {
for (unsigned k = 0; k < r_maxdlights; k++) {
if ((r_dlights[k].die < vr_data.realtime)
|| (!r_dlights[k].radius))
continue;
auto dlight_pool = &r_refdef.registry->comp_pools[scene_dynlight];
auto dlight_data = (dlight_t *) dlight_pool->data;
for (uint32_t i = 0; i < dlight_pool->count; i++) {
auto dlight = &dlight_data[i];
vec4f_t lightorigin;
VectorSubtract (r_dlights[k].origin, worldMatrix[3], lightorigin);
VectorSubtract (dlight->origin, worldMatrix[3], lightorigin);
lightorigin[3] = 1;
R_RecursiveMarkLights (brush, lightorigin, &r_dlights[k], k,
R_RecursiveMarkLights (brush, lightorigin, dlight, i,
brush->hulls[0].firstclipnode);
}
}

View file

@ -152,7 +152,6 @@ static void
calc_lighting (entity_t ent, float *ambient, float *shadelight,
vec3_t lightvec)
{
unsigned i;
float add;
vec3_t dist;
int light;
@ -167,13 +166,14 @@ calc_lighting (entity_t ent, float *ambient, float *shadelight,
renderer->min_light) * 128);
*shadelight = *ambient;
for (i = 0; i < r_maxdlights; i++) {
if (r_dlights[i].die >= vr_data.realtime) {
VectorSubtract (entorigin, r_dlights[i].origin, dist);
add = r_dlights[i].radius - VectorLength (dist);
if (add > 0)
*ambient += add;
}
auto dlight_pool = &r_refdef.registry->comp_pools[scene_dynlight];
auto dlight_data = (dlight_t *) dlight_pool->data;
for (uint32_t i = 0; i < dlight_pool->count; i++) {
auto dlight = &dlight_data[i];
VectorSubtract (entorigin, dlight->origin, dist);
add = dlight->radius - VectorLength (dist);
if (add > 0)
*ambient += add;
}
if (*ambient >= 128)
*ambient = 128;

View file

@ -651,7 +651,6 @@ static void
R_DrawBrushModel (entity_t e)
{
float dot, radius;
unsigned k;
renderer_t *renderer = Ent_GetComponent (e.id, scene_renderer, e.reg);
model_t *model = renderer->model;
mod_brush_t *brush = &model->brush;
@ -695,16 +694,15 @@ R_DrawBrushModel (entity_t e)
}
// calculate dynamic lighting for bmodel if it's not an instanced model
auto dlight_pool = &r_refdef.registry->comp_pools[scene_dynlight];
auto dlight_data = (dlight_t *) dlight_pool->data;
if (brush->firstmodelsurface != 0 && r_dlight_lightmap) {
for (k = 0; k < r_maxdlights; k++) {
if ((r_dlights[k].die < vr_data.realtime)
|| (!r_dlights[k].radius))
continue;
for (uint32_t i = 0; i < dlight_pool->count; i++) {
auto dlight = &dlight_data[i];
vec4f_t lightorigin;
VectorSubtract (r_dlights[k].origin, mat[3], lightorigin);
VectorSubtract (dlight->origin, mat[3], lightorigin);
lightorigin[3] = 1;
R_RecursiveMarkLights (brush, lightorigin, &r_dlights[k], k,
R_RecursiveMarkLights (brush, lightorigin, dlight, i,
brush->hulls[0].firstclipnode);
}
}

View file

@ -246,7 +246,7 @@ glsl_R_DrawIQM (entity_t ent)
VectorSubtract (lights[i]->origin, entorigin, val);
val[3] = lights[i]->radius;
qfeglUniform4fv (l->position.location, 1, val);
qfeglUniform4fv (l->color.location, 1, lights[i]->color);
qfeglUniform4fv (l->color.location, 1, (vec_t*)&lights[i]->color);
}
for (; i < MAX_IQM_LIGHTS; i++) {
lightpar_t *l = &iqm_shader.lights[i];

View file

@ -66,7 +66,6 @@ void (*glsl_R_BuildLightMap) (const vec4f_t *transform, mod_brush_t *brush,
static void
R_AddDynamicLights_1 (const vec4f_t *transform, msurface_t *surf)
{
unsigned lnum;
int sd, td;
float dist, rad, minlight;
vec3_t impact, local, lightorigin;
@ -84,16 +83,19 @@ R_AddDynamicLights_1 (const vec4f_t *transform, msurface_t *surf)
entorigin = transform[3];
}
for (lnum = 0; lnum < r_maxdlights; lnum++) {
if (!(surf->dlightbits[lnum / 32] & (1 << (lnum % 32))))
auto dlight_pool = &r_refdef.registry->comp_pools[scene_dynlight];
auto dlight_data = (dlight_t *) dlight_pool->data;
for (uint32_t i = 0; i < dlight_pool->count; i++) {
auto dlight = &dlight_data[i];
if (!(surf->dlightbits[i / 32] & (1 << (i % 32))))
continue; // not lit by this light
VectorSubtract (r_dlights[lnum].origin, entorigin, lightorigin);
rad = r_dlights[lnum].radius;
VectorSubtract (dlight->origin, entorigin, lightorigin);
rad = dlight->radius;
dist = DotProduct (lightorigin, surf->plane->normal)
- surf->plane->dist;
rad -= fabs (dist);
minlight = r_dlights[lnum].minlight;
minlight = dlight->minlight;
if (rad < minlight)
continue;
minlight = rad - minlight;

View file

@ -223,6 +223,5 @@ void
glsl_R_ClearState (void)
{
r_refdef.worldmodel = 0;
R_ClearDlights ();
R_ClearParticles ();
}

View file

@ -153,15 +153,6 @@ static cvar_t r_dlight_lightmap_cvar = {
.flags = CVAR_ARCHIVE,
.value = { .type = &cexpr_int, .value = &r_dlight_lightmap },
};
int r_dlight_max;
static cvar_t r_dlight_max_cvar = {
.name = "r_dlight_max",
.description =
"Number of dynamic lights.",
.default_value = "32",
.flags = CVAR_ARCHIVE,
.value = { .type = &cexpr_int, .value = &r_dlight_max },
};
int r_drawentities;
static cvar_t r_drawentities_cvar = {
.name = "r_drawentities",
@ -568,12 +559,6 @@ viewsize_f (void *data, const cvar_t *cvar)
r_data->viewsize_callback (scr_viewsize);
}
static void
r_dlight_max_f (void *data, const cvar_t *cvar)
{
R_MaxDlightsCheck (r_dlight_max);
}
void
R_Init_Cvars (void)
{
@ -590,7 +575,6 @@ R_Init_Cvars (void)
Cvar_Register (&r_aliastransbase_cvar, 0, 0);
Cvar_Register (&r_clearcolor_cvar, 0, 0);
Cvar_Register (&r_dlight_lightmap_cvar, 0, 0);
Cvar_Register (&r_dlight_max_cvar, r_dlight_max_f, 0);
Cvar_Register (&r_drawentities_cvar, 0, 0);
Cvar_Register (&r_drawexplosions_cvar, 0, 0);
Cvar_Register (&r_drawviewmodel_cvar, 0, 0);

View file

@ -77,7 +77,6 @@ static void
R_shutdown (void *data)
{
R_ShutdownEfrags ();
R_MaxDlightsCheck (0); // frees memory
PI_UnloadPlugin (vidrendmodule);
}

View file

@ -46,7 +46,6 @@
#include "compat.h"
#include "r_internal.h"
dlight_t *r_dlights;
vec3_t ambientcolor;
unsigned int r_maxdlights;
@ -57,44 +56,42 @@ R_FindNearLights (vec4f_t pos, int count, dlight_t **lights)
{
float *scores = alloca (count * sizeof (float));
float score;
dlight_t *dl;
unsigned i;
int num = 0, j;
int num = 0;
vec3_t d;
dl = r_dlights;
for (i = 0; i < r_maxdlights; i++, dl++) {
if (dl->die < r_data->realtime || !dl->radius)
continue;
VectorSubtract (dl->origin, pos, d);
score = DotProduct (d, d) / dl->radius;
auto dlight_pool = &r_refdef.registry->comp_pools[scene_dynlight];
auto dlight_data = (dlight_t *) dlight_pool->data;
for (uint32_t i = 0; i < dlight_pool->count; i++) {
auto dlight = &dlight_data[i];
VectorSubtract (dlight->origin, pos, d);
score = DotProduct (d, d) / dlight->radius;
if (!num) {
scores[0] = score;
lights[0] = dl;
lights[0] = dlight;
num = 1;
} else if (score <= scores[0]) {
memmove (&lights[1], &lights[0],
(count - 1) * sizeof (dlight_t *));
memmove (&scores[1], &scores[0], (count - 1) * sizeof (float));
scores[0] = score;
lights[0] = dl;
lights[0] = dlight;
if (num < count)
num++;
} else if (score > scores[num - 1]) {
if (num < count) {
scores[num] = score;
lights[num] = dl;
lights[num] = dlight;
num++;
}
} else {
for (j = num - 1; j > 0; j--) {
for (int j = num - 1; j > 0; j--) {
if (score > scores[j - 1]) {
memmove (&lights[j + 1], &lights[j],
(count - j) * sizeof (dlight_t *));
memmove (&scores[j + 1], &scores[j],
(count - j) * sizeof (float));
scores[j] = score;
lights[j] = dl;
lights[j] = dlight;
if (num < count)
num++;
break;
@ -102,27 +99,11 @@ R_FindNearLights (vec4f_t pos, int count, dlight_t **lights)
}
}
}
for (j = num; j < count; j++)
for (int j = num; j < count; j++)
lights[j] = 0;
return num;
}
void
R_MaxDlightsCheck (int max_dlights)
{
r_maxdlights = bound (0, max_dlights, MAX_DLIGHTS);
if (r_dlights)
free (r_dlights);
r_dlights = 0;
if (r_maxdlights)
r_dlights = (dlight_t *) calloc (r_maxdlights, sizeof (dlight_t));
R_ClearDlights();
}
void
R_AnimateLight (void)
{
@ -320,23 +301,19 @@ R_MarkLights (vec4f_t lightorigin, dlight_t *light, int lightnum,
void
R_PushDlights (const vec3_t entorigin, const visstate_t *visstate)
{
unsigned int i;
dlight_t *l;
r_dlightframecount = r_framecount;
if (!r_dlight_lightmap)
return;
l = r_dlights;
for (i = 0; i < r_maxdlights; i++, l++) {
if (l->die < r_data->realtime || !l->radius)
continue;
auto dlight_pool = &r_refdef.registry->comp_pools[scene_dynlight];
auto dlight_data = (dlight_t *) dlight_pool->data;
for (uint32_t i = 0; i < dlight_pool->count; i++) {
auto dlight = &dlight_data[i];
vec4f_t lightorigin;
VectorSubtract (l->origin, entorigin, lightorigin);
VectorSubtract (dlight->origin, entorigin, lightorigin);
lightorigin[3] = 1;
R_MarkLights (lightorigin, l, i, visstate);
R_MarkLights (lightorigin, dlight, i, visstate);
}
}
@ -496,66 +473,3 @@ R_LightPoint (mod_brush_t *brush, vec4f_t p)
return r;
}
dlight_t *
R_AllocDlight (int key)
{
unsigned int i;
dlight_t *dl;
if (!r_maxdlights) {
return NULL;
}
// first look for an exact key match
if (key) {
dl = r_dlights;
for (i = 0; i < r_maxdlights; i++, dl++) {
if (dl->key == key) {
memset (dl, 0, sizeof (*dl));
dl->key = key;
dl->color[0] = dl->color[1] = dl->color[2] = 1;
return dl;
}
}
}
// then look for anything else
dl = r_dlights;
for (i = 0; i < r_maxdlights; i++, dl++) {
if (dl->die < r_data->realtime) {
memset (dl, 0, sizeof (*dl));
dl->key = key;
dl->color[0] = dl->color[1] = dl->color[2] = 1;
return dl;
}
}
dl = &r_dlights[0];
memset (dl, 0, sizeof (*dl));
dl->key = key;
return dl;
}
void
R_DecayLights (double frametime)
{
unsigned int i;
dlight_t *dl;
dl = r_dlights;
for (i = 0; i < r_maxdlights; i++, dl++) {
if (dl->die < r_data->realtime || !dl->radius)
continue;
dl->radius -= frametime * dl->decay;
if (dl->radius < 0)
dl->radius = 0;
}
}
void
R_ClearDlights (void)
{
if (r_maxdlights)
memset (r_dlights, 0, r_maxdlights * sizeof (dlight_t));
}

View file

@ -332,7 +332,9 @@ SCR_UpdateScreen (transform_t camera, double realtime, SCR_Func *scr_funcs)
R_MarkLeaves (&r_visstate, scr_scene->viewleaf);
}
r_framecount++;
R_PushDlights (vec3_origin, &r_visstate);
if (scr_scene) {
R_PushDlights (vec3_origin, &r_visstate);
}
r_funcs->UpdateScreen (scr_funcs);
}
@ -506,10 +508,12 @@ SCR_NewScene (scene_t *scene)
.leaf_visframes = leaf_visframes,
.face_visframes = face_visframes,
};
r_refdef.registry = scene->reg;
r_funcs->set_fov (tan_fov_x, tan_fov_y);
r_funcs->R_NewScene (scene);
} else {
r_visstate = (visstate_t) {};
r_funcs->R_ClearState ();
r_refdef.registry = 0;
}
}

View file

@ -197,7 +197,6 @@ R_NewScene (scene_t *scene)
model_t *worldmodel = scene->worldmodel;
mod_brush_t *brush = &worldmodel->brush;
r_refdef.registry = scene->reg;
r_refdef.worldmodel = worldmodel;
if (brush->skytexture)
@ -284,14 +283,15 @@ setup_lighting (entity_t ent, alight_t *lighting)
VectorCopy (lightvec, lighting->lightvec);
for (unsigned lnum = 0; lnum < r_maxdlights; lnum++) {
if (r_dlights[lnum].die >= vr_data.realtime) {
VectorSubtract (r_entorigin, r_dlights[lnum].origin, dist);
add = r_dlights[lnum].radius - VectorLength (dist);
auto dlight_pool = &r_refdef.registry->comp_pools[scene_dynlight];
auto dlight_data = (dlight_t *) dlight_pool->data;
for (uint32_t i = 0; i < dlight_pool->count; i++) {
auto dlight = &dlight_data[i];
VectorSubtract (r_entorigin, dlight->origin, dist);
add = dlight->radius - VectorLength (dist);
if (add > 0)
lighting->ambientlight += add;
}
if (add > 0)
lighting->ambientlight += add;
}
// clamp lighting so it doesn't overbright as much
@ -360,11 +360,9 @@ R_DrawViewModel (void)
{
// FIXME: remove and do real lighting
int j;
unsigned int lnum;
vec3_t dist;
float add;
float minlight;
dlight_t *dl;
entity_t viewent;
alight_t lighting;
@ -404,15 +402,10 @@ R_DrawViewModel (void)
lighting.shadelight = j;
// add dynamic lights
for (lnum = 0; lnum < r_maxdlights; lnum++) {
dl = &r_dlights[lnum];
if (!dl->radius)
continue;
if (!dl->radius)
continue;
if (dl->die < vr_data.realtime)
continue;
auto dlight_pool = &r_refdef.registry->comp_pools[scene_dynlight];
auto dlight_data = (dlight_t *) dlight_pool->data;
for (uint32_t i = 0; i < dlight_pool->count; i++) {
auto dl = &dlight_data[i];
VectorSubtract (r_entorigin, dl->origin, dist);
add = dl->radius - VectorLength (dist);
if (add > 0)
@ -494,6 +487,9 @@ R_DrawBrushEntitiesOnList (entqueue_t *queue)
insubmodel = true;
auto dlight_pool = &r_refdef.registry->comp_pools[scene_dynlight];
auto dlight_data = (dlight_t *) dlight_pool->data;
for (size_t i = 0; i < queue->ent_queues[mod_brush].size; i++) {
entity_t ent = queue->ent_queues[mod_brush].a[i];
uint32_t render_id = SW_AddEntity (ent);
@ -527,17 +523,13 @@ R_DrawBrushEntitiesOnList (entqueue_t *queue)
// calculate dynamic lighting for bmodel if it's not an
// instanced model
if (brush->firstmodelsurface != 0) {
for (k = 0; k < r_maxdlights; k++) {
if ((r_dlights[k].die < vr_data.realtime) ||
(!r_dlights[k].radius)) {
continue;
}
for (k = 0; k < dlight_pool->count; k++) {
auto dlight = &dlight_data[k];
vec4f_t lightorigin;
VectorSubtract (r_dlights[k].origin, origin, lightorigin);
VectorSubtract (dlight->origin, origin, lightorigin);
lightorigin[3] = 1;
R_RecursiveMarkLights (brush, lightorigin,
&r_dlights[k], k,
dlight, k,
brush->hulls[0].firstclipnode);
}
}
@ -699,6 +691,5 @@ void
R_ClearState (void)
{
r_refdef.worldmodel = 0;
R_ClearDlights ();
R_ClearParticles ();
}

View file

@ -76,13 +76,11 @@ static void
R_AddDynamicLights (uint32_t render_id)
{
msurface_t *surf;
unsigned int lnum;
int sd, td;
float dist, rad, minlight;
vec3_t impact, local, lightorigin;
vec4f_t entorigin = { 0, 0, 0, 1 };
int s, t;
int i;
int smax, tmax;
mtexinfo_t *tex;
@ -97,21 +95,25 @@ R_AddDynamicLights (uint32_t render_id)
entorigin = transform[3];
}
for (lnum = 0; lnum < r_maxdlights; lnum++) {
if (!(surf->dlightbits[lnum / 32] & (1 << (lnum % 32))))
auto dlight_pool = &r_refdef.registry->comp_pools[scene_dynlight];
auto dlight_data = (dlight_t *) dlight_pool->data;
for (uint32_t k = 0; k < dlight_pool->count; k++) {
auto dlight = &dlight_data[k];
//FIXME
if (!(surf->dlightbits[k / 32] & (1 << (k % 32))))
continue; // not lit by this light
VectorSubtract (r_dlights[lnum].origin, entorigin, lightorigin);
rad = r_dlights[lnum].radius;
VectorSubtract (dlight->origin, entorigin, lightorigin);
rad = dlight->radius;
dist = DotProduct (lightorigin, surf->plane->normal) -
surf->plane->dist;
rad -= fabs (dist);
minlight = r_dlights[lnum].minlight;
minlight = dlight->minlight;
if (rad < minlight)
continue;
minlight = rad - minlight;
for (i = 0; i < 3; i++)
for (int i = 0; i < 3; i++)
impact[i] = lightorigin[i] - surf->plane->normal[i] * dist;
local[0] = DotProduct (impact, tex->vecs[0]) + tex->vecs[0][3];

View file

@ -146,7 +146,6 @@ vulkan_R_ClearState (void)
//FIXME clear scene correctly
r_refdef.worldmodel = 0;
EntQueue_Clear (r_ent_queue);
R_ClearDlights ();
R_ClearParticles ();
Vulkan_LoadLights (0, vulkan_ctx);
}

View file

@ -310,7 +310,7 @@ CL_RelinkEntities (void)
angles[YAW] = bobjrotate;
CL_TransformEntity (ent, new->scale / 16.0, angles, new->origin);
}
CL_EntityEffects (i, ent, new, cl.time);
CL_EntityEffects (ent, new, cl.time);
vec4f_t org = Transform_GetWorldPosition (transform);
int effects = new->effects;
if (cl.maxclients == 1 && effects) {
@ -325,13 +325,13 @@ CL_RelinkEntities (void)
effects |= (it & IT_INVULNERABILITY)
>> (BITOP_LOG2(IT_INVULNERABILITY) - BITOP_LOG2 (EF_RED));
}
CL_NewDlight (i, org, effects, new->glow_size,
CL_NewDlight (ent, org, effects, new->glow_size,
new->glow_color, cl.time);
if (VectorDistance_fast (old->origin, org) > (256 * 256)) {
old->origin = org;
}
if (model_flags & ~EF_ROTATE)
CL_ModelEffects (ent, i, new->glow_color, cl.time);
CL_ModelEffects (ent, new->glow_color, cl.time);
SET_REMOVE (&cl_forcelink, i);
}

View file

@ -52,6 +52,7 @@
#include "QF/plugin/console.h"
#include "QF/plugin/vid_render.h"
#include "QF/scene/entity.h"
#include "QF/scene/light.h"
#include "QF/scene/scene.h"
#include "QF/ui/font.h"//FIXME
@ -659,7 +660,7 @@ CL_Frame (void)
if (l)
asl = l->ambient_sound_level;
S_Update (cl.viewstate.camera_transform, asl);
R_DecayLights (host_frametime);
Light_DecayLights (cl_world.scene->lights, host_frametime, realtime);
} else
S_Update (nulltransform, 0);

View file

@ -65,6 +65,7 @@ typedef struct player_state_s {
int oldbuttons;
int oldonground;
bool muzzle_flash;
} player_state_t;
typedef struct {

View file

@ -42,6 +42,7 @@
#include "QF/sys.h"
#include "QF/scene/entity.h"
#include "QF/scene/light.h"
#include "compat.h"
@ -194,7 +195,7 @@ CL_LinkPacketEntities (void)
ent.reg);
// spawn light flashes, even ones coming from invisible objects
CL_NewDlight (i, new->origin, new->effects, new->glow_size,
CL_NewDlight (ent, new->origin, new->effects, new->glow_size,
new->glow_color, cl.time);
if (forcelink)
@ -298,7 +299,7 @@ CL_LinkPacketEntities (void)
if (VectorDistance_fast (old->origin, org) > (256 * 256))
old->origin = org;
if (renderer->model->flags & ~EF_ROTATE) {
CL_ModelEffects (ent, -new->number, new->glow_color, cl.time);
CL_ModelEffects (ent, new->glow_color, cl.time);
}
}
}
@ -385,6 +386,21 @@ CL_RemoveFlagModels (int key)
Transform_SetParent (transform, nulltransform);
}
static void
muzzle_flash (entity_t ent, player_state_t *state, bool is_player)
{
vec3_t f, r, u;
vec4f_t position = { 0, 0, 0, 1}, fv = {};
if (is_player)
AngleVectors (cl.viewstate.player_angles, f, r, u);
else
AngleVectors (state->viewangles, f, r, u);
VectorCopy (f, fv);
VectorCopy (state->pls.es.origin, position);
CL_MuzzleFlash (ent, position, fv, 0, cl.time);
}
/*
CL_LinkPlayers
@ -441,16 +457,19 @@ CL_LinkPlayers (void)
clientplayer = false;
}
if (player->chat && player->chat->value[0] != '0') {
dlight_t *dl = R_AllocDlight (j + 1);
VectorCopy (org, dl->origin);
dl->radius = 100;
dl->die = cl.time + 0.1;
QuatSet (0.0, 1.0, 0.0, 1.0, dl->color);
Ent_SetComponent (ent.id, scene_dynlight, ent.reg, &(dlight_t) {
.origin = org,
.color = {0.0, 1.0, 0.0, 1.0},
.radius = 100,
.die = cl.time + 0.1,
});
Light_LinkLight (cl_world.scene->lights, ent.id);
} else {
CL_NewDlight (j + 1, org, state->pls.es.effects,
CL_NewDlight (ent, org, state->pls.es.effects,
state->pls.es.glow_size, state->pls.es.glow_color,
cl.time);
}
muzzle_flash (ent, state, j == cl.playernum);
// Draw player?
if (!Cam_DrawPlayer (j))

View file

@ -91,6 +91,7 @@
#include "QF/gib.h"
#include "QF/plugin/console.h"
#include "QF/scene/light.h"
#include "QF/scene/transform.h"
#include "QF/ui/font.h"//FIXME
@ -1969,7 +1970,7 @@ Host_Frame (float time)
if (l)
asl = l->ambient_sound_level;
S_Update (cl.viewstate.camera_transform, asl);
R_DecayLights (host_frametime);
Light_DecayLights (cl_world.scene->lights, host_frametime, realtime);
} else
S_Update (nulltransform, 0);

View file

@ -1184,12 +1184,8 @@ CL_SetStat (int stat, int value)
static void
CL_ParseMuzzleFlash (void)
{
//FIXME this should just enable the effect on the relevant entity and
//then automatic entity updates take care of the rest
int i;
player_state_t *pl;
vec3_t f, r, u;
vec4f_t position = { 0, 0, 0, 1}, fv = {};
i = MSG_ReadShort (net_message);
@ -1197,15 +1193,7 @@ CL_ParseMuzzleFlash (void)
return;
pl = &cl.frames[parsecountmod].playerstate[i - 1];
if (i - 1 == cl.playernum)
AngleVectors (cl.viewstate.player_angles, f, r, u);
else
AngleVectors (pl->viewangles, f, r, u);
VectorCopy (f, fv);
VectorCopy (pl->pls.es.origin, position);
CL_MuzzleFlash (position, fv, 0, i, cl.time);
pl->muzzle_flash = true;
}
#define SHOWNET(x) \