Start working on solid trails for smoke etc.

The implementation is based on
http://codeflow.org/entries/2012/aug/05/webgl-rendering-of-solid-trails/

The shaders have been written and compile and link. The next step is to
generate some data for them.
This commit is contained in:
Bill Currie 2013-02-21 11:40:11 +09:00
parent 946561ba44
commit ddd8885cd6
4 changed files with 128 additions and 2 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 shader_src= quakeforge.glsl trail.frag trail.vert
shader_gen= quakeforge.slc shader_gen= quakeforge.slc trail.fc trail.vc
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

@ -106,6 +106,14 @@ static const char *particle_textured_frag_effects[] =
0 0
}; };
static const char trail_vert[] =
#include "trail.vc"
;
static const char trail_frag[] =
#include "trail.fc"
;
static struct { static struct {
int program; int program;
shaderparam_t mvp_matrix; shaderparam_t mvp_matrix;
@ -140,6 +148,32 @@ static struct {
{"fog", 1}, {"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 smoke;
} trail = {
0,
{"proj", 1},
{"view", 1},
{"viewport", 1},
{"width", 1},
{"last", 0},
{"current", 0},
{"next", 0},
{"barycentric", 0},
{"texoff", 0},
{"smoke", 1},
};
inline static void inline static void
particle_new (ptype_t type, int texnum, const vec3_t org, float scale, particle_new (ptype_t type, int texnum, const vec3_t org, float scale,
const vec3_t vel, float die, int color, float alpha, float ramp) const vec3_t vel, float die, int color, float alpha, float ramp)
@ -267,6 +301,20 @@ 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);
frag = GLSL_CompileShader ("trail.frag", trail_frag, 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.smoke);
memset (data, 0, sizeof (data)); memset (data, 0, sizeof (data));
qfeglGenTextures (1, &part_tex); qfeglGenTextures (1, &part_tex);
qfeglBindTexture (GL_TEXTURE_2D, part_tex); qfeglBindTexture (GL_TEXTURE_2D, part_tex);

View file

@ -0,0 +1,10 @@
uniform sampler2D smoke;
varying vec2 texcoord;
varying vec3 vBC;
void
main (void)
{
gl_FragColor = texture2D (smoke, texcoord) * vec4 (1.0, 1.0, 1.0, 0.7);
}

View file

@ -0,0 +1,68 @@
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 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;
// FIXME either n1 or n2 could be zero
vec2 n1 = normalize (sLast - sCurrent);
vec2 n2 = normalize (sCurrent - sNext);
// FIXME if n1 == -n2, the vector will be zero
vec2 n = normalize (n1 + 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);
}