actually render trails
authorhgn <hgodden00@gmail.com>
Sun, 4 Feb 2024 19:14:34 +0000 (19:14 +0000)
committerhgn <hgodden00@gmail.com>
Sun, 4 Feb 2024 19:14:34 +0000 (19:14 +0000)
build.c
particle.c
shaders/trail.fs [new file with mode: 0644]
shaders/trail.h [new file with mode: 0644]
shaders/trail.vs [new file with mode: 0644]
skaterift.c
trail.c

diff --git a/build.c b/build.c
index 5958fa3a9d5e94a1c0923d072b38f8e05a5afec7..cb7a71a26324e40ef1c48388ad34d5e5c71e79b7 100644 (file)
--- a/build.c
+++ b/build.c
@@ -267,9 +267,8 @@ void build_shaders(void){
    _S( "model_gate_unlinked",  "model.vs",         "model_gate_unlinked.fs" );
    _S( "model_font",           "model_font.vs",    "model_font.fs" );
 
-   /* Pointcloud */
-   //_S( "point_map", "cloud.vs", "cloud.fs" );
    _S( "particle", "particle.vs", "particle.fs" );
+   _S( "trail", "trail.vs", "trail.fs" );
 
    /* 2D */
    _S( "blit",      "blit.vs",      "blit.fs" );
index d12a87a024e3db67de24a1134810655e884775d2..e1f6ac85b0f31270b75c0fafb91160aa0c767233 100644 (file)
@@ -1,4 +1,5 @@
 #include "particle.h"
+#include "shaders/trail.h"
 
 static void particle_spawn( particle_system *sys, 
                             v3f co, v3f v, f32 lifetime, u32 colour ){
@@ -98,6 +99,7 @@ static void particle_alloc( particle_system *sys, u32 max ){
    static int reg = 1;
    if( reg ){
       shader_particle_register();
+      shader_trail_register();
       reg = 0;
    }
 
diff --git a/shaders/trail.fs b/shaders/trail.fs
new file mode 100644 (file)
index 0000000..e6ba5a8
--- /dev/null
@@ -0,0 +1,18 @@
+layout (location = 0) out vec4 oColour;
+in float aAlpha;
+uniform vec4 uColour;
+
+#include "motion_vectors_fs.glsl"
+
+void main(){
+   compute_motion_vectors();
+
+   vec2 ssuv = gl_FragCoord.xy;
+   vec3 vDither = vec3( dot( vec2( 171.0, 231.0 ), ssuv) );
+   float dither = fract( vDither.g / 71.0 ) - 0.5;
+
+   if( aAlpha+dither<0.5 )
+      discard;
+
+   oColour = vec4( uColour.rgb, uColour.a * aAlpha );
+}
diff --git a/shaders/trail.h b/shaders/trail.h
new file mode 100644 (file)
index 0000000..ee6090c
--- /dev/null
@@ -0,0 +1,113 @@
+#ifndef SHADER_trail_H
+#define SHADER_trail_H
+static void shader_trail_link(void);
+static void shader_trail_register(void);
+static struct vg_shader _shader_trail = {
+   .name = "trail",
+   .link = shader_trail_link,
+   .vs = 
+{
+.orig_file = "shaders/trail.vs",
+.static_src = 
+"layout (location=0) in vec4 a_co;\n"
+"\n"
+"#line       1        1 \n"
+"const float k_motion_lerp_amount = 0.01;\n"
+"\n"
+"#line      2        0 \n"
+"\n"
+"out vec3 aMotionVec0;\n"
+"out vec3 aMotionVec1;\n"
+"\n"
+"void vs_motion_out( vec4 vproj0, vec4 vproj1 )\n"
+"{\n"
+"   // This magically solves some artifacting errors!\n"
+"   //\n"
+"   vproj1 = vproj0*(1.0-k_motion_lerp_amount) + vproj1*k_motion_lerp_amount;\n"
+"\n"
+"   aMotionVec0 = vec3( vproj0.xy, vproj0.w );\n"
+"   aMotionVec1 = vec3( vproj1.xy, vproj1.w );\n"
+"}\n"
+"\n"
+"#line      4        0 \n"
+"\n"
+"uniform mat4 uPv;\n"
+"uniform mat4 uPvPrev;\n"
+"\n"
+"out float aAlpha;\n"
+"\n"
+"void main(){\n"
+"   vec4 vproj0     = uPv     * vec4( a_co.xyz, 1.0 );\n"
+"   vec4 vproj1     = uPvPrev * vec4( a_co.xyz, 1.0 );\n"
+"   vs_motion_out( vproj0, vproj1 );\n"
+"\n"
+"   gl_Position = vproj0;\n"
+"   aAlpha = a_co.w;\n"
+"}\n"
+""},
+   .fs = 
+{
+.orig_file = "shaders/trail.fs",
+.static_src = 
+"layout (location = 0) out vec4 oColour;\n"
+"in float aAlpha;\n"
+"uniform vec4 uColour;\n"
+"\n"
+"#line       1        1 \n"
+"const float k_motion_lerp_amount = 0.01;\n"
+"\n"
+"#line      2        0 \n"
+"\n"
+"layout (location = 1) out vec2 oMotionVec;\n"
+"\n"
+"in vec3 aMotionVec0;\n"
+"in vec3 aMotionVec1;\n"
+"\n"
+"void compute_motion_vectors()\n"
+"{\n"
+"   // Write motion vectors\n"
+"   vec2 vmotion0 = aMotionVec0.xy / aMotionVec0.z;\n"
+"   vec2 vmotion1 = aMotionVec1.xy / aMotionVec1.z;\n"
+"\n"
+"   oMotionVec = (vmotion1-vmotion0) * (1.0/k_motion_lerp_amount);\n"
+"}\n"
+"\n"
+"#line      6        0 \n"
+"\n"
+"void main(){\n"
+"   compute_motion_vectors();\n"
+"\n"
+"   vec2 ssuv = gl_FragCoord.xy;\n"
+"   vec3 vDither = vec3( dot( vec2( 171.0, 231.0 ), ssuv) );\n"
+"   float dither = fract( vDither.g / 71.0 ) - 0.5;\n"
+"\n"
+"   if( aAlpha+dither<0.5 )\n"
+"      discard;\n"
+"\n"
+"   oColour = vec4( uColour.rgb, uColour.a * aAlpha );\n"
+"}\n"
+""},
+};
+
+static GLuint _uniform_trail_uPv;
+static GLuint _uniform_trail_uPvPrev;
+static GLuint _uniform_trail_uColour;
+static void shader_trail_uPv(m4x4f m){
+   glUniformMatrix4fv(_uniform_trail_uPv,1,GL_FALSE,(float*)m);
+}
+static void shader_trail_uPvPrev(m4x4f m){
+   glUniformMatrix4fv(_uniform_trail_uPvPrev,1,GL_FALSE,(float*)m);
+}
+static void shader_trail_uColour(v4f v){
+   glUniform4fv(_uniform_trail_uColour,1,v);
+}
+static void shader_trail_register(void){
+   vg_shader_register( &_shader_trail );
+}
+static void shader_trail_use(void){ glUseProgram(_shader_trail.id); }
+static void shader_trail_link(void){
+   _uniform_trail_uPv = glGetUniformLocation( _shader_trail.id, "uPv" );
+   _uniform_trail_uPvPrev = glGetUniformLocation( _shader_trail.id, "uPvPrev" );
+   _uniform_trail_uColour = glGetUniformLocation( _shader_trail.id, "uColour" );
+}
+#endif /* SHADER_trail_H */
diff --git a/shaders/trail.vs b/shaders/trail.vs
new file mode 100644 (file)
index 0000000..827d160
--- /dev/null
@@ -0,0 +1,17 @@
+layout (location=0) in vec4 a_co;
+
+#include "motion_vectors_vs.glsl"
+
+uniform mat4 uPv;
+uniform mat4 uPvPrev;
+
+out float aAlpha;
+
+void main(){
+   vec4 vproj0     = uPv     * vec4( a_co.xyz, 1.0 );
+   vec4 vproj1     = uPvPrev * vec4( a_co.xyz, 1.0 );
+   vs_motion_out( vproj0, vproj1 );
+
+   gl_Position = vproj0;
+   aAlpha = a_co.w;
+}
index 82aa54cd4e9f6d31c64be86ee88265be5c49edee..ecdad8e54b19cd6aafe69f3184621cfe29dfac0f 100644 (file)
@@ -516,9 +516,16 @@ static void render_scene(void){
    particle_system_prerender( &particles_env );
    particle_system_render( &particles_env, &skaterift.cam );
 
+   v3f co;
+   v4f q;
+   rb_extrapolate( &localplayer.rb, co, q );
+
    trail_system_update( &trails_test, vg.time_delta, 
-                        localplayer.rb.co, localplayer.rb.to_world[1], 1.0f );
+                        co,
+                        localplayer.rb.to_world[1], 1.0f );
    trail_system_debug( &trails_test );
+   trail_system_prerender( &trails_test );
+   trail_system_render( &trails_test, &skaterift.cam );
 
    /* 
     * render transition 
diff --git a/trail.c b/trail.c
index bf23b1c56c5427a6ea371e19328b33707647c4db..b492cabc36b7d0580fcc029786b4ead5eb0e804a 100644 (file)
--- a/trail.c
+++ b/trail.c
@@ -1,5 +1,18 @@
 #pragma once
 #include "trail.h"
+#include "shaders/particle.h"
+#include "shaders/trail.h"
+
+static void trail_increment( trail_system *sys ){
+   sys->head ++;
+
+   if( sys->head == sys->max )
+      sys->head = 0;
+
+   /* undesirable effect: will remove active points if out of space! */
+   if( sys->count < sys->max )
+      sys->count ++;
+}
 
 static void trail_system_update( trail_system *sys, f32 dt,
                                  v3f co, v3f normal, f32 alpha ){
@@ -20,62 +33,53 @@ static void trail_system_update( trail_system *sys, f32 dt,
       }
    }
 
-   bool add_point = 1;
-   i32 index_current = sys->head;
-   if( sys->count >= 2 ) index_current = sys->head -1;
+   i32 icur  = sys->head -1,
+       iprev = sys->head -2,
+       ihead = sys->head;
 
-   i32 index_prev = index_current -1;
+   if( icur  < 0 ) icur += sys->max;
+   if( iprev < 0 ) iprev += sys->max;
 
-   if( index_current < 0 ) index_current += sys->max;
-   if( index_prev    < 0 ) index_prev    += sys->max;
+   trail_point *pcur  = &sys->array[ icur ],
+               *pprev = &sys->array[ iprev ],
+               *phead = &sys->array[ ihead ],
+               *pdest = NULL;
+   v3f dir;
 
-   /* always enforced non-zero distance */
-   if( sys->count >= 1 ){
-      if( v3_dist2( sys->array[index_prev].co, co ) < 0.001f*0.001f )
-         return;
-   }
+   f32 k_min = 0.001f;
 
-   /* copy new info in */
-   trail_point *p_current = &sys->array[index_current];
-   v3_copy( co, p_current->co );
-   v3_copy( normal, p_current->normal );
-   p_current->alpha = alpha;
-
-   /* update direction */
-   if( sys->count >= 2 ){
-      trail_point *p_prev = &sys->array[index_prev];
-
-      v3f dir;
-      v3_sub( co, p_prev->co, dir );
-      v3_normalize( dir );
-      v3_cross( dir, normal, p_current->right );
-      v3_copy( p_current->right, p_prev->right );
-
-      /* decide if to prevent split based on user min-distance */
-      if( v3_dist2( p_prev->co, co ) < sys->min_dist*sys->min_dist )
-         add_point = 0;
+   if( sys->count == 0 ){
+      trail_increment( sys );
+      v3_copy( (v3f){0,0,-1}, dir );
+      pdest = phead;
    }
-   else 
-      v3_zero( p_current->right );
-
-   if( add_point ){
-      sys->head ++;
+   else if( sys->count == 1 ){
+      if( v3_dist2( pcur->co, co ) < k_min*k_min )
+         return;
 
-      if( sys->head == sys->max )
-         sys->head = 0;
+      trail_increment( sys );
+      pdest = phead;
+      v3_sub( co, pcur->co, dir );
+   }
+   else {
+      if( v3_dist2( pprev->co, co ) < k_min*k_min )
+         return;
 
-      /* undesirable effect: will remove active points if out of space! */
-      if( sys->count < sys->max )
-         sys->count ++;
+      if( v3_dist2( pprev->co, co ) > sys->min_dist*sys->min_dist ){
+         trail_increment( sys );
+         pdest = phead;
+      }
+      else
+         pdest = pcur;
 
-      index_current = sys->head;
+      v3_sub( co, pprev->co, dir );
    }
 
-   p_current = &sys->array[index_current];
-   v3_copy( co, p_current->co );
-   v3_copy( normal, p_current->normal );
-   p_current->alpha = alpha;
-   v3_zero( p_current->right );
+   v3_cross( dir, normal, pdest->right );
+   v3_normalize( pdest->right );
+   v3_copy( co, pdest->co );
+   v3_copy( normal, pdest->normal );
+   pdest->alpha = alpha;
 }
 
 static void trail_system_debug( trail_system *sys ){
@@ -135,17 +139,31 @@ static void trail_alloc( trail_system *sys, u32 max ){
 }
 
 static void trail_system_prerender( trail_system *sys ){
-#if 0
+   if( sys->count < 2 ) return;
+
+   for( i32 i=0; i<sys->count; i ++ ){
+      i32 i0 = sys->head - sys->count + i;
+      if( i0 < 0 ) i0 += sys->max;
+
+      trail_point *p0 = &sys->array[i0];
+      trail_vert *v0 = &sys->vertices[i*2+0],
+                 *v1 = &sys->vertices[i*2+1];
+
+      v3_muladds( p0->co, p0->right, -sys->width, v0->co );
+      v3_muladds( p0->co, p0->right,  sys->width, v1->co );
+      v0->co[3] = p0->alpha;
+      v1->co[3] = p0->alpha;
+   }
+
    glBindVertexArray( sys->vao );
 
    size_t stride = sizeof(trail_vert);
    glBindBuffer( GL_ARRAY_BUFFER, sys->vbo );
-   glBufferSubData( GL_ARRAY_BUFFER, 0, sys->alive*stride*4, sys->vertices );
-#endif
+   glBufferSubData( GL_ARRAY_BUFFER, 0, sys->count*stride*2, sys->vertices );
 }
 
 static void trail_system_render( trail_system *sys, camera *cam ){
-#if 0
+   if( sys->count < 2 ) return;
    glDisable( GL_CULL_FACE );
    glEnable( GL_DEPTH_TEST );
 
@@ -154,6 +172,5 @@ static void trail_system_render( trail_system *sys, camera *cam ){
    shader_trail_uPvPrev( cam->mtx_prev.pv );
 
        glBindVertexArray( sys->vao );
-       glDrawElements( GL_TRIANGLES, sys->alive*6, GL_UNSIGNED_SHORT, NULL );
-#endif
+   glDrawArrays( GL_TRIANGLE_STRIP, 0, sys->count*2 );
 }