mirror of
https://git.code.sf.net/p/quake/quakeforge
synced 2025-02-24 04:31:35 +00:00
[renderer] Get trails rendering again
They're not quite working (trail path offset is incorrect) but their pixels are getting to the screen. Also, lifetimes are off for rocket trails in that as soon as the entity dies, so does the trail.
This commit is contained in:
parent
ef6b10afb1
commit
34daf9032d
19 changed files with 463 additions and 305 deletions
|
@ -44,4 +44,8 @@ void glsl_R_Particles_Init_Cvars (void);
|
|||
void glsl_R_InitParticles (void);
|
||||
void glsl_R_ShutdownParticles (void);
|
||||
|
||||
void glsl_R_InitTrails (void);
|
||||
void glsl_R_ShutdownTrails (void);
|
||||
void glsl_R_DrawTrails (struct psystem_s *psystem);
|
||||
|
||||
#endif//__QF_GLSL_qf_particles_h
|
||||
|
|
|
@ -118,6 +118,7 @@ typedef struct vid_render_funcs_s {
|
|||
void (*Draw_Glyph) (int x, int y, int fontid, int glyphid, int c);
|
||||
|
||||
struct psystem_s *(*ParticleSystem) (void);
|
||||
struct psystem_s *(*TrailSystem) (void);
|
||||
void (*R_Init) (void);
|
||||
void (*R_ClearState) (void);
|
||||
void (*R_LoadSkys) (const char *);
|
||||
|
@ -127,6 +128,7 @@ typedef struct vid_render_funcs_s {
|
|||
void (*begin_frame) (void);
|
||||
void (*render_view) (void);
|
||||
void (*draw_particles) (struct psystem_s *psystem);
|
||||
void (*draw_trails) (struct psystem_s *psystem);
|
||||
void (*draw_transparent) (void);
|
||||
void (*post_process) (struct framebuffer_s *src);
|
||||
void (*set_2d) (int scaled);
|
||||
|
|
|
@ -41,10 +41,8 @@ typedef enum {
|
|||
part_tex_smoke,
|
||||
} ptextype_t;
|
||||
|
||||
typedef struct particle_s particle_t;
|
||||
|
||||
// !!! if this is changed, it must be changed in d_ifacea.h too !!!
|
||||
struct particle_s {
|
||||
typedef struct particle_s {
|
||||
vec4f_t pos;
|
||||
vec4f_t vel;
|
||||
|
||||
|
@ -61,7 +59,24 @@ struct particle_s {
|
|||
float ramp;
|
||||
float scale;
|
||||
float live;
|
||||
};
|
||||
} particle_t;
|
||||
|
||||
static_assert (sizeof (particle_t) == 4 * sizeof(vec4f_t),
|
||||
"particle_t wrong size");
|
||||
|
||||
typedef struct trailpnt_s {
|
||||
vec4f_t pos;
|
||||
vec4f_t vel;
|
||||
vec3_t bary;
|
||||
float pathoffset;
|
||||
byte colora[4];
|
||||
byte colorb[4];
|
||||
uint32_t trailid;
|
||||
float live;
|
||||
} trailpnt_t;
|
||||
|
||||
static_assert (sizeof (trailpnt_t) == 4 * sizeof(vec4f_t),
|
||||
"trailprt_t wrong size");
|
||||
|
||||
typedef struct partparm_s {
|
||||
vec4f_t drag; // drag[3] is grav scale
|
||||
|
@ -71,6 +86,9 @@ typedef struct partparm_s {
|
|||
float alpha_rate;
|
||||
} partparm_t;
|
||||
|
||||
static_assert (sizeof (partparm_t) == 2 * sizeof(vec4f_t),
|
||||
"partparm_t wrong size");
|
||||
|
||||
typedef struct psystem_s {
|
||||
vec4f_t gravity;
|
||||
uint32_t maxparticles;
|
||||
|
@ -186,4 +204,9 @@ void Fog_StartAdditive (void);
|
|||
void Fog_StopAdditive (void);
|
||||
void Fog_Init (void);
|
||||
|
||||
bool R_Trail_Valid (psystem_t *system, uint32_t trailid) __attribute__((pure));
|
||||
uint32_t R_Trail_Create (psystem_t *system, int num_points, vec4f_t start);
|
||||
void R_Trail_Update (psystem_t *system, uint32_t trailid, vec4f_t pos);
|
||||
void R_Trail_Destroy (psystem_t *system, uint32_t trailid);
|
||||
|
||||
#endif//__QF_render_h
|
||||
|
|
|
@ -75,7 +75,7 @@ typedef struct visibility_s {
|
|||
typedef struct renderer_s {
|
||||
struct model_s *model; // NULL = no model
|
||||
struct skin_s *skin;
|
||||
struct trail_s *trail; // FIXME should be own component
|
||||
struct trail_s *trail;
|
||||
unsigned fullbright:1;
|
||||
unsigned noshadows:1;
|
||||
unsigned onlyshadows:1;
|
||||
|
|
|
@ -36,6 +36,7 @@
|
|||
enum {
|
||||
effect_light, // light entity id
|
||||
effect_muzzleflash, // light entity id
|
||||
effect_trail, // trail id
|
||||
|
||||
effect_comp_count,
|
||||
};
|
||||
|
@ -54,5 +55,6 @@ 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);
|
||||
void CL_Effects_Init (void);
|
||||
|
||||
#endif//__client_effects_h
|
||||
|
|
|
@ -45,16 +45,13 @@ typedef enum {
|
|||
|
||||
struct entity_s;
|
||||
|
||||
void R_Particles_Init_Cvars (void);
|
||||
void R_Particle_New (const char *type, int texnum, const vec3_t org,
|
||||
float scale, const vec3_t vel, float die, int color,
|
||||
float alpha, float ramp);
|
||||
void R_Particle_NewRandom (const char *type, int texnum, const vec3_t org,
|
||||
int org_fuzz, float scale, int vel_fuzz, float die,
|
||||
int color, float alpha, float ramp);
|
||||
void R_InitBubble (void);
|
||||
void R_Trails_Init (void);
|
||||
void R_Trails_Init_Cvars (void);
|
||||
void R_ClearTrails (void);
|
||||
void R_RunTrails (float dT);
|
||||
|
||||
void R_InitParticles (void);
|
||||
void R_RunParticles (float dT);
|
||||
void R_Particles_Init_Cvars (void);
|
||||
void R_ClearParticles (void);
|
||||
void R_InitSprites (void);
|
||||
|
||||
|
|
|
@ -42,10 +42,11 @@ void R_ViewChanged (void); // must set r_refdef first
|
|||
// called whenever r_refdef or vid change
|
||||
|
||||
extern struct psystem_s r_psystem;
|
||||
extern struct psystem_s r_tsystem;
|
||||
struct psystem_s *gl_ParticleSystem (void);
|
||||
struct psystem_s *glsl_ParticleSystem (void);
|
||||
struct psystem_s *glsl_TrailSystem (void);
|
||||
struct psystem_s *sw_ParticleSystem (void);
|
||||
void R_RunParticles (float dT);
|
||||
|
||||
struct scene_s;
|
||||
void R_NewScene (struct scene_s *scene);
|
||||
|
|
|
@ -53,6 +53,15 @@
|
|||
|
||||
ecs_system_t effect_system;
|
||||
|
||||
static psystem_t *cl_tsystem;
|
||||
|
||||
static void
|
||||
cl_destroy_trail (void *comp)
|
||||
{
|
||||
auto trail = *(uint32_t *) comp;
|
||||
R_Trail_Destroy (cl_tsystem, trail);
|
||||
}
|
||||
|
||||
const component_t effect_components[effect_comp_count] = {
|
||||
[effect_light] = {
|
||||
.size = sizeof (uint32_t),
|
||||
|
@ -62,9 +71,15 @@ const component_t effect_components[effect_comp_count] = {
|
|||
.size = sizeof (uint32_t),
|
||||
.name = "muzzle flash",
|
||||
},
|
||||
[effect_trail] = {
|
||||
.size = sizeof (uint32_t),
|
||||
.name = "effect trail",
|
||||
.destroy = cl_destroy_trail,
|
||||
},
|
||||
};
|
||||
|
||||
#define c_light (effect_system.base + effect_light)
|
||||
#define c_trail (effect_system.base + effect_trail)
|
||||
|
||||
static bool
|
||||
has_light (entity_t ent)
|
||||
|
@ -98,6 +113,27 @@ attach_light_ent (entity_t ent)
|
|||
return light;
|
||||
}
|
||||
|
||||
static bool
|
||||
has_trail (entity_t ent)
|
||||
{
|
||||
return Ent_HasComponent (ent.id, c_trail, ent.reg);
|
||||
}
|
||||
|
||||
static uint32_t
|
||||
get_trail (entity_t ent)
|
||||
{
|
||||
if (!has_trail (ent)) {
|
||||
return nullent;
|
||||
}
|
||||
return *(uint32_t *) Ent_GetComponent (ent.id, c_trail, ent.reg);
|
||||
}
|
||||
|
||||
static void
|
||||
set_trail (entity_t ent, uint32_t trail)
|
||||
{
|
||||
Ent_SetComponent (ent.id, c_trail, ent.reg, &trail);
|
||||
}
|
||||
|
||||
void
|
||||
CL_NewDlight (entity_t ent, vec4f_t org, int effects, byte glow_size,
|
||||
byte glow_color, double time)
|
||||
|
@ -181,6 +217,14 @@ CL_ModelEffects (entity_t ent, int glow_color, double time)
|
|||
});
|
||||
Light_LinkLight (cl_world.scene->lights, light);
|
||||
clp_funcs->RocketTrail (*old_origin, ent_origin);
|
||||
if (cl_tsystem) {
|
||||
uint32_t trail = get_trail (ent);
|
||||
if (R_Trail_Valid (cl_tsystem, trail)) {
|
||||
R_Trail_Update (cl_tsystem, trail, ent_origin);
|
||||
} else {
|
||||
set_trail (ent, R_Trail_Create (cl_tsystem, 30, ent_origin));
|
||||
}
|
||||
}
|
||||
renderer->noshadows = 1;
|
||||
} else if (model->effects & ME_GRENADE)
|
||||
clp_funcs->GrenadeTrail (*old_origin, ent_origin);
|
||||
|
@ -210,3 +254,11 @@ CL_EntityEffects (entity_t ent, entity_state_t *state, double time)
|
|||
CL_MuzzleFlash (ent, position, fv, 16, time);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
CL_Effects_Init (void)
|
||||
{
|
||||
if (r_funcs->TrailSystem) {
|
||||
cl_tsystem = r_funcs->TrailSystem ();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -58,9 +58,10 @@ libs_video_renderer_libQFrenderer_la_SOURCES=\
|
|||
libs/video/renderer/r_light.c \
|
||||
libs/video/renderer/r_main.c \
|
||||
libs/video/renderer/r_part.c \
|
||||
libs/video/renderer/r_progs.c \
|
||||
libs/video/renderer/r_scrap.c \
|
||||
libs/video/renderer/r_screen.c \
|
||||
libs/video/renderer/r_progs.c
|
||||
libs/video/renderer/r_trails.c
|
||||
|
||||
video_renderer_gl_libs= \
|
||||
libs/video/renderer/librender_gl.la \
|
||||
|
|
|
@ -186,6 +186,7 @@ glsl_R_Init (void)
|
|||
glsl_R_InitIQM ();
|
||||
glsl_R_InitSprites ();
|
||||
glsl_R_InitParticles ();
|
||||
glsl_R_InitTrails ();
|
||||
glsl_InitFisheye ();
|
||||
glsl_InitWarp ();
|
||||
Skin_Init ();
|
||||
|
|
|
@ -87,9 +87,8 @@ static const char *particle_trail_debug_frag_effects[] =
|
|||
0
|
||||
};
|
||||
|
||||
static struct {
|
||||
typedef struct {
|
||||
int program;
|
||||
int debug_program;
|
||||
shaderparam_t proj;
|
||||
shaderparam_t view;
|
||||
shaderparam_t viewport;
|
||||
|
@ -101,8 +100,10 @@ static struct {
|
|||
shaderparam_t texoff;
|
||||
shaderparam_t colora;
|
||||
shaderparam_t colorb;
|
||||
} trail = {
|
||||
0, 0,
|
||||
} trailprog_t;
|
||||
|
||||
static trailprog_t trail = {
|
||||
0,
|
||||
{"projection_mat", 1},
|
||||
{"view_mat", 1},
|
||||
{"viewport", 1},
|
||||
|
@ -115,62 +116,16 @@ static struct {
|
|||
{"vcolora", 0},
|
||||
{"vcolorb", 0},
|
||||
};
|
||||
|
||||
typedef struct point_s {
|
||||
particle_t p;
|
||||
struct point_s *next;
|
||||
} point_t;
|
||||
|
||||
typedef struct trail_s {
|
||||
struct trail_s *next;
|
||||
struct trail_s **prev;
|
||||
struct trail_s **owner;
|
||||
point_t *points;
|
||||
point_t **head; // new points are appended to the list
|
||||
int num_points;
|
||||
} trail_t;
|
||||
static trailprog_t trail_debug;
|
||||
|
||||
typedef struct trailvtx_s {
|
||||
quat_t vertex;
|
||||
vec4f_t vertex;
|
||||
vec3_t bary;
|
||||
float texoff;
|
||||
quat_t colora;
|
||||
quat_t colorb;
|
||||
byte colora[4];
|
||||
byte colorb[4];
|
||||
} trailvtx_t;
|
||||
|
||||
ALLOC_STATE (trail_t, trails);
|
||||
ALLOC_STATE (point_t, points);
|
||||
static trail_t *trails_active;
|
||||
|
||||
static trail_t *
|
||||
new_trail (void)
|
||||
{
|
||||
trail_t *trail;
|
||||
ALLOC (16, trail_t, trails, trail);
|
||||
trail->head = &trail->points;
|
||||
return trail;
|
||||
}
|
||||
|
||||
static void
|
||||
free_trail (trail_t *trail)
|
||||
{
|
||||
FREE (trails, trail);
|
||||
}
|
||||
|
||||
static point_t *
|
||||
new_point (void)
|
||||
{
|
||||
point_t *point;
|
||||
ALLOC (128, point_t, points, point);
|
||||
return point;
|
||||
}
|
||||
|
||||
static void
|
||||
free_point (point_t *point)
|
||||
{
|
||||
FREE (points, point);
|
||||
}
|
||||
|
||||
static void
|
||||
alloc_arrays (psystem_t *ps)
|
||||
{
|
||||
|
@ -197,20 +152,38 @@ alloc_arrays (psystem_t *ps)
|
|||
}
|
||||
|
||||
void
|
||||
glsl_R_ShutdownParticles (void)
|
||||
glsl_R_ShutdownTrails (void)
|
||||
{
|
||||
free (particleVertexArray);
|
||||
free (pVAindices);
|
||||
}
|
||||
|
||||
static void
|
||||
build_program (trailprog_t *prog, const char *name, int vert, int frag)
|
||||
{
|
||||
prog->program = GLSL_LinkProgram (name, vert, frag);
|
||||
GLSL_ResolveShaderParam (prog->program, &prog->proj);
|
||||
GLSL_ResolveShaderParam (prog->program, &prog->view);
|
||||
GLSL_ResolveShaderParam (prog->program, &prog->viewport);
|
||||
GLSL_ResolveShaderParam (prog->program, &prog->width);
|
||||
GLSL_ResolveShaderParam (prog->program, &prog->last);
|
||||
GLSL_ResolveShaderParam (prog->program, &prog->current);
|
||||
GLSL_ResolveShaderParam (prog->program, &prog->next);
|
||||
GLSL_ResolveShaderParam (prog->program, &prog->barycentric);
|
||||
GLSL_ResolveShaderParam (prog->program, &prog->texoff);
|
||||
GLSL_ResolveShaderParam (prog->program, &prog->colora);
|
||||
GLSL_ResolveShaderParam (prog->program, &prog->colorb);
|
||||
}
|
||||
|
||||
void
|
||||
glsl_R_InitParticles (void)
|
||||
glsl_R_InitTrails (void)
|
||||
{
|
||||
shader_t *vert_shader, *frag_shader, *debug_shader;
|
||||
int vert;
|
||||
int frag;
|
||||
int debug;
|
||||
|
||||
|
||||
vert_shader = GLSL_BuildShader (particle_trail_vert_effects);
|
||||
frag_shader = GLSL_BuildShader (particle_trail_frag_effects);
|
||||
debug_shader = GLSL_BuildShader (particle_trail_debug_frag_effects);
|
||||
|
@ -218,270 +191,143 @@ glsl_R_InitParticles (void)
|
|||
frag = GLSL_CompileShader ("trail.frag", frag_shader, GL_FRAGMENT_SHADER);
|
||||
debug = GLSL_CompileShader ("trail.frag.debug", debug_shader,
|
||||
GL_FRAGMENT_SHADER);
|
||||
trail.program = GLSL_LinkProgram ("trail", vert, frag);
|
||||
trail.debug_program = GLSL_LinkProgram ("trail.debug", vert, debug);
|
||||
trail_debug = trail;
|
||||
build_program (&trail, "trail", vert, frag);
|
||||
build_program (&trail_debug, "trail.debug", vert, debug);
|
||||
|
||||
GLSL_ResolveShaderParam (trail.program, &trail.proj);
|
||||
GLSL_ResolveShaderParam (trail.program, &trail.view);
|
||||
GLSL_ResolveShaderParam (trail.program, &trail.viewport);
|
||||
GLSL_ResolveShaderParam (trail.program, &trail.width);
|
||||
GLSL_ResolveShaderParam (trail.program, &trail.last);
|
||||
GLSL_ResolveShaderParam (trail.program, &trail.current);
|
||||
GLSL_ResolveShaderParam (trail.program, &trail.next);
|
||||
GLSL_ResolveShaderParam (trail.program, &trail.barycentric);
|
||||
GLSL_ResolveShaderParam (trail.program, &trail.texoff);
|
||||
GLSL_ResolveShaderParam (trail.program, &trail.colora);
|
||||
GLSL_ResolveShaderParam (trail.program, &trail.colorb);
|
||||
GLSL_FreeShader (vert_shader);
|
||||
GLSL_FreeShader (frag_shader);
|
||||
GLSL_FreeShader (debug_shader);
|
||||
|
||||
alloc_arrays (&r_psystem);
|
||||
}
|
||||
|
||||
static void
|
||||
add_trail_to_ent (entity_t ent)
|
||||
static int
|
||||
count_bits (uint32_t v)
|
||||
{
|
||||
renderer_t *r = Ent_GetComponent (ent.id, scene_renderer, ent.reg);
|
||||
r->trail = new_trail ();
|
||||
r->trail->next = trails_active;
|
||||
r->trail->prev = &trails_active;
|
||||
r->trail->owner = &r->trail;
|
||||
if (trails_active)
|
||||
trails_active->prev = &r->trail->next;
|
||||
trails_active = r->trail;
|
||||
}
|
||||
|
||||
static inline point_t *
|
||||
new_trail_point (vec4f_t origin, float pscale, float percent)
|
||||
{
|
||||
point_t *point;
|
||||
//int ramp;
|
||||
|
||||
point = new_point ();
|
||||
*point = (point_t) {
|
||||
.p.pos = origin,
|
||||
.p.color = (vec4f_t) {1,1,1,1},//ramp3[ramp = mtwist_rand (&mt) & 3],XXX
|
||||
.p.tex = part_tex_smoke,
|
||||
.p.scale = pscale + percent * 4.0,
|
||||
.p.alpha = 0.5 + qfrandom (0.125) - percent * 0.40,
|
||||
.p.vel = {},
|
||||
.p.live = 2.0 - percent * 2.0,
|
||||
// .p.ramp = ramp,XXX
|
||||
// .p.physics = R_ParticlePhysics ("pt_float"),XXX pt_static for debug
|
||||
};
|
||||
|
||||
return point;
|
||||
}
|
||||
|
||||
static inline void
|
||||
add_point_to_trail (trail_t *trail, point_t *point)
|
||||
{
|
||||
*trail->head = point;
|
||||
trail->head = &point->next;
|
||||
trail->num_points++;
|
||||
}
|
||||
|
||||
static void __attribute__((used))//XXX
|
||||
R_RocketTrail_trail (entity_t ent)
|
||||
{
|
||||
transform_t transform = Entity_Transform (ent);
|
||||
renderer_t *renderer = Ent_GetComponent (ent.id, scene_renderer, ent.reg);
|
||||
vec4f_t *old_origin = Ent_GetComponent (ent.id, scene_old_origin, ent.reg);
|
||||
vec4f_t ent_origin = Transform_GetWorldPosition (transform);
|
||||
|
||||
vec4f_t vec = ent_origin - *old_origin;
|
||||
float maxlen = magnitudef (vec)[0];
|
||||
vec /= maxlen;
|
||||
|
||||
if (!renderer->trail) {
|
||||
add_trail_to_ent (ent);
|
||||
}
|
||||
trail_t *trail = renderer->trail;
|
||||
|
||||
float origlen = vr_data.frametime / maxlen;
|
||||
float pscale = 1.5 + qfrandom (1.5);
|
||||
vec4f_t pos = *old_origin;
|
||||
float len = 0.0;
|
||||
|
||||
while (len < maxlen) {
|
||||
float pscalenext = 1.5 + qfrandom (1.5);
|
||||
float dist = (pscale + pscalenext) * 3.0;
|
||||
float percent = len * origlen;
|
||||
|
||||
point_t *point = new_trail_point (pos, pscale, percent);
|
||||
add_point_to_trail (trail, point);
|
||||
|
||||
len += dist;
|
||||
pos += dist * vec;
|
||||
pscale = pscalenext;
|
||||
int c = 0;
|
||||
for (; v; c++) {
|
||||
v &= v - 1;
|
||||
}
|
||||
return c;
|
||||
}
|
||||
|
||||
static inline void
|
||||
set_vertex (trailvtx_t *v, const point_t *point, float w, const vec3_t bary,
|
||||
float off)
|
||||
|
||||
static int
|
||||
count_points (uint32_t block_mask)
|
||||
{
|
||||
VectorCopy (point->p.pos, v->vertex);
|
||||
VectorCopy (bary, v->bary);
|
||||
v->vertex[3] = w * point->p.scale;// just w for debug
|
||||
v->texoff = off;
|
||||
VectorCopy (point->p.color, v->colora);
|
||||
v->colora[3] = point->p.alpha * 1.2;
|
||||
QuatSet (-1, -1, -1, -0.5, v->colorb);
|
||||
int num_blocks = count_bits (block_mask);
|
||||
return num_blocks * 64;
|
||||
}
|
||||
|
||||
static void
|
||||
count_points (int *num_verts)
|
||||
build_verts (trailvtx_t *verts, int *counts,
|
||||
const trailpnt_t *points, uint32_t block_mask)
|
||||
{
|
||||
trail_t *trail;
|
||||
|
||||
*num_verts = 0;
|
||||
for (trail = trails_active; trail; trail = trail->next) {
|
||||
if (trail->num_points < 2)
|
||||
uint32_t id = ~0u;
|
||||
for (int m = 0; m < 32; m++, points += 64) {
|
||||
if (!(block_mask & (1 << m))) {
|
||||
if (*counts) {
|
||||
counts++;
|
||||
}
|
||||
continue;
|
||||
// Each point has two vertices, thus the * 2. However, both the
|
||||
// first point and the last point need to be duplicated so the vertex
|
||||
// shader has valid data, thus need vertices for two extra points.
|
||||
*num_verts += (trail->num_points + 2) * 2;
|
||||
}
|
||||
if (id != ~0u && points->trailid != id) {
|
||||
counts++;
|
||||
}
|
||||
id = points->trailid;
|
||||
*counts += 64;
|
||||
for (int i = 0; i < 64; i++) {
|
||||
verts[i] = (trailvtx_t) {
|
||||
.vertex = points[i].pos,
|
||||
.bary = {VectorExpand (points[i].bary)},
|
||||
.texoff = points[i].pathoffset,
|
||||
.colora = { QuatExpand (points[i].colora)},
|
||||
.colorb = { QuatExpand (points[i].colorb)},
|
||||
};
|
||||
}
|
||||
verts += 64;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
build_verts (trailvtx_t *v)
|
||||
draw_trails (trailpnt_t *points, uint32_t block_mask)
|
||||
{
|
||||
trail_t *trail;
|
||||
point_t *point, *last_point = 0, *second_last_point = 0;
|
||||
point_t dup;
|
||||
float bary[] = {0, 0, 1, 0, 0, 1, 0, 0};
|
||||
int bind = 0;
|
||||
|
||||
memset (&dup, 0, sizeof (dup));
|
||||
for (trail = trails_active; trail; trail = trail->next) {
|
||||
int index = 0;
|
||||
if (trail->num_points < 2)
|
||||
continue;
|
||||
point = trail->points;
|
||||
dup.p.pos = 2 * point->p.pos;
|
||||
dup.p.pos -= point->next->p.pos;
|
||||
set_vertex (v++, &dup, -1, bary, 0);
|
||||
set_vertex (v++, &dup, +1, bary, 0);
|
||||
for (point = trail->points; point; point = point->next) {
|
||||
second_last_point = last_point;
|
||||
last_point = point;
|
||||
set_vertex (v++, point, -1, bary + bind++, index);
|
||||
set_vertex (v++, point, +1, bary + bind++, index);
|
||||
bind %= 3;
|
||||
index++;
|
||||
R_RunParticlePhysics (&point->p);
|
||||
}
|
||||
dup.p.pos = 2 * last_point->p.pos;
|
||||
dup.p.pos -= second_last_point->p.pos;
|
||||
set_vertex (v++, &dup, -1, bary, 0);
|
||||
set_vertex (v++, &dup, +1, bary, 0);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
expire_trails (void)
|
||||
{
|
||||
trail_t *trail, *next_trail;
|
||||
|
||||
for (trail = trails_active; trail; trail = next_trail) {
|
||||
next_trail = trail->next;
|
||||
while (trail->points && trail->points->p.live <= 0) {
|
||||
point_t *point = trail->points;
|
||||
trail->points = point->next;
|
||||
free_point (point);
|
||||
trail->num_points--;
|
||||
}
|
||||
if (trail->num_points < 2) {
|
||||
if (trail->next)
|
||||
trail->next->prev = trail->prev;
|
||||
*trail->prev = trail->next;
|
||||
*trail->owner = 0;
|
||||
free_trail (trail);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
draw_trails (void)
|
||||
{
|
||||
trail_t *trl;
|
||||
int num_verts;
|
||||
int first;
|
||||
trailvtx_t *verts;
|
||||
|
||||
count_points (&num_verts);
|
||||
if (!num_verts)
|
||||
int num_verts = count_points (block_mask);
|
||||
if (!num_verts) {
|
||||
return;
|
||||
|
||||
verts = alloca (num_verts * sizeof (trailvtx_t));
|
||||
build_verts (verts);
|
||||
|
||||
qfeglUseProgram (trail.program);
|
||||
qfeglEnableVertexAttribArray (trail.last.location);
|
||||
qfeglEnableVertexAttribArray (trail.current.location);
|
||||
qfeglEnableVertexAttribArray (trail.next.location);
|
||||
if (trail.barycentric.location >= 0)
|
||||
qfeglEnableVertexAttribArray (trail.barycentric.location);
|
||||
qfeglEnableVertexAttribArray (trail.texoff.location);
|
||||
qfeglEnableVertexAttribArray (trail.colora.location);
|
||||
qfeglEnableVertexAttribArray (trail.colorb.location);
|
||||
|
||||
qfeglUniformMatrix4fv (trail.proj.location, 1, false,
|
||||
(vec_t*)&glsl_projection[0]);//FIXME
|
||||
qfeglUniformMatrix4fv (trail.view.location, 1, false,
|
||||
(vec_t*)&glsl_view[0]);//FIXME
|
||||
qfeglUniform2f (trail.viewport.location, r_refdef.vrect.width,
|
||||
r_refdef.vrect.height);
|
||||
qfeglUniform1f (trail.width.location, 10);
|
||||
|
||||
qfeglVertexAttribPointer (trail.last.location, 4, GL_FLOAT,
|
||||
0, sizeof (trailvtx_t), &verts[0].vertex);
|
||||
qfeglVertexAttribPointer (trail.current.location, 4, GL_FLOAT,
|
||||
0, sizeof (trailvtx_t), &verts[2].vertex);
|
||||
qfeglVertexAttribPointer (trail.next.location, 4, GL_FLOAT,
|
||||
0, sizeof (trailvtx_t), &verts[4].vertex);
|
||||
if (trail.barycentric.location >= 0)
|
||||
qfeglVertexAttribPointer (trail.barycentric.location, 3, GL_FLOAT,
|
||||
0, sizeof (trailvtx_t), &verts[2].bary);
|
||||
qfeglVertexAttribPointer (trail.texoff.location, 1, GL_FLOAT,
|
||||
0, sizeof (trailvtx_t), &verts[0].texoff);
|
||||
qfeglVertexAttribPointer (trail.colora.location, 4, GL_FLOAT,
|
||||
0, sizeof (trailvtx_t), &verts[0].colora);
|
||||
qfeglVertexAttribPointer (trail.colorb.location, 4, GL_FLOAT,
|
||||
0, sizeof (trailvtx_t), &verts[0].colorb);
|
||||
|
||||
for (first = 0, trl = trails_active; trl; trl = trl->next) {
|
||||
int count;
|
||||
if (trl->num_points < 2)
|
||||
continue;
|
||||
count = trl->num_points * 2;
|
||||
qfeglDrawArrays (GL_TRIANGLE_STRIP, first, count);
|
||||
first += count + 4;
|
||||
}
|
||||
|
||||
qfeglDisableVertexAttribArray (trail.last.location);
|
||||
qfeglDisableVertexAttribArray (trail.current.location);
|
||||
qfeglDisableVertexAttribArray (trail.next.location);
|
||||
if (trail.barycentric.location >= 0)
|
||||
qfeglDisableVertexAttribArray (trail.barycentric.location);
|
||||
qfeglDisableVertexAttribArray (trail.texoff.location);
|
||||
qfeglDisableVertexAttribArray (trail.colora.location);
|
||||
qfeglDisableVertexAttribArray (trail.colorb.location);
|
||||
trailvtx_t verts[num_verts];
|
||||
int counts[33] = {};
|
||||
build_verts (verts, counts, points, block_mask);
|
||||
|
||||
expire_trails ();
|
||||
auto prog = trail;
|
||||
qfeglUseProgram (prog.program);
|
||||
qfeglEnableVertexAttribArray (prog.last.location);
|
||||
qfeglEnableVertexAttribArray (prog.current.location);
|
||||
qfeglEnableVertexAttribArray (prog.next.location);
|
||||
if (prog.barycentric.location >= 0)
|
||||
qfeglEnableVertexAttribArray (prog.barycentric.location);
|
||||
qfeglEnableVertexAttribArray (prog.texoff.location);
|
||||
if (prog.colora.location >= 0)
|
||||
qfeglEnableVertexAttribArray (prog.colora.location);
|
||||
if (prog.colorb.location >= 0)
|
||||
qfeglEnableVertexAttribArray (prog.colorb.location);
|
||||
|
||||
qfeglUniformMatrix4fv (prog.proj.location, 1, false,
|
||||
(vec_t*)&glsl_projection[0]);//FIXME
|
||||
qfeglUniformMatrix4fv (prog.view.location, 1, false,
|
||||
(vec_t*)&glsl_view[0]);//FIXME
|
||||
qfeglUniform2f (prog.viewport.location, r_refdef.vrect.width,
|
||||
r_refdef.vrect.height);
|
||||
qfeglUniform1f (prog.width.location, 10);
|
||||
|
||||
qfeglVertexAttribPointer (prog.last.location, 4, GL_FLOAT,
|
||||
0, sizeof (trailvtx_t), &verts[0].vertex);
|
||||
qfeglVertexAttribPointer (prog.current.location, 4, GL_FLOAT,
|
||||
0, sizeof (trailvtx_t), &verts[2].vertex);
|
||||
qfeglVertexAttribPointer (prog.next.location, 4, GL_FLOAT,
|
||||
0, sizeof (trailvtx_t), &verts[4].vertex);
|
||||
if (prog.barycentric.location >= 0)
|
||||
qfeglVertexAttribPointer (prog.barycentric.location, 3, GL_FLOAT,
|
||||
0, sizeof (trailvtx_t), &verts[2].bary);
|
||||
qfeglVertexAttribPointer (prog.texoff.location, 1, GL_FLOAT,
|
||||
0, sizeof (trailvtx_t), &verts[0].texoff);
|
||||
if (prog.colora.location >= 0)
|
||||
qfeglVertexAttribPointer (prog.colora.location, 4, GL_UNSIGNED_BYTE,
|
||||
1, sizeof (trailvtx_t), &verts[0].colora);
|
||||
if (prog.colorb.location >= 0)
|
||||
qfeglVertexAttribPointer (prog.colorb.location, 4, GL_UNSIGNED_BYTE,
|
||||
1, sizeof (trailvtx_t), &verts[0].colorb);
|
||||
|
||||
int first = 0;
|
||||
for (auto c = counts; *c; c++) {
|
||||
qfeglDrawArrays (GL_TRIANGLE_STRIP, first, *c - 4);
|
||||
first += *c;
|
||||
}
|
||||
|
||||
qfeglDisableVertexAttribArray (prog.last.location);
|
||||
qfeglDisableVertexAttribArray (prog.current.location);
|
||||
qfeglDisableVertexAttribArray (prog.next.location);
|
||||
if (prog.barycentric.location >= 0)
|
||||
qfeglDisableVertexAttribArray (prog.barycentric.location);
|
||||
qfeglDisableVertexAttribArray (prog.texoff.location);
|
||||
if (prog.colora.location >= 0)
|
||||
qfeglDisableVertexAttribArray (prog.colora.location);
|
||||
if (prog.colorb.location >= 0)
|
||||
qfeglDisableVertexAttribArray (prog.colorb.location);
|
||||
}
|
||||
|
||||
static void __attribute__((used))//XXX
|
||||
void
|
||||
glsl_R_DrawTrails (psystem_t *psystem)
|
||||
{
|
||||
draw_trails ();
|
||||
//FIXME abuse of psystem_t
|
||||
draw_trails ((trailpnt_t *)psystem->particles, psystem->numparticles);
|
||||
}
|
||||
|
||||
static psystem_t * __attribute__((const,used))//FIXME XXX
|
||||
psystem_t * __attribute__((const))//FIXME
|
||||
glsl_TrailSystem (void)
|
||||
{
|
||||
return &r_psystem;
|
||||
return &r_tsystem;
|
||||
}
|
||||
|
|
|
@ -614,4 +614,5 @@ R_Init_Cvars (void)
|
|||
r_data->scr_viewsize = &scr_viewsize;
|
||||
|
||||
R_Particles_Init_Cvars ();
|
||||
R_Trails_Init_Cvars ();
|
||||
}
|
||||
|
|
|
@ -105,4 +105,5 @@ R_Init (void)
|
|||
r_funcs->R_Init ();
|
||||
R_ClearEfrags (); //FIXME force link of r_efrag.o for qwaq
|
||||
Fog_Init ();
|
||||
R_Trails_Init ();
|
||||
}
|
||||
|
|
|
@ -29,7 +29,6 @@
|
|||
#endif
|
||||
|
||||
#include "QF/cvar.h"
|
||||
#include "QF/qargs.h"
|
||||
#include "QF/render.h"
|
||||
#include "QF/sys.h"
|
||||
|
||||
|
|
|
@ -190,6 +190,9 @@ render_scene (void)
|
|||
EntQueue_Clear (r_ent_queue);
|
||||
r_funcs->render_view ();
|
||||
r_funcs->draw_particles (&r_psystem);
|
||||
if (r_funcs->draw_trails) {
|
||||
r_funcs->draw_trails (&r_tsystem);
|
||||
}
|
||||
r_funcs->draw_transparent ();
|
||||
}
|
||||
|
||||
|
|
219
libs/video/renderer/r_trails.c
Normal file
219
libs/video/renderer/r_trails.c
Normal file
|
@ -0,0 +1,219 @@
|
|||
/*
|
||||
r_trails.c
|
||||
|
||||
Interface for trails
|
||||
|
||||
Copyright (C) 2023 Bill Currie <bill@taniwha.org>
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License
|
||||
as published by the Free Software Foundation; either version 2
|
||||
of the License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
|
||||
See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to:
|
||||
|
||||
Free Software Foundation, Inc.
|
||||
59 Temple Place - Suite 330
|
||||
Boston, MA 02111-1307, USA
|
||||
|
||||
*/
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include "config.h"
|
||||
#endif
|
||||
|
||||
#include "QF/cvar.h"
|
||||
#include "QF/ecs.h"
|
||||
#include "QF/render.h"
|
||||
#include "QF/sys.h"
|
||||
|
||||
#include "QF/simd/vec4f.h"
|
||||
|
||||
#include "r_dynamic.h"
|
||||
|
||||
psystem_t r_tsystem; //FIXME singleton
|
||||
static ecs_system_t trails_system;
|
||||
static trailpnt_t *trail_point_buffer;
|
||||
static uint32_t trail_point_count;
|
||||
static uint32_t trail_point_buffer_size;
|
||||
static uint32_t allocated_blocks; // bitmask of 64-point blocks in use
|
||||
|
||||
typedef struct {
|
||||
uint32_t base;
|
||||
uint32_t count;
|
||||
} pointset_t;
|
||||
|
||||
enum trails_components {
|
||||
trails_pointset,
|
||||
|
||||
trails_comp_count
|
||||
};
|
||||
|
||||
static void
|
||||
destroy_pointset (void *comp)
|
||||
{
|
||||
pointset_t *pointset = comp;
|
||||
int base = pointset->base / 64;
|
||||
int count = pointset->count / 64;
|
||||
uint32_t mask = ((1 << count) - 1) << base;
|
||||
allocated_blocks &= ~mask;
|
||||
r_tsystem.numparticles = allocated_blocks;
|
||||
}
|
||||
|
||||
static const component_t trails_components[trails_comp_count] = {
|
||||
[trails_pointset] = {
|
||||
.size = sizeof (pointset_t),
|
||||
.create = 0,
|
||||
.name = "pointset",
|
||||
.destroy = destroy_pointset,
|
||||
},
|
||||
};
|
||||
|
||||
bool
|
||||
R_Trail_Valid (psystem_t *system, uint32_t trailid)
|
||||
{
|
||||
return ECS_EntValid (trailid, trails_system.reg);
|
||||
}
|
||||
|
||||
uint32_t
|
||||
R_Trail_Create (psystem_t *system, int num_points, vec4f_t start)
|
||||
{
|
||||
num_points += 2; // need an extra point at either end
|
||||
num_points = (num_points + 31) & ~31; // want a multiple of 32
|
||||
num_points *= 2; // each point needs two verts
|
||||
|
||||
int blocks = num_points / 64;
|
||||
uint32_t mask = (1 << blocks) - 1;
|
||||
int block_ind;
|
||||
for (block_ind = 0; block_ind <= 32 - blocks; block_ind++) {
|
||||
if (!(allocated_blocks & mask)) {
|
||||
break;
|
||||
}
|
||||
mask <<= 1;
|
||||
}
|
||||
if (allocated_blocks & mask) {
|
||||
return nullent;
|
||||
}
|
||||
allocated_blocks |= mask;
|
||||
r_tsystem.numparticles = allocated_blocks;
|
||||
|
||||
uint32_t trail = ECS_NewEntity (trails_system.reg);
|
||||
pointset_t pointset = {
|
||||
.base = block_ind * 64,
|
||||
.count = num_points,
|
||||
};
|
||||
Ent_SetComponent (trail, trails_pointset, trails_system.reg, &pointset);
|
||||
for (uint32_t i = 0; i < pointset.count; i++) {
|
||||
static float bary[] = {0, 0, 1, 0, 0, 1, 0, 0};
|
||||
auto p = trail_point_buffer + pointset.base + i;
|
||||
*p = (trailpnt_t) {
|
||||
.pos = start,
|
||||
.colora = { 0xc0, 0xc0, 0xc0, 0xa0 },
|
||||
.colorb = { 0x40, 0x40, 0x40, 0x40 },
|
||||
.trailid = trail,
|
||||
.live = 10,
|
||||
};
|
||||
p->pos[3] = i & 1 ? 1 : -1;
|
||||
VectorCopy (bary + i % 3, p->bary);
|
||||
};
|
||||
return trail;
|
||||
}
|
||||
|
||||
void
|
||||
R_Trail_Update (psystem_t *system, uint32_t trailid, vec4f_t pos)
|
||||
{
|
||||
pointset_t *p = Ent_GetComponent (trailid, trails_pointset,
|
||||
trails_system.reg);
|
||||
|
||||
trailpnt_t *points = trail_point_buffer + p->base;
|
||||
|
||||
pos[3] = -1;
|
||||
vec4f_t dist = pos - points[4].pos;
|
||||
vec4f_t prev1 = points[2].pos;
|
||||
vec4f_t prev2 = points[3].pos;
|
||||
points[2].pos = pos;
|
||||
pos[3] = 1;
|
||||
points[3].pos = pos;
|
||||
|
||||
points[0].pos = points[2].pos + dist;
|
||||
points[1].pos = points[3].pos + dist;
|
||||
|
||||
if (dotf (dist, dist)[0] > 128) {
|
||||
for (uint32_t i = 4; i < p->count; i += 2) {
|
||||
vec4f_t t1 = points[i + 0].pos;
|
||||
vec4f_t t2 = points[i + 1].pos;
|
||||
points[i + 0].pos = prev1;
|
||||
points[i + 1].pos = prev2;
|
||||
prev1 = t1;
|
||||
prev2 = t2;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
R_Trail_Destroy (psystem_t *system, uint32_t trailid)
|
||||
{
|
||||
ECS_DelEntity (trails_system.reg, trailid);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
R_ClearTrails (void)
|
||||
{
|
||||
auto reg = trails_system.reg;
|
||||
for (uint32_t i = 0; i < reg->num_entities; i++) {
|
||||
uint32_t ent = reg->entities[i];
|
||||
uint32_t ind = Ent_Index (ent);
|
||||
if (ind == i) {
|
||||
ECS_DelEntity (reg, ent);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
R_RunTrails (float dT)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
R_Trails_Init_Cvars (void)
|
||||
{
|
||||
Sys_Printf ("R_Trails_Init_Cvars\n");
|
||||
}
|
||||
|
||||
static void
|
||||
trails_shutdown (void *data)
|
||||
{
|
||||
Sys_Printf ("trails_shutdown\n");
|
||||
ECS_DelRegistry (trails_system.reg);
|
||||
Sys_Free (trail_point_buffer, trail_point_buffer_size);
|
||||
}
|
||||
|
||||
void
|
||||
R_Trails_Init (void)
|
||||
{
|
||||
Sys_Printf ("R_Trails_Init\n");
|
||||
Sys_RegisterShutdown (trails_shutdown, 0);
|
||||
auto reg = ECS_NewRegistry ();
|
||||
trails_system.reg = reg;
|
||||
trails_system.base = ECS_RegisterComponents (reg, trails_components,
|
||||
trails_comp_count);
|
||||
ECS_CreateComponentPools (reg);
|
||||
|
||||
trail_point_count = 32*64;
|
||||
trail_point_buffer_size = trail_point_count * sizeof (trailpnt_t);
|
||||
trail_point_buffer = Sys_Alloc (trail_point_buffer_size);
|
||||
|
||||
r_tsystem = (psystem_t) {
|
||||
.maxparticles = trail_point_count,
|
||||
.particles = (particle_t *) trail_point_buffer,
|
||||
.partparams = 0,//FIXME
|
||||
.partramps = 0,//FIXME
|
||||
};
|
||||
}
|
|
@ -477,6 +477,7 @@ vid_render_funcs_t glsl_vid_render_funcs = {
|
|||
.Draw_Glyph = glsl_Draw_Glyph,
|
||||
|
||||
.ParticleSystem = glsl_ParticleSystem,
|
||||
.TrailSystem = glsl_TrailSystem,
|
||||
.R_Init = glsl_R_Init,
|
||||
.R_ClearState = glsl_R_ClearState,
|
||||
.R_LoadSkys = glsl_R_LoadSkys,
|
||||
|
@ -485,6 +486,7 @@ vid_render_funcs_t glsl_vid_render_funcs = {
|
|||
.begin_frame = glsl_begin_frame,
|
||||
.render_view = glsl_render_view,
|
||||
.draw_particles = glsl_R_DrawParticles,
|
||||
.draw_trails = glsl_R_DrawTrails,
|
||||
.draw_transparent = glsl_draw_transparent,
|
||||
.post_process = glsl_post_process,
|
||||
.set_2d = glsl_set_2d,
|
||||
|
|
|
@ -59,6 +59,7 @@
|
|||
#include "compat.h"
|
||||
|
||||
#include "client/chase.h"
|
||||
#include "client/effects.h"
|
||||
#include "client/particles.h"
|
||||
#include "client/sbar.h"
|
||||
#include "client/screen.h"
|
||||
|
@ -737,6 +738,7 @@ CL_Init (cbuf_t *cbuf)
|
|||
|
||||
CL_Init_Input (cbuf);
|
||||
CL_Particles_Init ();
|
||||
CL_Effects_Init ();
|
||||
CL_TEnts_Init ();
|
||||
CL_World_Init ();
|
||||
CL_ClearState ();
|
||||
|
|
|
@ -98,6 +98,7 @@
|
|||
#include "buildnum.h"
|
||||
#include "compat.h"
|
||||
|
||||
#include "client/effects.h"
|
||||
#include "client/particles.h"
|
||||
#include "client/sbar.h"
|
||||
#include "client/screen.h"
|
||||
|
@ -1488,6 +1489,7 @@ CL_Init (void)
|
|||
CL_Init_Input (cl_cbuf);
|
||||
CL_Ents_Init ();
|
||||
CL_Particles_Init ();
|
||||
CL_Effects_Init ();
|
||||
CL_TEnts_Init ();
|
||||
CL_World_Init ();
|
||||
CL_ClearState ();
|
||||
|
|
Loading…
Reference in a new issue