--- /dev/null
+#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();
+}