_S( "model_font", "model_font.vs", "model_font.fs" );
/* Pointcloud */
- _S( "point_map", "cloud.vs", "cloud.fs" );
+ //_S( "point_map", "cloud.vs", "cloud.fs" );
+ _S( "particle", "particle.vs", "particle.fs" );
/* 2D */
_S( "blit", "blit.vs", "blit.fs" );
--- /dev/null
+#include "particle.h"
+
+static void particle_spawn( particle_system *sys,
+ v3f co, v3f v, f32 lifetime, u32 colour ){
+ if( sys->alive == sys->max ) return;
+
+ particle *p = &sys->array[ sys->alive ++ ];
+ v3_copy( co, p->co );
+ v3_copy( v, p->v );
+ p->life = lifetime;
+ p->colour = colour;
+}
+
+static void particle_system_update( particle_system *sys, f32 dt ){
+ u32 i = 0;
+iter: if( i == sys->alive ) return;
+
+ particle *p = &sys->array[i];
+ p->life -= dt;
+
+ if( p->life < 0.0f ){
+ *p = sys->array[ -- sys->alive ];
+ goto iter;
+ }
+
+ v3_muladds( p->co, p->v, dt, p->co );
+ p->v[1] += -9.8f * dt;
+
+ i ++;
+ goto iter;
+}
+
+static void particle_system_debug( particle_system *sys ){
+ for( u32 i=0; i<sys->alive; i ++ ){
+ particle *p = &sys->array[i];
+ v3f p1;
+ v3_muladds( p->co, p->v, 0.2f, p1 );
+ vg_line( p->co, p1, p->colour );
+ }
+}
+
+struct particle_init_args {
+ particle_system *sys;
+ u16 indices[];
+};
+
+static void async_particle_init( void *payload, u32 size ){
+ struct particle_init_args *args = payload;
+ particle_system *sys = args->sys;
+
+ glGenVertexArrays( 1, &sys->vao );
+ glGenBuffers( 1, &sys->vbo );
+ glGenBuffers( 1, &sys->ebo );
+ glBindVertexArray( sys->vao );
+
+ size_t stride = sizeof(particle_vert);
+
+ glBindBuffer( GL_ARRAY_BUFFER, sys->vbo );
+ glBufferData( GL_ARRAY_BUFFER, sys->max*stride*4, NULL, GL_DYNAMIC_DRAW );
+ glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, sys->ebo );
+ glBufferData( GL_ELEMENT_ARRAY_BUFFER,
+ sys->max*sizeof(u16)*6, args->indices, GL_STATIC_DRAW );
+
+ /* 0: coordinates */
+ glVertexAttribPointer( 0, 3, GL_FLOAT, GL_FALSE, stride, (void*)0 );
+ glEnableVertexAttribArray( 0 );
+
+ /* 3: colour */
+ glVertexAttribPointer( 1, 4, GL_UNSIGNED_BYTE, GL_TRUE,
+ stride, (void *)offsetof(particle_vert, colour) );
+ glEnableVertexAttribArray( 1 );
+
+ VG_CHECK_GL_ERR();
+}
+
+static void particle_init( particle_system *sys, u32 max ){
+ static int reg = 1;
+ if( reg ){
+ shader_particle_register();
+ reg = 0;
+ }
+
+ size_t stride = sizeof(particle_vert);
+
+ particles_grind.max = max;
+ particles_grind.array =
+ vg_linear_alloc( vg_mem.rtmemory, max*sizeof(particle) );
+ particles_grind.vertices =
+ vg_linear_alloc( vg_mem.rtmemory, max*stride*4 );
+
+ vg_async_item *call =
+ vg_async_alloc( sizeof(particle_system *) + max*sizeof(u16)*6 );
+ struct particle_init_args *init = call->payload;
+ init->sys = sys;
+
+ for( u32 i=0; i<max; i ++ ){
+ init->indices[i*6+0] = i*4;
+ init->indices[i*6+1] = i*4+1;
+ init->indices[i*6+2] = i*4+2;
+ init->indices[i*6+3] = i*4;
+ init->indices[i*6+4] = i*4+2;
+ init->indices[i*6+5] = i*4+3;
+ }
+
+ vg_async_dispatch( call, async_particle_init );
+}
+
+static void particle_system_prerender( particle_system *sys ){
+ for( u32 i=0; i<sys->alive; i ++ ){
+ particle *p = &sys->array[i];
+ particle_vert *vs = &sys->vertices[i*4];
+
+ v3f v, right;
+ v3_copy( p->v, v );
+ v3_normalize( v );
+ v3_cross( v, (v3f){0,1,0}, right );
+
+ f32 l = 0.3f, w = 0.025f;
+
+ v3f p0, p1;
+ v3_muladds( p->co, p->v, l, p0 );
+ v3_muladds( p->co, p->v, -l, p1 );
+
+ v3_muladds( p0, right, w, vs[0].co );
+ v3_muladds( p1, right, w, vs[1].co );
+ v3_muladds( p1, right, -w, vs[2].co );
+ v3_muladds( p0, right, -w, vs[3].co );
+
+ vs[0].colour = p->colour;
+ vs[1].colour = p->colour;
+ vs[2].colour = p->colour;
+ vs[3].colour = p->colour;
+ }
+
+ glBindVertexArray( sys->vao );
+
+ size_t stride = sizeof(particle_vert);
+ glBindBuffer( GL_ARRAY_BUFFER, sys->vbo );
+ glBufferSubData( GL_ARRAY_BUFFER, 0, sys->alive*stride*4, sys->vertices );
+}
+
+static void particle_system_render( particle_system *sys, camera *cam ){
+ glDisable( GL_CULL_FACE );
+ glDisable( GL_DEPTH_TEST );
+
+ shader_particle_use();
+ shader_particle_uPv( cam->mtx.pv );
+ shader_particle_uPvPrev( cam->mtx_prev.pv );
+
+ glBindVertexArray( sys->vao );
+ glDrawElements( GL_TRIANGLES, sys->alive*6, GL_UNSIGNED_SHORT, NULL );
+}
--- /dev/null
+#ifndef PARTICLE_H
+#define PARTICLE_H
+
+typedef struct particle_system particle_system;
+typedef struct particle particle;
+typedef struct particle_vert particle_vert;
+
+struct particle_system {
+ struct particle {
+ v3f co, v;
+ f32 life;
+ u32 colour;
+ }
+ *array;
+
+#pragma pack(push,1)
+ struct particle_vert {
+ v3f co;
+ u32 colour;
+ }
+ *vertices;
+#pragma pack(pop)
+
+ u32 alive, max;
+ GLuint vao, vbo, ebo;
+}
+static particles_grind;
+
+static void particle_spawn( particle_system *sys,
+ v3f co, v3f v, f32 lifetime, u32 colour );
+static void particle_init( particle_system *sys, u32 max );
+
+#include "shaders/particle.h"
+
+#endif /* PARTICLE_H */
--- /dev/null
+layout (location = 0) out vec4 oColour;
+in vec4 aColour;
+
+#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( vsamplemain.a+dither<0.5 )
+ // discard;
+
+ oColour = aColour;
+}
--- /dev/null
+#ifndef SHADER_particle_H
+#define SHADER_particle_H
+static void shader_particle_link(void);
+static void shader_particle_register(void);
+static struct vg_shader _shader_particle = {
+ .name = "particle",
+ .link = shader_particle_link,
+ .vs =
+{
+.orig_file = "shaders/particle.vs",
+.static_src =
+"layout (location=0) in vec3 a_co;\n"
+"layout (location=1) in vec4 a_colour;\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 5 0 \n"
+"\n"
+"uniform mat4 uPv;\n"
+"uniform mat4 uPvPrev;\n"
+"\n"
+"out vec4 aColour;\n"
+"\n"
+"void main(){\n"
+" vec4 vproj0 = uPv * vec4( a_co, 1.0 );\n"
+" vec4 vproj1 = uPvPrev * vec4( a_co, 1.0 );\n"
+" vs_motion_out( vproj0, vproj1 );\n"
+"\n"
+" gl_Position = vproj0;\n"
+" aColour = a_colour;\n"
+"}\n"
+""},
+ .fs =
+{
+.orig_file = "shaders/particle.fs",
+.static_src =
+"layout (location = 0) out vec4 oColour;\n"
+"in vec4 aColour;\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 5 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( vsamplemain.a+dither<0.5 )\n"
+" // discard;\n"
+"\n"
+" oColour = aColour;\n"
+"}\n"
+""},
+};
+
+static GLuint _uniform_particle_uPv;
+static GLuint _uniform_particle_uPvPrev;
+static void shader_particle_uPv(m4x4f m){
+ glUniformMatrix4fv(_uniform_particle_uPv,1,GL_FALSE,(float*)m);
+}
+static void shader_particle_uPvPrev(m4x4f m){
+ glUniformMatrix4fv(_uniform_particle_uPvPrev,1,GL_FALSE,(float*)m);
+}
+static void shader_particle_register(void){
+ vg_shader_register( &_shader_particle );
+}
+static void shader_particle_use(void){ glUseProgram(_shader_particle.id); }
+static void shader_particle_link(void){
+ _uniform_particle_uPv = glGetUniformLocation( _shader_particle.id, "uPv" );
+ _uniform_particle_uPvPrev = glGetUniformLocation( _shader_particle.id, "uPvPrev" );
+}
+#endif /* SHADER_particle_H */
--- /dev/null
+layout (location=0) in vec3 a_co;
+layout (location=1) in vec4 a_colour;
+
+#include "motion_vectors_vs.glsl"
+
+uniform mat4 uPv;
+uniform mat4 uPvPrev;
+
+out vec4 aColour;
+
+void main(){
+ vec4 vproj0 = uPv * vec4( a_co, 1.0 );
+ vec4 vproj1 = uPvPrev * vec4( a_co, 1.0 );
+ vs_motion_out( vproj0, vproj1 );
+
+ gl_Position = vproj0;
+ aColour = a_colour;
+}
#include "player_remote.c"
#include "vg/vg_audio_dsp.h"
#include "world_routes_ui.c"
+#include "particle.c"
static int k_tools_mode = 0;
skaterift.replay.size = bytes;
replay_clear( &skaterift.replay );
+ particle_init( &particles_grind, 300 );
+
player_load_animation_reference( "models/ch_none.mdl" );
player_model_load( &localplayer.fallback_model, "models/ch_none.mdl" );
player__bind();
world_instance *view_world = get_view_world();
render_world( view_world, &skaterift.cam, 0, 0, 1, 1 );
+ particle_spawn( &particles_grind, localplayer.rb.co,
+ (v3f){vg_randf64()*2.0f,vg_randf64()*3.0f,vg_randf64()*2.0f},
+ vg_randf64(), 0xff0000ff );
+ particle_system_update( &particles_grind, vg.time_delta );
+ //particle_system_debug( &particles_grind );
+ particle_system_prerender( &particles_grind );
+ particle_system_render( &particles_grind, &skaterift.cam );
+
+
/*
* render transition
*/