mirror of
https://git.code.sf.net/p/quake/quakeforge
synced 2025-02-25 13:11:00 +00:00
Rework the trails vertex shader to be reusable.
This commit is contained in:
parent
6b2e45cae6
commit
11c2d8f422
2 changed files with 101 additions and 66 deletions
|
@ -109,6 +109,9 @@ static const char *particle_textured_frag_effects[] =
|
||||||
|
|
||||||
static const char *particle_trail_vert_effects[] =
|
static const char *particle_trail_vert_effects[] =
|
||||||
{
|
{
|
||||||
|
"QuakeForge.Screen.viewport",
|
||||||
|
"QuakeForge.Vertex.transform.view_projection",
|
||||||
|
"QuakeForge.Vertex.ScreenSpace.curve.width",
|
||||||
"QuakeForge.Vertex.particle.trail",
|
"QuakeForge.Vertex.particle.trail",
|
||||||
0
|
0
|
||||||
};
|
};
|
||||||
|
@ -171,8 +174,8 @@ static struct {
|
||||||
shaderparam_t colorb;
|
shaderparam_t colorb;
|
||||||
} trail = {
|
} trail = {
|
||||||
0,
|
0,
|
||||||
{"proj", 1},
|
{"projection_mat", 1},
|
||||||
{"view", 1},
|
{"view_mat", 1},
|
||||||
{"viewport", 1},
|
{"viewport", 1},
|
||||||
{"width", 1},
|
{"width", 1},
|
||||||
{"last", 0},
|
{"last", 0},
|
||||||
|
|
|
@ -50,6 +50,100 @@ dqtrans (vec4 q0, vec4 qe)
|
||||||
return 2.0 * (Ts * qv + qs * Tv + cross (Tv, qv));
|
return 2.0 * (Ts * qv + qs * Tv + cross (Tv, qv));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
-- Vertex.transform.mvp
|
||||||
|
uniform mat4 mvp_mat;
|
||||||
|
|
||||||
|
-- Vertex.transform.view_projection
|
||||||
|
uniform mat4 projection_mat, view_mat;
|
||||||
|
|
||||||
|
-- Screen.viewport
|
||||||
|
uniform vec2 viewport;
|
||||||
|
|
||||||
|
-- Vertex.ScreenSpace.curve.width
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
vec2
|
||||||
|
direction (vec2 from, vec2 to)
|
||||||
|
{
|
||||||
|
vec2 t = to - from;
|
||||||
|
vec2 d = vec2 (0.0, 0.0);
|
||||||
|
|
||||||
|
if (dot (t, t) > 0.001) {
|
||||||
|
d = normalize (t);
|
||||||
|
}
|
||||||
|
return d;
|
||||||
|
}
|
||||||
|
|
||||||
|
vec2
|
||||||
|
shared_direction (vec2 a, vec2 b)
|
||||||
|
{
|
||||||
|
vec2 d = a + b;
|
||||||
|
|
||||||
|
if (dot (d, d) > 0.001) {
|
||||||
|
d = normalize (d);
|
||||||
|
} else if (dot (a, a) > 0.001) {
|
||||||
|
d = normalize (a);
|
||||||
|
} else if (dot (b, b) > 0.001) {
|
||||||
|
d = normalize (b);
|
||||||
|
} else {
|
||||||
|
d = vec2 (0.0);
|
||||||
|
}
|
||||||
|
return d;
|
||||||
|
}
|
||||||
|
|
||||||
|
float
|
||||||
|
estimateScale (vec3 position, vec2 sPosition, float width)
|
||||||
|
{
|
||||||
|
vec4 view_pos = view_mat * vec4 (position, 1.0);
|
||||||
|
vec4 scale_pos = view_pos - vec4 (normalize (view_pos.xy) * width,
|
||||||
|
0.0, 0.0);
|
||||||
|
vec2 screen_scale_pos = project (projection_mat * scale_pos);
|
||||||
|
return distance (sPosition, screen_scale_pos);
|
||||||
|
}
|
||||||
|
|
||||||
|
vec4
|
||||||
|
transform (vec4 coord)
|
||||||
|
{
|
||||||
|
return projection_mat * view_mat * vec4 (coord.xyz, 1.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
vec4
|
||||||
|
curve_offset_vertex (vec4 last, vec4 current, vec4 next, float width)
|
||||||
|
{
|
||||||
|
float offset = current.w;
|
||||||
|
|
||||||
|
vec2 sLast = project (transform (last));
|
||||||
|
vec2 sNext = project (transform (next));
|
||||||
|
vec4 dCurrent = transform (current);
|
||||||
|
vec2 sCurrent = project (dCurrent);
|
||||||
|
|
||||||
|
vec2 n1 = direction (sCurrent, sLast);
|
||||||
|
vec2 n2 = direction (sNext, sCurrent);
|
||||||
|
vec2 n = shared_direction (n1, n2);
|
||||||
|
|
||||||
|
// rotate the normal by 90 degrees and scale by the desired offset
|
||||||
|
vec2 dir = vec2(n.y, -n.x) * offset;
|
||||||
|
float scale = estimateScale (vec3(current), sCurrent, width);
|
||||||
|
vec2 pos = sCurrent + dir * scale;
|
||||||
|
|
||||||
|
return unproject (pos, dCurrent.z, dCurrent.w);
|
||||||
|
}
|
||||||
|
|
||||||
-- Fragment.fog
|
-- Fragment.fog
|
||||||
|
|
||||||
uniform vec4 fog;
|
uniform vec4 fog;
|
||||||
|
@ -587,8 +681,6 @@ attribute float texoff;
|
||||||
attribute vec4 vcolora;
|
attribute vec4 vcolora;
|
||||||
attribute vec4 vcolorb;
|
attribute vec4 vcolorb;
|
||||||
|
|
||||||
uniform mat4 proj, view;
|
|
||||||
uniform vec2 viewport;
|
|
||||||
uniform float width;
|
uniform float width;
|
||||||
|
|
||||||
varying vec2 texcoord;
|
varying vec2 texcoord;
|
||||||
|
@ -596,75 +688,15 @@ varying vec3 vbarycentric;
|
||||||
varying vec4 colora;
|
varying vec4 colora;
|
||||||
varying vec4 colorb;
|
varying vec4 colorb;
|
||||||
|
|
||||||
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
|
void
|
||||||
main (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;
|
|
||||||
|
|
||||||
colora = vcolora;
|
colora = vcolora;
|
||||||
colorb = vcolorb;
|
colorb = vcolorb;
|
||||||
texcoord = vec2 (texoff * 0.7, off);// * 0.5 + 0.5);
|
texcoord = vec2 (texoff * 0.7, current.w);// * 0.5 + 0.5);
|
||||||
vbarycentric = barycentric;
|
vbarycentric = barycentric;
|
||||||
|
|
||||||
t = sLast - sCurrent;
|
gl_Position = curve_offset_vertex (last, current, next, width);
|
||||||
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
|
-- Fragment.particle.trail
|
||||||
|
|
Loading…
Reference in a new issue