From: hgn Date: Sun, 4 Feb 2024 19:14:34 +0000 (+0000) Subject: actually render trails X-Git-Url: https://harrygodden.com/git/?p=carveJwlIkooP6JGAAIwe30JlM.git;a=commitdiff_plain;h=b6c1b99a420927d4f4b7a52865e908712ae55484 actually render trails --- diff --git a/build.c b/build.c index 5958fa3..cb7a71a 100644 --- 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" ); diff --git a/particle.c b/particle.c index d12a87a..e1f6ac8 100644 --- a/particle.c +++ b/particle.c @@ -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 index 0000000..e6ba5a8 --- /dev/null +++ b/shaders/trail.fs @@ -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 index 0000000..ee6090c --- /dev/null +++ b/shaders/trail.h @@ -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 index 0000000..827d160 --- /dev/null +++ b/shaders/trail.vs @@ -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; +} diff --git a/skaterift.c b/skaterift.c index 82aa54c..ecdad8e 100644 --- a/skaterift.c +++ b/skaterift.c @@ -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 bf23b1c..b492cab 100644 --- 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; icount; 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 ); }