From: hgn Date: Fri, 14 Jun 2024 12:55:24 +0000 (+0100) Subject: transfer code from skate rift X-Git-Url: https://harrygodden.com/git/?a=commitdiff_plain;h=1c4f4db09ea9501264a6bc2f58412166c9328e52;p=vg.git transfer code from skate rift --- diff --git a/shaders/blit.vs b/shaders/blit.vs new file mode 100644 index 0000000..06ffba6 --- /dev/null +++ b/shaders/blit.vs @@ -0,0 +1,10 @@ +layout (location=0) in vec2 a_co; +out vec2 aUv; + +uniform vec2 uInverseRatio; + +void main() +{ + gl_Position = vec4(a_co*2.0-1.0,0.0,1.0); + aUv = a_co * uInverseRatio; +} diff --git a/shaders/blit_blur.fs b/shaders/blit_blur.fs new file mode 100644 index 0000000..592c83f --- /dev/null +++ b/shaders/blit_blur.fs @@ -0,0 +1,32 @@ +out vec4 FragColor; +uniform sampler2D uTexMain; +uniform sampler2D uTexMotion; +uniform float uBlurStrength; +uniform vec2 uOverrideDir; +uniform vec2 uClampUv; + +in vec2 aUv; + +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 vuv = aUv; + + vec2 vrand = rand_hash22( vuv ) * 2.0 - vec2(1.0); + vec2 vrand1 = rand_hash22( vrand ) * 2.0 - vec2(1.0); + + vec2 vdir = texture( uTexMotion, vuv ).xy * uBlurStrength + uOverrideDir; + + vec4 vcolour0 = texture( uTexMain, min(vuv + vdir*vrand.x,uClampUv) ); + vec4 vcolour1 = texture( uTexMain, min(vuv + vdir*vrand.y,uClampUv) ); + vec4 vcolour2 = texture( uTexMain, min(vuv + vdir*vrand1.x,uClampUv) ); + vec4 vcolour3 = texture( uTexMain, min(vuv + vdir*vrand1.y,uClampUv) ); + + FragColor = ( vcolour0 + vcolour1 + vcolour2 + vcolour3 ) * 0.25; +} diff --git a/shaders/blit_colour.fs b/shaders/blit_colour.fs new file mode 100644 index 0000000..7eb290e --- /dev/null +++ b/shaders/blit_colour.fs @@ -0,0 +1,9 @@ +out vec4 FragColor; +uniform vec4 uColour; + +in vec2 aUv; + +void main() +{ + FragColor = uColour; +} diff --git a/shaders/blit_tex.fs b/shaders/blit_tex.fs new file mode 100644 index 0000000..634e84f --- /dev/null +++ b/shaders/blit_tex.fs @@ -0,0 +1,41 @@ +out vec4 FragColor; +uniform sampler2D uTexMain; + +in vec2 aUv; + +float kPi = 3.14159265358979; + +vec2 fisheye_distort(vec2 xy) +{ + float aperture = 1350.0; + float apertureHalf = 0.5 * aperture * (kPi / 180.0); + float maxFactor = sin(apertureHalf); + + vec2 uv; + float d = length(xy); + if(d < (2.0-maxFactor)) + { + d = length(xy * maxFactor); + float z = sqrt(1.0 - d * d); + float r = atan(d, z) / kPi; + float phi = atan(xy.y, xy.x); + + uv.x = r * cos(phi) + 0.5; + uv.y = r * sin(phi) + 0.5; + } + else + { + uv = 0.5*xy + 0.5; + } + + return uv; +} + + +void main() +{ + vec2 vwarp = 2.0*aUv - 1.0; + vwarp = fisheye_distort( vwarp ); + + FragColor = texture( uTexMain, aUv ); +} diff --git a/shaders/motion_vectors_common.glsl b/shaders/motion_vectors_common.glsl new file mode 100644 index 0000000..7e6c114 --- /dev/null +++ b/shaders/motion_vectors_common.glsl @@ -0,0 +1 @@ +const float k_motion_lerp_amount = 0.01; diff --git a/shaders/motion_vectors_fs.glsl b/shaders/motion_vectors_fs.glsl new file mode 100644 index 0000000..b92ae2d --- /dev/null +++ b/shaders/motion_vectors_fs.glsl @@ -0,0 +1,16 @@ +#include "../vg/shaders/motion_vectors_common.glsl" + +layout (location = 1) out vec4 oMotionVec; + +in vec3 aMotionVec0; +in vec3 aMotionVec1; + +void compute_motion_vectors() +{ + // Write motion vectors + vec2 vmotion0 = aMotionVec0.xy / aMotionVec0.z; + vec2 vmotion1 = aMotionVec1.xy / aMotionVec1.z; + vec2 vmotion = (vmotion1-vmotion0) * (1.0/k_motion_lerp_amount); + + oMotionVec = vec4( vmotion, 0.0, 1.0 ); +} diff --git a/shaders/motion_vectors_vs.glsl b/shaders/motion_vectors_vs.glsl new file mode 100644 index 0000000..4eee0a6 --- /dev/null +++ b/shaders/motion_vectors_vs.glsl @@ -0,0 +1,14 @@ +#include "../vg/shaders/motion_vectors_common.glsl" + +out vec3 aMotionVec0; +out vec3 aMotionVec1; + +void vs_motion_out( vec4 vproj0, vec4 vproj1 ) +{ + // This magically solves some artifacting errors! + // + vproj1 = vproj0*(1.0-k_motion_lerp_amount) + vproj1*k_motion_lerp_amount; + + aMotionVec0 = vec3( vproj0.xy, vproj0.w ); + aMotionVec1 = vec3( vproj1.xy, vproj1.w ); +} diff --git a/vg_build_utils_shader.h b/vg_build_utils_shader.h index a9d885b..f83e20c 100644 --- a/vg_build_utils_shader.h +++ b/vg_build_utils_shader.h @@ -154,6 +154,9 @@ void vg_build_shader_impl( char *path ) fclose( fp ); } +#define _S( NAME, VS, FS ) \ + vg_build_shader( "shaders/" VS, "shaders/" FS, NULL, "shaders", NAME ) + int vg_build_shader( char *src_vert, /* path/to/vert.vs */ char *src_frag, /* path/to/frag.fs */ char *src_geo, /* unused currently */ @@ -201,6 +204,7 @@ int vg_build_shader( char *src_vert, /* path/to/vert.vs */ if( !compile_subshader( c_body, src_vert ) ) { fclose( header ); + vg_fatal_error( "Failed to assemble vertex source code" ); return 0; } @@ -208,6 +212,7 @@ int vg_build_shader( char *src_vert, /* path/to/vert.vs */ if( !compile_subshader( c_body, src_frag ) ) { fclose( header ); + vg_fatal_error( "Failed to assemble fragment source code" ); return 0; } @@ -281,3 +286,10 @@ int vg_build_shader( char *src_vert, /* path/to/vert.vs */ fclose( header ); return 1; } + +void vg_build_postprocess_shaders(void) +{ + _S( "blit", "../vg/shaders/blit.vs", "../vg/shaders/blit_tex.fs" ); + _S( "blitblur", "../vg/shaders/blit.vs", "../vg/shaders/blit_blur.fs" ); + _S( "blitcolour","../vg/shaders/blit.vs", "../vg/shaders/blit_colour.fs" ); +} diff --git a/vg_engine.c b/vg_engine.c index 86b44c4..a7e8a68 100644 --- a/vg_engine.c +++ b/vg_engine.c @@ -1,7 +1,8 @@ #include "vg_engine.h" #include "vg_async.h" -struct vg_engine vg = { +struct vg_engine vg = +{ .time_rate = 1.0, .time_fixed_delta = VG_TIMESTEP_FIXED, }; @@ -64,6 +65,7 @@ static void _vg_opengl_sync_init(void) #include "vg_tex.h" #include "vg_input.h" #include "vg_framebuffer.h" +#include "vg_render.h" #include "vg_lines.h" #include "vg_rigidbody_view.h" #include "vg_loader.h" @@ -132,6 +134,7 @@ static void _vg_load_full( void *data ) /* internal */ vg_loader_step( vg_framebuffer_init, NULL ); + vg_loader_step( vg_render_init, NULL ); vg_loader_step( vg_input_init, vg_input_free ); vg_loader_step( vg_lines_init, NULL ); vg_loader_step( vg_rb_view_init, NULL ); @@ -744,6 +747,7 @@ void vg_enter( int argc, char *argv[], const char *window_name ) k_var_dtype_i32, VG_VAR_PERSISTENT ); vg_console_reg_var( "vg_screen_mode", &vg.screen_mode, k_var_dtype_i32, VG_VAR_PERSISTENT ); + vg_audio_register(); vg_console_load_autos(); @@ -1304,6 +1308,7 @@ int AmdPowerXpressRequestHighPerformance = 1; #include "vg_rigidbody_view.c" #include "vg_shader.c" #include "vg_framebuffer.c" +#include "vg_render.c" #ifdef VG_CUSTOM_SHADERS #include "shaders/impl.c" diff --git a/vg_render.c b/vg_render.c new file mode 100644 index 0000000..3274721 --- /dev/null +++ b/vg_render.c @@ -0,0 +1,183 @@ +#include "vg_render.h" +#include "shaders/blit.h" +#include "shaders/blitblur.h" + +struct vg_postprocess vg_postprocess = +{ + .blur_effect = 1, + .blur_strength = 0.3f, +}; + +struct vg_render _vg_render = +{ + .scale = 1.0f +}; + +static void vg_async_postprocess_init( void *payload, u32 size ) +{ + f32 quad[] = + { + 0.00f,0.00f, 1.00f,1.00f, 0.00f,1.00f, + 0.00f,0.00f, 1.00f,0.00f, 1.00f,1.00f, + }; + + glGenVertexArrays( 1, &vg_postprocess.quad_vao ); + glGenBuffers( 1, &vg_postprocess.quad_vbo ); + glBindVertexArray( vg_postprocess.quad_vao ); + glBindBuffer( GL_ARRAY_BUFFER, vg_postprocess.quad_vbo ); + glBufferData( GL_ARRAY_BUFFER, sizeof(quad), quad, GL_STATIC_DRAW ); + glBindVertexArray( vg_postprocess.quad_vao ); + glVertexAttribPointer( 0, 2, GL_FLOAT, GL_FALSE, sizeof(f32)*2, (void*)0 ); + glEnableVertexAttribArray( 0 ); +} + +void vg_render_init(void) +{ + vg_async_call( vg_async_postprocess_init, NULL, 0 ); + + vg_console_reg_var( "render_scale", &_vg_render.scale, + k_var_dtype_f32, VG_VAR_PERSISTENT ); + +#ifdef VG_3D + vg_console_reg_var( "blur_strength", &vg_postprocess.blur_strength, + k_var_dtype_f32, 0 ); + vg_console_reg_var( "blur_effect", &vg_postprocess.blur_effect, + k_var_dtype_i32, VG_VAR_PERSISTENT ); + + void *alloc = vg_mem.rtmemory; + + /* + * Main framebuffer + */ + _vg_render.fb_main = vg_framebuffer_allocate( alloc, 3, 1 ); + _vg_render.fb_main->display_name = "main"; + _vg_render.fb_main->resolution_div = 1; + _vg_render.fb_main->attachments[0] = (vg_framebuffer_attachment) + { + "colour", k_framebuffer_attachment_type_texture, + + .internalformat = GL_RGB, + .format = GL_RGB, + .type = GL_UNSIGNED_BYTE, + .attachment = GL_COLOR_ATTACHMENT0 + }; + _vg_render.fb_main->attachments[1] = (vg_framebuffer_attachment) + { + "motion", k_framebuffer_attachment_type_texture, + + .quality = k_framebuffer_quality_high_only, + .internalformat = GL_RG16F, + .format = GL_RG, + .type = GL_FLOAT, + .attachment = GL_COLOR_ATTACHMENT1 + }; + _vg_render.fb_main->attachments[2] = (vg_framebuffer_attachment) + { + "depth_stencil", k_framebuffer_attachment_type_texture_depth, + .internalformat = GL_DEPTH24_STENCIL8, + .format = GL_DEPTH_STENCIL, + .type = GL_UNSIGNED_INT_24_8, + .attachment = GL_DEPTH_STENCIL_ATTACHMENT + }; + vg_framebuffer_create( _vg_render.fb_main ); + + /* + * Water reflection + */ + _vg_render.fb_water_reflection = vg_framebuffer_allocate( alloc, 2, 1 ); + _vg_render.fb_water_reflection->display_name = "water_reflection"; + _vg_render.fb_water_reflection->resolution_div = 2; + _vg_render.fb_water_reflection->attachments[0] = (vg_framebuffer_attachment) + { + "colour", k_framebuffer_attachment_type_texture, + .internalformat = GL_RGB, + .format = GL_RGB, + .type = GL_UNSIGNED_BYTE, + .attachment = GL_COLOR_ATTACHMENT0 + }; + _vg_render.fb_water_reflection->attachments[1] = (vg_framebuffer_attachment) + { + "depth_stencil", k_framebuffer_attachment_type_renderbuffer, + .internalformat = GL_DEPTH24_STENCIL8, + .attachment = GL_DEPTH_STENCIL_ATTACHMENT + }; + vg_framebuffer_create( _vg_render.fb_water_reflection ); + + /* + * Thid rendered view from the perspective of the camera, but just + * captures stuff thats under the water + */ + _vg_render.fb_water_beneath = vg_framebuffer_allocate( alloc, 2, 1 ); + _vg_render.fb_water_beneath->display_name = "water_beneath"; + _vg_render.fb_water_beneath->resolution_div = 2; + _vg_render.fb_water_beneath->attachments[0] = (vg_framebuffer_attachment) + { + "colour", k_framebuffer_attachment_type_texture, + .internalformat = GL_RED, + .format = GL_RED, + .type = GL_UNSIGNED_BYTE, + .attachment = GL_COLOR_ATTACHMENT0 + }; + _vg_render.fb_water_beneath->attachments[1] = (vg_framebuffer_attachment) + { + "depth_stencil", k_framebuffer_attachment_type_renderbuffer, + .internalformat = GL_DEPTH24_STENCIL8, + .attachment = GL_DEPTH_STENCIL_ATTACHMENT + }; + vg_framebuffer_create( _vg_render.fb_water_beneath ); +#endif +} + +void vg_render_fullscreen_quad(void) +{ + glBindVertexArray( vg_postprocess.quad_vao ); + glDrawArrays( GL_TRIANGLES, 0, 6 ); +} + +/* + * Utility + */ + +void vg_postprocess_to_screen( vg_framebuffer *fb ) +{ + glBindFramebuffer( GL_FRAMEBUFFER, 0 ); + glViewport( 0,0, vg.window_x, vg.window_y ); + + glEnable(GL_BLEND); + glDisable(GL_DEPTH_TEST); + glBlendFunc(GL_ONE_MINUS_DST_ALPHA, GL_DST_ALPHA); + glBlendEquation(GL_FUNC_ADD); + + v2f inverse; + vg_framebuffer_inverse_ratio( fb, inverse ); + +#ifdef VG_3D + if( vg_postprocess.blur_effect ) + { + shader_blitblur_use(); + shader_blitblur_uTexMain( 0 ); + shader_blitblur_uTexMotion( 1 ); + + f32 s = vg.time_frame_delta*60.0; + shader_blitblur_uBlurStrength( vg_postprocess.blur_strength / s ); + shader_blitblur_uInverseRatio( inverse ); + + inverse[0] -= 0.0001f; + inverse[1] -= 0.0001f; + shader_blitblur_uClampUv( inverse ); + shader_blitblur_uOverrideDir( vg_postprocess.motion_blur_override ); + + vg_framebuffer_bind_texture( fb, 0, 0 ); + vg_framebuffer_bind_texture( fb, 1, 1 ); + } + else +#endif + { + shader_blit_use(); + shader_blit_uTexMain( 0 ); + shader_blit_uInverseRatio( inverse ); + vg_framebuffer_bind_texture( fb, 0, 0 ); + } + + vg_render_fullscreen_quad(); +} diff --git a/vg_render.h b/vg_render.h new file mode 100644 index 0000000..15ff12e --- /dev/null +++ b/vg_render.h @@ -0,0 +1,31 @@ +#pragma once +#include "vg_engine.h" + +struct vg_postprocess +{ + GLuint quad_vao, + quad_vbo; + +#ifdef VG_3D + i32 blur_effect; + f32 blur_strength; + v2f motion_blur_override; +#endif +} +extern vg_postprocess; + +struct vg_render +{ + f32 scale; + +#ifdef VG_3D + vg_framebuffer *fb_main, + *fb_water_reflection, + *fb_water_beneath; +#endif +} +extern _vg_render; + +void vg_render_init(void); +void vg_render_fullscreen_quad(void); +void vg_postprocess_to_screen( vg_framebuffer *fb );