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_CPPFLAGS= -I$(top_srcdir)/include $(GLX_CFLAGS)
shader_src= quakeforge.glsl trail.frag trail.vert
shader_gen= quakeforge.slc trail.fc trail.vc
shader_src= quakeforge.glsl
shader_gen= quakeforge.slc
glsl_src = \
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
};
static const char trail_vert[] =
#include "trail.vc"
;
static const char *particle_trail_vert_effects[] =
{
"QuakeForge.Vertex.particle.trail",
0
};
static const char trail_frag[] =
#include "trail.fc"
;
static const char *particle_trail_frag_effects[] =
{
"QuakeForge.Fragment.particle.trail",
0
};
static struct {
int program;
@ -190,9 +194,9 @@ typedef struct trailvtx_s {
float texoff;
} trailvtx_t;
static trail_t *free_trails;
static trail_t *active_trails;
static particle_t *free_points;
static trail_t *trails_freelist;
static trail_t *trails_active;
static particle_t *points_freelist;
static trail_t *
new_trail (void)
@ -350,8 +354,10 @@ glsl_R_InitParticles (void)
GLSL_FreeShader (vert_shader);
GLSL_FreeShader (frag_shader);
vert = GLSL_CompileShader ("trail.vert", trail_vert, GL_VERTEX_SHADER);
frag = GLSL_CompileShader ("trail.frag", trail_frag, GL_FRAGMENT_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);
@ -363,6 +369,8 @@ glsl_R_InitParticles (void)
GLSL_ResolveShaderParam (trail.program, &trail.barycentric);
GLSL_ResolveShaderParam (trail.program, &trail.texoff);
GLSL_ResolveShaderParam (trail.program, &trail.smoke);
GLSL_FreeShader (vert_shader);
GLSL_FreeShader (frag_shader);
memset (data, 0, sizeof (data));
qfeglGenTextures (1, &part_tex);
@ -730,12 +738,12 @@ R_RocketTrail_trail (entity_t *ent)
if (!ent->trail) {
ent->trail = new_trail ();
ent->trail->next = active_trails;
ent->trail->prev = &active_trails;
ent->trail->next = trails_active;
ent->trail->prev = &trails_active;
ent->trail->owner = &ent->trail;
if (active_trails)
active_trails->prev = &ent->trail->next;
active_trails = ent->trail;
if (trails_active)
trails_active->prev = &ent->trail->next;
trails_active = ent->trail;
}
VectorCopy (ent->old_origin, old_origin);
@ -1723,7 +1731,7 @@ count_points (int *num_verts, int *num_elements)
*num_verts = 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)
continue;
// +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};
int bind = 0;
for (trail = active_trails; trail; trail = trail->next) {
for (trail = trails_active; trail; trail = trail->next) {
if (trail->num_points < 2)
continue;
point = trail->points;
@ -1768,7 +1776,7 @@ expire_trails (void)
{
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;
while (trail->points && trail->points->die <= vr_data.realtime) {
particle_t *point = trail->points;
@ -1827,7 +1835,7 @@ draw_trails (void)
qfeglVertexAttribPointer (trail.texoff.location, 1, GL_FLOAT,
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;
if (trl->num_points < 2)
continue;

View file

@ -551,3 +551,114 @@ main (void)
col = texture2D (texture, st) * color * vec4 (l, 1.0);
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);
}