k_srbind_mback,
k_srbind_maccept,
k_srbind_mopen,
+ k_srbind_replay_play,
+ k_srbind_replay_freecam,
+ k_srbind_replay_resume,
k_srbind_max,
};
k_sraxis_grab = 0,
k_sraxis_mbrowse_h,
k_sraxis_mbrowse_v,
+ k_sraxis_replay_h,
+
k_sraxis_max
};
[ SDL_CONTROLLER_BUTTON_GUIDE ] = { "\x91", "\x91" },
};
-static const char *controller_glyph( u32 sdl_index )
-{
+static const char *controller_glyph( u32 sdl_index ){
if( vg_input.display_input_type == SDL_CONTROLLER_TYPE_PS3 ||
vg_input.display_input_type == SDL_CONTROLLER_TYPE_PS4 ||
vg_input.display_input_type == SDL_CONTROLLER_TYPE_PS5 )
[k_srbind_mdown] = controller_glyph( SDL_CONTROLLER_BUTTON_DPAD_DOWN ),
[k_srbind_mback] = controller_glyph( SDL_CONTROLLER_BUTTON_B ),
[k_srbind_maccept]= controller_glyph( SDL_CONTROLLER_BUTTON_A ),
- [k_srbind_mopen] = controller_glyph( SDL_CONTROLLER_BUTTON_GUIDE )
+ [k_srbind_mopen] = controller_glyph( SDL_CONTROLLER_BUTTON_GUIDE ),
+[k_srbind_replay_play]= controller_glyph( SDL_CONTROLLER_BUTTON_A ),
+[k_srbind_replay_freecam]=controller_glyph(SDL_CONTROLLER_BUTTON_Y ),
+[k_srbind_replay_resume]=controller_glyph( SDL_CONTROLLER_BUTTON_LEFTSHOULDER )
};
const char *keyboard_table[ k_srbind_max ] = {
[k_srbind_mback] = "\xa3",
[k_srbind_maccept]= "\xa2",
[k_srbind_mopen] = "\xa3" ,
+[k_srbind_replay_play]= "\xa1",
+[k_srbind_replay_freecam] = KEYBOARD_GLYPH( "F" ),
+[k_srbind_replay_resume]=KEYBOARD_GLYPH( "R" )
};
if( vg_input.display_input_method == k_input_method_controller )
const char *controller_table[ k_sraxis_max ] = {
[k_sraxis_grab] = "\x90",
[k_sraxis_mbrowse_h] = "\x88",
- [k_sraxis_mbrowse_v] = "\x89"
+ [k_sraxis_mbrowse_v] = "\x89",
+ [k_sraxis_replay_h] = "\x88"
};
const char *keyboard_table[ k_sraxis_max ] = {
[k_sraxis_grab] = "\x9e",
[k_sraxis_mbrowse_h] = KEYBOARD_GLYPH("\x93")KEYBOARD_GLYPH("\x95"),
- [k_sraxis_mbrowse_v] = KEYBOARD_GLYPH("\x96")KEYBOARD_GLYPH("\x94")
+ [k_sraxis_mbrowse_v] = KEYBOARD_GLYPH("\x96")KEYBOARD_GLYPH("\x94"),
+ [k_sraxis_replay_h] = KEYBOARD_GLYPH("\x93")KEYBOARD_GLYPH("\x95"),
};
if( vg_input.display_input_method == k_input_method_controller )
v2_copy( srinput.joystick_states[ joystick ][0], state );
}
-static float axis_state( enum sr_axis axis )
-{
+static float axis_state( enum sr_axis axis ){
if( vg_ui.wants_mouse ) return 0.0f;
else return srinput.axis_states[axis][0];
}
setbtn( k_srbind_maccept, vg_getkey(SDLK_e) );
setbtn( k_srbind_maccept, vg_getkey(SDLK_RETURN));
setbtn( k_srbind_maccept, vg_getkey(SDLK_RETURN2));
+ setbtn( k_srbind_replay_play, vg_getkey(SDLK_SPACE) );
+ setbtn( k_srbind_replay_freecam, vg_getkey(SDLK_f) );
+ setbtn( k_srbind_replay_resume, vg_getkey(SDLK_r) );
/* axis
* --------------------------------------------*/
srinput.axis_states[ k_sraxis_mbrowse_v ][0] -= 1.0f;
if( vg_getkey( SDLK_UP ) )
srinput.axis_states[ k_sraxis_mbrowse_v ][0] += 1.0f;
- if( vg_getkey( SDLK_LEFT ) )
+
+ if( vg_getkey( SDLK_LEFT ) ){
srinput.axis_states[ k_sraxis_mbrowse_h ][0] -= 1.0f;
- if( vg_getkey( SDLK_RIGHT ) )
+ srinput.axis_states[ k_sraxis_replay_h ][0] -= 1.0f;
+ }
+ if( vg_getkey( SDLK_RIGHT ) ){
srinput.axis_states[ k_sraxis_mbrowse_h ][0] += 1.0f;
+ srinput.axis_states[ k_sraxis_replay_h ][0] += 1.0f;
+ }
if( vg_input.active_controller_index >= 0 ){
struct vg_controller *controller =
setbtn( k_srbind_maccept,buttons[ SDL_CONTROLLER_BUTTON_A ] );
setbtn( k_srbind_mopen, buttons[ SDL_CONTROLLER_BUTTON_START ] );
setbtn( k_srbind_mback, buttons[ SDL_CONTROLLER_BUTTON_START ] );
+ setbtn( k_srbind_replay_resume,
+ buttons[ SDL_CONTROLLER_BUTTON_LEFTSHOULDER ] );
+ setbtn( k_srbind_replay_play, buttons[ SDL_CONTROLLER_BUTTON_A ] );
+ setbtn( k_srbind_replay_freecam, buttons[ SDL_CONTROLLER_BUTTON_Y ] );
float *axis = controller->axises;
-
float *steer = srinput.joystick_states[ k_srjoystick_steer ][0],
*look = srinput.joystick_states[ k_srjoystick_look ][0],
*grab = srinput.joystick_states[ k_srjoystick_grab ][0],
*axisgrab = &srinput.axis_states[ k_sraxis_grab ][0],
*axisbrowseh = &srinput.axis_states[ k_sraxis_mbrowse_h ][0],
- *axisbrowsev = &srinput.axis_states[ k_sraxis_mbrowse_v ][0];
+ *axisbrowsev = &srinput.axis_states[ k_sraxis_mbrowse_v ][0],
+ *axisreplayh = &srinput.axis_states[ k_sraxis_replay_h ][0];
steer[0] += axis[ SDL_CONTROLLER_AXIS_LEFTX ];
steer[1] += axis[ SDL_CONTROLLER_AXIS_LEFTY ];
axisgrab[0] += vg_maxf( 0.0f, axis[ SDL_CONTROLLER_AXIS_TRIGGERRIGHT ] );
axisbrowseh[0] += axis[ SDL_CONTROLLER_AXIS_LEFTX ];
axisbrowsev[0] += axis[ SDL_CONTROLLER_AXIS_LEFTY ];
+ axisreplayh[0] += axis[ SDL_CONTROLLER_AXIS_LEFTX ];
float lh = axis[ SDL_CONTROLLER_AXIS_LEFTX ],
lv = axis[ SDL_CONTROLLER_AXIS_LEFTY ],
#include "input.h"
#include "world.h"
#include "audio.h"
+#include "player_replay.h"
VG_STATIC int localplayer_cmd_respawn( int argc, const char *argv[] )
{
audio_lock();
audio_oneshot( &audio_gate_pass, 1.0f, 0.0f );
audio_unlock();
+
+ replay_clear( &skaterift.replay );
}
VG_STATIC void player_apply_transport_to_cam( m4x3f transport )
}
PLAYER_API void player__spawn( player_instance *player, ent_spawn *rp ){
+ replay_clear( &skaterift.replay );
player__setpos( player, rp->transform.co );
v3_zero( player->rb.w );
q_identity( player->rb.q );
#define PLAYER_REPLAY_C
#include "player_replay.h"
+#include "input.h"
VG_STATIC void replay_clear( replay_buffer *replay ){
replay->head = NULL;
res->type = k_player_animation_type_absolute;
struct skeleton *sk = &localplayer.playeravatar->sk;
- skeleton_decompose_mtx_absolute( sk, res->pose );
memcpy( &frame->board_pose, &localplayer.board_pose,
sizeof(localplayer.board_pose) );
frame->time = vg.time;
v3_copy( localplayer.cam.pos, frame->cam_pos );
+
+ if( localplayer.gate_waiting ){
+ m4x3_mulv( localplayer.gate_waiting->transport,
+ frame->cam_pos, frame->cam_pos );
+
+ for( u32 i=1; i<sk->bone_count; i++ ){
+ struct skeleton_bone *sb = &sk->bones[i];
+ mdl_keyframe *kf = &res->pose[i-1];
+ m4x3f mtx;
+ m4x3_mul( localplayer.gate_waiting->transport, sk->final_mtx[i], mtx );
+ m4x3_decompose( mtx, kf->co, kf->q, kf->s );
+ }
+ }
+ else
+ skeleton_decompose_mtx_absolute( sk, res->pose );
+
v3_copy( localplayer.cam.angles, frame->cam_angles );
frame->cam_fov = localplayer.cam.fov;
}
VG_STATIC void skaterift_replay_pre_update(void){
if( skaterift.activity != k_skaterift_replay ) return;
- f64 speed = vg.time_frame_delta * 1.0;
- f64 target = skaterift.replay.cursor;
-
if( skaterift.replay_control == k_replay_control_resume ){
if( skaterift.replay.cursor_frame == skaterift.resume_target ||
skaterift.replay.cursor_frame == NULL ){
if( skaterift.resume_transition >= 1.0f )
skaterift_restore_frame( skaterift.resume_target );
else {
- target = vg_lerp( skaterift.resume_begin,
+ f64 target = vg_lerp( skaterift.resume_begin,
skaterift.resume_target->time,
vg_smoothstepf( skaterift.resume_transition ) );
replay_seek( &skaterift.replay, target );
}
}
else {
- if( vg_getkey( SDLK_9 ) ){
- target -= speed;
- skaterift.replay_control = k_replay_control_scrub;
- replay_seek( &skaterift.replay, target );
- }
- if( vg_getkey( SDLK_0 ) ){
- target += speed;
+ if( button_down( k_srbind_replay_play ) )
+ skaterift.replay_control = k_replay_control_play;
+
+ f32 target_speed = axis_state( k_sraxis_replay_h ) * 5.0;
+
+ if( fabsf(target_speed) > 0.01f )
skaterift.replay_control = k_replay_control_scrub;
- replay_seek( &skaterift.replay, target );
- }
- if( vg_getkey( SDLK_7 ) )
- skaterift.replay_control = k_replay_control_play;
+ if( skaterift.replay_control == k_replay_control_play )
+ target_speed = 1.0;
+
+ vg_slewf( &skaterift.track_velocity, target_speed,
+ 10.0f*vg.time_frame_delta );
+
+ if( fabsf( skaterift.track_velocity ) > 0.0001f ){
+ f64 target = skaterift.replay.cursor;
+ target += skaterift.track_velocity * vg.time_frame_delta;
- if( skaterift.replay_control == k_replay_control_play ){
- target += vg.time_frame_delta;
replay_seek( &skaterift.replay, target );
}
- if( vg_getkey( SDLK_8 ) ){
+ if( button_down( k_srbind_replay_resume ) ){
replay_frame *prev = replay_find_recent_stateframe(&skaterift.replay);
if( prev ){
skaterift.resume_transition = 0.0f;
}
}
+ else if( button_down( k_srbind_mback ) ){
+ if( skaterift.replay.statehead )
+ skaterift_restore_frame( skaterift.replay.statehead );
+ else
+ skaterift.activity = k_skaterift_default;
+ srinput.enabled = 0;
+ }
}
}
char buffer[ 128 ];
/* mainbar */
- ui_px height = 20,
+ ui_px height = 32,
cwidth = 2;
ui_rect bar = { 0, vg.window_y - height, vg.window_x, height };
ui_fill( bar, ui_colour( k_ui_bg ) );
snprintf( buffer, 128, "-%.2fs\n", len );
ui_text( bar, buffer, 1, k_ui_align_middle_left, 0 );
ui_text( bar, "0s", 1, k_ui_align_middle_right, 0 );
+
+ ui_rect info = { 0, vg.window_y-bar[3]-64, 128, 64 };
+ if( vg_input.display_input_method == k_input_method_controller )
+ ui_text( info, "scrub: <- LS ->\nresume:LB\nplay: A", 1,0,0 );
+ else
+ ui_text( info, "scrub: <- ->\nresume:R\nplay: space", 1,0,0 );
}
#endif /* PLAYER_REPLAY_C */
VG_STATIC void replay_get_camera( replay_buffer *replay, camera *cam );
VG_STATIC void replay_get_frame_camera( replay_frame *frame, camera *cam );
VG_STATIC f32 replay_subframe_time( replay_buffer *replay );
+VG_STATIC void replay_clear( replay_buffer *replay );
VG_STATIC void skaterift_replay_pre_update(void);
VG_STATIC void skaterift_replay_imgui(void);
uniform sampler2D uTexMotion;
uniform float uBlurStrength;
uniform vec2 uOverrideDir;
+uniform float uTime;
+uniform float uGlitchStrength;
in vec2 aUv;
-vec2 rand_hash22( vec2 p )
-{
+vec2 rand_hash22( vec2 p ){
vec3 p3 = fract(vec3(p.xyx) * 213.8976123);
p3 += dot(p3, p3.yzx+19.19);
return fract(vec2((p3.x + p3.y)*p3.z, (p3.x+p3.z)*p3.y));
}
-void main()
-{
- vec2 vcenter = (aUv-vec2(0.5))*vec2(2.0);
- vec2 vrand = rand_hash22( aUv ) * 2.0 - vec2(1.0);
+const int NOISE_LOOP = 3;
+vec3 digital_noise( uvec3 iuv ){
+ iuv *=uvec3(8,2524,7552);
+ for( int i=0; i<NOISE_LOOP; i++ )
+ iuv += (iuv.yzx<<2) ^ (iuv.yxz)+iuv.z;
+ return vec3(iuv)*(1.0/float(0xffffffffU));
+}
+
+void main(){
+ vec2 vuv = aUv;
+
+ if( uGlitchStrength > 0.0 ){
+ uvec3 p = uvec3( gl_FragCoord.xy, uint(uTime*30.0) );
+ vec2 g = digital_noise(p).xy;
+ vuv = aUv + g.xy*uGlitchStrength - uGlitchStrength*0.5;
+ }
+
+ vec2 vrand = rand_hash22( vuv ) * 2.0 - vec2(1.0);
vec2 vrand1 = rand_hash22( vrand ) * 2.0 - vec2(1.0);
- vec2 vdir = texture( uTexMotion, aUv ).xy * uBlurStrength + uOverrideDir;
+ vec2 vdir = texture( uTexMotion, vuv ).xy * uBlurStrength + uOverrideDir;
- vec4 vcolour0 = texture( uTexMain, aUv + vdir*vrand.x );
- vec4 vcolour1 = texture( uTexMain, aUv + vdir*vrand.y );
- vec4 vcolour2 = texture( uTexMain, aUv + vdir*vrand1.x );
- vec4 vcolour3 = texture( uTexMain, aUv + vdir*vrand1.y );
+ vec4 vcolour0 = texture( uTexMain, vuv + vdir*vrand.x );
+ vec4 vcolour1 = texture( uTexMain, vuv + vdir*vrand.y );
+ vec4 vcolour2 = texture( uTexMain, vuv + vdir*vrand1.x );
+ vec4 vcolour3 = texture( uTexMain, vuv + vdir*vrand1.y );
FragColor = ( vcolour0 + vcolour1 + vcolour2 + vcolour3 ) * 0.25;
}
"uniform sampler2D uTexMotion;\n"
"uniform float uBlurStrength;\n"
"uniform vec2 uOverrideDir;\n"
+"uniform float uTime;\n"
+"uniform float uGlitchStrength;\n"
"\n"
"in vec2 aUv;\n"
"\n"
-"vec2 rand_hash22( vec2 p )\n"
-"{\n"
+"vec2 rand_hash22( vec2 p ){\n"
" vec3 p3 = fract(vec3(p.xyx) * 213.8976123);\n"
" p3 += dot(p3, p3.yzx+19.19);\n"
" return fract(vec2((p3.x + p3.y)*p3.z, (p3.x+p3.z)*p3.y));\n"
"}\n"
"\n"
-"void main()\n"
-"{\n"
-" vec2 vcenter = (aUv-vec2(0.5))*vec2(2.0);\n"
-" vec2 vrand = rand_hash22( aUv ) * 2.0 - vec2(1.0);\n"
+"const int NOISE_LOOP = 3;\n"
+"vec3 digital_noise( uvec3 iuv ){\n"
+" iuv *=uvec3(8,2524,7552);\n"
+" for( int i=0; i<NOISE_LOOP; i++ )\n"
+" iuv += (iuv.yzx<<2) ^ (iuv.yxz)+iuv.z;\n"
+" return vec3(iuv)*(1.0/float(0xffffffffU));\n"
+"}\n"
+"\n"
+"void main(){\n"
+" vec2 vuv = aUv; \n"
+"\n"
+" if( uGlitchStrength > 0.0 ){\n"
+" uvec3 p = uvec3( gl_FragCoord.xy, uint(uTime*30.0) );\n"
+" vec2 g = digital_noise(p).xy;\n"
+" vuv = aUv + g.xy*uGlitchStrength - uGlitchStrength*0.5;\n"
+" }\n"
+"\n"
+" vec2 vrand = rand_hash22( vuv ) * 2.0 - vec2(1.0);\n"
" vec2 vrand1 = rand_hash22( vrand ) * 2.0 - vec2(1.0);\n"
" \n"
-" vec2 vdir = texture( uTexMotion, aUv ).xy * uBlurStrength + uOverrideDir;\n"
+" vec2 vdir = texture( uTexMotion, vuv ).xy * uBlurStrength + uOverrideDir;\n"
"\n"
-" vec4 vcolour0 = texture( uTexMain, aUv + vdir*vrand.x );\n"
-" vec4 vcolour1 = texture( uTexMain, aUv + vdir*vrand.y );\n"
-" vec4 vcolour2 = texture( uTexMain, aUv + vdir*vrand1.x );\n"
-" vec4 vcolour3 = texture( uTexMain, aUv + vdir*vrand1.y );\n"
+" vec4 vcolour0 = texture( uTexMain, vuv + vdir*vrand.x );\n"
+" vec4 vcolour1 = texture( uTexMain, vuv + vdir*vrand.y );\n"
+" vec4 vcolour2 = texture( uTexMain, vuv + vdir*vrand1.x );\n"
+" vec4 vcolour3 = texture( uTexMain, vuv + vdir*vrand1.y );\n"
"\n"
" FragColor = ( vcolour0 + vcolour1 + vcolour2 + vcolour3 ) * 0.25;\n"
"}\n"
static GLuint _uniform_blitblur_uTexMotion;
static GLuint _uniform_blitblur_uBlurStrength;
static GLuint _uniform_blitblur_uOverrideDir;
+static GLuint _uniform_blitblur_uTime;
+static GLuint _uniform_blitblur_uGlitchStrength;
static void shader_blitblur_uInverseRatio(v2f v){
glUniform2fv(_uniform_blitblur_uInverseRatio,1,v);
}
static void shader_blitblur_uOverrideDir(v2f v){
glUniform2fv(_uniform_blitblur_uOverrideDir,1,v);
}
+static void shader_blitblur_uTime(float f){
+ glUniform1f(_uniform_blitblur_uTime,f);
+}
+static void shader_blitblur_uGlitchStrength(float f){
+ glUniform1f(_uniform_blitblur_uGlitchStrength,f);
+}
static void shader_blitblur_register(void){
vg_shader_register( &_shader_blitblur );
}
_uniform_blitblur_uTexMotion = glGetUniformLocation( _shader_blitblur.id, "uTexMotion" );
_uniform_blitblur_uBlurStrength = glGetUniformLocation( _shader_blitblur.id, "uBlurStrength" );
_uniform_blitblur_uOverrideDir = glGetUniformLocation( _shader_blitblur.id, "uOverrideDir" );
+ _uniform_blitblur_uTime = glGetUniformLocation( _shader_blitblur.id, "uTime" );
+ _uniform_blitblur_uGlitchStrength = glGetUniformLocation( _shader_blitblur.id, "uGlitchStrength" );
}
#endif /* SHADER_blitblur_H */
#if 1
#define SR_NETWORKED
-#define VG_DEVWINDOW
+//#define VG_DEVWINDOW
/*
* system headers
vg_loader_step( load_playermodels, NULL );
/* player setup */
- u32 bytes = (1024*1024*1)/2;
+ u32 bytes = 1024*1024*10;
skaterift.replay.data = vg_linear_alloc( vg_mem.rtmemory, bytes );
skaterift.replay.size = bytes;
replay_clear( &skaterift.replay );
if( skaterift.activity & (k_skaterift_replay|k_skaterift_menu) )
target = 0;
- vg_slewf( &skaterift.time_rate, target, vg.time_frame_delta * 6.0f );
+ vg_slewf( &skaterift.time_rate, target, vg.time_frame_delta * (1.0f/0.3f) );
vg.time_rate = vg_smoothstepf( skaterift.time_rate );
player__pre_update( &localplayer );
(vg.time_frame_delta*60.0) );
shader_blitblur_uInverseRatio( inverse );
+ static f64 effect_time = 133.0;
+ effect_time += vg.time_frame_delta;
+ shader_blitblur_uTime( effect_time );
+
+ f32 glitch_strength = 0.0f;
+ if( skaterift.activity == k_skaterift_replay ){
+ glitch_strength = 0.005f;
+ if( skaterift.replay_control == k_replay_control_play )
+ glitch_strength = 0.005f;
+ else
+ glitch_strength += 0.005f*skaterift.track_velocity;
+ }
+ shader_blitblur_uGlitchStrength( glitch_strength );
+
v2f override;
if( skaterift.activity == k_skaterift_menu )
v2_muls( (v2f){ 0.04f, 0.001f }, 1.0f-skaterift.time_rate, override );
vg_smoothstepf(global_skateshop.factive), &skaterift.cam );
if( skaterift.activity == k_skaterift_replay ){
- camera temp;
- replay_get_camera( &skaterift.replay, &temp );
- camera_lerp( &skaterift.cam, &temp, 1.0f-skaterift.time_rate,
- &skaterift.cam );
+ replay_get_camera( &skaterift.replay, &skaterift.cam );
}
skaterift.cam.nearz = 0.1f;