Update the trails code to use shader effects.

Trails was actually the reason I started that project. This is just cleanup
after rebasing.
This commit is contained in:
Bill Currie 2014-01-28 16:45:36 +09:00
parent bb022bc4fc
commit 299f305453
5 changed files with 141 additions and 127 deletions

View file

@ -3,8 +3,8 @@ AUTOMAKE_OPTIONS= foreign
AM_CFLAGS= @PREFER_PIC@ AM_CFLAGS= @PREFER_PIC@
AM_CPPFLAGS= -I$(top_srcdir)/include $(GLX_CFLAGS) AM_CPPFLAGS= -I$(top_srcdir)/include $(GLX_CFLAGS)
shader_src= quakeforge.glsl trail.frag trail.vert shader_src= quakeforge.glsl
shader_gen= quakeforge.slc trail.fc trail.vc shader_gen= quakeforge.slc
glsl_src = \ glsl_src = \
glsl_alias.c glsl_bsp.c glsl_draw.c glsl_fog.c glsl_iqm.c glsl_lightmap.c \ glsl_alias.c glsl_bsp.c glsl_draw.c glsl_fog.c glsl_iqm.c glsl_lightmap.c \

View file

@ -107,13 +107,17 @@ static const char *particle_textured_frag_effects[] =
0 0
}; };
static const char trail_vert[] = static const char *particle_trail_vert_effects[] =
#include "trail.vc" {
; "QuakeForge.Vertex.particle.trail",
0
};
static const char trail_frag[] = static const char *particle_trail_frag_effects[] =
#include "trail.fc" {
; "QuakeForge.Fragment.particle.trail",
0
};
static struct { static struct {
int program; int program;
@ -190,9 +194,9 @@ typedef struct trailvtx_s {
float texoff; float texoff;
} trailvtx_t; } trailvtx_t;
static trail_t *free_trails; static trail_t *trails_freelist;
static trail_t *active_trails; static trail_t *trails_active;
static particle_t *free_points; static particle_t *points_freelist;
static trail_t * static trail_t *
new_trail (void) new_trail (void)
@ -350,8 +354,10 @@ glsl_R_InitParticles (void)
GLSL_FreeShader (vert_shader); GLSL_FreeShader (vert_shader);
GLSL_FreeShader (frag_shader); GLSL_FreeShader (frag_shader);
vert = GLSL_CompileShader ("trail.vert", trail_vert, GL_VERTEX_SHADER); vert_shader = GLSL_BuildShader (particle_trail_vert_effects);
frag = GLSL_CompileShader ("trail.frag", trail_frag, GL_FRAGMENT_SHADER); 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); trail.program = GLSL_LinkProgram ("trail", vert, frag);
GLSL_ResolveShaderParam (trail.program, &trail.proj); GLSL_ResolveShaderParam (trail.program, &trail.proj);
GLSL_ResolveShaderParam (trail.program, &trail.view); GLSL_ResolveShaderParam (trail.program, &trail.view);
@ -363,6 +369,8 @@ glsl_R_InitParticles (void)
GLSL_ResolveShaderParam (trail.program, &trail.barycentric); GLSL_ResolveShaderParam (trail.program, &trail.barycentric);
GLSL_ResolveShaderParam (trail.program, &trail.texoff); GLSL_ResolveShaderParam (trail.program, &trail.texoff);
GLSL_ResolveShaderParam (trail.program, &trail.smoke); GLSL_ResolveShaderParam (trail.program, &trail.smoke);
GLSL_FreeShader (vert_shader);
GLSL_FreeShader (frag_shader);
memset (data, 0, sizeof (data)); memset (data, 0, sizeof (data));
qfeglGenTextures (1, &part_tex); qfeglGenTextures (1, &part_tex);
@ -730,12 +738,12 @@ R_RocketTrail_trail (entity_t *ent)
if (!ent->trail) { if (!ent->trail) {
ent->trail = new_trail (); ent->trail = new_trail ();
ent->trail->next = active_trails; ent->trail->next = trails_active;
ent->trail->prev = &active_trails; ent->trail->prev = &trails_active;
ent->trail->owner = &ent->trail; ent->trail->owner = &ent->trail;
if (active_trails) if (trails_active)
active_trails->prev = &ent->trail->next; trails_active->prev = &ent->trail->next;
active_trails = ent->trail; trails_active = ent->trail;
} }
VectorCopy (ent->old_origin, old_origin); VectorCopy (ent->old_origin, old_origin);
@ -1723,7 +1731,7 @@ count_points (int *num_verts, int *num_elements)
*num_verts = 0; *num_verts = 0;
*num_elements = 0; *num_elements = 0;
for (trail = active_trails; trail; trail = trail->next) { for (trail = trails_active; trail; trail = trail->next) {
if (trail->num_points < 2) if (trail->num_points < 2)
continue; continue;
// +2 for an extra point at either end of the strip // +2 for an extra point at either end of the strip
@ -1741,7 +1749,7 @@ build_verts (trailvtx_t *v, GLushort *e)
float bary[] = {0, 0, 1, 0, 0, 1, 0, 0}; float bary[] = {0, 0, 1, 0, 0, 1, 0, 0};
int bind = 0; int bind = 0;
for (trail = active_trails; trail; trail = trail->next) { for (trail = trails_active; trail; trail = trail->next) {
if (trail->num_points < 2) if (trail->num_points < 2)
continue; continue;
point = trail->points; point = trail->points;
@ -1768,7 +1776,7 @@ expire_trails (void)
{ {
trail_t *trail, *next_trail; trail_t *trail, *next_trail;
for (trail = active_trails; trail; trail = next_trail) { for (trail = trails_active; trail; trail = next_trail) {
next_trail = trail->next; next_trail = trail->next;
while (trail->points && trail->points->die <= vr_data.realtime) { while (trail->points && trail->points->die <= vr_data.realtime) {
particle_t *point = trail->points; particle_t *point = trail->points;
@ -1827,7 +1835,7 @@ draw_trails (void)
qfeglVertexAttribPointer (trail.texoff.location, 1, GL_FLOAT, qfeglVertexAttribPointer (trail.texoff.location, 1, GL_FLOAT,
0, sizeof (trailvtx_t), &verts[0].texoff); 0, sizeof (trailvtx_t), &verts[0].texoff);
for (trl = active_trails; trl; trl = trl->next) { for (trl = trails_active; trl; trl = trl->next) {
int count; int count;
if (trl->num_points < 2) if (trl->num_points < 2)
continue; continue;

View file

@ -551,3 +551,114 @@ main (void)
col = texture2D (texture, st) * color * vec4 (l, 1.0); col = texture2D (texture, st) * color * vec4 (l, 1.0);
gl_FragColor = fogBlend (col); gl_FragColor = fogBlend (col);
} }
-- Vertex.particle.trail
attribute vec4 last, current, next;
attribute vec3 barycentric;
attribute float texoff;
uniform mat4 proj, view;
uniform vec2 viewport;
uniform float width;
varying vec2 texcoord;
varying vec3 vBC;
vec4
transform (vec3 coord)
{
return proj * view * vec4 (coord, 1.0);
}
vec2
project (vec4 coord)
{
vec3 device = coord.xyz / coord.w;
vec2 clip = (device * 0.5 + 0.5).xy;
return clip * viewport;
}
vec4
unproject (vec2 screen, float z, float w)
{
vec2 clip = screen / viewport;
vec2 device = clip * 2.0 - 1.0;
return vec4 (device * w, z, w);
}
float
estimateScale (vec3 position, vec2 sPosition)
{
vec4 view_pos = view * vec4 (position, 1.0);
vec4 scale_pos = view_pos - vec4 (normalize (view_pos.xy) * width,
0.0, 0.0);
vec2 screen_scale_pos = project (proj * scale_pos);
return distance (sPosition, screen_scale_pos);
}
void
main (void)
{
vec2 t, n1, n2, n;
vec2 sLast = project (transform (last.xyz));
vec2 sNext = project (transform (next.xyz));
vec4 dCurrent = transform (current.xyz);
vec2 sCurrent = project (dCurrent);
float off = current.w;
texcoord = vec2 (texoff * 0.7, off * 0.5 + 0.5);
vBC = barycentric;
t = sLast - sCurrent;
n1 = vec2 (0.0);
if (dot (t, t) > 0.001)
n1 = normalize (t);
t = sCurrent - sNext;
n2 = vec2 (0.0);
if (dot (t, t) > 0.001)
n2 = normalize (t);
n = vec2 (0.0);
if (n1 != -n2)
n = normalize (n1 + n2);
else if (dot (n1, n1) > 0.001)
n = n1;
else if (dot (n2, n2) > 0.001)
n = n2;
// rotate the normal by 90 degrees and scale by the desired width
vec2 dir = vec2 (n.y, -n.x) * off;
float scale = estimateScale (current.xyz, sCurrent);
vec2 pos = sCurrent + dir * scale;
gl_Position = unproject (pos, dCurrent.z, dCurrent.w);
}
-- Fragment.particle.trail
uniform sampler2D smoke;
varying vec2 texcoord;
varying vec3 vBC;
#if 0
void
main (void)
{
gl_FragColor = texture2D (smoke, texcoord) * vec4 (1.0, 1.0, 1.0, 0.7);
}
#else
float
edgeFactor (void)
{
vec3 d = fwidth (vBC);
vec3 a3 = smoothstep (vec3 (0.0), d * 1.5, vBC);
return min (min (a3.x, a3.y), a3.z);
}
void
main (void)
{
gl_FragColor = vec4 (vec3 (edgeFactor ()), 0.5);
}
#endif

View file

@ -1,26 +0,0 @@
uniform sampler2D smoke;
varying vec2 texcoord;
varying vec3 vBC;
#if 0
void
main (void)
{
gl_FragColor = texture2D (smoke, texcoord) * vec4 (1.0, 1.0, 1.0, 0.7);
}
#else
float
edgeFactor (void)
{
vec3 d = fwidth (vBC);
vec3 a3 = smoothstep (vec3 (0.0), d * 1.5, vBC);
return min (min (a3.x, a3.y), a3.z);
}
void
main (void)
{
gl_FragColor = vec4 (vec3 (edgeFactor ()), 0.5);
}
#endif

View file

@ -1,79 +0,0 @@
attribute vec4 last, current, next;
attribute vec3 barycentric;
attribute float texoff;
uniform mat4 proj, view;
uniform vec2 viewport;
uniform float width;
varying vec2 texcoord;
varying vec3 vBC;
vec4
transform (vec3 coord)
{
return proj * view * vec4 (coord, 1.0);
}
vec2
project (vec4 coord)
{
vec3 device = coord.xyz / coord.w;
vec2 clip = (device * 0.5 + 0.5).xy;
return clip * viewport;
}
vec4
unproject (vec2 screen, float z, float w)
{
vec2 clip = screen / viewport;
vec2 device = clip * 2.0 - 1.0;
return vec4 (device * w, z, w);
}
float
estimateScale (vec3 position, vec2 sPosition)
{
vec4 view_pos = view * vec4 (position, 1.0);
vec4 scale_pos = view_pos - vec4 (normalize (view_pos.xy) * width,
0.0, 0.0);
vec2 screen_scale_pos = project (proj * scale_pos);
return distance (sPosition, screen_scale_pos);
}
void
main (void)
{
vec2 t, n1, n2, n;
vec2 sLast = project (transform (last.xyz));
vec2 sNext = project (transform (next.xyz));
vec4 dCurrent = transform (current.xyz);
vec2 sCurrent = project (dCurrent);
float off = current.w;
texcoord = vec2 (texoff * 0.7, off * 0.5 + 0.5);
vBC = barycentric;
t = sLast - sCurrent;
n1 = vec2 (0.0);
if (dot (t, t) > 0.001)
n1 = normalize (t);
t = sCurrent - sNext;
n2 = vec2 (0.0);
if (dot (t, t) > 0.001)
n2 = normalize (t);
n = vec2 (0.0);
if (n1 != -n2)
n = normalize (n1 + n2);
else if (dot (n1, n1) > 0.001)
n = n1;
else if (dot (n2, n2) > 0.001)
n = n2;
// rotate the normal by 90 degrees and scale by the desired width
vec2 dir = vec2 (n.y, -n.x) * off;
float scale = estimateScale (current.xyz, sCurrent);
vec2 pos = sCurrent + dir * scale;
gl_Position = unproject (pos, dCurrent.z, dCurrent.w);
}