mirror of
https://git.code.sf.net/p/quake/quakeforge
synced 2025-02-21 11:11:37 +00:00
[client] Put dynamic lights on separate entities
Dynamic lights can't go directly on visible entities as one or the other will fail to be queued. In addition, the number of lights on an entity needs to be limited. For now, one general purpose light for various effects (eg, quad damage etc) and one for the muzzle flash.
This commit is contained in:
parent
fb818d15d9
commit
7294a77356
4 changed files with 118 additions and 24 deletions
|
@ -31,6 +31,17 @@
|
|||
#define __client_effects_h
|
||||
|
||||
#include "QF/simd/types.h"
|
||||
#include "QF/ecs/component.h"
|
||||
|
||||
enum {
|
||||
effect_light, // light entity id
|
||||
effect_muzzleflash, // light entity id
|
||||
|
||||
effect_comp_count,
|
||||
};
|
||||
|
||||
extern const component_t effect_components[effect_comp_count];
|
||||
extern struct ecs_system_s effect_system;
|
||||
|
||||
struct entity_s;
|
||||
struct entity_state_s;
|
||||
|
|
|
@ -38,6 +38,7 @@
|
|||
# include <strings.h>
|
||||
#endif
|
||||
|
||||
#include "QF/ecs.h"
|
||||
#include "QF/render.h"
|
||||
|
||||
#include "QF/plugin/vid_render.h" //FIXME
|
||||
|
@ -50,6 +51,53 @@
|
|||
#include "client/particles.h"
|
||||
#include "client/world.h"
|
||||
|
||||
ecs_system_t effect_system;
|
||||
|
||||
const component_t effect_components[effect_comp_count] = {
|
||||
[effect_light] = {
|
||||
.size = sizeof (uint32_t),
|
||||
.name = "effect light",
|
||||
},
|
||||
[effect_muzzleflash] = {
|
||||
.size = sizeof (uint32_t),
|
||||
.name = "muzzle flash",
|
||||
},
|
||||
};
|
||||
|
||||
#define c_light (effect_system.base + effect_light)
|
||||
|
||||
static bool
|
||||
has_light (entity_t ent)
|
||||
{
|
||||
return Ent_HasComponent (ent.id, c_light, ent.reg);
|
||||
}
|
||||
|
||||
static uint32_t
|
||||
get_light (entity_t ent)
|
||||
{
|
||||
return *(uint32_t *) Ent_GetComponent (ent.id, c_light, ent.reg);
|
||||
}
|
||||
|
||||
static void
|
||||
set_light (entity_t ent, uint32_t light)
|
||||
{
|
||||
Ent_SetComponent (ent.id, c_light, ent.reg, &light);
|
||||
}
|
||||
|
||||
static uint32_t
|
||||
attach_light_ent (entity_t ent)
|
||||
{
|
||||
uint32_t light = nullent;
|
||||
if (has_light (ent)) {
|
||||
light = get_light (ent);
|
||||
}
|
||||
if (!ECS_EntValid (light, ent.reg)) {
|
||||
light = ECS_NewEntity (ent.reg);
|
||||
set_light (ent, light);
|
||||
}
|
||||
return light;
|
||||
}
|
||||
|
||||
void
|
||||
CL_NewDlight (entity_t ent, vec4f_t org, int effects, byte glow_size,
|
||||
byte glow_color, double time)
|
||||
|
@ -103,13 +151,14 @@ CL_NewDlight (entity_t ent, vec4f_t org, int effects, byte glow_size,
|
|||
}
|
||||
}
|
||||
|
||||
Ent_SetComponent (ent.id, scene_dynlight, ent.reg, &(dlight_t) {
|
||||
uint32_t light = attach_light_ent (ent);
|
||||
Ent_SetComponent (light, scene_dynlight, ent.reg, &(dlight_t) {
|
||||
.origin = org,
|
||||
.color = color,
|
||||
.radius = radius,
|
||||
.die = die,
|
||||
});
|
||||
Light_LinkLight (cl_world.scene->lights, ent.id);
|
||||
Light_LinkLight (cl_world.scene->lights, light);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -123,14 +172,15 @@ CL_ModelEffects (entity_t ent, int glow_color, double time)
|
|||
|
||||
// add automatic particle trails
|
||||
if (model->flags & EF_ROCKET) {
|
||||
Ent_SetComponent (ent.id, scene_dynlight, ent.reg, &(dlight_t) {
|
||||
uint32_t light = attach_light_ent (ent);
|
||||
Ent_SetComponent (light, scene_dynlight, ent.reg, &(dlight_t) {
|
||||
.origin = ent_origin,
|
||||
//FIXME VectorCopy (r_firecolor, dl->color);
|
||||
.color = { 0.9, 0.7, 0.0, 0.7 },
|
||||
.radius = 200,
|
||||
.die = time + 0.1,
|
||||
});
|
||||
Light_LinkLight (cl_world.scene->lights, ent.id);
|
||||
Light_LinkLight (cl_world.scene->lights, light);
|
||||
clp_funcs->RocketTrail (*old_origin, ent_origin);
|
||||
} else if (model->flags & EF_GRENADE)
|
||||
clp_funcs->GrenadeTrail (*old_origin, ent_origin);
|
||||
|
@ -148,20 +198,6 @@ CL_ModelEffects (entity_t ent, int glow_color, double time)
|
|||
clp_funcs->GlowTrail (*old_origin, ent_origin, glow_color);
|
||||
}
|
||||
|
||||
void
|
||||
CL_MuzzleFlash (entity_t ent, vec4f_t position, vec4f_t fv, float zoffset,
|
||||
double time)
|
||||
{
|
||||
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 (entity_t ent, entity_state_t *state, double time)
|
||||
{
|
||||
|
|
|
@ -749,3 +749,48 @@ CL_ParseProjectiles (qmsg_t *net_message, bool nail2, TEntContext_t *ctx)
|
|||
*tail = cl_projectiles;
|
||||
cl_projectiles = head;
|
||||
}
|
||||
|
||||
#define c_muzzleflash (effect_system.base + effect_muzzleflash)
|
||||
|
||||
static bool
|
||||
has_muzzleflash (entity_t ent)
|
||||
{
|
||||
return Ent_HasComponent (ent.id, c_muzzleflash, ent.reg);
|
||||
}
|
||||
|
||||
static uint32_t
|
||||
get_muzzleflash (entity_t ent)
|
||||
{
|
||||
return *(uint32_t *) Ent_GetComponent (ent.id, c_muzzleflash, ent.reg);
|
||||
}
|
||||
|
||||
static void
|
||||
set_muzzleflash (entity_t ent, uint32_t light)
|
||||
{
|
||||
Ent_SetComponent (ent.id, c_muzzleflash, ent.reg, &light);
|
||||
}
|
||||
|
||||
void
|
||||
CL_MuzzleFlash (entity_t ent, vec4f_t position, vec4f_t fv, float zoffset,
|
||||
double time)
|
||||
{
|
||||
// spawn a new entity so the light doesn't mess with the owner
|
||||
uint32_t light = nullent;
|
||||
if (has_muzzleflash (ent)) {
|
||||
light = get_muzzleflash (ent);
|
||||
}
|
||||
if (!ECS_EntValid (light, ent.reg)) {
|
||||
light = ECS_NewEntity (ent.reg);
|
||||
set_muzzleflash (ent, light);
|
||||
}
|
||||
DARRAY_APPEND (&light_entities, ((entity_t) {.reg = ent.reg, .id = light}));
|
||||
|
||||
Ent_SetComponent (light, 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, light);
|
||||
}
|
||||
|
|
|
@ -43,16 +43,12 @@
|
|||
#include "QF/idparse.h"
|
||||
#include "QF/quakefs.h"
|
||||
#include "QF/plist.h"
|
||||
#include "QF/progs.h"
|
||||
#include "QF/msg.h"
|
||||
|
||||
#include "QF/scene/entity.h"
|
||||
#include "QF/scene/light.h"
|
||||
#include "QF/scene/scene.h"
|
||||
#include "QF/simd/vec4f.h"
|
||||
|
||||
#include "QF/plugin/vid_render.h" //FIXME
|
||||
|
||||
#include "client/effects.h"
|
||||
#include "client/entities.h"
|
||||
#include "client/temp_entities.h"
|
||||
#include "client/world.h"
|
||||
|
@ -64,7 +60,13 @@ worldscene_t cl_world = {
|
|||
void
|
||||
CL_World_Init (void)
|
||||
{
|
||||
cl_world.scene = Scene_NewScene (0);
|
||||
scene_system_t extra_systems[] = {
|
||||
{ .system = &effect_system,
|
||||
.components = effect_components,
|
||||
.component_count = effect_comp_count },
|
||||
{}
|
||||
};
|
||||
cl_world.scene = Scene_NewScene (extra_systems);
|
||||
cl_world.scene->lights = Light_CreateLightingData (cl_world.scene);
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue