[glsl] Separate out the trails implementation

This gets things *compiling* again, though it's still non-functional and
definitely wrong (don't want trail in renderer_t), but I need to think
about the design for getting trails as components. Also need to think
about integrating trails into the client effects system so trails can be
shared between renderers.
This commit is contained in:
Bill Currie 2023-10-03 13:49:25 +09:00
parent 6423c13108
commit c5731374cd
4 changed files with 476 additions and 349 deletions

View file

@ -75,6 +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
unsigned fullbright:1;
unsigned noshadows:1;
unsigned onlyshadows:1;

View file

@ -135,6 +135,7 @@ libs_video_renderer_librender_glsl_la_SOURCES = \
libs/video/renderer/glsl/glsl_shader.c \
libs/video/renderer/glsl/glsl_sprite.c \
libs/video/renderer/glsl/glsl_textures.c \
libs/video/renderer/glsl/glsl_trails.c \
libs/video/renderer/glsl/glsl_warp.c \
libs/video/renderer/glsl/qfglsl.c \
libs/video/renderer/glsl/quakeforge.glsl \

View file

@ -98,24 +98,6 @@ static const char *particle_textured_frag_effects[] =
0
};
static const char *particle_trail_vert_effects[] =
{
"QuakeForge.Screen.viewport",
"QuakeForge.Vertex.transform.view_projection",
"QuakeForge.Vertex.ScreenSpace.curve.width",
"QuakeForge.Vertex.particle.trail",
0
};
static const char *particle_trail_frag_effects[] =
{
"QuakeForge.Math.InvSqrt",
"QuakeForge.Math.permute",
"QuakeForge.Noise.simplex",
"QuakeForge.Fragment.particle.trail",
0
};
static struct {
int program;
shaderparam_t mvp_matrix;
@ -150,84 +132,6 @@ static struct {
{"fog", 1},
};
static struct {
int program;
shaderparam_t proj;
shaderparam_t view;
shaderparam_t viewport;
shaderparam_t width;
shaderparam_t last;
shaderparam_t current;
shaderparam_t next;
shaderparam_t barycentric;
shaderparam_t texoff;
shaderparam_t colora;
shaderparam_t colorb;
} trail = {
0,
{"projection_mat", 1},
{"view_mat", 1},
{"viewport", 1},
{"width", 1},
{"last", 0},
{"current", 0},
{"next", 0},
{"barycentric", 0},
{"texoff", 0},
{"vcolora", 0},
{"vcolorb", 0},
};
#if 0
typedef struct trail_s {
struct trail_s *next;
struct trail_s **prev;
struct trail_s **owner;
particle_t *points;
particle_t **head; // new points are appended to the list
int num_points;
} trail_t;
typedef struct trailvtx_s {
quat_t vertex;
vec3_t bary;
float texoff;
quat_t colora;
quat_t colorb;
} trailvtx_t;
ALLOC_STATE (trail_t, trails);
ALLOC_STATE (particle_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 particle_t *
new_point (void)
{
particle_t *point;
ALLOC (128, particle_t, points, point);
return point;
}
static void
free_point (particle_t *point)
{
FREE (points, point);
}
#endif
static void
alloc_arrays (psystem_t *ps)
{
@ -316,25 +220,6 @@ glsl_R_InitParticles (void)
GLSL_FreeShader (vert_shader);
GLSL_FreeShader (frag_shader);
vert_shader = GLSL_BuildShader (particle_trail_vert_effects);
frag_shader = GLSL_BuildShader (particle_trail_frag_effects);
vert = GLSL_CompileShader ("trail.vert", vert_shader, GL_VERTEX_SHADER);
frag = GLSL_CompileShader ("trail.frag", frag_shader, GL_FRAGMENT_SHADER);
trail.program = GLSL_LinkProgram ("trail", vert, frag);
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);
memset (data, 0, sizeof (data));
qfeglGenTextures (1, &part_tex);
qfeglBindTexture (GL_TEXTURE_2D, part_tex);
@ -357,238 +242,7 @@ glsl_R_InitParticles (void)
alloc_arrays (&r_psystem);
}
#if 0
static void
add_trail_to_ent (entity_t *ent)
{
ent->trail = new_trail ();
ent->trail->next = trails_active;
ent->trail->prev = &trails_active;
ent->trail->owner = &ent->trail;
if (trails_active)
trails_active->prev = &ent->trail->next;
trails_active = ent->trail;
}
static inline particle_t *
new_trail_point (const vec3_t origin, float pscale, float percent)
{
particle_t *point;
int ramp;
point = new_point ();
VectorCopy (origin, point->org);
point->color = ramp3[ramp = mtwist_rand (&mt) & 3];
point->tex = part_tex_smoke;
point->scale = pscale + percent * 4.0;
point->alpha = 0.5 + qfrandom (0.125) - percent * 0.40;
VectorCopy (vec3_origin, point->vel);
point->die = vr_data.realtime + 2.0 - percent * 2.0;
point->ramp = ramp;
point->physics = R_ParticlePhysics ("pt_float");
return point;
}
static inline void
add_point_to_trail (trail_t *trail, particle_t *point)
{
*trail->head = point;
trail->head = &point->next;
trail->num_points++;
}
static void
R_RocketTrail_trail (entity_t *ent)
{
float dist, maxlen, origlen, percent, pscale, pscalenext;
float len = 0.0;
vec3_t old_origin, vec;
particle_t *point;
if (!ent->trail) {
add_trail_to_ent (ent);
}
VectorCopy (ent->old_origin, old_origin);
VectorSubtract (ent->origin, old_origin, vec);
maxlen = VectorNormalize (vec);
origlen = vr_data.frametime / maxlen;
pscale = 1.5 + qfrandom (1.5);
while (len < maxlen) {
pscalenext = 1.5 + qfrandom (1.5);
dist = (pscale + pscalenext) * 3.0;
percent = len * origlen;
point = new_trail_point (old_origin, pscale, percent);
add_point_to_trail (ent->trail, point);
len += dist;
VectorMultAdd (old_origin, len, vec, old_origin);
pscale = pscalenext;
}
}
static inline void
set_vertex (trailvtx_t *v, const particle_t *point, float w, const vec3_t bary,
float off)
{
byte *color = (byte *) &d_8to24table[(byte) point->color];
VectorCopy (point->org, v->vertex);
VectorCopy (bary, v->bary);
v->vertex[3] = w * point->scale;
v->texoff = off;
VectorScale (color, 1.5 / 255, v->colora);
v->colora[3] = point->alpha * 1.2;
QuatSet (-1, -1, -1, -0.5, v->colorb);
}
static void
count_points (int *num_verts)
{
trail_t *trail;
*num_verts = 0;
for (trail = trails_active; trail; trail = trail->next) {
if (trail->num_points < 2)
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 (even though the distance between points will
// be 0), thus need vertices for two extra points.
*num_verts += (trail->num_points + 2) * 2;
}
}
static void
build_verts (trailvtx_t *v)
{
trail_t *trail;
particle_t *point, *last_point = 0, *second_last_point = 0;
particle_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;
VectorScale (point->org, 2, dup.org);
VectorSubtract (dup.org, point->next->org, dup.org);
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);
}
VectorScale (last_point->org, 2, dup.org);
VectorSubtract (dup.org, second_last_point->org, dup.org);
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->die <= vr_data.realtime) {
particle_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)
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, glsl_projection);
qfeglUniformMatrix4fv (trail.view.location, 1, false, glsl_view);
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);
expire_trails ();
}
#endif
static void
draw_qf_particles (psystem_t *psystem)
{
@ -780,9 +434,6 @@ draw_id_particles (psystem_t *psystem)
void
glsl_R_DrawParticles (psystem_t *psystem)
{
#if 0
draw_trails ();
#endif
if (!psystem->numparticles) {
return;
}

View file

@ -0,0 +1,474 @@
/*
glsl_trails.c
OpenGL trail system.
Copyright (C) 2013 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
#ifdef HAVE_STRING_H
# include <string.h>
#endif
#ifdef HAVE_STRINGS_H
# include <strings.h>
#endif
#include <stdlib.h>
#include "QF/alloc.h"
#include "QF/cmd.h"
#include "QF/cvar.h"
#include "QF/image.h"
#include "QF/mersenne.h"
#include "QF/qargs.h"
#include "QF/quakefs.h"
#include "QF/render.h"
#include "QF/sys.h"
#include "QF/va.h"
#include "QF/scene/entity.h"
#include "QF/GLSL/defines.h"
#include "QF/GLSL/funcs.h"
#include "QF/GLSL/qf_particles.h"
#include "QF/GLSL/qf_textures.h"
#include "QF/GLSL/qf_vid.h"
#include "r_internal.h"
#include "r_local.h"
static uint32_t maxparticles;
static GLushort *pVAindices;
static partvert_t *particleVertexArray;
static const char *particle_trail_vert_effects[] =
{
"QuakeForge.Screen.viewport",
"QuakeForge.Vertex.transform.view_projection",
"QuakeForge.Vertex.ScreenSpace.curve.width",
"QuakeForge.Vertex.particle.trail",
0
};
static const char *particle_trail_frag_effects[] =
{
"QuakeForge.Math.InvSqrt",
"QuakeForge.Math.permute",
"QuakeForge.Noise.simplex",
"QuakeForge.Fragment.particle.trail",
0
};
static struct {
int program;
shaderparam_t proj;
shaderparam_t view;
shaderparam_t viewport;
shaderparam_t width;
shaderparam_t last;
shaderparam_t current;
shaderparam_t next;
shaderparam_t barycentric;
shaderparam_t texoff;
shaderparam_t colora;
shaderparam_t colorb;
} trail = {
0,
{"projection_mat", 1},
{"view_mat", 1},
{"viewport", 1},
{"width", 1},
{"last", 0},
{"current", 0},
{"next", 0},
{"barycentric", 0},
{"texoff", 0},
{"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;
typedef struct trailvtx_s {
quat_t vertex;
vec3_t bary;
float texoff;
quat_t colora;
quat_t colorb;
} 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)
{
if (ps->maxparticles > maxparticles) {
maxparticles = ps->maxparticles;
if (particleVertexArray)
free (particleVertexArray);
printf ("alloc_arrays: %d\n", ps->maxparticles);
particleVertexArray = calloc (ps->maxparticles * 4,
sizeof (partvert_t));
if (pVAindices)
free (pVAindices);
pVAindices = calloc (ps->maxparticles * 6, sizeof (GLushort));
for (uint32_t i = 0; i < ps->maxparticles; i++) {
pVAindices[i * 6 + 0] = i * 4 + 0;
pVAindices[i * 6 + 1] = i * 4 + 1;
pVAindices[i * 6 + 2] = i * 4 + 2;
pVAindices[i * 6 + 3] = i * 4 + 0;
pVAindices[i * 6 + 4] = i * 4 + 2;
pVAindices[i * 6 + 5] = i * 4 + 3;
}
}
}
void
glsl_R_ShutdownParticles (void)
{
free (particleVertexArray);
free (pVAindices);
}
void
glsl_R_InitParticles (void)
{
shader_t *vert_shader, *frag_shader;
int vert;
int frag;
vert_shader = GLSL_BuildShader (particle_trail_vert_effects);
frag_shader = GLSL_BuildShader (particle_trail_frag_effects);
vert = GLSL_CompileShader ("trail.vert", vert_shader, GL_VERTEX_SHADER);
frag = GLSL_CompileShader ("trail.frag", frag_shader, GL_FRAGMENT_SHADER);
trail.program = GLSL_LinkProgram ("trail", vert, frag);
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);
alloc_arrays (&r_psystem);
}
static void
add_trail_to_ent (entity_t ent)
{
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
};
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;
}
}
static inline void
set_vertex (trailvtx_t *v, const point_t *point, float w, const vec3_t bary,
float off)
{
VectorCopy (point->p.pos, v->vertex);
VectorCopy (bary, v->bary);
v->vertex[3] = w * point->p.scale;
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);
}
static void
count_points (int *num_verts)
{
trail_t *trail;
*num_verts = 0;
for (trail = trails_active; trail; trail = trail->next) {
if (trail->num_points < 2)
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;
}
}
static void
build_verts (trailvtx_t *v)
{
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)
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);
expire_trails ();
}
static void __attribute__((used))//XXX
glsl_R_DrawTrails (psystem_t *psystem)
{
draw_trails ();
}
static psystem_t * __attribute__((const,used))//FIXME XXX
glsl_TrailSystem (void)
{
return &r_psystem;
}