revision 2
authorhgn <hgodden00@gmail.com>
Fri, 23 Feb 2024 03:33:09 +0000 (03:33 +0000)
committerhgn <hgodden00@gmail.com>
Fri, 23 Feb 2024 03:33:09 +0000 (03:33 +0000)
144 files changed:
addon.c
addon.h
addon_types.c [new file with mode: 0644]
addon_types.h
audio.c [new file with mode: 0644]
audio.h
build.c
bvh.h [deleted file]
camera.h
depth_compare.h
ent_challenge.c
ent_challenge.h
ent_miniworld.c
ent_miniworld.h
ent_objective.c
ent_objective.h [new file with mode: 0644]
ent_region.c
ent_region.h
ent_relay.c
ent_relay.h [new file with mode: 0644]
ent_route.c
ent_route.h
ent_skateshop.c
ent_skateshop.h
ent_tornado.c
ent_tornado.h [new file with mode: 0644]
ent_traffic.c
ent_traffic.h
entity.c
entity.h
font.h
freecam.c
freecam.h
gui.h
menu.c [new file with mode: 0644]
menu.h
model.h
network.c
network.h
particle.c
particle.h
player.c
player.h
player_api.h
player_basic_info.c
player_basic_info.h
player_common.c
player_dead.c
player_dead.h
player_drive.c
player_drive.h
player_effects.c
player_effects.h
player_glide.c
player_glide.h
player_ragdoll.c
player_ragdoll.h
player_remote.c
player_remote.h
player_render.c
player_render.h
player_replay.c
player_replay.h
player_skate.c
player_skate.h
player_walk.c
player_walk.h
render.c [new file with mode: 0644]
render.h
save.c
save.h
scene.c [new file with mode: 0644]
scene.h
shaders/blit.h
shaders/blit_transition.h
shaders/blitblur.h
shaders/blitcolour.h
shaders/impl.c [new file with mode: 0644]
shaders/model_board_view.h
shaders/model_character_view.h
shaders/model_entity.h
shaders/model_font.h
shaders/model_gate.h
shaders/model_gate_unlinked.h
shaders/model_menu.h
shaders/model_sky.h
shaders/model_sky_space.h
shaders/particle.h
shaders/routeui.h
shaders/scene_cubemapped.h
shaders/scene_depth.h
shaders/scene_foliage.h
shaders/scene_font.h
shaders/scene_fxglow.h
shaders/scene_override.h
shaders/scene_position.h
shaders/scene_route.h
shaders/scene_scoretext.h
shaders/scene_standard.h
shaders/scene_standard_alphatest.h
shaders/scene_terrain.h
shaders/scene_vertex_blend.h
shaders/scene_water.h
shaders/scene_water_fast.h
shaders/trail.h
skaterift.c
skaterift.h
skeleton.h
steam.c [new file with mode: 0644]
steam.h
testing.c [deleted file]
trail.c
trail.h
vehicle.c
vehicle.h
workshop.c
workshop.h
world.c
world.h
world_audio.c
world_audio.h
world_entity.c
world_entity.h
world_gate.c
world_gate.h
world_gen.c
world_load.c
world_load.h
world_map.c
world_map.h
world_physics.c
world_physics.h
world_render.c
world_render.h
world_routes.c
world_routes.h
world_routes_ui.c
world_routes_ui.h
world_sfd.c
world_sfd.h
world_volumes.c
world_volumes.h
world_water.c
world_water.h

diff --git a/addon.c b/addon.c
index 984bb9c62cf40d868a257c012d41b365eacc69f9..b67db74f925e9b883116c70de183eec55c703701 100644 (file)
--- a/addon.c
+++ b/addon.c
@@ -1,13 +1,14 @@
-#ifndef ADDON_C
-#define ADDON_C
-
+#include "vg/vg_engine.h"
 #include "addon.h"
 #include "addon_types.h"
 #include "vg/vg_msg.h"
 #include "steam.h"
 #include "workshop.h"
 
-static u32 addon_count( enum addon_type type, u32 ignoreflags ){
+struct addon_system addon_system;
+
+u32 addon_count( enum addon_type type, u32 ignoreflags )
+{
    if( ignoreflags ){
       u32 typecount = 0, count = 0;
       for( u32 i=0; typecount<addon_count( type, 0 ); i++ ){
@@ -30,8 +31,9 @@ static u32 addon_count( enum addon_type type, u32 ignoreflags ){
 
 
 /* these kind of suck, oh well. */
-static addon_reg *get_addon_from_index( enum addon_type type, u32 index, 
-                                        u32 ignoreflags ){
+addon_reg *get_addon_from_index( enum addon_type type, u32 index, 
+                                 u32 ignoreflags )
+{
    u32 typecount = 0, count = 0;
    for( u32 i=0; typecount<addon_count(type,0); i++ ){
       addon_reg *reg = &addon_system.registry[i];
@@ -51,7 +53,8 @@ static addon_reg *get_addon_from_index( enum addon_type type, u32 index,
    return NULL;
 }
 
-static u32 get_index_from_addon( enum addon_type type, addon_reg *a ){
+u32 get_index_from_addon( enum addon_type type, addon_reg *a )
+{
    u32 count = 0;
    for( u32 i=0; count<addon_system.registry_type_counts[type]; i++ ){
       addon_reg *reg = &addon_system.registry[i];
@@ -66,7 +69,8 @@ static u32 get_index_from_addon( enum addon_type type, addon_reg *a ){
    return 0xffffffff;
 }
 
-static u32 addon_match( addon_alias *alias ){
+u32 addon_match( addon_alias *alias )
+{
    if( alias->type == k_addon_type_none ) return 0xffffffff;
 
    u32 foldername_djb2 = 0;
@@ -100,7 +104,8 @@ static u32 addon_match( addon_alias *alias ){
 /*
  * Create a string version of addon alias in buf
  */
-static void addon_alias_uid( addon_alias *alias, char buf[ADDON_UID_MAX] ){
+void addon_alias_uid( addon_alias *alias, char buf[ADDON_UID_MAX] )
+{
    if( alias->workshop_id ){
       snprintf( buf, 128, "sr%03d-steam-"PRINTF_U64, 
             alias->type, alias->workshop_id );
@@ -114,7 +119,8 @@ static void addon_alias_uid( addon_alias *alias, char buf[ADDON_UID_MAX] ){
 /*
  * equality check
  */
-static int addon_alias_eq( addon_alias *a, addon_alias *b ){
+int addon_alias_eq( addon_alias *a, addon_alias *b )
+{
    if( a->type == b->type ){
       if( a->workshop_id == b->workshop_id ){
          if( a->workshop_id )
@@ -131,7 +137,8 @@ static int addon_alias_eq( addon_alias *a, addon_alias *b ){
 /*
  * make alias represent NULL.
  */
-static void invalidate_addon_alias( addon_alias *alias ){
+void invalidate_addon_alias( addon_alias *alias )
+{
    alias->type = k_addon_type_none;
    alias->workshop_id = 0;
    alias->foldername[0] = '\0';
@@ -140,7 +147,8 @@ static void invalidate_addon_alias( addon_alias *alias ){
 /*
  * parse uid to alias. returns 1 if successful
  */
-static int addon_uid_to_alias( const char *uid, addon_alias *alias ){
+int addon_uid_to_alias( const char *uid, addon_alias *alias )
+{
 /*           1
  * 01234567890123
  * sr&&&-@@@@@-#*
@@ -181,7 +189,8 @@ static int addon_uid_to_alias( const char *uid, addon_alias *alias ){
    return 1;
 }
 
-static void addon_system_init( void ){
+void addon_system_init( void )
+{
    u32 reg_size   = sizeof(addon_reg)*ADDON_MOUNTED_MAX;
    addon_system.registry = vg_linear_alloc( vg_mem.rtmemory, reg_size );
 
@@ -224,7 +233,7 @@ static void addon_system_init( void ){
 /*
  * Reciever for scan completion. copies the registry counts back into main fred
  */
-static void async_addon_reg_update( void *data, u32 size )
+void async_addon_reg_update( void *data, u32 size )
 {
    vg_info( "Registry update notify\n" );
    
@@ -351,9 +360,9 @@ static addon_reg *addon_mount_workshop_folder( PublishedFileId_t workshop_id,
 /*
  * Mount a local folder. may or may not have addon.inf
  */
-static addon_reg *addon_mount_local_addon( const char *folder,
-                                              enum addon_type type,
-                                              const char *content_ext )
+addon_reg *addon_mount_local_addon( const char *folder,
+                                    enum addon_type type,
+                                    const char *content_ext )
 {
    char folder_path_buf[4096];
    vg_str folder_path;
@@ -428,7 +437,8 @@ static addon_reg *addon_mount_local_addon( const char *folder,
 /*
  * Check all subscribed items
  */
-static void addon_mount_workshop_items(void){
+void addon_mount_workshop_items(void)
+{
    if( skaterift.demo_mode ){
       vg_info( "Won't load workshop items in demo mode\n" );
       return;
@@ -485,9 +495,9 @@ next_file_workshop:;
  * Scan a local content folder for addons. It must find at least one file with 
  * the specified content_ext to be considered.
  */
-static void addon_mount_content_folder( enum addon_type type,
-                                           const char *base_folder, 
-                                           const char *content_ext )
+void addon_mount_content_folder( enum addon_type type,
+                                 const char *base_folder, 
+                                 const char *content_ext )
 {
    vg_info( "Mounting addons(type:%d) matching skaterift/%s/*/*%s\n", 
                   type, base_folder, content_ext );
@@ -527,7 +537,8 @@ static void addon_mount_content_folder( enum addon_type type,
 /*
  * write the full path of the addon's folder into the vg_str
  */
-static int addon_get_content_folder( addon_reg *reg, vg_str *folder, int async){
+int addon_get_content_folder( addon_reg *reg, vg_str *folder, int async)
+{
    if( reg->alias.workshop_id ){
       struct async_workshop_filepath_info *info = NULL;
       vg_async_item *call = NULL;
@@ -576,7 +587,8 @@ static int addon_get_content_folder( addon_reg *reg, vg_str *folder, int async){
  * Return existing cache id if reg_index points to a registry with its cache
  * already set.
  */
-static u16 addon_cache_fetch( enum addon_type type, u32 reg_index ){
+u16 addon_cache_fetch( enum addon_type type, u32 reg_index )
+{
    addon_reg *reg = NULL;
 
    if( reg_index < addon_count( type, 0 ) ){
@@ -591,7 +603,8 @@ static u16 addon_cache_fetch( enum addon_type type, u32 reg_index ){
 /*
  * Allocate a new cache item from the pool
  */
-static u16 addon_cache_alloc( enum addon_type type, u32 reg_index ){
+u16 addon_cache_alloc( enum addon_type type, u32 reg_index )
+{
    struct addon_cache *cache = &addon_system.cache[ type ];
 
    u16 new_id = vg_pool_lru( &cache->pool );
@@ -621,7 +634,8 @@ static u16 addon_cache_alloc( enum addon_type type, u32 reg_index ){
 /*
  * Get the real item data for cache id 
  */
-static void *addon_cache_item( enum addon_type type, u16 id ){
+void *addon_cache_item( enum addon_type type, u16 id )
+{
    if( !id ) return NULL;
 
    struct addon_cache *cache = &addon_system.cache[type];
@@ -631,7 +645,8 @@ static void *addon_cache_item( enum addon_type type, u16 id ){
 /*
  * Get the real item data for cache id ONLY if the item is completely loaded.
  */
-static void *addon_cache_item_if_loaded( enum addon_type type, u16 id ){
+void *addon_cache_item_if_loaded( enum addon_type type, u16 id )
+{
    if( !id ) return NULL;
 
    struct addon_cache *cache = &addon_system.cache[type];
@@ -645,7 +660,8 @@ static void *addon_cache_item_if_loaded( enum addon_type type, u16 id ){
 /* 
  * Updates the item state from the main thread
  */
-static void async_addon_setstate( void *_entry, u32 _state ){
+void async_addon_setstate( void *_entry, u32 _state )
+{
    addon_cache_entry *entry = _entry;
    SDL_AtomicLock( &addon_system.sl_cache_using_resources );
    entry->state = _state;
@@ -712,7 +728,8 @@ static void addon_cache_free_item( enum addon_type type, u16 id ){
 /*
  * Goes over cache item load requests and calls the above ^
  */
-static void addon_cache_load_loop(void){
+void addon_cache_load_loop(void)
+{
    vg_info( "Running load loop\n" );
    char path_buf[4096];
 
@@ -765,7 +782,8 @@ static void addon_cache_load_loop(void){
  * Perform the cache interactions required to create a viewslot which will
  * eventually be loaded by other parts of the system.
  */
-static u16 addon_cache_create_viewer( enum addon_type type, u16 reg_id ){
+u16 addon_cache_create_viewer( enum addon_type type, u16 reg_id )
+{
    struct addon_cache *cache = &addon_system.cache[type];
    vg_pool *pool = &cache->pool;
 
@@ -792,8 +810,9 @@ static u16 addon_cache_create_viewer( enum addon_type type, u16 reg_id ){
    return cache_id;
 }
 
-static u16 addon_cache_create_viewer_from_uid( enum addon_type type,
-                                               char uid[ADDON_UID_MAX] ){
+u16 addon_cache_create_viewer_from_uid( enum addon_type type,
+                                        char uid[ADDON_UID_MAX] )
+{
    addon_alias q;
    if( !addon_uid_to_alias( uid, &q ) ) return 0;
    if( q.type != type ) return 0;
@@ -809,7 +828,8 @@ static u16 addon_cache_create_viewer_from_uid( enum addon_type type,
    }
 }
 
-static void addon_cache_watch( enum addon_type type, u16 cache_id ){
+void addon_cache_watch( enum addon_type type, u16 cache_id )
+{
    if( !cache_id ) return;
 
    struct addon_cache *cache = &addon_system.cache[type];
@@ -817,12 +837,11 @@ static void addon_cache_watch( enum addon_type type, u16 cache_id ){
    vg_pool_watch( pool, cache_id );
 }
 
-static void addon_cache_unwatch( enum addon_type type, u16 cache_id ){
+void addon_cache_unwatch( enum addon_type type, u16 cache_id )
+{
    if( !cache_id ) return;
 
    struct addon_cache *cache = &addon_system.cache[type];
    vg_pool *pool = &cache->pool;
    vg_pool_unwatch( pool, cache_id );
 }
-
-#endif /* ADDON_C */
diff --git a/addon.h b/addon.h
index bb96f2e5023777cb8a21642745a05891ce427138..bb5747d54178c80dcc0ad65ac1fec40add88cf66 100644 (file)
--- a/addon.h
+++ b/addon.h
@@ -1,19 +1,15 @@
-#ifndef ADDON_H
-#define ADDON_H
-
-#include "skaterift.h"
+#pragma once
 #include "vg/vg_steam_ugc.h"
-#include "addon_types.h"
 #include "vg/vg_mem_pool.h"
-
-#include "world.h"
-#include "player.h"
+#include "vg/vg_string.h"
+#include "addon_types.h"
 
 typedef struct addon_reg addon_reg;
 typedef struct addon_cache_entry addon_cache_entry;
 typedef struct addon_alias addon_alias;
 
-struct addon_alias {
+struct addon_alias 
+{
    enum addon_type type;
    PublishedFileId_t workshop_id;
    char foldername[ ADDON_FOLDERNAME_MAX ];
@@ -24,8 +20,10 @@ struct addon_alias {
 #define ADDON_REG_CITY     0x4
 #define ADDON_REG_PREMIUM  0x8
 
-struct {
-   struct addon_reg{
+struct addon_system
+{
+   struct addon_reg
+   {
       addon_alias alias;
       u32 foldername_hash;
       u8 metadata[512];  /* vg_msg buffer */
@@ -47,8 +45,10 @@ struct {
    /* deffered: updates in main thread */
    u32 registry_type_counts[k_addon_type_max];
 
-   struct addon_cache{
-      struct addon_cache_entry{
+   struct addon_cache
+   {
+      struct addon_cache_entry
+      {
          u32 reg_index;
          addon_reg *reg_ptr;     /* TODO: only use reg_index? */
 
@@ -70,40 +70,38 @@ struct {
    cache[k_addon_type_max];
    SDL_SpinLock sl_cache_using_resources;
 }
-static addon_system;
+extern addon_system;
 
-static void addon_system_init( void );
-static u32 addon_count( enum addon_type type, u32 ignoreflags );
-static addon_reg *get_addon_from_index( enum addon_type type, u32 index, 
-                                        u32 ignoreflags );
-static u32 get_index_from_addon( enum addon_type type, addon_reg *a );
-static int addon_get_content_folder( addon_reg *reg, vg_str *folder, int async);
+void addon_system_init( void );
+u32 addon_count( enum addon_type type, u32 ignoreflags );
+addon_reg *get_addon_from_index( enum addon_type type, u32 index, 
+                                 u32 ignoreflags );
+u32 get_index_from_addon( enum addon_type type, addon_reg *a );
+int addon_get_content_folder( addon_reg *reg, vg_str *folder, int async);
 
 /* scanning routines */
-static u32 addon_match( addon_alias *alias );
-static int addon_alias_eq( addon_alias *a, addon_alias *b );
-static void addon_alias_uid( addon_alias *alias, char buf[ADDON_UID_MAX] );
-static int addon_uid_to_alias( const char *uid, addon_alias *alias );
-static void invalidate_addon_alias( addon_alias *alias );
-static void addon_mount_content_folder( enum addon_type type,
-                                           const char *base_folder, 
-                                           const char *content_ext );
-static void addon_mount_workshop_items(void);
-static void async_addon_reg_update( void *data, u32 size );
-static addon_reg *addon_mount_local_addon( const char *folder,
-                                              enum addon_type type,
-                                              const char *content_ext );
-static u16 addon_cache_fetch( enum addon_type type, u32 reg_index );
-static u16 addon_cache_alloc( enum addon_type type, u32 reg_index );
-static void *addon_cache_item( enum addon_type type, u16 id );
-static void *addon_cache_item_if_loaded( enum addon_type type, u16 id );
-static void async_addon_setstate( void *data, u32 size );
-static void addon_cache_load_loop(void);
-static u16 addon_cache_create_viewer( enum addon_type type, u16 reg_id);
-
-static void addon_cache_watch( enum addon_type type, u16 cache_id );
-static void addon_cache_unwatch( enum addon_type type, u16 cache_id );
-static u16 addon_cache_create_viewer_from_uid( enum addon_type type,
-                                               char uid[ADDON_UID_MAX] );
-
-#endif /* ADDON_H */
+u32 addon_match( addon_alias *alias );
+int addon_alias_eq( addon_alias *a, addon_alias *b );
+void addon_alias_uid( addon_alias *alias, char buf[ADDON_UID_MAX] );
+int addon_uid_to_alias( const char *uid, addon_alias *alias );
+void invalidate_addon_alias( addon_alias *alias );
+void addon_mount_content_folder( enum addon_type type,
+                                    const char *base_folder, 
+                                    const char *content_ext );
+void addon_mount_workshop_items(void);
+void async_addon_reg_update( void *data, u32 size );
+addon_reg *addon_mount_local_addon( const char *folder,
+                                       enum addon_type type,
+                                       const char *content_ext );
+u16 addon_cache_fetch( enum addon_type type, u32 reg_index );
+u16 addon_cache_alloc( enum addon_type type, u32 reg_index );
+void *addon_cache_item( enum addon_type type, u16 id );
+void *addon_cache_item_if_loaded( enum addon_type type, u16 id );
+void async_addon_setstate( void *data, u32 size );
+void addon_cache_load_loop(void);
+u16 addon_cache_create_viewer( enum addon_type type, u16 reg_id);
+
+void addon_cache_watch( enum addon_type type, u16 cache_id );
+void addon_cache_unwatch( enum addon_type type, u16 cache_id );
+u16 addon_cache_create_viewer_from_uid( enum addon_type type,
+                                        char uid[ADDON_UID_MAX] );
diff --git a/addon_types.c b/addon_types.c
new file mode 100644 (file)
index 0000000..b10a23c
--- /dev/null
@@ -0,0 +1,20 @@
+#include "player.h"
+#include "player_render.h"
+#include "player_api.h"
+
+struct addon_type_info addon_type_infos[] = 
+{
+   [k_addon_type_board] = { 
+      .local_content_folder = "boards/",
+      .cache_stride = sizeof(struct player_board),
+      .cache_count  = 20
+   },
+   [k_addon_type_player] = {
+      .local_content_folder = "playermodels/",
+      .cache_stride = sizeof(struct player_model),
+      .cache_count  = 20
+   },
+   [k_addon_type_world] = {
+      .local_content_folder = "maps/"
+   }
+};
index 5c6730fd117af91d63376faa727dfbaa63ed5c1d..a244fc0e7d6c60bc184081b1738231cf5187313c 100644 (file)
@@ -1,5 +1,4 @@
-#ifndef ADDON_TYPES_H
-#define ADDON_TYPES_H
+#pragma once
 
 enum addon_type{
    k_addon_type_none   = 0,
@@ -10,37 +9,16 @@ enum addon_type{
 };
 
 #define ADDON_FOLDERNAME_MAX 64
-
-/* total count that we have knowledge of */
-#define ADDON_MOUNTED_MAX 128
+#define ADDON_MOUNTED_MAX 128 /* total count that we have knowledge of */
 #define ADDON_UID_MAX 76
 
 #ifdef VG_ENGINE
 
-#include "world.h"
-#include "player.h"
-
 struct addon_type_info {
    size_t cache_stride;
    u16 cache_count;
    const char *local_content_folder;
 }
-static addon_type_infos[] = {
-   [k_addon_type_board] = { 
-      .local_content_folder = "boards/",
-      .cache_stride = sizeof(struct player_board),
-      .cache_count  = 20
-   },
-   [k_addon_type_player] = {
-      .local_content_folder = "playermodels/",
-      .cache_stride = sizeof(struct player_model),
-      .cache_count  = 20
-   },
-   [k_addon_type_world] = {
-      .local_content_folder = "maps/"
-   }
-};
+extern addon_type_infos[];
 
 #endif
-
-#endif /* ADDON_TYPES_H */
diff --git a/audio.c b/audio.c
new file mode 100644 (file)
index 0000000..bbbe476
--- /dev/null
+++ b/audio.c
@@ -0,0 +1,264 @@
+#include "world.h"
+#include "audio.h"
+#include "vg/vg_audio_dsp.h"
+
+audio_clip audio_board[] =
+{
+   { .path="sound/skate_hpf.ogg" },
+   { .path="sound/wheel.ogg" },
+   { .path="sound/slide.ogg" },
+   { .path="sound/grind_enter.ogg" },
+   { .path="sound/grind_exit.ogg" },
+   { .path="sound/grind_loop.ogg" },
+   { .path="sound/woodslide.ogg" },
+   { .path="sound/metalscrape.ogg" },
+   { .path="sound/slidetap.ogg" }
+};
+
+audio_clip audio_taps[] =
+{
+   { .path="sound/tap0.ogg" },
+   { .path="sound/tap1.ogg" },
+   { .path="sound/tap2.ogg" },
+   { .path="sound/tap3.ogg" }
+};
+
+audio_clip audio_flips[] =
+{
+   { .path="sound/lf0.ogg" },
+   { .path="sound/lf1.ogg" },
+   { .path="sound/lf2.ogg" },
+   { .path="sound/lf3.ogg" },
+};
+
+audio_clip audio_hits[] =
+{
+   { .path="sound/hit0.ogg" },
+   { .path="sound/hit1.ogg" },
+   { .path="sound/hit2.ogg" },
+   { .path="sound/hit3.ogg" },
+   { .path="sound/hit4.ogg" }
+};
+
+audio_clip audio_splash =
+{ .path = "sound/splash.ogg" };
+
+audio_clip audio_jumps[] = {
+   { .path = "sound/jump0.ogg" },
+   { .path = "sound/jump1.ogg" },
+};
+
+audio_clip audio_footsteps[] = {
+ {.path = "sound/step_concrete0.ogg" },
+ {.path = "sound/step_concrete1.ogg" },
+ {.path = "sound/step_concrete2.ogg" },
+ {.path = "sound/step_concrete3.ogg" }
+};
+
+audio_clip audio_footsteps_grass[] = {
+ {.path = "sound/step_bush0.ogg" },
+ {.path = "sound/step_bush1.ogg" },
+ {.path = "sound/step_bush2.ogg" },
+ {.path = "sound/step_bush3.ogg" },
+ {.path = "sound/step_bush4.ogg" },
+ {.path = "sound/step_bush5.ogg" }
+};
+
+audio_clip audio_footsteps_wood[] = {
+ {.path = "sound/step_wood0.ogg" },
+ {.path = "sound/step_wood1.ogg" },
+ {.path = "sound/step_wood2.ogg" },
+ {.path = "sound/step_wood3.ogg" },
+ {.path = "sound/step_wood4.ogg" },
+ {.path = "sound/step_wood5.ogg" }
+};
+
+audio_clip audio_lands[] = {
+   { .path = "sound/land0.ogg" },
+   { .path = "sound/land1.ogg" },
+   { .path = "sound/land2.ogg" },
+   { .path = "sound/landsk0.ogg" },
+   { .path = "sound/landsk1.ogg" },
+   { .path = "sound/onto.ogg" },
+   { .path = "sound/outo.ogg" },
+};
+
+audio_clip audio_water[] = {
+   { .path = "sound/wave0.ogg" },
+   { .path = "sound/wave1.ogg" },
+   { .path = "sound/wave2.ogg" },
+   { .path = "sound/wave3.ogg" },
+   { .path = "sound/wave4.ogg" },
+   { .path = "sound/wave5.ogg" }
+};
+
+audio_clip audio_grass[] = {
+   { .path = "sound/grass0.ogg" },
+   { .path = "sound/grass1.ogg" },
+   { .path = "sound/grass2.ogg" },
+   { .path = "sound/grass3.ogg" },
+};
+
+audio_clip audio_ambience[] =
+{
+   { .path="sound/town_generic.ogg" }
+};
+
+audio_clip audio_gate_pass = {
+   .path = "sound/gate_pass.ogg"
+};
+
+audio_clip audio_gate_lap = {
+   .path = "sound/gate_lap.ogg"
+};
+
+audio_clip audio_gate_ambient = {
+.path = "sound/gate_ambient.ogg"
+};
+
+audio_clip audio_rewind[] = {
+{ .path = "sound/rewind_start.ogg" },
+{ .path = "sound/rewind_end_1.5.ogg" },
+{ .path = "sound/rewind_end_2.5.ogg" },
+{ .path = "sound/rewind_end_6.5.ogg" },
+{ .path = "sound/rewind_clack.ogg" },
+};
+
+audio_clip audio_ui[] = {
+   { .path = "sound/ui_click.ogg" },
+   { .path = "sound/ui_ding.ogg" },
+   { .path = "sound/teleport.ogg" }
+};
+
+audio_clip audio_challenge[] = {
+   { .path = "sound/objective0.ogg" },
+   { .path = "sound/objective1.ogg" },
+   { .path = "sound/objective_win.ogg" },
+   { .path = "sound/ui_good.ogg" },
+   { .path = "sound/ui_inf.ogg" },
+   { .path = "sound/ui_ok.ogg" },
+   { .path = "sound/objective_fail.ogg" }
+};
+
+struct air_synth_data air_audio_data;
+
+static void audio_air_synth_get_samples( void *_data, f32 *buf, u32 count ){
+   struct air_synth_data *data = _data;
+
+   SDL_AtomicLock( &data->sl );
+   f32 spd = data->speed;
+   SDL_AtomicUnlock( &data->sl );
+
+   f32 s0  = sinf(data->t*2.0f),
+       s1  = sinf(data->t*0.43f),
+       s2  = sinf(data->t*1.333f),
+       sm  = vg_clampf( data->speed / 45.0f, 0, 1 ),
+       ft  = (s0*s1*s2)*0.5f+0.5f,
+       f   = vg_lerpf( 200.0f, 1200.0f, sm*0.7f + ft*0.3f ),
+       vol = 0.25f * sm;
+
+   dsp_init_biquad_butterworth_lpf( &data->lpf, f );
+
+   for( u32 i=0; i<count; i ++ ){
+      f32 v = (vg_randf64(&vg_dsp.rand) * 2.0f - 1.0f) * vol;
+      v = dsp_biquad_process( &data->lpf, v );
+
+      buf[i*2+0] = v;
+      buf[i*2+1] = v;
+   }
+
+   data->t += (f32)(count)/44100.0f;
+};
+
+static audio_clip air_synth = {
+   .flags = k_audio_format_gen,
+   .size = 0,
+   .func = audio_air_synth_get_samples,
+   .data = &air_audio_data
+};
+
+void audio_init(void)
+{
+   audio_clip_loadn( audio_board, vg_list_size(audio_board), NULL );
+   audio_clip_loadn( audio_taps, vg_list_size(audio_taps), NULL );
+   audio_clip_loadn( audio_flips, vg_list_size(audio_flips), NULL );
+   audio_clip_loadn( audio_hits, vg_list_size(audio_hits), NULL );
+   audio_clip_loadn( audio_ambience, vg_list_size(audio_ambience), NULL );
+   audio_clip_loadn( &audio_splash, 1, NULL );
+   audio_clip_loadn( &audio_gate_pass, 1, NULL );
+   audio_clip_loadn( &audio_gate_lap, 1, NULL );
+   audio_clip_loadn( &audio_gate_ambient, 1, NULL );
+
+   audio_clip_loadn( audio_jumps, vg_list_size(audio_jumps), NULL );
+   audio_clip_loadn( audio_lands, vg_list_size(audio_lands), NULL );
+   audio_clip_loadn( audio_water, vg_list_size(audio_water), NULL );
+   audio_clip_loadn( audio_grass, vg_list_size(audio_grass), NULL );
+   audio_clip_loadn( audio_footsteps, vg_list_size(audio_footsteps), NULL );
+   audio_clip_loadn( audio_footsteps_grass, 
+                     vg_list_size(audio_footsteps_grass), NULL );
+   audio_clip_loadn( audio_footsteps_wood, 
+                     vg_list_size(audio_footsteps_wood), NULL );
+   audio_clip_loadn( audio_rewind, vg_list_size(audio_rewind), NULL );
+   audio_clip_loadn( audio_ui, vg_list_size(audio_ui), NULL );
+   audio_clip_loadn( audio_challenge, vg_list_size(audio_challenge), NULL );
+
+   audio_lock();
+   audio_set_lfo_wave( 0, k_lfo_polynomial_bipolar, 80.0f );
+   audio_set_lfo_frequency( 0, 20.0f );
+
+   air_audio_data.channel = audio_get_first_idle_channel();
+   if( air_audio_data.channel )
+      audio_channel_init( air_audio_data.channel, &air_synth, 0 );
+
+   audio_unlock();
+}
+
+void audio_free(void)
+{
+   /* TODO! */
+   vg_warn( "UNIMPLEMENTED: audio_free()\n" );
+}
+
+void audio_ambient_sprite_play( v3f co, audio_clip *clip )
+{
+   audio_lock();
+   u16 group_id = 0xfff0;
+   audio_channel *ch = audio_get_group_idle_channel( group_id, 4 );
+
+   if( ch ){
+      audio_channel_init( ch, clip, AUDIO_FLAG_SPACIAL_3D );
+      audio_channel_group( ch, group_id );
+      audio_channel_set_spacial( ch, co, 80.0f );
+      audio_channel_edit_volume( ch, 1.0f, 1 );
+      ch = audio_relinquish_channel( ch );
+   }
+   audio_unlock();
+}
+
+enum audio_sprite_type world_audio_sample_sprite_random(v3f origin, v3f output);
+void audio_ambient_sprites_update( world_instance *world, v3f co )
+{
+   static float accum = 0.0f;
+   accum += vg.time_delta;
+
+   if( accum > 0.1f )
+      accum -= 0.1f;
+   else return;
+
+   v3f sprite_pos;
+   enum audio_sprite_type sprite_type = 
+      world_audio_sample_sprite_random( co, sprite_pos );
+   
+   if( sprite_type != k_audio_sprite_type_none ){
+      if( sprite_type == k_audio_sprite_type_grass ){
+         audio_ambient_sprite_play( sprite_pos, 
+                                    &audio_grass[vg_randu32(&vg.rand)%4] );
+      }
+      else if( sprite_type == k_audio_sprite_type_water ){
+         if( world->water.enabled ){
+            audio_ambient_sprite_play( sprite_pos, 
+                                       &audio_water[vg_randu32(&vg.rand)%6] );
+         }
+      }
+   }
+}
diff --git a/audio.h b/audio.h
index 984303aa92bd81787349587ba119feac5b14d1a2..4b57a7998a13d4705284bc961c2dcf858f12b571 100644 (file)
--- a/audio.h
+++ b/audio.h
  * Copyright (C) 2021-2022 Mt.ZERO Software, Harry Godden - All Rights Reserved
  */
 
-#include "common.h"
+#pragma once
 
-#ifndef AUDIO_H
-#define AUDIO_H
-
-#include "world.h"
+#include "vg/vg_engine.h"
+#include "vg/vg_audio.h"
 #include "vg/vg_audio_dsp.h"
-
-audio_clip audio_board[] =
-{
-   { .path="sound/skate_hpf.ogg" },
-   { .path="sound/wheel.ogg" },
-   { .path="sound/slide.ogg" },
-   { .path="sound/grind_enter.ogg" },
-   { .path="sound/grind_exit.ogg" },
-   { .path="sound/grind_loop.ogg" },
-   { .path="sound/woodslide.ogg" },
-   { .path="sound/metalscrape.ogg" },
-   { .path="sound/slidetap.ogg" }
-};
-
-audio_clip audio_taps[] =
-{
-   { .path="sound/tap0.ogg" },
-   { .path="sound/tap1.ogg" },
-   { .path="sound/tap2.ogg" },
-   { .path="sound/tap3.ogg" }
-};
-
-audio_clip audio_flips[] =
-{
-   { .path="sound/lf0.ogg" },
-   { .path="sound/lf1.ogg" },
-   { .path="sound/lf2.ogg" },
-   { .path="sound/lf3.ogg" },
-};
-
-audio_clip audio_hits[] =
-{
-   { .path="sound/hit0.ogg" },
-   { .path="sound/hit1.ogg" },
-   { .path="sound/hit2.ogg" },
-   { .path="sound/hit3.ogg" },
-   { .path="sound/hit4.ogg" }
-};
-
-audio_clip audio_splash =
-{ .path = "sound/splash.ogg" };
-
-audio_clip audio_jumps[] = {
-   { .path = "sound/jump0.ogg" },
-   { .path = "sound/jump1.ogg" },
-};
-
-audio_clip audio_footsteps[] = {
- {.path = "sound/step_concrete0.ogg" },
- {.path = "sound/step_concrete1.ogg" },
- {.path = "sound/step_concrete2.ogg" },
- {.path = "sound/step_concrete3.ogg" }
-};
-
-audio_clip audio_footsteps_grass[] = {
- {.path = "sound/step_bush0.ogg" },
- {.path = "sound/step_bush1.ogg" },
- {.path = "sound/step_bush2.ogg" },
- {.path = "sound/step_bush3.ogg" },
- {.path = "sound/step_bush4.ogg" },
- {.path = "sound/step_bush5.ogg" }
-};
-
-audio_clip audio_footsteps_wood[] = {
- {.path = "sound/step_wood0.ogg" },
- {.path = "sound/step_wood1.ogg" },
- {.path = "sound/step_wood2.ogg" },
- {.path = "sound/step_wood3.ogg" },
- {.path = "sound/step_wood4.ogg" },
- {.path = "sound/step_wood5.ogg" }
-};
-
-audio_clip audio_lands[] = {
-   { .path = "sound/land0.ogg" },
-   { .path = "sound/land1.ogg" },
-   { .path = "sound/land2.ogg" },
-   { .path = "sound/landsk0.ogg" },
-   { .path = "sound/landsk1.ogg" },
-   { .path = "sound/onto.ogg" },
-   { .path = "sound/outo.ogg" },
-};
-
-audio_clip audio_water[] = {
-   { .path = "sound/wave0.ogg" },
-   { .path = "sound/wave1.ogg" },
-   { .path = "sound/wave2.ogg" },
-   { .path = "sound/wave3.ogg" },
-   { .path = "sound/wave4.ogg" },
-   { .path = "sound/wave5.ogg" }
-};
-
-audio_clip audio_grass[] = {
-   { .path = "sound/grass0.ogg" },
-   { .path = "sound/grass1.ogg" },
-   { .path = "sound/grass2.ogg" },
-   { .path = "sound/grass3.ogg" },
-};
-
-audio_clip audio_ambience[] =
-{
-   { .path="sound/town_generic.ogg" }
-};
-
-audio_clip audio_gate_pass = {
-   .path = "sound/gate_pass.ogg"
-};
-
-audio_clip audio_gate_lap = {
-   .path = "sound/gate_lap.ogg"
-};
-
-audio_clip audio_gate_ambient = {
-.path = "sound/gate_ambient.ogg"
-};
-
-audio_clip audio_rewind[] = {
-{ .path = "sound/rewind_start.ogg" },
-{ .path = "sound/rewind_end_1.5.ogg" },
-{ .path = "sound/rewind_end_2.5.ogg" },
-{ .path = "sound/rewind_end_6.5.ogg" },
-{ .path = "sound/rewind_clack.ogg" },
-};
-
-audio_clip audio_ui[] = {
-   { .path = "sound/ui_click.ogg" },
-   { .path = "sound/ui_ding.ogg" },
-   { .path = "sound/teleport.ogg" }
-};
-
-audio_clip audio_challenge[] = {
-   { .path = "sound/objective0.ogg" },
-   { .path = "sound/objective1.ogg" },
-   { .path = "sound/objective_win.ogg" },
-   { .path = "sound/ui_good.ogg" },
-   { .path = "sound/ui_inf.ogg" },
-   { .path = "sound/ui_ok.ogg" },
-   { .path = "sound/objective_fail.ogg" }
-};
+#include "world.h"
 
 struct air_synth_data {
    f32 speed;
@@ -155,85 +16,39 @@ struct air_synth_data {
    f32 t;
    struct dsp_biquad lpf;
    SDL_SpinLock sl;
-}
-static air_data;
-
-static void audio_air_synth_get_samples( void *_data, f32 *buf, u32 count ){
-   struct air_synth_data *data = _data;
-
-   SDL_AtomicLock( &data->sl );
-   f32 spd = data->speed;
-   SDL_AtomicUnlock( &data->sl );
 
-   f32 s0  = sinf(data->t*2.0f),
-       s1  = sinf(data->t*0.43f),
-       s2  = sinf(data->t*1.333f),
-       sm  = vg_clampf( data->speed / 45.0f, 0, 1 ),
-       ft  = (s0*s1*s2)*0.5f+0.5f,
-       f   = vg_lerpf( 200.0f, 1200.0f, sm*0.7f + ft*0.3f ),
-       vol = 0.25f * sm;
-
-   dsp_init_biquad_butterworth_lpf( &data->lpf, f );
-
-   for( u32 i=0; i<count; i ++ ){
-      f32 v = (vg_randf64(&vg_dsp.rand) * 2.0f - 1.0f) * vol;
-      v = dsp_biquad_process( &data->lpf, v );
-
-      buf[i*2+0] = v;
-      buf[i*2+1] = v;
-   }
-
-   data->t += (f32)(count)/44100.0f;
-};
-
-static audio_clip air_synth = {
-   .flags = k_audio_format_gen,
-   .size = 0,
-   .func = audio_air_synth_get_samples,
-   .data = &air_data
-};
-
-static void audio_init(void)
-{
-   audio_clip_loadn( audio_board, vg_list_size(audio_board), NULL );
-   audio_clip_loadn( audio_taps, vg_list_size(audio_taps), NULL );
-   audio_clip_loadn( audio_flips, vg_list_size(audio_flips), NULL );
-   audio_clip_loadn( audio_hits, vg_list_size(audio_hits), NULL );
-   audio_clip_loadn( audio_ambience, vg_list_size(audio_ambience), NULL );
-   audio_clip_loadn( &audio_splash, 1, NULL );
-   audio_clip_loadn( &audio_gate_pass, 1, NULL );
-   audio_clip_loadn( &audio_gate_lap, 1, NULL );
-   audio_clip_loadn( &audio_gate_ambient, 1, NULL );
-
-   audio_clip_loadn( audio_jumps, vg_list_size(audio_jumps), NULL );
-   audio_clip_loadn( audio_lands, vg_list_size(audio_lands), NULL );
-   audio_clip_loadn( audio_water, vg_list_size(audio_water), NULL );
-   audio_clip_loadn( audio_grass, vg_list_size(audio_grass), NULL );
-   audio_clip_loadn( audio_footsteps, vg_list_size(audio_footsteps), NULL );
-   audio_clip_loadn( audio_footsteps_grass, 
-                     vg_list_size(audio_footsteps_grass), NULL );
-   audio_clip_loadn( audio_footsteps_wood, 
-                     vg_list_size(audio_footsteps_wood), NULL );
-   audio_clip_loadn( audio_rewind, vg_list_size(audio_rewind), NULL );
-   audio_clip_loadn( audio_ui, vg_list_size(audio_ui), NULL );
-   audio_clip_loadn( audio_challenge, vg_list_size(audio_challenge), NULL );
-
-   audio_lock();
-   audio_set_lfo_wave( 0, k_lfo_polynomial_bipolar, 80.0f );
-   audio_set_lfo_frequency( 0, 20.0f );
-
-   skaterift.aud_air = audio_get_first_idle_channel();
-   if( skaterift.aud_air ) 
-      audio_channel_init( skaterift.aud_air, &air_synth, 0 );
-
-   audio_unlock();
+   /* not used in locking */
+   audio_channel *channel;
 }
+extern air_audio_data;
 
-static void audio_free(void)
-{
-   /* TODO! */
-   vg_warn( "UNIMPLEMENTED: audio_free()\n" );
-}
+void audio_init(void);
+void audio_free(void);
+void audio_ambient_sprite_play( v3f co, audio_clip *clip );
+void audio_ambient_sprites_update( world_instance *world, v3f co );
+
+/* TODO(ASSETS): 
+ * Have these as asignable ID's and not a bunch of different arrays. 
+ */
+extern audio_clip audio_board[];
+extern audio_clip audio_taps[];
+extern audio_clip audio_flips[];
+extern audio_clip audio_hits[];
+extern audio_clip audio_splash;
+extern audio_clip audio_jumps[];
+extern audio_clip audio_footsteps[];
+extern audio_clip audio_footsteps_grass[];
+extern audio_clip audio_footsteps_wood[];
+extern audio_clip audio_lands[];
+extern audio_clip audio_water[];
+extern audio_clip audio_grass[];
+extern audio_clip audio_ambience[];
+extern audio_clip audio_gate_pass;
+extern audio_clip audio_gate_lap;
+extern audio_clip audio_gate_ambient;
+extern audio_clip audio_rewind[];
+extern audio_clip audio_ui[];
+extern audio_clip audio_challenge[];
 
 enum audio_sprite_type 
 {
@@ -241,50 +56,3 @@ enum audio_sprite_type
    k_audio_sprite_type_grass,
    k_audio_sprite_type_water
 };
-
-static void audio_ambient_sprite_play( v3f co, audio_clip *clip )
-{
-   audio_lock();
-   u16 group_id = 0xfff0;
-   audio_channel *ch = audio_get_group_idle_channel( group_id, 4 );
-
-   if( ch ){
-      audio_channel_init( ch, clip, AUDIO_FLAG_SPACIAL_3D );
-      audio_channel_group( ch, group_id );
-      audio_channel_set_spacial( ch, co, 80.0f );
-      audio_channel_edit_volume( ch, 1.0f, 1 );
-      ch = audio_relinquish_channel( ch );
-   }
-   audio_unlock();
-}
-
-static
-enum audio_sprite_type world_audio_sample_sprite_random(v3f origin, v3f output);
-static void audio_ambient_sprites_update( world_instance *world, v3f co )
-{
-   static float accum = 0.0f;
-   accum += vg.time_delta;
-
-   if( accum > 0.1f )
-      accum -= 0.1f;
-   else return;
-
-   v3f sprite_pos;
-   enum audio_sprite_type sprite_type = 
-      world_audio_sample_sprite_random( co, sprite_pos );
-   
-   if( sprite_type != k_audio_sprite_type_none ){
-      if( sprite_type == k_audio_sprite_type_grass ){
-         audio_ambient_sprite_play( sprite_pos, 
-                                    &audio_grass[vg_randu32(&vg.rand)%4] );
-      }
-      else if( sprite_type == k_audio_sprite_type_water ){
-         if( world->water.enabled ){
-            audio_ambient_sprite_play( sprite_pos, 
-                                       &audio_water[vg_randu32(&vg.rand)%6] );
-         }
-      }
-   }
-}
-
-#endif /* AUDIO_H */
diff --git a/build.c b/build.c
index 9367e81b64929c187d69d6ce5d32e2c337143100..3190da1da6698b4007036b5fa049e3f3fbe01029 100644 (file)
--- a/build.c
+++ b/build.c
@@ -127,6 +127,8 @@ void build_shaders(void){
    _S( "blitcolour","blit.vs",      "colour.fs" );
    _S( "blit_transition", "blit.vs", "blit_transition.fs" );
    _S( "routeui",   "routeui.vs",   "routeui.fs" );
+
+   vg_build_shader_impl( "shaders/impl.c" );
 }
 
 void build_game_content( struct vg_project *proj )
@@ -163,7 +165,8 @@ void build_game_bin( struct vg_project *proj )
             .log_source_info = 1,
             .steam_api = 1,
             .use_3d = 1,
-            .custom_game_settings = 0
+            .custom_game_settings = 0,
+            .custom_shaders = 1
          });
 
    vg_add_source( proj, "skaterift.c " );
diff --git a/bvh.h b/bvh.h
deleted file mode 100644 (file)
index ced346e..0000000
--- a/bvh.h
+++ /dev/null
@@ -1,416 +0,0 @@
-/*
- * Copyright (C) 2021-2022 Mt.ZERO Software, Harry Godden - All Rights Reserved
- */
-
-#ifndef BVH_H
-#define BVH_H
-
-#include "vg/vg_mem.h"
-#include "vg/vg_m.h"
-#include "vg/vg_lines.h"
-
-/*
- * Usage:
- *
- * create a bh_system with functions filled out for expand, centroid, and swap.
- * optionally include item_debug and cast_ray functions if needed, otherwise,
- *   set them to null
- *
- * create a bh_tree struct with:
- *   user: a pointer back the base of the data you are ordering
- *   system: the system we created above which will deal with the data
- *
- * call bh_create( bh_tree *bh, u32 item_count )
- * static int bh_ray( bh_tree *bh, u32 inode, v3f co, v3f dir, ray_hit *hit )
- * static int bh_select( bh_tree *bh, boxf box, u32 *buffer, int len )
- */
-
-typedef struct bh_node bh_node;
-typedef struct bh_tree bh_tree;
-typedef struct bh_system bh_system;
-
-typedef struct ray_hit ray_hit;
-struct ray_hit{
-   float dist;
-   u32 *tri;
-   v3f pos, normal;
-};
-
-struct bh_tree{
-   u32 node_count;
-
-   bh_system *system;
-   void *user;
-   u32 max_per_leaf;
-
-   struct bh_node
-   {
-      boxf bbx;
-
-      /* if il is 0, this is a leaf */
-      int il, count;
-      union{ int ir, start; };
-   } 
-   nodes[];
-};
-
-struct bh_system{
-   u32 system_type;
-   void  (*expand_bound)( void *user, boxf bound, u32 item_index );
-   float (*item_centroid)( void *user, u32 item_index, int axis );
-   void  (*item_closest)( void *user, u32 item_index, v3f point, v3f closest );
-   void  (*item_swap)( void *user, u32 ia, u32 ib );
-
-   /*
-    * Optional:
-    *   item_debug   - draw this item quickly usually with lines
-    *   cast_ray     - shoot a ray against the object, if this is not set,
-    *                  raycasts will simply return the hit on the bvh node
-    */
-
-   void  (*item_debug)( void *user, u32 item_index );
-   int   (*cast_ray)( void *user, u32 index, v3f co, v3f dir, ray_hit *hit );
-};
-
-static float scene_bh_centroid( void *user, u32 item_index, int axis );
-static void scene_bh_swap( void *user, u32 ia, u32 ib );
-static void scene_bh_expand_bound( void *user, boxf bound, u32 item_index );
-
-static void bh_update_bounds( bh_tree *bh, u32 inode ){
-   bh_node *node = &bh->nodes[ inode ];
-
-   box_init_inf( node->bbx );
-   for( u32 i=0; i<node->count; i++ ){
-      u32 idx = node->start+i;
-      if( bh->system->system_type == 0x1 )
-         scene_bh_expand_bound( bh->user, node->bbx, idx );
-      else
-         bh->system->expand_bound( bh->user, node->bbx, idx );
-   }
-}
-
-static void bh_subdivide( bh_tree *bh, u32 inode ){
-   bh_node *node = &bh->nodes[ inode ];
-
-   if( node->count <= bh->max_per_leaf )
-      return;
-
-   v3f extent;
-   v3_sub( node->bbx[1], node->bbx[0], extent );
-
-   int axis = 0;
-   if( extent[1] > extent[0] ) axis = 1;
-   if( extent[2] > extent[axis] ) axis = 2;
-
-   float split = node->bbx[0][axis] + extent[axis]*0.5f;
-   float avg = 0.0;
-   for( u32 t=0; t<node->count; t++ ){
-      u32 idx = node->start+t;
-
-      if( bh->system->system_type == 0x1 )
-         avg += scene_bh_centroid( bh->user, idx, axis );
-      else 
-         avg += bh->system->item_centroid( bh->user, idx, axis );
-   }
-   avg /= (float)node->count;
-   split = avg;
-
-
-   i32 i = node->start,
-       j = i + node->count-1;
-   
-   while( i <= j ){
-      f32 centroid;
-      
-      if( bh->system->system_type == 0x1 )
-         centroid = scene_bh_centroid( bh->user, i, axis );
-      else
-         centroid = bh->system->item_centroid( bh->user, i, axis );
-
-      if( centroid < split )
-         i ++;
-      else{
-         if( bh->system->system_type == 0x1 )
-            scene_bh_swap( bh->user, i, j );
-         else
-            bh->system->item_swap( bh->user, i, j );
-         j --;
-      }
-   }
-
-   u32 left_count = i - node->start;
-   if( left_count == 0 || left_count == node->count ) return;
-
-   u32 il = bh->node_count ++,
-       ir = bh->node_count ++;
-
-   bh_node *lnode = &bh->nodes[il],
-           *rnode = &bh->nodes[ir];
-
-   lnode->start = node->start;
-   lnode->count = left_count;
-   rnode->start = i;
-   rnode->count = node->count - left_count;
-
-   node->il = il;
-   node->ir = ir;
-   node->count = 0;
-
-   bh_update_bounds( bh, il );
-   bh_update_bounds( bh, ir );
-   bh_subdivide( bh, il );
-   bh_subdivide( bh, ir );
-}
-
-static bh_tree *bh_create( void *lin_alloc, bh_system *system, 
-                              void *user, u32 item_count, u32 max_per_leaf ){
-   if( max_per_leaf == 0 )
-      vg_fatal_error( "Minimum of 1 per leaf\n" );
-
-   u32 alloc_count = VG_MAX( 1, item_count );
-
-   u32 totsize = sizeof(bh_tree) + sizeof(bh_node)*(alloc_count*2-1);
-   bh_tree *bh = vg_linear_alloc( lin_alloc, vg_align8(totsize) );
-   bh->system = system;
-   bh->user = user;
-   bh->max_per_leaf = max_per_leaf;
-
-   bh_node *root = &bh->nodes[0];
-   bh->node_count = 1;
-   
-   root->il = 0;
-   root->ir = 0;
-   root->count = item_count;
-   root->start = 0;
-
-   bh_update_bounds( bh, 0 );
-
-   if( item_count > 2 )
-      bh_subdivide( bh, 0 );
-
-   totsize = vg_align8(sizeof(bh_tree) + sizeof(bh_node) * bh->node_count);
-   bh = vg_linear_resize( lin_alloc, bh, totsize );
-
-   vg_success( "BVH done, size: %u/%u\n", bh->node_count, (alloc_count*2-1) );
-   return bh;
-}
-
-/*
- * Draw items in this leaf node.
- * *item_debug() must be set!
- */
-static void bh_debug_leaf( bh_tree *bh, bh_node *node ){
-   vg_line_boxf( node->bbx, 0xff00ff00 );
-
-   if( bh->system->item_debug ){
-      for( u32 i=0; i<node->count; i++ ){
-         u32 idx = node->start+i;
-         bh->system->item_debug( bh->user, idx );
-      }
-   }
-}
-
-/*
- * Trace the bh tree all the way down to the leaf nodes where pos is inside
- */
-static void bh_debug_trace( bh_tree *bh, u32 inode, v3f pos, u32 colour ){
-   bh_node *node = &bh->nodes[ inode ];
-
-   if( (pos[0] >= node->bbx[0][0] && pos[0] <= node->bbx[1][0]) &&
-       (pos[2] >= node->bbx[0][2] && pos[2] <= node->bbx[1][2]) )
-   {
-      if( !node->count ){
-         vg_line_boxf( node->bbx, colour );
-
-         bh_debug_trace( bh, node->il, pos, colour );
-         bh_debug_trace( bh, node->ir, pos, colour );
-      }
-      else{
-         if( bh->system->item_debug )
-            bh_debug_leaf( bh, node );
-      }
-   }
-}
-
-typedef struct bh_iter bh_iter;
-struct bh_iter{
-   struct {
-      i32 id, depth;
-   }
-   stack[64];
-
-   enum bh_query_type{
-      k_bh_query_box,
-      k_bh_query_ray,
-      k_bh_query_range
-   }
-   query;
-
-   union{
-      struct{
-         boxf box;
-      }
-      box;
-
-      struct{
-         v3f co, inv_dir;
-         f32 max_dist;
-      }
-      ray;
-
-      struct {
-         v3f co;
-         f32 dist_sqr;
-      }
-      range;
-   };
-
-   i32 depth, i;
-};
-
-static void bh_iter_init_generic( i32 root, bh_iter *it ){
-   it->stack[0].id = root;
-   it->stack[0].depth = 0;
-   it->depth = 0;
-   it->i = 0;
-}
-
-static void bh_iter_init_box( i32 root, bh_iter *it, boxf box ){
-   bh_iter_init_generic( root, it );
-   it->query = k_bh_query_box;
-
-   box_copy( box, it->box.box );
-}
-
-static void bh_iter_init_ray( i32 root, bh_iter *it, v3f co, 
-                                 v3f dir, f32 max_dist ){
-   bh_iter_init_generic( root, it );
-   it->query = k_bh_query_ray;
-   
-   v3_div( (v3f){1.0f,1.0f,1.0f}, dir, it->ray.inv_dir );
-   v3_copy( co, it->ray.co );
-   it->ray.max_dist = max_dist;
-}
-
-static void bh_iter_init_range( i32 root, bh_iter *it, v3f co, f32 range ){
-   bh_iter_init_generic( root, it );
-   it->query = k_bh_query_range;
-
-   v3_copy( co, it->range.co );
-   it->range.dist_sqr = range*range;
-}
-
-/* NOTE: does not compute anything beyond the leaf level. element level tests
- *       should be implemented by the users code.
- *
- *       this is like a 'broad phase only' deal.
- */
-static i32 bh_next( bh_tree *bh, bh_iter *it, i32 *em ){
-   while( it->depth >= 0 ){
-      bh_node *inode = &bh->nodes[ it->stack[it->depth].id ];
-      
-      /* Only process overlapping nodes */
-      i32 q = 0;
-
-      if( it->i ) /* already checked */
-         q = 1;
-      else{
-         if( it->query == k_bh_query_box )
-            q = box_overlap( inode->bbx, it->box.box );
-         else if( it->query == k_bh_query_ray )
-            q = ray_aabb1( inode->bbx, it->ray.co, 
-                           it->ray.inv_dir, it->ray.max_dist );
-         else {
-            v3f nearest;
-            closest_point_aabb( it->range.co, inode->bbx, nearest );
-
-            if( v3_dist2( nearest, it->range.co ) <= it->range.dist_sqr )
-               q = 1;
-         }
-      }
-
-      if( !q ){
-         it->depth --;
-         continue;
-      }
-
-      if( inode->count ){
-         if( it->i < inode->count ){
-            *em = inode->start+it->i;
-            it->i ++;
-            return 1;
-         }
-         else{
-            it->depth --;
-            it->i = 0;
-         }
-      }
-      else{
-         if( it->depth+1 >= vg_list_size(it->stack) ){
-            vg_error( "Maximum stack reached!\n" );
-            return 0;
-         }
-
-         it->stack[it->depth  ].id = inode->il;
-         it->stack[it->depth+1].id = inode->ir;
-         it->depth ++;
-         it->i = 0;
-      }
-   }
-
-   return 0;
-}
-
-static int bh_closest_point( bh_tree *bh, v3f pos, 
-                                v3f closest, float max_dist )
-{
-   if( bh->node_count < 2 )
-      return -1;
-
-   max_dist = max_dist*max_dist;
-
-   int queue[ 128 ],
-       depth = 0,
-       best_item = -1;
-
-   queue[0] = 0;
-
-   while( depth >= 0 ){
-      bh_node *inode = &bh->nodes[ queue[depth] ];
-
-      v3f p1;
-      closest_point_aabb( pos, inode->bbx, p1 );
-
-      /* branch into node if its closer than current best */
-      float node_dist = v3_dist2( pos, p1 );
-      if( node_dist < max_dist ){
-         if( inode->count ){
-            for( int i=0; i<inode->count; i++ ){
-               v3f p2;
-               bh->system->item_closest( bh->user, inode->start+i, pos, p2 );
-
-               float item_dist = v3_dist2( pos, p2 );
-               if( item_dist < max_dist ){
-                  max_dist = item_dist;
-                  v3_copy( p2, closest );
-                  best_item = inode->start+i;
-               }
-            }
-
-            depth --;
-         }
-         else{
-            queue[depth] = inode->il;
-            queue[depth+1] = inode->ir;
-
-            depth ++;
-         }
-      }
-      else
-         depth --;
-   }
-
-   return best_item;
-}
-
-#endif /* BVH_H */
index fdbc00c44fafbc4d75697970dc1bb4f8ba124bfe..7aa1b14a92eb6b29f03338765587b3afe07dd949 100644 (file)
--- a/camera.h
+++ b/camera.h
@@ -1,7 +1,5 @@
-#ifndef CAMERA_H
-#define CAMERA_H
-
-#include "skaterift.h"
+#pragma once
+#if 0
 
 typedef struct camera camera;
 struct camera{
@@ -95,5 +93,4 @@ static void camera_finalize( camera *cam )
    m4x4_copy( cam->mtx.pv, cam->mtx_prev.pv );
    m4x4_mul( cam->mtx.p, cam->mtx.v, cam->mtx.pv );
 }
-
-#endif /* CAMERA_H */
+#endif
index 8b64586bdd5e3d5efe931fd9cd22501daf9fcc8a..592381bd3ad29c7f7c189487571f56f90744ea8f 100644 (file)
@@ -1,14 +1,14 @@
-#ifndef DEPTH_COMPARE_H
-#define DEPTH_COMPARE_H
-
+#pragma once
 #include "vg/vg_m.h"
+#include "skaterift.h"
 #include "render.h"
 
-static void depth_compare_bind( 
+static inline void depth_compare_bind( 
       void (*uTexSceneDepth)(int),
       void (*uInverseRatioDepth)(v3f),
       void (*uInverseRatioMain)(v3f),
-      camera *cam ){
+      vg_camera *cam )
+{
    uTexSceneDepth( 5 );
    render_fb_bind_texture( gpipeline.fb_main, 2, 5 );
    v3f inverse;
@@ -20,5 +20,3 @@ static void depth_compare_bind(
    inverse[2] = cam->farz-cam->nearz;
    uInverseRatioMain( inverse );
 }
-
-#endif /* DEPTH_COMPARE_H */
index 72149b1a4d4dd72327c01b71ad6207cb8a8b2fbe..ce87366421522049a14c304c74331c2dee5766fc 100644 (file)
@@ -1,12 +1,10 @@
-#ifndef ENT_CHALLENGE_C
-#define ENT_CHALLENGE_C
-
 #include "entity.h"
 #include "input.h"
 #include "gui.h"
 #include "audio.h"
 
-static void ent_challenge_call( world_instance *world, ent_call *call ){
+void ent_challenge_call( world_instance *world, ent_call *call )
+{
    u32 index = mdl_entity_id_id( call->id );
    ent_challenge *challenge = mdl_arritm( &world->ent_challenge, index );
 
@@ -42,7 +40,8 @@ static void ent_challenge_call( world_instance *world, ent_call *call ){
    }
 }
 
-static void ent_challenge_preupdate( ent_challenge *challenge, int active ){
+void ent_challenge_preupdate( ent_challenge *challenge, int active )
+{
    world_instance *world = world_current_instance();
 
    /* maximum distance from active challenge */
@@ -115,5 +114,3 @@ static void ent_challenge_preupdate( ent_challenge *challenge, int active ){
 static void ent_challenge_render( ent_challenge *challenge ){
    
 }
-
-#endif /* ENT_CHALLENGE_C */
index a3cd92adf9e893889b3a7d7210e32a71c8336941..9b9ea10fad61accb3ab25b7f74353561ff550543 100644 (file)
@@ -1,9 +1,5 @@
-#ifndef ENT_CHALLENGE_H
-#define ENT_CHALLENGE_H
-
+#pragma once
 #include "entity.h"
 
-static void ent_challenge_preupdate( ent_challenge *challenge, int active );
-static void ent_challenge_call( world_instance *world, ent_call *call );
-
-#endif /* ENT_CHALLENGE_H */
+void ent_challenge_preupdate( ent_challenge *challenge, int active );
+void ent_challenge_call( world_instance *world, ent_call *call );
index 46def88bf700f90eeacef359585da43d8762997d..4f22df8d7bc30065c79874c5657ad6de213ca626 100644 (file)
@@ -5,7 +5,10 @@
 #include "gui.h"
 #include "menu.h"
 
-static void ent_miniworld_call( world_instance *world, ent_call *call ){
+struct global_miniworld global_miniworld;
+
+void ent_miniworld_call( world_instance *world, ent_call *call )
+{
    ent_miniworld *miniworld = mdl_arritm( &world->ent_miniworld, 
                                           mdl_entity_id_id(call->id) );
 
@@ -36,7 +39,9 @@ static void ent_miniworld_call( world_instance *world, ent_call *call ){
    }
 }
 
-static void miniworld_icon( camera *cam, enum gui_icon icon, v3f pos, f32 size){
+static void miniworld_icon( vg_camera *cam, enum gui_icon icon, 
+                            v3f pos, f32 size)
+{
    m4x3f mmdl;
    v3_copy( cam->transform[2], mmdl[2] );
    mmdl[2][1] = 0.0f;
@@ -58,7 +63,8 @@ static void miniworld_icon( camera *cam, enum gui_icon icon, v3f pos, f32 size){
       mdl_draw_submesh( sm );
 }
 
-static void ent_miniworld_render( world_instance *host_world, camera *cam ){
+void ent_miniworld_render( world_instance *host_world, vg_camera *cam )
+{
    if( host_world != &world_static.instances[k_world_purpose_hub] )
       return;
 
@@ -138,7 +144,8 @@ static void ent_miniworld_render( world_instance *host_world, camera *cam ){
    }
 }
 
-static void ent_miniworld_preupdate(void){
+void ent_miniworld_preupdate(void)
+{
    world_instance *hub = world_current_instance(),
                   *dest = &world_static.instances[k_world_purpose_client];
 
@@ -177,7 +184,8 @@ static void ent_miniworld_preupdate(void){
    }
 }
 
-static void ent_miniworld_goback(void){
+void ent_miniworld_goback(void)
+{
    audio_lock();
    audio_oneshot( &audio_ui[2], 1.0f, 0.0f );
    audio_unlock();
@@ -186,6 +194,6 @@ static void ent_miniworld_goback(void){
    global_miniworld.t = 1.0f;
 
    global_miniworld.cam = skaterift.cam;
-   m4x3_transform_camera( global_miniworld.mmdl, &global_miniworld.cam );
+   vg_m4x3_transform_camera( global_miniworld.mmdl, &global_miniworld.cam );
    world_switch_instance(0);
 }
index e963a09f549ce63dc822b6f0fa02767b691c7075..b1aed55bf12d73b2717e8ff51d35e6ab827fb66e 100644 (file)
@@ -1,20 +1,18 @@
-#ifndef ENT_MINIWORLD_H
-#define ENT_MINIWORLD_H
-
+#pragma once
 #include "entity.h"
 
-struct {
+struct global_miniworld
+{
    ent_miniworld *active;
    int transition;
    f32 t;
 
    m4x3f mmdl;
-   camera cam;
+   vg_camera cam;
 }
-static global_miniworld;
-
-static void ent_miniworld_call( world_instance *world, ent_call *call );
-static void ent_miniworld_render( world_instance *host_world, camera *cam );
-static void ent_miniworld_goback(void);
+extern global_miniworld;
 
-#endif /* ENT_MINIWORLD_H */
+void ent_miniworld_call( world_instance *world, ent_call *call );
+void ent_miniworld_render( world_instance *host_world, vg_camera *cam );
+void ent_miniworld_goback(void);
+void ent_miniworld_preupdate(void);
index ce5ad0f2168c9067d504a0ca8cc17d4f05b0c8c8..66b822db62d9e4eb9bf2a20cd71ab76db8c2230f 100644 (file)
@@ -1,11 +1,11 @@
-#ifndef ENT_OBJECTIVE_C
-#define ENT_OBJECTIVE_C
-
 #include "world.h"
 #include "world_load.h"
 #include "entity.h"
 #include "audio.h"
 #include "steam.h"
+#include "ent_region.h"
+#include "player.h"
+#include "player_skate.h"
 
 static void ent_objective_pass( world_instance *world, 
                                    ent_objective *objective ){
@@ -81,7 +81,8 @@ static int ent_objective_check_filter( ent_objective *objective ){
    }
 }
 
-static void ent_objective_call( world_instance *world, ent_call *call ){
+void ent_objective_call( world_instance *world, ent_call *call )
+{
    u32 index = mdl_entity_id_id( call->id );
    ent_objective *objective = mdl_arritm( &world->ent_objective, index );
 
@@ -127,5 +128,3 @@ static void ent_objective_call( world_instance *world, ent_call *call ){
       vg_error( "Unhandled function id: %u\n", call->function );
    }
 }
-
-#endif /* ENT_OBJECTIVE_C */
diff --git a/ent_objective.h b/ent_objective.h
new file mode 100644 (file)
index 0000000..0f3e4e5
--- /dev/null
@@ -0,0 +1,4 @@
+#pragma once
+#include "entity.h"
+#include "world.h"
+void ent_objective_call( world_instance *world, ent_call *call );
index 44d49a096637bff1f4e6777aedb38e7820fcf12f..e58d594708443bd46c3ef92e70569932410348ff 100644 (file)
@@ -3,7 +3,10 @@
 #include "network_common.h"
 #include "network.h"
 
-static u32 region_spark_colour( u32 flags ){
+struct global_ent_region global_ent_region;
+
+u32 region_spark_colour( u32 flags )
+{
    if( flags & k_ent_route_flag_achieve_gold )
       return 0xff8ce0fa;
    else if( flags & k_ent_route_flag_achieve_silver )
@@ -12,7 +15,8 @@ static u32 region_spark_colour( u32 flags ){
       return 0x00;
 }
 
-static void ent_region_call( world_instance *world, ent_call *call ){
+void ent_region_call( world_instance *world, ent_call *call )
+{
    ent_region *region = 
       mdl_arritm( &world->ent_region, mdl_entity_id_id(call->id) );
 
@@ -61,7 +65,8 @@ static void ent_region_call( world_instance *world, ent_call *call ){
 /* 
  * reevaluate all achievements to calculate the compiled achievement
  */
-static void ent_region_re_eval( world_instance *world ){
+void ent_region_re_eval( world_instance *world )
+{
    u32 world_total = k_ent_route_flag_achieve_gold | 
                      k_ent_route_flag_achieve_silver;
 
index 85acb45852f4e4e5db92c4659da6ca66c0e15a81..4b278251907998b4db693819169b92a6a8ff261a 100644 (file)
@@ -1,14 +1,13 @@
-#ifndef ENT_REGION_H
-#define ENT_REGION_H
-
+#pragma once
 #include "world_entity.h"
 
-struct {
+struct global_ent_region
+{
    char location[ NETWORK_REGION_MAX ];
    u32 flags;
 }
-static global_ent_region;
-
-static u32 region_spark_colour( u32 flags );
+extern global_ent_region;
 
-#endif /* ENT_REGION_H */
+u32 region_spark_colour( u32 flags );
+void ent_region_re_eval( world_instance *world );
+void ent_region_call( world_instance *world, ent_call *call );
index 357031b049cd9b0f05ef775cea53580ef227d554..50bbeabf690429b442e4d3043de67bf1c655d214 100644 (file)
@@ -1,9 +1,7 @@
-#ifndef ENT_RELAY_C
-#define ENT_RELAY_C
+#include "ent_relay.h"
 
-#include "entity.h"
-
-static void ent_relay_call( world_instance *world, ent_call *call ){
+void ent_relay_call( world_instance *world, ent_call *call )
+{
    u32 index = mdl_entity_id_id( call->id );
    ent_relay *relay = mdl_arritm( &world->ent_relay, index );
 
@@ -23,5 +21,3 @@ static void ent_relay_call( world_instance *world, ent_call *call ){
       vg_error( "Unhandled function id: %u\n", call->function );
    }
 }
-
-#endif /* ENT_RELAY_C */
diff --git a/ent_relay.h b/ent_relay.h
new file mode 100644 (file)
index 0000000..acbe943
--- /dev/null
@@ -0,0 +1,3 @@
+#pragma once
+#include "entity.h"
+void ent_relay_call( world_instance *world, ent_call *call );
index fa1d66900c452edbf58f5641cf8351f5d1a574c7..8f95a26d292ce22c76c528e1819d8394f6cb7408 100644 (file)
@@ -1,11 +1,11 @@
-#ifndef ENT_ROUTE_C
-#define ENT_ROUTE_C
-
 #include "ent_route.h"
 #include "input.h"
 #include "gui.h"
 
-static void ent_route_call( world_instance *world, ent_call *call ){
+struct global_ent_route global_ent_route;
+
+void ent_route_call( world_instance *world, ent_call *call )
+{
    u32 index = mdl_entity_id_id( call->id );
    ent_route *route = mdl_arritm( &world->ent_route, index );
 
@@ -36,7 +36,8 @@ static void ent_route_call( world_instance *world, ent_call *call ){
 }
 
 /* TODO: these should recieve the world instance */
-static void ent_route_preupdate( ent_route *route, int active ){
+void ent_route_preupdate( ent_route *route, int active )
+{
    if( !active ) return;
 
    world_instance *world = world_current_instance();
@@ -66,5 +67,3 @@ static void ent_route_preupdate( ent_route *route, int active ){
       return;
    }
 }
-
-#endif /* ENT_ROUTE_C */
index 65c074f2ca545ab1a9726faf95b3f71421627a9e..ecc3278b72714522d31a58864a5e543537ad9e10 100644 (file)
@@ -1,14 +1,11 @@
-#ifndef ENT_ROUTE_H
-#define ENT_ROUTE_H
-
+#pragma once
 #include "entity.h"
 
-static struct {
+struct global_ent_route
+{
    struct gui_helper *helper_weekly, *helper_alltime;
 }
-global_ent_route;
-
-static void ent_route_call( world_instance *world, ent_call *call );
-static void ent_route_preupdate( ent_route *route, int active );
+extern global_ent_route;
 
-#endif /* ENT_ROUTE_H */
+void ent_route_call( world_instance *world, ent_call *call );
+void ent_route_preupdate( ent_route *route, int active );
index 86fc9714d039dd11f0563d4d845f9dec084114e1..ed222168ab59a94e2aab0df426645fa78b06e453 100644 (file)
@@ -1,5 +1,8 @@
 #include "vg/vg_steam_ugc.h"
 #include "vg/vg_msg.h"
+#include "vg/vg_tex.h"
+#include "vg/vg_image.h"
+#include "vg/vg_loader.h"
 #include "ent_skateshop.h"
 #include "world.h"
 #include "player.h"
 #include "save.h"
 #include "network.h"
 
+struct global_skateshop global_skateshop = 
+{
+   .render={.reg_id=0xffffffff,.world_reg=0xffffffff}
+};
+
 /*
  * Checks string equality but does a hash check first
  */
@@ -143,7 +151,8 @@ static void skateshop_op_board_scan(void){
 }
 
 /* TODO: migrate to addon.c */
-static void skateshop_autostart_loading(void){
+void skateshop_autostart_loading(void)
+{
    if( !vg_loader_availible() ) return;
 
    SDL_AtomicLock( &addon_system.sl_cache_using_resources );
@@ -194,7 +203,8 @@ static void skateshop_init_async(void *_data,u32 size){
 /*
  * VG event init
  */
-static void skateshop_init(void){
+void skateshop_init(void)
+{
    vg_async_call( skateshop_init_async, NULL, 0 );
 }
 
@@ -228,7 +238,8 @@ static void skateshop_server_helper_update(void){
  * VG event preupdate 
  */
 void temp_update_playermodel(void);
-static void ent_skateshop_preupdate( ent_skateshop *shop, int active ){
+void ent_skateshop_preupdate( ent_skateshop *shop, int active )
+{
    if( !active ) return;
 
    /* input filter */
@@ -436,7 +447,8 @@ static void ent_skateshop_preupdate( ent_skateshop *shop, int active ){
    }
 }
 
-static void skateshop_world_preupdate( world_instance *world ){
+void skateshop_world_preupdate( world_instance *world )
+{
    for( u32 i=0; i<mdl_arrcount(&world->ent_skateshop); i++ ){
       ent_skateshop *shop = mdl_arritm( &world->ent_skateshop, i );
 
@@ -707,7 +719,8 @@ none:;
 /*
  * World: render event
  */
-static void skateshop_render( ent_skateshop *shop ){
+void skateshop_render( ent_skateshop *shop )
+{
    if( shop->type == k_skateshop_type_boardshop )
       skateshop_render_boardshop( shop );
    else if( shop->type == k_skateshop_type_charshop )
@@ -720,7 +733,8 @@ static void skateshop_render( ent_skateshop *shop ){
       vg_fatal_error( "Unknown store (%u)\n", shop->type );
 }
 
-static void skateshop_render_nonfocused( world_instance *world, camera *cam ){
+void skateshop_render_nonfocused( world_instance *world, vg_camera *cam )
+{
    for( u32 j=0; j<mdl_arrcount( &world->ent_skateshop ); j ++ ){
       ent_skateshop *shop = mdl_arritm(&world->ent_skateshop, j );
 
@@ -774,7 +788,8 @@ static void ent_skateshop_helpers_pickable( const char *acceptance ){
 /*
  * Entity logic: entrance event
  */
-static void ent_skateshop_call( world_instance *world, ent_call *call ){
+void ent_skateshop_call( world_instance *world, ent_call *call )
+{
    u32 index = mdl_entity_id_id( call->id );
    ent_skateshop *shop = mdl_arritm( &world->ent_skateshop, index );
    vg_info( "skateshop_call\n" );
index 68a34f4f7980a2f7224ba07402d2b70ad97bb3db..0bbeb8d0e02cf7ddf09ef7bd1d33e42beca83dc6 100644 (file)
@@ -1,6 +1,4 @@
-#ifndef ENT_SKATESHOP_H
-#define ENT_SKATESHOP_H
-
+#pragma once
 #include "world.h"
 #include "world_load.h"
 #include "player.h"
@@ -10,7 +8,8 @@
 
 #define SKATESHOP_VIEW_SLOT_MAX    5
 
-struct{
+struct global_skateshop
+{
    v3f look_target;
 
    struct shop_view_slot{
@@ -43,12 +42,12 @@ struct{
    addon_reg *reg_preview, *reg_loaded_preview;
    GLuint tex_preview;
 }
-static global_skateshop={
-   .render={.reg_id=0xffffffff,.world_reg=0xffffffff}
-};
-
-static void ent_skateshop_preupdate( ent_skateshop *shop, int active );
-static void skateshop_render( ent_skateshop *shop );
-static void skateshop_render_nonfocused( world_instance *world, camera *cam );
-
-#endif /* ENT_SKATESHOP_H */
+extern global_skateshop;
+
+void skateshop_init(void);
+void ent_skateshop_preupdate( ent_skateshop *shop, int active );
+void skateshop_render( ent_skateshop *shop );
+void skateshop_render_nonfocused( world_instance *world, vg_camera *cam );
+void skateshop_autostart_loading(void);
+void skateshop_world_preupdate( world_instance *world );
+void ent_skateshop_call( world_instance *world, ent_call *call );
index d59c6b778c91b661aa17137fa589d37f5d1e4711..f9fca03e8928db2c982dc2d4bbbfe2dfa053ec21 100644 (file)
@@ -5,7 +5,8 @@ static f32 k_tornado_strength = 0.0f,
            k_tornado_ratio    = 0.5f,
            k_tornado_range    = 10.f;
 
-static void ent_tornado_init(void){
+void ent_tornado_init(void)
+{
    vg_console_reg_var( "k_tonado_strength", &k_tornado_strength,
                         k_var_dtype_f32, VG_VAR_PERSISTENT|VG_VAR_CHEAT );
    vg_console_reg_var( "k_tonado_ratio", &k_tornado_ratio,
@@ -14,7 +15,8 @@ static void ent_tornado_init(void){
                         k_var_dtype_f32, VG_VAR_PERSISTENT|VG_VAR_CHEAT );
 }
 
-static void ent_tornado_debug(void) {
+void ent_tornado_debug(void) 
+{
    world_instance *world = world_current_instance();
    for( u32 i=0; i<mdl_arrcount(&world->ent_marker); i ++ ){
       ent_marker *marker = mdl_arritm( &world->ent_marker, i );
@@ -32,7 +34,8 @@ static void ent_tornado_debug(void) {
    }
 }
 
-static void ent_tornado_forces( v3f co, v3f cv, v3f out_a ){
+void ent_tornado_forces( v3f co, v3f cv, v3f out_a )
+{
    world_instance *world = world_current_instance();
    v3_zero( out_a );
 
@@ -61,7 +64,8 @@ static void ent_tornado_forces( v3f co, v3f cv, v3f out_a ){
    }
 }
 
-static void ent_tornado_pre_update(void){
+void ent_tornado_pre_update(void)
+{
    world_instance *world = world_current_instance();
    for( u32 i=0; i<mdl_arrcount(&world->ent_marker); i ++ ){
       ent_marker *marker = mdl_arritm( &world->ent_marker, i );
diff --git a/ent_tornado.h b/ent_tornado.h
new file mode 100644 (file)
index 0000000..f89c070
--- /dev/null
@@ -0,0 +1,6 @@
+#pragma once
+
+void ent_tornado_init(void);
+void ent_tornado_debug(void);
+void ent_tornado_forces( v3f co, v3f cv, v3f out_a );
+void ent_tornado_pre_update(void);
index f7167f29e9d410d0f19f2c096ea46c701a9f6a2b..5735d5b1bf9723fe5044b36a76335ca36a29385a 100644 (file)
@@ -1,6 +1,3 @@
-#ifndef ENT_TRAFFIC_C
-#define ENT_TRAFFIC_C
-
 #include "world.h"
 
 static void ent_traffic_update( world_instance *world, v3f pos ){
@@ -63,5 +60,3 @@ static void ent_traffic_update( world_instance *world, v3f pos ){
       vg_line_point( traffic->transform.co, 0.3f, VG__BLUE );
    }
 }
-
-#endif /* ENT_TRAFFIC_C */
index bebee23ac65fe2af87cf9d643f580a2ba5ed16fc..18d8d1ed57947e2d149846aaed8782bdcf76beee 100644 (file)
@@ -1,7 +1,3 @@
-#ifndef ENT_TRAFFIC_H
-#define ENT_TRAFFIC_H
-
+#pragma once
 #include "world.h"
-static void ent_traffic_update( world_instance *world, v3f pos );
-
-#endif /* ENT_TRAFFIC_H */
+void ent_traffic_update( world_instance *world, v3f pos );
index ce6d98eb76ecd959f572160c8f6c08f14b66d928..261dbbcd2c1ba89c89b58d4ff45997eae0f2871a 100644 (file)
--- a/entity.c
+++ b/entity.c
@@ -1,23 +1,20 @@
-#ifndef ENTITY_C
-#define ENTITY_C
-
 #include "world.h"
 #include "entity.h"
 #include "world_entity.h"
 
-#include "ent_skateshop.c"
-#include "ent_objective.c"
-#include "ent_challenge.c"
-#include "ent_relay.c"
-#include "ent_route.c"
-#include "ent_miniworld.c"
-#include "ent_region.c"
-#include "ent_traffic.c"
-#include "ent_glider.c"
+#include "ent_objective.h"
+#include "ent_skateshop.h"
+#include "ent_relay.h"
+#include "ent_challenge.h"
+#include "ent_route.h"
+#include "ent_miniworld.h"
+#include "ent_region.h"
+#include "ent_glider.h"
 
 typedef void (*fn_entity_call_handler)( world_instance *, ent_call *);
 
-static void entity_call( world_instance *world, ent_call *call ){
+void entity_call( world_instance *world, ent_call *call )
+{
    u32 type = mdl_entity_id_type( call->id );
 
    fn_entity_call_handler table[] = {
@@ -50,4 +47,17 @@ static void entity_call( world_instance *world, ent_call *call ){
    fn( world, call );
 }
 
-#endif /* ENTITY_C */
+ent_marker *ent_find_marker( mdl_context *mdl, mdl_array_ptr *arr, 
+                             const char *alias )
+{
+   for( u32 i=0; i<mdl_arrcount(arr); i++ ){
+      ent_marker *marker = mdl_arritm( arr, i );
+
+      if( !strcmp( mdl_pstr( mdl, marker->pstr_alias ), alias ) ){
+         return marker;
+      }
+   }
+
+   return NULL;
+}
+
index 2874441a51b56b0cfccd440f72d4800d6a4e93eb..a925318b92be649ec09725ce3a2112572474edc0 100644 (file)
--- a/entity.h
+++ b/entity.h
@@ -67,19 +67,23 @@ enum entity_alias{
    k_ent_glider      = 26
 };
 
-static u32 mdl_entity_id_type( u32 entity_id ){
+static inline u32 mdl_entity_id_type( u32 entity_id )
+{
    return (entity_id & 0x0fff0000) >> 16;
 }
 
-static u32 mdl_entity_id_id( u32 entity_id ){
+static inline u32 mdl_entity_id_id( u32 entity_id )
+{
    return entity_id & 0x0000ffff;
 }
 
-static u32 mdl_entity_id( u32 type, u32 index ){
+static inline u32 mdl_entity_id( u32 type, u32 index )
+{
    return (type & 0xfffff)<<16 | (index & 0xfffff);
 }
 
-enum entity_function{
+enum entity_function
+{
    k_ent_function_trigger,
    k_ent_function_particle_spawn,
    k_ent_function_trigger_leave
@@ -414,19 +418,8 @@ struct ent_worldinfo{
    u32 flags;
 };
 
-static ent_marker *ent_find_marker( mdl_context *mdl,
-                                       mdl_array_ptr *arr, const char *alias )
-{
-   for( u32 i=0; i<mdl_arrcount(arr); i++ ){
-      ent_marker *marker = mdl_arritm( arr, i );
-
-      if( !strcmp( mdl_pstr( mdl, marker->pstr_alias ), alias ) ){
-         return marker;
-      }
-   }
-
-   return NULL;
-}
+ent_marker *ent_find_marker( mdl_context *mdl, mdl_array_ptr *arr, 
+                             const char *alias );
 
 enum channel_behaviour{
    k_channel_behaviour_unlimited = 0,
@@ -565,4 +558,4 @@ struct ent_glider {
 };
 
 #include "world.h"
-static void entity_call( world_instance *world, ent_call *call );
+void entity_call( world_instance *world, ent_call *call );
diff --git a/font.h b/font.h
index a83b73cea7ad82808b8406d7e4d879209fc892d3..a7836139ffc574b06a082c35362b499d5f71a245 100644 (file)
--- a/font.h
+++ b/font.h
@@ -1,9 +1,7 @@
-#ifndef FONT_H
-#define FONT_H
-
+#pragma once
 #include "model.h"
 #include "entity.h"
-#include "camera.h"
+#include "vg/vg_camera.h"
 #include "shaders/model_font.h"
 #include "shaders/scene_font.h"
 #include "world_render.h"
@@ -105,11 +103,6 @@ static void font3d_load( font3d *font, const char *mdl_path, void *alloc ){
    mdl_close( &font->mdl );
 }
 
-static void font3d_init(void){
-   shader_model_font_register();
-   shader_scene_font_register();
-}
-
 static u32 font3d_find_variant( font3d *font, const char *name ){
    for( u32 i=0; i<mdl_arrcount( &font->font_variants ); i ++ ){
       ent_font_variant *variant = mdl_arritm( &font->font_variants, i );
@@ -140,7 +133,7 @@ static gui_font3d;
  */
 static void font3d_bind( font3d *font, enum font_shader shader, 
                          int depth_compare, world_instance *world,
-                         camera *cam ){
+                         vg_camera *cam ){
    gui_font3d.shader = shader;
    gui_font3d.font = font;
    glActiveTexture( GL_TEXTURE1 );
@@ -188,7 +181,7 @@ static ent_glyph *font3d_glyph( font3d *font, u32 variant_id, u32 utf32 ){
 }
 
 static void font3d_set_transform( const char *text,
-                                  camera *cam, m4x3f transform ){
+                                  vg_camera *cam, m4x3f transform ){
    v4_copy( (v4f){0.0f,0.0f,0.0f,1.0f}, gui_font3d.offset );
 
    m4x4f prev_mtx;
@@ -296,7 +289,7 @@ static void font3d_draw( const char *text ){
 }
 
 static f32 font3d_simple_draw( u32 variant_id, const char *text, 
-                               camera *cam, m4x3f transform ){
+                               vg_camera *cam, m4x3f transform ){
    if( !text ) return 0.0f;
 
    gui_font3d.variant_id = variant_id;
@@ -322,5 +315,3 @@ static f32 font3d_string_width( u32 variant_id, const char *text ){
 
    return width;
 }
-
-#endif /* FONT_H */
index 2e79ff1fefed3e57175736f4c61aa7016cf66ad5..246af3ca71a458dd3da15f78204c736bf7d64997 100644 (file)
--- a/freecam.c
+++ b/freecam.c
@@ -1,8 +1,10 @@
 #include "skaterift.h"
+#include "player_replay.h"
 #include "input.h"
 
-static void freecam_preupdate(void){
-   camera *cam = &skaterift.replay_freecam;
+void freecam_preupdate(void)
+{
+   vg_camera *cam = &player_replay.replay_freecam;
    v3f angles;
    v3_copy( cam->angles, angles );
    player_look( angles, 1.0f );
@@ -11,13 +13,13 @@ static void freecam_preupdate(void){
 
    v3f d;
    v3_sub( angles, cam->angles, d );
-   v3_muladds( skaterift.freecam_w, d, 20.0f, skaterift.freecam_w );
-   v3_muls( skaterift.freecam_w, decay, skaterift.freecam_w );
-   v3_muladds( cam->angles, skaterift.freecam_w, vg.time_frame_delta,
+   v3_muladds( player_replay.freecam_w, d, 20.0f, player_replay.freecam_w );
+   v3_muls( player_replay.freecam_w, decay, player_replay.freecam_w );
+   v3_muladds( cam->angles, player_replay.freecam_w, vg.time_frame_delta,
                cam->angles );
    cam->angles[1] = vg_clampf( cam->angles[1], -VG_PIf*0.5f,VG_PIf*0.5f);
 
-   camera_update_transform( cam );
+   vg_camera_update_transform( cam );
 
    v3f lookdir = { 0.0f, 0.0f, -1.0f },
        sidedir = { 1.0f, 0.0f,  0.0f };
@@ -29,22 +31,23 @@ static void freecam_preupdate(void){
    joystick_state( k_srjoystick_steer, input );
    v2_muls( input, vg.time_frame_delta*6.0f*20.0f, input );
    
-   v3_muladds( skaterift.freecam_v, lookdir, -input[1], 
-               skaterift.freecam_v );
-   v3_muladds( skaterift.freecam_v, sidedir, input[0], 
-               skaterift.freecam_v );
+   v3_muladds( player_replay.freecam_v, lookdir, -input[1], 
+               player_replay.freecam_v );
+   v3_muladds( player_replay.freecam_v, sidedir, input[0], 
+               player_replay.freecam_v );
 
-   v3_muls( skaterift.freecam_v, decay, skaterift.freecam_v );
+   v3_muls( player_replay.freecam_v, decay, player_replay.freecam_v );
    v3_muladds( cam->pos,
-               skaterift.freecam_v, vg.time_frame_delta, cam->pos );
+               player_replay.freecam_v, vg.time_frame_delta, cam->pos );
 }
 
-static int freecam_cmd( int argc, const char *argv[] ){
+int freecam_cmd( int argc, const char *argv[] )
+{
    if( argc ){
-      skaterift.freecam = atoi(argv[0]);
+      player_replay.freecam = atoi(argv[0]);
 
-      if( skaterift.freecam ){
-         camera_copy( &skaterift.cam, &skaterift.replay_freecam );
+      if( player_replay.freecam ){
+         vg_camera_copy( &skaterift.cam, &player_replay.replay_freecam );
       }
    }
    return 0;
index e0d5adea61d17052acf8d75bb2088f2bc02826af..1f9f5e28204d28652db95204f134817957adde30 100644 (file)
--- a/freecam.h
+++ b/freecam.h
@@ -1 +1,3 @@
-static void freecam_preupdate(void);
+#pragma once
+void freecam_preupdate(void);
+int freecam_cmd( int argc, const char *argv[] );
diff --git a/gui.h b/gui.h
index 67f78b5df9829e4b66e7405cb1015e8cac3765cb..c6ebe715b0441ac3a94245f69124d92b80f0a854 100644 (file)
--- a/gui.h
+++ b/gui.h
@@ -1,6 +1,4 @@
-#ifndef GUI_H
-#define GUI_H
-
+#pragma once
 #include "font.h"
 #include "input.h"
 #include "player.h"
@@ -87,7 +85,7 @@ static void gui_draw(void){
          (v3_dist2(localplayer.rb.co,gui.trick_co) > 2.0f) )
       gui_helper_clear();
 
-   camera ortho;
+   vg_camera ortho;
 
    float fl = 0.0f,
          fr = vg.window_x,
@@ -103,9 +101,9 @@ static void gui_draw(void){
    ortho.mtx.p[3][1] = (ft + fb) * -tb;
    ortho.mtx.p[3][3] = 1.0f;
    m4x3_identity( ortho.transform );
-   camera_update_view( &ortho );
+   vg_camera_update_view( &ortho );
    m4x4_mul( ortho.mtx.p, ortho.mtx.v, ortho.mtx.pv );   /* HACK */
-   camera_finalize( &ortho );
+   vg_camera_finalize( &ortho );
 
 
    /* icons */
@@ -349,5 +347,3 @@ static void gui_init(void){
    mdl_async_load_glmesh( &gui.model_icons, &gui.icons_mesh, NULL );
    mdl_close( &gui.model_icons );
 }
-
-#endif /* GUI_H */
diff --git a/menu.c b/menu.c
new file mode 100644 (file)
index 0000000..b98f5d4
--- /dev/null
+++ b/menu.c
@@ -0,0 +1,792 @@
+#pragma once
+#include "skaterift.h"
+#include "menu.h"
+#include "model.h"
+#include "entity.h"
+#include "input.h"
+#include "world_map.h"
+#include "ent_miniworld.h"
+#include "audio.h"
+#include "workshop.h"
+#include "gui.h"
+#include "shaders/model_menu.h"
+
+struct global_menu menu;
+
+/*
+ * Attaches memory locations to the various items in the menu
+ */
+void menu_link(void)
+{
+   /* link data locations */
+   for( u32 i=0; i<mdl_arrcount(&menu.items); i++ ){
+      ent_menuitem *item = mdl_arritm( &menu.items, i );
+      
+      if( item->type == k_ent_menuitem_type_toggle ||
+          item->type == k_ent_menuitem_type_slider ){
+         
+         const char *name;
+
+         if( item->type == k_ent_menuitem_type_slider )
+            name = mdl_pstr( &menu.model, item->slider.pstr_data );
+         else
+            name = mdl_pstr( &menu.model, item->checkmark.pstr_data );
+         vg_var *var = vg_console_match_var( name );
+
+         if( var ){
+            if( ( item->type == k_ent_menuitem_type_slider && 
+                  var->data_type != k_var_dtype_f32
+                ) ||
+                ( item->type == k_ent_menuitem_type_toggle &&!
+                  ( var->data_type == k_var_dtype_i32 ||
+                    var->data_type == k_var_dtype_u32 
+                  )
+               )
+            ){
+               vg_error( "Cannot hook to data %s(%p), because it is type %d.\n",
+                           name, var, var->data_type );
+               item->pvoid = NULL;
+            }
+            else{
+               item->pvoid = var->data;
+            }
+         }
+         else{
+            vg_error( "No data named %s\n", name );
+            item->pvoid = NULL;
+         }
+      }
+      else{
+         item->pvoid = NULL;
+      }
+   }
+
+   /* link controllers */
+   menu.ctr_deck = NULL;
+   menu.ctr_kbm = NULL;
+   menu.ctr_ps = NULL;
+   menu.ctr_steam = NULL;
+   menu.ctr_xbox = NULL;
+
+   for( u32 i=0; i<mdl_arrcount(&menu.items); i++ ){
+      ent_menuitem *item = mdl_arritm( &menu.items, i );
+
+      if( MDL_CONST_PSTREQ( &menu.model, item->visual.pstr_name, "deck" ) )
+         menu.ctr_deck = item;
+      if( MDL_CONST_PSTREQ( &menu.model, item->visual.pstr_name, "kbm" ) )
+         menu.ctr_kbm = item;
+      if( MDL_CONST_PSTREQ( &menu.model, item->visual.pstr_name, "ps" ) )
+         menu.ctr_ps = item;
+      if( MDL_CONST_PSTREQ( &menu.model, item->visual.pstr_name, "steam" ) )
+         menu.ctr_steam = item;
+      if( MDL_CONST_PSTREQ( &menu.model, item->visual.pstr_name, "xbox" ) )
+         menu.ctr_xbox = item;
+   }
+}
+
+void menu_close(void)
+{
+   skaterift.activity = k_skaterift_default;
+   menu.page_depth = 0;
+   menu.page = 0xffffffff;
+   srinput.state = k_input_state_resume;
+}
+
+void menu_init(void)
+{
+   void *alloc = vg_mem.rtmemory;
+
+   mdl_open( &menu.model, "models/rs_menu.mdl", alloc );
+   mdl_load_metadata_block( &menu.model, alloc );
+
+   vg_linear_clear( vg_mem.scratch );
+
+   MDL_LOAD_ARRAY( &menu.model, &menu.items,   ent_menuitem, alloc );
+   MDL_LOAD_ARRAY( &menu.model, &menu.markers, ent_marker, alloc );
+   MDL_LOAD_ARRAY( &menu.model, &menu.cameras, ent_camera, alloc );
+
+   u32 count = mdl_arrcount( &menu.model.textures );
+   menu.textures = vg_linear_alloc(alloc,vg_align8(sizeof(GLuint)*(count+1)));
+   menu.textures[0] = vg.tex_missing;
+
+   mdl_async_load_glmesh( &menu.model, &menu.mesh, NULL );
+
+   for( u32 i=0; i<count; i ++ ){
+      vg_linear_clear( vg_mem.scratch );
+      menu.textures[i+1] = vg.tex_missing;
+
+      mdl_texture *tex = mdl_arritm( &menu.model.textures, i );
+      void *data = vg_linear_alloc( vg_mem.scratch, tex->file.pack_size );
+      mdl_fread_pack_file( &menu.model, &tex->file, data );
+      vg_tex2d_load_qoi_async( data, tex->file.pack_size, 
+                               VG_TEX2D_LINEAR|VG_TEX2D_CLAMP,
+                               &menu.textures[i+1] );
+   }
+
+   mdl_close( &menu.model );
+}
+
+/*
+ * Drop back a page until we're at the bottom which then we jus quit
+ */
+static void menu_back_page(void){
+   menu.page_depth --;
+   if( menu.page_depth == 0 ){
+      menu_close();
+   }
+   else{
+      menu.page = menu.page_stack[ menu.page_depth ].page;
+      menu.cam = menu.page_stack[ menu.page_depth ].cam;
+
+      if( menu.input_mode == k_menu_input_mode_keys )
+         menu.loc = menu.page_stack[ menu.page_depth ].loc;
+      else menu.loc = NULL;
+   }
+}
+
+/*
+ * Open page to the string identifier
+ */
+void menu_open_page( const char *name, 
+                     enum ent_menuitem_stack_behaviour stackmode )
+{
+   srinput.state = k_input_state_resume;
+   if( stackmode == k_ent_menuitem_stack_append ){
+      if( menu.page_depth >= MENU_STACK_SIZE )
+         vg_fatal_error( "Stack overflow\n" );
+   }
+   else{
+      if( menu.page_depth == 0 )
+         vg_fatal_error( "Stack underflow\n" );
+   }
+
+   u32 hash = vg_strdjb2( name );
+   for( u32 i=0; i<mdl_arrcount(&menu.items); i++ ){
+      ent_menuitem *item = mdl_arritm( &menu.items, i );
+      
+      if( item->type == k_ent_menuitem_type_page ){
+         if( mdl_pstreq( &menu.model, item->page.pstr_name, name, hash ) ){
+            u32 new_page = __builtin_ctz( item->groups );
+
+            if( new_page == menu.page ){
+               if( stackmode != k_ent_menuitem_stack_replace )
+                  menu_back_page();
+            }
+            else{
+               menu.page_stack[ menu.page_depth ].page = menu.page;
+               menu.page_stack[ menu.page_depth ].cam = menu.cam;
+               menu.page_stack[ menu.page_depth ].loc = menu.loc;
+               
+               if( stackmode == k_ent_menuitem_stack_append )
+                  menu.page_depth ++;
+
+               menu.page = __builtin_ctz( item->groups );
+
+               if( menu.input_mode == k_menu_input_mode_keys ){
+                  if( item->page.id_entrypoint ){
+                     u32 id = mdl_entity_id_id( item->page.id_entrypoint );
+                     menu.loc = mdl_arritm( &menu.items, id );
+                  }
+               }
+
+               if( item->page.id_viewpoint ){
+                  u32 id = mdl_entity_id_id( item->page.id_viewpoint );
+                  menu.cam = mdl_arritm( &menu.cameras, id );
+               }
+            }
+            return;
+         }
+      }
+   }
+}
+
+/*
+ * activate a pressable type
+ */
+static void menu_trigger_item( ent_menuitem *item ){
+   if     ( item->type == k_ent_menuitem_type_event_button ){
+      u32 q = item->button.pstr;
+
+      if( MDL_CONST_PSTREQ( &menu.model, q, "quit" ) ){
+         vg.window_should_close = 1;
+      }
+      else if( MDL_CONST_PSTREQ( &menu.model, q, "map" ) ){
+         menu_close();
+         world_map_enter();
+      }
+      else if( MDL_CONST_PSTREQ( &menu.model, q, "hub" ) ){
+         if( world_static.active_instance == k_world_purpose_client ){
+            menu_close();
+            ent_miniworld_goback();
+         }
+      }
+      else if( MDL_CONST_PSTREQ( &menu.model, q, "credits" ) ){
+         menu.credits_open = 1;
+      }
+      else if( MDL_CONST_PSTREQ( &menu.model, q, "workshop" ) ){
+         workshop_submit_command(0,NULL);
+      }
+      else if( MDL_CONST_PSTREQ( &menu.model, q, "engine" ) ){
+         vg_settings_open();
+      }
+      else if( MDL_CONST_PSTREQ( &menu.model, q, "prem_store" ) ){
+         if( steam_ready )
+            SteamAPI_ISteamFriends_ActivateGameOverlayToStore( 
+                  SteamAPI_SteamFriends(), 2103940, k_EOverlayToStoreFlag_None);
+      }
+      else if( MDL_CONST_PSTREQ( &menu.model, q, "prem_nevermind" ) ){
+         menu_close();
+      }
+   }
+   else if( item->type == k_ent_menuitem_type_page_button ){
+      menu_open_page( mdl_pstr( &menu.model, item->button.pstr ),
+                      item->button.stack_behaviour );
+   }
+   else if( item->type == k_ent_menuitem_type_toggle ){
+      if( item->pi32 ){
+         *item->pi32 = *item->pi32 ^ 0x1;
+      }
+   }
+}
+
+static f32 menu_slider_snap( f32 value, f32 old, f32 notch ){
+   f32 const k_epsilon = 0.0125f;
+
+   if( fabsf(notch-value) < k_epsilon ){
+      if( fabsf(notch-old) > k_epsilon ){
+         audio_lock();
+         audio_oneshot( &audio_ui[0], 1.0f, 0.0f );
+         audio_unlock();
+      }
+
+      return notch;
+   }
+   else
+      return value;
+}
+
+static void menu_setitem_type( ent_menuitem *item, 
+                               enum ent_menuitem_type type ){
+   if( !item ) return;
+   item->type = type;
+}
+
+/* 
+ * Run from vg_gui every frame
+ */
+void menu_update(void)
+{
+   if( workshop_form.page != k_workshop_form_hidden ){
+      return;
+   }
+
+   int escape = button_down( k_srbind_mback );
+   if( menu.credits_open || vg.settings_open ){
+      if( escape ){
+         menu.credits_open = 0;
+
+         if( vg.settings_open )
+            vg_settings_close();
+      }
+      return;
+   }
+
+   if( button_down( k_srbind_mopen ) ){
+      if( skaterift.activity == k_skaterift_default ){
+         skaterift.activity = k_skaterift_menu;
+         menu.page = 0xffffffff;
+         menu_open_page( "Main Menu", k_ent_menuitem_stack_append );
+         return;
+      }
+   }
+
+   if( skaterift.activity != k_skaterift_menu ) return;
+   enum menu_input_mode prev_mode = menu.input_mode;
+
+   /* get buttons inputs
+    * -------------------------------------------------------------------*/
+   int ml = button_down( k_srbind_mleft ),
+       mr = button_down( k_srbind_mright ),
+       mu = button_down( k_srbind_mup ),
+       md = button_down( k_srbind_mdown ),
+       mh = ml-mr,
+       mv = mu-md,
+       enter = button_down( k_srbind_maccept );
+
+   if( mh||mv||enter ){
+      menu.input_mode = k_menu_input_mode_keys;
+   }
+
+   /* get mouse inputs 
+    * --------------------------------------------------------------------*/
+   menu.mouse_dist += v2_length( vg.mouse_delta ); /* TODO: Move to UI */
+   menu.mouse_track += vg.time_frame_delta;
+   if( menu.mouse_track > 0.1f ){
+      menu.mouse_track = fmodf( menu.mouse_track, 0.1f );
+      if( menu.mouse_dist > 10.0f ){
+         menu.input_mode = k_menu_input_mode_mouse;
+         menu.mouse_dist = 0.0f;
+      }
+   }
+
+   if( ui_clicking(UI_MOUSE_LEFT) || ui_clicking(UI_MOUSE_RIGHT) ){
+      menu.input_mode = k_menu_input_mode_mouse;
+   }
+
+   if( menu.input_mode == k_menu_input_mode_mouse ){
+      /* 
+       * handle mouse input
+       * ------------------------------------------------------------*/
+      vg_ui.wants_mouse = 1;
+
+      /* 
+       * this raycasting is super cumbersome because all the functions were 
+       * designed for other purposes. we dont care though.
+       */
+      m4x4f inverse;
+      m4x4_inv( menu.view.mtx.p, inverse );
+      v4f coords;
+      coords[0] = vg_ui.mouse[0];
+      coords[1] = vg.window_y - vg_ui.mouse[1];
+      v2_div( coords, (v2f){ vg.window_x, vg.window_y }, coords );
+      v2_muls( coords, 2.0f, coords );
+      v2_add( coords, (v2f){-1.0f,-1.0f}, coords );
+      coords[2] = 1.0f;
+      coords[3] = 1.0f;
+      m4x4_mulv( inverse, coords, coords );
+      v3f ray;
+      m3x3_mulv( menu.view.transform, coords, ray );
+      v3_normalize( ray );
+
+      if( menu.loc && (menu.loc->type == k_ent_menuitem_type_slider) &&
+          ui_clicking(UI_MOUSE_LEFT) && menu.loc->pf32 ){
+
+         u32 il = mdl_entity_id_id( menu.loc->slider.id_min ),
+             ir = mdl_entity_id_id( menu.loc->slider.id_max );
+         ent_marker *ml = mdl_arritm( &menu.markers, il ),
+                    *mr = mdl_arritm( &menu.markers, ir );
+
+         v3f q2;
+         v3_muladds( menu.view.pos, ray, 100.0f, q2 );
+
+         f32 s,t;
+         v3f c1, c2;
+         v3f p1, q1, v0;
+         v3_sub( mr->transform.co, ml->transform.co, v0 );
+         v3_muladds( ml->transform.co, v0, -1.0f, p1 );
+         v3_muladds( mr->transform.co, v0,  1.0f, q1 );
+         closest_segment_segment( p1, q1, menu.view.pos, q2, &s,&t, c1,c2 );
+
+         s-=(1.0f/3.0f);
+         s/=(1.0f/3.0f);
+
+         if( ui_click_down(UI_MOUSE_LEFT) ){
+            menu.slider_offset = *menu.loc->pf32 - s;
+         }
+
+         f32 newvalue = vg_clampf( s+menu.slider_offset, 0.0f, 1.0f );
+
+         newvalue = menu_slider_snap( newvalue, *menu.loc->pf32, 0.00f );
+         newvalue = menu_slider_snap( newvalue, *menu.loc->pf32, 1.00f );
+         newvalue = menu_slider_snap( newvalue, *menu.loc->pf32, 0.25f );
+         newvalue = menu_slider_snap( newvalue, *menu.loc->pf32, 0.50f );
+         newvalue = menu_slider_snap( newvalue, *menu.loc->pf32, 0.75f );
+
+         *menu.loc->pf32 = newvalue;
+         return;
+      }
+
+      ent_menuitem *hit_item = NULL;
+
+      for( u32 i=0; i<mdl_arrcount(&menu.items); i++ ){
+         ent_menuitem *item = mdl_arritm( &menu.items, i );
+
+         if( item->type == k_ent_menuitem_type_page ) continue;
+         if( (item->type == k_ent_menuitem_type_visual) ||
+             (item->type == k_ent_menuitem_type_visual_nocol) ) continue;
+         if( item->type == k_ent_menuitem_type_binding ) continue;
+         if( !(item->groups & (0x1<<menu.page)) ) continue;
+
+         ent_menuitem *ray_item = item;
+
+         if( item->type == k_ent_menuitem_type_slider ){
+            u32 subtarget = mdl_entity_id_id( item->slider.id_handle );
+            ray_item = mdl_arritm( &menu.items, subtarget );
+         }
+         
+         v3f local_ray,
+             local_co;
+
+         m4x3f inverse_mtx;
+         mdl_transform_m4x3( &ray_item->transform, inverse_mtx );
+         m4x3_invert_full( inverse_mtx, inverse_mtx );
+         
+         m4x3_mulv( inverse_mtx, menu.view.transform[3], local_co );
+         m3x3_mulv( inverse_mtx, ray, local_ray );
+         v3_normalize( local_ray );
+         
+         local_ray[0] = 1.0f/local_ray[0];
+         local_ray[1] = 1.0f/local_ray[1];
+         local_ray[2] = 1.0f/local_ray[2];
+
+         for( u32 j=0; j<ray_item->submesh_count; j++ ){
+            mdl_submesh *sm = mdl_arritm( &menu.model.submeshs, 
+                                           ray_item->submesh_start + j );
+            if( ray_aabb1( sm->bbx, local_co, local_ray, 1000.0f ) ){
+               hit_item = item;
+               break;
+            }
+         }
+      }
+
+      if( hit_item != menu.loc ){
+         menu.loc = hit_item;
+      }
+
+      if( escape ){
+         menu_back_page();
+      }
+      else if( menu.loc ){
+         if( ui_click_down( UI_MOUSE_LEFT ) ){
+            menu_trigger_item( menu.loc );
+         }
+      }
+   }
+   else if( menu.input_mode == k_menu_input_mode_keys ){
+      /* 
+       * handle button input
+       * ------------------------------------------------------------*/
+      if( (prev_mode != k_menu_input_mode_keys) && !menu.loc ){
+         for( u32 i=0; i<mdl_arrcount(&menu.items); i++ ){
+            ent_menuitem *item = mdl_arritm( &menu.items, i );
+            
+            if( (item->type != k_ent_menuitem_type_page) &&
+                (item->type != k_ent_menuitem_type_visual) &&
+                (item->type != k_ent_menuitem_type_visual_nocol) &&
+                (item->groups & (0x1<<menu.page)) ){
+               menu.loc = item;
+            }
+         }
+      }
+
+      if( !menu.loc ) vg_fatal_error( "No location\n" );
+
+      if( menu.loc->type == k_ent_menuitem_type_slider && menu.loc->pf32 ){
+         f32 move = 0.0f;
+
+         if( vg_input.display_input_method == k_input_method_controller ){
+            move += button_press( k_srbind_mright );
+            move -= button_press( k_srbind_mleft );
+         }
+         else{
+            move += axis_state( k_sraxis_mbrowse_h );
+         }
+
+         move *= vg.time_frame_delta;
+         *menu.loc->pf32 = vg_clampf( *menu.loc->pf32 + move, 0.0f, 1.0f );
+
+         mh = 0;
+      }
+      
+      if( escape ){
+         menu_back_page();
+      }
+      else if( enter ){
+         menu_trigger_item( menu.loc );
+      }
+      else if( mh||mv ){
+         v3f opt; 
+         v3_zero( opt );
+         f32 best = 0.707f;
+         ent_menuitem *nextpos = NULL;
+
+         opt[0] += mh;
+         opt[2] += mv;
+         mdl_transform_vector( &menu.cam->transform, opt, opt );
+
+         for( u32 i=0; i<4; i++ ){
+            u32 id = menu.loc->id_links[i];
+            if( !id ) continue;
+            u32 index = mdl_entity_id_id( id );
+
+            ent_menuitem *other = mdl_arritm( &menu.items, index );
+            v3f delta;
+            v3_sub( menu.loc->transform.co, other->transform.co, delta );
+            v3_normalize( delta );
+
+            f32 score = v3_dot( delta, opt );
+            if( score > best ){
+               best = score;
+               nextpos = other;
+            }
+         }
+
+         if( nextpos ){
+            menu.loc = nextpos;
+         }
+      }
+   }
+
+   menu_setitem_type( menu.ctr_deck, k_ent_menuitem_type_disabled );
+   menu_setitem_type( menu.ctr_ps, k_ent_menuitem_type_disabled );
+   menu_setitem_type( menu.ctr_kbm, k_ent_menuitem_type_disabled );
+   menu_setitem_type( menu.ctr_xbox, k_ent_menuitem_type_disabled );
+   menu_setitem_type( menu.ctr_steam, k_ent_menuitem_type_disabled );
+
+   if( vg_input.display_input_method == k_input_method_kbm )
+      menu_setitem_type( menu.ctr_kbm, k_ent_menuitem_type_visual_nocol );
+   else{
+      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 ){
+         menu_setitem_type( menu.ctr_ps, k_ent_menuitem_type_visual_nocol );
+      }
+      else {
+         menu_setitem_type( menu.ctr_xbox, k_ent_menuitem_type_visual_nocol );
+      }
+      /* FIXME: Steam/Deck controller detection? */
+   }
+}
+
+static void menu_binding_string( char buf[128], u32 pstr );
+
+/*
+ * Run from vg_gui when active
+ */
+void menu_render(void)
+{
+   glEnable(GL_BLEND);
+   glDisable(GL_DEPTH_TEST);
+   glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
+   glBlendEquation(GL_FUNC_ADD);
+
+   shader_blitcolour_use();
+   v4f colour;
+   ui_hex_to_norm( ui_colour( k_ui_bg+3 ), colour );
+   colour[3] = 0.5f;
+
+   shader_blitcolour_uColour( colour );
+   render_fsquad();
+
+   if( (workshop_form.page != k_workshop_form_hidden) ||
+       (vg_ui.focused_control_type != k_ui_control_none) ){
+      return;
+   }
+
+   if( vg.settings_open )
+      return;
+
+   if( menu.credits_open ){
+      ui_rect panel = { 0,0, 460, 400 },
+              screen = { 0,0, vg.window_x,vg.window_y };
+      ui_rect_center( screen, panel );
+      ui_fill( panel, ui_colour(k_ui_bg) );
+      ui_outline( panel, 1, ui_colour(k_ui_fg), 0 );
+      ui_rect_pad( panel, (ui_px[]){8,8} );
+
+      ui_rect title;
+      ui_split( panel, k_ui_axis_h, 28*2, 0, title, panel );
+      ui_text( title, "Skate Rift - Credits", 2, k_ui_align_middle_center, 0 );
+      ui_split( panel, k_ui_axis_h, 28, 0, title, panel );
+      ui_text( title, "Mt.Zero Software", 1, k_ui_align_middle_center, 0 );
+
+      ui_split( panel, k_ui_axis_h, 8, 0, title, panel );
+      ui_split( panel, k_ui_axis_h, 28*2, 0, title, panel );
+      ui_text( title, "Free Software", 2, k_ui_align_middle_center, 0 );
+
+      ui_split( panel, k_ui_axis_h, 8, 0, title, panel );
+      ui_text( panel, 
+            "Sam Lantinga       - SDL2 - libsdl.org\n"
+            "Hunter WB          - Anyascii\n"
+            "David Herberth     - GLAD\n"
+            "Dominic Szablewski - QOI - qoiformat.org\n"
+            "Sean Barrett       - stb_image,stb_vorbis,stb_include\n"
+            "Khronos Group      - OpenGL\n"
+            , 1, k_ui_align_left, 0 );
+      return;
+   }
+
+   glEnable( GL_DEPTH_TEST );
+   glDisable( GL_BLEND );
+
+   f32 rate = vg.time_frame_delta * 12.0f;
+
+   if( menu.cam ){
+      vg_camera target;
+
+      target.fov = menu.cam->fov;
+      v3_copy( menu.cam->transform.co, target.pos );
+
+      v3f v0;
+      mdl_transform_vector( &menu.cam->transform, (v3f){0.0f,-1.0f,0.0f}, v0 );
+      v3_angles( v0, target.angles );
+
+      vg_camera_lerp( &menu.view, &target, rate, &menu.view );
+
+      menu.view.farz = 150.0f;
+      menu.view.nearz = 0.01f;
+
+      vg_camera_update_transform( &menu.view );
+      vg_camera_update_view( &menu.view );
+      vg_camera_update_projection( &menu.view );
+      vg_camera_finalize( &menu.view );
+   }
+   else return;
+
+   shader_model_menu_use();
+   shader_model_menu_uTexMain( 1 );
+   shader_model_menu_uPv( menu.view.mtx.pv );
+   shader_model_menu_uPvmPrev( menu.view.mtx_prev.pv );
+
+   mesh_bind( &menu.mesh );
+
+   v4f white, blue;
+
+   ui_hex_to_norm( ui_colour( k_ui_fg ), white );
+   ui_hex_to_norm( ui_colour( k_ui_orange+k_ui_brighter ), blue );
+
+   ent_menuitem *text_list[ 8 ];
+   u32 text_count = 0;
+
+   u32 current_tex = 0xffffffff;
+
+   for( u32 i=0; i<mdl_arrcount(&menu.items); i++ ){
+      ent_menuitem *item = mdl_arritm( &menu.items, i );
+
+      if(   item->type == k_ent_menuitem_type_disabled ) continue;
+      if(   item->type == k_ent_menuitem_type_page ) continue;
+      if( !(item->groups & (0x1 << menu.page)) ) continue;
+
+      if(   item->type == k_ent_menuitem_type_binding ){
+         if( text_count < vg_list_size(text_list) )
+            text_list[ text_count ++ ] = item;
+         else
+            vg_fatal_error( "Text list overflow" );
+
+         continue;  
+      }
+
+      int selected = 0;
+      
+      if( menu.loc ){
+         if( menu.loc->type == k_ent_menuitem_type_slider ){
+            u32 subid = menu.loc->slider.id_handle;
+            if( item == mdl_arritm( &menu.items, mdl_entity_id_id(subid) ))
+               selected = 1;
+         }
+         else{
+            if( item == menu.loc )
+               selected = 1;
+         }
+      }
+
+      if( item->type == k_ent_menuitem_type_visual_nocol ){
+         shader_model_menu_uColour( (v4f){1.0f,1.0f,1.0f,1.0f} );
+      }
+      else{
+         v4f colour;
+         item->factive = vg_lerpf( item->factive, selected, rate );
+         v4_lerp( white, blue, item->factive, colour );
+         shader_model_menu_uColour( colour );
+      }
+
+      f32 scale = 1.0f+item->factive*0.1f;
+
+      m4x3f mmdl;
+      mdl_transform transform = item->transform;
+      v3_muls( transform.s, scale, transform.s );
+      mdl_transform_m4x3( &transform, mmdl );
+
+      if( item->type == k_ent_menuitem_type_toggle && item->pi32 ){
+         u32 subid = mdl_entity_id_id( item->checkmark.id_check );
+         ent_menuitem *subitem = mdl_arritm( &menu.items, subid );
+
+         v3_muladds( item->transform.co, item->checkmark.offset, scale,
+                     subitem->transform.co );
+
+         subitem->fvisible = vg_lerpf( subitem->fvisible, *item->pi32, rate );
+         v3_fill( subitem->transform.s, subitem->fvisible );
+      }
+      else if( item->type == k_ent_menuitem_type_slider && item->pf32 ){
+         u32 il = mdl_entity_id_id( item->slider.id_min ),
+             ir = mdl_entity_id_id( item->slider.id_max ),
+             ih = mdl_entity_id_id( item->slider.id_handle );
+         ent_marker *ml = mdl_arritm( &menu.markers, il ),
+                    *mr = mdl_arritm( &menu.markers, ir );
+         ent_menuitem *handle = mdl_arritm( &menu.items, ih );
+
+         v3_lerp( ml->transform.co, mr->transform.co, *item->pf32,
+                  handle->transform.co );
+      }
+
+      shader_model_menu_uMdl( mmdl );
+
+      for( u32 j=0; j<item->submesh_count; j++ ){
+         u32 index = item->submesh_start + j;
+         mdl_submesh *sm = mdl_arritm( &menu.model.submeshs, index );
+         
+         mdl_material *mat = mdl_arritm( &menu.model.materials, 
+                                         sm->material_id-1 );
+
+         if( mat->tex_diffuse != current_tex ){
+            glActiveTexture( GL_TEXTURE1 );
+            glBindTexture( GL_TEXTURE_2D, menu.textures[ mat->tex_diffuse ] );
+            current_tex = mat->tex_diffuse;
+         }
+
+         mdl_draw_submesh( sm );
+      }
+   }
+
+   if( !text_count ) return;
+
+   char buf[ 128 ];
+
+   m4x3f local;
+   m4x3_identity( local );
+
+   font3d_bind( &gui.font, k_font_shader_default, 0, NULL, &menu.view );
+   for( u32 i=0; i<text_count; i++ ){
+      ent_menuitem *item = text_list[ i ];
+      m4x3f transform;
+      mdl_transform_m4x3( &item->transform, transform );
+
+      u32 variant = item->binding.font_variant;
+      menu_binding_string( buf, item->binding.pstr_bind );
+      f32 offset = font3d_string_width( variant, buf );
+
+      local[3][0] = -0.5f * offset;
+      m4x3_mul( transform, local, transform );
+
+      font3d_simple_draw( variant, buf, &menu.view, transform );
+   }
+}
+
+static void menu_binding_string( char buf[128], u32 pstr ){
+   vg_str str;
+   vg_strnull( &str, buf, 128 );
+
+   if( MDL_CONST_PSTREQ( &menu.model, pstr, "bind_jump" ) ){
+      vg_input_string( &str, input_button_list[k_srbind_jump], 1 );
+   }
+   else if( MDL_CONST_PSTREQ( &menu.model, pstr, "bind_trick0" ) ){
+      vg_strcat( &str, "SHUVIT " );
+      vg_input_string( &str, input_button_list[k_srbind_trick0], 1 );
+   }
+   else if( MDL_CONST_PSTREQ( &menu.model, pstr, "bind_trick1" ) ){
+      vg_strcat( &str, "KICKFLIP " );
+      vg_input_string( &str, input_button_list[k_srbind_trick1], 1 );
+   }
+   else if( MDL_CONST_PSTREQ( &menu.model, pstr, "bind_trick2" ) ){
+      vg_strcat( &str, "TREFLIP " );
+      vg_input_string( &str, input_button_list[k_srbind_trick2], 1 );
+   }
+   else if( MDL_CONST_PSTREQ( &menu.model, pstr, "bind_grab" ) ){
+      vg_input_string( &str, input_axis_list[k_sraxis_grab], 1 );
+   }
+   else if( MDL_CONST_PSTREQ( &menu.model, pstr, "bind_grab_mod" ) ){
+      vg_input_string( &str, input_joy_list[k_srjoystick_grab], 1 );
+   }
+   else
+      vg_strcat( &str, "error" );
+}
diff --git a/menu.h b/menu.h
index e8d94748133be9e2343890c06140d6bbdca569ec..65fba46d7b465829f19b5830413d7cf94932203b 100644 (file)
--- a/menu.h
+++ b/menu.h
@@ -1,18 +1,11 @@
 #pragma once
-#include "model.h"
-#include "world_render.h"
-#include "player.h"
-#include "shaders/model_menu.h"
-#include "audio.h"
-#include "input.h"
-#include "workshop.h"
-#include "world_map.h"
-#include "gui.h"
-#include "ent_miniworld.h"
-
 #define MENU_STACK_SIZE 8
 
-struct {
+#include "vg/vg_engine.h"
+#include "entity.h"
+
+struct global_menu
+{
    int credits_open;
    int disable_open;
 
@@ -43,7 +36,7 @@ struct {
    
    ent_menuitem *loc;
    ent_camera   *cam;
-   camera        view;
+   vg_camera     view;
 
    mdl_context model;
    GLuint *textures;
@@ -51,777 +44,11 @@ struct {
 
    mdl_array_ptr items, markers, cameras;
 }
-static menu;
-
-/*
- * Attaches memory locations to the various items in the menu
- */
-static void menu_link(void){
-   /* link data locations */
-   for( u32 i=0; i<mdl_arrcount(&menu.items); i++ ){
-      ent_menuitem *item = mdl_arritm( &menu.items, i );
-      
-      if( item->type == k_ent_menuitem_type_toggle ||
-          item->type == k_ent_menuitem_type_slider ){
-         
-         const char *name;
-
-         if( item->type == k_ent_menuitem_type_slider )
-            name = mdl_pstr( &menu.model, item->slider.pstr_data );
-         else
-            name = mdl_pstr( &menu.model, item->checkmark.pstr_data );
-         vg_var *var = vg_console_match_var( name );
-
-         if( var ){
-            if( ( item->type == k_ent_menuitem_type_slider && 
-                  var->data_type != k_var_dtype_f32
-                ) ||
-                ( item->type == k_ent_menuitem_type_toggle &&!
-                  ( var->data_type == k_var_dtype_i32 ||
-                    var->data_type == k_var_dtype_u32 
-                  )
-               )
-            ){
-               vg_error( "Cannot hook to data %s(%p), because it is type %d.\n",
-                           name, var, var->data_type );
-               item->pvoid = NULL;
-            }
-            else{
-               item->pvoid = var->data;
-            }
-         }
-         else{
-            vg_error( "No data named %s\n", name );
-            item->pvoid = NULL;
-         }
-      }
-      else{
-         item->pvoid = NULL;
-      }
-   }
-
-   /* link controllers */
-   menu.ctr_deck = NULL;
-   menu.ctr_kbm = NULL;
-   menu.ctr_ps = NULL;
-   menu.ctr_steam = NULL;
-   menu.ctr_xbox = NULL;
-
-   for( u32 i=0; i<mdl_arrcount(&menu.items); i++ ){
-      ent_menuitem *item = mdl_arritm( &menu.items, i );
-
-      if( MDL_CONST_PSTREQ( &menu.model, item->visual.pstr_name, "deck" ) )
-         menu.ctr_deck = item;
-      if( MDL_CONST_PSTREQ( &menu.model, item->visual.pstr_name, "kbm" ) )
-         menu.ctr_kbm = item;
-      if( MDL_CONST_PSTREQ( &menu.model, item->visual.pstr_name, "ps" ) )
-         menu.ctr_ps = item;
-      if( MDL_CONST_PSTREQ( &menu.model, item->visual.pstr_name, "steam" ) )
-         menu.ctr_steam = item;
-      if( MDL_CONST_PSTREQ( &menu.model, item->visual.pstr_name, "xbox" ) )
-         menu.ctr_xbox = item;
-   }
-}
-
-static void menu_close(void){
-   skaterift.activity = k_skaterift_default;
-   menu.page_depth = 0;
-   menu.page = 0xffffffff;
-   srinput.state = k_input_state_resume;
-}
-
-static void menu_init(void){
-   void *alloc = vg_mem.rtmemory;
-
-   mdl_open( &menu.model, "models/rs_menu.mdl", alloc );
-   mdl_load_metadata_block( &menu.model, alloc );
-
-   vg_linear_clear( vg_mem.scratch );
-
-   MDL_LOAD_ARRAY( &menu.model, &menu.items,   ent_menuitem, alloc );
-   MDL_LOAD_ARRAY( &menu.model, &menu.markers, ent_marker, alloc );
-   MDL_LOAD_ARRAY( &menu.model, &menu.cameras, ent_camera, alloc );
-
-   u32 count = mdl_arrcount( &menu.model.textures );
-   menu.textures = vg_linear_alloc(alloc,vg_align8(sizeof(GLuint)*(count+1)));
-   menu.textures[0] = vg.tex_missing;
-
-   mdl_async_load_glmesh( &menu.model, &menu.mesh, NULL );
-
-   for( u32 i=0; i<count; i ++ ){
-      vg_linear_clear( vg_mem.scratch );
-      menu.textures[i+1] = vg.tex_missing;
-
-      mdl_texture *tex = mdl_arritm( &menu.model.textures, i );
-      void *data = vg_linear_alloc( vg_mem.scratch, tex->file.pack_size );
-      mdl_fread_pack_file( &menu.model, &tex->file, data );
-      vg_tex2d_load_qoi_async( data, tex->file.pack_size, 
-                               VG_TEX2D_LINEAR|VG_TEX2D_CLAMP,
-                               &menu.textures[i+1] );
-   }
-
-   mdl_close( &menu.model );
-   shader_model_menu_register();
-}
-
-/*
- * Drop back a page until we're at the bottom which then we jus quit
- */
-static void menu_back_page(void){
-   menu.page_depth --;
-   if( menu.page_depth == 0 ){
-      menu_close();
-   }
-   else{
-      menu.page = menu.page_stack[ menu.page_depth ].page;
-      menu.cam = menu.page_stack[ menu.page_depth ].cam;
-
-      if( menu.input_mode == k_menu_input_mode_keys )
-         menu.loc = menu.page_stack[ menu.page_depth ].loc;
-      else menu.loc = NULL;
-   }
-}
-
-/*
- * Open page to the string identifier
- */
-static void menu_open_page( const char *name, 
-                            enum ent_menuitem_stack_behaviour stackmode ){
-   srinput.state = k_input_state_resume;
-   if( stackmode == k_ent_menuitem_stack_append ){
-      if( menu.page_depth >= MENU_STACK_SIZE )
-         vg_fatal_error( "Stack overflow\n" );
-   }
-   else{
-      if( menu.page_depth == 0 )
-         vg_fatal_error( "Stack underflow\n" );
-   }
-
-   u32 hash = vg_strdjb2( name );
-   for( u32 i=0; i<mdl_arrcount(&menu.items); i++ ){
-      ent_menuitem *item = mdl_arritm( &menu.items, i );
-      
-      if( item->type == k_ent_menuitem_type_page ){
-         if( mdl_pstreq( &menu.model, item->page.pstr_name, name, hash ) ){
-            u32 new_page = __builtin_ctz( item->groups );
-
-            if( new_page == menu.page ){
-               if( stackmode != k_ent_menuitem_stack_replace )
-                  menu_back_page();
-            }
-            else{
-               menu.page_stack[ menu.page_depth ].page = menu.page;
-               menu.page_stack[ menu.page_depth ].cam = menu.cam;
-               menu.page_stack[ menu.page_depth ].loc = menu.loc;
-               
-               if( stackmode == k_ent_menuitem_stack_append )
-                  menu.page_depth ++;
-
-               menu.page = __builtin_ctz( item->groups );
-
-               if( menu.input_mode == k_menu_input_mode_keys ){
-                  if( item->page.id_entrypoint ){
-                     u32 id = mdl_entity_id_id( item->page.id_entrypoint );
-                     menu.loc = mdl_arritm( &menu.items, id );
-                  }
-               }
-
-               if( item->page.id_viewpoint ){
-                  u32 id = mdl_entity_id_id( item->page.id_viewpoint );
-                  menu.cam = mdl_arritm( &menu.cameras, id );
-               }
-            }
-            return;
-         }
-      }
-   }
-}
-
-/*
- * activate a pressable type
- */
-static void menu_trigger_item( ent_menuitem *item ){
-   if     ( item->type == k_ent_menuitem_type_event_button ){
-      u32 q = item->button.pstr;
-
-      if( MDL_CONST_PSTREQ( &menu.model, q, "quit" ) ){
-         vg.window_should_close = 1;
-      }
-      else if( MDL_CONST_PSTREQ( &menu.model, q, "map" ) ){
-         menu_close();
-         world_map_enter();
-      }
-      else if( MDL_CONST_PSTREQ( &menu.model, q, "hub" ) ){
-         if( world_static.active_instance == k_world_purpose_client ){
-            menu_close();
-            ent_miniworld_goback();
-         }
-      }
-      else if( MDL_CONST_PSTREQ( &menu.model, q, "credits" ) ){
-         menu.credits_open = 1;
-      }
-      else if( MDL_CONST_PSTREQ( &menu.model, q, "workshop" ) ){
-         workshop_submit_command(0,NULL);
-      }
-      else if( MDL_CONST_PSTREQ( &menu.model, q, "engine" ) ){
-         vg_settings_open();
-      }
-      else if( MDL_CONST_PSTREQ( &menu.model, q, "prem_store" ) ){
-         if( steam_ready )
-            SteamAPI_ISteamFriends_ActivateGameOverlayToStore( 
-                  SteamAPI_SteamFriends(), 2103940, k_EOverlayToStoreFlag_None);
-      }
-      else if( MDL_CONST_PSTREQ( &menu.model, q, "prem_nevermind" ) ){
-         menu_close();
-      }
-   }
-   else if( item->type == k_ent_menuitem_type_page_button ){
-      menu_open_page( mdl_pstr( &menu.model, item->button.pstr ),
-                      item->button.stack_behaviour );
-   }
-   else if( item->type == k_ent_menuitem_type_toggle ){
-      if( item->pi32 ){
-         *item->pi32 = *item->pi32 ^ 0x1;
-      }
-   }
-}
-
-static f32 menu_slider_snap( f32 value, f32 old, f32 notch ){
-   f32 const k_epsilon = 0.0125f;
-
-   if( fabsf(notch-value) < k_epsilon ){
-      if( fabsf(notch-old) > k_epsilon ){
-         audio_lock();
-         audio_oneshot( &audio_ui[0], 1.0f, 0.0f );
-         audio_unlock();
-      }
-
-      return notch;
-   }
-   else
-      return value;
-}
-
-static void menu_setitem_type( ent_menuitem *item, 
-                               enum ent_menuitem_type type ){
-   if( !item ) return;
-   item->type = type;
-}
-
-/* 
- * Run from vg_gui every frame
- */
-static void menu_update(void){
-   if( workshop_form.page != k_workshop_form_hidden ){
-      return;
-   }
-
-   int escape = button_down( k_srbind_mback );
-   if( menu.credits_open || vg.settings_open ){
-      if( escape ){
-         menu.credits_open = 0;
-
-         if( vg.settings_open )
-            vg_settings_close();
-      }
-      return;
-   }
-
-   if( button_down( k_srbind_mopen ) ){
-      if( skaterift.activity == k_skaterift_default ){
-         skaterift.activity = k_skaterift_menu;
-         menu.page = 0xffffffff;
-         menu_open_page( "Main Menu", k_ent_menuitem_stack_append );
-         return;
-      }
-   }
-
-   if( skaterift.activity != k_skaterift_menu ) return;
-   enum menu_input_mode prev_mode = menu.input_mode;
-
-   /* get buttons inputs
-    * -------------------------------------------------------------------*/
-   int ml = button_down( k_srbind_mleft ),
-       mr = button_down( k_srbind_mright ),
-       mu = button_down( k_srbind_mup ),
-       md = button_down( k_srbind_mdown ),
-       mh = ml-mr,
-       mv = mu-md,
-       enter = button_down( k_srbind_maccept );
-
-   if( mh||mv||enter ){
-      menu.input_mode = k_menu_input_mode_keys;
-   }
-
-   /* get mouse inputs 
-    * --------------------------------------------------------------------*/
-   menu.mouse_dist += v2_length( vg.mouse_delta ); /* TODO: Move to UI */
-   menu.mouse_track += vg.time_frame_delta;
-   if( menu.mouse_track > 0.1f ){
-      menu.mouse_track = fmodf( menu.mouse_track, 0.1f );
-      if( menu.mouse_dist > 10.0f ){
-         menu.input_mode = k_menu_input_mode_mouse;
-         menu.mouse_dist = 0.0f;
-      }
-   }
-
-   if( ui_clicking(UI_MOUSE_LEFT) || ui_clicking(UI_MOUSE_RIGHT) ){
-      menu.input_mode = k_menu_input_mode_mouse;
-   }
-
-   if( menu.input_mode == k_menu_input_mode_mouse ){
-      /* 
-       * handle mouse input
-       * ------------------------------------------------------------*/
-      vg_ui.wants_mouse = 1;
-
-      /* 
-       * this raycasting is super cumbersome because all the functions were 
-       * designed for other purposes. we dont care though.
-       */
-      m4x4f inverse;
-      m4x4_inv( menu.view.mtx.p, inverse );
-      v4f coords;
-      coords[0] = vg_ui.mouse[0];
-      coords[1] = vg.window_y - vg_ui.mouse[1];
-      v2_div( coords, (v2f){ vg.window_x, vg.window_y }, coords );
-      v2_muls( coords, 2.0f, coords );
-      v2_add( coords, (v2f){-1.0f,-1.0f}, coords );
-      coords[2] = 1.0f;
-      coords[3] = 1.0f;
-      m4x4_mulv( inverse, coords, coords );
-      v3f ray;
-      m3x3_mulv( menu.view.transform, coords, ray );
-      v3_normalize( ray );
-
-      if( menu.loc && (menu.loc->type == k_ent_menuitem_type_slider) &&
-          ui_clicking(UI_MOUSE_LEFT) && menu.loc->pf32 ){
-
-         u32 il = mdl_entity_id_id( menu.loc->slider.id_min ),
-             ir = mdl_entity_id_id( menu.loc->slider.id_max );
-         ent_marker *ml = mdl_arritm( &menu.markers, il ),
-                    *mr = mdl_arritm( &menu.markers, ir );
-
-         v3f q2;
-         v3_muladds( menu.view.pos, ray, 100.0f, q2 );
-
-         f32 s,t;
-         v3f c1, c2;
-         v3f p1, q1, v0;
-         v3_sub( mr->transform.co, ml->transform.co, v0 );
-         v3_muladds( ml->transform.co, v0, -1.0f, p1 );
-         v3_muladds( mr->transform.co, v0,  1.0f, q1 );
-         closest_segment_segment( p1, q1, menu.view.pos, q2, &s,&t, c1,c2 );
-
-         s-=(1.0f/3.0f);
-         s/=(1.0f/3.0f);
-
-         if( ui_click_down(UI_MOUSE_LEFT) ){
-            menu.slider_offset = *menu.loc->pf32 - s;
-         }
-
-         f32 newvalue = vg_clampf( s+menu.slider_offset, 0.0f, 1.0f );
-
-         newvalue = menu_slider_snap( newvalue, *menu.loc->pf32, 0.00f );
-         newvalue = menu_slider_snap( newvalue, *menu.loc->pf32, 1.00f );
-         newvalue = menu_slider_snap( newvalue, *menu.loc->pf32, 0.25f );
-         newvalue = menu_slider_snap( newvalue, *menu.loc->pf32, 0.50f );
-         newvalue = menu_slider_snap( newvalue, *menu.loc->pf32, 0.75f );
-
-         *menu.loc->pf32 = newvalue;
-         return;
-      }
-
-      ent_menuitem *hit_item = NULL;
-
-      for( u32 i=0; i<mdl_arrcount(&menu.items); i++ ){
-         ent_menuitem *item = mdl_arritm( &menu.items, i );
-
-         if( item->type == k_ent_menuitem_type_page ) continue;
-         if( (item->type == k_ent_menuitem_type_visual) ||
-             (item->type == k_ent_menuitem_type_visual_nocol) ) continue;
-         if( item->type == k_ent_menuitem_type_binding ) continue;
-         if( !(item->groups & (0x1<<menu.page)) ) continue;
-
-         ent_menuitem *ray_item = item;
-
-         if( item->type == k_ent_menuitem_type_slider ){
-            u32 subtarget = mdl_entity_id_id( item->slider.id_handle );
-            ray_item = mdl_arritm( &menu.items, subtarget );
-         }
-         
-         v3f local_ray,
-             local_co;
-
-         m4x3f inverse_mtx;
-         mdl_transform_m4x3( &ray_item->transform, inverse_mtx );
-         m4x3_invert_full( inverse_mtx, inverse_mtx );
-         
-         m4x3_mulv( inverse_mtx, menu.view.transform[3], local_co );
-         m3x3_mulv( inverse_mtx, ray, local_ray );
-         v3_normalize( local_ray );
-         
-         local_ray[0] = 1.0f/local_ray[0];
-         local_ray[1] = 1.0f/local_ray[1];
-         local_ray[2] = 1.0f/local_ray[2];
-
-         for( u32 j=0; j<ray_item->submesh_count; j++ ){
-            mdl_submesh *sm = mdl_arritm( &menu.model.submeshs, 
-                                           ray_item->submesh_start + j );
-            if( ray_aabb1( sm->bbx, local_co, local_ray, 1000.0f ) ){
-               hit_item = item;
-               break;
-            }
-         }
-      }
-
-      if( hit_item != menu.loc ){
-         menu.loc = hit_item;
-      }
-
-      if( escape ){
-         menu_back_page();
-      }
-      else if( menu.loc ){
-         if( ui_click_down( UI_MOUSE_LEFT ) ){
-            menu_trigger_item( menu.loc );
-         }
-      }
-   }
-   else if( menu.input_mode == k_menu_input_mode_keys ){
-      /* 
-       * handle button input
-       * ------------------------------------------------------------*/
-      if( (prev_mode != k_menu_input_mode_keys) && !menu.loc ){
-         for( u32 i=0; i<mdl_arrcount(&menu.items); i++ ){
-            ent_menuitem *item = mdl_arritm( &menu.items, i );
-            
-            if( (item->type != k_ent_menuitem_type_page) &&
-                (item->type != k_ent_menuitem_type_visual) &&
-                (item->type != k_ent_menuitem_type_visual_nocol) &&
-                (item->groups & (0x1<<menu.page)) ){
-               menu.loc = item;
-            }
-         }
-      }
-
-      if( !menu.loc ) vg_fatal_error( "No location\n" );
-
-      if( menu.loc->type == k_ent_menuitem_type_slider && menu.loc->pf32 ){
-         f32 move = 0.0f;
-
-         if( vg_input.display_input_method == k_input_method_controller ){
-            move += button_press( k_srbind_mright );
-            move -= button_press( k_srbind_mleft );
-         }
-         else{
-            move += axis_state( k_sraxis_mbrowse_h );
-         }
-
-         move *= vg.time_frame_delta;
-         *menu.loc->pf32 = vg_clampf( *menu.loc->pf32 + move, 0.0f, 1.0f );
-
-         mh = 0;
-      }
-      
-      if( escape ){
-         menu_back_page();
-      }
-      else if( enter ){
-         menu_trigger_item( menu.loc );
-      }
-      else if( mh||mv ){
-         v3f opt; 
-         v3_zero( opt );
-         f32 best = 0.707f;
-         ent_menuitem *nextpos = NULL;
-
-         opt[0] += mh;
-         opt[2] += mv;
-         mdl_transform_vector( &menu.cam->transform, opt, opt );
-
-         for( u32 i=0; i<4; i++ ){
-            u32 id = menu.loc->id_links[i];
-            if( !id ) continue;
-            u32 index = mdl_entity_id_id( id );
-
-            ent_menuitem *other = mdl_arritm( &menu.items, index );
-            v3f delta;
-            v3_sub( menu.loc->transform.co, other->transform.co, delta );
-            v3_normalize( delta );
-
-            f32 score = v3_dot( delta, opt );
-            if( score > best ){
-               best = score;
-               nextpos = other;
-            }
-         }
-
-         if( nextpos ){
-            menu.loc = nextpos;
-         }
-      }
-   }
-
-   menu_setitem_type( menu.ctr_deck, k_ent_menuitem_type_disabled );
-   menu_setitem_type( menu.ctr_ps, k_ent_menuitem_type_disabled );
-   menu_setitem_type( menu.ctr_kbm, k_ent_menuitem_type_disabled );
-   menu_setitem_type( menu.ctr_xbox, k_ent_menuitem_type_disabled );
-   menu_setitem_type( menu.ctr_steam, k_ent_menuitem_type_disabled );
-
-   if( vg_input.display_input_method == k_input_method_kbm )
-      menu_setitem_type( menu.ctr_kbm, k_ent_menuitem_type_visual_nocol );
-   else{
-      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 ){
-         menu_setitem_type( menu.ctr_ps, k_ent_menuitem_type_visual_nocol );
-      }
-      else {
-         menu_setitem_type( menu.ctr_xbox, k_ent_menuitem_type_visual_nocol );
-      }
-      /* FIXME: Steam/Deck controller detection? */
-   }
-}
-
-static void menu_binding_string( char buf[128], u32 pstr );
-
-/*
- * Run from vg_gui when active
- */
-static void menu_render(void){
-   glEnable(GL_BLEND);
-   glDisable(GL_DEPTH_TEST);
-   glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
-   glBlendEquation(GL_FUNC_ADD);
-
-   shader_blitcolour_use();
-   v4f colour;
-   ui_hex_to_norm( ui_colour( k_ui_bg+3 ), colour );
-   colour[3] = 0.5f;
-
-   shader_blitcolour_uColour( colour );
-   render_fsquad();
-
-   if( (workshop_form.page != k_workshop_form_hidden) ||
-       (vg_ui.focused_control_type != k_ui_control_none) ){
-      return;
-   }
-
-   if( vg.settings_open )
-      return;
-
-   if( menu.credits_open ){
-      ui_rect panel = { 0,0, 460, 400 },
-              screen = { 0,0, vg.window_x,vg.window_y };
-      ui_rect_center( screen, panel );
-      ui_fill( panel, ui_colour(k_ui_bg) );
-      ui_outline( panel, 1, ui_colour(k_ui_fg), 0 );
-      ui_rect_pad( panel, (ui_px[]){8,8} );
-
-      ui_rect title;
-      ui_split( panel, k_ui_axis_h, 28*2, 0, title, panel );
-      ui_text( title, "Skate Rift - Credits", 2, k_ui_align_middle_center, 0 );
-      ui_split( panel, k_ui_axis_h, 28, 0, title, panel );
-      ui_text( title, "Mt.Zero Software", 1, k_ui_align_middle_center, 0 );
-
-      ui_split( panel, k_ui_axis_h, 8, 0, title, panel );
-      ui_split( panel, k_ui_axis_h, 28*2, 0, title, panel );
-      ui_text( title, "Free Software", 2, k_ui_align_middle_center, 0 );
-
-      ui_split( panel, k_ui_axis_h, 8, 0, title, panel );
-      ui_text( panel, 
-            "Sam Lantinga       - SDL2 - libsdl.org\n"
-            "Hunter WB          - Anyascii\n"
-            "David Herberth     - GLAD\n"
-            "Dominic Szablewski - QOI - qoiformat.org\n"
-            "Sean Barrett       - stb_image,stb_vorbis,stb_include\n"
-            "Khronos Group      - OpenGL\n"
-            , 1, k_ui_align_left, 0 );
-      return;
-   }
-
-   glEnable( GL_DEPTH_TEST );
-   glDisable( GL_BLEND );
-
-   f32 rate = vg.time_frame_delta * 12.0f;
-
-   if( menu.cam ){
-      camera target;
-
-      target.fov = menu.cam->fov;
-      v3_copy( menu.cam->transform.co, target.pos );
-
-      v3f v0;
-      mdl_transform_vector( &menu.cam->transform, (v3f){0.0f,-1.0f,0.0f}, v0 );
-      v3_angles( v0, target.angles );
-
-      camera_lerp( &menu.view, &target, rate, &menu.view );
-
-      menu.view.farz = 150.0f;
-      menu.view.nearz = 0.01f;
-
-      camera_update_transform( &menu.view );
-      camera_update_view( &menu.view );
-      camera_update_projection( &menu.view );
-      camera_finalize( &menu.view );
-   }
-   else return;
-
-   shader_model_menu_use();
-   shader_model_menu_uTexMain( 1 );
-   shader_model_menu_uPv( menu.view.mtx.pv );
-   shader_model_menu_uPvmPrev( menu.view.mtx_prev.pv );
-
-   mesh_bind( &menu.mesh );
-
-   v4f white, blue;
-
-   ui_hex_to_norm( ui_colour( k_ui_fg ), white );
-   ui_hex_to_norm( ui_colour( k_ui_orange+k_ui_brighter ), blue );
-
-   ent_menuitem *text_list[ 8 ];
-   u32 text_count = 0;
-
-   u32 current_tex = 0xffffffff;
-
-   for( u32 i=0; i<mdl_arrcount(&menu.items); i++ ){
-      ent_menuitem *item = mdl_arritm( &menu.items, i );
-
-      if(   item->type == k_ent_menuitem_type_disabled ) continue;
-      if(   item->type == k_ent_menuitem_type_page ) continue;
-      if( !(item->groups & (0x1 << menu.page)) ) continue;
-
-      if(   item->type == k_ent_menuitem_type_binding ){
-         if( text_count < vg_list_size(text_list) )
-            text_list[ text_count ++ ] = item;
-         else
-            vg_fatal_error( "Text list overflow" );
-
-         continue;  
-      }
-
-      int selected = 0;
-      
-      if( menu.loc ){
-         if( menu.loc->type == k_ent_menuitem_type_slider ){
-            u32 subid = menu.loc->slider.id_handle;
-            if( item == mdl_arritm( &menu.items, mdl_entity_id_id(subid) ))
-               selected = 1;
-         }
-         else{
-            if( item == menu.loc )
-               selected = 1;
-         }
-      }
-
-      if( item->type == k_ent_menuitem_type_visual_nocol ){
-         shader_model_menu_uColour( (v4f){1.0f,1.0f,1.0f,1.0f} );
-      }
-      else{
-         v4f colour;
-         item->factive = vg_lerpf( item->factive, selected, rate );
-         v4_lerp( white, blue, item->factive, colour );
-         shader_model_menu_uColour( colour );
-      }
-
-      f32 scale = 1.0f+item->factive*0.1f;
-
-      m4x3f mmdl;
-      mdl_transform transform = item->transform;
-      v3_muls( transform.s, scale, transform.s );
-      mdl_transform_m4x3( &transform, mmdl );
-
-      if( item->type == k_ent_menuitem_type_toggle && item->pi32 ){
-         u32 subid = mdl_entity_id_id( item->checkmark.id_check );
-         ent_menuitem *subitem = mdl_arritm( &menu.items, subid );
-
-         v3_muladds( item->transform.co, item->checkmark.offset, scale,
-                     subitem->transform.co );
-
-         subitem->fvisible = vg_lerpf( subitem->fvisible, *item->pi32, rate );
-         v3_fill( subitem->transform.s, subitem->fvisible );
-      }
-      else if( item->type == k_ent_menuitem_type_slider && item->pf32 ){
-         u32 il = mdl_entity_id_id( item->slider.id_min ),
-             ir = mdl_entity_id_id( item->slider.id_max ),
-             ih = mdl_entity_id_id( item->slider.id_handle );
-         ent_marker *ml = mdl_arritm( &menu.markers, il ),
-                    *mr = mdl_arritm( &menu.markers, ir );
-         ent_menuitem *handle = mdl_arritm( &menu.items, ih );
-
-         v3_lerp( ml->transform.co, mr->transform.co, *item->pf32,
-                  handle->transform.co );
-      }
-
-      shader_model_menu_uMdl( mmdl );
-
-      for( u32 j=0; j<item->submesh_count; j++ ){
-         u32 index = item->submesh_start + j;
-         mdl_submesh *sm = mdl_arritm( &menu.model.submeshs, index );
-         
-         mdl_material *mat = mdl_arritm( &menu.model.materials, 
-                                         sm->material_id-1 );
-
-         if( mat->tex_diffuse != current_tex ){
-            glActiveTexture( GL_TEXTURE1 );
-            glBindTexture( GL_TEXTURE_2D, menu.textures[ mat->tex_diffuse ] );
-            current_tex = mat->tex_diffuse;
-         }
-
-         mdl_draw_submesh( sm );
-      }
-   }
-
-   if( !text_count ) return;
-
-   char buf[ 128 ];
-
-   m4x3f local;
-   m4x3_identity( local );
-
-   font3d_bind( &gui.font, k_font_shader_default, 0, NULL, &menu.view );
-   for( u32 i=0; i<text_count; i++ ){
-      ent_menuitem *item = text_list[ i ];
-      m4x3f transform;
-      mdl_transform_m4x3( &item->transform, transform );
-
-      u32 variant = item->binding.font_variant;
-      menu_binding_string( buf, item->binding.pstr_bind );
-      f32 offset = font3d_string_width( variant, buf );
-
-      local[3][0] = -0.5f * offset;
-      m4x3_mul( transform, local, transform );
-
-      font3d_simple_draw( variant, buf, &menu.view, transform );
-   }
-}
-
-static void menu_binding_string( char buf[128], u32 pstr ){
-   vg_str str;
-   vg_strnull( &str, buf, 128 );
-
-   if( MDL_CONST_PSTREQ( &menu.model, pstr, "bind_jump" ) ){
-      vg_input_string( &str, input_button_list[k_srbind_jump], 1 );
-   }
-   else if( MDL_CONST_PSTREQ( &menu.model, pstr, "bind_trick0" ) ){
-      vg_strcat( &str, "SHUVIT " );
-      vg_input_string( &str, input_button_list[k_srbind_trick0], 1 );
-   }
-   else if( MDL_CONST_PSTREQ( &menu.model, pstr, "bind_trick1" ) ){
-      vg_strcat( &str, "KICKFLIP " );
-      vg_input_string( &str, input_button_list[k_srbind_trick1], 1 );
-   }
-   else if( MDL_CONST_PSTREQ( &menu.model, pstr, "bind_trick2" ) ){
-      vg_strcat( &str, "TREFLIP " );
-      vg_input_string( &str, input_button_list[k_srbind_trick2], 1 );
-   }
-   else if( MDL_CONST_PSTREQ( &menu.model, pstr, "bind_grab" ) ){
-      vg_input_string( &str, input_axis_list[k_sraxis_grab], 1 );
-   }
-   else if( MDL_CONST_PSTREQ( &menu.model, pstr, "bind_grab_mod" ) ){
-      vg_input_string( &str, input_joy_list[k_srjoystick_grab], 1 );
-   }
-   else
-      vg_strcat( &str, "error" );
-}
+extern menu;
+void menu_close(void);
+void menu_init(void);
+void menu_open_page( const char *name, 
+                     enum ent_menuitem_stack_behaviour stackmode );
+void menu_link(void);
+void menu_update(void);
+void menu_render(void);
diff --git a/model.h b/model.h
index 63e6e7f5ebf84b31a28b5e1e39dd4205fae37092..bc0ab66f5ab2e5a0da5cafd898161e74ad92526e 100644 (file)
--- a/model.h
+++ b/model.h
@@ -4,8 +4,6 @@
 
 #pragma once
 
-#include "skaterift.h"
-
 #include "vg/vg_io.h"
 #include "vg/vg_async.h"
 #include "vg/vg_tex.h"
index 4d55707fbeb0feee105fba803aed7e9ff407fee1..74e03bf720187fe7dc2cd85393ba0dd0d01a82f4 100644 (file)
--- a/network.c
+++ b/network.c
@@ -1,3 +1,8 @@
+#include "skaterift.h"
+#include "vg/vg_steam.h"
+#include "vg/vg_steam_networking.h"
+#include "vg/vg_steam_auth.h"
+#include "vg/vg_steam_friends.h"
 #include "player.h"
 #include "network.h"
 #include "network_msg.h"
 #include "gui.h"
 #include "ent_region.h"
 
+struct network_client network_client =
+{
+   .auth_mode = eServerModeAuthentication,
+   .state = k_ESteamNetworkingConnectionState_None,
+   .server_adress = "46.101.34.155",
+   .last_intent_change = -99999.9
+};
+
 static void scores_update(void);
 
-static int packet_minsize( SteamNetworkingMessage_t *msg, u32 size ){
+int packet_minsize( SteamNetworkingMessage_t *msg, u32 size ){
    if( msg->m_cbSize < size ) {
       vg_error( "Invalid packet size (must be at least %u)\n", size );
       return 0;
@@ -79,7 +92,8 @@ static void network_send_username(void){
          k_nSteamNetworkingSend_Reliable, NULL );
 }
 
-static void network_send_region(void){
+void network_send_region(void)
+{
    if( !network_connected() )
       return;
    
@@ -159,9 +173,9 @@ static void network_scoreboard_callback( netmsg_request *res, vg_msg *body,
  *   .
  *   10+ specific week index
  */
-static void network_request_scoreboard( const char *mod_uid, 
-                                        const char *route_uid,
-                                        u32 week, u64 userdata ){
+void network_request_scoreboard( const char *mod_uid, 
+                                 const char *route_uid,
+                                 u32 week, u64 userdata ){
    if( !network_connected() ) 
       return;
 
@@ -184,8 +198,8 @@ static void network_publish_callback( netmsg_request *res, vg_msg *body,
    }
 }
 
-static void network_publish_laptime( const char *mod_uid, 
-                                     const char *route_uid, f64 lap_time ){
+void network_publish_laptime( const char *mod_uid, 
+                              const char *route_uid, f64 lap_time ){
    if( !network_connected() )
       return;
 
@@ -234,7 +248,8 @@ static void network_request_rx_300_400( SteamNetworkingMessage_t *msg ){
    }
 }
 
-static void network_send_item( enum netmsg_playeritem_type type ){
+void network_send_item( enum netmsg_playeritem_type type )
+{
    if( !network_connected() )
       return;
 
@@ -297,7 +312,8 @@ static void network_disconnect(void){
    }
 }
 
-static void network_status_string( vg_str *str, u32 *colour ){
+void network_status_string( vg_str *str, u32 *colour )
+{
    if( skaterift.demo_mode ){
       vg_strcat( str, "Offline" );
       return;
@@ -344,7 +360,8 @@ static void network_status_string( vg_str *str, u32 *colour ){
    }
 }
 
-static void render_server_status_gui(void){
+void render_server_status_gui(void)
+{
    render_fb_bind( gpipeline.fb_workshop_preview, 0 );
 
    /* HACK */
@@ -535,7 +552,8 @@ static void poll_remote_connection(void){
    }
 }
 
-static void network_update(void){
+void network_update(void)
+{
    if( !steam_ready )
       return;
 
@@ -582,7 +600,8 @@ static void network_update(void){
    }
 }
 
-static void chat_send_message( const char *message ){
+void chat_send_message( const char *message )
+{
    if( !network_connected() ){
       return;
    }
@@ -616,7 +635,8 @@ static int cmd_network_send_message( int argc, const char *argv[] ){
    return 0;
 }
 
-static void network_init(void){
+void network_init(void)
+{
    vg_console_reg_var( "network_info", &network_client.network_info,
                        k_var_dtype_i32, VG_VAR_PERSISTENT );
    if( steam_ready ){
@@ -642,7 +662,8 @@ static void network_init(void){
    }
 }
 
-static void network_end(void){
+void network_end(void)
+{
    /* TODO: Send buffered highscores that were not already */
    if( (network_client.state == k_ESteamNetworkingConnectionState_Connected) ||
        (network_client.state == k_ESteamNetworkingConnectionState_Connecting) )
index 08a989b3b1edf2f1c627e80b54461f191a1de472..7500c8800552619d94af1d6ac33e20473aad4e3f 100644 (file)
--- a/network.h
+++ b/network.h
@@ -3,10 +3,9 @@
  * All trademarks are property of their respective owners
  */
 
-#ifndef NETWORK_H
-#define NETWORK_H
-
+#pragma once
 #include "vg/vg_platform.h"
+#include "vg/vg_steam_networking.h"
 #include "steam.h"
 #include "network_common.h"
 #include "network_msg.h"
  */
 
 /* Call it at start; Connects us to the gameserver */
-static void network_init(void);
+void network_init(void);
 
 /* Run this from main loop */
-static void network_update(void);
+void network_update(void);
 
 /* Call it at shutdown */
-static void network_end(void);
+void network_end(void);
 
 /* 
  * Can buffer up a bunch of these by calling many times, they will be
  * sent at the next connection 
  */
-static void network_submit_highscore( u32 trackid, u16 points, u16 time );
+void network_submit_highscore( u32 trackid, u16 points, u16 time );
 
 /*
  * Game endpoints are provided with the same names to allow running without a
  * network connection.
  */
 
-struct {
+struct network_client
+{
    u8 app_symmetric_key[ 1024 ];
    u32 app_key_length;
    EServerMode auth_mode;
@@ -71,28 +71,22 @@ struct {
    f64 last_intent_change;
    f32 fintent; /* yeah this shit really shouldnt be here but oh well */
 }
-static network_client = {
-   .auth_mode = eServerModeAuthentication,
-   .state = k_ESteamNetworkingConnectionState_None,
-   .server_adress = "46.101.34.155",
-   .last_intent_change = -99999.9
-};
-
-static int packet_minsize( SteamNetworkingMessage_t *msg, u32 size );
-static void network_send_item( enum netmsg_playeritem_type type );
-static void network_request_scoreboard( const char *mod_uid, 
-                                        const char *route_uid,
-                                        u32 week, u64 userdata );
-static void network_publish_laptime( const char *mod_uid, 
-                                     const char *route_uid, f64 lap_time );
-static void chat_send_message( const char *message );
-static void render_server_status_gui(void);
-static void network_status_string( vg_str *str, u32 *colour );
-static void network_send_region(void);
-
-static int network_connected(void){
+extern network_client;
+
+int packet_minsize( SteamNetworkingMessage_t *msg, u32 size );
+void network_send_item( enum netmsg_playeritem_type type );
+void network_request_scoreboard( const char *mod_uid, 
+                                 const char *route_uid,
+                                 u32 week, u64 userdata );
+void network_publish_laptime( const char *mod_uid, 
+                              const char *route_uid, f64 lap_time );
+void chat_send_message( const char *message );
+void render_server_status_gui(void);
+void network_status_string( vg_str *str, u32 *colour );
+void network_send_region(void);
+
+static inline int network_connected(void)
+{
    if( network_client.remote_version != NETWORK_SKATERIFT_VERSION ) return 0;
    return network_client.state == k_ESteamNetworkingConnectionState_Connected;
 }
-
-#endif /* NETWORK_H */
index 9c1f87e5e044f8674b4995cc4f6ee53367004c60..2e05a1923dc05a5d94560731832d94704a339b1f 100644 (file)
@@ -1,8 +1,22 @@
+#include "vg/vg_lines.h"
+#include "vg/vg_async.h"
 #include "particle.h"
-#include "shaders/trail.h"
+#include "shaders/particle.h"
+
+struct particle_system particles_grind = {
+   .scale = 0.02f,
+   .velocity_scale = 0.001f,
+   .width = 0.0125f
+},
+particles_env = {
+   .scale = 0.04f,
+   .velocity_scale = 0.001f,
+   .width = 0.25f
+};
 
-static void particle_spawn( particle_system *sys, 
-                            v3f co, v3f v, f32 lifetime, u32 colour ){
+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 ++ ];
@@ -12,9 +26,10 @@ static void particle_spawn( particle_system *sys,
    p->colour = colour;
 }
 
-static void particle_spawn_cone( particle_system *sys, 
-                                 v3f co, v3f dir, f32 angle, f32 speed, 
-                                 f32 lifetime, u32 colour ){
+void particle_spawn_cone( particle_system *sys, 
+                          v3f co, v3f dir, f32 angle, f32 speed, 
+                          f32 lifetime, u32 colour )
+{
    if( sys->alive == sys->max ) return;
 
    particle *p = &sys->array[ sys->alive ++ ];
@@ -33,7 +48,8 @@ static void particle_spawn_cone( particle_system *sys,
    v3_copy( co, p->co );
 }
 
-static void particle_system_update( particle_system *sys, f32 dt ){
+void particle_system_update( particle_system *sys, f32 dt )
+{
    u32 i = 0;
 iter: if( i == sys->alive ) return;
 
@@ -52,7 +68,8 @@ iter: if( i == sys->alive ) return;
    goto iter;
 }
 
-static void particle_system_debug( particle_system *sys ){
+void particle_system_debug( particle_system *sys )
+{
    for( u32 i=0; i<sys->alive; i ++ ){
       particle *p = &sys->array[i];
       v3f p1;
@@ -95,11 +112,8 @@ static void async_particle_init( void *payload, u32 size ){
    VG_CHECK_GL_ERR();
 }
 
-static void particle_init(void){
-   shader_particle_register();
-}
-
-static void particle_alloc( particle_system *sys, u32 max ){
+void particle_alloc( particle_system *sys, u32 max )
+{
    size_t stride = sizeof(particle_vert);
 
    sys->max = max;
@@ -123,7 +137,8 @@ static void particle_alloc( particle_system *sys, u32 max ){
    vg_async_dispatch( call, async_particle_init );
 }
 
-static void particle_system_prerender( particle_system *sys ){
+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];
@@ -160,7 +175,8 @@ static void particle_system_prerender( particle_system *sys ){
    glBufferSubData( GL_ARRAY_BUFFER, 0, sys->alive*stride*4, sys->vertices );
 }
 
-static void particle_system_render( particle_system *sys, camera *cam ){
+void particle_system_render( particle_system *sys, vg_camera *cam )
+{
    glDisable( GL_CULL_FACE );
    glEnable( GL_DEPTH_TEST );
 
index fb4d27f1bbdff659cdfe76bb12d1e5d170f9dfe2..6858890522fa7f5d183a632759e8f09498f4e699 100644 (file)
@@ -1,6 +1,4 @@
-#ifndef PARTICLE_H
-#define PARTICLE_H
-
+#pragma once
 #include "skaterift.h"
 
 typedef struct particle_system particle_system;
@@ -29,29 +27,16 @@ struct particle_system {
    /* render settings */
    f32 scale, velocity_scale, width;
 }
-static particles_grind = {
-   .scale = 0.02f,
-   .velocity_scale = 0.001f,
-   .width = 0.0125f
-},
-particles_env = {
-   .scale = 0.04f,
-   .velocity_scale = 0.001f,
-   .width = 0.25f
-};
-
-static void particle_alloc( particle_system *sys, u32 max );
-static void particle_system_update( particle_system *sys, f32 dt );
-static void particle_system_debug( particle_system *sys );
-static void particle_system_prerender( particle_system *sys );
-static void particle_system_render( particle_system *sys, camera *cam );
-
-static void particle_spawn( particle_system *sys, 
-                            v3f co, v3f v, f32 lifetime, u32 colour );
-static void particle_spawn_cone( particle_system *sys, 
-                                 v3f co, v3f dir, f32 angle, f32 speed, 
-                                 f32 lifetime, u32 colour );
-
-#include "shaders/particle.h"
-
-#endif /* PARTICLE_H */
+extern particles_grind, particles_env;
+
+void particle_alloc( particle_system *sys, u32 max );
+void particle_system_update( particle_system *sys, f32 dt );
+void particle_system_debug( particle_system *sys );
+void particle_system_prerender( particle_system *sys );
+void particle_system_render( particle_system *sys, vg_camera *cam );
+
+void particle_spawn( particle_system *sys, 
+                     v3f co, v3f v, f32 lifetime, u32 colour );
+void particle_spawn_cone( particle_system *sys, 
+                          v3f co, v3f dir, f32 angle, f32 speed, 
+                          f32 lifetime, u32 colour );
index 1d690a088bab23a0e39225d9561d8ed167f597ae..b11eacb1777618a4d66740358ebf939cec038b89 100644 (file)
--- a/player.c
+++ b/player.c
@@ -1,7 +1,5 @@
-#ifndef PLAYER_C
-#define PLAYER_C
-
 #include "player.h"
+#include "addon.h"
 #include "camera.h"
 #include "player_model.h"
 #include "input.h"
 #include "shaders/model_character_view.h"
 #include "shaders/model_board_view.h"
 
-static int localplayer_cmd_respawn( int argc, const char *argv[] ){
+#include "player_walk.h"
+#include "player_dead.h"
+#include "player_drive.h"
+#include "player_skate.h"
+#include "player_basic_info.h"
+#include "player_glide.h"
+
+i32 k_invert_y = 0;
+struct localplayer localplayer = 
+{
+   .rb = 
+   {
+      .co = { 0,0,0 },
+      .w = { 0,0,0 },
+      .v = { 0,0,0 },
+      .q = { 0,0,0,1 },
+      .to_world = M4X3_IDENTITY,
+      .to_local = M4X3_IDENTITY
+   }
+};
+
+struct player_subsystem_interface *player_subsystems[] = 
+{
+   [k_player_subsystem_walk]  = &player_subsystem_walk,
+   [k_player_subsystem_dead]  = &player_subsystem_dead,
+   [k_player_subsystem_drive] = &player_subsystem_drive,
+   [k_player_subsystem_skate] = &player_subsystem_skate,
+   [k_player_subsystem_basic_info]=&player_subsystem_basic_info,
+   [k_player_subsystem_glide] = &player_subsystem_glide,
+};
+
+int localplayer_cmd_respawn( int argc, const char *argv[] )
+{
    ent_spawn *rp = NULL, *r;
    world_instance *world = world_current_instance();
 
@@ -36,8 +66,10 @@ static int localplayer_cmd_respawn( int argc, const char *argv[] ){
    return 1;
 }
 
-static void player_init(void){
-   for( u32 i=0; i<vg_list_size(player_subsystems); i++ ){
+void player_init(void)
+{
+   for( u32 i=0; i<k_player_subsystem_max; i++ )
+   {
       struct player_subsystem_interface *sys = player_subsystems[i];
       if( sys->system_register ) sys->system_register();
    }
@@ -50,17 +82,16 @@ static void player_init(void){
    VG_VAR_F32( k_cam_shake_trackspeed );
    VG_VAR_I32( k_player_debug_info, flags=VG_VAR_PERSISTENT );
 
+#if 0
    vg_console_reg_var( "cinema", &k_cinema, k_var_dtype_f32, 0 );
    vg_console_reg_var( "cinema_fixed", &k_cinema_fixed, k_var_dtype_i32, 0 );
-   vg_console_reg_var( "invert_y", &k_invert_y, 
+#endif
+   vg_console_reg_var( "invert_y", &k_invert_y,
                         k_var_dtype_i32, VG_VAR_PERSISTENT );
-
-   shader_model_character_view_register();
-   shader_model_board_view_register();
-   shader_model_entity_register();
 }
 
-static void player__debugtext( int size, const char *fmt, ... ){
+void player__debugtext( int size, const char *fmt, ... )
+{
        char buffer[ 1024 ];
 
    va_list args;
@@ -76,15 +107,18 @@ static void player__debugtext( int size, const char *fmt, ... ){
  * Appearence
  */
 
-static void player__use_model( u16 reg_id ){
+void player__use_model( u16 reg_id )
+{
    addon_cache_unwatch( k_addon_type_player, 
                         localplayer.playermodel_view_slot );
    localplayer.playermodel_view_slot = 
       addon_cache_create_viewer( k_addon_type_player, reg_id );
 }
 
-static void player__bind(void){
-   for( u32 i=0; i<vg_list_size(player_subsystems); i++ ){
+void player__bind(void)
+{
+   for( u32 i=0; i<k_player_subsystem_max; i++ )
+   {
       struct player_subsystem_interface *sys = player_subsystems[i];
 
       if( sys->bind ) sys->bind();
@@ -96,7 +130,8 @@ static void player__bind(void){
  * ----------------------------------------------------------------------------
  */
 
-static void player__pre_update(void){
+void player__pre_update(void)
+{
    if( button_down( k_srbind_camera ) && !localplayer.immobile &&
        (localplayer.subsystem != k_player_subsystem_dead) ){
       if( localplayer.cam_control.camera_mode == k_cam_firstperson )
@@ -109,7 +144,8 @@ static void player__pre_update(void){
       player_subsystems[ localplayer.subsystem ]->pre_update();
 }
 
-static void player__update(void){
+void player__update(void)
+{
    if( player_subsystems[ localplayer.subsystem ]->update )
       player_subsystems[ localplayer.subsystem ]->update();
 
@@ -118,25 +154,25 @@ static void player__update(void){
       glider_physics( (v2f){0,0} );
 }
 
-static void player__post_update(void)
+void player__post_update(void)
 {
    struct player_subsystem_interface *sys = 
       player_subsystems[ localplayer.subsystem ];
 
    if( sys->post_update ) sys->post_update();
 
-   SDL_AtomicLock( &air_data.sl );
-   air_data.speed = v3_length( localplayer.rb.v ) * vg.time_rate;
-   SDL_AtomicUnlock( &air_data.sl );
+   SDL_AtomicLock( &air_audio_data.sl );
+   air_audio_data.speed = v3_length( localplayer.rb.v ) * vg.time_rate;
+   SDL_AtomicUnlock( &air_audio_data.sl );
 }
 
 /*
  * Applies gate transport to a player_interface
  */
-static void player__pass_gate( u32 id )
+void player__pass_gate( u32 id )
 {
    world_instance *world = world_current_instance();
-   skaterift_record_frame( &skaterift.replay, 1 );
+   skaterift_record_frame( &player_replay.local, 1 );
 
    /* update boundary hash (network animation) */
    u16 index = mdl_entity_id_id(id) & ~NETMSG_BOUNDARY_MASK;
@@ -163,7 +199,7 @@ static void player__pass_gate( u32 id )
       world_static.active_instance = gate->target;
       player__clean_refs();
 
-      replay_clear( &skaterift.replay );
+      replay_clear( &player_replay.local );
    }
    else 
    {
@@ -180,7 +216,7 @@ static void player__pass_gate( u32 id )
    audio_unlock();
 }
 
-static void player_apply_transport_to_cam( m4x3f transport )
+void player_apply_transport_to_cam( m4x3f transport )
 {
    /* Pre-emptively edit the camera matrices so that the motion vectors 
     * are correct */
@@ -197,7 +233,7 @@ static void player_apply_transport_to_cam( m4x3f transport )
    m4x4_mul( world_gates.cam.mtx.v,  transport_4, world_gates.cam.mtx.v );
 }
 
-static void player__im_gui(void)
+void player__im_gui(void)
 {
    if( !k_player_debug_info ) return;
 
@@ -246,14 +282,16 @@ static void player__im_gui(void)
    skaterift_replay_debug_info();
 }
 
-static void player__setpos( v3f pos ){
+void player__setpos( v3f pos )
+{
    v3_copy( pos, localplayer.rb.co );
    v3_zero( localplayer.rb.v );
    rb_update_matrices( &localplayer.rb );
 }
 
-static void player__clean_refs(void){
-   replay_clear( &skaterift.replay );
+void player__clean_refs(void)
+{
+   replay_clear( &player_replay.local );
    gui_helper_clear();
 
    world_static.challenge_target = NULL;
@@ -273,7 +311,8 @@ static void player__clean_refs(void){
    }
 }
 
-static void player__reset(void){
+void player__reset(void)
+{
    v3_zero( localplayer.rb.v );
    v3_zero( localplayer.rb.w );
    
@@ -295,23 +334,27 @@ static void player__reset(void){
    player__clean_refs();
 }
 
-static void player__spawn( ent_spawn *rp ){
+void player__spawn( ent_spawn *rp )
+{
    player__setpos( rp->transform.co );
    player__reset();
 }
 
 
-static void player__kill(void){
+void player__kill(void)
+{
 }
 
-static void player__begin_holdout( v3f offset ){
+void player__begin_holdout( v3f offset )
+{
    memcpy( &localplayer.holdout_pose, &localplayer.pose, 
             sizeof(localplayer.pose) );
    v3_copy( offset, localplayer.holdout_pose.root_co );
    localplayer.holdout_time = 1.0f;
 }
 
-static void net_sfx_exchange( bitpack_ctx *ctx, struct net_sfx *sfx ){
+void net_sfx_exchange( bitpack_ctx *ctx, struct net_sfx *sfx )
+{
    bitpack_bytes( ctx, 1, &sfx->system );
    bitpack_bytes( ctx, 1, &sfx->priority );
    bitpack_bytes( ctx, 1, &sfx->id );
@@ -320,7 +363,8 @@ static void net_sfx_exchange( bitpack_ctx *ctx, struct net_sfx *sfx ){
    bitpack_qv3f( ctx, 16, -1024.0f, 1024.0f, sfx->location );
 }
 
-static void net_sfx_play( struct net_sfx *sfx ){
+void net_sfx_play( struct net_sfx *sfx )
+{
    if( sfx->system < k_player_subsystem_max ){
       struct player_subsystem_interface *sys = player_subsystems[sfx->system];
       if( sys->sfx_oneshot ){
@@ -349,8 +393,9 @@ static struct net_sfx *find_lower_priority_sfx( struct net_sfx *buffer, u32 len,
    return p_sfx;
 }
 
-static void player__networked_sfx( u8 system, u8 priority, u8 id, 
-                                   v3f pos, f32 volume ){
+void player__networked_sfx( u8 system, u8 priority, u8 id, 
+                            v3f pos, f32 volume )
+{
    struct net_sfx sfx,
          *p_net = find_lower_priority_sfx( 
                localplayer.sfx_buffer, 4, 
@@ -375,19 +420,3 @@ static void player__networked_sfx( u8 system, u8 priority, u8 id,
 
    net_sfx_play( &sfx );
 }
-
-/* implementation */
-#include "player_common.c"
-
-#include "player_walk.c"
-#include "player_skate.c"
-#include "player_dead.c"
-#include "player_drive.c"
-#include "player_glide.c"
-#include "player_basic_info.c"
-
-#include "player_render.c"
-#include "player_ragdoll.c"
-#include "player_replay.c"
-
-#endif /* PLAYER_C */
index b2e910651204212a6035f0661e81bb3084ba7866..69da5094133bfcaff8afec76f7962d8d141ffccc 100644 (file)
--- a/player.h
+++ b/player.h
@@ -1,21 +1,5 @@
-#ifndef PLAYER_H
-#define PLAYER_H
-
-#include "skaterift.h"
-#include "player_common.h"
-#include "network_compression.h"
-#include "player_effects.h"
-
-enum player_subsystem{
-   k_player_subsystem_walk = 0,
-   k_player_subsystem_skate = 1,
-   k_player_subsystem_dead = 2,
-   k_player_subsystem_drive = 3,
-   k_player_subsystem_basic_info = 4,
-   k_player_subsystem_glide = 5,
-   k_player_subsystem_max,
-   k_player_subsystem_invalid = 255
-};
+#pragma once
+#include "vg/vg_platform.h"
 
 struct player_cam_controller {
    enum camera_mode{
@@ -36,6 +20,14 @@ struct player_cam_controller {
        cam_velocity_smooth;
 };
 
+#include "player_common.h"
+#include "network_compression.h"
+#include "player_effects.h"
+#include "player_api.h"
+#include "player_ragdoll.h"
+#include "player_model.h"
+#include "player_render.h"
+
 struct player_subsystem_interface{
    void(*system_register)(void);
    void(*bind)(void);
@@ -61,29 +53,12 @@ struct player_subsystem_interface{
    const char *name;
 };
 
-#include "player_ragdoll.h"
-#include "player_render.h"
-#include "player_model.h"
-
-/* subsystem headers */
-#include "player_walk.h"
-#include "player_skate.h"
-#include "player_dead.h"
-#include "player_drive.h"
-#include "player_glide.h"
-#include "player_basic_info.h"
-
-#include "player_replay.h"
-
 #define PLAYER_REWIND_FRAMES 60*4
 #define RESET_MAX_TIME 45.0
 
-static i32 k_cinema_fixed = 0;
-static f32 k_cinema       = 0.0f;
-static i32 k_invert_y     = 0;
-static f32 k_cam_dist     = 1.8f;
-
-struct {
+extern i32 k_invert_y;
+struct localplayer
+{
    /* transform definition */
    rigidbody rb;
    v3f angles;
@@ -94,7 +69,7 @@ struct {
     * Camera management
     * ---------------------------
     */
-   camera cam;
+   vg_camera cam;
    struct player_cam_controller cam_control;
    f32 cam_trackshake;
 
@@ -184,56 +159,38 @@ struct {
 
    struct player_effects_data effect_data;
 }
-static localplayer = {
-   .rb = {
-      .co = { 0,0,0 },
-      .w = { 0,0,0 },
-      .v = { 0,0,0 },
-      .q = { 0,0,0,1 },
-      .to_world = M4X3_IDENTITY,
-      .to_local = M4X3_IDENTITY
-   }
-};
-
-struct player_subsystem_interface static *player_subsystems[] = {
-   [k_player_subsystem_walk]  = &player_subsystem_walk,
-   [k_player_subsystem_dead]  = &player_subsystem_dead,
-   [k_player_subsystem_drive] = &player_subsystem_drive,
-   [k_player_subsystem_skate] = &player_subsystem_skate,
-   [k_player_subsystem_basic_info]=&player_subsystem_basic_info,
-   [k_player_subsystem_glide] = &player_subsystem_glide,
-};
+extern localplayer;
+extern struct player_subsystem_interface *player_subsystems[];
 
 /*
  * Gameloop tables
  * ---------------------------------------------------------
  */
 
-static void player__debugtext( int size, const char *fmt, ... );
-static void player__use_mesh( glmesh *mesh );
-static void player__use_model( u16 reg_id );
-
-static void player__bind(void);
-static void player__pre_update(void);
-static void player__update(void);
-static void player__post_update(void);
-
-static void player__pass_gate( u32 id );
-static void player__im_gui(void);
-static void player__setpos( v3f pos );
-static void player__spawn( ent_spawn *rp );
-static void player__clean_refs(void);
-static void player__reset(void);
-static void player__kill(void);
-static void player__begin_holdout( v3f offset );
-
-static int localplayer_cmd_respawn( int argc, const char *argv[] );
-static void player_apply_transport_to_cam( m4x3f transport );
-
-static void player__clear_sfx_buffer(void);
-static void player__networked_sfx( u8 system, u8 priority, u8 id, 
-                                   v3f pos, f32 volume );
-static void net_sfx_exchange( bitpack_ctx *ctx, struct net_sfx *sfx );
-static void net_sfx_play( struct net_sfx *sfx );
-
-#endif /* PLAYER_H */
+void player_init(void);
+void player__debugtext( int size, const char *fmt, ... );
+void player__use_mesh( glmesh *mesh );
+void player__use_model( u16 reg_id );
+
+void player__bind(void);
+void player__pre_update(void);
+void player__update(void);
+void player__post_update(void);
+
+void player__pass_gate( u32 id );
+void player__im_gui(void);
+void player__setpos( v3f pos );
+void player__spawn( ent_spawn *rp );
+void player__clean_refs(void);
+void player__reset(void);
+void player__kill(void);
+void player__begin_holdout( v3f offset );
+
+int localplayer_cmd_respawn( int argc, const char *argv[] );
+void player_apply_transport_to_cam( m4x3f transport );
+
+void player__clear_sfx_buffer(void);
+void player__networked_sfx( u8 system, u8 priority, u8 id, 
+                            v3f pos, f32 volume );
+void net_sfx_exchange( bitpack_ctx *ctx, struct net_sfx *sfx );
+void net_sfx_play( struct net_sfx *sfx );
index b3b6907c047b165e372baabcb7e9c495a1fd990c..68f5aca348d6ebd5c676b22d3ecde082705bbe42 100644 (file)
@@ -1,11 +1,7 @@
-#ifndef PLAYER_API_H
-#define PLAYER_API_H
-
+#pragma once
 #include "model.h"
 #include "camera.h"
-#include "entity.h"
 
-#define PLAYER_API static
 typedef struct player_instance player_instance;
 typedef struct player_pose player_pose;
 
@@ -27,4 +23,13 @@ struct player_pose{
    board;
 };
 
-#endif /* PLAYER_API_H */
+enum player_subsystem{
+   k_player_subsystem_walk = 0,
+   k_player_subsystem_skate = 1,
+   k_player_subsystem_dead = 2,
+   k_player_subsystem_drive = 3,
+   k_player_subsystem_basic_info = 4,
+   k_player_subsystem_glide = 5,
+   k_player_subsystem_max,
+   k_player_subsystem_invalid = 255
+};
index 3d6c85a112c22d301b5d2806758787c26e0aebdb..ffc7ae0f83ad0cafac580fe03dcd6e7bf86323c0 100644 (file)
@@ -1,13 +1,25 @@
 #include "player_basic_info.h"
 #include "network_compression.h"
 
-static void player__basic_info_animator_exchange(bitpack_ctx *ctx, void *data){
+struct player_basic_info player_basic_info;
+struct player_subsystem_interface player_subsystem_basic_info = 
+{
+   .pose = player__basic_info_pose,
+   .network_animator_exchange = player__basic_info_animator_exchange,
+   .animator_data = &player_basic_info.animator,
+   .animator_size = sizeof(player_basic_info.animator),
+   .name = "Basic Info"
+};
+
+void player__basic_info_animator_exchange(bitpack_ctx *ctx, void *data)
+{
    struct player_basic_info_animator *animator = data;
    /* TODO: This range needs to be standardized in a common header */
    bitpack_qv3f( ctx, 24, -1024.0f, 1024.0f, animator->root_co );
 }
 
-static void player__basic_info_pose( void *_animator, player_pose *pose ){
+void player__basic_info_pose( void *_animator, player_pose *pose )
+{
    struct player_basic_info_animator *animator = _animator;
    v3_copy( animator->root_co, pose->root_co );
    q_identity( pose->root_q );
index 12f46c9b532ea8dde6d353ce7a20558203e3aef5..815be672e0499f8ca9fff3e3729420ab1d2a3209 100644 (file)
@@ -1,25 +1,18 @@
-#ifndef PLAYER_BASIC_INFO_H
-#define PLAYER_BASIC_INFO_H
-
+#pragma once
 #include "player.h"
 #include "player_api.h"
 
-struct player_basic_info {
-   struct player_basic_info_animator {
+struct player_basic_info 
+{
+   struct player_basic_info_animator 
+   {
       v3f root_co;
    }
    animator;
 }
-static player_basic_info;
-static void player__basic_info_animator_exchange(bitpack_ctx *ctx, void *data);
-static void player__basic_info_pose( void *_animator, player_pose *pose );
+extern player_basic_info;
+extern struct player_subsystem_interface player_subsystem_basic_info;
 
-struct player_subsystem_interface static player_subsystem_basic_info = {
-   .pose = player__basic_info_pose,
-   .network_animator_exchange = player__basic_info_animator_exchange,
-   .animator_data = &player_basic_info.animator,
-   .animator_size = sizeof(player_basic_info.animator),
-   .name = "Basic Info"
-};
+void player__basic_info_animator_exchange(bitpack_ctx *ctx, void *data);
+void player__basic_info_pose( void *_animator, player_pose *pose );
 
-#endif /* PLAYER_BASIC_INFO_H */
index bfdef1ab97b306129acfe9cf3c47b6dbe5321884..2551968e5f76cbea21af133dbca99d4de041ed54 100644 (file)
@@ -1,6 +1,3 @@
-#ifndef PLAYER_COMMON_C
-#define PLAYER_COMMON_C
-
 #include "ent_skateshop.h"
 #include "player.h"
 #include "input.h"
@@ -42,8 +39,9 @@ static void player_camera_portal_correction(void){
                                  localplayer.final_mtx );
 
       /* record and re-put things again */
-      if( cleared ){
-         skaterift_record_frame( &skaterift.replay, 1 );
+      if( cleared )
+      {
+         skaterift_record_frame( &player_replay.local, 1 );
          localplayer.deferred_frame_record = 1;
 
          skeleton_apply_transform( &localplayer.skeleton, 
@@ -164,7 +162,7 @@ static void player__cam_iterate(void){
          inf_tpv = localplayer.cam_velocity_influence_smooth *
                      (1.0f-cc->camera_type_blend);
 
-   camera_lerp_angles( localplayer.angles, velocity_angles, 
+   vg_camera_lerp_angles( localplayer.angles, velocity_angles, 
                         inf_fpv,
                         localplayer.angles );
 
@@ -196,7 +194,7 @@ static void player__cam_iterate(void){
    float ya = atan2f( -cc->cam_velocity_smooth[1], 30.0f );
 
    follow_angles[1] = 0.3f + ya;
-   camera_lerp_angles( localplayer.angles, follow_angles,
+   vg_camera_lerp_angles( localplayer.angles, follow_angles,
                         inf_tpv,
                         localplayer.angles );
 
@@ -250,35 +248,6 @@ static void player__cam_iterate(void){
    v3_add( localplayer.cam_land_punch, localplayer.cam.pos, 
            localplayer.cam.pos );
 
-   if( k_cinema >= 0.0001f ){
-      ent_camera *cam = NULL;
-      f32 min_dist = k_cinema;
-
-      world_instance *world = world_current_instance();
-      for( u32 i=0; i<mdl_arrcount(&world->ent_camera); i++ ){
-         ent_camera *c = mdl_arritm(&world->ent_camera,i);
-
-         f32 dist = v3_dist( c->transform.co, localplayer.rb.co );
-
-         if( dist < min_dist ){
-            min_dist = dist;
-            cam = c;
-         }
-      }
-
-      if( cam ){
-         localplayer.cam.fov = cam->fov;
-         v3_copy( cam->transform.co, localplayer.cam.pos );
-         v3f v0;
-         if( k_cinema_fixed )
-            mdl_transform_vector( &cam->transform, (v3f){0.0f,-1.0f,0.0f}, v0 );
-         else 
-            v3_sub( localplayer.rb.co, cam->transform.co, v0 );
-
-         v3_angles( v0, localplayer.cam.angles );
-      }
-   }
-
    /* portal transitions */
    player_camera_portal_correction();
 }
@@ -303,5 +272,3 @@ static void player_look( v3f angles, float speed ){
    angles[1] += input_y * speed;
    angles[1] = vg_clampf( angles[1], -VG_PIf*0.5f, VG_PIf*0.5f );
 }
-
-#endif /* PLAYER_COMMON_C */
index 625ff0e7643cae2dfb8c0d4c5a4cb9dc93cd1789..5f4ab7260a26cfca7648a0074d01014ecbf10648 100644 (file)
@@ -1,14 +1,28 @@
-#ifndef PLAYER_DEAD_C
-#define PLAYER_DEAD_C
-
-#include "player.h"
+#include "skaterift.h"
+#include "player_dead.h"
 #include "gui.h"
 
-static void player__dead_update(void){
+struct player_dead player_dead;
+struct player_subsystem_interface player_subsystem_dead = {
+   .update = player__dead_update,
+   .post_update = player__dead_post_update,
+   .animate = player__dead_animate,
+   .pose = player__dead_pose,
+   .post_animate = player__dead_post_animate,
+   .im_gui = player__dead_im_gui,
+   .bind = player__dead_bind,
+
+   .animator_data = &player_dead.animator,
+   .animator_size = sizeof(player_dead.animator),
+   .network_animator_exchange = player__dead_animator_exchange,
+   .name = "Dead"
+};
+
+void player__dead_update(void){
    player_ragdoll_iter( &localplayer.ragdoll );
 }
 
-static void player__dead_post_update(void){
+void player__dead_post_update(void){
    struct ragdoll_part *part = 
       &localplayer.ragdoll.parts[ localplayer.id_hip-1 ];
    struct player_dead *d = &player_dead;
@@ -41,7 +55,7 @@ static void player__dead_post_update(void){
    }
 }
 
-static void player__dead_animate(void){
+void player__dead_animate(void){
    struct player_dead *d = &player_dead;
    struct player_dead_animator *animator = &d->animator;
    struct player_ragdoll *rd = &localplayer.ragdoll;
@@ -113,7 +127,8 @@ static void player__dead_animate(void){
    }
 }
 
-static void player__dead_pose( void *_animator, player_pose *pose ){
+void player__dead_pose( void *_animator, player_pose *pose )
+{
    struct player_dead_animator *animator = _animator;
    struct player_ragdoll *rd = &localplayer.ragdoll;
    struct skeleton *sk = &localplayer.skeleton;
@@ -131,14 +146,17 @@ static void player__dead_pose( void *_animator, player_pose *pose ){
    }
 }
 
-static void player__dead_post_animate(void){
+void player__dead_post_animate(void)
+{
    localplayer.cam_velocity_influence = 1.0f;
 }
 
-static void player__dead_im_gui(void){
+void player__dead_im_gui(void)
+{
 }
 
-static void player__dead_transition( enum player_die_type type ){
+void player__dead_transition( enum player_die_type type )
+{
    localplayer.subsystem = k_player_subsystem_dead;
    copy_localplayer_to_ragdoll( &localplayer.ragdoll, type );
 
@@ -163,7 +181,8 @@ static void player__dead_transition( enum player_die_type type ){
       vg_strcat( &str, "spawn" );
 }
 
-static void player__dead_animator_exchange( bitpack_ctx *ctx, void *data ){
+void player__dead_animator_exchange( bitpack_ctx *ctx, void *data )
+{
    struct player_dead_animator *animator = data;
 
    for( u32 i=0; i<localplayer.skeleton.bone_count; i ++ ){
@@ -172,9 +191,8 @@ static void player__dead_animator_exchange( bitpack_ctx *ctx, void *data ){
    }
 }
 
-static void player__dead_bind(void){
+void player__dead_bind(void)
+{
    struct skeleton *sk = &localplayer.skeleton;
    player_dead.anim_bail = skeleton_get_anim( sk, "pose_bail_ball" );
 }
-
-#endif /* PLAYER_DEAD_C */
index f90a3029cb393f45e0dca322c6dd60f0855994fa..94241b96c019658b188f62398f8c0af8a9c38a8a 100644 (file)
@@ -1,10 +1,9 @@
-#ifndef PLAYER_DEAD_H
-#define PLAYER_DEAD_H
-
+#pragma once
 #include "player.h"
 #include "player_api.h"
 
-struct player_dead{
+struct player_dead
+{
    v3f co_lpf, v_lpf, w_lpf;
 
    struct player_dead_animator{
@@ -18,31 +17,16 @@ struct player_dead{
 
    struct skeleton_anim *anim_bail;
 }
-static player_dead;
-
-static void player__dead_update      (void);
-static void player__dead_post_update (void);
-static void player__dead_animate     (void);
-static void player__dead_pose        (void *animator, player_pose *pose);
-static void player__dead_post_animate(void);
-static void player__dead_im_gui      (void);
-static void player__dead_bind        (void);
-static void player__dead_transition  ( enum player_die_type type );
-static void player__dead_animator_exchange( bitpack_ctx *ctx, void *data );
-
-struct player_subsystem_interface static player_subsystem_dead = {
-   .update = player__dead_update,
-   .post_update = player__dead_post_update,
-   .animate = player__dead_animate,
-   .pose = player__dead_pose,
-   .post_animate = player__dead_post_animate,
-   .im_gui = player__dead_im_gui,
-   .bind = player__dead_bind,
-
-   .animator_data = &player_dead.animator,
-   .animator_size = sizeof(player_dead.animator),
-   .network_animator_exchange = player__dead_animator_exchange,
-   .name = "Dead"
-};
+extern player_dead;
+extern struct player_subsystem_interface player_subsystem_dead;
+
+void player__dead_update      (void);
+void player__dead_post_update (void);
+void player__dead_animate     (void);
+void player__dead_pose        (void *animator, player_pose *pose);
+void player__dead_post_animate(void);
+void player__dead_im_gui      (void);
+void player__dead_bind        (void);
+void player__dead_transition  ( enum player_die_type type );
+void player__dead_animator_exchange( bitpack_ctx *ctx, void *data );
 
-#endif /* PLAYER_DEAD_H */
index cddd0d43ad3a8179da1acc3cce2e3185205e48fe..230e7bdb0970c2ebc94242a211c024ca73327558 100644 (file)
@@ -1,10 +1,25 @@
-#ifndef PLAYER_DRIVE_C
-#define PLAYER_DRIVE_C
-
-#include "player.h"
+#include "player_drive.h"
 #include "input.h"
 
-static void player__drive_pre_update(void){
+struct player_drive player_drive;
+struct player_subsystem_interface player_subsystem_drive = 
+{
+   .pre_update = player__drive_pre_update,
+   .update = player__drive_update,
+   .post_update = player__drive_post_update,
+   .animate = player__drive_animate,
+   .pose = player__drive_pose,
+   .post_animate = player__drive_post_animate,
+   .im_gui = player__drive_im_gui,
+   .bind = player__drive_bind,
+
+   .animator_data = NULL,
+   .animator_size = 0,
+   .name = "Drive"
+};
+
+void player__drive_pre_update(void)
+{
    drivable_vehicle *vehc = player_drive.vehicle;
 
    v2f steer;
@@ -15,18 +30,20 @@ static void player__drive_pre_update(void){
    vehc->drive = steer[1];
 }
 
-static void player__drive_update(void){}
+void player__drive_update(void){}
 
-static void player__drive_post_update(void){
+void player__drive_post_update(void)
+{
    v3_copy( player_drive.vehicle->rb.co,localplayer.rb.co );
    v3_copy( player_drive.vehicle->rb.v, localplayer.rb.v );
    v4_copy( player_drive.vehicle->rb.q, localplayer.rb.q );
    v3_copy( player_drive.vehicle->rb.w, localplayer.rb.w );
 }
 
-static void player__drive_animate(void){}
+void player__drive_animate(void){}
 
-static void player__drive_pose( void *animator, player_pose *pose ){
+void player__drive_pose( void *animator, player_pose *pose )
+{
    struct skeleton *sk = &localplayer.skeleton;
 
    skeleton_sample_anim( sk, player_drive.anim_drive, 0.0f, pose->keyframes );
@@ -34,7 +51,8 @@ static void player__drive_pose( void *animator, player_pose *pose ){
    v4_copy( localplayer.rb.q, pose->root_q );
 }
 
-static void player__drive_post_animate(void){
+void player__drive_post_animate(void)
+{
    if( localplayer.cam_control.camera_mode == k_cam_firstperson )
       localplayer.cam_velocity_influence = 0.0f;
    else
@@ -56,14 +74,14 @@ static void player__drive_post_animate(void){
    localplayer.angles[1] = pitch;
 }
 
-static void player__drive_im_gui(void){
+void player__drive_im_gui(void)
+{
    player__debugtext( 1, "Nothing here" );
 }
 
-static void player__drive_bind(void){
+void player__drive_bind(void)
+{
    struct skeleton *sk = &localplayer.skeleton;
    player_drive.vehicle = &gzoomer;
    player_drive.anim_drive = skeleton_get_anim( sk, "idle_cycle+y" );
 }
-
-#endif /* PLAYER_DRIVE_C */
index 0dd135c14e9048a959fbec20ee477cb8419e1be5..76c2557c9ea484f2ac3d6564378b10d092bd5449 100644 (file)
@@ -1,38 +1,21 @@
-#ifndef PLAYER_DRIVE_H
-#define PLAYER_DRIVE_H
-
+#pragma once
 #include "player.h"
 #include "vehicle.h"
 
-struct player_drive {
+struct player_drive 
+{
    drivable_vehicle *vehicle;
    struct skeleton_anim *anim_drive;
 }
-static player_drive;
-
-static void player__drive_pre_update(void);
-static void player__drive_update(void);
-static void player__drive_post_update(void);
-static void player__drive_animate(void);
-static void player__drive_pose( void *animator, player_pose *pose );
-
-static void player__drive_post_animate(void);
-static void player__drive_im_gui(void);
-static void player__drive_bind(void);
-
-struct player_subsystem_interface static player_subsystem_drive = {
-   .pre_update = player__drive_pre_update,
-   .update = player__drive_update,
-   .post_update = player__drive_post_update,
-   .animate = player__drive_animate,
-   .pose = player__drive_pose,
-   .post_animate = player__drive_post_animate,
-   .im_gui = player__drive_im_gui,
-   .bind = player__drive_bind,
+extern player_drive;
+extern struct player_subsystem_interface player_subsystem_drive;
 
-   .animator_data = NULL,
-   .animator_size = 0,
-   .name = "Drive"
-};
+void player__drive_pre_update(void);
+void player__drive_update(void);
+void player__drive_post_update(void);
+void player__drive_animate(void);
+void player__drive_pose( void *animator, player_pose *pose );
 
-#endif /* PLAYER_DRIVE_H */
+void player__drive_post_animate(void);
+void player__drive_im_gui(void);
+void player__drive_bind(void);
index 9b13445a6b4207ebde985b934202118382921261..feca984b7a7b324fb3bcc56618c60c9ab47e2d81 100644 (file)
@@ -1,7 +1,9 @@
 #include "player_effects.h"
+#include "player_render.h"
 #include "particle.h"
 
-static void effect_blink_apply( effect_blink *ef, player_pose *pose, f32 dt ){
+void effect_blink_apply( effect_blink *ef, player_pose *pose, f32 dt )
+{
    if( ef->t < 0.0f ){
       ef->t = (1.0f-powf(vg_randf64(&vg.rand),4.0f))*4.0f;
       ef->l = 0.08f;
@@ -13,7 +15,8 @@ static void effect_blink_apply( effect_blink *ef, player_pose *pose, f32 dt ){
    ef->l -= dt;
 }
 
-static void effect_spark_apply( effect_spark *ef, v3f co, v3f v, f32 dt ){
+void effect_spark_apply( effect_spark *ef, v3f co, v3f v, f32 dt )
+{
    if( !ef->colour ) return;
 
    if( ef->t < 0.0f ){
index c52361d45bcae8e7a1fc0fb32c2f602fb24f1b50..50caabc4fddd5feefb64899ed6c060ee786be50b 100644 (file)
@@ -1,26 +1,25 @@
-#ifndef PLAYER_EFFECTS
-#define PLAYER_EFFECTS
-
-#include "skaterift.h"
+#pragma once
+#include "vg/vg_platform.h"
 
 typedef struct effect_blink effect_blink;
 typedef struct effect_spark effect_spark;
 
-struct effect_blink {
+struct effect_blink 
+{
    f32 t, l;
 };
 
-struct effect_spark {
+struct effect_spark 
+{
    u32 colour;
    f32 t;
 };
 
-static void effect_blink_apply( effect_blink *ef, player_pose *pose, f32 dt );
-static void effect_spark_apply( effect_spark *ef, v3f co, v3f v, f32 dt );
+void effect_blink_apply( effect_blink *ef, player_pose *pose, f32 dt );
+void effect_spark_apply( effect_spark *ef, v3f co, v3f v, f32 dt );
 
-struct player_effects_data {
+struct player_effects_data 
+{
    effect_blink blink;
    effect_spark spark, sand;
 };
-
-#endif /* PLAYER_EFFECTS */
index 32768f6d1c866e5deecb94adb053e5a5275be603..f7339373869924086ceb02272a80b1af9a01da89 100644 (file)
@@ -1,13 +1,74 @@
-#ifndef PLAYER_GLIDE_C
-#define PLAYER_GLIDE_C
-
 #include "player_glide.h"
-#include "input.h"
-
 #include "vg/vg_rigidbody.h"
 #include "scene_rigidbody.h"
 #include "shaders/model_board_view.h"
 #include "shaders/model_entity.h"
+#include "input.h"
+#include "skaterift.h"
+
+#include "player_dead.h"
+#include "player_skate.h"
+
+trail_system trails_glider[] = {
+   {
+      .width = 0.035f,
+      .lifetime = 5.0f,
+      .min_dist = 0.5f
+   },
+   {
+      .width = 0.035f,
+      .lifetime = 5.0f,
+      .min_dist = 0.5f
+   },
+};
+
+struct player_glide player_glide =
+{
+   .parts = {
+      {
+         .co    = { 1.0f, 0.5f, -1.0f },
+         .euler = { VG_TAUf*0.25f,  VG_TAUf*0.125f, 0.0f },
+         .shape = k_rb_shape_capsule,
+         .inf   = { .h = 2.82842712475f, .r = 0.25f },
+      },
+      {
+         .co    = { -1.0f, 0.5f, -1.0f },
+         .euler = { VG_TAUf*0.25f, -VG_TAUf*0.125f, 0.0f },
+         .shape = k_rb_shape_capsule,
+         .inf   = { .h = 2.82842712475f, .r = 0.25f },
+      },
+      {
+         .co    = {  0.0f, 0.5f, 1.0f },
+         .euler = { VG_TAUf*0.25f, VG_TAUf*0.25f, 0.0f },
+         .shape = k_rb_shape_capsule,
+         .inf   = { .h = 6.0f, .r = 0.25f },
+      },
+      {
+         .co    = {  0.0f, -0.5f, 0.0f },
+         .euler = { VG_TAUf*0.25f, VG_TAUf*0.25f, 0.0f },
+         .shape = k_rb_shape_capsule,
+         .inf   = { .h = 2.0f, .r = 0.25f },
+         .is_damage = 1,
+      },
+   }
+};
+
+struct player_subsystem_interface player_subsystem_glide = 
+{
+   .pre_update = player_glide_pre_update,
+   .update = player_glide_update,
+   .post_update = player_glide_post_update,
+   .animate = player_glide_animate,
+   .pose = player_glide_pose,
+   .post_animate = player_glide_post_animate,
+   .network_animator_exchange = player_glide_animator_exchange,
+   .im_gui = player_glide_im_gui,
+   .bind = player_glide_bind,
+
+   .animator_data = &player_glide.animator,
+   .animator_size = sizeof(player_glide.animator),
+   .name = "Glide"
+};
 
 static f32 k_glide_steer = 2.0f,
            k_glide_cl = 0.04f,
@@ -20,7 +81,8 @@ static f32 k_glide_steer = 2.0f,
 
 static i32 k_glide_pause = 0;
 
-static void player_glide_pre_update(void){
+void player_glide_pre_update(void)
+{
    if( button_down(k_srbind_use) ){
       localplayer.subsystem = k_player_subsystem_skate;
       localplayer.glider_orphan = 1;
@@ -86,7 +148,8 @@ static void calculate_drag( v3f vl, f32 cd, v3f out_force ){
 /*
  * Returns true if the bottom sphere is hit 
  */
-static bool glider_physics( v2f steer ){
+bool glider_physics( v2f steer )
+{
    rigidbody *rb = &player_glide.rb;
 
    /* lift */
@@ -205,7 +268,8 @@ static bool glider_physics( v2f steer ){
    return bottom_hit;
 }
 
-static void player_glide_update(void){
+void player_glide_update(void)
+{
    v2f steer;
    joystick_state( k_srjoystick_steer, steer );
 
@@ -216,7 +280,8 @@ static void player_glide_update(void){
    }
 }
 
-static void player_glide_post_update(void){
+void player_glide_post_update(void)
+{
    v3_copy( player_glide.rb.co, localplayer.rb.co );
    v4_copy( player_glide.rb.q, localplayer.rb.q );
    v3_copy( player_glide.rb.v, localplayer.rb.v );
@@ -224,13 +289,15 @@ static void player_glide_post_update(void){
    rb_update_matrices( &localplayer.rb );
 }
 
-static void player_glide_animate(void){
+void player_glide_animate(void)
+{
    struct player_glide *g = &player_glide;
    struct player_glide_animator *animator = &g->animator;
    rb_extrapolate( &localplayer.rb, animator->root_co, animator->root_q );
 }
 
-static void player_glide_pose( void *_animator, player_pose *pose ){
+void player_glide_pose( void *_animator, player_pose *pose )
+{
    struct skeleton *sk = &localplayer.skeleton;
    struct player_glide_animator *animator = _animator;
    pose->type = k_player_pose_type_ik;
@@ -245,7 +312,8 @@ static void player_glide_pose( void *_animator, player_pose *pose ){
    v4_copy( animator->root_q, pose->root_q );
 }
 
-static void player_glide_post_animate(void){
+void player_glide_post_animate(void)
+{
    if( localplayer.cam_control.camera_mode == k_cam_firstperson )
       localplayer.cam_velocity_influence = 0.0f;
    else
@@ -258,15 +326,16 @@ static void player_glide_post_animate(void){
    localplayer.cam_dist = 2.0f + v3_length( localplayer.rb.v )*0.2f;
 }
 
-static void player_glide_animator_exchange( bitpack_ctx *ctx, void *data ){
+void player_glide_animator_exchange( bitpack_ctx *ctx, void *data )
+{
    struct player_glide_animator *animator = data;
 
    bitpack_qv3f( ctx, 24, -1024.0f, 1024.0f, animator->root_co );
    bitpack_qquat( ctx, animator->root_q );
 }
 
-static void 
-player_glide_remote_animator_exchange( bitpack_ctx *ctx, void *data ){
+void player_glide_remote_animator_exchange( bitpack_ctx *ctx, void *data )
+{
    struct remote_glider_animator *animator = data;
 
    bitpack_qv3f( ctx, 24, -1024.0f, 1024.0f, animator->root_co );
@@ -274,7 +343,8 @@ player_glide_remote_animator_exchange( bitpack_ctx *ctx, void *data ){
    bitpack_qquat( ctx, animator->root_q );
 }
 
-static void player_glide_im_gui(void){
+void player_glide_im_gui(void)
+{
    player__debugtext( 1, "Nothing here" );
    player__debugtext( 1, " lift: %.2f %.2f %.2f", 
                            player_glide.info_lift[0],
@@ -290,7 +360,8 @@ static void player_glide_im_gui(void){
                            player_glide.info_drag[2] );
 }
 
-static void player_glide_equip_glider(void){
+void player_glide_equip_glider(void)
+{
    if( !localplayer.have_glider ){
       localplayer.have_glider = 1;
       localplayer.glider_orphan = 0;
@@ -308,7 +379,7 @@ static int ccmd_player_glider_spawn( int argc, const char *argv[] ){
    return 0;
 }
 
-static void player_glide_bind(void)
+void player_glide_bind(void)
 {
    u32 mask = VG_VAR_CHEAT|VG_VAR_PERSISTENT;
    VG_VAR_F32( k_glide_steer, flags=mask );
@@ -387,9 +458,8 @@ static void player_glide_bind(void)
 
    u32 count = mdl_arrcount( &mdl->textures );
    player_glide.glider_textures = 
-      vg_linear_alloc(alloc,vg_align8(sizeof(GLuint)*(count+1)));
+      vg_linear_alloc( alloc, vg_align8(sizeof(GLuint)*(count+1))); 
    player_glide.glider_textures[0] = vg.tex_missing;
-
    mdl_async_load_glmesh( mdl, &player_glide.glider_mesh, NULL );
 
    for( u32 i=0; i<count; i ++ ){
@@ -425,7 +495,8 @@ static void player_glide_bind(void)
    }
 }
 
-static void player_glide_transition(void){
+void player_glide_transition(void)
+{
    localplayer.subsystem = k_player_subsystem_glide;
    localplayer.have_glider = 0;
    world_static.challenge_target = NULL;
@@ -459,8 +530,9 @@ static void player_glide_transition(void){
    player__begin_holdout( (v3f){0,0,0} );
 }
 
-static void render_glider_model( camera *cam, world_instance *world,
-                                 m4x3f mmdl, enum board_shader shader ){
+void render_glider_model( vg_camera *cam, world_instance *world,
+                          m4x3f mmdl, enum board_shader shader )
+{
    u32 current_tex = 0xffffffff;
    glActiveTexture( GL_TEXTURE0 );
 
@@ -510,8 +582,9 @@ static void render_glider_model( camera *cam, world_instance *world,
  *        that can hold that information instead so we can save it into 
  *        the replay
  */
-static void player_glide_render( camera *cam, world_instance *world,
-                                 player_pose *pose ){
+void player_glide_render( vg_camera *cam, world_instance *world,
+                          player_pose *pose )
+{
    if( !((localplayer.subsystem == k_player_subsystem_glide) ||
          (localplayer.observing_system == k_player_subsystem_glide) ||
           localplayer.have_glider ||
@@ -610,7 +683,8 @@ static void player_glide_render( camera *cam, world_instance *world,
    player_glide.remote_animator.s = kf_res.s[0];
 }
 
-static void player_glide_render_effects( camera *cam ){
+void player_glide_render_effects( vg_camera *cam )
+{
    v3f co, temp;
    v4f q;
    rb_extrapolate( &player_glide.rb, co, q );
@@ -631,5 +705,3 @@ static void player_glide_render_effects( camera *cam ){
       trail_system_render( &trails_glider[i], &skaterift.cam );
    }
 }
-
-#endif /* PLAYER_GLIDE_C */
index f8f6dd99dffee4de2a9d85f47d91c8c6b025826f..061a04dd65f427007d5436a3e42c803dd6f6635e 100644 (file)
@@ -1,20 +1,22 @@
-#ifndef PLAYER_GLIDE_H
-#define PLAYER_GLIDE_H
-
+#pragma once
 #include "player.h"
+#include "player_render.h"
 #include "trail.h"
 
-struct player_glide {
+struct player_glide 
+{
    struct skeleton_anim *anim_glide;
 
-   struct player_glide_animator {
+   struct player_glide_animator 
+   {
       v3f root_co;
       v4f root_q;
    }
    animator;
 
    /* this sucks */
-   struct remote_glider_animator {
+   struct remote_glider_animator 
+   {
       v3f root_co;
       v4f root_q;
       f32 s;
@@ -52,92 +54,26 @@ struct player_glide {
    GLuint *glider_textures;
    glmesh glider_mesh;
 }
-static player_glide = {
-   .parts = {
-      {
-         .co    = { 1.0f, 0.5f, -1.0f },
-         .euler = { VG_TAUf*0.25f,  VG_TAUf*0.125f, 0.0f },
-         .shape = k_rb_shape_capsule,
-         .inf   = { .h = 2.82842712475f, .r = 0.25f },
-      },
-      {
-         .co    = { -1.0f, 0.5f, -1.0f },
-         .euler = { VG_TAUf*0.25f, -VG_TAUf*0.125f, 0.0f },
-         .shape = k_rb_shape_capsule,
-         .inf   = { .h = 2.82842712475f, .r = 0.25f },
-      },
-      {
-         .co    = {  0.0f, 0.5f, 1.0f },
-         .euler = { VG_TAUf*0.25f, VG_TAUf*0.25f, 0.0f },
-         .shape = k_rb_shape_capsule,
-         .inf   = { .h = 6.0f, .r = 0.25f },
-      },
-      {
-         .co    = {  0.0f, -0.5f, 0.0f },
-         .euler = { VG_TAUf*0.25f, VG_TAUf*0.25f, 0.0f },
-         .shape = k_rb_shape_capsule,
-         .inf   = { .h = 2.0f, .r = 0.25f },
-         .is_damage = 1,
-      },
-
-#if 0
-      {
-         .co    = { 0.0f, 0.0f, 0.0f },
-         .euler = { 0.0f, 0.0f, 0.0f },
-         .shape = k_rb_shape_sphere,
-         .r     = 0.5f
-      }
-#endif
-   }
-};
-
-static trail_system trails_glider[] = {
-{
-   .width = 0.035f,
-   .lifetime = 5.0f,
-   .min_dist = 0.5f
-},
-{
-   .width = 0.035f,
-   .lifetime = 5.0f,
-   .min_dist = 0.5f
-},
-};
-
-static void player_glide_pre_update(void);
-static void player_glide_update(void);
-static void player_glide_post_update(void);
-static void player_glide_animate(void);
-static void player_glide_pose( void *animator, player_pose *pose );
-
-static void player_glide_post_animate(void);
-static void player_glide_im_gui(void);
-static void player_glide_bind(void);
-static void player_glide_transition(void);
-static bool glider_physics( v2f steer );
-static void player_glide_animator_exchange( bitpack_ctx *ctx, void *data );
-static void player_glide_render( camera *cam, world_instance *world,
-                                 player_pose *pose );
-static void render_glider_model( camera *cam, world_instance *world,
-                                 m4x3f mmdl, enum board_shader shader );
-static void 
-player_glide_remote_animator_exchange( bitpack_ctx *ctx, void *data );
-static void player_glide_equip_glider(void);
-
-struct player_subsystem_interface static player_subsystem_glide = {
-   .pre_update = player_glide_pre_update,
-   .update = player_glide_update,
-   .post_update = player_glide_post_update,
-   .animate = player_glide_animate,
-   .pose = player_glide_pose,
-   .post_animate = player_glide_post_animate,
-   .network_animator_exchange = player_glide_animator_exchange,
-   .im_gui = player_glide_im_gui,
-   .bind = player_glide_bind,
-
-   .animator_data = &player_glide.animator,
-   .animator_size = sizeof(player_glide.animator),
-   .name = "Glide"
-};
+extern player_glide;
+extern struct player_subsystem_interface player_subsystem_glide;
+
+void player_glide_pre_update(void);
+void player_glide_update(void);
+void player_glide_post_update(void);
+void player_glide_animate(void);
+void player_glide_pose( void *animator, player_pose *pose );
+
+void player_glide_post_animate(void);
+void player_glide_im_gui(void);
+void player_glide_bind(void);
+void player_glide_transition(void);
+bool glider_physics( v2f steer );
+void player_glide_animator_exchange( bitpack_ctx *ctx, void *data );
+void player_glide_render( vg_camera *cam, world_instance *world,
+                          player_pose *pose );
+void render_glider_model( vg_camera *cam, world_instance *world,
+                          m4x3f mmdl, enum board_shader shader );
+void player_glide_remote_animator_exchange( bitpack_ctx *ctx, void *data );
+void player_glide_equip_glider(void);
+void player_glide_render_effects( vg_camera *cam );
 
-#endif /* PLAYER_GLIDE_H */
index 413f9a8d137e73b58466475b7d4713bfd681bc6f..84908ffee0fe946a4dca9d249673abbaadfcc463 100644 (file)
@@ -5,8 +5,23 @@
 #include "scene_rigidbody.h"
 
 #include "player.h"
+#include "player_dead.h"
 #include "audio.h"
 
+static float k_ragdoll_floatyiness = 20.0f,
+             k_ragdoll_floatydrag  = 1.0f,
+             k_ragdoll_limit_scale = 1.0f,
+             k_ragdoll_spring = 127.0f,
+             k_ragdoll_dampening = 15.0f,
+             k_ragdoll_correction = 0.5f,
+             k_ragdoll_angular_drag = 0.08f,
+             k_ragdoll_active_threshold = 5.0f;
+
+static int   k_ragdoll_div = 1,
+             ragdoll_frame = 0,
+             k_ragdoll_debug_collider = 1,
+             k_ragdoll_debug_constraints = 0;
+
 static int dev_ragdoll_saveload(int argc, const char *argv[]){
    if( argc != 2 ){
       vg_info( "Usage: ragdoll load/save filepath\n" );
@@ -42,7 +57,8 @@ static int dev_ragdoll_saveload(int argc, const char *argv[]){
    return 0;
 }
 
-static void player_ragdoll_init(void){
+void player_ragdoll_init(void)
+{
    VG_VAR_F32( k_ragdoll_active_threshold );
    VG_VAR_F32( k_ragdoll_angular_drag );
    VG_VAR_F32( k_ragdoll_correction );
@@ -55,8 +71,8 @@ static void player_ragdoll_init(void){
    vg_console_reg_cmd( "ragdoll", dev_ragdoll_saveload, NULL );
 }
 
-static void player_init_ragdoll_bone_collider( struct skeleton_bone *bone,
-                                                  struct ragdoll_part *rp )
+void player_init_ragdoll_bone_collider( struct skeleton_bone *bone,
+                                        struct ragdoll_part *rp )
 {
    f32 k_density = 8.0f,
        k_inertia_scale = 2.0f;
@@ -128,7 +144,8 @@ static void player_init_ragdoll_bone_collider( struct skeleton_bone *bone,
 /*
  * Get parent index in the ragdoll
  */
-static u32 ragdoll_bone_parent( struct player_ragdoll *rd, u32 bone_id ){
+u32 ragdoll_bone_parent( struct player_ragdoll *rd, u32 bone_id )
+{
    for( u32 j=0; j<rd->part_count; j++ )
       if( rd->parts[ j ].bone_id == bone_id )
          return j;
@@ -140,8 +157,9 @@ static u32 ragdoll_bone_parent( struct player_ragdoll *rd, u32 bone_id ){
 /*
  * Setup ragdoll colliders from skeleton
  */
-static void setup_ragdoll_from_skeleton( struct skeleton *sk,
-                                         struct player_ragdoll *rd ){
+void setup_ragdoll_from_skeleton( struct skeleton *sk,
+                                  struct player_ragdoll *rd )
+{
    rd->part_count = 0;
 
    if( !sk->collider_count )
@@ -236,7 +254,8 @@ static void setup_ragdoll_from_skeleton( struct skeleton *sk,
 /*
  * Make avatar copy the ragdoll
  */
-static void copy_ragdoll_pose_to_localplayer( struct player_ragdoll *rd ){
+void copy_ragdoll_pose_to_localplayer( struct player_ragdoll *rd )
+{
    for( int i=0; i<rd->part_count; i++ ){
       struct ragdoll_part *part = &rd->parts[i];
 
@@ -280,8 +299,9 @@ static void copy_ragdoll_pose_to_localplayer( struct player_ragdoll *rd ){
 /*
  * Make the ragdoll copy the player model
  */
-static void copy_localplayer_to_ragdoll( struct player_ragdoll *rd, 
-                                         enum player_die_type type ){
+void copy_localplayer_to_ragdoll( struct player_ragdoll *rd, 
+                                  enum player_die_type type )
+{
    v3f centroid;
 
    v3f *bone_mtx = localplayer.final_mtx[localplayer.id_hip];
@@ -328,7 +348,8 @@ static void copy_localplayer_to_ragdoll( struct player_ragdoll *rd,
 /*
  * Ragdoll physics step
  */
-static void player_ragdoll_iter( struct player_ragdoll *rd ){
+void player_ragdoll_iter( struct player_ragdoll *rd )
+{
    world_instance *world = world_current_instance();
 
    int run_sim = 0;
index 25b6fad7b682e9d8d9625f67f8c6222380e6877d..08ab5e75d9ff56ce37129ed4b7ed248d7c3d913e 100644 (file)
@@ -10,7 +10,6 @@
 #include "skeleton.h"
 #include "vg/vg_rigidbody.h"
 #include "vg/vg_rigidbody_constraints.h"
-#include "player_render.h"
 
 struct player_ragdoll{
    struct ragdoll_part{
@@ -52,35 +51,21 @@ struct player_ragdoll{
    int shoes[2];
 };
 
-static float k_ragdoll_floatyiness = 20.0f,
-                k_ragdoll_floatydrag  = 1.0f,
-                k_ragdoll_limit_scale = 1.0f,
-                k_ragdoll_spring = 127.0f,
-                k_ragdoll_dampening = 15.0f,
-                k_ragdoll_correction = 0.5f,
-                k_ragdoll_angular_drag = 0.08f,
-                k_ragdoll_active_threshold = 5.0f;
-
-static int   k_ragdoll_div = 1,
-                ragdoll_frame = 0,
-                k_ragdoll_debug_collider = 1,
-                k_ragdoll_debug_constraints = 0;
-
 enum player_die_type {
    k_player_die_type_generic,
    k_player_die_type_head,
    k_player_die_type_feet
 };
 
-static void player_ragdoll_init(void);
-static void player_init_ragdoll_bone_collider( struct skeleton_bone *bone,
-                                                  struct ragdoll_part *rp );
-static u32 ragdoll_bone_parent( struct player_ragdoll *rd, u32 bone_id );
-static void setup_ragdoll_from_skeleton( struct skeleton *sk,
-                                         struct player_ragdoll *rd );
-static void copy_ragdoll_pose_to_localplayer( struct player_ragdoll *rd );
-static void copy_localplayer_to_ragdoll( struct player_ragdoll *rd, 
-                                         enum player_die_type type );
-                                          
-static void player_debug_ragdoll(void);
-static void player_ragdoll_iter( struct player_ragdoll *rd );
+void player_ragdoll_init(void);
+void player_init_ragdoll_bone_collider( struct skeleton_bone *bone,
+                                           struct ragdoll_part *rp );
+u32 ragdoll_bone_parent( struct player_ragdoll *rd, u32 bone_id );
+void setup_ragdoll_from_skeleton( struct skeleton *sk,
+                                  struct player_ragdoll *rd );
+void copy_ragdoll_pose_to_localplayer( struct player_ragdoll *rd );
+void copy_localplayer_to_ragdoll( struct player_ragdoll *rd, 
+                                  enum player_die_type type );
+                                   
+void player_debug_ragdoll(void);
+void player_ragdoll_iter( struct player_ragdoll *rd );
index ba07abea312a44ebcae783bb00c9c16d792a05d6..f829ec0512de5585cc54a5a21c2feb1e53af0439 100644 (file)
@@ -1,6 +1,7 @@
 #include "player_remote.h"
 #include "skeleton.h"
 #include "player_render.h"
+#include "player_api.h"
 #include "network_common.h"
 #include "addon.h"
 #include "font.h"
@@ -8,10 +9,14 @@
 #include "ent_miniworld.h"
 #include "ent_region.h"
 #include "shaders/model_entity.h"
+#include "vg/vg_steam_friends.h"
+
+struct global_netplayers netplayers;
 
 static i32 k_show_own_name = 0;
 
-static void player_remote_clear( struct network_player *player ){
+static void player_remote_clear( struct network_player *player )
+{
    addon_cache_unwatch( k_addon_type_player, player->playermodel_view_slot );
    addon_cache_unwatch( k_addon_type_board, player->board_view_slot );
 
@@ -53,7 +58,8 @@ static void relink_remote_player_worlds( u32 client_id ){
  *
  * Run if local worlds change
  */
-static void relink_all_remote_player_worlds(void){
+void relink_all_remote_player_worlds(void)
+{
    for( u32 i=0; i<vg_list_size(netplayers.list); i++ ){
       struct network_player *player = &netplayers.list[i];
       if( player->active )
@@ -61,7 +67,8 @@ static void relink_all_remote_player_worlds(void){
    }
 }
 
-static void player_remote_update_friendflags( struct network_player *remote ){
+void player_remote_update_friendflags( struct network_player *remote )
+{
    ISteamFriends *hSteamFriends = SteamAPI_SteamFriends();
    remote->isfriend = SteamAPI_ISteamFriends_HasFriend( hSteamFriends,
                         remote->steamid, k_EFriendFlagImmediate );
@@ -69,7 +76,8 @@ static void player_remote_update_friendflags( struct network_player *remote ){
                         remote->steamid, k_EFriendFlagBlocked );
 }
 
-static void player_remote_rx_200_300( SteamNetworkingMessage_t *msg ){
+void player_remote_rx_200_300( SteamNetworkingMessage_t *msg )
+{
    netmsg_blank *tmp = msg->m_pData;
 
    if( tmp->inetmsg_id == k_inetmsg_playerjoin ){
@@ -313,7 +321,8 @@ static void player_remote_rx_200_300( SteamNetworkingMessage_t *msg ){
 /*
  * Write localplayer pose to network
  */
-static void remote_player_send_playerframe(void){
+void remote_player_send_playerframe(void)
+{
    u8 sysid = localplayer.subsystem;
    if( sysid >= k_player_subsystem_max ) return;
 
@@ -386,7 +395,8 @@ static void remote_player_send_playerframe(void){
 /*
  * Updates network traffic stats
  */
-static void remote_player_debug_update(void){
+void remote_player_debug_update(void)
+{
    if( (vg.time_real - netplayers.last_data_measurement) > 1.0 ){
       netplayers.last_data_measurement = vg.time_real;
       u32 total_down = 0;
@@ -409,7 +419,8 @@ static void remote_player_debug_update(void){
 /*
  * Debugging information
  */
-static void remote_player_network_imgui( m4x4f pv ){
+void remote_player_network_imgui( m4x4f pv )
+{
    if( network_client.user_intent == k_server_intent_online ){
       if( !(steam_ready &&
          (network_client.state == k_ESteamNetworkingConnectionState_Connected)))
@@ -596,8 +607,8 @@ static void pose_remote_player( u32 index,
 /* 
  * animate remote player and store in final_mtx
  */
-static void animate_remote_player( u32 index ){
-
+void animate_remote_player( u32 index )
+{
    /*
     * Trys to keep the cursor inside the buffer
     */
@@ -652,7 +663,8 @@ static void animate_remote_player( u32 index ){
 /*
  * Update full final_mtx for all remote players
  */
-static void animate_remote_players(void){
+void animate_remote_players(void)
+{
    for( u32 i=0; i<vg_list_size(netplayers.list); i ++ ){
       struct network_player *player = &netplayers.list[i];
       if( !player->active ) continue;
@@ -664,7 +676,8 @@ static void animate_remote_players(void){
 /*
  * Draw remote players
  */
-static void render_remote_players( world_instance *world, camera *cam ){
+void render_remote_players( world_instance *world, vg_camera *cam )
+{
    u32 draw_list[ NETWORK_MAX_PLAYERS ],
        draw_list_count = 0,
        gliders = 0;
@@ -774,7 +787,8 @@ static int remote_players_randomize( int argc, const char *argv[] ){
    return 0;
 }
 
-static void remote_players_init(void){
+void remote_players_init(void)
+{
    vg_console_reg_cmd( "add_test_players", remote_players_randomize, NULL );
    vg_console_reg_var( "k_show_own_name", &k_show_own_name, 
                        k_var_dtype_i32, 0 );
@@ -783,7 +797,8 @@ static void remote_players_init(void){
    }
 }
 
-static void remote_sfx_pre_update(void){
+void remote_sfx_pre_update(void)
+{
    for( u32 i=0; i<NETWORK_SFX_QUEUE_LENGTH; i ++ ){
       struct net_sfx *si = &netplayers.sfx_queue[i];
 
@@ -955,7 +970,8 @@ static void remote_player_gui_info( ui_rect box,
    ui_text( bottom, activity, 1, k_ui_align_middle_center, fg );
 }
 
-static void remote_players_imgui_lobby(void){
+void remote_players_imgui_lobby(void)
+{
    if( network_client.user_intent == k_server_intent_online ){
       if( !(steam_ready &&
          (network_client.state == k_ESteamNetworkingConnectionState_Connected)))
@@ -999,8 +1015,9 @@ static void remote_players_imgui_lobby(void){
    }
 }
 
-static void remote_players_imgui_world( world_instance *world, m4x4f pv,
-                                        f32 max_dist, int geo_cull ){
+void remote_players_imgui_world( world_instance *world, m4x4f pv,
+                                 f32 max_dist, int geo_cull )
+{
    ui_flush( k_ui_shader_colour, vg.window_x, vg.window_y );
 
    for( u32 i=0; i<NETWORK_MAX_PLAYERS; i++ ){
@@ -1070,7 +1087,8 @@ static void chat_enter( char *buf, u32 len ){
    chat_send_message( buf );
 }
 
-static void remote_players_chat_imgui(void){
+void remote_players_chat_imgui(void)
+{
    if( netplayers.chatting == 1 ){
       ui_rect box = { 0, 0, 400, 40 },
               window = { 0, 0, vg.window_x, vg.window_y };
index 2d6200b365c6bbfcc39df8932df95f57ec457bef..2d3250c5b0298d439ffcbdb09fd202f41ce823b2 100644 (file)
@@ -1,14 +1,21 @@
-#ifndef PLAYER_REMOTE_H
-#define PLAYER_REMOTE_H
-
+#pragma once
 #include "player.h"
 #include "network.h"
 #include "network_common.h"
+#include "player_render.h"
 #include "player_effects.h"
+#include "player_api.h"
+
+#include "player_skate.h"
+#include "player_walk.h"
+#include "player_dead.h"
+#include "player_basic_info.h"
+#include "player_glide.h"
 
 #define NETWORK_SFX_QUEUE_LENGTH 12
 
-struct {
+struct global_netplayers
+{
    struct network_player {
       int active, isfriend, isblocked;
       u64 steamid;
@@ -82,14 +89,20 @@ struct {
    char chat_buffer[ NETWORK_MAX_CHAT ], chat_message[ NETWORK_MAX_CHAT ];
    f64 chat_time;
 }
-static netplayers;
-
-static void player_remote_rx_200_300( SteamNetworkingMessage_t *msg );
-static void remote_player_debug_update(void);
-static void remote_player_send_playerframe(void);
-static void animate_remote_player( u32 index );
-static void render_remote_players( world_instance *world, camera *cam );
-static void relink_all_remote_player_worlds(void);
-static void player_remote_update_friendflags( struct network_player *remote );
-
-#endif /* PLAYER_REMOTE_H */
+extern netplayers;
+
+void player_remote_rx_200_300( SteamNetworkingMessage_t *msg );
+void remote_player_debug_update(void);
+void remote_player_send_playerframe(void);
+void animate_remote_player( u32 index );
+void animate_remote_players(void);
+void render_remote_players( world_instance *world, vg_camera *cam );
+void relink_all_remote_player_worlds(void);
+void player_remote_update_friendflags( struct network_player *remote );
+void remote_players_init(void);
+void remote_sfx_pre_update(void);
+void remote_player_network_imgui( m4x4f pv );
+void remote_players_imgui_world( world_instance *world, m4x4f pv,
+                                 f32 max_dist, int geo_cull );
+void remote_players_imgui_lobby(void);
+void remote_players_chat_imgui(void);
index 2707c949a6a00515fb0206bab89ab5a83a26c072..689f7a8b7345684398f3d23719573dc83374c99b 100644 (file)
@@ -1,9 +1,6 @@
-#ifndef PLAYER_RENDER_C
-#define PLAYER_RENDER_C
-
 #include "player.h"
 #include "player_render.h"
-#include "camera.h"
+#include "vg/vg_camera.h"
 #include "player_model.h"
 #include "ent_skateshop.h"
 #include "audio.h"
@@ -19,7 +16,8 @@
 #include "player_remote.h"
 #include "player_glide.h"
 
-static void player_load_animation_reference( const char *path ){
+void player_load_animation_reference( const char *path )
+{
    mdl_context *meta = &localplayer.skeleton_meta;
    mdl_open( meta, path, vg_mem.rtmemory );
    mdl_load_metadata_block( meta, vg_mem.rtmemory );
@@ -90,9 +88,10 @@ static void player_load_animation_reference( const char *path ){
 
 /* TODO: Standard model load */
 
-static void dynamic_model_load( mdl_context *ctx,
-                                struct dynamic_model_1texture *mdl, 
-                                const char *path, u32 *fixup_table ){
+void dynamic_model_load( mdl_context *ctx,
+                         struct dynamic_model_1texture *mdl, 
+                         const char *path, u32 *fixup_table )
+{
    if( !mdl_arrcount( &ctx->textures ) )
       vg_fatal_error( "No texture in model" );
 
@@ -107,15 +106,15 @@ static void dynamic_model_load( mdl_context *ctx,
    mdl_async_load_glmesh( ctx, &mdl->mesh, fixup_table );
 }
 
-static void dynamic_model_unload( struct dynamic_model_1texture *mdl ){
+void dynamic_model_unload( struct dynamic_model_1texture *mdl )
+{
    mesh_free( &mdl->mesh );
    glDeleteTextures( 1, &mdl->texture );
 }
 
 /* TODO: allow error handling */
-static void player_board_load( struct player_board *board, 
-                                  const char *path ){
-
+void player_board_load( struct player_board *board, const char *path )
+{
    vg_linear_clear( vg_mem.scratch );
 
    mdl_context ctx;
@@ -167,11 +166,13 @@ static void player_board_load( struct player_board *board,
    mdl_close( &ctx );
 }
 
-static void player_board_unload( struct player_board *board ){
+void player_board_unload( struct player_board *board )
+{
    dynamic_model_unload( &board->mdl );
 }
 
-static void player_model_load( struct player_model *board, const char *path){
+void player_model_load( struct player_model *board, const char *path)
+{
    vg_linear_clear( vg_mem.scratch );
 
    mdl_context ctx;
@@ -205,12 +206,13 @@ static void player_model_load( struct player_model *board, const char *path){
    mdl_close( &ctx );
 }
 
-static void player_model_unload( struct player_model *board ){
+void player_model_unload( struct player_model *board )
+{
    dynamic_model_unload( &board->mdl );
 }
 
-static void apply_full_skeleton_pose( struct skeleton *sk, player_pose *pose,
-                                      m4x3f *final_mtx ){
+void apply_full_skeleton_pose( struct skeleton *sk, player_pose *pose,
+                               m4x3f *final_mtx ){
    m4x3f transform;
    q_m3x3( pose->root_q, transform );
    v3_copy( pose->root_co, transform[3] );
@@ -232,7 +234,8 @@ static void apply_full_skeleton_pose( struct skeleton *sk, player_pose *pose,
    }
 }
 
-static void player__animate(void){
+void player__animate(void)
+{
    struct player_subsystem_interface *sys = 
       player_subsystems[localplayer.subsystem];
 
@@ -291,8 +294,8 @@ static void player_copy_frame_animator( replay_frame *frame ){
    }
 }
 
-static void lerp_player_pose( player_pose *pose0, player_pose *pose1, f32 t,
-                              player_pose *posed ){
+void lerp_player_pose( player_pose *pose0, player_pose *pose1, f32 t,
+                       player_pose *posed ){
    struct skeleton *sk = &localplayer.skeleton;
    
    v3_lerp( pose0->root_co, pose1->root_co, t, posed->root_co );
@@ -310,7 +313,8 @@ static void lerp_player_pose( player_pose *pose0, player_pose *pose1, f32 t,
    }
 }
 
-static void player__observe_system( enum player_subsystem id ){
+void player__observe_system( enum player_subsystem id )
+{
    if( id != localplayer.observing_system ){
       struct player_subsystem_interface *sysm1 = 
          player_subsystems[ localplayer.observing_system ];
@@ -320,7 +324,8 @@ static void player__observe_system( enum player_subsystem id ){
    }
 }
 
-static void player__animate_from_replay( replay_buffer *replay ){
+void player__animate_from_replay( replay_buffer *replay )
+{
    replay_frame *frame = replay->cursor_frame,
                 *next = NULL;
    if( frame ){
@@ -394,7 +399,8 @@ static void player__animate_from_replay( replay_buffer *replay ){
                              localplayer.final_mtx );
 }
 
-static void player__pre_render(void){
+void player__pre_render(void)
+{
    /* shadowing/ao info */
    struct player_board *board = 
       addon_cache_item_if_loaded( k_addon_type_board,
@@ -415,10 +421,10 @@ static void player__pre_render(void){
    m4x3_mulv( board_mtx, vp1, ubo->g_board_1 );
 }
 
-static void render_board( camera *cam, world_instance *world,
-                          struct player_board *board, m4x3f root,
-                          struct player_board_pose *pose,
-                          enum board_shader shader )
+void render_board( vg_camera *cam, world_instance *world,
+                   struct player_board *board, m4x3f root,
+                   struct player_board_pose *pose,
+                   enum board_shader shader )
 {
    if( !board ) 
       board = &localplayer.fallback_board;
@@ -535,11 +541,12 @@ static void render_board( camera *cam, world_instance *world,
    }
 }
 
-static void render_playermodel( camera *cam, world_instance *world,
-                                int depth_compare,
-                                struct player_model *model,
-                                struct skeleton *skeleton,
-                                m4x3f *final_mtx ){
+void render_playermodel( vg_camera *cam, world_instance *world,
+                         int depth_compare,
+                         struct player_model *model,
+                         struct skeleton *skeleton,
+                         m4x3f *final_mtx )
+{
    if( !model ) return;
    
    shader_model_character_view_use();
@@ -570,7 +577,8 @@ static void render_playermodel( camera *cam, world_instance *world,
    mesh_draw( &model->mdl.mesh );
 }
 
-static void player__render( camera *cam ){
+void player__render( vg_camera *cam )
+{
    world_instance *world = world_current_instance();
    SDL_AtomicLock( &addon_system.sl_cache_using_resources );
 
@@ -596,8 +604,8 @@ static void player__render( camera *cam ){
    glDisable( GL_CULL_FACE );
 }
 
-static void player_mirror_pose( mdl_keyframe pose[32], 
-                                mdl_keyframe mirrored[32] ){
+void player_mirror_pose( mdl_keyframe pose[32], mdl_keyframe mirrored[32] )
+{
    mdl_keyframe temp[32];
 
    struct skeleton *sk = &localplayer.skeleton;
@@ -617,4 +625,3 @@ static void player_mirror_pose( mdl_keyframe pose[32],
       mirrored[i] = temp[i];
    }
 }
-#endif /* PLAYER_RENDER_C */
index ee98488db270dd1524daa58c435376788ab64017..cfc48e78940cd5a67256911682bea13039d8327e 100644 (file)
@@ -1,10 +1,11 @@
-#ifndef PLAYER_RENDER_H
-#define PLAYER_RENDER_H
-
+#pragma once
 #include "model.h"
 #include "skeleton.h"
-#include "camera.h"
+#include "vg/vg_camera.h"
 #include "world.h"
+#include "player_render.h"
+#include "player_api.h"
+#include "player_replay.h"
 
 enum eboard_truck{
    k_board_truck_back = 0,
@@ -46,33 +47,36 @@ enum board_shader{
    k_board_shader_entity
 };
 
-static void dynamic_model_load( mdl_context *ctx,
-                                   struct dynamic_model_1texture *mdl, 
-                                   const char *path, u32 *fixup_table );
-static void dynamic_model_unload( struct dynamic_model_1texture *mdl );
-
-static void player_board_load( struct player_board *mdl, const char *path );
-static void player_board_unload( struct player_board *mdl );
+void dynamic_model_load( mdl_context *ctx,
+                            struct dynamic_model_1texture *mdl, 
+                            const char *path, u32 *fixup_table );
+void dynamic_model_unload( struct dynamic_model_1texture *mdl );
 
-static void player_model_load( struct player_model *board, const char *path);
-static void player_model_unload( struct player_model *board );
+void player_board_load( struct player_board *mdl, const char *path );
+void player_board_unload( struct player_board *mdl );
 
-static void render_board( camera *cam, world_instance *world,
-                             struct player_board *board, m4x3f root,
-                             struct player_board_pose *pose,
-                             enum board_shader shader );
+void player_model_load( struct player_model *board, const char *path);
+void player_model_unload( struct player_model *board );
 
-static void render_playermodel( camera *cam, world_instance *world,
-                                   int depth_compare,
-                                   struct player_model *model,
-                                   struct skeleton *skeleton,
-                                   m4x3f *final_mtx );
-static void apply_full_skeleton_pose( struct skeleton *sk, player_pose *pose,
-                                      m4x3f *final_mtx );
-static void lerp_player_pose( player_pose *pose0, player_pose *pose1, f32 t,
-                              player_pose *posed );
-static void player_mirror_pose( mdl_keyframe pose[32], 
-                                mdl_keyframe mirrored[32] );
-static void player__observe_system( enum player_subsystem id );
+void render_board( vg_camera *cam, world_instance *world,
+                      struct player_board *board, m4x3f root,
+                      struct player_board_pose *pose,
+                      enum board_shader shader );
 
-#endif /* PLAYER_RENDER_H */
+void render_playermodel( vg_camera *cam, world_instance *world,
+                            int depth_compare,
+                            struct player_model *model,
+                            struct skeleton *skeleton,
+                            m4x3f *final_mtx );
+void apply_full_skeleton_pose( struct skeleton *sk, player_pose *pose,
+                               m4x3f *final_mtx );
+void lerp_player_pose( player_pose *pose0, player_pose *pose1, f32 t,
+                       player_pose *posed );
+void player_mirror_pose( mdl_keyframe pose[32], 
+                         mdl_keyframe mirrored[32] );
+void player__observe_system( enum player_subsystem id );
+void player_load_animation_reference( const char *path );
+void player__render( vg_camera *cam );
+void player__animate_from_replay( replay_buffer *replay );
+void player__animate(void);
+void player__pre_render(void);
index b0df4f27183648d87af07d9ffe9c49936db43faa..1994eb68f4f05c8191874e3688fb251e2f46afc6 100644 (file)
@@ -1,12 +1,18 @@
-#ifndef PLAYER_REPLAY_C
-#define PLAYER_REPLAY_C
-
+#include "skaterift.h"
 #include "player_replay.h"
 #include "input.h"
 #include "gui.h"
 #include "freecam.h"
 
-static void replay_clear( replay_buffer *replay ){
+#include "player_walk.h"
+#include "player_skate.h"
+#include "player_dead.h"
+#include "player_glide.h"
+
+struct replay_globals player_replay;
+
+void replay_clear( replay_buffer *replay )
+{
    replay->head = NULL;
    replay->tail = NULL;
    replay->cursor_frame = NULL;
@@ -14,8 +20,8 @@ static void replay_clear( replay_buffer *replay ){
    replay->cursor = -99999.9;
 }
 
-static 
-void * replay_frame_data( replay_frame *frame, enum replay_framedata type ){
+void *replay_frame_data( replay_frame *frame, enum replay_framedata type )
+{
    if( frame->data_table[type][1] == 0 )
       return NULL;
 
@@ -136,7 +142,8 @@ static void replay_emit_frame_sounds( replay_frame *frame ){
    }
 }
 
-static int replay_seek( replay_buffer *replay, f64 t ){
+int replay_seek( replay_buffer *replay, f64 t )
+{
    if( !replay->head ) return 0;
 
    if( t < replay->tail->time ) t = replay->tail->time;
@@ -191,7 +198,8 @@ static int replay_seek( replay_buffer *replay, f64 t ){
    return 0;
 }
 
-static replay_frame *replay_find_recent_stateframe( replay_buffer *replay ){
+replay_frame *replay_find_recent_stateframe( replay_buffer *replay )
+{
    replay_frame *frame = replay->cursor_frame;
    u32 i=4096;
    while( i --> 0 ){
@@ -203,7 +211,8 @@ static replay_frame *replay_find_recent_stateframe( replay_buffer *replay ){
    return NULL;
 }
 
-static f32 replay_subframe_time( replay_buffer *replay ){
+f32 replay_subframe_time( replay_buffer *replay )
+{
    replay_frame *frame = replay->cursor_frame;
    if( !frame ) return 0.0f;
    replay_frame *next = frame->r;
@@ -216,24 +225,26 @@ static f32 replay_subframe_time( replay_buffer *replay ){
       return 0.0f;
 }
 
-static void replay_get_frame_camera( replay_frame *frame, camera *cam ){
+void replay_get_frame_camera( replay_frame *frame, vg_camera *cam )
+{
    cam->fov = frame->cam_fov;
    v3_copy( frame->cam_pos, cam->pos );
    v3_copy( frame->cam_angles, cam->angles );
 }
 
-static void replay_get_camera( replay_buffer *replay, camera *cam ){
+void replay_get_camera( replay_buffer *replay, vg_camera *cam )
+{
    cam->nearz = 0.1f;
    cam->farz = 100.0f;
    if( replay->cursor_frame ){
       replay_frame *next = replay->cursor_frame->r;
 
       if( next ){
-         camera temp;
+         vg_camera temp;
          
          replay_get_frame_camera( replay->cursor_frame, cam );
          replay_get_frame_camera( next, &temp );
-         camera_lerp( cam, &temp, replay_subframe_time( replay ), cam );
+         vg_camera_lerp( cam, &temp, replay_subframe_time( replay ), cam );
       }
       else {
          replay_get_frame_camera( replay->cursor_frame, cam );
@@ -251,8 +262,8 @@ struct replay_rb{
    v4f q;
 };
 
-static void skaterift_record_frame( replay_buffer *replay, 
-                                    int force_gamestate ){
+void skaterift_record_frame( replay_buffer *replay, int force_gamestate )
+{
    f64 delta      = 9999999.9,
        statedelta = 9999999.9;
 
@@ -458,23 +469,23 @@ void skaterift_restore_frame( replay_frame *frame ){
 
    /* chop end off replay */
    frame->r = NULL;
-   skaterift.replay.statehead = frame;
-   skaterift.replay.head = frame;
-   skaterift.replay.cursor_frame = frame;
-   skaterift.replay.cursor = frame->time;
-   skaterift.replay_control = k_replay_control_scrub;
+   player_replay.local.statehead = frame;
+   player_replay.local.head = frame;
+   player_replay.local.cursor_frame = frame;
+   player_replay.local.cursor = frame->time;
+   player_replay.replay_control = k_replay_control_scrub;
    skaterift.activity = k_skaterift_default;
    vg.time = frame->time;
 }
 
 static void skaterift_replay_resume(void){
-   replay_frame *prev = replay_find_recent_stateframe(&skaterift.replay);
+   replay_frame *prev = replay_find_recent_stateframe(&player_replay.local);
 
    if( prev ){
-      skaterift.replay_control = k_replay_control_resume;
-      skaterift.resume_target = prev;
-      skaterift.resume_begin = skaterift.replay.cursor;
-      skaterift.resume_transition = 0.0f;
+      player_replay.replay_control = k_replay_control_resume;
+      player_replay.resume_target = prev;
+      player_replay.resume_begin = player_replay.local.cursor;
+      player_replay.resume_transition = 0.0f;
    }
 
    gui_helper_clear();
@@ -482,40 +493,44 @@ static void skaterift_replay_resume(void){
 
 static void skaterift_replay_update_helpers(void);
 
-static void skaterift_replay_pre_update(void){
+void skaterift_replay_pre_update(void)
+{
    if( skaterift.activity != k_skaterift_replay ) return;
 
-   if( skaterift.replay_control == k_replay_control_resume ){
-      if( skaterift.replay.cursor_frame == skaterift.resume_target ||
-          skaterift.replay.cursor_frame == NULL ){
-         skaterift_restore_frame( skaterift.resume_target );
+   if( player_replay.replay_control == k_replay_control_resume )
+   {
+      if( player_replay.local.cursor_frame == player_replay.resume_target ||
+          player_replay.local.cursor_frame == NULL )
+      {
+         skaterift_restore_frame( player_replay.resume_target );
       }
-      else {
-         vg_slewf( &skaterift.resume_transition, 1.0f, 
+      else 
+      {
+         vg_slewf( &player_replay.resume_transition, 1.0f, 
                    vg.time_frame_delta * (1.0f/1.0f) );
 
-         if( skaterift.resume_transition >= 1.0f )
-            skaterift_restore_frame( skaterift.resume_target );
+         if( player_replay.resume_transition >= 1.0f )
+            skaterift_restore_frame( player_replay.resume_target );
          else {
-            f64 target = vg_lerp( skaterift.resume_begin, 
-                              skaterift.resume_target->time, 
-                              vg_smoothstepf( skaterift.resume_transition ) );
-            if( replay_seek( &skaterift.replay, target ) )
-               skaterift.track_velocity = 1.0f;
+            f64 target = vg_lerp( player_replay.resume_begin, 
+                           player_replay.resume_target->time, 
+                           vg_smoothstepf( player_replay.resume_transition ) );
+            if( replay_seek( &player_replay.local, target ) )
+               player_replay.track_velocity = 1.0f;
             else
-               skaterift.track_velocity = 0.0f;
+               player_replay.track_velocity = 0.0f;
          }
       }
    }
    else {
       if( button_down( k_srbind_replay_play ) )
-         skaterift.replay_control = k_replay_control_play;
+         player_replay.replay_control = k_replay_control_play;
       if( button_down( k_srbind_replay_freecam ) ){
-         skaterift.freecam = skaterift.freecam ^ 0x1;
-
-         if( skaterift.freecam )
-            replay_get_camera( &skaterift.replay, &skaterift.replay_freecam );
+         player_replay.freecam = player_replay.freecam ^ 0x1;
 
+         if( player_replay.freecam )
+            replay_get_camera( &player_replay.local, 
+                               &player_replay.replay_freecam );
          skaterift_replay_update_helpers();
       }
 
@@ -524,32 +539,34 @@ static void skaterift_replay_pre_update(void){
          target_speed += -2.0;
 
       if( fabsf(target_speed) > 0.01f )
-         skaterift.replay_control = k_replay_control_scrub;
+         player_replay.replay_control = k_replay_control_scrub;
 
-      if( skaterift.replay_control == k_replay_control_play )
+      if( player_replay.replay_control == k_replay_control_play )
          target_speed = 1.0;
 
-      vg_slewf( &skaterift.track_velocity, target_speed, 
+      vg_slewf( &player_replay.track_velocity, target_speed, 
                 18.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( fabsf( player_replay.track_velocity ) > 0.0001f )
+      {
+         f64 target = player_replay.local.cursor;
+         target += player_replay.track_velocity * vg.time_frame_delta;
 
-         if( !replay_seek( &skaterift.replay, target ) )
-            skaterift.track_velocity = 0.0f;
+         if( !replay_seek( &player_replay.local, target ) )
+            player_replay.track_velocity = 0.0f;
       }
 
-      if( button_down( k_srbind_mback ) ){
-         if( skaterift.replay.statehead )
-            skaterift_restore_frame( skaterift.replay.statehead );
+      if( button_down( k_srbind_mback ) )
+      {
+         if( player_replay.local.statehead )
+            skaterift_restore_frame( player_replay.local.statehead );
          else
             skaterift.activity = k_skaterift_default;
          srinput.state = k_input_state_resume;
          gui_helper_clear();
       }
 
-      if( skaterift.freecam ){
+      if( player_replay.freecam ){
          //freecam_preupdate();
       }
       else {
@@ -561,31 +578,35 @@ static void skaterift_replay_pre_update(void){
 }
 
 static void skaterift_replay_update_helpers(void){
-   skaterift.helper_resume->greyed = skaterift.freecam;
+   player_replay.helper_resume->greyed = player_replay.freecam;
 
    vg_str freecam_text;
-   vg_strnull( &freecam_text, skaterift.helper_freecam->text, 
+   vg_strnull( &freecam_text, player_replay.helper_freecam->text, 
                GUI_HELPER_TEXT_LENGTH );
-   vg_strcat( &freecam_text, skaterift.freecam? "exit freecam": "freecam" );
+   vg_strcat( &freecam_text, player_replay.freecam? "exit freecam": "freecam" );
 }
 
-static void skaterift_replay_post_render(void){
+void skaterift_replay_post_render(void)
+{
 #ifndef SR_ALLOW_REWIND_HUB
    if( world_static.active_instance != k_world_purpose_client )
       return;
 #endif
 
    /* capture the current resume frame at the very last point */
-   if( button_down( k_srbind_reset ) ){
-      if( skaterift.activity == k_skaterift_default ){
+   if( button_down( k_srbind_reset ) )
+   {
+      if( skaterift.activity == k_skaterift_default )
+      {
          localplayer.rewinded_since_last_gate = 1;
          skaterift.activity = k_skaterift_replay;
-         skaterift_record_frame( &skaterift.replay, 1 );
-         if( skaterift.replay.head ){
-            skaterift.replay.cursor = skaterift.replay.head->time;
-            skaterift.replay.cursor_frame = skaterift.replay.head;
+         skaterift_record_frame( &player_replay.local, 1 );
+         if( player_replay.local.head )
+         {
+            player_replay.local.cursor = player_replay.local.head->time;
+            player_replay.local.cursor_frame = player_replay.local.head;
          }
-         skaterift.replay_control = k_replay_control_scrub;
+         player_replay.replay_control = k_replay_control_scrub;
 
          gui_helper_clear();
          vg_str text;
@@ -593,14 +614,14 @@ static void skaterift_replay_post_render(void){
          if( gui_new_helper( input_axis_list[k_sraxis_replay_h], &text ) )
             vg_strcat( &text, "scrub" );
 
-         if( (skaterift.helper_resume = gui_new_helper( 
+         if( (player_replay.helper_resume = gui_new_helper( 
                      input_button_list[k_srbind_replay_resume], &text )) )
             vg_strcat( &text, "resume" );
          
          if( gui_new_helper( input_button_list[k_srbind_replay_play], &text ))
             vg_strcat( &text, "playback" );
 
-         skaterift.helper_freecam = gui_new_helper(
+         player_replay.helper_freecam = gui_new_helper(
                input_button_list[k_srbind_replay_freecam], &text );
 
          skaterift_replay_update_helpers();
@@ -608,10 +629,10 @@ static void skaterift_replay_post_render(void){
    }
 }
 
-static void skaterift_replay_debug_info(void){
+void skaterift_replay_debug_info(void)
+{
    player__debugtext( 2, "replay info" );
-
-   replay_buffer *replay = &skaterift.replay;
+   replay_buffer *replay = &player_replay.local;
 
    u32 head = 0,
        tail = 0;
@@ -645,10 +666,11 @@ static void skaterift_replay_debug_info(void){
    player__debugtext( 1, "cursor: %.2fs / %.2fs\n", cur, len );
 }
 
-static void skaterift_replay_imgui(void){
+void skaterift_replay_imgui(void)
+{
    if( skaterift.activity != k_skaterift_replay ) return;
 
-   replay_buffer *replay = &skaterift.replay;
+   replay_buffer *replay = &player_replay.local;
    f64 start = replay->cursor,
        end   = replay->cursor;
    if( replay->tail ) start = replay->tail->time;
@@ -704,5 +726,3 @@ static void skaterift_replay_imgui(void){
    ui_text( bar, buffer, 1, k_ui_align_middle_left, 0 );
    ui_text( bar, "0s", 1, k_ui_align_middle_right, 0 );
 }
-
-#endif /* PLAYER_REPLAY_C */
index 38ea25308ff981b1284b5955257e548f3b0e2b08..b7f4a57e91ede4af0ebe8a50bf201ad3b40647ff 100644 (file)
@@ -1,9 +1,6 @@
-#ifndef PLAYER_REPLAY_H
-#define PLAYER_REPLAY_H
-
-#include "skaterift.h"
-#include "player.h"
+#pragma once
 #include "player_render.h"
+#include "vg/vg_rigidbody.h"
 
 typedef struct replay_buffer replay_buffer;
 typedef struct replay_frame replay_frame;
@@ -60,20 +57,41 @@ struct replay_sfx {
    u32 none;
 };
 
-static int replay_seek( replay_buffer *replay, f64 t );
+struct replay_globals 
+{
+   replay_buffer local;
+   replay_frame *resume_target;
+   f64 resume_begin;
+   f32 resume_transition;
+
+   enum replay_control {
+      k_replay_control_scrub,
+      k_replay_control_play,
+      k_replay_control_resume
+   }
+   replay_control;
+   f32 track_velocity;
+   struct gui_helper *helper_resume, *helper_freecam;
+
+   vg_camera replay_freecam;
+   i32 freecam;
+   v3f freecam_v, freecam_w;
+}
+extern player_replay;
 
-static replay_frame *replay_find_recent_stateframe( replay_buffer *replay );
-static void replay_get_camera( replay_buffer *replay, camera *cam );
-static void replay_get_frame_camera( replay_frame *frame, camera *cam );
-static f32 replay_subframe_time( replay_buffer *replay );
-static void replay_clear( replay_buffer *replay );
-static void *
+int replay_seek( replay_buffer *replay, f64 t );
+
+replay_frame *replay_find_recent_stateframe( replay_buffer *replay );
+void replay_get_camera( replay_buffer *replay, vg_camera *cam );
+void replay_get_frame_camera( replay_frame *frame, vg_camera *cam );
+f32 replay_subframe_time( replay_buffer *replay );
+void replay_clear( replay_buffer *replay );
+void *
 replay_frame_data( replay_frame *frame, enum replay_framedata type );
 
-static void skaterift_replay_pre_update(void);
-static void skaterift_replay_imgui(void);
-static void skaterift_replay_debug_info(void);
-static void skaterift_record_frame( replay_buffer *replay, 
+void skaterift_replay_pre_update(void);
+void skaterift_replay_imgui(void);
+void skaterift_replay_debug_info(void);
+void skaterift_record_frame( replay_buffer *replay, 
                                     int force_gamestate );
-
-#endif /* PLAYER_REPLAY_H */
+void skaterift_replay_post_render(void);
index b193173b888960bc497c9d2cfecf520a7fdf7171..11ff6ae8348e88bfda5862532b2905de5bf84344 100644 (file)
@@ -1,6 +1,4 @@
-#ifndef PLAYER_SKATE_C
-#define PLAYER_SKATE_C
-
+#include "player_skate.h"
 #include "player.h"
 #include "audio.h"
 #include "vg/vg_perlin.h"
@@ -8,13 +6,39 @@
 #include "menu.h"
 #include "ent_skateshop.h"
 #include "addon.h"
+#include "input.h"
+#include "ent_tornado.h"
 
-#include "ent_tornado.c"
 #include "vg/vg_rigidbody.h"
 #include "scene_rigidbody.h"
 #include "player_glide.h"
+#include "player_dead.h"
+#include "player_walk.h"
+
+struct player_skate player_skate;
+struct player_subsystem_interface player_subsystem_skate = 
+{
+   .system_register = player__skate_register,
+   .bind = player__skate_bind,
+   .pre_update = player__skate_pre_update,
+   .update = player__skate_update,
+   .post_update = player__skate_post_update,
+   .im_gui = player__skate_im_gui,
+   .animate = player__skate_animate,
+   .pose = player__skate_pose,
+   .effects = player__skate_effects,
+   .post_animate = player__skate_post_animate,
+   .network_animator_exchange = player__skate_animator_exchange,
+   .sfx_oneshot = player__skate_sfx_oneshot,
+   .sfx_comp = player__skate_comp_audio,
+   .sfx_kill = player__skate_kill_audio,
+
+   .animator_data = &player_skate.animator,
+   .animator_size = sizeof(player_skate.animator),
+   .name = "Skate"
+};
 
-static void player__skate_bind(void){
+void player__skate_bind(void){
    struct skeleton *sk = &localplayer.skeleton;
    rb_update_matrices( &localplayer.rb );
 
@@ -38,7 +62,7 @@ static void player__skate_bind(void){
       *bindings[i].anim = skeleton_get_anim( sk, bindings[i].name );
 }
 
-static void player__skate_kill_audio(void){
+void player__skate_kill_audio(void){
    audio_lock();
    if( player_skate.aud_main ){
       player_skate.aud_main = 
@@ -342,7 +366,8 @@ static int create_jumps_to_hit_target( jump_info *jumps,
    return valid_count;
 }
 
-static void player__approximate_best_trajectory(void){
+void player__approximate_best_trajectory(void)
+{
    world_instance *world0 = world_current_instance();
 
    float k_trace_delta = vg.time_fixed_delta * 10.0f;
@@ -1161,7 +1186,7 @@ static enum trick_type player_skate_trick_input(void){
           (button_press( k_srbind_trick2 )     );
 }
 
-static void player__skate_pre_update(void){
+void player__skate_pre_update(void){
    struct player_skate_state *state = &player_skate.state;
 
    if( state->activity == k_skate_activity_handplant ){
@@ -1286,7 +1311,7 @@ static void player__skate_pre_update(void){
       state->trick_type = k_trick_type_none;
 }
 
-static void player__skate_comp_audio( void *_animator ){
+void player__skate_comp_audio( void *_animator ){
    struct player_skate_animator *animator = _animator;
    audio_lock();
 
@@ -1302,7 +1327,7 @@ static void player__skate_comp_audio( void *_animator ){
    f32 gate = skaterift.time_rate;
 
    if( skaterift.activity == k_skaterift_replay ){
-      gate = vg_minf( 1.0f, fabsf(skaterift.track_velocity) );
+      gate = vg_minf( 1.0f, fabsf(player_replay.track_velocity) );
    }
 
    f32
@@ -1430,7 +1455,7 @@ static void player__skate_comp_audio( void *_animator ){
    audio_unlock();
 }
 
-static void player__skate_post_update(void){
+void player__skate_post_update(void){
    struct player_skate_state *state = &player_skate.state;
 
    for( int i=0; i<player_skate.possible_jump_count; i++ ){
@@ -2200,7 +2225,7 @@ static enum skate_activity skate_availible_grind(void){
    return new_activity;
 }
 
-static void player__skate_update(void){
+void player__skate_update(void){
    struct player_skate_state *state = &player_skate.state;
    world_instance *world = world_current_instance();
 
@@ -2779,7 +2804,7 @@ begin_collision:;
    }
 }
 
-static void player__skate_im_gui(void){
+void player__skate_im_gui(void){
    struct player_skate_state *state = &player_skate.state;
    player__debugtext( 1, "V:  %5.2f %5.2f %5.2f",localplayer.rb.v[0],
                                                 localplayer.rb.v[1],
@@ -2824,7 +2849,7 @@ static void player__skate_im_gui(void){
                            state->trick_euler[2] );
 }
 
-static void player__skate_animate(void){
+void player__skate_animate(void){
    struct player_skate_state *state = &player_skate.state;
    struct player_skate_animator *animator = &player_skate.animator;
 
@@ -3113,7 +3138,7 @@ static void player__skate_animate(void){
    animator->handplant_t = state->handplant_t;
 }
                         
-static void player__skate_pose( void *_animator, player_pose *pose ){
+void player__skate_pose( void *_animator, player_pose *pose ){
    struct skeleton *sk = &localplayer.skeleton;
    struct player_skate_animator *animator = _animator;
 
@@ -3436,7 +3461,7 @@ static void player__skate_pose( void *_animator, player_pose *pose ){
 #endif
 }
 
-static void player__skate_effects( void *_animator, m4x3f *final_mtx,
+void player__skate_effects( void *_animator, m4x3f *final_mtx,
                                    struct player_board *board,
                                    struct player_effects_data *effect_data ){
    struct skeleton *sk = &localplayer.skeleton;
@@ -3503,7 +3528,7 @@ static void player__skate_effects( void *_animator, m4x3f *final_mtx,
    }
 }
 
-static void player__skate_post_animate(void){
+void player__skate_post_animate(void){
    struct player_skate_state *state = &player_skate.state;
    localplayer.cam_velocity_influence = 1.0f;
    localplayer.cam_dist = 1.8f;
@@ -3515,7 +3540,7 @@ static void player__skate_post_animate(void){
               state->head_position, state->head_position );
 }
 
-static void player__skate_reset_animator(void){
+void player__skate_reset_animator(void){
    struct player_skate_state *state = &player_skate.state;
 
    memset( &player_skate.animator, 0, sizeof(player_skate.animator) );
@@ -3526,7 +3551,7 @@ static void player__skate_reset_animator(void){
       player_skate.animator.fly = 0.0f;
 }
 
-static void player__skate_clear_mechanics(void){
+void player__skate_clear_mechanics(void){
    struct player_skate_state *state = &player_skate.state;
    state->jump_charge    = 0.0f;
    state->charging_jump  = 0;
@@ -3565,7 +3590,7 @@ static void player__skate_clear_mechanics(void){
 
 #include "network_compression.h"
 
-static void player__skate_animator_exchange( bitpack_ctx *ctx, void *data ){
+void player__skate_animator_exchange( bitpack_ctx *ctx, void *data ){
    struct player_skate_animator *animator = data;
    
    bitpack_qv3f( ctx, 24, -1024.0f, 1024.0f, animator->root_co );
@@ -3617,7 +3642,7 @@ static void player__skate_animator_exchange( bitpack_ctx *ctx, void *data ){
    bitpack_bytes( ctx, 1, &animator->activity );
 }
 
-static void player__skate_sfx_oneshot( u8 id, v3f pos, f32 volume ){
+void player__skate_sfx_oneshot( u8 id, v3f pos, f32 volume ){
    audio_lock();
 
    if( id == k_player_skate_soundeffect_jump ){
@@ -3645,5 +3670,3 @@ static void player__skate_sfx_oneshot( u8 id, v3f pos, f32 volume ){
 
    audio_unlock();
 }
-
-#endif /* PLAYER_SKATE_C */
index 4118fd63f8552b8c8647c69225772db21d744a7b..b6e23f5177325d1a94d8fc1dea7919cc5cc20dda 100644 (file)
@@ -1,6 +1,5 @@
-#ifndef PLAYER_SKATE_H
-#define PLAYER_SKATE_H
-
+#pragma once
+#include "vg/vg_audio.h"
 #include "player.h"
 #include "player_api.h"
 
@@ -208,7 +207,8 @@ struct player_skate{
    limits[3];
    u32 limit_count;
 }
-static player_skate;
+extern player_skate;
+extern struct player_subsystem_interface player_subsystem_skate;
 
 enum player_skate_soundeffect {
    k_player_skate_soundeffect_jump,
@@ -302,45 +302,22 @@ static void player__skate_register(void){
    VG_VAR_F32( k_anim_transition,      flags=VG_VAR_CHEAT );
 }
 
-static void player__skate_bind         (void);
-static void player__skate_pre_update   (void);
-static void player__skate_update       (void);
-static void player__skate_post_update  (void);
-static void player__skate_im_gui       (void);
-static void player__skate_animate      (void);
-static void player__skate_pose         (void *animator, player_pose *pose);
-static void player__skate_effects( void *_animator, m4x3f *final_mtx,
-                                   struct player_board *board,
-                                   struct player_effects_data *effect_data );
-static void player__skate_post_animate (void);
-static void player__skate_animator_exchange( bitpack_ctx *ctx, void *data );
-static void player__skate_sfx_oneshot  ( u8 id, v3f pos, f32 volume );
-
-static void player__skate_clear_mechanics(void);
-static void player__skate_reset_animator(void);
-static void player__approximate_best_trajectory(void);
-static void player__skate_comp_audio( void *animator );
-static void player__skate_kill_audio(void);
-
-struct player_subsystem_interface static player_subsystem_skate = {
-   .system_register = player__skate_register,
-   .bind = player__skate_bind,
-   .pre_update = player__skate_pre_update,
-   .update = player__skate_update,
-   .post_update = player__skate_post_update,
-   .im_gui = player__skate_im_gui,
-   .animate = player__skate_animate,
-   .pose = player__skate_pose,
-   .effects = player__skate_effects,
-   .post_animate = player__skate_post_animate,
-   .network_animator_exchange = player__skate_animator_exchange,
-   .sfx_oneshot = player__skate_sfx_oneshot,
-   .sfx_comp = player__skate_comp_audio,
-   .sfx_kill = player__skate_kill_audio,
-
-   .animator_data = &player_skate.animator,
-   .animator_size = sizeof(player_skate.animator),
-   .name = "Skate"
-};
-
-#endif /* PLAYER_SKATE_H */
+void player__skate_bind         (void);
+void player__skate_pre_update   (void);
+void player__skate_update       (void);
+void player__skate_post_update  (void);
+void player__skate_im_gui       (void);
+void player__skate_animate      (void);
+void player__skate_pose         (void *animator, player_pose *pose);
+void player__skate_effects( void *_animator, m4x3f *final_mtx,
+                            struct player_board *board,
+                            struct player_effects_data *effect_data );
+void player__skate_post_animate (void);
+void player__skate_animator_exchange( bitpack_ctx *ctx, void *data );
+void player__skate_sfx_oneshot  ( u8 id, v3f pos, f32 volume );
+
+void player__skate_clear_mechanics(void);
+void player__skate_reset_animator(void);
+void player__approximate_best_trajectory(void);
+void player__skate_comp_audio( void *animator );
+void player__skate_kill_audio(void);
index d673584db88b691c0917bd64e576ad09f2a5ff4d..68415dd7d4c619907ec295ba8e3460415928452d 100644 (file)
@@ -1,11 +1,35 @@
 #pragma once
 
 #include "vg/vg_rigidbody_collision.h"
-#include "scene_rigidbody.h"
 
+#include "skaterift.h"
+#include "player_walk.h"
+#include "player_skate.h"
+#include "player_dead.h"
 #include "player.h"
 #include "input.h"
 #include "audio.h"
+#include "scene_rigidbody.h"
+
+struct player_walk player_walk;
+struct player_subsystem_interface player_subsystem_walk = 
+{
+   .system_register = player__walk_register,
+   .bind = player__walk_bind,
+   .pre_update = player__walk_pre_update,
+   .update = player__walk_update,
+   .post_update = player__walk_post_update,
+   .im_gui = player__walk_im_gui,
+   .animate = player__walk_animate,
+   .post_animate = player__walk_post_animate,
+   .pose = player__walk_pose,
+   .network_animator_exchange = player__walk_animator_exchange,
+
+   .animator_data = &player_walk.animator,
+   .animator_size = sizeof(player_walk.animator),
+   .name = "Walk"
+};
+
 
 static void player_walk_drop_in_vector( v3f vec ){
    v3f axis, init_dir;
@@ -341,7 +365,7 @@ static void player_walk_pre_popoff(void){
    }
 }
 
-static void player__walk_pre_update(void){
+void player__walk_pre_update(void){
    struct player_walk *w = &player_walk;
 
    if( localplayer.immobile ) return;
@@ -683,7 +707,7 @@ static void player_walk_update_generic(void){
                             k_runspeed );
 }
 
-static void player__walk_post_update(void){
+void player__walk_post_update(void){
    struct player_walk *w = &player_walk;
 
    m4x3f mtx;
@@ -737,22 +761,19 @@ static void player__walk_post_update(void){
       audio_lock();
       if( w->surface == k_surface_prop_concrete ){
          audio_oneshot_3d( 
-               &audio_footsteps[vg_randu32(&vg.rand) % 
-                                 vg_list_size(audio_footsteps)], 
+               &audio_footsteps[vg_randu32(&vg.rand) % 4],
                localplayer.rb.co, 40.0f, 1.0f 
          );
       }
       else if( w->surface == k_surface_prop_grass ){
          audio_oneshot_3d( 
-           &audio_footsteps_grass[ vg_randu32(&vg.rand) %
-                                    vg_list_size(audio_footsteps_grass)],
+           &audio_footsteps_grass[ vg_randu32(&vg.rand) % 6 ],
             localplayer.rb.co, 40.0f, 1.0f 
          );
       }
       else if( w->surface == k_surface_prop_wood ){
          audio_oneshot_3d( 
-           &audio_footsteps_wood[ vg_randu32(&vg.rand) %
-                                    vg_list_size(audio_footsteps_wood)],
+           &audio_footsteps_wood[ vg_randu32(&vg.rand) % 6 ],
             localplayer.rb.co, 40.0f, 1.0f 
          );
       }
@@ -762,7 +783,7 @@ static void player__walk_post_update(void){
    w->state.step_phase = walk_phase;
 }
 
-static void player__walk_update(void){
+void player__walk_update(void){
    struct player_walk *w = &player_walk;
 
    if( (w->state.activity == k_walk_activity_air) ||
@@ -842,7 +863,7 @@ static void player_walk_animate_generic(void){
    q_mul( localplayer.rb.q, qrev, animator->root_q );
 }
 
-static void player__walk_animate(void){
+void player__walk_animate(void){
    struct player_walk *w = &player_walk;
    player_pose *pose = &localplayer.pose;
    struct player_walk_animator *animator = &w->animator;
@@ -978,7 +999,7 @@ static void player_walk_pose_transition(
       skeleton_lerp_pose( sk, apose, bpose, blend, pose->keyframes );
 }
 
-static void player__walk_pose( void *_animator, player_pose *pose ){
+void player__walk_pose( void *_animator, player_pose *pose ){
    struct player_walk *w = &player_walk;
    struct player_walk_animator *animator = _animator;
    struct skeleton *sk = &localplayer.skeleton;
@@ -1073,7 +1094,7 @@ static void player__walk_pose( void *_animator, player_pose *pose ){
    }
 }
 
-static void player__walk_post_animate(void){
+void player__walk_post_animate(void){
    /* 
     * Camera 
     */
@@ -1081,7 +1102,7 @@ static void player__walk_post_animate(void){
 
 }
 
-static void player__walk_im_gui(void){
+void player__walk_im_gui(void){
    struct player_walk *w = &player_walk;
    player__debugtext( 1, "V:  %5.2f %5.2f %5.2f (%5.2fm/s)",
       localplayer.rb.v[0], localplayer.rb.v[1], localplayer.rb.v[2],
@@ -1112,7 +1133,7 @@ static void player__walk_im_gui(void){
                                              [w->surface] );
 }
 
-static void player__walk_bind(void){
+void player__walk_bind(void){
    struct player_walk *w = &player_walk;
    struct skeleton *sk = &localplayer.skeleton;
 
@@ -1127,7 +1148,7 @@ static void player__walk_bind(void){
    w->anim_popoff       = skeleton_get_anim( sk, "pop_off_short" );
 }
 
-static void player__walk_transition( bool grounded, f32 board_yaw ){
+void player__walk_transition( bool grounded, f32 board_yaw ){
    struct player_walk *w = &player_walk;
    w->state.activity = k_walk_activity_air;
 
@@ -1144,7 +1165,8 @@ static void player__walk_transition( bool grounded, f32 board_yaw ){
    rb_update_matrices( &localplayer.rb );
 }
 
-static void player__walk_reset(void){
+void player__walk_reset(void)
+{
    struct player_walk *w = &player_walk;
    w->state.activity = k_walk_activity_air;
    w->state.transition_t = 0.0f;
@@ -1157,7 +1179,7 @@ static void player__walk_reset(void){
    rb_update_matrices( &localplayer.rb );
 }
 
-static void player__walk_animator_exchange( bitpack_ctx *ctx, void *data ){
+void player__walk_animator_exchange( bitpack_ctx *ctx, void *data ){
    struct player_walk_animator *animator = data;
 
    bitpack_qv3f( ctx, 24, -1024.0f, 1024.0f, animator->root_co );
@@ -1182,7 +1204,7 @@ static void player__walk_animator_exchange( bitpack_ctx *ctx, void *data ){
    bitpack_qf32( ctx, 16, -100.0f, 100.0f, &animator->board_yaw );
 }
 
-static void player__walk_sfx_oneshot( u8 id, v3f pos, f32 volume ){
+void player__walk_sfx_oneshot( u8 id, v3f pos, f32 volume ){
    audio_lock();
 
    if( id == k_player_walk_soundeffect_splash ){
index 95ce2a0414e55ee7976e684933ff97575bac40c8..b1213547c3d469c857a67a9a0417025bc3af1e53 100644 (file)
@@ -1,13 +1,12 @@
-#ifndef PLAYER_WALK_H
-#define PLAYER_WALK_H
-
+#pragma once
 #include "player.h"
 #include "player_api.h"
 #include "vg/vg_rigidbody.h"
 
 #define PLAYER_JUMP_EPSILON 0.1     /* 100ms jump allowance */
 
-struct player_walk{
+struct player_walk
+{
    rb_capsule collider;
 
    struct player_walk_state{
@@ -68,7 +67,8 @@ struct player_walk{
    }
    animator;
 }
-static player_walk;
+extern player_walk;
+extern struct player_subsystem_interface player_subsystem_walk;
 
 enum player_walk_soundeffect {
    k_player_walk_soundeffect_splash
@@ -97,34 +97,15 @@ static void player__walk_register(void){
    VG_VAR_F32( k_walk_accel,     flags=VG_VAR_CHEAT );
 }
 
-static void player__walk_pre_update  (void);
-static void player__walk_update      (void);
-static void player__walk_post_update (void);
-static void player__walk_animate     (void);
-static void player__walk_pose        (void *animator, player_pose *pose);
-static void player__walk_post_animate(void);
-static void player__walk_im_gui      (void);
-static void player__walk_bind        (void);
-static void player__walk_reset       (void);
-static void player__walk_restore     (void);
-static void player__walk_animator_exchange( bitpack_ctx *ctx, void *data );
-static void player__walk_transition( bool grounded, f32 board_yaw );
-
-struct player_subsystem_interface static player_subsystem_walk = {
-   .system_register = player__walk_register,
-   .bind = player__walk_bind,
-   .pre_update = player__walk_pre_update,
-   .update = player__walk_update,
-   .post_update = player__walk_post_update,
-   .im_gui = player__walk_im_gui,
-   .animate = player__walk_animate,
-   .post_animate = player__walk_post_animate,
-   .pose = player__walk_pose,
-   .network_animator_exchange = player__walk_animator_exchange,
-
-   .animator_data = &player_walk.animator,
-   .animator_size = sizeof(player_walk.animator),
-   .name = "Walk"
-};
-
-#endif /* PLAYER_WALK_H */
+void player__walk_pre_update  (void);
+void player__walk_update      (void);
+void player__walk_post_update (void);
+void player__walk_animate     (void);
+void player__walk_pose        (void *animator, player_pose *pose);
+void player__walk_post_animate(void);
+void player__walk_im_gui      (void);
+void player__walk_bind        (void);
+void player__walk_reset       (void);
+void player__walk_restore     (void);
+void player__walk_animator_exchange( bitpack_ctx *ctx, void *data );
+void player__walk_transition( bool grounded, f32 board_yaw );
diff --git a/render.c b/render.c
new file mode 100644 (file)
index 0000000..ae11b8b
--- /dev/null
+++ b/render.c
@@ -0,0 +1,718 @@
+#include "render.h"
+
+struct framebuffer framebuffers[] = 
+{
+   {
+      /*
+       * The primary draw target
+       */
+      "main", 
+      .link = &gpipeline.fb_main,
+      .resolution_div = 1,
+      .attachments = 
+      {
+         {
+            "colour", k_framebuffer_attachment_type_texture,
+
+            .internalformat = GL_RGB,
+            .format         = GL_RGB,
+            .type           = GL_UNSIGNED_BYTE,
+            .attachment     = GL_COLOR_ATTACHMENT0
+         },
+         {
+            "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
+         },
+         {
+#if 0
+            "depth_stencil", k_framebuffer_attachment_type_renderbuffer,
+
+            .internalformat = GL_DEPTH24_STENCIL8,
+#else
+            "depth_stencil", k_framebuffer_attachment_type_texture_depth,
+            .internalformat = GL_DEPTH24_STENCIL8,
+            .format         = GL_DEPTH_STENCIL,
+            .type           = GL_UNSIGNED_INT_24_8,
+#endif
+            .attachment     = GL_DEPTH_STENCIL_ATTACHMENT
+         }
+      }
+   },
+   {
+      /*
+       * Second rendered view from the perspective of the water reflection
+       */
+      "water_reflection",
+      .link = &gpipeline.fb_water_reflection,
+      .resolution_div = 2,
+      .attachments = 
+      {
+         {
+            "colour", k_framebuffer_attachment_type_texture,
+            .internalformat = GL_RGB,
+            .format         = GL_RGB,
+            .type           = GL_UNSIGNED_BYTE,
+            .attachment     = GL_COLOR_ATTACHMENT0
+         },
+         {
+            "depth_stencil", k_framebuffer_attachment_type_renderbuffer,
+
+            .internalformat = GL_DEPTH24_STENCIL8,
+            .attachment     = GL_DEPTH_STENCIL_ATTACHMENT
+         }
+      }
+   },
+   {
+      /*
+       * Thid rendered view from the perspective of the camera, but just 
+       * captures stuff thats under the water
+       */
+      "water_beneath",
+      .link = &gpipeline.fb_water_beneath,
+      .resolution_div = 2,
+      .attachments = 
+      {
+         {
+            "colour", k_framebuffer_attachment_type_texture,
+            .internalformat = GL_RED,
+            .format         = GL_RED,
+            .type           = GL_UNSIGNED_BYTE,
+            .attachment     = GL_COLOR_ATTACHMENT0
+         },
+         {
+            "depth_stencil", k_framebuffer_attachment_type_renderbuffer,
+
+            .internalformat = GL_DEPTH24_STENCIL8,
+            .attachment     = GL_DEPTH_STENCIL_ATTACHMENT
+         }
+      }
+   },
+   {
+      "workshop_preview",
+      .link = &gpipeline.fb_workshop_preview,
+      .resolution_div = 0,
+      .fixed_w = WORKSHOP_PREVIEW_WIDTH, .fixed_h = WORKSHOP_PREVIEW_HEIGHT,
+      .attachments = 
+      {
+         {
+            "colour", k_framebuffer_attachment_type_texture,
+            .internalformat = GL_RGB,
+            .format         = GL_RGB,
+            .type           = GL_UNSIGNED_BYTE,
+            .attachment     = GL_COLOR_ATTACHMENT0
+         },
+         {
+            "depth_stencil", k_framebuffer_attachment_type_renderbuffer,
+            .internalformat = GL_DEPTH24_STENCIL8,
+            .attachment = GL_DEPTH_STENCIL_ATTACHMENT
+         }
+      }
+   },
+   {
+      "network_status_ui",
+      .link = &gpipeline.fb_network_status,
+      .resolution_div = 0,
+      .fixed_w = 128, .fixed_h = 48,
+      .attachments = 
+      {
+         {
+            "colour", k_framebuffer_attachment_type_texture,
+            .internalformat = GL_RGB,
+            .format         = GL_RGB,
+            .type           = GL_UNSIGNED_BYTE,
+            .attachment     = GL_COLOR_ATTACHMENT0
+         }
+      }
+   }
+};
+
+/* 
+ * Get the current (automatically scaled or fixed) resolution of framebuffer
+ */
+void render_fb_get_current_res( struct framebuffer *fb, int *x, int *y )
+{
+   if( fb->resolution_div ){
+      *x = vg.window_x / fb->resolution_div;
+      *y = vg.window_y / fb->resolution_div;
+   }
+   else{
+      *x = fb->fixed_w;
+      *y = fb->fixed_h;
+   }
+}
+
+void render_fb_inverse_ratio( framebuffer *fb, v2f inverse )
+{
+   if( fb ){
+      int x, y;
+      render_fb_get_current_res( fb, &x, &y );
+
+      v2f render   = { fb->render_w, fb->render_h },
+          original = { x, y };
+
+      v2_div( render, original, inverse );
+   }
+   else{
+      v2_div( (v2f){1.0f,1.0f}, (v2f){ vg.window_x, vg.window_y }, inverse );
+   }
+}
+
+/*
+ * Bind framebuffer for drawing to
+ */
+void render_fb_bind( framebuffer *fb, int use_scaling )
+{
+   int x, y;
+   render_fb_get_current_res( fb, &x, &y );
+
+   if( use_scaling ){
+      x = k_render_scale*(float)x;
+      y = k_render_scale*(float)y;
+
+      x = VG_MAX( 16, x );
+      y = VG_MAX( 16, y );
+
+      fb->render_w = x;
+      fb->render_h = y;
+   }
+
+   glBindFramebuffer( GL_FRAMEBUFFER, fb->fb );
+   glViewport( 0, 0, x, y );
+}
+
+/*
+ * Bind framebuffer attachment's texture
+ */
+void render_fb_bind_texture( framebuffer *fb, int attachment, int slot )
+{
+   struct framebuffer_attachment *at = &fb->attachments[attachment];
+
+   if( (at->purpose != k_framebuffer_attachment_type_texture) &&
+       (at->purpose != k_framebuffer_attachment_type_texture_depth) )
+   {
+      vg_fatal_error( "illegal operation: bind non-texture framebuffer"
+                          " attachment to texture slot" );
+   }
+
+   glActiveTexture( GL_TEXTURE0 + slot );
+   glBindTexture( GL_TEXTURE_2D, fb->attachments[attachment].id );
+}
+
+
+/*
+ * Shaders
+ */
+
+#define FB_FORMAT_STR( E ) { E, #E },
+
+/* 
+ * Convert OpenGL attachment ID enum to string
+ */
+static const char *render_fb_attachment_str( GLenum e )
+{
+   struct { GLenum e; const char *str; }
+   formats[] =
+   { 
+      FB_FORMAT_STR(GL_COLOR_ATTACHMENT0)
+      FB_FORMAT_STR(GL_COLOR_ATTACHMENT1)
+      FB_FORMAT_STR(GL_COLOR_ATTACHMENT2)
+      FB_FORMAT_STR(GL_COLOR_ATTACHMENT3)
+      FB_FORMAT_STR(GL_COLOR_ATTACHMENT4)
+      FB_FORMAT_STR(GL_DEPTH_STENCIL_ATTACHMENT)
+   };
+
+   for( int i=0; i<vg_list_size(formats); i++ )
+      if( formats[i].e == e )
+         return formats[i].str;
+
+   return "UNDEFINED";
+}
+
+/*
+ * Convert OpenGL texture format enums from TexImage2D table 1,2 &
+ * RenderBufferStorage Table 1, into strings
+ */
+static const char *render_fb_format_str( GLenum format )
+{
+   struct { GLenum e; const char *str; }
+   formats[] =
+   { 
+      /* Table 1 */
+      FB_FORMAT_STR(GL_DEPTH_COMPONENT)
+      FB_FORMAT_STR(GL_DEPTH_STENCIL)
+      FB_FORMAT_STR(GL_RED)
+      FB_FORMAT_STR(GL_RG)
+      FB_FORMAT_STR(GL_RGB)
+      FB_FORMAT_STR(GL_RGBA)
+
+      /* Render buffer formats */
+      FB_FORMAT_STR(GL_DEPTH_COMPONENT16)
+      FB_FORMAT_STR(GL_DEPTH_COMPONENT24)
+      FB_FORMAT_STR(GL_DEPTH_COMPONENT32F)
+      FB_FORMAT_STR(GL_DEPTH24_STENCIL8)
+      FB_FORMAT_STR(GL_DEPTH32F_STENCIL8)
+      FB_FORMAT_STR(GL_STENCIL_INDEX8)
+
+      /* Table 2 */
+      FB_FORMAT_STR(GL_R8)
+      FB_FORMAT_STR(GL_R8_SNORM)
+      FB_FORMAT_STR(GL_R16)
+      FB_FORMAT_STR(GL_R16_SNORM)
+      FB_FORMAT_STR(GL_RG8)
+      FB_FORMAT_STR(GL_RG8_SNORM)
+      FB_FORMAT_STR(GL_RG16)
+      FB_FORMAT_STR(GL_RG16_SNORM)
+      FB_FORMAT_STR(GL_R3_G3_B2)
+      FB_FORMAT_STR(GL_RGB4)
+      FB_FORMAT_STR(GL_RGB5)
+      FB_FORMAT_STR(GL_RGB8)
+      FB_FORMAT_STR(GL_RGB8_SNORM)
+      FB_FORMAT_STR(GL_RGB10)
+      FB_FORMAT_STR(GL_RGB12)
+      FB_FORMAT_STR(GL_RGB16_SNORM)
+      FB_FORMAT_STR(GL_RGBA2)
+      FB_FORMAT_STR(GL_RGBA4)
+      FB_FORMAT_STR(GL_RGB5_A1)
+      FB_FORMAT_STR(GL_RGBA8)
+      FB_FORMAT_STR(GL_RGBA8_SNORM)
+      FB_FORMAT_STR(GL_RGB10_A2)
+      FB_FORMAT_STR(GL_RGB10_A2UI)
+      FB_FORMAT_STR(GL_RGBA12)
+      FB_FORMAT_STR(GL_RGBA16)
+      FB_FORMAT_STR(GL_SRGB8)
+      FB_FORMAT_STR(GL_SRGB8_ALPHA8)
+      FB_FORMAT_STR(GL_R16F)
+      FB_FORMAT_STR(GL_RG16F)
+      FB_FORMAT_STR(GL_RGB16F)
+      FB_FORMAT_STR(GL_RGBA16F)
+      FB_FORMAT_STR(GL_R32F)
+      FB_FORMAT_STR(GL_RG32F)
+      FB_FORMAT_STR(GL_RGB32F)
+      FB_FORMAT_STR(GL_RGBA32F)
+      FB_FORMAT_STR(GL_R11F_G11F_B10F)
+      FB_FORMAT_STR(GL_RGB9_E5)
+      FB_FORMAT_STR(GL_R8I)
+      FB_FORMAT_STR(GL_R8UI)
+      FB_FORMAT_STR(GL_R16I)
+      FB_FORMAT_STR(GL_R16UI)
+      FB_FORMAT_STR(GL_R32I)
+      FB_FORMAT_STR(GL_R32UI)
+      FB_FORMAT_STR(GL_RG8I)
+      FB_FORMAT_STR(GL_RG8UI)
+      FB_FORMAT_STR(GL_RG16I)
+      FB_FORMAT_STR(GL_RG16UI)
+      FB_FORMAT_STR(GL_RG32I)
+      FB_FORMAT_STR(GL_RG32UI)
+      FB_FORMAT_STR(GL_RGB8I)
+      FB_FORMAT_STR(GL_RGB8UI)
+      FB_FORMAT_STR(GL_RGB16I)
+      FB_FORMAT_STR(GL_RGB16UI)
+      FB_FORMAT_STR(GL_RGB32I)
+      FB_FORMAT_STR(GL_RGB32UI)
+      FB_FORMAT_STR(GL_RGBA8I)
+      FB_FORMAT_STR(GL_RGBA8UI)
+      FB_FORMAT_STR(GL_RGBA16I)
+      FB_FORMAT_STR(GL_RGBA16UI)
+      FB_FORMAT_STR(GL_RGBA32I)
+      FB_FORMAT_STR(GL_RGBA32UI)
+   };
+
+   for( int i=0; i<vg_list_size(formats); i++ )
+      if( formats[i].e == format )
+         return formats[i].str;
+
+   return "UNDEFINED";
+}
+
+/*
+ * Bind and allocate texture for framebuffer attachment
+ */
+static void render_fb_allocate_texture( struct framebuffer *fb, 
+                                           struct framebuffer_attachment *a )
+{
+   int rx, ry;
+   render_fb_get_current_res( fb, &rx, &ry );
+
+   if( a->purpose == k_framebuffer_attachment_type_renderbuffer ){
+      glBindRenderbuffer( GL_RENDERBUFFER, a->id );
+      glRenderbufferStorage( GL_RENDERBUFFER, a->internalformat, rx, ry );
+   }
+   else if( a->purpose == k_framebuffer_attachment_type_texture ||
+            a->purpose == k_framebuffer_attachment_type_texture_depth )
+   {
+      glBindTexture( GL_TEXTURE_2D, a->id );
+      glTexImage2D( GL_TEXTURE_2D, 0, a->internalformat, rx, ry,
+                                   0, a->format, a->type, NULL );
+   }
+}
+
+/* 
+ * Full allocation of a framebuffer
+ */
+void render_fb_allocate( struct framebuffer *fb )
+{
+   glGenFramebuffers( 1, &fb->fb );
+   glBindFramebuffer( GL_FRAMEBUFFER, fb->fb );
+
+   int rx, ry;
+   render_fb_get_current_res( fb, &rx, &ry );
+
+   vg_info( "allocate_framebuffer( %s, %dx%d )\n", fb->display_name, rx, ry );
+   vg_info( "{\n" );
+
+   GLenum colour_attachments[4];
+   u32    colour_count = 0;
+
+   for( int j=0; j<vg_list_size(fb->attachments); j++ ){
+      struct framebuffer_attachment *attachment = &fb->attachments[j];
+
+      if( attachment->purpose == k_framebuffer_attachment_type_none )
+         continue;
+
+      vg_info( "  %s: %s\n", 
+                  render_fb_attachment_str( attachment->attachment ),
+                  render_fb_format_str( attachment->internalformat ) );
+
+      if( attachment->purpose == k_framebuffer_attachment_type_renderbuffer ){
+         glGenRenderbuffers( 1, &attachment->id );
+         render_fb_allocate_texture( fb, attachment );
+         glFramebufferRenderbuffer( GL_FRAMEBUFFER, 
+                                    GL_DEPTH_STENCIL_ATTACHMENT,
+                                    GL_RENDERBUFFER, attachment->id );
+      }
+      else if( attachment->purpose == k_framebuffer_attachment_type_texture || 
+         attachment->purpose == k_framebuffer_attachment_type_texture_depth )
+      {
+         glGenTextures( 1, &attachment->id );
+         render_fb_allocate_texture( fb, attachment );
+         glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
+         glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
+         glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE );
+         glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE );
+
+         glFramebufferTexture2D( GL_FRAMEBUFFER, attachment->attachment,
+                                 GL_TEXTURE_2D,  attachment->id, 0 );
+
+         if( attachment->purpose == k_framebuffer_attachment_type_texture )
+            colour_attachments[ colour_count ++ ] = attachment->attachment;
+      }
+   }
+
+   glDrawBuffers( colour_count, colour_attachments );
+
+   /* 
+    * Check result 
+    */
+   GLenum result = glCheckFramebufferStatus( GL_FRAMEBUFFER );
+
+   if( result == GL_FRAMEBUFFER_COMPLETE ){
+      /* 
+       * Attatch to gpipeline
+       */
+      if( fb->link )
+         *fb->link = fb;
+
+      vg_success( "  status: complete\n" );
+      vg_info( "}\n" );
+   }
+   else{
+      if( result == GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT )
+         vg_error( "  status: Incomplete attachment" );
+      else if( result == GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT )
+         vg_error( "  status: Missing attachment" );
+      else if( result == GL_FRAMEBUFFER_UNSUPPORTED )
+         vg_error( "  status: Unsupported framebuffer format" );
+      else
+         vg_error( "  status: Generic Error" );
+
+      vg_info( "}\n" );
+      vg_fatal_error( "Incomplete framebuffer (see logs)" );
+   }
+}
+
+/*
+ * Resize/Update all framebuffers(we know about)
+ */
+void render_fb_resize(void)
+{
+   if( !gpipeline.ready ) return;
+
+   for( int i=0; i<vg_list_size(framebuffers); i++ ){
+      struct framebuffer *fb = &framebuffers[i];
+      for( int j=0; j<vg_list_size(fb->attachments); j++ ){
+         struct framebuffer_attachment *attachment = &fb->attachments[j];
+         render_fb_allocate_texture( fb, attachment );
+      }
+   }
+}
+
+static int render_framebuffer_control( int argc, char const *argv[] );
+static void render_framebuffer_poll( int argc, char const *argv[] );
+
+static void async_render_init( void *payload, u32 size )
+{
+   /* 
+    * Complete Framebuffers
+    */
+   for( int i=0; i<vg_list_size(framebuffers); i++ ){
+      struct framebuffer *fb = &framebuffers[i];
+      render_fb_allocate( fb );
+   }
+
+   f32 rh = 0x1p-4f, ih = 0.3f;
+
+   float quad[] = { 
+      0.00f,0.00f, 1.00f,1.00f, 0.00f,1.00f,    /* fsquad */
+      0.00f,0.00f, 1.00f,0.00f, 1.00f,1.00f,    
+
+      0.00f,0.00f, 1.00f,rh,     0.00f,rh,    /* fsquad1 */
+      0.00f,0.00f, 1.00f,0.00f,  1.00f,rh,
+
+      /* 9x9 debug grid */
+      /* row0 */
+      0.00f,0.00f, 0.30f,0.30f, 0.00f,0.30f,
+      0.00f,0.00f, 0.30f,0.00f, 0.30f,0.30f,
+      0.30f,0.00f, 0.60f,0.30f, 0.30f,0.30f,
+      0.30f,0.00f, 0.60f,0.00f, 0.60f,0.30f,
+      0.60f,0.00f, 0.90f,0.30f, 0.60f,0.30f,
+      0.60f,0.00f, 0.90f,0.00f, 0.90f,0.30f,
+      /* row1 */
+      0.00f,0.30f, 0.30f,0.60f, 0.00f,0.60f,
+      0.00f,0.30f, 0.30f,0.30f, 0.30f,0.60f,
+      0.30f,0.30f, 0.60f,0.60f, 0.30f,0.60f,
+      0.30f,0.30f, 0.60f,0.30f, 0.60f,0.60f,
+      0.60f,0.30f, 0.90f,0.60f, 0.60f,0.60f,
+      0.60f,0.30f, 0.90f,0.30f, 0.90f,0.60f,
+      /* row2 */
+      0.00f,0.60f, 0.30f,0.90f, 0.00f,0.90f,
+      0.00f,0.60f, 0.30f,0.60f, 0.30f,0.90f,
+      0.30f,0.60f, 0.60f,0.90f, 0.30f,0.90f,
+      0.30f,0.60f, 0.60f,0.60f, 0.60f,0.90f,
+      0.60f,0.60f, 0.90f,0.90f, 0.60f,0.90f,
+      0.60f,0.60f, 0.90f,0.60f, 0.90f,0.90f,
+
+      0.00f,ih, 1.00f,ih+rh, 0.00f,ih+rh,    /* fsquad2 */
+      0.00f,ih, 1.00f,ih,    1.00f,ih+rh,
+   };
+
+   glGenVertexArrays( 1, &gpipeline.fsquad.vao );
+   glGenBuffers( 1, &gpipeline.fsquad.vbo );
+   glBindVertexArray( gpipeline.fsquad.vao );
+   glBindBuffer( GL_ARRAY_BUFFER, gpipeline.fsquad.vbo );
+   glBufferData( GL_ARRAY_BUFFER, sizeof(quad), quad, GL_STATIC_DRAW );
+   glBindVertexArray( gpipeline.fsquad.vao );
+   glVertexAttribPointer( 0, 2, GL_FLOAT, GL_FALSE, 
+                          sizeof(float)*2, (void*)0 );
+   glEnableVertexAttribArray( 0 );
+
+   VG_CHECK_GL_ERR();
+
+   glBindFramebuffer( GL_FRAMEBUFFER, 0 );
+   gpipeline.ready = 1;
+}
+
+void render_init(void)
+{
+   vg_console_reg_var( "blur_strength", &k_blur_strength, k_var_dtype_f32, 0 );
+   vg_console_reg_var( "render_scale", &k_render_scale,
+                       k_var_dtype_f32, VG_VAR_PERSISTENT );
+   vg_console_reg_var( "fov", &k_fov, k_var_dtype_f32, VG_VAR_PERSISTENT );
+   vg_console_reg_var( "cam_height", &k_cam_height, 
+                        k_var_dtype_f32, VG_VAR_PERSISTENT );
+   vg_console_reg_var( "blur_effect", &k_blur_effect, 
+                        k_var_dtype_i32, VG_VAR_PERSISTENT );
+
+   vg_console_reg_cmd( "fb", render_framebuffer_control, 
+                             render_framebuffer_poll );
+
+   vg_async_call( async_render_init, NULL, 0 );
+}
+
+/*
+ * Utility
+ */
+void render_fsquad(void)
+{
+   glBindVertexArray( gpipeline.fsquad.vao );
+   glDrawArrays( GL_TRIANGLES, 0, 6 );
+}
+
+void render_fsquad1(void)
+{
+   glBindVertexArray( gpipeline.fsquad.vao );
+   glDrawArrays( GL_TRIANGLES, 6, 6 );
+}
+
+void render_fsquad2(void)
+{
+   glBindVertexArray( gpipeline.fsquad.vao );
+   glDrawArrays( GL_TRIANGLES, 66,6 );
+}
+
+/*
+ * Call this inside the UI function
+ */
+void render_view_framebuffer_ui(void)
+{
+#if 0
+   int viewing_count = 0;
+
+   glBindVertexArray( gpipeline.fsquad.vao );
+   shader_blit_use();
+   shader_blit_uTexMain( 0 );
+   
+   v2f identity = { 1.0f, 1.0f };
+   shader_blit_uInverseRatio( identity );
+
+   for( int i=0; i<vg_list_size(framebuffers); i++ ){
+      struct framebuffer *fb = &framebuffers[i];
+
+      for( int j=0; j<vg_list_size(fb->attachments); j++ ){
+         struct framebuffer_attachment *at = &fb->attachments[j];
+
+         if( !at->debug_view )
+            continue;
+
+         v2f corner,
+             window = { vg.window_x, vg.window_y };
+
+         corner[0] = viewing_count % 3;
+         corner[1] = 1 + (viewing_count / 3);
+         v2_mul( corner, window, corner );
+         v2_muls( corner, 0.3f, corner );
+         corner[1] = vg.window_y - corner[1];
+         
+         ui_text( (ui_rect){ corner[0], corner[1],      0.0f, 0.0f }, 
+                  fb->display_name, 2, k_text_align_left );
+         ui_text( (ui_rect){ corner[0], corner[1] + 32, 0.0f, 0.0f, },
+                  at->display_name, 1, k_text_align_left );
+
+         if( at->purpose == k_framebuffer_attachment_type_renderbuffer ){
+            v2f center;
+            v2_muladds( corner, window, 0.15f, center );
+
+            ui_text( (ui_rect){ center[0], center[1], 0.0f, 0.0f },
+                     "<hardware texture>", 1, k_text_align_center );
+         }
+         else{
+            render_fb_bind_texture( fb, j, 0 );
+            
+            int start = (viewing_count+2) * 6,
+                count = 6;
+            glDrawArrays( GL_TRIANGLES, start, count );
+         }
+
+         viewing_count ++;
+      }
+   }
+#endif
+}
+
+static void render_framebuffer_show( struct framebuffer *fb,
+                                        struct framebuffer_attachment *at,
+                                        int operation )
+{
+   at->debug_view = operation;
+   vg_info( "%s %s:%s\n", (operation?"shown": "hidden"), 
+               fb->display_name, at->display_name );
+}
+
+/* 
+ * arg0: command           "show"/"hide"
+ * arg1: framebuffer name  <name>/"all"
+ * arg2: subname           <name>/none
+ */
+static int render_framebuffer_control( int argc, char const *argv[] )
+{
+   if( argc < 2 ){
+      vg_error( "Usage: fb \"show/hide\" <name>/\"all\" <name>/none\n" );
+      return 0;
+   }
+
+   int modify_all = 0,
+       operation  = 0;
+
+   if( !strcmp( argv[0], "show" ) )
+      operation = 1;
+   else if( !strcmp( argv[0], "hide" ) )
+      operation = 0;
+   else{
+      vg_error( "Unknown framebuffer operation: '%s'\n", argv[0] );
+      return 0;
+   }
+
+   if( !strcmp( argv[1], "all" ) )
+      modify_all = 1;
+
+   for( int i=0; i<vg_list_size(framebuffers); i++ ){
+      struct framebuffer *fb = &framebuffers[i];
+      
+      for( int j=0; j<vg_list_size(fb->attachments); j++ ){
+         struct framebuffer_attachment *at = &fb->attachments[j];
+
+         if( at->purpose == k_framebuffer_attachment_type_none )
+            continue;
+
+         if( modify_all ){
+            render_framebuffer_show( fb, at, operation );
+         }
+         else{
+            if( !strcmp( fb->display_name, argv[1] ) ){
+               if( argc == 2 )
+                  render_framebuffer_show( fb, at, operation );
+               else if( !strcmp( at->display_name, argv[2] ) )
+                  render_framebuffer_show( fb, at, operation );
+            }
+         }
+      }
+   }
+
+   return 0;
+}
+
+static void render_framebuffer_poll( int argc, char const *argv[] )
+{
+   const char *term = argv[argc-1];
+
+   if( argc == 1 ){
+      console_suggest_score_text( "show", term, 0 );
+      console_suggest_score_text( "hide", term, 0 );
+   }
+   else if( argc == 2 ){
+      console_suggest_score_text( "all", term, 0 );
+
+      for( int i=0; i<vg_list_size(framebuffers); i++ ){
+         struct framebuffer *fb = &framebuffers[i];
+         console_suggest_score_text( fb->display_name, term, 0 );
+      }
+   }
+   else if( argc == 3 ){
+      int modify_all = 0;
+
+      if( !strcmp( argv[1], "all" ) )
+         modify_all = 1;
+
+      for( int i=0; i<vg_list_size(framebuffers); i++ ){
+         struct framebuffer *fb = &framebuffers[i];
+         
+         for( int j=0; j<vg_list_size(fb->attachments); j++ ){
+            struct framebuffer_attachment *at = &fb->attachments[j];
+
+            if( at->purpose == k_framebuffer_attachment_type_none )
+               continue;
+
+            if( modify_all ){
+               console_suggest_score_text( at->display_name, term, 0 );
+            }
+            else if( !strcmp( fb->display_name, argv[1] ) ){
+               console_suggest_score_text( at->display_name, term, 0 );
+            }
+         }
+      }
+   }
+}
index a10422874caa3ee8d80fc4a84a36c6a8a4de5c69..3b69b2b3dd8dc07873d011b8fd32496c435d1c66 100644 (file)
--- a/render.h
+++ b/render.h
@@ -1,11 +1,10 @@
 /*
  * Copyright (C) 2021-2022 Mt.ZERO Software, Harry Godden - All Rights Reserved
  */
-
+#pragma once
 #include "common.h"
 #include "model.h"
 #include "camera.h"
-#include "world.h"
 
 #include "shaders/blit.h"
 #include "shaders/blitblur.h"
@@ -14,8 +13,6 @@
 
 #define WORKSHOP_PREVIEW_WIDTH  504
 #define WORKSHOP_PREVIEW_HEIGHT 336
-#ifndef RENDER_H
-#define RENDER_H
 
 static f32 k_render_scale  = 1.0f;
 static i32 k_blur_effect   = 1;
@@ -80,728 +77,17 @@ struct framebuffer{
    GLuint fb;
    framebuffer **link;
 }
-framebuffers[] = 
-{
-   {
-      /*
-       * The primary draw target
-       */
-      "main", 
-      .link = &gpipeline.fb_main,
-      .resolution_div = 1,
-      .attachments = 
-      {
-         {
-            "colour", k_framebuffer_attachment_type_texture,
-
-            .internalformat = GL_RGB,
-            .format         = GL_RGB,
-            .type           = GL_UNSIGNED_BYTE,
-            .attachment     = GL_COLOR_ATTACHMENT0
-         },
-         {
-            "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
-         },
-         {
-#if 0
-            "depth_stencil", k_framebuffer_attachment_type_renderbuffer,
-
-            .internalformat = GL_DEPTH24_STENCIL8,
-#else
-            "depth_stencil", k_framebuffer_attachment_type_texture_depth,
-            .internalformat = GL_DEPTH24_STENCIL8,
-            .format         = GL_DEPTH_STENCIL,
-            .type           = GL_UNSIGNED_INT_24_8,
-#endif
-            .attachment     = GL_DEPTH_STENCIL_ATTACHMENT
-         }
-      }
-   },
-   {
-      /*
-       * Second rendered view from the perspective of the water reflection
-       */
-      "water_reflection",
-      .link = &gpipeline.fb_water_reflection,
-      .resolution_div = 2,
-      .attachments = 
-      {
-         {
-            "colour", k_framebuffer_attachment_type_texture,
-            .internalformat = GL_RGB,
-            .format         = GL_RGB,
-            .type           = GL_UNSIGNED_BYTE,
-            .attachment     = GL_COLOR_ATTACHMENT0
-         },
-         {
-            "depth_stencil", k_framebuffer_attachment_type_renderbuffer,
-
-            .internalformat = GL_DEPTH24_STENCIL8,
-            .attachment     = GL_DEPTH_STENCIL_ATTACHMENT
-         }
-      }
-   },
-   {
-      /*
-       * Thid rendered view from the perspective of the camera, but just 
-       * captures stuff thats under the water
-       */
-      "water_beneath",
-      .link = &gpipeline.fb_water_beneath,
-      .resolution_div = 2,
-      .attachments = 
-      {
-         {
-            "colour", k_framebuffer_attachment_type_texture,
-            .internalformat = GL_RED,
-            .format         = GL_RED,
-            .type           = GL_UNSIGNED_BYTE,
-            .attachment     = GL_COLOR_ATTACHMENT0
-         },
-         {
-            "depth_stencil", k_framebuffer_attachment_type_renderbuffer,
-
-            .internalformat = GL_DEPTH24_STENCIL8,
-            .attachment     = GL_DEPTH_STENCIL_ATTACHMENT
-         }
-      }
-   },
-   {
-      "workshop_preview",
-      .link = &gpipeline.fb_workshop_preview,
-      .resolution_div = 0,
-      .fixed_w = WORKSHOP_PREVIEW_WIDTH, .fixed_h = WORKSHOP_PREVIEW_HEIGHT,
-      .attachments = 
-      {
-         {
-            "colour", k_framebuffer_attachment_type_texture,
-            .internalformat = GL_RGB,
-            .format         = GL_RGB,
-            .type           = GL_UNSIGNED_BYTE,
-            .attachment     = GL_COLOR_ATTACHMENT0
-         },
-         {
-            "depth_stencil", k_framebuffer_attachment_type_renderbuffer,
-            .internalformat = GL_DEPTH24_STENCIL8,
-            .attachment = GL_DEPTH_STENCIL_ATTACHMENT
-         }
-      }
-   },
-   {
-      "network_status_ui",
-      .link = &gpipeline.fb_network_status,
-      .resolution_div = 0,
-      .fixed_w = 128, .fixed_h = 48,
-      .attachments = 
-      {
-         {
-            "colour", k_framebuffer_attachment_type_texture,
-            .internalformat = GL_RGB,
-            .format         = GL_RGB,
-            .type           = GL_UNSIGNED_BYTE,
-            .attachment     = GL_COLOR_ATTACHMENT0
-         }
-      }
-   }
-};
-
-/* 
- * Get the current (automatically scaled or fixed) resolution of framebuffer
- */
-static void render_fb_get_current_res( struct framebuffer *fb, 
-                                          int *x, int *y )
-{
-   if( fb->resolution_div ){
-      *x = vg.window_x / fb->resolution_div;
-      *y = vg.window_y / fb->resolution_div;
-   }
-   else{
-      *x = fb->fixed_w;
-      *y = fb->fixed_h;
-   }
-}
-
-static void render_fb_inverse_ratio( framebuffer *fb, v2f inverse )
-{
-   if( fb ){
-      int x, y;
-      render_fb_get_current_res( fb, &x, &y );
-
-      v2f render   = { fb->render_w, fb->render_h },
-          original = { x, y };
-
-      v2_div( render, original, inverse );
-   }
-   else{
-      v2_div( (v2f){1.0f,1.0f}, (v2f){ vg.window_x, vg.window_y }, inverse );
-   }
-}
-
-/*
- * Bind framebuffer for drawing to
- */
-static void render_fb_bind( framebuffer *fb, int use_scaling )
-{
-   int x, y;
-   render_fb_get_current_res( fb, &x, &y );
-
-   if( use_scaling ){
-      x = k_render_scale*(float)x;
-      y = k_render_scale*(float)y;
-
-      x = VG_MAX( 16, x );
-      y = VG_MAX( 16, y );
-
-      fb->render_w = x;
-      fb->render_h = y;
-   }
-
-   glBindFramebuffer( GL_FRAMEBUFFER, fb->fb );
-   glViewport( 0, 0, x, y );
-}
-
-/*
- * Bind framebuffer attachment's texture
- */
-static void render_fb_bind_texture( framebuffer *fb, 
-                                       int attachment, int slot )
-{
-   struct framebuffer_attachment *at = &fb->attachments[attachment];
-
-   if( (at->purpose != k_framebuffer_attachment_type_texture) &&
-       (at->purpose != k_framebuffer_attachment_type_texture_depth) )
-   {
-      vg_fatal_error( "illegal operation: bind non-texture framebuffer"
-                          " attachment to texture slot" );
-   }
-
-   glActiveTexture( GL_TEXTURE0 + slot );
-   glBindTexture( GL_TEXTURE_2D, fb->attachments[attachment].id );
-}
-
-
-/*
- * Shaders
- */
-
-#define FB_FORMAT_STR( E ) { E, #E },
-
-/* 
- * Convert OpenGL attachment ID enum to string
- */
-static const char *render_fb_attachment_str( GLenum e )
-{
-   struct { GLenum e; const char *str; }
-   formats[] =
-   { 
-      FB_FORMAT_STR(GL_COLOR_ATTACHMENT0)
-      FB_FORMAT_STR(GL_COLOR_ATTACHMENT1)
-      FB_FORMAT_STR(GL_COLOR_ATTACHMENT2)
-      FB_FORMAT_STR(GL_COLOR_ATTACHMENT3)
-      FB_FORMAT_STR(GL_COLOR_ATTACHMENT4)
-      FB_FORMAT_STR(GL_DEPTH_STENCIL_ATTACHMENT)
-   };
-
-   for( int i=0; i<vg_list_size(formats); i++ )
-      if( formats[i].e == e )
-         return formats[i].str;
-
-   return "UNDEFINED";
-}
-
-/*
- * Convert OpenGL texture format enums from TexImage2D table 1,2 &
- * RenderBufferStorage Table 1, into strings
- */
-static const char *render_fb_format_str( GLenum format )
-{
-   struct { GLenum e; const char *str; }
-   formats[] =
-   { 
-      /* Table 1 */
-      FB_FORMAT_STR(GL_DEPTH_COMPONENT)
-      FB_FORMAT_STR(GL_DEPTH_STENCIL)
-      FB_FORMAT_STR(GL_RED)
-      FB_FORMAT_STR(GL_RG)
-      FB_FORMAT_STR(GL_RGB)
-      FB_FORMAT_STR(GL_RGBA)
-
-      /* Render buffer formats */
-      FB_FORMAT_STR(GL_DEPTH_COMPONENT16)
-      FB_FORMAT_STR(GL_DEPTH_COMPONENT24)
-      FB_FORMAT_STR(GL_DEPTH_COMPONENT32F)
-      FB_FORMAT_STR(GL_DEPTH24_STENCIL8)
-      FB_FORMAT_STR(GL_DEPTH32F_STENCIL8)
-      FB_FORMAT_STR(GL_STENCIL_INDEX8)
-
-      /* Table 2 */
-      FB_FORMAT_STR(GL_R8)
-      FB_FORMAT_STR(GL_R8_SNORM)
-      FB_FORMAT_STR(GL_R16)
-      FB_FORMAT_STR(GL_R16_SNORM)
-      FB_FORMAT_STR(GL_RG8)
-      FB_FORMAT_STR(GL_RG8_SNORM)
-      FB_FORMAT_STR(GL_RG16)
-      FB_FORMAT_STR(GL_RG16_SNORM)
-      FB_FORMAT_STR(GL_R3_G3_B2)
-      FB_FORMAT_STR(GL_RGB4)
-      FB_FORMAT_STR(GL_RGB5)
-      FB_FORMAT_STR(GL_RGB8)
-      FB_FORMAT_STR(GL_RGB8_SNORM)
-      FB_FORMAT_STR(GL_RGB10)
-      FB_FORMAT_STR(GL_RGB12)
-      FB_FORMAT_STR(GL_RGB16_SNORM)
-      FB_FORMAT_STR(GL_RGBA2)
-      FB_FORMAT_STR(GL_RGBA4)
-      FB_FORMAT_STR(GL_RGB5_A1)
-      FB_FORMAT_STR(GL_RGBA8)
-      FB_FORMAT_STR(GL_RGBA8_SNORM)
-      FB_FORMAT_STR(GL_RGB10_A2)
-      FB_FORMAT_STR(GL_RGB10_A2UI)
-      FB_FORMAT_STR(GL_RGBA12)
-      FB_FORMAT_STR(GL_RGBA16)
-      FB_FORMAT_STR(GL_SRGB8)
-      FB_FORMAT_STR(GL_SRGB8_ALPHA8)
-      FB_FORMAT_STR(GL_R16F)
-      FB_FORMAT_STR(GL_RG16F)
-      FB_FORMAT_STR(GL_RGB16F)
-      FB_FORMAT_STR(GL_RGBA16F)
-      FB_FORMAT_STR(GL_R32F)
-      FB_FORMAT_STR(GL_RG32F)
-      FB_FORMAT_STR(GL_RGB32F)
-      FB_FORMAT_STR(GL_RGBA32F)
-      FB_FORMAT_STR(GL_R11F_G11F_B10F)
-      FB_FORMAT_STR(GL_RGB9_E5)
-      FB_FORMAT_STR(GL_R8I)
-      FB_FORMAT_STR(GL_R8UI)
-      FB_FORMAT_STR(GL_R16I)
-      FB_FORMAT_STR(GL_R16UI)
-      FB_FORMAT_STR(GL_R32I)
-      FB_FORMAT_STR(GL_R32UI)
-      FB_FORMAT_STR(GL_RG8I)
-      FB_FORMAT_STR(GL_RG8UI)
-      FB_FORMAT_STR(GL_RG16I)
-      FB_FORMAT_STR(GL_RG16UI)
-      FB_FORMAT_STR(GL_RG32I)
-      FB_FORMAT_STR(GL_RG32UI)
-      FB_FORMAT_STR(GL_RGB8I)
-      FB_FORMAT_STR(GL_RGB8UI)
-      FB_FORMAT_STR(GL_RGB16I)
-      FB_FORMAT_STR(GL_RGB16UI)
-      FB_FORMAT_STR(GL_RGB32I)
-      FB_FORMAT_STR(GL_RGB32UI)
-      FB_FORMAT_STR(GL_RGBA8I)
-      FB_FORMAT_STR(GL_RGBA8UI)
-      FB_FORMAT_STR(GL_RGBA16I)
-      FB_FORMAT_STR(GL_RGBA16UI)
-      FB_FORMAT_STR(GL_RGBA32I)
-      FB_FORMAT_STR(GL_RGBA32UI)
-   };
-
-   for( int i=0; i<vg_list_size(formats); i++ )
-      if( formats[i].e == format )
-         return formats[i].str;
-
-   return "UNDEFINED";
-}
-
-/*
- * Bind and allocate texture for framebuffer attachment
- */
-static void render_fb_allocate_texture( struct framebuffer *fb, 
-                                           struct framebuffer_attachment *a )
-{
-   int rx, ry;
-   render_fb_get_current_res( fb, &rx, &ry );
-
-   if( a->purpose == k_framebuffer_attachment_type_renderbuffer ){
-      glBindRenderbuffer( GL_RENDERBUFFER, a->id );
-      glRenderbufferStorage( GL_RENDERBUFFER, a->internalformat, rx, ry );
-   }
-   else if( a->purpose == k_framebuffer_attachment_type_texture ||
-            a->purpose == k_framebuffer_attachment_type_texture_depth )
-   {
-      glBindTexture( GL_TEXTURE_2D, a->id );
-      glTexImage2D( GL_TEXTURE_2D, 0, a->internalformat, rx, ry,
-                                   0, a->format, a->type, NULL );
-   }
-}
-
-/* 
- * Full allocation of a framebuffer
- */
-static void render_fb_allocate( struct framebuffer *fb )
-{
-   glGenFramebuffers( 1, &fb->fb );
-   glBindFramebuffer( GL_FRAMEBUFFER, fb->fb );
-
-   int rx, ry;
-   render_fb_get_current_res( fb, &rx, &ry );
-
-   vg_info( "allocate_framebuffer( %s, %dx%d )\n", fb->display_name, rx, ry );
-   vg_info( "{\n" );
-
-   GLenum colour_attachments[4];
-   u32    colour_count = 0;
-
-   for( int j=0; j<vg_list_size(fb->attachments); j++ ){
-      struct framebuffer_attachment *attachment = &fb->attachments[j];
-
-      if( attachment->purpose == k_framebuffer_attachment_type_none )
-         continue;
-
-      vg_info( "  %s: %s\n", 
-                  render_fb_attachment_str( attachment->attachment ),
-                  render_fb_format_str( attachment->internalformat ) );
-
-      if( attachment->purpose == k_framebuffer_attachment_type_renderbuffer ){
-         glGenRenderbuffers( 1, &attachment->id );
-         render_fb_allocate_texture( fb, attachment );
-         glFramebufferRenderbuffer( GL_FRAMEBUFFER, 
-                                    GL_DEPTH_STENCIL_ATTACHMENT,
-                                    GL_RENDERBUFFER, attachment->id );
-      }
-      else if( attachment->purpose == k_framebuffer_attachment_type_texture || 
-         attachment->purpose == k_framebuffer_attachment_type_texture_depth )
-      {
-         glGenTextures( 1, &attachment->id );
-         render_fb_allocate_texture( fb, attachment );
-         glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
-         glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
-         glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE );
-         glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE );
-
-         glFramebufferTexture2D( GL_FRAMEBUFFER, attachment->attachment,
-                                 GL_TEXTURE_2D,  attachment->id, 0 );
-
-         if( attachment->purpose == k_framebuffer_attachment_type_texture )
-            colour_attachments[ colour_count ++ ] = attachment->attachment;
-      }
-   }
-
-   glDrawBuffers( colour_count, colour_attachments );
-
-   /* 
-    * Check result 
-    */
-   GLenum result = glCheckFramebufferStatus( GL_FRAMEBUFFER );
-
-   if( result == GL_FRAMEBUFFER_COMPLETE ){
-      /* 
-       * Attatch to gpipeline
-       */
-      if( fb->link )
-         *fb->link = fb;
-
-      vg_success( "  status: complete\n" );
-      vg_info( "}\n" );
-   }
-   else{
-      if( result == GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT )
-         vg_error( "  status: Incomplete attachment" );
-      else if( result == GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT )
-         vg_error( "  status: Missing attachment" );
-      else if( result == GL_FRAMEBUFFER_UNSUPPORTED )
-         vg_error( "  status: Unsupported framebuffer format" );
-      else
-         vg_error( "  status: Generic Error" );
-
-      vg_info( "}\n" );
-      vg_fatal_error( "Incomplete framebuffer (see logs)" );
-   }
-}
-
-/*
- * Resize/Update all framebuffers(we know about)
- */
-static void render_fb_resize(void)
-{
-   if( !gpipeline.ready ) return;
-
-   for( int i=0; i<vg_list_size(framebuffers); i++ ){
-      struct framebuffer *fb = &framebuffers[i];
-      for( int j=0; j<vg_list_size(fb->attachments); j++ ){
-         struct framebuffer_attachment *attachment = &fb->attachments[j];
-         render_fb_allocate_texture( fb, attachment );
-      }
-   }
-}
-
-static int render_framebuffer_control( int argc, char const *argv[] );
-static void render_framebuffer_poll( int argc, char const *argv[] );
-
-static void async_render_init( void *payload, u32 size )
-{
-   /* 
-    * Complete Framebuffers
-    */
-   for( int i=0; i<vg_list_size(framebuffers); i++ ){
-      struct framebuffer *fb = &framebuffers[i];
-      render_fb_allocate( fb );
-   }
-
-   f32 rh = 0x1p-4f, ih = 0.3f;
-
-   float quad[] = { 
-      0.00f,0.00f, 1.00f,1.00f, 0.00f,1.00f,    /* fsquad */
-      0.00f,0.00f, 1.00f,0.00f, 1.00f,1.00f,    
-
-      0.00f,0.00f, 1.00f,rh,     0.00f,rh,    /* fsquad1 */
-      0.00f,0.00f, 1.00f,0.00f,  1.00f,rh,
-
-      /* 9x9 debug grid */
-      /* row0 */
-      0.00f,0.00f, 0.30f,0.30f, 0.00f,0.30f,
-      0.00f,0.00f, 0.30f,0.00f, 0.30f,0.30f,
-      0.30f,0.00f, 0.60f,0.30f, 0.30f,0.30f,
-      0.30f,0.00f, 0.60f,0.00f, 0.60f,0.30f,
-      0.60f,0.00f, 0.90f,0.30f, 0.60f,0.30f,
-      0.60f,0.00f, 0.90f,0.00f, 0.90f,0.30f,
-      /* row1 */
-      0.00f,0.30f, 0.30f,0.60f, 0.00f,0.60f,
-      0.00f,0.30f, 0.30f,0.30f, 0.30f,0.60f,
-      0.30f,0.30f, 0.60f,0.60f, 0.30f,0.60f,
-      0.30f,0.30f, 0.60f,0.30f, 0.60f,0.60f,
-      0.60f,0.30f, 0.90f,0.60f, 0.60f,0.60f,
-      0.60f,0.30f, 0.90f,0.30f, 0.90f,0.60f,
-      /* row2 */
-      0.00f,0.60f, 0.30f,0.90f, 0.00f,0.90f,
-      0.00f,0.60f, 0.30f,0.60f, 0.30f,0.90f,
-      0.30f,0.60f, 0.60f,0.90f, 0.30f,0.90f,
-      0.30f,0.60f, 0.60f,0.60f, 0.60f,0.90f,
-      0.60f,0.60f, 0.90f,0.90f, 0.60f,0.90f,
-      0.60f,0.60f, 0.90f,0.60f, 0.90f,0.90f,
-
-      0.00f,ih, 1.00f,ih+rh, 0.00f,ih+rh,    /* fsquad2 */
-      0.00f,ih, 1.00f,ih,    1.00f,ih+rh,
-   };
-
-   glGenVertexArrays( 1, &gpipeline.fsquad.vao );
-   glGenBuffers( 1, &gpipeline.fsquad.vbo );
-   glBindVertexArray( gpipeline.fsquad.vao );
-   glBindBuffer( GL_ARRAY_BUFFER, gpipeline.fsquad.vbo );
-   glBufferData( GL_ARRAY_BUFFER, sizeof(quad), quad, GL_STATIC_DRAW );
-   glBindVertexArray( gpipeline.fsquad.vao );
-   glVertexAttribPointer( 0, 2, GL_FLOAT, GL_FALSE, 
-                          sizeof(float)*2, (void*)0 );
-   glEnableVertexAttribArray( 0 );
-
-   VG_CHECK_GL_ERR();
-
-   glBindFramebuffer( GL_FRAMEBUFFER, 0 );
-   gpipeline.ready = 1;
-}
-
-static void render_init(void)
-{
-   vg_console_reg_var( "blur_strength", &k_blur_strength, k_var_dtype_f32, 0 );
-   vg_console_reg_var( "render_scale", &k_render_scale,
-                       k_var_dtype_f32, VG_VAR_PERSISTENT );
-   vg_console_reg_var( "fov", &k_fov, k_var_dtype_f32, VG_VAR_PERSISTENT );
-   vg_console_reg_var( "cam_height", &k_cam_height, 
-                        k_var_dtype_f32, VG_VAR_PERSISTENT );
-   vg_console_reg_var( "blur_effect", &k_blur_effect, 
-                        k_var_dtype_i32, VG_VAR_PERSISTENT );
-
-   vg_console_reg_cmd( "fb", render_framebuffer_control, 
-                             render_framebuffer_poll );
-
-   shader_blit_register();
-   shader_blitblur_register();
-   shader_blitcolour_register();
-   shader_blit_transition_register();
-
-   vg_async_call( async_render_init, NULL, 0 );
-}
-
-/*
- * Utility
- */
-static void render_fsquad(void)
-{
-   glBindVertexArray( gpipeline.fsquad.vao );
-   glDrawArrays( GL_TRIANGLES, 0, 6 );
-}
-
-static void render_fsquad1(void)
-{
-   glBindVertexArray( gpipeline.fsquad.vao );
-   glDrawArrays( GL_TRIANGLES, 6, 6 );
-}
-
-static void render_fsquad2(void)
-{
-   glBindVertexArray( gpipeline.fsquad.vao );
-   glDrawArrays( GL_TRIANGLES, 66,6 );
-}
-
-/*
- * Call this inside the UI function
- */
-static void render_view_framebuffer_ui(void)
-{
-#if 0
-   int viewing_count = 0;
-
-   glBindVertexArray( gpipeline.fsquad.vao );
-   shader_blit_use();
-   shader_blit_uTexMain( 0 );
-   
-   v2f identity = { 1.0f, 1.0f };
-   shader_blit_uInverseRatio( identity );
-
-   for( int i=0; i<vg_list_size(framebuffers); i++ ){
-      struct framebuffer *fb = &framebuffers[i];
-
-      for( int j=0; j<vg_list_size(fb->attachments); j++ ){
-         struct framebuffer_attachment *at = &fb->attachments[j];
-
-         if( !at->debug_view )
-            continue;
-
-         v2f corner,
-             window = { vg.window_x, vg.window_y };
-
-         corner[0] = viewing_count % 3;
-         corner[1] = 1 + (viewing_count / 3);
-         v2_mul( corner, window, corner );
-         v2_muls( corner, 0.3f, corner );
-         corner[1] = vg.window_y - corner[1];
-         
-         ui_text( (ui_rect){ corner[0], corner[1],      0.0f, 0.0f }, 
-                  fb->display_name, 2, k_text_align_left );
-         ui_text( (ui_rect){ corner[0], corner[1] + 32, 0.0f, 0.0f, },
-                  at->display_name, 1, k_text_align_left );
-
-         if( at->purpose == k_framebuffer_attachment_type_renderbuffer ){
-            v2f center;
-            v2_muladds( corner, window, 0.15f, center );
-
-            ui_text( (ui_rect){ center[0], center[1], 0.0f, 0.0f },
-                     "<hardware texture>", 1, k_text_align_center );
-         }
-         else{
-            render_fb_bind_texture( fb, j, 0 );
-            
-            int start = (viewing_count+2) * 6,
-                count = 6;
-            glDrawArrays( GL_TRIANGLES, start, count );
-         }
-
-         viewing_count ++;
-      }
-   }
-#endif
-}
-
-static void render_framebuffer_show( struct framebuffer *fb,
-                                        struct framebuffer_attachment *at,
-                                        int operation )
-{
-   at->debug_view = operation;
-   vg_info( "%s %s:%s\n", (operation?"shown": "hidden"), 
-               fb->display_name, at->display_name );
-}
-
-/* 
- * arg0: command           "show"/"hide"
- * arg1: framebuffer name  <name>/"all"
- * arg2: subname           <name>/none
- */
-static int render_framebuffer_control( int argc, char const *argv[] )
-{
-   if( argc < 2 ){
-      vg_error( "Usage: fb \"show/hide\" <name>/\"all\" <name>/none\n" );
-      return 0;
-   }
-
-   int modify_all = 0,
-       operation  = 0;
-
-   if( !strcmp( argv[0], "show" ) )
-      operation = 1;
-   else if( !strcmp( argv[0], "hide" ) )
-      operation = 0;
-   else{
-      vg_error( "Unknown framebuffer operation: '%s'\n", argv[0] );
-      return 0;
-   }
-
-   if( !strcmp( argv[1], "all" ) )
-      modify_all = 1;
-
-   for( int i=0; i<vg_list_size(framebuffers); i++ ){
-      struct framebuffer *fb = &framebuffers[i];
-      
-      for( int j=0; j<vg_list_size(fb->attachments); j++ ){
-         struct framebuffer_attachment *at = &fb->attachments[j];
-
-         if( at->purpose == k_framebuffer_attachment_type_none )
-            continue;
-
-         if( modify_all ){
-            render_framebuffer_show( fb, at, operation );
-         }
-         else{
-            if( !strcmp( fb->display_name, argv[1] ) ){
-               if( argc == 2 )
-                  render_framebuffer_show( fb, at, operation );
-               else if( !strcmp( at->display_name, argv[2] ) )
-                  render_framebuffer_show( fb, at, operation );
-            }
-         }
-      }
-   }
-
-   return 0;
-}
-
-static void render_framebuffer_poll( int argc, char const *argv[] )
-{
-   const char *term = argv[argc-1];
-
-   if( argc == 1 ){
-      console_suggest_score_text( "show", term, 0 );
-      console_suggest_score_text( "hide", term, 0 );
-   }
-   else if( argc == 2 ){
-      console_suggest_score_text( "all", term, 0 );
-
-      for( int i=0; i<vg_list_size(framebuffers); i++ ){
-         struct framebuffer *fb = &framebuffers[i];
-         console_suggest_score_text( fb->display_name, term, 0 );
-      }
-   }
-   else if( argc == 3 ){
-      int modify_all = 0;
-
-      if( !strcmp( argv[1], "all" ) )
-         modify_all = 1;
-
-      for( int i=0; i<vg_list_size(framebuffers); i++ ){
-         struct framebuffer *fb = &framebuffers[i];
-         
-         for( int j=0; j<vg_list_size(fb->attachments); j++ ){
-            struct framebuffer_attachment *at = &fb->attachments[j];
-
-            if( at->purpose == k_framebuffer_attachment_type_none )
-               continue;
-
-            if( modify_all ){
-               console_suggest_score_text( at->display_name, term, 0 );
-            }
-            else if( !strcmp( fb->display_name, argv[1] ) ){
-               console_suggest_score_text( at->display_name, term, 0 );
-            }
-         }
-      }
-   }
-}
-
-#endif /* RENDER_H */
+extern framebuffers[];
+
+void render_init(void);
+void render_fsquad(void);
+void render_fsquad1(void);
+void render_fsquad2(void);
+void render_view_framebuffer_ui(void);
+void render_fb_bind_texture( framebuffer *fb, int attachment, int slot );
+void render_fb_inverse_ratio( framebuffer *fb, v2f inverse );
+void render_fb_get_current_res( struct framebuffer *fb, int *x, int *y );
+void render_fb_bind( framebuffer *fb, int use_scaling );
+void render_fb_bind_texture( framebuffer *fb, int attachment, int slot );
+void render_fb_allocate( struct framebuffer *fb );
+void render_fb_resize(void);
diff --git a/save.c b/save.c
index 1009e61285e8cc1367a55e4d4ac09e849a85fa1a..db609ca86a45ac0c07a9f1eeebc82cec4511713e 100644 (file)
--- a/save.c
+++ b/save.c
@@ -1,6 +1,4 @@
-#ifndef SAVE_C
-#define SAVE_C
-
+#include "skaterift.h"
 #include "save.h"
 #include "addon.h"
 #include "vg/vg_msg.h"
@@ -8,7 +6,11 @@
 #include "vg/vg_loader.h"
 #include "world.h"
 
-static void savedata_file_write( savedata_file *file ){
+static const char *str_skaterift_main_save = "save.bkv";
+static f64 last_autosave;
+
+void savedata_file_write( savedata_file *file )
+{
    savedata_file *sav = file;
    FILE *fp = fopen( sav->path, "wb" );
    if( fp ){
@@ -21,13 +23,15 @@ static void savedata_file_write( savedata_file *file ){
    }
 }
 
-static void savedata_group_write( savedata_group *group ){
+void savedata_group_write( savedata_group *group )
+{
    for( u32 i=0; i<group->file_count; i++ ){
       savedata_file_write( &group->files[i] );
    }
 }
 
-static void savedata_file_read( savedata_file *file ){
+void savedata_file_read( savedata_file *file )
+{
    FILE *fp = fopen( file->path, "rb" );
    if( fp ){
       file->len = fread( file->buf, 1, sizeof(file->buf), fp );
@@ -59,9 +63,10 @@ static void skaterift_write_viewslot( vg_msg *msg, const char *key,
       skaterift_write_addon_alias( msg, key, &reg->alias );
 }
 
-static void skaterift_read_addon_alias( vg_msg *msg, const char *key,
-                                        enum addon_type type, 
-                                        addon_alias *alias ){
+void skaterift_read_addon_alias( vg_msg *msg, const char *key,
+                                 enum addon_type type, 
+                                 addon_alias *alias )
+{
    alias->foldername[0] = '\0';
    alias->workshop_id = 0;
    alias->type = type;
@@ -108,7 +113,8 @@ static void skaterift_populate_world_savedata( savedata_file *file,
    file->len = sav.cur.co;
 }
 
-static void skaterift_populate_main_savedata( savedata_file *file ){
+static void skaterift_populate_main_savedata( savedata_file *file )
+{
    strcpy( file->path, str_skaterift_main_save );
 
    vg_msg sav;
@@ -127,7 +133,14 @@ static void skaterift_populate_main_savedata( savedata_file *file ){
    file->len = sav.cur.co;
 }
 
-static int skaterift_autosave( int async ){
+void skaterift_read_main_savedata( savedata_file *file )
+{
+   strcpy( file->path, str_skaterift_main_save );
+   savedata_file_read( file );
+}
+
+int skaterift_autosave( int async )
+{
    if( async )
       if( !vg_loader_availible() ) return 0;
 
@@ -166,8 +179,16 @@ static int skaterift_autosave( int async ){
    return 1;
 }
 
-static void skaterift_autosave_synchronous(void){
+void skaterift_autosave_synchronous(void)
+{
    skaterift_autosave(0);
 }
 
-#endif /* SAVE_C */
+void skaterift_autosave_update(void)
+{
+   if( vg.time - last_autosave > 20.0 ){
+      if( skaterift_autosave(1) ){
+         last_autosave = vg.time;
+      }
+   }
+}
diff --git a/save.h b/save.h
index 4424bd3446204baa2079d2439b6cd252c3673fce..acda3019f0b91e3e4faa962876fac86b8931a5a6 100644 (file)
--- a/save.h
+++ b/save.h
@@ -1,10 +1,7 @@
-#ifndef SAVE_H
-#define SAVE_H
-
+#pragma once
 #include "vg/vg_platform.h"
-
-static const char *str_skaterift_main_save = "save.bkv";
-static f64 skaterift_last_autosave = 0.0;
+#include "vg/vg_msg.h"
+#include "addon.h"
 
 typedef struct savedata_file savedata_file;
 typedef struct savedata_group savedata_group;
@@ -19,11 +16,14 @@ struct savedata_group {
    files[];
 };
 
-static void savedata_file_read( savedata_file *file );
-static void savedata_file_write( savedata_file *file );
-static void savedata_group_write( savedata_group *group );
-
-//static void skaterift_read_main_save( savedata_file *sav );
-static int skaterift_autosave(int async);
+void savedata_file_read( savedata_file *file );
+void savedata_file_write( savedata_file *file );
+void savedata_group_write( savedata_group *group );
+int skaterift_autosave(int async);
+void skaterift_autosave_synchronous(void);
+void skaterift_autosave_update(void);
+void skaterift_read_addon_alias( vg_msg *msg, const char *key,
+                                 enum addon_type type, 
+                                 addon_alias *alias );
 
-#endif /* SAVE_H */
+void skaterift_read_main_savedata( savedata_file *file );
diff --git a/scene.c b/scene.c
new file mode 100644 (file)
index 0000000..f472f2c
--- /dev/null
+++ b/scene.c
@@ -0,0 +1,404 @@
+#include "scene.h"
+
+u32 scene_mem_required( scene_context *ctx )
+{
+   u32 vertex_length = vg_align8(ctx->max_vertices * sizeof(scene_vert)),
+       index_length  = vg_align8(ctx->max_indices  * sizeof(u32));
+
+   return vertex_length + index_length;
+}
+
+void scene_init( scene_context *ctx, u32 max_vertices, u32 max_indices )
+{
+   ctx->vertex_count = 0;
+   ctx->indice_count = 0;
+   ctx->max_vertices = max_vertices;
+   ctx->max_indices = max_indices;
+   ctx->arrindices = NULL; /* must be filled out by user */
+   ctx->arrvertices = NULL;
+
+   memset( &ctx->submesh, 0, sizeof(mdl_submesh) );
+
+   v3_fill( ctx->bbx[0],  999999.9f );
+   v3_fill( ctx->bbx[1], -999999.9f );
+}
+
+void scene_supply_buffer( scene_context *ctx, void *buffer )
+{
+   u32 vertex_length = vg_align8( ctx->max_vertices * sizeof(scene_vert) );
+
+   ctx->arrvertices = buffer;
+   ctx->arrindices  = (u32*)(((u8*)buffer) + vertex_length);
+}
+
+void scene_vert_pack_norm( scene_vert *vert, v3f norm, f32 blend )
+{
+   v3f n;
+   v3_muls( norm, 127.0f, n );
+   v3_minv( n, (v3f){  127.0f,  127.0f,  127.0f }, n );
+   v3_maxv( n, (v3f){ -127.0f, -127.0f, -127.0f }, n );
+   vert->norm[0] = n[0];
+   vert->norm[1] = n[1];
+   vert->norm[2] = n[2];
+   vert->norm[3] = blend * 127.0f;
+}
+
+/* 
+ * Append a model into the scene with a given transform
+ */
+void scene_add_mdl_submesh( scene_context *ctx, mdl_context *mdl, 
+                            mdl_submesh *sm, m4x3f transform )
+{
+   if( ctx->vertex_count + sm->vertex_count > ctx->max_vertices ){
+      vg_fatal_error( "Scene vertex buffer overflow (%u exceeds %u)\n",
+                        ctx->vertex_count + sm->vertex_count, 
+                        ctx->max_vertices );
+   }
+
+   if( ctx->indice_count + sm->indice_count > ctx->max_indices ){
+      vg_fatal_error( "Scene index buffer overflow (%u exceeds %u)\n",
+                        ctx->indice_count + sm->indice_count,
+                        ctx->max_indices );
+   }
+
+   mdl_vert   *src_verts = mdl_arritm( &mdl->verts, sm->vertex_start );
+   scene_vert *dst_verts = &ctx->arrvertices[ ctx->vertex_count ];
+
+   u32 *src_indices    =  mdl_arritm( &mdl->indices, sm->indice_start ),
+       *dst_indices    = &ctx->arrindices[ ctx->indice_count ];
+   
+   /* Transform and place vertices */
+   boxf bbxnew;
+   box_init_inf( bbxnew );
+   m4x3_expand_aabb_aabb( transform, bbxnew, sm->bbx );
+   box_concat( ctx->bbx, bbxnew );
+
+   m3x3f normal_matrix;
+   m3x3_copy( transform, normal_matrix );
+   v3_normalize( normal_matrix[0] );
+   v3_normalize( normal_matrix[1] );
+   v3_normalize( normal_matrix[2] );
+   
+   for( u32 i=0; i<sm->vertex_count; i++ ){
+      mdl_vert   *src   = &src_verts[i];
+      scene_vert *pvert = &dst_verts[i];
+
+      m4x3_mulv( transform, src->co, pvert->co );
+
+      v3f normal;
+      m3x3_mulv( normal_matrix, src->norm, normal );
+      scene_vert_pack_norm( pvert, normal, src->colour[0]*(1.0f/255.0f) );
+      
+      v2_copy( src->uv, pvert->uv );
+   }
+
+   u32 real_indices = 0;
+   for( u32 i=0; i<sm->indice_count/3; i++ ){
+      u32 *src = &src_indices[i*3],
+          *dst = &dst_indices[real_indices];
+
+      v3f ab, ac, tn;
+      v3_sub( src_verts[src[2]].co, src_verts[src[0]].co, ab );
+      v3_sub( src_verts[src[1]].co, src_verts[src[0]].co, ac );
+      v3_cross( ac, ab, tn );
+
+#if 0
+      if( v3_length2( tn ) <= 0.00001f )
+         continue;
+#endif
+
+      dst[0] = src[0] + ctx->vertex_count;
+      dst[1] = src[1] + ctx->vertex_count;
+      dst[2] = src[2] + ctx->vertex_count;
+
+      real_indices += 3;
+   }
+
+   if( real_indices != sm->indice_count )
+      vg_warn( "Zero area triangles in model\n" );
+
+   ctx->vertex_count += sm->vertex_count;
+   ctx->indice_count += real_indices;
+}
+
+/*
+ * One by one adders for simplified access (mostly procedural stuff)
+ */
+void scene_push_tri( scene_context *ctx, u32 tri[3] )
+{
+   if( ctx->indice_count + 3 > ctx->max_indices )
+      vg_fatal_error( "Scene indice buffer overflow (%u exceeds %u)\n",
+                        ctx->indice_count+3, ctx->max_indices );
+
+   u32 *dst = &ctx->arrindices[ ctx->indice_count ];
+
+   dst[0] = tri[0];
+   dst[1] = tri[1];
+   dst[2] = tri[2];
+
+   ctx->indice_count += 3;
+}
+
+void scene_push_vert( scene_context *ctx, scene_vert *v )
+{
+   if( ctx->vertex_count + 1 > ctx->max_vertices )
+      vg_fatal_error( "Scene vertex buffer overflow (%u exceeds %u)\n",
+                        ctx->vertex_count+1, ctx->max_vertices );
+
+   scene_vert *dst = &ctx->arrvertices[ ctx->vertex_count ];
+   *dst = *v;
+
+   ctx->vertex_count ++;
+}
+
+void scene_copy_slice( scene_context *ctx, mdl_submesh *sm )
+{
+   sm->indice_start = ctx->submesh.indice_start;
+   sm->indice_count = ctx->indice_count - sm->indice_start;
+
+   sm->vertex_start = ctx->submesh.vertex_start;
+   sm->vertex_count = ctx->vertex_count - sm->vertex_start;
+   
+   ctx->submesh.indice_start = ctx->indice_count;
+   ctx->submesh.vertex_start = ctx->vertex_count;
+}
+
+void scene_set_vertex_flags( scene_context *ctx, 
+                             u32 start, u32 count, u16 flags )
+{
+   for( u32 i=0; i<count; i++ )
+      ctx->arrvertices[ start + i ].flags = flags;
+}
+
+struct scene_upload_info{
+   scene_context *ctx;
+   glmesh *mesh;
+};
+
+void async_scene_upload( void *payload, u32 size )
+{
+   struct scene_upload_info *info = payload;
+
+   //assert( mesh->loaded == 0 );
+   
+   glmesh *mesh = info->mesh;
+   scene_context *ctx = info->ctx;
+
+   glGenVertexArrays( 1, &mesh->vao );
+   glGenBuffers( 1, &mesh->vbo );
+   glGenBuffers( 1, &mesh->ebo );
+   glBindVertexArray( mesh->vao );
+
+   size_t stride = sizeof(scene_vert);
+
+   glBindBuffer( GL_ARRAY_BUFFER, mesh->vbo );
+   glBufferData( GL_ARRAY_BUFFER, ctx->vertex_count*stride, 
+                 ctx->arrvertices, GL_STATIC_DRAW );
+
+   glBindVertexArray( mesh->vao );
+   glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, mesh->ebo );
+   glBufferData( GL_ELEMENT_ARRAY_BUFFER, ctx->indice_count*sizeof(u32),
+                 ctx->arrindices, GL_STATIC_DRAW );
+   
+   /* 0: coordinates */
+   glVertexAttribPointer( 0, 3, GL_FLOAT, GL_FALSE, stride, (void*)0 );
+   glEnableVertexAttribArray( 0 );
+
+   /* 1: normal */
+   glVertexAttribPointer( 1, 4, GL_BYTE, GL_TRUE,
+         stride, (void *)offsetof(scene_vert, norm) );
+   glEnableVertexAttribArray( 1 );
+
+   /* 2: uv */
+   glVertexAttribPointer( 2, 2, GL_FLOAT, GL_FALSE, 
+         stride, (void *)offsetof(scene_vert, uv) );
+   glEnableVertexAttribArray( 2 );
+
+   VG_CHECK_GL_ERR();
+
+   mesh->indice_count = ctx->indice_count;
+   mesh->loaded = 1;
+
+   vg_info( "Scene upload ( XYZ_f32 UV_f32 XYZW_i8 )[ u32 ]\n" );
+   vg_info( "   indices:%u\n", ctx->indice_count );
+   vg_info( "   verts:%u\n",   ctx->vertex_count );
+}
+
+void scene_upload_async( scene_context *ctx, glmesh *mesh )
+{
+   vg_async_item *call = vg_async_alloc( sizeof(struct scene_upload_info) );
+
+   struct scene_upload_info *info = call->payload;
+   info->mesh = mesh;
+   info->ctx = ctx;
+
+   vg_async_dispatch( call, async_scene_upload );
+}
+
+vg_async_item *scene_alloc_async( scene_context *scene, glmesh *mesh,
+                                  u32 max_vertices, u32 max_indices )
+{
+   scene_init( scene, max_vertices, max_indices );
+   u32 buf_size = scene_mem_required( scene );
+
+   u32 hdr_size = vg_align8(sizeof(struct scene_upload_info));
+   vg_async_item *call = vg_async_alloc( hdr_size + buf_size );
+
+   struct scene_upload_info *info = call->payload;
+
+   info->mesh = mesh;
+   info->ctx = scene;
+
+   void *buffer = ((u8*)call->payload)+hdr_size;
+   scene_supply_buffer( scene, buffer );
+
+   return call;
+}
+
+
+/*
+ * BVH implementation
+ */
+
+static void scene_bh_expand_bound( void *user, boxf bound, u32 item_index )
+{
+   scene_context *s = user;
+   scene_vert *pa = &s->arrvertices[ s->arrindices[item_index*3+0] ],
+              *pb = &s->arrvertices[ s->arrindices[item_index*3+1] ],
+              *pc = &s->arrvertices[ s->arrindices[item_index*3+2] ];
+   
+  box_addpt( bound, pa->co );
+  box_addpt( bound, pb->co );
+  box_addpt( bound, pc->co );
+}
+
+static float scene_bh_centroid( void *user, u32 item_index, int axis )
+{
+   scene_context *s = user;
+   scene_vert *pa = &s->arrvertices[ s->arrindices[item_index*3+0] ],
+              *pb = &s->arrvertices[ s->arrindices[item_index*3+1] ],
+              *pc = &s->arrvertices[ s->arrindices[item_index*3+2] ];
+
+   #if 0
+
+   float min, max;
+
+   min = vg_minf( pa->co[axis], pb->co[axis] );
+   max = vg_maxf( pa->co[axis], pb->co[axis] );
+   min = vg_minf( min, pc->co[axis] );
+   max = vg_maxf( max, pc->co[axis] );
+
+   return (min+max) * 0.5f;
+
+   #else
+   return (pa->co[axis] + pb->co[axis] + pc->co[axis]) * (1.0f/3.0f);
+   #endif
+}
+
+static void scene_bh_swap( void *user, u32 ia, u32 ib )
+{
+   scene_context *s = user;
+
+   u32 *ti = &s->arrindices[ia*3];
+   u32 *tj = &s->arrindices[ib*3];
+
+   u32 temp[3];
+   temp[0] = ti[0];
+   temp[1] = ti[1];
+   temp[2] = ti[2];
+
+   ti[0] = tj[0];
+   ti[1] = tj[1];
+   ti[2] = tj[2];
+
+   tj[0] = temp[0];
+   tj[1] = temp[1];
+   tj[2] = temp[2];
+}
+
+static void scene_bh_debug( void *user, u32 item_index )
+{
+   scene_context *s = user;
+   u32 idx = item_index*3;
+   scene_vert *pa = &s->arrvertices[ s->arrindices[ idx+0 ] ],
+              *pb = &s->arrvertices[ s->arrindices[ idx+1 ] ],
+              *pc = &s->arrvertices[ s->arrindices[ idx+2 ] ];
+
+   vg_line( pa->co, pb->co, 0xff0000ff );
+   vg_line( pb->co, pc->co, 0xff0000ff );
+   vg_line( pc->co, pa->co, 0xff0000ff );
+}
+
+static void scene_bh_closest( void *user, u32 index, v3f point, v3f closest )
+{
+   scene_context *s = user;
+
+   v3f positions[3];
+   u32 *tri = &s->arrindices[ index*3 ];
+   for( int i=0; i<3; i++ )
+      v3_copy( s->arrvertices[tri[i]].co, positions[i] );
+
+   closest_on_triangle_1( point, positions, closest );
+}
+
+bh_system bh_system_scene = 
+{
+   .expand_bound = scene_bh_expand_bound,
+   .item_centroid = scene_bh_centroid,
+   .item_closest = scene_bh_closest,
+   .item_swap = scene_bh_swap,
+   .item_debug = scene_bh_debug,
+};
+
+/*
+ * An extra step is added onto the end to calculate the hit normal
+ */
+int scene_raycast( scene_context *s, bh_tree *bh, 
+                   v3f co, v3f dir, ray_hit *hit, u16 ignore )
+{
+   hit->tri = NULL;
+
+   bh_iter it;
+   bh_iter_init_ray( 0, &it, co, dir, hit->dist );
+   i32 idx;
+
+   while( bh_next( bh, &it, &idx ) ){
+      u32 *tri = &s->arrindices[ idx*3 ];
+
+      if( s->arrvertices[tri[0]].flags & ignore )  continue;
+
+      v3f vs[3];
+      for( u32 i=0; i<3; i++ )
+         v3_copy( s->arrvertices[tri[i]].co, vs[i] );
+      
+      f32 t;
+      if( ray_tri( vs, co, dir, &t, 0 ) ){
+         if( t < hit->dist ){
+            hit->dist = t;
+            hit->tri = tri;
+         }
+      }
+   }
+
+   if( hit->tri ){
+      v3f v0, v1;
+      
+      float *pa = s->arrvertices[hit->tri[0]].co,
+            *pb = s->arrvertices[hit->tri[1]].co,
+            *pc = s->arrvertices[hit->tri[2]].co;
+
+      v3_sub( pa, pb, v0 );
+      v3_sub( pc, pb, v1 );
+      v3_cross( v1, v0, hit->normal );
+      v3_normalize( hit->normal );
+      v3_muladds( co, dir, hit->dist, hit->pos );
+   }
+
+   return hit->tri?1:0;
+}
+
+bh_tree *scene_bh_create( void *lin_alloc, scene_context *s )
+{
+   u32 triangle_count = s->indice_count / 3;
+   return bh_create( lin_alloc, &bh_system_scene, s, triangle_count, 2 );
+}
diff --git a/scene.h b/scene.h
index d8fac1ad524a05672feabee916237ddfbeac8acf..06f36bb75f65cda2110930eea995daefae561067 100644 (file)
--- a/scene.h
+++ b/scene.h
@@ -1,9 +1,7 @@
-#ifndef SCENE_H
-#define SCENE_H
-
+#pragma once
+#include "vg/vg_bvh.h"
 #include "common.h"
 #include "model.h"
-#include "bvh.h"
 
 typedef struct scene_context scene_context;
 typedef struct scene_vert scene_vert;
@@ -41,408 +39,22 @@ struct scene_context
    mdl_submesh submesh;
 };
 
-static u32 scene_mem_required( scene_context *ctx )
-{
-   u32 vertex_length = vg_align8(ctx->max_vertices * sizeof(scene_vert)),
-       index_length  = vg_align8(ctx->max_indices  * sizeof(u32));
-
-   return vertex_length + index_length;
-}
-
-static 
-void scene_init( scene_context *ctx, u32 max_vertices, u32 max_indices )
-{
-   ctx->vertex_count = 0;
-   ctx->indice_count = 0;
-   ctx->max_vertices = max_vertices;
-   ctx->max_indices = max_indices;
-   ctx->arrindices = NULL; /* must be filled out by user */
-   ctx->arrvertices = NULL;
-
-   memset( &ctx->submesh, 0, sizeof(mdl_submesh) );
-
-   v3_fill( ctx->bbx[0],  999999.9f );
-   v3_fill( ctx->bbx[1], -999999.9f );
-}
-
-void scene_supply_buffer( scene_context *ctx, void *buffer )
-{
-   u32 vertex_length = vg_align8( ctx->max_vertices * sizeof(scene_vert) );
-
-   ctx->arrvertices = buffer;
-   ctx->arrindices  = (u32*)(((u8*)buffer) + vertex_length);
-}
-
-static void scene_vert_pack_norm( scene_vert *vert, v3f norm, f32 blend ){
-   v3f n;
-   v3_muls( norm, 127.0f, n );
-   v3_minv( n, (v3f){  127.0f,  127.0f,  127.0f }, n );
-   v3_maxv( n, (v3f){ -127.0f, -127.0f, -127.0f }, n );
-   vert->norm[0] = n[0];
-   vert->norm[1] = n[1];
-   vert->norm[2] = n[2];
-   vert->norm[3] = blend * 127.0f;
-}
-
-/* 
- * Append a model into the scene with a given transform
- */
-static void scene_add_mdl_submesh( scene_context *ctx, mdl_context *mdl, 
-                                      mdl_submesh *sm, m4x3f transform )
-{
-   if( ctx->vertex_count + sm->vertex_count > ctx->max_vertices ){
-      vg_fatal_error( "Scene vertex buffer overflow (%u exceeds %u)\n",
-                        ctx->vertex_count + sm->vertex_count, 
-                        ctx->max_vertices );
-   }
-
-   if( ctx->indice_count + sm->indice_count > ctx->max_indices ){
-      vg_fatal_error( "Scene index buffer overflow (%u exceeds %u)\n",
-                        ctx->indice_count + sm->indice_count,
-                        ctx->max_indices );
-   }
-
-   mdl_vert   *src_verts = mdl_arritm( &mdl->verts, sm->vertex_start );
-   scene_vert *dst_verts = &ctx->arrvertices[ ctx->vertex_count ];
-
-   u32 *src_indices    =  mdl_arritm( &mdl->indices, sm->indice_start ),
-       *dst_indices    = &ctx->arrindices[ ctx->indice_count ];
-   
-   /* Transform and place vertices */
-   boxf bbxnew;
-   box_init_inf( bbxnew );
-   m4x3_expand_aabb_aabb( transform, bbxnew, sm->bbx );
-   box_concat( ctx->bbx, bbxnew );
-
-   m3x3f normal_matrix;
-   m3x3_copy( transform, normal_matrix );
-   v3_normalize( normal_matrix[0] );
-   v3_normalize( normal_matrix[1] );
-   v3_normalize( normal_matrix[2] );
-   
-   for( u32 i=0; i<sm->vertex_count; i++ ){
-      mdl_vert   *src   = &src_verts[i];
-      scene_vert *pvert = &dst_verts[i];
-
-      m4x3_mulv( transform, src->co, pvert->co );
-
-      v3f normal;
-      m3x3_mulv( normal_matrix, src->norm, normal );
-      scene_vert_pack_norm( pvert, normal, src->colour[0]*(1.0f/255.0f) );
-      
-      v2_copy( src->uv, pvert->uv );
-   }
-
-   u32 real_indices = 0;
-   for( u32 i=0; i<sm->indice_count/3; i++ ){
-      u32 *src = &src_indices[i*3],
-          *dst = &dst_indices[real_indices];
-
-      v3f ab, ac, tn;
-      v3_sub( src_verts[src[2]].co, src_verts[src[0]].co, ab );
-      v3_sub( src_verts[src[1]].co, src_verts[src[0]].co, ac );
-      v3_cross( ac, ab, tn );
-
-#if 0
-      if( v3_length2( tn ) <= 0.00001f )
-         continue;
-#endif
-
-      dst[0] = src[0] + ctx->vertex_count;
-      dst[1] = src[1] + ctx->vertex_count;
-      dst[2] = src[2] + ctx->vertex_count;
-
-      real_indices += 3;
-   }
-
-   if( real_indices != sm->indice_count )
-      vg_warn( "Zero area triangles in model\n" );
-
-   ctx->vertex_count += sm->vertex_count;
-   ctx->indice_count += real_indices;
-}
-
-/*
- * One by one adders for simplified access (mostly procedural stuff)
- */
-static void scene_push_tri( scene_context *ctx, u32 tri[3] )
-{
-   if( ctx->indice_count + 3 > ctx->max_indices )
-      vg_fatal_error( "Scene indice buffer overflow (%u exceeds %u)\n",
-                        ctx->indice_count+3, ctx->max_indices );
-
-   u32 *dst = &ctx->arrindices[ ctx->indice_count ];
-
-   dst[0] = tri[0];
-   dst[1] = tri[1];
-   dst[2] = tri[2];
-
-   ctx->indice_count += 3;
-}
-
-static void scene_push_vert( scene_context *ctx, scene_vert *v )
-{
-   if( ctx->vertex_count + 1 > ctx->max_vertices )
-      vg_fatal_error( "Scene vertex buffer overflow (%u exceeds %u)\n",
-                        ctx->vertex_count+1, ctx->max_vertices );
-
-   scene_vert *dst = &ctx->arrvertices[ ctx->vertex_count ];
-   *dst = *v;
-
-   ctx->vertex_count ++;
-}
-
-static void scene_copy_slice( scene_context *ctx, mdl_submesh *sm )
-{
-   sm->indice_start = ctx->submesh.indice_start;
-   sm->indice_count = ctx->indice_count - sm->indice_start;
-
-   sm->vertex_start = ctx->submesh.vertex_start;
-   sm->vertex_count = ctx->vertex_count - sm->vertex_start;
-   
-   ctx->submesh.indice_start = ctx->indice_count;
-   ctx->submesh.vertex_start = ctx->vertex_count;
-}
-
-static void scene_set_vertex_flags( scene_context *ctx, 
-                                       u32 start, u32 count, u16 flags ){
-   for( u32 i=0; i<count; i++ )
-      ctx->arrvertices[ start + i ].flags = flags;
-}
-
-struct scene_upload_info{
-   scene_context *ctx;
-   glmesh *mesh;
-};
-
-static void async_scene_upload( void *payload, u32 size )
-{
-   struct scene_upload_info *info = payload;
-
-   //assert( mesh->loaded == 0 );
-   
-   glmesh *mesh = info->mesh;
-   scene_context *ctx = info->ctx;
-
-   glGenVertexArrays( 1, &mesh->vao );
-   glGenBuffers( 1, &mesh->vbo );
-   glGenBuffers( 1, &mesh->ebo );
-   glBindVertexArray( mesh->vao );
-
-   size_t stride = sizeof(scene_vert);
-
-   glBindBuffer( GL_ARRAY_BUFFER, mesh->vbo );
-   glBufferData( GL_ARRAY_BUFFER, ctx->vertex_count*stride, 
-                 ctx->arrvertices, GL_STATIC_DRAW );
-
-   glBindVertexArray( mesh->vao );
-   glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, mesh->ebo );
-   glBufferData( GL_ELEMENT_ARRAY_BUFFER, ctx->indice_count*sizeof(u32),
-                 ctx->arrindices, GL_STATIC_DRAW );
-   
-   /* 0: coordinates */
-   glVertexAttribPointer( 0, 3, GL_FLOAT, GL_FALSE, stride, (void*)0 );
-   glEnableVertexAttribArray( 0 );
-
-   /* 1: normal */
-   glVertexAttribPointer( 1, 4, GL_BYTE, GL_TRUE,
-         stride, (void *)offsetof(scene_vert, norm) );
-   glEnableVertexAttribArray( 1 );
-
-   /* 2: uv */
-   glVertexAttribPointer( 2, 2, GL_FLOAT, GL_FALSE, 
-         stride, (void *)offsetof(scene_vert, uv) );
-   glEnableVertexAttribArray( 2 );
-
-   VG_CHECK_GL_ERR();
-
-   mesh->indice_count = ctx->indice_count;
-   mesh->loaded = 1;
-
-   vg_info( "Scene upload ( XYZ_f32 UV_f32 XYZW_i8 )[ u32 ]\n" );
-   vg_info( "   indices:%u\n", ctx->indice_count );
-   vg_info( "   verts:%u\n",   ctx->vertex_count );
-}
-
-static void scene_upload_async( scene_context *ctx, glmesh *mesh )
-{
-   vg_async_item *call = vg_async_alloc( sizeof(struct scene_upload_info) );
-
-   struct scene_upload_info *info = call->payload;
-   info->mesh = mesh;
-   info->ctx = ctx;
-
-   vg_async_dispatch( call, async_scene_upload );
-}
-
-static
+extern bh_system bh_system_scene;
+bh_tree *scene_bh_create( void *lin_alloc, scene_context *s );
+int scene_raycast( scene_context *s, bh_tree *bh, 
+                   v3f co, v3f dir, ray_hit *hit, u16 ignore );
 vg_async_item *scene_alloc_async( scene_context *scene, glmesh *mesh,
-                                  u32 max_vertices, u32 max_indices )
-{
-   scene_init( scene, max_vertices, max_indices );
-   u32 buf_size = scene_mem_required( scene );
-
-   u32 hdr_size = vg_align8(sizeof(struct scene_upload_info));
-   vg_async_item *call = vg_async_alloc( hdr_size + buf_size );
-
-   struct scene_upload_info *info = call->payload;
-
-   info->mesh = mesh;
-   info->ctx = scene;
-
-   void *buffer = ((u8*)call->payload)+hdr_size;
-   scene_supply_buffer( scene, buffer );
-
-   return call;
-}
-
-
-/*
- * BVH implementation
- */
-
-static void scene_bh_expand_bound( void *user, boxf bound, u32 item_index )
-{
-   scene_context *s = user;
-   scene_vert *pa = &s->arrvertices[ s->arrindices[item_index*3+0] ],
-              *pb = &s->arrvertices[ s->arrindices[item_index*3+1] ],
-              *pc = &s->arrvertices[ s->arrindices[item_index*3+2] ];
-   
-  box_addpt( bound, pa->co );
-  box_addpt( bound, pb->co );
-  box_addpt( bound, pc->co );
-}
-
-static float scene_bh_centroid( void *user, u32 item_index, int axis )
-{
-   scene_context *s = user;
-   scene_vert *pa = &s->arrvertices[ s->arrindices[item_index*3+0] ],
-              *pb = &s->arrvertices[ s->arrindices[item_index*3+1] ],
-              *pc = &s->arrvertices[ s->arrindices[item_index*3+2] ];
-
-   #if 0
-
-   float min, max;
-
-   min = vg_minf( pa->co[axis], pb->co[axis] );
-   max = vg_maxf( pa->co[axis], pb->co[axis] );
-   min = vg_minf( min, pc->co[axis] );
-   max = vg_maxf( max, pc->co[axis] );
-
-   return (min+max) * 0.5f;
-
-   #else
-   return (pa->co[axis] + pb->co[axis] + pc->co[axis]) * (1.0f/3.0f);
-   #endif
-}
-
-static void scene_bh_swap( void *user, u32 ia, u32 ib )
-{
-   scene_context *s = user;
-
-   u32 *ti = &s->arrindices[ia*3];
-   u32 *tj = &s->arrindices[ib*3];
-
-   u32 temp[3];
-   temp[0] = ti[0];
-   temp[1] = ti[1];
-   temp[2] = ti[2];
-
-   ti[0] = tj[0];
-   ti[1] = tj[1];
-   ti[2] = tj[2];
-
-   tj[0] = temp[0];
-   tj[1] = temp[1];
-   tj[2] = temp[2];
-}
-
-static void scene_bh_debug( void *user, u32 item_index )
-{
-   scene_context *s = user;
-   u32 idx = item_index*3;
-   scene_vert *pa = &s->arrvertices[ s->arrindices[ idx+0 ] ],
-              *pb = &s->arrvertices[ s->arrindices[ idx+1 ] ],
-              *pc = &s->arrvertices[ s->arrindices[ idx+2 ] ];
-
-   vg_line( pa->co, pb->co, 0xff0000ff );
-   vg_line( pb->co, pc->co, 0xff0000ff );
-   vg_line( pc->co, pa->co, 0xff0000ff );
-}
-
-static void scene_bh_closest( void *user, u32 index, v3f point, v3f closest )
-{
-   scene_context *s = user;
-
-   v3f positions[3];
-   u32 *tri = &s->arrindices[ index*3 ];
-   for( int i=0; i<3; i++ )
-      v3_copy( s->arrvertices[tri[i]].co, positions[i] );
-
-   closest_on_triangle_1( point, positions, closest );
-}
-
-static bh_system bh_system_scene = 
-{
-   .expand_bound = scene_bh_expand_bound,
-   .item_centroid = scene_bh_centroid,
-   .item_closest = scene_bh_closest,
-   .item_swap = scene_bh_swap,
-   .item_debug = scene_bh_debug,
-   .system_type = 0x1
-};
-
-/*
- * An extra step is added onto the end to calculate the hit normal
- */
-static int scene_raycast( scene_context *s, bh_tree *bh, 
-                             v3f co, v3f dir, ray_hit *hit, u16 ignore )
-{
-   hit->tri = NULL;
-
-   bh_iter it;
-   bh_iter_init_ray( 0, &it, co, dir, hit->dist );
-   i32 idx;
-
-   while( bh_next( bh, &it, &idx ) ){
-      u32 *tri = &s->arrindices[ idx*3 ];
-
-      if( s->arrvertices[tri[0]].flags & ignore )  continue;
-
-      v3f vs[3];
-      for( u32 i=0; i<3; i++ )
-         v3_copy( s->arrvertices[tri[i]].co, vs[i] );
-      
-      f32 t;
-      if( ray_tri( vs, co, dir, &t, 0 ) ){
-         if( t < hit->dist ){
-            hit->dist = t;
-            hit->tri = tri;
-         }
-      }
-   }
-
-   if( hit->tri ){
-      v3f v0, v1;
-      
-      float *pa = s->arrvertices[hit->tri[0]].co,
-            *pb = s->arrvertices[hit->tri[1]].co,
-            *pc = s->arrvertices[hit->tri[2]].co;
-
-      v3_sub( pa, pb, v0 );
-      v3_sub( pc, pb, v1 );
-      v3_cross( v1, v0, hit->normal );
-      v3_normalize( hit->normal );
-      v3_muladds( co, dir, hit->dist, hit->pos );
-   }
-
-   return hit->tri?1:0;
-}
-
-static bh_tree *scene_bh_create( void *lin_alloc, scene_context *s )
-{
-   u32 triangle_count = s->indice_count / 3;
-   return bh_create( lin_alloc, &bh_system_scene, s, triangle_count, 2 );
-}
-
-#endif
+                                  u32 max_vertices, u32 max_indices );
+void scene_copy_slice( scene_context *ctx, mdl_submesh *sm );
+void scene_push_vert( scene_context *ctx, scene_vert *v );
+void scene_vert_pack_norm( scene_vert *vert, v3f norm, f32 blend );
+void scene_push_tri( scene_context *ctx, u32 tri[3] );
+void scene_add_mdl_submesh( scene_context *ctx, mdl_context *mdl, 
+                            mdl_submesh *sm, m4x3f transform );
+void scene_set_vertex_flags( scene_context *ctx, 
+                             u32 start, u32 count, u16 flags );
+void scene_supply_buffer( scene_context *ctx, void *buffer );
+void scene_init( scene_context *ctx, u32 max_vertices, u32 max_indices );
+u32 scene_mem_required( scene_context *ctx );
+void async_scene_upload( void *payload, u32 size );
+void scene_upload_async( scene_context *ctx, glmesh *mesh );
index 116007aa8194e58c09644ec8721ac4596ea61f52..94d3dce07db7da39f050b85b5dec539c793929c5 100644 (file)
@@ -1,87 +1,18 @@
-#ifndef SHADER_blit_H
-#define SHADER_blit_H
-static void shader_blit_link(void);
-static void shader_blit_register(void);
-static struct vg_shader _shader_blit = {
-   .name = "blit",
-   .link = shader_blit_link,
-   .vs = 
+#pragma once
+#include "vg/vg_engine.h"
+extern struct vg_shader _shader_blit;
+extern GLuint _uniform_blit_uInverseRatio;
+extern GLuint _uniform_blit_uTexMain;
+static inline void shader_blit_uInverseRatio(v2f v)
 {
-.orig_file = "shaders/blit.vs",
-.static_src = 
-"layout (location=0) in vec2 a_co;\n"
-"out vec2 aUv;\n"
-"\n"
-"uniform vec2 uInverseRatio;\n"
-"\n"
-"void main()\n"
-"{\n"
-"   gl_Position = vec4(a_co*2.0-1.0,0.0,1.0);\n"
-"   aUv = a_co * uInverseRatio;\n"
-"}\n"
-""},
-   .fs = 
-{
-.orig_file = "shaders/blit.fs",
-.static_src = 
-"out vec4 FragColor;\n"
-"uniform sampler2D uTexMain;\n"
-"\n"
-"in vec2 aUv;\n"
-"\n"
-"float kPi = 3.14159265358979;\n"
-"\n"
-"vec2 fisheye_distort(vec2 xy)\n"
-"{\n"
-"   float aperture = 1350.0;\n"
-"   float apertureHalf = 0.5 * aperture * (kPi / 180.0);\n"
-"   float maxFactor = sin(apertureHalf);\n"
-"\n"
-"   vec2 uv;\n"
-"   float d = length(xy);\n"
-"   if(d < (2.0-maxFactor))\n"
-"   {\n"
-"      d = length(xy * maxFactor);\n"
-"      float z = sqrt(1.0 - d * d);\n"
-"      float r = atan(d, z) / kPi;\n"
-"      float phi = atan(xy.y, xy.x);\n"
-"\n"
-"      uv.x = r * cos(phi) + 0.5;\n"
-"      uv.y = r * sin(phi) + 0.5;\n"
-"   }\n"
-"   else\n"
-"   {\n"
-"      uv = 0.5*xy + 0.5;\n"
-"   }\n"
-"   \n"
-"   return uv;\n"
-"}\n"
-"\n"
-"\n"
-"void main()\n"
-"{\n"
-"   vec2 vwarp = 2.0*aUv - 1.0;\n"
-"   vwarp = fisheye_distort( vwarp );\n"
-"\n"
-"   FragColor = texture( uTexMain, aUv );\n"
-"}\n"
-""},
-};
-
-static GLuint _uniform_blit_uInverseRatio;
-static GLuint _uniform_blit_uTexMain;
-static void shader_blit_uInverseRatio(v2f v){
    glUniform2fv(_uniform_blit_uInverseRatio,1,v);
 }
-static void shader_blit_uTexMain(int i){
+static inline void shader_blit_uTexMain(int i)
+{
    glUniform1i(_uniform_blit_uTexMain,i);
 }
-static void shader_blit_register(void){
-   vg_shader_register( &_shader_blit );
-}
-static void shader_blit_use(void){ glUseProgram(_shader_blit.id); }
-static void shader_blit_link(void){
-   _uniform_blit_uInverseRatio = glGetUniformLocation( _shader_blit.id, "uInverseRatio" );
-   _uniform_blit_uTexMain = glGetUniformLocation( _shader_blit.id, "uTexMain" );
+static inline void shader_blit_use(void);
+static inline void shader_blit_use(void)
+{
+   glUseProgram(_shader_blit.id);
 }
-#endif /* SHADER_blit_H */
index f5f304973fa8be35f40f6665f0ef8544cd95f0a1..f73d1d4191a9352734adfd67ff11540dab4613ce 100644 (file)
@@ -1,61 +1,18 @@
-#ifndef SHADER_blit_transition_H
-#define SHADER_blit_transition_H
-static void shader_blit_transition_link(void);
-static void shader_blit_transition_register(void);
-static struct vg_shader _shader_blit_transition = {
-   .name = "blit_transition",
-   .link = shader_blit_transition_link,
-   .vs = 
+#pragma once
+#include "vg/vg_engine.h"
+extern struct vg_shader _shader_blit_transition;
+extern GLuint _uniform_blit_transition_uInverseRatio;
+extern GLuint _uniform_blit_transition_uT;
+static inline void shader_blit_transition_uInverseRatio(v2f v)
 {
-.orig_file = "shaders/blit.vs",
-.static_src = 
-"layout (location=0) in vec2 a_co;\n"
-"out vec2 aUv;\n"
-"\n"
-"uniform vec2 uInverseRatio;\n"
-"\n"
-"void main()\n"
-"{\n"
-"   gl_Position = vec4(a_co*2.0-1.0,0.0,1.0);\n"
-"   aUv = a_co * uInverseRatio;\n"
-"}\n"
-""},
-   .fs = 
-{
-.orig_file = "shaders/blit_transition.fs",
-.static_src = 
-"out vec4 FragColor;\n"
-"in vec2 aUv;\n"
-"uniform float uT;\n"
-"\n"
-"void main(){\n"
-"   float d = uT + distance( aUv, vec2(0.5,0.5) );\n"
-"\n"
-"   vec3 vDither = vec3( dot( vec2( 171.0, 231.0 ), gl_FragCoord.xy) );\n"
-"   float dither = fract( vDither.g / 71.0 ) - 0.5;\n"
-"\n"
-"   if( d+dither < -0.5 )\n"
-"      discard;\n"
-"\n"
-"   FragColor = vec4( 1.0, 0.0, 0.0, 1.0 );\n"
-"}\n"
-""},
-};
-
-static GLuint _uniform_blit_transition_uInverseRatio;
-static GLuint _uniform_blit_transition_uT;
-static void shader_blit_transition_uInverseRatio(v2f v){
    glUniform2fv(_uniform_blit_transition_uInverseRatio,1,v);
 }
-static void shader_blit_transition_uT(float f){
+static inline void shader_blit_transition_uT(f32 f)
+{
    glUniform1f(_uniform_blit_transition_uT,f);
 }
-static void shader_blit_transition_register(void){
-   vg_shader_register( &_shader_blit_transition );
-}
-static void shader_blit_transition_use(void){ glUseProgram(_shader_blit_transition.id); }
-static void shader_blit_transition_link(void){
-   _uniform_blit_transition_uInverseRatio = glGetUniformLocation( _shader_blit_transition.id, "uInverseRatio" );
-   _uniform_blit_transition_uT = glGetUniformLocation( _shader_blit_transition.id, "uT" );
+static inline void shader_blit_transition_use(void);
+static inline void shader_blit_transition_use(void)
+{
+   glUseProgram(_shader_blit_transition.id);
 }
-#endif /* SHADER_blit_transition_H */
index ac8f3cc20cf3e3bcfd58deca8a63a32de1a58b4c..8a75c38d69aa48b311e83667c3eaaef216ba68f8 100644 (file)
-#ifndef SHADER_blitblur_H
-#define SHADER_blitblur_H
-static void shader_blitblur_link(void);
-static void shader_blitblur_register(void);
-static struct vg_shader _shader_blitblur = {
-   .name = "blitblur",
-   .link = shader_blitblur_link,
-   .vs = 
+#pragma once
+#include "vg/vg_engine.h"
+extern struct vg_shader _shader_blitblur;
+extern GLuint _uniform_blitblur_uInverseRatio;
+extern GLuint _uniform_blitblur_uTexMain;
+extern GLuint _uniform_blitblur_uTexMotion;
+extern GLuint _uniform_blitblur_uBlurStrength;
+extern GLuint _uniform_blitblur_uOverrideDir;
+extern GLuint _uniform_blitblur_uTime;
+extern GLuint _uniform_blitblur_uGlitchStrength;
+extern GLuint _uniform_blitblur_uClampUv;
+static inline void shader_blitblur_uInverseRatio(v2f v)
 {
-.orig_file = "shaders/blit.vs",
-.static_src = 
-"layout (location=0) in vec2 a_co;\n"
-"out vec2 aUv;\n"
-"\n"
-"uniform vec2 uInverseRatio;\n"
-"\n"
-"void main()\n"
-"{\n"
-"   gl_Position = vec4(a_co*2.0-1.0,0.0,1.0);\n"
-"   aUv = a_co * uInverseRatio;\n"
-"}\n"
-""},
-   .fs = 
-{
-.orig_file = "shaders/blitblur.fs",
-.static_src = 
-"out vec4 FragColor;\n"
-"uniform sampler2D uTexMain;\n"
-"uniform sampler2D uTexMotion;\n"
-"uniform float uBlurStrength;\n"
-"uniform vec2 uOverrideDir;\n"
-"uniform float uTime;\n"
-"uniform float uGlitchStrength;\n"
-"uniform vec2 uClampUv;\n"
-"\n"
-"in vec2 aUv;\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"
-"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, vuv ).xy * uBlurStrength + uOverrideDir;\n"
-"\n"
-"   vec4 vcolour0 = texture( uTexMain, min(vuv + vdir*vrand.x,uClampUv) );\n"
-"   vec4 vcolour1 = texture( uTexMain, min(vuv + vdir*vrand.y,uClampUv) );\n"
-"   vec4 vcolour2 = texture( uTexMain, min(vuv + vdir*vrand1.x,uClampUv) );\n"
-"   vec4 vcolour3 = texture( uTexMain, min(vuv + vdir*vrand1.y,uClampUv) );\n"
-"\n"
-"   FragColor = ( vcolour0 + vcolour1 + vcolour2 + vcolour3 ) * 0.25;\n"
-"}\n"
-""},
-};
-
-static GLuint _uniform_blitblur_uInverseRatio;
-static GLuint _uniform_blitblur_uTexMain;
-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 GLuint _uniform_blitblur_uClampUv;
-static void shader_blitblur_uInverseRatio(v2f v){
    glUniform2fv(_uniform_blitblur_uInverseRatio,1,v);
 }
-static void shader_blitblur_uTexMain(int i){
+static inline void shader_blitblur_uTexMain(int i)
+{
    glUniform1i(_uniform_blitblur_uTexMain,i);
 }
-static void shader_blitblur_uTexMotion(int i){
+static inline void shader_blitblur_uTexMotion(int i)
+{
    glUniform1i(_uniform_blitblur_uTexMotion,i);
 }
-static void shader_blitblur_uBlurStrength(float f){
+static inline void shader_blitblur_uBlurStrength(f32 f)
+{
    glUniform1f(_uniform_blitblur_uBlurStrength,f);
 }
-static void shader_blitblur_uOverrideDir(v2f v){
+static inline void shader_blitblur_uOverrideDir(v2f v)
+{
    glUniform2fv(_uniform_blitblur_uOverrideDir,1,v);
 }
-static void shader_blitblur_uTime(float f){
+static inline void shader_blitblur_uTime(f32 f)
+{
    glUniform1f(_uniform_blitblur_uTime,f);
 }
-static void shader_blitblur_uGlitchStrength(float f){
+static inline void shader_blitblur_uGlitchStrength(f32 f)
+{
    glUniform1f(_uniform_blitblur_uGlitchStrength,f);
 }
-static void shader_blitblur_uClampUv(v2f v){
+static inline void shader_blitblur_uClampUv(v2f v)
+{
    glUniform2fv(_uniform_blitblur_uClampUv,1,v);
 }
-static void shader_blitblur_register(void){
-   vg_shader_register( &_shader_blitblur );
-}
-static void shader_blitblur_use(void){ glUseProgram(_shader_blitblur.id); }
-static void shader_blitblur_link(void){
-   _uniform_blitblur_uInverseRatio = glGetUniformLocation( _shader_blitblur.id, "uInverseRatio" );
-   _uniform_blitblur_uTexMain = glGetUniformLocation( _shader_blitblur.id, "uTexMain" );
-   _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" );
-   _uniform_blitblur_uClampUv = glGetUniformLocation( _shader_blitblur.id, "uClampUv" );
+static inline void shader_blitblur_use(void);
+static inline void shader_blitblur_use(void)
+{
+   glUseProgram(_shader_blitblur.id);
 }
-#endif /* SHADER_blitblur_H */
index 91a2e618dadde87618690ad999af6a2899947e00..1bd3349497bd7b75f7ce986892e024e6e1fecda9 100644 (file)
@@ -1,55 +1,18 @@
-#ifndef SHADER_blitcolour_H
-#define SHADER_blitcolour_H
-static void shader_blitcolour_link(void);
-static void shader_blitcolour_register(void);
-static struct vg_shader _shader_blitcolour = {
-   .name = "blitcolour",
-   .link = shader_blitcolour_link,
-   .vs = 
+#pragma once
+#include "vg/vg_engine.h"
+extern struct vg_shader _shader_blitcolour;
+extern GLuint _uniform_blitcolour_uInverseRatio;
+extern GLuint _uniform_blitcolour_uColour;
+static inline void shader_blitcolour_uInverseRatio(v2f v)
 {
-.orig_file = "shaders/blit.vs",
-.static_src = 
-"layout (location=0) in vec2 a_co;\n"
-"out vec2 aUv;\n"
-"\n"
-"uniform vec2 uInverseRatio;\n"
-"\n"
-"void main()\n"
-"{\n"
-"   gl_Position = vec4(a_co*2.0-1.0,0.0,1.0);\n"
-"   aUv = a_co * uInverseRatio;\n"
-"}\n"
-""},
-   .fs = 
-{
-.orig_file = "shaders/colour.fs",
-.static_src = 
-"out vec4 FragColor;\n"
-"uniform vec4 uColour;\n"
-"\n"
-"in vec2 aUv;\n"
-"\n"
-"void main()\n"
-"{\n"
-"   FragColor = uColour;\n"
-"}\n"
-""},
-};
-
-static GLuint _uniform_blitcolour_uInverseRatio;
-static GLuint _uniform_blitcolour_uColour;
-static void shader_blitcolour_uInverseRatio(v2f v){
    glUniform2fv(_uniform_blitcolour_uInverseRatio,1,v);
 }
-static void shader_blitcolour_uColour(v4f v){
+static inline void shader_blitcolour_uColour(v4f v)
+{
    glUniform4fv(_uniform_blitcolour_uColour,1,v);
 }
-static void shader_blitcolour_register(void){
-   vg_shader_register( &_shader_blitcolour );
-}
-static void shader_blitcolour_use(void){ glUseProgram(_shader_blitcolour.id); }
-static void shader_blitcolour_link(void){
-   _uniform_blitcolour_uInverseRatio = glGetUniformLocation( _shader_blitcolour.id, "uInverseRatio" );
-   _uniform_blitcolour_uColour = glGetUniformLocation( _shader_blitcolour.id, "uColour" );
+static inline void shader_blitcolour_use(void);
+static inline void shader_blitcolour_use(void)
+{
+   glUseProgram(_shader_blitcolour.id);
 }
-#endif /* SHADER_blitcolour_H */
diff --git a/shaders/impl.c b/shaders/impl.c
new file mode 100644 (file)
index 0000000..0bc64bb
--- /dev/null
@@ -0,0 +1,11365 @@
+#include "shaders/scene_standard.h"
+struct vg_shader _shader_scene_standard = {
+   .name = "scene_standard",
+   .vs = 
+{
+.orig_file = "shaders/scene.vs",
+.static_src = 
+"layout (location=0) in vec3  a_co;\n"
+"layout (location=1) in vec4  a_norm;\n"
+"layout (location=2) in vec2  a_uv;\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      6        0 \n"
+"\n"
+"uniform mat4x3 uMdl;\n"
+"uniform mat4   uPv;\n"
+"uniform mat4   uPvmPrev;\n"
+"\n"
+"out vec2 aUv;\n"
+"out vec4 aNorm;\n"
+"out vec3 aCo;\n"
+"out vec3 aWorldCo;\n"
+"\n"
+"void main()\n"
+"{\n"
+"   vec3 world_pos0 = uMdl     * vec4( a_co, 1.0 );\n"
+"   vec4 vproj0     = uPv      * vec4( world_pos0, 1.0 );\n"
+"   vec4 vproj1     = uPvmPrev * vec4( a_co, 1.0 );\n"
+"\n"
+"   vs_motion_out( vproj0, vproj1 );\n"
+"\n"
+"   gl_Position = vproj0;\n"
+"\n"
+"   aUv = a_uv;\n"
+"   aNorm = vec4( mat3(uMdl) * a_norm.xyz, a_norm.w );\n"
+"   aCo = a_co;\n"
+"   aWorldCo = world_pos0;\n"
+"}\n"
+""},
+   .fs = 
+{
+.orig_file = "shaders/scene_standard.fs",
+.static_src = 
+"uniform sampler2D uTexGarbage;\n"
+"uniform sampler2D uTexMain;\n"
+"uniform vec3 uCamera;\n"
+"uniform vec4 uPlane;\n"
+"\n"
+"#line       1        1 \n"
+"// :D\n"
+"const float CLEARSKIES_LIGHT_DOT_MIN = 0.0;\n"
+"\n"
+"#line      7        0 \n"
+"#line       1        2 \n"
+"// :D\n"
+"\n"
+"in vec2 aUv;\n"
+"in vec4 aNorm;\n"
+"in vec3 aCo;\n"
+"in vec3 aWorldCo;\n"
+"\n"
+"#line       1        1 \n"
+"layout (location = 0) out vec4 oColour;\n"
+"\n"
+"// OpenGL wiki: Recommends do not use vec3 because of drivers. hence the v4s...\n"
+"layout (std140) uniform ub_world_lighting\n"
+"{\n"
+"   vec4 g_cube_min;\n"
+"   vec4 g_cube_inv_range;\n"
+"\n"
+"   vec4 g_water_plane;\n"
+"   vec4 g_depth_bounds;\n"
+"\n"
+"   vec4 g_daysky_colour;\n"
+"   vec4 g_nightsky_colour;\n"
+"   vec4 g_sunset_colour;\n"
+"   vec4 g_ambient_colour;\n"
+"   vec4 g_sunset_ambient;\n"
+"   vec4 g_sun_colour;\n"
+"   vec4 g_sun_dir;\n"
+"   vec4 g_board_0;\n"
+"   vec4 g_board_1;\n"
+"\n"
+"   float g_water_fog;\n"
+"   float g_time;\n"
+"   float g_realtime;\n"
+"   float g_shadow_length;\n"
+"   float g_shadow_spread;\n"
+"\n"
+"   float g_time_of_day;\n"
+"   float g_day_phase;\n"
+"   float g_sunset_phase;\n"
+"\n"
+"   int g_light_preview;\n"
+"   int g_shadow_samples;\n"
+"\n"
+"   int g_debug_indices;\n"
+"   int g_debug_complexity;\n"
+"};\n"
+"\n"
+"uniform sampler2D g_world_depth;\n"
+"uniform samplerBuffer uLightsArray;\n"
+"uniform usampler3D uLightsIndex;\n"
+"\n"
+"#line       1        1 \n"
+"//const vec3  DAYSKY_COLOUR   = vec3( 0.37, 0.54, 0.97 );\n"
+"//const vec3  NIGHTSKY_COLOUR = vec3( 0.03, 0.05, 0.20 );\n"
+"//const vec3  SUNSET_COLOUR   = vec3( 1.00, 0.32, 0.01 );\n"
+"//const vec3  AMBIENT_COLOUR  = vec3( 0.13, 0.17, 0.35 );\n"
+"//const vec3  SUNSET_AMBIENT  = vec3( 0.25, 0.17, 0.51 );\n"
+"//const vec3  SUN_COLOUR      = vec3( 1.10, 0.89, 0.35 );\n"
+"\n"
+"const float SUN_ANGLE       = 0.0001;\n"
+"const float PI              = 3.14159265358979323846264;\n"
+"\n"
+"//struct world_info\n"
+"//{\n"
+"//   float time,\n"
+"//         time_of_day,\n"
+"//         day_phase,\n"
+"//         sunset_phase;\n"
+"//   \n"
+"//   vec3 sun_dir;\n"
+"//};\n"
+"\n"
+"vec3 rand33(vec3 p3)\n"
+"{\n"
+"      p3 = fract(p3 * vec3(.1031, .1030, .0973));\n"
+"   p3 += dot(p3, p3.yxz+33.33);\n"
+"   return fract((p3.xxy + p3.yxx)*p3.zyx);\n"
+"}\n"
+"\n"
+"float stars( vec3 rd, float rr, float size ){\n"
+"   vec3 co = rd * rr;\n"
+"\n"
+"   float a = atan(co.y, length(co.xz)) + 4.0 * PI;\n"
+"\n"
+"   float spaces = 1.0 / rr;\n"
+"   size = (rr * 0.0015) * fwidth(a) * 1000.0 * size;\n"
+"   a -= mod(a, spaces) - spaces * 0.5;\n"
+"\n"
+"   float count = floor(sqrt(pow(rr, 2.0) * (1.0 - pow(sin(a), 2.0))) * 3.0);\n"
+"   \n"
+"   float plane = atan(co.z, co.x) + 4.0 * PI;\n"
+"   plane = plane - mod(plane, PI / count);\n"
+"\n"
+"   vec2 delta = rand33(vec3(plane, a, 0.0)).xy;\n"
+"\n"
+"   float level = sin(a + spaces * (delta.y - 0.5) * (1.0 - size)) * rr;\n"
+"   float ydist = sqrt(rr * rr - level * level);\n"
+"   float angle = plane + (PI * (delta.x * (1.0-size) + size * 0.5) / count);\n"
+"   vec3 center = vec3(cos(angle) * ydist, level, sin(angle) * ydist);\n"
+"   float star = smoothstep(size, 0.0, distance(center, co));\n"
+"   return star;\n"
+"}\n"
+"\n"
+"float luminance( vec3 v )\n"
+"{\n"
+"   return dot( v, vec3(0.2126, 0.7152, 0.0722) );\n"
+"}\n"
+"\n"
+"vec3 clearskies_ambient( vec3 dir )\n"
+"{\n"
+"   float sun_azimuth  = g_sunset_phase * (dot( dir.xz, g_sun_dir.xz )*0.4+0.6);\n"
+"   float sky_gradient = dir.y;\n"
+"   \n"
+"   /* Blend phase colours */\n"
+"   vec3 ambient  = g_daysky_colour.rgb   * (g_day_phase-g_sunset_phase*0.1);\n"
+"        ambient += g_sunset_colour.rgb   * (1.0-dir.y*0.5)*sun_azimuth;\n"
+"        ambient += g_nightsky_colour.rgb * (1.0-g_day_phase);\n"
+"   \n"
+"   /* Add gradient */\n"
+"        ambient -= sky_gradient * luminance(ambient);\n"
+"        \n"
+"   return ambient;\n"
+"}\n"
+"\n"
+"vec3 clearskies_sky( vec3 ray_dir )\n"
+"{\n"
+"   ray_dir.y = abs( ray_dir.y );\n"
+"   vec3 sky_colour  = clearskies_ambient( ray_dir );\n"
+"   \n"
+"   /* Sun */\n"
+"   float sun_theta  = dot( ray_dir, g_sun_dir.xyz );\n"
+"   float sun_size   = max( 0.0, sun_theta * 0.5 + 0.5 + SUN_ANGLE );\n"
+"   float sun_shape  = pow( sun_size, 2000.0 );\n"
+"         sun_shape += sun_size * max(g_sun_dir.y,0.0) * 0.5;\n"
+"         \n"
+"   vec3 sun_colour  = mix( vec3(1.0), g_sunset_colour.rgb, g_sunset_phase*0.5 );\n"
+"        sun_colour *= sun_shape;\n"
+"\n"
+"   \n"
+"   float star = 0.0;\n"
+"   float star_blend = 10.0*max(0.0,(1.0-g_day_phase*2.0));\n"
+"\n"
+"   if( star_blend > 0.001 ){\n"
+"      for( float j = 1.0; j <= 4.1; j += 1.0 ){\n"
+"         float m = mix(0.6, 0.9, smoothstep(1.0, 2.0, j));\n"
+"         star += stars( ray_dir, 1.94 * pow( 1.64, j ), m ) * (1.0/pow(4.0, j));\n"
+"      }\n"
+"   }\n"
+"   \n"
+"   vec3 composite   = sky_colour + sun_colour + star*star_blend;\n"
+"   return composite;\n"
+"}\n"
+"\n"
+"vec3 clearskies_lighting( vec3 normal, float shadow, vec3 halfview )\n"
+"{\n"
+"   float fresnel = 1.0 - abs(dot(normal,halfview));\n"
+"\n"
+"   vec3  reflect_colour = mix( g_daysky_colour.rgb, g_sunset_colour.rgb, \n"
+"                               g_sunset_phase );\n"
+"\n"
+"   vec3  sky_reflection = 0.5 * fresnel * reflect_colour;\n"
+"   vec3  light_sun      = max( CLEARSKIES_LIGHT_DOT_MIN, \n"
+"                               dot(normal,g_sun_dir.xyz)*0.75+0.25\n"
+"                           ) * g_sun_colour.rgb * g_day_phase;\n"
+"\n"
+"   float scaled_shadow = max( shadow, 1.0 - max(g_sun_dir.y,0.0) );\n"
+"   vec3 ambient = mix( g_ambient_colour.rgb, g_sunset_ambient.rgb, \n"
+"                       g_sunset_phase );\n"
+"\n"
+"   return ambient + (light_sun + sky_reflection) * shadow;\n"
+"}\n"
+"\n"
+"#line     44        0 \n"
+"\n"
+"float world_depth_sample( vec3 pos )\n"
+"{\n"
+"   vec2 depth_coord = (pos.xz - g_depth_bounds.xy) * g_depth_bounds.zw; \n"
+"   return texture( g_world_depth, depth_coord ).r;\n"
+"}\n"
+"\n"
+"float world_water_depth( vec3 pos )\n"
+"{\n"
+"   float ref_depth = g_water_plane.y*g_water_plane.w;\n"
+"   return world_depth_sample( pos ) - ref_depth;\n"
+"}\n"
+"\n"
+"float shadow_sample( vec3 co ){\n"
+"   float height_sample = world_depth_sample( co );\n"
+"\n"
+"   float fdelta = height_sample - co.y;\n"
+"   return clamp( fdelta, 0.2, 0.4 )-0.2;\n"
+"}\n"
+"\n"
+"float newlight_compute_sun_shadow( vec3 co, vec3 dir ){\n"
+"   if( g_shadow_samples == 0 ){\n"
+"      return 1.0;\n"
+"   }\n"
+"\n"
+"   float fspread = g_shadow_spread;\n"
+"   float flength = g_shadow_length;\n"
+"\n"
+"   float famt = 0.0;\n"
+"   famt += shadow_sample(co+(dir+vec3(-0.56,0.55, 0.30)*fspread)*flength*0.1);\n"
+"   famt += shadow_sample(co+(dir+vec3( 0.80,0.68, 0.34)*fspread)*flength*0.2);\n"
+"   famt += shadow_sample(co+(dir+vec3( 0.78,0.07,-0.06)*fspread)*flength*0.3);\n"
+"   famt += shadow_sample(co+(dir+vec3(-0.59,0.07,-0.42)*fspread)*flength*0.4);\n"
+"\n"
+"   //famt+=shadow_sample(co+(dir+vec3(-0.790,-0.933,-0.875)*fspread)*flength*0.5);\n"
+"   //famt+=shadow_sample(co+(dir+vec3( 0.807,-0.690, 0.472)*fspread)*flength*0.6);\n"
+"   //famt+=shadow_sample(co+(dir+vec3( 0.522,-0.379, 0.350)*fspread)*flength*0.7);\n"
+"   //famt+=shadow_sample(co+(dir+vec3( 0.483, 0.201, 0.306)*fspread)*flength*0.8);\n"
+"\n"
+"   return 1.0 - famt;\n"
+"}\n"
+"\n"
+"float newlight_specular( vec3 wnormal, vec3 dir, vec3 halfview, float exponent )\n"
+"{\n"
+"   vec3 specdir = reflect( -dir, wnormal );\n"
+"   return pow(max(dot( halfview, specdir ), 0.0), exponent);\n"
+"}\n"
+"\n"
+"vec3 scene_apply_fog( vec3 vfrag, vec3 colour, float fdist ){\n"
+"   float dist = pow(fdist*0.0010,0.78);\n"
+"   return mix( vfrag, colour, min( 1.0, dist ) );\n"
+"}\n"
+"\n"
+"vec3 scene_calculate_light( int light_index, \n"
+"                            vec3 halfview, vec3 co, vec3 normal )\n"
+"{\n"
+"   vec4 light_colour = texelFetch( uLightsArray, light_index+0 );\n"
+"   vec4 light_co     = texelFetch( uLightsArray, light_index+1 );\n"
+"   vec4 light_dir    = texelFetch( uLightsArray, light_index+2 );\n"
+"\n"
+"   vec3 light_delta = light_co.xyz-co;\n"
+"   float dist2 = dot(light_delta,light_delta);\n"
+"\n"
+"   light_delta = normalize( light_delta );\n"
+"\n"
+"   float quadratic = dist2*100.0;\n"
+"   float attenuation  = 1.0/( 1.0 + quadratic );\n"
+"         attenuation *= max( dot( light_delta, normal ), 0.0 );\n"
+"\n"
+"   float falloff = max( 0.0, 1.0-(dist2*light_co.w) );\n"
+"\n"
+"   if( light_dir.w < 0.999999 ){\n"
+"      float spot_theta = max( 0.0, dot( light_delta, -light_dir.xyz ) );\n"
+"      falloff *= max( 0.0, (spot_theta - light_dir.w) / (1.0-light_dir.w) );\n"
+"   }\n"
+"\n"
+"   return light_colour.rgb * attenuation * falloff \n"
+"            * step( g_day_phase, light_colour.w );\n"
+"}\n"
+"\n"
+"vec3 scene_calculate_packed_light_patch( uint packed_index, \n"
+"                                         vec3 halfview, vec3 co, vec3 normal )\n"
+"{\n"
+"   uint light_count = packed_index & 0x3u;\n"
+"\n"
+"   vec3 l = vec3(0.0);\n"
+"\n"
+"   if( light_count >= 1u ){\n"
+"      int index_0 = int( ((packed_index >>  2u) & 0x3ffu) * 3u );\n"
+"      int index_1 = int( ((packed_index >> 12u) & 0x3ffu) * 3u );\n"
+"      int index_2 = int( ((packed_index >> 22u) & 0x3ffu) * 3u );\n"
+"\n"
+"      l += scene_calculate_light( index_0, halfview, co, normal );\n"
+"\n"
+"      if( light_count >= 2u ){\n"
+"         l += scene_calculate_light( index_1, halfview, co, normal );\n"
+"\n"
+"         if( light_count >= 3u ){\n"
+"            l += scene_calculate_light( index_2, halfview, co, normal );\n"
+"         }\n"
+"      }\n"
+"   }\n"
+"\n"
+"   return l;\n"
+"}\n"
+"\n"
+"vec3 world_compute_lighting( vec3 diffuse, vec3 normal, vec3 co,\n"
+"                             float light_mask )\n"
+"{\n"
+"   if( g_light_preview == 1 )\n"
+"      diffuse = vec3(0.75);\n"
+"\n"
+"   // Lighting\n"
+"   vec3 halfview = uCamera - co;\n"
+"   float fdist = length(halfview);\n"
+"   halfview /= fdist;\n"
+"\n"
+"   float world_shadow = newlight_compute_sun_shadow( \n"
+"               co, g_sun_dir.xyz * (1.0/(max(g_sun_dir.y,0.0)+0.2)) );\n"
+"\n"
+"   vec3 total_light = clearskies_lighting( \n"
+"                           normal, min( light_mask, world_shadow ), halfview );\n"
+"\n"
+"   vec3 cube_coord = (co - g_cube_min.xyz) * g_cube_inv_range.xyz;\n"
+"        cube_coord = floor( cube_coord );\n"
+"\n"
+"   if( g_debug_indices == 1 )\n"
+"   {\n"
+"      return rand33(cube_coord);\n"
+"   }\n"
+"\n"
+"   if( g_debug_complexity == 1 )\n"
+"   {\n"
+"      ivec3 coord = ivec3( cube_coord );\n"
+"      uvec4 index_sample = texelFetch( uLightsIndex, coord, 0 );\n"
+"\n"
+"      uint light_count = (index_sample.x & 0x3u) + (index_sample.y & 0x3u);\n"
+"      return vec3( float(light_count)*(1.0/6.0), 0.0, 0.5 );\n"
+"   }\n"
+"\n"
+"   // FIXME: this coord should absolutely must be clamped!\n"
+"   \n"
+"   ivec3 coord = ivec3( cube_coord );\n"
+"   uvec4 index_sample = texelFetch( uLightsIndex, coord, 0 );\n"
+"\n"
+"   total_light += \n"
+"      scene_calculate_packed_light_patch( index_sample.x,\n"
+"                                          halfview, co, normal ) \n"
+"                                          * light_mask;\n"
+"   total_light += \n"
+"      scene_calculate_packed_light_patch( index_sample.y,\n"
+"                                          halfview, co, normal )\n"
+"                                          * light_mask;\n"
+"\n"
+"   // Take a section of the sky function to give us a matching fog colour\n"
+"\n"
+"   vec3 fog_colour  = clearskies_ambient( -halfview );\n"
+"   float sun_theta  = dot( -halfview, g_sun_dir.xyz );\n"
+"   float sun_size   = max( 0.0, sun_theta * 0.5 + 0.5 );\n"
+"   float sun_shape  = sun_size * max(g_sun_dir.y,0.0) * 0.5;\n"
+"         \n"
+"   vec3 sun_colour  = mix( vec3(1.0), g_sunset_colour.rgb, g_sunset_phase*0.5 );\n"
+"        sun_colour *= sun_shape;\n"
+"\n"
+"   fog_colour += sun_colour;\n"
+"   return scene_apply_fog( diffuse * total_light, fog_colour, fdist );\n"
+"}\n"
+"\n"
+"#line      9        0 \n"
+"\n"
+"float sdLine( vec3 p, vec3 a, vec3 b )\n"
+"{\n"
+"  vec3 pa = p - a;\n"
+"  vec3 ba = b - a;\n"
+"\n"
+"  float h = clamp( dot(pa,ba)/dot(ba,ba), 0.0, 1.0 );\n"
+"  return length( pa - ba*h );\n"
+"}\n"
+"\n"
+"float compute_board_shadow()\n"
+"{\n"
+"   // player shadow\n"
+"   float dist_to_player = max( 0.0, sdLine( aWorldCo, g_board_0.xyz,\n"
+"                                                      g_board_1.xyz )-0.1 );\n"
+"   float player_shadow = max( 1.0-dist_to_player*2.7, 0.0 );\n"
+"   player_shadow *= player_shadow*player_shadow*player_shadow;\n"
+"\n"
+"   return 1.0 - player_shadow*0.8;\n"
+"}\n"
+"\n"
+"vec3 scene_compute_lighting( vec3 diffuse, vec3 normal, vec3 co )\n"
+"{\n"
+"   return world_compute_lighting( diffuse, normal, co, compute_board_shadow() );\n"
+"}\n"
+"\n"
+"#line      8        0 \n"
+"#line       1        3 \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      9        0 \n"
+"\n"
+"void main()\n"
+"{\n"
+"   compute_motion_vectors();\n"
+"\n"
+"   vec3 vfrag = vec3(0.5,0.5,0.5);\n"
+"   vec4 vsamplemain = texture( uTexMain, aUv );\n"
+"   vec3 qnorm = aNorm.xyz;\n"
+"\n"
+"   vfrag = vsamplemain.rgb;\n"
+"\n"
+"   if( g_light_preview == 1 )\n"
+"   {\n"
+"      vfrag = vec3(0.5);\n"
+"   }\n"
+"\n"
+"   vfrag = scene_compute_lighting( vfrag, qnorm, aWorldCo );\n"
+"   oColour = vec4( vfrag, 1.0 );\n"
+"}\n"
+""},
+};
+
+GLuint _uniform_scene_standard_uMdl;
+GLuint _uniform_scene_standard_uPv;
+GLuint _uniform_scene_standard_uPvmPrev;
+GLuint _uniform_scene_standard_uTexGarbage;
+GLuint _uniform_scene_standard_uTexMain;
+GLuint _uniform_scene_standard_uCamera;
+GLuint _uniform_scene_standard_uPlane;
+GLuint _uniform_scene_standard_g_world_depth;
+GLuint _uniform_scene_standard_uLightsArray;
+GLuint _uniform_scene_standard_uLightsIndex;
+#include "shaders/scene_standard_alphatest.h"
+struct vg_shader _shader_scene_standard_alphatest = {
+   .name = "scene_standard_alphatest",
+   .vs = 
+{
+.orig_file = "shaders/scene.vs",
+.static_src = 
+"layout (location=0) in vec3  a_co;\n"
+"layout (location=1) in vec4  a_norm;\n"
+"layout (location=2) in vec2  a_uv;\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      6        0 \n"
+"\n"
+"uniform mat4x3 uMdl;\n"
+"uniform mat4   uPv;\n"
+"uniform mat4   uPvmPrev;\n"
+"\n"
+"out vec2 aUv;\n"
+"out vec4 aNorm;\n"
+"out vec3 aCo;\n"
+"out vec3 aWorldCo;\n"
+"\n"
+"void main()\n"
+"{\n"
+"   vec3 world_pos0 = uMdl     * vec4( a_co, 1.0 );\n"
+"   vec4 vproj0     = uPv      * vec4( world_pos0, 1.0 );\n"
+"   vec4 vproj1     = uPvmPrev * vec4( a_co, 1.0 );\n"
+"\n"
+"   vs_motion_out( vproj0, vproj1 );\n"
+"\n"
+"   gl_Position = vproj0;\n"
+"\n"
+"   aUv = a_uv;\n"
+"   aNorm = vec4( mat3(uMdl) * a_norm.xyz, a_norm.w );\n"
+"   aCo = a_co;\n"
+"   aWorldCo = world_pos0;\n"
+"}\n"
+""},
+   .fs = 
+{
+.orig_file = "shaders/scene_standard_alphatest.fs",
+.static_src = 
+"uniform sampler2D uTexGarbage;\n"
+"uniform sampler2D uTexMain;\n"
+"uniform vec3 uCamera;\n"
+"uniform vec4 uPlane;\n"
+"\n"
+"#line       1        1 \n"
+"// :D\n"
+"const float CLEARSKIES_LIGHT_DOT_MIN = 0.0;\n"
+"\n"
+"#line      7        0 \n"
+"#line       1        2 \n"
+"// :D\n"
+"\n"
+"in vec2 aUv;\n"
+"in vec4 aNorm;\n"
+"in vec3 aCo;\n"
+"in vec3 aWorldCo;\n"
+"\n"
+"#line       1        1 \n"
+"layout (location = 0) out vec4 oColour;\n"
+"\n"
+"// OpenGL wiki: Recommends do not use vec3 because of drivers. hence the v4s...\n"
+"layout (std140) uniform ub_world_lighting\n"
+"{\n"
+"   vec4 g_cube_min;\n"
+"   vec4 g_cube_inv_range;\n"
+"\n"
+"   vec4 g_water_plane;\n"
+"   vec4 g_depth_bounds;\n"
+"\n"
+"   vec4 g_daysky_colour;\n"
+"   vec4 g_nightsky_colour;\n"
+"   vec4 g_sunset_colour;\n"
+"   vec4 g_ambient_colour;\n"
+"   vec4 g_sunset_ambient;\n"
+"   vec4 g_sun_colour;\n"
+"   vec4 g_sun_dir;\n"
+"   vec4 g_board_0;\n"
+"   vec4 g_board_1;\n"
+"\n"
+"   float g_water_fog;\n"
+"   float g_time;\n"
+"   float g_realtime;\n"
+"   float g_shadow_length;\n"
+"   float g_shadow_spread;\n"
+"\n"
+"   float g_time_of_day;\n"
+"   float g_day_phase;\n"
+"   float g_sunset_phase;\n"
+"\n"
+"   int g_light_preview;\n"
+"   int g_shadow_samples;\n"
+"\n"
+"   int g_debug_indices;\n"
+"   int g_debug_complexity;\n"
+"};\n"
+"\n"
+"uniform sampler2D g_world_depth;\n"
+"uniform samplerBuffer uLightsArray;\n"
+"uniform usampler3D uLightsIndex;\n"
+"\n"
+"#line       1        1 \n"
+"//const vec3  DAYSKY_COLOUR   = vec3( 0.37, 0.54, 0.97 );\n"
+"//const vec3  NIGHTSKY_COLOUR = vec3( 0.03, 0.05, 0.20 );\n"
+"//const vec3  SUNSET_COLOUR   = vec3( 1.00, 0.32, 0.01 );\n"
+"//const vec3  AMBIENT_COLOUR  = vec3( 0.13, 0.17, 0.35 );\n"
+"//const vec3  SUNSET_AMBIENT  = vec3( 0.25, 0.17, 0.51 );\n"
+"//const vec3  SUN_COLOUR      = vec3( 1.10, 0.89, 0.35 );\n"
+"\n"
+"const float SUN_ANGLE       = 0.0001;\n"
+"const float PI              = 3.14159265358979323846264;\n"
+"\n"
+"//struct world_info\n"
+"//{\n"
+"//   float time,\n"
+"//         time_of_day,\n"
+"//         day_phase,\n"
+"//         sunset_phase;\n"
+"//   \n"
+"//   vec3 sun_dir;\n"
+"//};\n"
+"\n"
+"vec3 rand33(vec3 p3)\n"
+"{\n"
+"      p3 = fract(p3 * vec3(.1031, .1030, .0973));\n"
+"   p3 += dot(p3, p3.yxz+33.33);\n"
+"   return fract((p3.xxy + p3.yxx)*p3.zyx);\n"
+"}\n"
+"\n"
+"float stars( vec3 rd, float rr, float size ){\n"
+"   vec3 co = rd * rr;\n"
+"\n"
+"   float a = atan(co.y, length(co.xz)) + 4.0 * PI;\n"
+"\n"
+"   float spaces = 1.0 / rr;\n"
+"   size = (rr * 0.0015) * fwidth(a) * 1000.0 * size;\n"
+"   a -= mod(a, spaces) - spaces * 0.5;\n"
+"\n"
+"   float count = floor(sqrt(pow(rr, 2.0) * (1.0 - pow(sin(a), 2.0))) * 3.0);\n"
+"   \n"
+"   float plane = atan(co.z, co.x) + 4.0 * PI;\n"
+"   plane = plane - mod(plane, PI / count);\n"
+"\n"
+"   vec2 delta = rand33(vec3(plane, a, 0.0)).xy;\n"
+"\n"
+"   float level = sin(a + spaces * (delta.y - 0.5) * (1.0 - size)) * rr;\n"
+"   float ydist = sqrt(rr * rr - level * level);\n"
+"   float angle = plane + (PI * (delta.x * (1.0-size) + size * 0.5) / count);\n"
+"   vec3 center = vec3(cos(angle) * ydist, level, sin(angle) * ydist);\n"
+"   float star = smoothstep(size, 0.0, distance(center, co));\n"
+"   return star;\n"
+"}\n"
+"\n"
+"float luminance( vec3 v )\n"
+"{\n"
+"   return dot( v, vec3(0.2126, 0.7152, 0.0722) );\n"
+"}\n"
+"\n"
+"vec3 clearskies_ambient( vec3 dir )\n"
+"{\n"
+"   float sun_azimuth  = g_sunset_phase * (dot( dir.xz, g_sun_dir.xz )*0.4+0.6);\n"
+"   float sky_gradient = dir.y;\n"
+"   \n"
+"   /* Blend phase colours */\n"
+"   vec3 ambient  = g_daysky_colour.rgb   * (g_day_phase-g_sunset_phase*0.1);\n"
+"        ambient += g_sunset_colour.rgb   * (1.0-dir.y*0.5)*sun_azimuth;\n"
+"        ambient += g_nightsky_colour.rgb * (1.0-g_day_phase);\n"
+"   \n"
+"   /* Add gradient */\n"
+"        ambient -= sky_gradient * luminance(ambient);\n"
+"        \n"
+"   return ambient;\n"
+"}\n"
+"\n"
+"vec3 clearskies_sky( vec3 ray_dir )\n"
+"{\n"
+"   ray_dir.y = abs( ray_dir.y );\n"
+"   vec3 sky_colour  = clearskies_ambient( ray_dir );\n"
+"   \n"
+"   /* Sun */\n"
+"   float sun_theta  = dot( ray_dir, g_sun_dir.xyz );\n"
+"   float sun_size   = max( 0.0, sun_theta * 0.5 + 0.5 + SUN_ANGLE );\n"
+"   float sun_shape  = pow( sun_size, 2000.0 );\n"
+"         sun_shape += sun_size * max(g_sun_dir.y,0.0) * 0.5;\n"
+"         \n"
+"   vec3 sun_colour  = mix( vec3(1.0), g_sunset_colour.rgb, g_sunset_phase*0.5 );\n"
+"        sun_colour *= sun_shape;\n"
+"\n"
+"   \n"
+"   float star = 0.0;\n"
+"   float star_blend = 10.0*max(0.0,(1.0-g_day_phase*2.0));\n"
+"\n"
+"   if( star_blend > 0.001 ){\n"
+"      for( float j = 1.0; j <= 4.1; j += 1.0 ){\n"
+"         float m = mix(0.6, 0.9, smoothstep(1.0, 2.0, j));\n"
+"         star += stars( ray_dir, 1.94 * pow( 1.64, j ), m ) * (1.0/pow(4.0, j));\n"
+"      }\n"
+"   }\n"
+"   \n"
+"   vec3 composite   = sky_colour + sun_colour + star*star_blend;\n"
+"   return composite;\n"
+"}\n"
+"\n"
+"vec3 clearskies_lighting( vec3 normal, float shadow, vec3 halfview )\n"
+"{\n"
+"   float fresnel = 1.0 - abs(dot(normal,halfview));\n"
+"\n"
+"   vec3  reflect_colour = mix( g_daysky_colour.rgb, g_sunset_colour.rgb, \n"
+"                               g_sunset_phase );\n"
+"\n"
+"   vec3  sky_reflection = 0.5 * fresnel * reflect_colour;\n"
+"   vec3  light_sun      = max( CLEARSKIES_LIGHT_DOT_MIN, \n"
+"                               dot(normal,g_sun_dir.xyz)*0.75+0.25\n"
+"                           ) * g_sun_colour.rgb * g_day_phase;\n"
+"\n"
+"   float scaled_shadow = max( shadow, 1.0 - max(g_sun_dir.y,0.0) );\n"
+"   vec3 ambient = mix( g_ambient_colour.rgb, g_sunset_ambient.rgb, \n"
+"                       g_sunset_phase );\n"
+"\n"
+"   return ambient + (light_sun + sky_reflection) * shadow;\n"
+"}\n"
+"\n"
+"#line     44        0 \n"
+"\n"
+"float world_depth_sample( vec3 pos )\n"
+"{\n"
+"   vec2 depth_coord = (pos.xz - g_depth_bounds.xy) * g_depth_bounds.zw; \n"
+"   return texture( g_world_depth, depth_coord ).r;\n"
+"}\n"
+"\n"
+"float world_water_depth( vec3 pos )\n"
+"{\n"
+"   float ref_depth = g_water_plane.y*g_water_plane.w;\n"
+"   return world_depth_sample( pos ) - ref_depth;\n"
+"}\n"
+"\n"
+"float shadow_sample( vec3 co ){\n"
+"   float height_sample = world_depth_sample( co );\n"
+"\n"
+"   float fdelta = height_sample - co.y;\n"
+"   return clamp( fdelta, 0.2, 0.4 )-0.2;\n"
+"}\n"
+"\n"
+"float newlight_compute_sun_shadow( vec3 co, vec3 dir ){\n"
+"   if( g_shadow_samples == 0 ){\n"
+"      return 1.0;\n"
+"   }\n"
+"\n"
+"   float fspread = g_shadow_spread;\n"
+"   float flength = g_shadow_length;\n"
+"\n"
+"   float famt = 0.0;\n"
+"   famt += shadow_sample(co+(dir+vec3(-0.56,0.55, 0.30)*fspread)*flength*0.1);\n"
+"   famt += shadow_sample(co+(dir+vec3( 0.80,0.68, 0.34)*fspread)*flength*0.2);\n"
+"   famt += shadow_sample(co+(dir+vec3( 0.78,0.07,-0.06)*fspread)*flength*0.3);\n"
+"   famt += shadow_sample(co+(dir+vec3(-0.59,0.07,-0.42)*fspread)*flength*0.4);\n"
+"\n"
+"   //famt+=shadow_sample(co+(dir+vec3(-0.790,-0.933,-0.875)*fspread)*flength*0.5);\n"
+"   //famt+=shadow_sample(co+(dir+vec3( 0.807,-0.690, 0.472)*fspread)*flength*0.6);\n"
+"   //famt+=shadow_sample(co+(dir+vec3( 0.522,-0.379, 0.350)*fspread)*flength*0.7);\n"
+"   //famt+=shadow_sample(co+(dir+vec3( 0.483, 0.201, 0.306)*fspread)*flength*0.8);\n"
+"\n"
+"   return 1.0 - famt;\n"
+"}\n"
+"\n"
+"float newlight_specular( vec3 wnormal, vec3 dir, vec3 halfview, float exponent )\n"
+"{\n"
+"   vec3 specdir = reflect( -dir, wnormal );\n"
+"   return pow(max(dot( halfview, specdir ), 0.0), exponent);\n"
+"}\n"
+"\n"
+"vec3 scene_apply_fog( vec3 vfrag, vec3 colour, float fdist ){\n"
+"   float dist = pow(fdist*0.0010,0.78);\n"
+"   return mix( vfrag, colour, min( 1.0, dist ) );\n"
+"}\n"
+"\n"
+"vec3 scene_calculate_light( int light_index, \n"
+"                            vec3 halfview, vec3 co, vec3 normal )\n"
+"{\n"
+"   vec4 light_colour = texelFetch( uLightsArray, light_index+0 );\n"
+"   vec4 light_co     = texelFetch( uLightsArray, light_index+1 );\n"
+"   vec4 light_dir    = texelFetch( uLightsArray, light_index+2 );\n"
+"\n"
+"   vec3 light_delta = light_co.xyz-co;\n"
+"   float dist2 = dot(light_delta,light_delta);\n"
+"\n"
+"   light_delta = normalize( light_delta );\n"
+"\n"
+"   float quadratic = dist2*100.0;\n"
+"   float attenuation  = 1.0/( 1.0 + quadratic );\n"
+"         attenuation *= max( dot( light_delta, normal ), 0.0 );\n"
+"\n"
+"   float falloff = max( 0.0, 1.0-(dist2*light_co.w) );\n"
+"\n"
+"   if( light_dir.w < 0.999999 ){\n"
+"      float spot_theta = max( 0.0, dot( light_delta, -light_dir.xyz ) );\n"
+"      falloff *= max( 0.0, (spot_theta - light_dir.w) / (1.0-light_dir.w) );\n"
+"   }\n"
+"\n"
+"   return light_colour.rgb * attenuation * falloff \n"
+"            * step( g_day_phase, light_colour.w );\n"
+"}\n"
+"\n"
+"vec3 scene_calculate_packed_light_patch( uint packed_index, \n"
+"                                         vec3 halfview, vec3 co, vec3 normal )\n"
+"{\n"
+"   uint light_count = packed_index & 0x3u;\n"
+"\n"
+"   vec3 l = vec3(0.0);\n"
+"\n"
+"   if( light_count >= 1u ){\n"
+"      int index_0 = int( ((packed_index >>  2u) & 0x3ffu) * 3u );\n"
+"      int index_1 = int( ((packed_index >> 12u) & 0x3ffu) * 3u );\n"
+"      int index_2 = int( ((packed_index >> 22u) & 0x3ffu) * 3u );\n"
+"\n"
+"      l += scene_calculate_light( index_0, halfview, co, normal );\n"
+"\n"
+"      if( light_count >= 2u ){\n"
+"         l += scene_calculate_light( index_1, halfview, co, normal );\n"
+"\n"
+"         if( light_count >= 3u ){\n"
+"            l += scene_calculate_light( index_2, halfview, co, normal );\n"
+"         }\n"
+"      }\n"
+"   }\n"
+"\n"
+"   return l;\n"
+"}\n"
+"\n"
+"vec3 world_compute_lighting( vec3 diffuse, vec3 normal, vec3 co,\n"
+"                             float light_mask )\n"
+"{\n"
+"   if( g_light_preview == 1 )\n"
+"      diffuse = vec3(0.75);\n"
+"\n"
+"   // Lighting\n"
+"   vec3 halfview = uCamera - co;\n"
+"   float fdist = length(halfview);\n"
+"   halfview /= fdist;\n"
+"\n"
+"   float world_shadow = newlight_compute_sun_shadow( \n"
+"               co, g_sun_dir.xyz * (1.0/(max(g_sun_dir.y,0.0)+0.2)) );\n"
+"\n"
+"   vec3 total_light = clearskies_lighting( \n"
+"                           normal, min( light_mask, world_shadow ), halfview );\n"
+"\n"
+"   vec3 cube_coord = (co - g_cube_min.xyz) * g_cube_inv_range.xyz;\n"
+"        cube_coord = floor( cube_coord );\n"
+"\n"
+"   if( g_debug_indices == 1 )\n"
+"   {\n"
+"      return rand33(cube_coord);\n"
+"   }\n"
+"\n"
+"   if( g_debug_complexity == 1 )\n"
+"   {\n"
+"      ivec3 coord = ivec3( cube_coord );\n"
+"      uvec4 index_sample = texelFetch( uLightsIndex, coord, 0 );\n"
+"\n"
+"      uint light_count = (index_sample.x & 0x3u) + (index_sample.y & 0x3u);\n"
+"      return vec3( float(light_count)*(1.0/6.0), 0.0, 0.5 );\n"
+"   }\n"
+"\n"
+"   // FIXME: this coord should absolutely must be clamped!\n"
+"   \n"
+"   ivec3 coord = ivec3( cube_coord );\n"
+"   uvec4 index_sample = texelFetch( uLightsIndex, coord, 0 );\n"
+"\n"
+"   total_light += \n"
+"      scene_calculate_packed_light_patch( index_sample.x,\n"
+"                                          halfview, co, normal ) \n"
+"                                          * light_mask;\n"
+"   total_light += \n"
+"      scene_calculate_packed_light_patch( index_sample.y,\n"
+"                                          halfview, co, normal )\n"
+"                                          * light_mask;\n"
+"\n"
+"   // Take a section of the sky function to give us a matching fog colour\n"
+"\n"
+"   vec3 fog_colour  = clearskies_ambient( -halfview );\n"
+"   float sun_theta  = dot( -halfview, g_sun_dir.xyz );\n"
+"   float sun_size   = max( 0.0, sun_theta * 0.5 + 0.5 );\n"
+"   float sun_shape  = sun_size * max(g_sun_dir.y,0.0) * 0.5;\n"
+"         \n"
+"   vec3 sun_colour  = mix( vec3(1.0), g_sunset_colour.rgb, g_sunset_phase*0.5 );\n"
+"        sun_colour *= sun_shape;\n"
+"\n"
+"   fog_colour += sun_colour;\n"
+"   return scene_apply_fog( diffuse * total_light, fog_colour, fdist );\n"
+"}\n"
+"\n"
+"#line      9        0 \n"
+"\n"
+"float sdLine( vec3 p, vec3 a, vec3 b )\n"
+"{\n"
+"  vec3 pa = p - a;\n"
+"  vec3 ba = b - a;\n"
+"\n"
+"  float h = clamp( dot(pa,ba)/dot(ba,ba), 0.0, 1.0 );\n"
+"  return length( pa - ba*h );\n"
+"}\n"
+"\n"
+"float compute_board_shadow()\n"
+"{\n"
+"   // player shadow\n"
+"   float dist_to_player = max( 0.0, sdLine( aWorldCo, g_board_0.xyz,\n"
+"                                                      g_board_1.xyz )-0.1 );\n"
+"   float player_shadow = max( 1.0-dist_to_player*2.7, 0.0 );\n"
+"   player_shadow *= player_shadow*player_shadow*player_shadow;\n"
+"\n"
+"   return 1.0 - player_shadow*0.8;\n"
+"}\n"
+"\n"
+"vec3 scene_compute_lighting( vec3 diffuse, vec3 normal, vec3 co )\n"
+"{\n"
+"   return world_compute_lighting( diffuse, normal, co, compute_board_shadow() );\n"
+"}\n"
+"\n"
+"#line      8        0 \n"
+"#line       1        3 \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      9        0 \n"
+"\n"
+"void main()\n"
+"{\n"
+"   compute_motion_vectors();\n"
+"\n"
+"   vec3 vfrag = vec3(0.5,0.5,0.5);\n"
+"   vec4 vsamplemain = texture( uTexMain, aUv );\n"
+"   vec3 qnorm = aNorm.xyz;\n"
+"\n"
+"   if( vsamplemain.a < 0.15 )\n"
+"     discard;\n"
+"\n"
+"   vfrag = vsamplemain.rgb;\n"
+"\n"
+"   if( g_light_preview == 1 )\n"
+"   {\n"
+"      vfrag = vec3(0.5);\n"
+"   }\n"
+"\n"
+"   vfrag = scene_compute_lighting( vfrag, qnorm, aWorldCo );\n"
+"   oColour = vec4(vfrag, 1.0);\n"
+"}\n"
+""},
+};
+
+GLuint _uniform_scene_standard_alphatest_uMdl;
+GLuint _uniform_scene_standard_alphatest_uPv;
+GLuint _uniform_scene_standard_alphatest_uPvmPrev;
+GLuint _uniform_scene_standard_alphatest_uTexGarbage;
+GLuint _uniform_scene_standard_alphatest_uTexMain;
+GLuint _uniform_scene_standard_alphatest_uCamera;
+GLuint _uniform_scene_standard_alphatest_uPlane;
+GLuint _uniform_scene_standard_alphatest_g_world_depth;
+GLuint _uniform_scene_standard_alphatest_uLightsArray;
+GLuint _uniform_scene_standard_alphatest_uLightsIndex;
+#include "shaders/scene_foliage.h"
+struct vg_shader _shader_scene_foliage = {
+   .name = "scene_foliage",
+   .vs = 
+{
+.orig_file = "shaders/scene_foliage.vs",
+.static_src = 
+"layout (location=0) in vec3  a_co;\n"
+"layout (location=1) in vec4  a_norm;\n"
+"layout (location=2) in vec2  a_uv;\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      6        0 \n"
+"\n"
+"uniform mat4x3 uMdl;\n"
+"uniform mat4   uPv;\n"
+"uniform mat4   uPvmPrev;\n"
+"uniform float uTime;\n"
+"\n"
+"out vec2 aUv;\n"
+"out vec4 aNorm;\n"
+"out vec3 aCo;\n"
+"out vec3 aWorldCo;\n"
+"\n"
+"void main(){\n"
+"   vec4 vsine = sin(vec4(uTime + a_co.x, uTime*0.7 + a_co.z,uTime,uTime*1.3));\n"
+"   vec3 co = a_co + vsine.xyz * a_norm.w * 0.5;\n"
+"   \n"
+"   vec3 world_pos0 = uMdl     * vec4( co, 1.0 );\n"
+"   vec4 vproj0     = uPv      * vec4( world_pos0, 1.0 );\n"
+"   vec4 vproj1     = uPvmPrev * vec4( co, 1.0 );\n"
+"\n"
+"   vs_motion_out( vproj0, vproj1 );\n"
+"\n"
+"   gl_Position = vproj0;\n"
+"\n"
+"   aUv = a_uv;\n"
+"   aNorm = vec4( mat3(uMdl) * a_norm.xyz, a_norm.w );\n"
+"   aCo = a_co;\n"
+"   aWorldCo = world_pos0;\n"
+"}\n"
+""},
+   .fs = 
+{
+.orig_file = "shaders/scene_foliage.fs",
+.static_src = 
+"uniform sampler2D uTexGarbage;\n"
+"uniform sampler2D uTexMain;\n"
+"uniform vec3 uCamera;\n"
+"uniform vec4 uPlane;\n"
+"\n"
+"const float CLEARSKIES_LIGHT_DOT_MIN = 0.4;\n"
+"#line       1        1 \n"
+"// :D\n"
+"\n"
+"in vec2 aUv;\n"
+"in vec4 aNorm;\n"
+"in vec3 aCo;\n"
+"in vec3 aWorldCo;\n"
+"\n"
+"#line       1        1 \n"
+"layout (location = 0) out vec4 oColour;\n"
+"\n"
+"// OpenGL wiki: Recommends do not use vec3 because of drivers. hence the v4s...\n"
+"layout (std140) uniform ub_world_lighting\n"
+"{\n"
+"   vec4 g_cube_min;\n"
+"   vec4 g_cube_inv_range;\n"
+"\n"
+"   vec4 g_water_plane;\n"
+"   vec4 g_depth_bounds;\n"
+"\n"
+"   vec4 g_daysky_colour;\n"
+"   vec4 g_nightsky_colour;\n"
+"   vec4 g_sunset_colour;\n"
+"   vec4 g_ambient_colour;\n"
+"   vec4 g_sunset_ambient;\n"
+"   vec4 g_sun_colour;\n"
+"   vec4 g_sun_dir;\n"
+"   vec4 g_board_0;\n"
+"   vec4 g_board_1;\n"
+"\n"
+"   float g_water_fog;\n"
+"   float g_time;\n"
+"   float g_realtime;\n"
+"   float g_shadow_length;\n"
+"   float g_shadow_spread;\n"
+"\n"
+"   float g_time_of_day;\n"
+"   float g_day_phase;\n"
+"   float g_sunset_phase;\n"
+"\n"
+"   int g_light_preview;\n"
+"   int g_shadow_samples;\n"
+"\n"
+"   int g_debug_indices;\n"
+"   int g_debug_complexity;\n"
+"};\n"
+"\n"
+"uniform sampler2D g_world_depth;\n"
+"uniform samplerBuffer uLightsArray;\n"
+"uniform usampler3D uLightsIndex;\n"
+"\n"
+"#line       1        1 \n"
+"//const vec3  DAYSKY_COLOUR   = vec3( 0.37, 0.54, 0.97 );\n"
+"//const vec3  NIGHTSKY_COLOUR = vec3( 0.03, 0.05, 0.20 );\n"
+"//const vec3  SUNSET_COLOUR   = vec3( 1.00, 0.32, 0.01 );\n"
+"//const vec3  AMBIENT_COLOUR  = vec3( 0.13, 0.17, 0.35 );\n"
+"//const vec3  SUNSET_AMBIENT  = vec3( 0.25, 0.17, 0.51 );\n"
+"//const vec3  SUN_COLOUR      = vec3( 1.10, 0.89, 0.35 );\n"
+"\n"
+"const float SUN_ANGLE       = 0.0001;\n"
+"const float PI              = 3.14159265358979323846264;\n"
+"\n"
+"//struct world_info\n"
+"//{\n"
+"//   float time,\n"
+"//         time_of_day,\n"
+"//         day_phase,\n"
+"//         sunset_phase;\n"
+"//   \n"
+"//   vec3 sun_dir;\n"
+"//};\n"
+"\n"
+"vec3 rand33(vec3 p3)\n"
+"{\n"
+"      p3 = fract(p3 * vec3(.1031, .1030, .0973));\n"
+"   p3 += dot(p3, p3.yxz+33.33);\n"
+"   return fract((p3.xxy + p3.yxx)*p3.zyx);\n"
+"}\n"
+"\n"
+"float stars( vec3 rd, float rr, float size ){\n"
+"   vec3 co = rd * rr;\n"
+"\n"
+"   float a = atan(co.y, length(co.xz)) + 4.0 * PI;\n"
+"\n"
+"   float spaces = 1.0 / rr;\n"
+"   size = (rr * 0.0015) * fwidth(a) * 1000.0 * size;\n"
+"   a -= mod(a, spaces) - spaces * 0.5;\n"
+"\n"
+"   float count = floor(sqrt(pow(rr, 2.0) * (1.0 - pow(sin(a), 2.0))) * 3.0);\n"
+"   \n"
+"   float plane = atan(co.z, co.x) + 4.0 * PI;\n"
+"   plane = plane - mod(plane, PI / count);\n"
+"\n"
+"   vec2 delta = rand33(vec3(plane, a, 0.0)).xy;\n"
+"\n"
+"   float level = sin(a + spaces * (delta.y - 0.5) * (1.0 - size)) * rr;\n"
+"   float ydist = sqrt(rr * rr - level * level);\n"
+"   float angle = plane + (PI * (delta.x * (1.0-size) + size * 0.5) / count);\n"
+"   vec3 center = vec3(cos(angle) * ydist, level, sin(angle) * ydist);\n"
+"   float star = smoothstep(size, 0.0, distance(center, co));\n"
+"   return star;\n"
+"}\n"
+"\n"
+"float luminance( vec3 v )\n"
+"{\n"
+"   return dot( v, vec3(0.2126, 0.7152, 0.0722) );\n"
+"}\n"
+"\n"
+"vec3 clearskies_ambient( vec3 dir )\n"
+"{\n"
+"   float sun_azimuth  = g_sunset_phase * (dot( dir.xz, g_sun_dir.xz )*0.4+0.6);\n"
+"   float sky_gradient = dir.y;\n"
+"   \n"
+"   /* Blend phase colours */\n"
+"   vec3 ambient  = g_daysky_colour.rgb   * (g_day_phase-g_sunset_phase*0.1);\n"
+"        ambient += g_sunset_colour.rgb   * (1.0-dir.y*0.5)*sun_azimuth;\n"
+"        ambient += g_nightsky_colour.rgb * (1.0-g_day_phase);\n"
+"   \n"
+"   /* Add gradient */\n"
+"        ambient -= sky_gradient * luminance(ambient);\n"
+"        \n"
+"   return ambient;\n"
+"}\n"
+"\n"
+"vec3 clearskies_sky( vec3 ray_dir )\n"
+"{\n"
+"   ray_dir.y = abs( ray_dir.y );\n"
+"   vec3 sky_colour  = clearskies_ambient( ray_dir );\n"
+"   \n"
+"   /* Sun */\n"
+"   float sun_theta  = dot( ray_dir, g_sun_dir.xyz );\n"
+"   float sun_size   = max( 0.0, sun_theta * 0.5 + 0.5 + SUN_ANGLE );\n"
+"   float sun_shape  = pow( sun_size, 2000.0 );\n"
+"         sun_shape += sun_size * max(g_sun_dir.y,0.0) * 0.5;\n"
+"         \n"
+"   vec3 sun_colour  = mix( vec3(1.0), g_sunset_colour.rgb, g_sunset_phase*0.5 );\n"
+"        sun_colour *= sun_shape;\n"
+"\n"
+"   \n"
+"   float star = 0.0;\n"
+"   float star_blend = 10.0*max(0.0,(1.0-g_day_phase*2.0));\n"
+"\n"
+"   if( star_blend > 0.001 ){\n"
+"      for( float j = 1.0; j <= 4.1; j += 1.0 ){\n"
+"         float m = mix(0.6, 0.9, smoothstep(1.0, 2.0, j));\n"
+"         star += stars( ray_dir, 1.94 * pow( 1.64, j ), m ) * (1.0/pow(4.0, j));\n"
+"      }\n"
+"   }\n"
+"   \n"
+"   vec3 composite   = sky_colour + sun_colour + star*star_blend;\n"
+"   return composite;\n"
+"}\n"
+"\n"
+"vec3 clearskies_lighting( vec3 normal, float shadow, vec3 halfview )\n"
+"{\n"
+"   float fresnel = 1.0 - abs(dot(normal,halfview));\n"
+"\n"
+"   vec3  reflect_colour = mix( g_daysky_colour.rgb, g_sunset_colour.rgb, \n"
+"                               g_sunset_phase );\n"
+"\n"
+"   vec3  sky_reflection = 0.5 * fresnel * reflect_colour;\n"
+"   vec3  light_sun      = max( CLEARSKIES_LIGHT_DOT_MIN, \n"
+"                               dot(normal,g_sun_dir.xyz)*0.75+0.25\n"
+"                           ) * g_sun_colour.rgb * g_day_phase;\n"
+"\n"
+"   float scaled_shadow = max( shadow, 1.0 - max(g_sun_dir.y,0.0) );\n"
+"   vec3 ambient = mix( g_ambient_colour.rgb, g_sunset_ambient.rgb, \n"
+"                       g_sunset_phase );\n"
+"\n"
+"   return ambient + (light_sun + sky_reflection) * shadow;\n"
+"}\n"
+"\n"
+"#line     44        0 \n"
+"\n"
+"float world_depth_sample( vec3 pos )\n"
+"{\n"
+"   vec2 depth_coord = (pos.xz - g_depth_bounds.xy) * g_depth_bounds.zw; \n"
+"   return texture( g_world_depth, depth_coord ).r;\n"
+"}\n"
+"\n"
+"float world_water_depth( vec3 pos )\n"
+"{\n"
+"   float ref_depth = g_water_plane.y*g_water_plane.w;\n"
+"   return world_depth_sample( pos ) - ref_depth;\n"
+"}\n"
+"\n"
+"float shadow_sample( vec3 co ){\n"
+"   float height_sample = world_depth_sample( co );\n"
+"\n"
+"   float fdelta = height_sample - co.y;\n"
+"   return clamp( fdelta, 0.2, 0.4 )-0.2;\n"
+"}\n"
+"\n"
+"float newlight_compute_sun_shadow( vec3 co, vec3 dir ){\n"
+"   if( g_shadow_samples == 0 ){\n"
+"      return 1.0;\n"
+"   }\n"
+"\n"
+"   float fspread = g_shadow_spread;\n"
+"   float flength = g_shadow_length;\n"
+"\n"
+"   float famt = 0.0;\n"
+"   famt += shadow_sample(co+(dir+vec3(-0.56,0.55, 0.30)*fspread)*flength*0.1);\n"
+"   famt += shadow_sample(co+(dir+vec3( 0.80,0.68, 0.34)*fspread)*flength*0.2);\n"
+"   famt += shadow_sample(co+(dir+vec3( 0.78,0.07,-0.06)*fspread)*flength*0.3);\n"
+"   famt += shadow_sample(co+(dir+vec3(-0.59,0.07,-0.42)*fspread)*flength*0.4);\n"
+"\n"
+"   //famt+=shadow_sample(co+(dir+vec3(-0.790,-0.933,-0.875)*fspread)*flength*0.5);\n"
+"   //famt+=shadow_sample(co+(dir+vec3( 0.807,-0.690, 0.472)*fspread)*flength*0.6);\n"
+"   //famt+=shadow_sample(co+(dir+vec3( 0.522,-0.379, 0.350)*fspread)*flength*0.7);\n"
+"   //famt+=shadow_sample(co+(dir+vec3( 0.483, 0.201, 0.306)*fspread)*flength*0.8);\n"
+"\n"
+"   return 1.0 - famt;\n"
+"}\n"
+"\n"
+"float newlight_specular( vec3 wnormal, vec3 dir, vec3 halfview, float exponent )\n"
+"{\n"
+"   vec3 specdir = reflect( -dir, wnormal );\n"
+"   return pow(max(dot( halfview, specdir ), 0.0), exponent);\n"
+"}\n"
+"\n"
+"vec3 scene_apply_fog( vec3 vfrag, vec3 colour, float fdist ){\n"
+"   float dist = pow(fdist*0.0010,0.78);\n"
+"   return mix( vfrag, colour, min( 1.0, dist ) );\n"
+"}\n"
+"\n"
+"vec3 scene_calculate_light( int light_index, \n"
+"                            vec3 halfview, vec3 co, vec3 normal )\n"
+"{\n"
+"   vec4 light_colour = texelFetch( uLightsArray, light_index+0 );\n"
+"   vec4 light_co     = texelFetch( uLightsArray, light_index+1 );\n"
+"   vec4 light_dir    = texelFetch( uLightsArray, light_index+2 );\n"
+"\n"
+"   vec3 light_delta = light_co.xyz-co;\n"
+"   float dist2 = dot(light_delta,light_delta);\n"
+"\n"
+"   light_delta = normalize( light_delta );\n"
+"\n"
+"   float quadratic = dist2*100.0;\n"
+"   float attenuation  = 1.0/( 1.0 + quadratic );\n"
+"         attenuation *= max( dot( light_delta, normal ), 0.0 );\n"
+"\n"
+"   float falloff = max( 0.0, 1.0-(dist2*light_co.w) );\n"
+"\n"
+"   if( light_dir.w < 0.999999 ){\n"
+"      float spot_theta = max( 0.0, dot( light_delta, -light_dir.xyz ) );\n"
+"      falloff *= max( 0.0, (spot_theta - light_dir.w) / (1.0-light_dir.w) );\n"
+"   }\n"
+"\n"
+"   return light_colour.rgb * attenuation * falloff \n"
+"            * step( g_day_phase, light_colour.w );\n"
+"}\n"
+"\n"
+"vec3 scene_calculate_packed_light_patch( uint packed_index, \n"
+"                                         vec3 halfview, vec3 co, vec3 normal )\n"
+"{\n"
+"   uint light_count = packed_index & 0x3u;\n"
+"\n"
+"   vec3 l = vec3(0.0);\n"
+"\n"
+"   if( light_count >= 1u ){\n"
+"      int index_0 = int( ((packed_index >>  2u) & 0x3ffu) * 3u );\n"
+"      int index_1 = int( ((packed_index >> 12u) & 0x3ffu) * 3u );\n"
+"      int index_2 = int( ((packed_index >> 22u) & 0x3ffu) * 3u );\n"
+"\n"
+"      l += scene_calculate_light( index_0, halfview, co, normal );\n"
+"\n"
+"      if( light_count >= 2u ){\n"
+"         l += scene_calculate_light( index_1, halfview, co, normal );\n"
+"\n"
+"         if( light_count >= 3u ){\n"
+"            l += scene_calculate_light( index_2, halfview, co, normal );\n"
+"         }\n"
+"      }\n"
+"   }\n"
+"\n"
+"   return l;\n"
+"}\n"
+"\n"
+"vec3 world_compute_lighting( vec3 diffuse, vec3 normal, vec3 co,\n"
+"                             float light_mask )\n"
+"{\n"
+"   if( g_light_preview == 1 )\n"
+"      diffuse = vec3(0.75);\n"
+"\n"
+"   // Lighting\n"
+"   vec3 halfview = uCamera - co;\n"
+"   float fdist = length(halfview);\n"
+"   halfview /= fdist;\n"
+"\n"
+"   float world_shadow = newlight_compute_sun_shadow( \n"
+"               co, g_sun_dir.xyz * (1.0/(max(g_sun_dir.y,0.0)+0.2)) );\n"
+"\n"
+"   vec3 total_light = clearskies_lighting( \n"
+"                           normal, min( light_mask, world_shadow ), halfview );\n"
+"\n"
+"   vec3 cube_coord = (co - g_cube_min.xyz) * g_cube_inv_range.xyz;\n"
+"        cube_coord = floor( cube_coord );\n"
+"\n"
+"   if( g_debug_indices == 1 )\n"
+"   {\n"
+"      return rand33(cube_coord);\n"
+"   }\n"
+"\n"
+"   if( g_debug_complexity == 1 )\n"
+"   {\n"
+"      ivec3 coord = ivec3( cube_coord );\n"
+"      uvec4 index_sample = texelFetch( uLightsIndex, coord, 0 );\n"
+"\n"
+"      uint light_count = (index_sample.x & 0x3u) + (index_sample.y & 0x3u);\n"
+"      return vec3( float(light_count)*(1.0/6.0), 0.0, 0.5 );\n"
+"   }\n"
+"\n"
+"   // FIXME: this coord should absolutely must be clamped!\n"
+"   \n"
+"   ivec3 coord = ivec3( cube_coord );\n"
+"   uvec4 index_sample = texelFetch( uLightsIndex, coord, 0 );\n"
+"\n"
+"   total_light += \n"
+"      scene_calculate_packed_light_patch( index_sample.x,\n"
+"                                          halfview, co, normal ) \n"
+"                                          * light_mask;\n"
+"   total_light += \n"
+"      scene_calculate_packed_light_patch( index_sample.y,\n"
+"                                          halfview, co, normal )\n"
+"                                          * light_mask;\n"
+"\n"
+"   // Take a section of the sky function to give us a matching fog colour\n"
+"\n"
+"   vec3 fog_colour  = clearskies_ambient( -halfview );\n"
+"   float sun_theta  = dot( -halfview, g_sun_dir.xyz );\n"
+"   float sun_size   = max( 0.0, sun_theta * 0.5 + 0.5 );\n"
+"   float sun_shape  = sun_size * max(g_sun_dir.y,0.0) * 0.5;\n"
+"         \n"
+"   vec3 sun_colour  = mix( vec3(1.0), g_sunset_colour.rgb, g_sunset_phase*0.5 );\n"
+"        sun_colour *= sun_shape;\n"
+"\n"
+"   fog_colour += sun_colour;\n"
+"   return scene_apply_fog( diffuse * total_light, fog_colour, fdist );\n"
+"}\n"
+"\n"
+"#line      9        0 \n"
+"\n"
+"float sdLine( vec3 p, vec3 a, vec3 b )\n"
+"{\n"
+"  vec3 pa = p - a;\n"
+"  vec3 ba = b - a;\n"
+"\n"
+"  float h = clamp( dot(pa,ba)/dot(ba,ba), 0.0, 1.0 );\n"
+"  return length( pa - ba*h );\n"
+"}\n"
+"\n"
+"float compute_board_shadow()\n"
+"{\n"
+"   // player shadow\n"
+"   float dist_to_player = max( 0.0, sdLine( aWorldCo, g_board_0.xyz,\n"
+"                                                      g_board_1.xyz )-0.1 );\n"
+"   float player_shadow = max( 1.0-dist_to_player*2.7, 0.0 );\n"
+"   player_shadow *= player_shadow*player_shadow*player_shadow;\n"
+"\n"
+"   return 1.0 - player_shadow*0.8;\n"
+"}\n"
+"\n"
+"vec3 scene_compute_lighting( vec3 diffuse, vec3 normal, vec3 co )\n"
+"{\n"
+"   return world_compute_lighting( diffuse, normal, co, compute_board_shadow() );\n"
+"}\n"
+"\n"
+"#line      8        0 \n"
+"#line       1        2 \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      9        0 \n"
+"\n"
+"void main(){\n"
+"   compute_motion_vectors();\n"
+"\n"
+"   vec3 vfrag = vec3(0.5,0.5,0.5);\n"
+"   vec4 vsamplemain = texture( uTexMain, aUv );\n"
+"   vec3 qnorm = aNorm.xyz;\n"
+"\n"
+"   if( vsamplemain.a < 0.15 )\n"
+"     discard;\n"
+"\n"
+"   vfrag = vsamplemain.rgb;\n"
+"\n"
+"   if( g_light_preview == 1 ){\n"
+"      vfrag = vec3(0.5);\n"
+"   }\n"
+"\n"
+"   vfrag = scene_compute_lighting( vfrag, qnorm, aWorldCo );\n"
+"   oColour = vec4(vfrag, 1.0);\n"
+"}\n"
+""},
+};
+
+GLuint _uniform_scene_foliage_uMdl;
+GLuint _uniform_scene_foliage_uPv;
+GLuint _uniform_scene_foliage_uPvmPrev;
+GLuint _uniform_scene_foliage_uTime;
+GLuint _uniform_scene_foliage_uTexGarbage;
+GLuint _uniform_scene_foliage_uTexMain;
+GLuint _uniform_scene_foliage_uCamera;
+GLuint _uniform_scene_foliage_uPlane;
+GLuint _uniform_scene_foliage_g_world_depth;
+GLuint _uniform_scene_foliage_uLightsArray;
+GLuint _uniform_scene_foliage_uLightsIndex;
+#include "shaders/scene_override.h"
+struct vg_shader _shader_scene_override = {
+   .name = "scene_override",
+   .vs = 
+{
+.orig_file = "shaders/scene_override.vs",
+.static_src = 
+"layout (location=0) in vec3  a_co;\n"
+"layout (location=1) in vec4  a_norm;\n"
+"layout (location=2) in vec2  a_uv;\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      6        0 \n"
+"\n"
+"uniform mat4x3 uMdl;\n"
+"uniform mat4   uPv;\n"
+"uniform mat4   uPvmPrev;\n"
+"uniform mat3   uNormalMtx;\n"
+"\n"
+"out vec2 aUv;\n"
+"out vec4 aNorm;\n"
+"out vec3 aCo;\n"
+"out vec3 aWorldCo;\n"
+"\n"
+"void main()\n"
+"{\n"
+"   vec3 world_pos0 = uMdl     * vec4( a_co, 1.0 );\n"
+"   vec4 vproj0     = uPv      * vec4( world_pos0, 1.0 );\n"
+"   vec4 vproj1     = uPvmPrev * vec4( a_co, 1.0 );\n"
+"\n"
+"   vs_motion_out( vproj0, vproj1 );\n"
+"\n"
+"   gl_Position = vproj0;\n"
+"\n"
+"   aUv = a_uv;\n"
+"   aNorm = vec4( uNormalMtx * a_norm.xyz, a_norm.w );\n"
+"   aCo = a_co;\n"
+"   aWorldCo = world_pos0;\n"
+"}\n"
+""},
+   .fs = 
+{
+.orig_file = "shaders/scene_override.fs",
+.static_src = 
+"uniform sampler2D uTexGarbage;\n"
+"uniform sampler2D uTexMain;\n"
+"uniform vec3 uCamera;\n"
+"uniform vec4 uPlane;\n"
+"\n"
+"uniform vec4 uPlayerPos; /* w: distance to uSpawnPos */\n"
+"uniform vec4 uSpawnPos;  /* w: inverse distance to uPlayerPos */\n"
+"uniform bool uAlphatest;\n"
+"uniform vec4 uMapInfo; /* x: min, y: max, z: iso line amount */\n"
+"\n"
+"#line       1        1 \n"
+"// :D\n"
+"const float CLEARSKIES_LIGHT_DOT_MIN = 0.0;\n"
+"\n"
+"#line     12        0 \n"
+"#line       1        2 \n"
+"// :D\n"
+"\n"
+"in vec2 aUv;\n"
+"in vec4 aNorm;\n"
+"in vec3 aCo;\n"
+"in vec3 aWorldCo;\n"
+"\n"
+"#line       1        1 \n"
+"layout (location = 0) out vec4 oColour;\n"
+"\n"
+"// OpenGL wiki: Recommends do not use vec3 because of drivers. hence the v4s...\n"
+"layout (std140) uniform ub_world_lighting\n"
+"{\n"
+"   vec4 g_cube_min;\n"
+"   vec4 g_cube_inv_range;\n"
+"\n"
+"   vec4 g_water_plane;\n"
+"   vec4 g_depth_bounds;\n"
+"\n"
+"   vec4 g_daysky_colour;\n"
+"   vec4 g_nightsky_colour;\n"
+"   vec4 g_sunset_colour;\n"
+"   vec4 g_ambient_colour;\n"
+"   vec4 g_sunset_ambient;\n"
+"   vec4 g_sun_colour;\n"
+"   vec4 g_sun_dir;\n"
+"   vec4 g_board_0;\n"
+"   vec4 g_board_1;\n"
+"\n"
+"   float g_water_fog;\n"
+"   float g_time;\n"
+"   float g_realtime;\n"
+"   float g_shadow_length;\n"
+"   float g_shadow_spread;\n"
+"\n"
+"   float g_time_of_day;\n"
+"   float g_day_phase;\n"
+"   float g_sunset_phase;\n"
+"\n"
+"   int g_light_preview;\n"
+"   int g_shadow_samples;\n"
+"\n"
+"   int g_debug_indices;\n"
+"   int g_debug_complexity;\n"
+"};\n"
+"\n"
+"uniform sampler2D g_world_depth;\n"
+"uniform samplerBuffer uLightsArray;\n"
+"uniform usampler3D uLightsIndex;\n"
+"\n"
+"#line       1        1 \n"
+"//const vec3  DAYSKY_COLOUR   = vec3( 0.37, 0.54, 0.97 );\n"
+"//const vec3  NIGHTSKY_COLOUR = vec3( 0.03, 0.05, 0.20 );\n"
+"//const vec3  SUNSET_COLOUR   = vec3( 1.00, 0.32, 0.01 );\n"
+"//const vec3  AMBIENT_COLOUR  = vec3( 0.13, 0.17, 0.35 );\n"
+"//const vec3  SUNSET_AMBIENT  = vec3( 0.25, 0.17, 0.51 );\n"
+"//const vec3  SUN_COLOUR      = vec3( 1.10, 0.89, 0.35 );\n"
+"\n"
+"const float SUN_ANGLE       = 0.0001;\n"
+"const float PI              = 3.14159265358979323846264;\n"
+"\n"
+"//struct world_info\n"
+"//{\n"
+"//   float time,\n"
+"//         time_of_day,\n"
+"//         day_phase,\n"
+"//         sunset_phase;\n"
+"//   \n"
+"//   vec3 sun_dir;\n"
+"//};\n"
+"\n"
+"vec3 rand33(vec3 p3)\n"
+"{\n"
+"      p3 = fract(p3 * vec3(.1031, .1030, .0973));\n"
+"   p3 += dot(p3, p3.yxz+33.33);\n"
+"   return fract((p3.xxy + p3.yxx)*p3.zyx);\n"
+"}\n"
+"\n"
+"float stars( vec3 rd, float rr, float size ){\n"
+"   vec3 co = rd * rr;\n"
+"\n"
+"   float a = atan(co.y, length(co.xz)) + 4.0 * PI;\n"
+"\n"
+"   float spaces = 1.0 / rr;\n"
+"   size = (rr * 0.0015) * fwidth(a) * 1000.0 * size;\n"
+"   a -= mod(a, spaces) - spaces * 0.5;\n"
+"\n"
+"   float count = floor(sqrt(pow(rr, 2.0) * (1.0 - pow(sin(a), 2.0))) * 3.0);\n"
+"   \n"
+"   float plane = atan(co.z, co.x) + 4.0 * PI;\n"
+"   plane = plane - mod(plane, PI / count);\n"
+"\n"
+"   vec2 delta = rand33(vec3(plane, a, 0.0)).xy;\n"
+"\n"
+"   float level = sin(a + spaces * (delta.y - 0.5) * (1.0 - size)) * rr;\n"
+"   float ydist = sqrt(rr * rr - level * level);\n"
+"   float angle = plane + (PI * (delta.x * (1.0-size) + size * 0.5) / count);\n"
+"   vec3 center = vec3(cos(angle) * ydist, level, sin(angle) * ydist);\n"
+"   float star = smoothstep(size, 0.0, distance(center, co));\n"
+"   return star;\n"
+"}\n"
+"\n"
+"float luminance( vec3 v )\n"
+"{\n"
+"   return dot( v, vec3(0.2126, 0.7152, 0.0722) );\n"
+"}\n"
+"\n"
+"vec3 clearskies_ambient( vec3 dir )\n"
+"{\n"
+"   float sun_azimuth  = g_sunset_phase * (dot( dir.xz, g_sun_dir.xz )*0.4+0.6);\n"
+"   float sky_gradient = dir.y;\n"
+"   \n"
+"   /* Blend phase colours */\n"
+"   vec3 ambient  = g_daysky_colour.rgb   * (g_day_phase-g_sunset_phase*0.1);\n"
+"        ambient += g_sunset_colour.rgb   * (1.0-dir.y*0.5)*sun_azimuth;\n"
+"        ambient += g_nightsky_colour.rgb * (1.0-g_day_phase);\n"
+"   \n"
+"   /* Add gradient */\n"
+"        ambient -= sky_gradient * luminance(ambient);\n"
+"        \n"
+"   return ambient;\n"
+"}\n"
+"\n"
+"vec3 clearskies_sky( vec3 ray_dir )\n"
+"{\n"
+"   ray_dir.y = abs( ray_dir.y );\n"
+"   vec3 sky_colour  = clearskies_ambient( ray_dir );\n"
+"   \n"
+"   /* Sun */\n"
+"   float sun_theta  = dot( ray_dir, g_sun_dir.xyz );\n"
+"   float sun_size   = max( 0.0, sun_theta * 0.5 + 0.5 + SUN_ANGLE );\n"
+"   float sun_shape  = pow( sun_size, 2000.0 );\n"
+"         sun_shape += sun_size * max(g_sun_dir.y,0.0) * 0.5;\n"
+"         \n"
+"   vec3 sun_colour  = mix( vec3(1.0), g_sunset_colour.rgb, g_sunset_phase*0.5 );\n"
+"        sun_colour *= sun_shape;\n"
+"\n"
+"   \n"
+"   float star = 0.0;\n"
+"   float star_blend = 10.0*max(0.0,(1.0-g_day_phase*2.0));\n"
+"\n"
+"   if( star_blend > 0.001 ){\n"
+"      for( float j = 1.0; j <= 4.1; j += 1.0 ){\n"
+"         float m = mix(0.6, 0.9, smoothstep(1.0, 2.0, j));\n"
+"         star += stars( ray_dir, 1.94 * pow( 1.64, j ), m ) * (1.0/pow(4.0, j));\n"
+"      }\n"
+"   }\n"
+"   \n"
+"   vec3 composite   = sky_colour + sun_colour + star*star_blend;\n"
+"   return composite;\n"
+"}\n"
+"\n"
+"vec3 clearskies_lighting( vec3 normal, float shadow, vec3 halfview )\n"
+"{\n"
+"   float fresnel = 1.0 - abs(dot(normal,halfview));\n"
+"\n"
+"   vec3  reflect_colour = mix( g_daysky_colour.rgb, g_sunset_colour.rgb, \n"
+"                               g_sunset_phase );\n"
+"\n"
+"   vec3  sky_reflection = 0.5 * fresnel * reflect_colour;\n"
+"   vec3  light_sun      = max( CLEARSKIES_LIGHT_DOT_MIN, \n"
+"                               dot(normal,g_sun_dir.xyz)*0.75+0.25\n"
+"                           ) * g_sun_colour.rgb * g_day_phase;\n"
+"\n"
+"   float scaled_shadow = max( shadow, 1.0 - max(g_sun_dir.y,0.0) );\n"
+"   vec3 ambient = mix( g_ambient_colour.rgb, g_sunset_ambient.rgb, \n"
+"                       g_sunset_phase );\n"
+"\n"
+"   return ambient + (light_sun + sky_reflection) * shadow;\n"
+"}\n"
+"\n"
+"#line     44        0 \n"
+"\n"
+"float world_depth_sample( vec3 pos )\n"
+"{\n"
+"   vec2 depth_coord = (pos.xz - g_depth_bounds.xy) * g_depth_bounds.zw; \n"
+"   return texture( g_world_depth, depth_coord ).r;\n"
+"}\n"
+"\n"
+"float world_water_depth( vec3 pos )\n"
+"{\n"
+"   float ref_depth = g_water_plane.y*g_water_plane.w;\n"
+"   return world_depth_sample( pos ) - ref_depth;\n"
+"}\n"
+"\n"
+"float shadow_sample( vec3 co ){\n"
+"   float height_sample = world_depth_sample( co );\n"
+"\n"
+"   float fdelta = height_sample - co.y;\n"
+"   return clamp( fdelta, 0.2, 0.4 )-0.2;\n"
+"}\n"
+"\n"
+"float newlight_compute_sun_shadow( vec3 co, vec3 dir ){\n"
+"   if( g_shadow_samples == 0 ){\n"
+"      return 1.0;\n"
+"   }\n"
+"\n"
+"   float fspread = g_shadow_spread;\n"
+"   float flength = g_shadow_length;\n"
+"\n"
+"   float famt = 0.0;\n"
+"   famt += shadow_sample(co+(dir+vec3(-0.56,0.55, 0.30)*fspread)*flength*0.1);\n"
+"   famt += shadow_sample(co+(dir+vec3( 0.80,0.68, 0.34)*fspread)*flength*0.2);\n"
+"   famt += shadow_sample(co+(dir+vec3( 0.78,0.07,-0.06)*fspread)*flength*0.3);\n"
+"   famt += shadow_sample(co+(dir+vec3(-0.59,0.07,-0.42)*fspread)*flength*0.4);\n"
+"\n"
+"   //famt+=shadow_sample(co+(dir+vec3(-0.790,-0.933,-0.875)*fspread)*flength*0.5);\n"
+"   //famt+=shadow_sample(co+(dir+vec3( 0.807,-0.690, 0.472)*fspread)*flength*0.6);\n"
+"   //famt+=shadow_sample(co+(dir+vec3( 0.522,-0.379, 0.350)*fspread)*flength*0.7);\n"
+"   //famt+=shadow_sample(co+(dir+vec3( 0.483, 0.201, 0.306)*fspread)*flength*0.8);\n"
+"\n"
+"   return 1.0 - famt;\n"
+"}\n"
+"\n"
+"float newlight_specular( vec3 wnormal, vec3 dir, vec3 halfview, float exponent )\n"
+"{\n"
+"   vec3 specdir = reflect( -dir, wnormal );\n"
+"   return pow(max(dot( halfview, specdir ), 0.0), exponent);\n"
+"}\n"
+"\n"
+"vec3 scene_apply_fog( vec3 vfrag, vec3 colour, float fdist ){\n"
+"   float dist = pow(fdist*0.0010,0.78);\n"
+"   return mix( vfrag, colour, min( 1.0, dist ) );\n"
+"}\n"
+"\n"
+"vec3 scene_calculate_light( int light_index, \n"
+"                            vec3 halfview, vec3 co, vec3 normal )\n"
+"{\n"
+"   vec4 light_colour = texelFetch( uLightsArray, light_index+0 );\n"
+"   vec4 light_co     = texelFetch( uLightsArray, light_index+1 );\n"
+"   vec4 light_dir    = texelFetch( uLightsArray, light_index+2 );\n"
+"\n"
+"   vec3 light_delta = light_co.xyz-co;\n"
+"   float dist2 = dot(light_delta,light_delta);\n"
+"\n"
+"   light_delta = normalize( light_delta );\n"
+"\n"
+"   float quadratic = dist2*100.0;\n"
+"   float attenuation  = 1.0/( 1.0 + quadratic );\n"
+"         attenuation *= max( dot( light_delta, normal ), 0.0 );\n"
+"\n"
+"   float falloff = max( 0.0, 1.0-(dist2*light_co.w) );\n"
+"\n"
+"   if( light_dir.w < 0.999999 ){\n"
+"      float spot_theta = max( 0.0, dot( light_delta, -light_dir.xyz ) );\n"
+"      falloff *= max( 0.0, (spot_theta - light_dir.w) / (1.0-light_dir.w) );\n"
+"   }\n"
+"\n"
+"   return light_colour.rgb * attenuation * falloff \n"
+"            * step( g_day_phase, light_colour.w );\n"
+"}\n"
+"\n"
+"vec3 scene_calculate_packed_light_patch( uint packed_index, \n"
+"                                         vec3 halfview, vec3 co, vec3 normal )\n"
+"{\n"
+"   uint light_count = packed_index & 0x3u;\n"
+"\n"
+"   vec3 l = vec3(0.0);\n"
+"\n"
+"   if( light_count >= 1u ){\n"
+"      int index_0 = int( ((packed_index >>  2u) & 0x3ffu) * 3u );\n"
+"      int index_1 = int( ((packed_index >> 12u) & 0x3ffu) * 3u );\n"
+"      int index_2 = int( ((packed_index >> 22u) & 0x3ffu) * 3u );\n"
+"\n"
+"      l += scene_calculate_light( index_0, halfview, co, normal );\n"
+"\n"
+"      if( light_count >= 2u ){\n"
+"         l += scene_calculate_light( index_1, halfview, co, normal );\n"
+"\n"
+"         if( light_count >= 3u ){\n"
+"            l += scene_calculate_light( index_2, halfview, co, normal );\n"
+"         }\n"
+"      }\n"
+"   }\n"
+"\n"
+"   return l;\n"
+"}\n"
+"\n"
+"vec3 world_compute_lighting( vec3 diffuse, vec3 normal, vec3 co,\n"
+"                             float light_mask )\n"
+"{\n"
+"   if( g_light_preview == 1 )\n"
+"      diffuse = vec3(0.75);\n"
+"\n"
+"   // Lighting\n"
+"   vec3 halfview = uCamera - co;\n"
+"   float fdist = length(halfview);\n"
+"   halfview /= fdist;\n"
+"\n"
+"   float world_shadow = newlight_compute_sun_shadow( \n"
+"               co, g_sun_dir.xyz * (1.0/(max(g_sun_dir.y,0.0)+0.2)) );\n"
+"\n"
+"   vec3 total_light = clearskies_lighting( \n"
+"                           normal, min( light_mask, world_shadow ), halfview );\n"
+"\n"
+"   vec3 cube_coord = (co - g_cube_min.xyz) * g_cube_inv_range.xyz;\n"
+"        cube_coord = floor( cube_coord );\n"
+"\n"
+"   if( g_debug_indices == 1 )\n"
+"   {\n"
+"      return rand33(cube_coord);\n"
+"   }\n"
+"\n"
+"   if( g_debug_complexity == 1 )\n"
+"   {\n"
+"      ivec3 coord = ivec3( cube_coord );\n"
+"      uvec4 index_sample = texelFetch( uLightsIndex, coord, 0 );\n"
+"\n"
+"      uint light_count = (index_sample.x & 0x3u) + (index_sample.y & 0x3u);\n"
+"      return vec3( float(light_count)*(1.0/6.0), 0.0, 0.5 );\n"
+"   }\n"
+"\n"
+"   // FIXME: this coord should absolutely must be clamped!\n"
+"   \n"
+"   ivec3 coord = ivec3( cube_coord );\n"
+"   uvec4 index_sample = texelFetch( uLightsIndex, coord, 0 );\n"
+"\n"
+"   total_light += \n"
+"      scene_calculate_packed_light_patch( index_sample.x,\n"
+"                                          halfview, co, normal ) \n"
+"                                          * light_mask;\n"
+"   total_light += \n"
+"      scene_calculate_packed_light_patch( index_sample.y,\n"
+"                                          halfview, co, normal )\n"
+"                                          * light_mask;\n"
+"\n"
+"   // Take a section of the sky function to give us a matching fog colour\n"
+"\n"
+"   vec3 fog_colour  = clearskies_ambient( -halfview );\n"
+"   float sun_theta  = dot( -halfview, g_sun_dir.xyz );\n"
+"   float sun_size   = max( 0.0, sun_theta * 0.5 + 0.5 );\n"
+"   float sun_shape  = sun_size * max(g_sun_dir.y,0.0) * 0.5;\n"
+"         \n"
+"   vec3 sun_colour  = mix( vec3(1.0), g_sunset_colour.rgb, g_sunset_phase*0.5 );\n"
+"        sun_colour *= sun_shape;\n"
+"\n"
+"   fog_colour += sun_colour;\n"
+"   return scene_apply_fog( diffuse * total_light, fog_colour, fdist );\n"
+"}\n"
+"\n"
+"#line      9        0 \n"
+"\n"
+"float sdLine( vec3 p, vec3 a, vec3 b )\n"
+"{\n"
+"  vec3 pa = p - a;\n"
+"  vec3 ba = b - a;\n"
+"\n"
+"  float h = clamp( dot(pa,ba)/dot(ba,ba), 0.0, 1.0 );\n"
+"  return length( pa - ba*h );\n"
+"}\n"
+"\n"
+"float compute_board_shadow()\n"
+"{\n"
+"   // player shadow\n"
+"   float dist_to_player = max( 0.0, sdLine( aWorldCo, g_board_0.xyz,\n"
+"                                                      g_board_1.xyz )-0.1 );\n"
+"   float player_shadow = max( 1.0-dist_to_player*2.7, 0.0 );\n"
+"   player_shadow *= player_shadow*player_shadow*player_shadow;\n"
+"\n"
+"   return 1.0 - player_shadow*0.8;\n"
+"}\n"
+"\n"
+"vec3 scene_compute_lighting( vec3 diffuse, vec3 normal, vec3 co )\n"
+"{\n"
+"   return world_compute_lighting( diffuse, normal, co, compute_board_shadow() );\n"
+"}\n"
+"\n"
+"#line     13        0 \n"
+"#line       1        3 \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     14        0 \n"
+"\n"
+"vec2 smin( float a, float b, float k ){\n"
+"   float h = max( k-abs(a-b), 0.0 )/k;\n"
+"   float m = h*h*0.5;\n"
+"   float s = m*k*(1.0/2.0);\n"
+"\n"
+"   if( a < b )\n"
+"      return vec2(a-s,m);\n"
+"   else\n"
+"      return vec2(b-s,1.0-m);\n"
+"}\n"
+"\n"
+"void main(){\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"
+"   float dcam = (-8.0+distance( aCo, uCamera ))/4.0;\n"
+"   float dy0 = aCo.y - uMapInfo.x;\n"
+"   float dy1 = uMapInfo.y - aCo.y;\n"
+"\n"
+"   if( min(min(dy0,dy1)*0.5, dcam) + dither < 0.51 ) \n"
+"      discard;\n"
+"\n"
+"   compute_motion_vectors();\n"
+"\n"
+"   vec3 vfrag = vec3(0.898,0.811,0.716);\n"
+"   vec3 qnorm = aNorm.xyz;\n"
+"\n"
+"   qnorm = normalize(floor(aNorm.xyz*4.0)*0.25);\n"
+"   qnorm += vec3(0.001,0.0,0.0);\n"
+"\n"
+"   if( uAlphatest ){\n"
+"      vec4 vSample = texture( uTexMain, aUv );\n"
+"      if( vSample.a < 0.5 )\n"
+"         discard;\n"
+"   }\n"
+"   else{\n"
+"   }\n"
+"\n"
+"   vfrag = scene_compute_lighting( vfrag, qnorm, aWorldCo );\n"
+"   \n"
+"   // dots\n"
+"   float d0 = distance( aCo, uPlayerPos.xyz )*2.0;\n"
+"   float d1 = distance( aCo, uSpawnPos.xyz );\n"
+"\n"
+"   vec2 dm = smin( d0, d1, 10.0 );\n"
+"   float dd = fract(dm.x*0.2-g_realtime*0.5) * \n"
+"               max(0.0,1.0-dm.x*0.04) * \n"
+"               max(0.0,qnorm.y);\n"
+"   vec3 emit = mix(vec3(1.0,0.0,0.0),vec3(0.0,1.0,0.0),dm.y)*dd;\n"
+"\n"
+"   // line\n"
+"   vec3 v0 = (uSpawnPos.xyz-uPlayerPos.xyz)*uSpawnPos.w;\n"
+"   float t = clamp( dot(aCo-uPlayerPos.xyz,v0), 0.0, uPlayerPos.w );\n"
+"   vec3 p0 = uPlayerPos.xyz + v0*t;\n"
+"   float d3 = distance(p0,aCo);\n"
+"   emit += vec3(fract(t*0.2-g_realtime+d3*0.2)*max(0.0,1.0-d3*0.2));\n"
+"\n"
+"   vfrag += emit;\n"
+"\n"
+"   if( uMapInfo.z > 0.0 ){\n"
+"      float height = fract( aCo.y * 0.1 );\n"
+"      float lg = 2.0*length(vec2(dFdx(height), dFdy(height)));\n"
+"      vfrag *= 1.0f+(lg*0.2*uMapInfo.z);\n"
+"   }\n"
+"\n"
+"   oColour = vec4( vfrag, 1.0 );\n"
+"   //oColour = vec4( vfrag, 1.0 );\n"
+"}\n"
+""},
+};
+
+GLuint _uniform_scene_override_uMdl;
+GLuint _uniform_scene_override_uPv;
+GLuint _uniform_scene_override_uPvmPrev;
+GLuint _uniform_scene_override_uNormalMtx;
+GLuint _uniform_scene_override_uTexGarbage;
+GLuint _uniform_scene_override_uTexMain;
+GLuint _uniform_scene_override_uCamera;
+GLuint _uniform_scene_override_uPlane;
+GLuint _uniform_scene_override_uPlayerPos;
+GLuint _uniform_scene_override_uSpawnPos;
+GLuint _uniform_scene_override_uAlphatest;
+GLuint _uniform_scene_override_uMapInfo;
+GLuint _uniform_scene_override_g_world_depth;
+GLuint _uniform_scene_override_uLightsArray;
+GLuint _uniform_scene_override_uLightsIndex;
+#include "shaders/scene_fxglow.h"
+struct vg_shader _shader_scene_fxglow = {
+   .name = "scene_fxglow",
+   .vs = 
+{
+.orig_file = "shaders/scene_fxglow.vs",
+.static_src = 
+"layout (location=0) in vec3  a_co;\n"
+"layout (location=1) in vec4  a_norm;\n"
+"layout (location=2) in vec2  a_uv;\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      6        0 \n"
+"\n"
+"uniform mat4x3 uMdl;\n"
+"uniform mat4   uPv;\n"
+"uniform mat4   uPvmPrev;\n"
+"uniform vec2   uUvOffset;\n"
+"\n"
+"out vec2 aUv;\n"
+"out vec4 aNorm;\n"
+"out vec3 aCo;\n"
+"out vec3 aWorldCo;\n"
+"\n"
+"void main()\n"
+"{\n"
+"   vec3 world_pos0 = uMdl     * vec4( a_co, 1.0 );\n"
+"   vec4 vproj0     = uPv      * vec4( world_pos0, 1.0 );\n"
+"   vec4 vproj1     = uPvmPrev * vec4( a_co, 1.0 );\n"
+"\n"
+"   vs_motion_out( vproj0, vproj1 );\n"
+"\n"
+"   gl_Position = vproj0;\n"
+"\n"
+"   aUv = a_uv + uUvOffset;\n"
+"   aNorm = vec4( mat3(uMdl) * a_norm.xyz, a_norm.w );\n"
+"   aCo = a_co;\n"
+"   aWorldCo = world_pos0;\n"
+"}\n"
+""},
+   .fs = 
+{
+.orig_file = "shaders/scene_fxglow.fs",
+.static_src = 
+"uniform sampler2D uTexMain;\n"
+"uniform vec3 uCamera;\n"
+"\n"
+"#line       1        1 \n"
+"// :D\n"
+"const float CLEARSKIES_LIGHT_DOT_MIN = 0.0;\n"
+"\n"
+"#line      5        0 \n"
+"#line       1        2 \n"
+"// :D\n"
+"\n"
+"in vec2 aUv;\n"
+"in vec4 aNorm;\n"
+"in vec3 aCo;\n"
+"in vec3 aWorldCo;\n"
+"\n"
+"#line       1        1 \n"
+"layout (location = 0) out vec4 oColour;\n"
+"\n"
+"// OpenGL wiki: Recommends do not use vec3 because of drivers. hence the v4s...\n"
+"layout (std140) uniform ub_world_lighting\n"
+"{\n"
+"   vec4 g_cube_min;\n"
+"   vec4 g_cube_inv_range;\n"
+"\n"
+"   vec4 g_water_plane;\n"
+"   vec4 g_depth_bounds;\n"
+"\n"
+"   vec4 g_daysky_colour;\n"
+"   vec4 g_nightsky_colour;\n"
+"   vec4 g_sunset_colour;\n"
+"   vec4 g_ambient_colour;\n"
+"   vec4 g_sunset_ambient;\n"
+"   vec4 g_sun_colour;\n"
+"   vec4 g_sun_dir;\n"
+"   vec4 g_board_0;\n"
+"   vec4 g_board_1;\n"
+"\n"
+"   float g_water_fog;\n"
+"   float g_time;\n"
+"   float g_realtime;\n"
+"   float g_shadow_length;\n"
+"   float g_shadow_spread;\n"
+"\n"
+"   float g_time_of_day;\n"
+"   float g_day_phase;\n"
+"   float g_sunset_phase;\n"
+"\n"
+"   int g_light_preview;\n"
+"   int g_shadow_samples;\n"
+"\n"
+"   int g_debug_indices;\n"
+"   int g_debug_complexity;\n"
+"};\n"
+"\n"
+"uniform sampler2D g_world_depth;\n"
+"uniform samplerBuffer uLightsArray;\n"
+"uniform usampler3D uLightsIndex;\n"
+"\n"
+"#line       1        1 \n"
+"//const vec3  DAYSKY_COLOUR   = vec3( 0.37, 0.54, 0.97 );\n"
+"//const vec3  NIGHTSKY_COLOUR = vec3( 0.03, 0.05, 0.20 );\n"
+"//const vec3  SUNSET_COLOUR   = vec3( 1.00, 0.32, 0.01 );\n"
+"//const vec3  AMBIENT_COLOUR  = vec3( 0.13, 0.17, 0.35 );\n"
+"//const vec3  SUNSET_AMBIENT  = vec3( 0.25, 0.17, 0.51 );\n"
+"//const vec3  SUN_COLOUR      = vec3( 1.10, 0.89, 0.35 );\n"
+"\n"
+"const float SUN_ANGLE       = 0.0001;\n"
+"const float PI              = 3.14159265358979323846264;\n"
+"\n"
+"//struct world_info\n"
+"//{\n"
+"//   float time,\n"
+"//         time_of_day,\n"
+"//         day_phase,\n"
+"//         sunset_phase;\n"
+"//   \n"
+"//   vec3 sun_dir;\n"
+"//};\n"
+"\n"
+"vec3 rand33(vec3 p3)\n"
+"{\n"
+"      p3 = fract(p3 * vec3(.1031, .1030, .0973));\n"
+"   p3 += dot(p3, p3.yxz+33.33);\n"
+"   return fract((p3.xxy + p3.yxx)*p3.zyx);\n"
+"}\n"
+"\n"
+"float stars( vec3 rd, float rr, float size ){\n"
+"   vec3 co = rd * rr;\n"
+"\n"
+"   float a = atan(co.y, length(co.xz)) + 4.0 * PI;\n"
+"\n"
+"   float spaces = 1.0 / rr;\n"
+"   size = (rr * 0.0015) * fwidth(a) * 1000.0 * size;\n"
+"   a -= mod(a, spaces) - spaces * 0.5;\n"
+"\n"
+"   float count = floor(sqrt(pow(rr, 2.0) * (1.0 - pow(sin(a), 2.0))) * 3.0);\n"
+"   \n"
+"   float plane = atan(co.z, co.x) + 4.0 * PI;\n"
+"   plane = plane - mod(plane, PI / count);\n"
+"\n"
+"   vec2 delta = rand33(vec3(plane, a, 0.0)).xy;\n"
+"\n"
+"   float level = sin(a + spaces * (delta.y - 0.5) * (1.0 - size)) * rr;\n"
+"   float ydist = sqrt(rr * rr - level * level);\n"
+"   float angle = plane + (PI * (delta.x * (1.0-size) + size * 0.5) / count);\n"
+"   vec3 center = vec3(cos(angle) * ydist, level, sin(angle) * ydist);\n"
+"   float star = smoothstep(size, 0.0, distance(center, co));\n"
+"   return star;\n"
+"}\n"
+"\n"
+"float luminance( vec3 v )\n"
+"{\n"
+"   return dot( v, vec3(0.2126, 0.7152, 0.0722) );\n"
+"}\n"
+"\n"
+"vec3 clearskies_ambient( vec3 dir )\n"
+"{\n"
+"   float sun_azimuth  = g_sunset_phase * (dot( dir.xz, g_sun_dir.xz )*0.4+0.6);\n"
+"   float sky_gradient = dir.y;\n"
+"   \n"
+"   /* Blend phase colours */\n"
+"   vec3 ambient  = g_daysky_colour.rgb   * (g_day_phase-g_sunset_phase*0.1);\n"
+"        ambient += g_sunset_colour.rgb   * (1.0-dir.y*0.5)*sun_azimuth;\n"
+"        ambient += g_nightsky_colour.rgb * (1.0-g_day_phase);\n"
+"   \n"
+"   /* Add gradient */\n"
+"        ambient -= sky_gradient * luminance(ambient);\n"
+"        \n"
+"   return ambient;\n"
+"}\n"
+"\n"
+"vec3 clearskies_sky( vec3 ray_dir )\n"
+"{\n"
+"   ray_dir.y = abs( ray_dir.y );\n"
+"   vec3 sky_colour  = clearskies_ambient( ray_dir );\n"
+"   \n"
+"   /* Sun */\n"
+"   float sun_theta  = dot( ray_dir, g_sun_dir.xyz );\n"
+"   float sun_size   = max( 0.0, sun_theta * 0.5 + 0.5 + SUN_ANGLE );\n"
+"   float sun_shape  = pow( sun_size, 2000.0 );\n"
+"         sun_shape += sun_size * max(g_sun_dir.y,0.0) * 0.5;\n"
+"         \n"
+"   vec3 sun_colour  = mix( vec3(1.0), g_sunset_colour.rgb, g_sunset_phase*0.5 );\n"
+"        sun_colour *= sun_shape;\n"
+"\n"
+"   \n"
+"   float star = 0.0;\n"
+"   float star_blend = 10.0*max(0.0,(1.0-g_day_phase*2.0));\n"
+"\n"
+"   if( star_blend > 0.001 ){\n"
+"      for( float j = 1.0; j <= 4.1; j += 1.0 ){\n"
+"         float m = mix(0.6, 0.9, smoothstep(1.0, 2.0, j));\n"
+"         star += stars( ray_dir, 1.94 * pow( 1.64, j ), m ) * (1.0/pow(4.0, j));\n"
+"      }\n"
+"   }\n"
+"   \n"
+"   vec3 composite   = sky_colour + sun_colour + star*star_blend;\n"
+"   return composite;\n"
+"}\n"
+"\n"
+"vec3 clearskies_lighting( vec3 normal, float shadow, vec3 halfview )\n"
+"{\n"
+"   float fresnel = 1.0 - abs(dot(normal,halfview));\n"
+"\n"
+"   vec3  reflect_colour = mix( g_daysky_colour.rgb, g_sunset_colour.rgb, \n"
+"                               g_sunset_phase );\n"
+"\n"
+"   vec3  sky_reflection = 0.5 * fresnel * reflect_colour;\n"
+"   vec3  light_sun      = max( CLEARSKIES_LIGHT_DOT_MIN, \n"
+"                               dot(normal,g_sun_dir.xyz)*0.75+0.25\n"
+"                           ) * g_sun_colour.rgb * g_day_phase;\n"
+"\n"
+"   float scaled_shadow = max( shadow, 1.0 - max(g_sun_dir.y,0.0) );\n"
+"   vec3 ambient = mix( g_ambient_colour.rgb, g_sunset_ambient.rgb, \n"
+"                       g_sunset_phase );\n"
+"\n"
+"   return ambient + (light_sun + sky_reflection) * shadow;\n"
+"}\n"
+"\n"
+"#line     44        0 \n"
+"\n"
+"float world_depth_sample( vec3 pos )\n"
+"{\n"
+"   vec2 depth_coord = (pos.xz - g_depth_bounds.xy) * g_depth_bounds.zw; \n"
+"   return texture( g_world_depth, depth_coord ).r;\n"
+"}\n"
+"\n"
+"float world_water_depth( vec3 pos )\n"
+"{\n"
+"   float ref_depth = g_water_plane.y*g_water_plane.w;\n"
+"   return world_depth_sample( pos ) - ref_depth;\n"
+"}\n"
+"\n"
+"float shadow_sample( vec3 co ){\n"
+"   float height_sample = world_depth_sample( co );\n"
+"\n"
+"   float fdelta = height_sample - co.y;\n"
+"   return clamp( fdelta, 0.2, 0.4 )-0.2;\n"
+"}\n"
+"\n"
+"float newlight_compute_sun_shadow( vec3 co, vec3 dir ){\n"
+"   if( g_shadow_samples == 0 ){\n"
+"      return 1.0;\n"
+"   }\n"
+"\n"
+"   float fspread = g_shadow_spread;\n"
+"   float flength = g_shadow_length;\n"
+"\n"
+"   float famt = 0.0;\n"
+"   famt += shadow_sample(co+(dir+vec3(-0.56,0.55, 0.30)*fspread)*flength*0.1);\n"
+"   famt += shadow_sample(co+(dir+vec3( 0.80,0.68, 0.34)*fspread)*flength*0.2);\n"
+"   famt += shadow_sample(co+(dir+vec3( 0.78,0.07,-0.06)*fspread)*flength*0.3);\n"
+"   famt += shadow_sample(co+(dir+vec3(-0.59,0.07,-0.42)*fspread)*flength*0.4);\n"
+"\n"
+"   //famt+=shadow_sample(co+(dir+vec3(-0.790,-0.933,-0.875)*fspread)*flength*0.5);\n"
+"   //famt+=shadow_sample(co+(dir+vec3( 0.807,-0.690, 0.472)*fspread)*flength*0.6);\n"
+"   //famt+=shadow_sample(co+(dir+vec3( 0.522,-0.379, 0.350)*fspread)*flength*0.7);\n"
+"   //famt+=shadow_sample(co+(dir+vec3( 0.483, 0.201, 0.306)*fspread)*flength*0.8);\n"
+"\n"
+"   return 1.0 - famt;\n"
+"}\n"
+"\n"
+"float newlight_specular( vec3 wnormal, vec3 dir, vec3 halfview, float exponent )\n"
+"{\n"
+"   vec3 specdir = reflect( -dir, wnormal );\n"
+"   return pow(max(dot( halfview, specdir ), 0.0), exponent);\n"
+"}\n"
+"\n"
+"vec3 scene_apply_fog( vec3 vfrag, vec3 colour, float fdist ){\n"
+"   float dist = pow(fdist*0.0010,0.78);\n"
+"   return mix( vfrag, colour, min( 1.0, dist ) );\n"
+"}\n"
+"\n"
+"vec3 scene_calculate_light( int light_index, \n"
+"                            vec3 halfview, vec3 co, vec3 normal )\n"
+"{\n"
+"   vec4 light_colour = texelFetch( uLightsArray, light_index+0 );\n"
+"   vec4 light_co     = texelFetch( uLightsArray, light_index+1 );\n"
+"   vec4 light_dir    = texelFetch( uLightsArray, light_index+2 );\n"
+"\n"
+"   vec3 light_delta = light_co.xyz-co;\n"
+"   float dist2 = dot(light_delta,light_delta);\n"
+"\n"
+"   light_delta = normalize( light_delta );\n"
+"\n"
+"   float quadratic = dist2*100.0;\n"
+"   float attenuation  = 1.0/( 1.0 + quadratic );\n"
+"         attenuation *= max( dot( light_delta, normal ), 0.0 );\n"
+"\n"
+"   float falloff = max( 0.0, 1.0-(dist2*light_co.w) );\n"
+"\n"
+"   if( light_dir.w < 0.999999 ){\n"
+"      float spot_theta = max( 0.0, dot( light_delta, -light_dir.xyz ) );\n"
+"      falloff *= max( 0.0, (spot_theta - light_dir.w) / (1.0-light_dir.w) );\n"
+"   }\n"
+"\n"
+"   return light_colour.rgb * attenuation * falloff \n"
+"            * step( g_day_phase, light_colour.w );\n"
+"}\n"
+"\n"
+"vec3 scene_calculate_packed_light_patch( uint packed_index, \n"
+"                                         vec3 halfview, vec3 co, vec3 normal )\n"
+"{\n"
+"   uint light_count = packed_index & 0x3u;\n"
+"\n"
+"   vec3 l = vec3(0.0);\n"
+"\n"
+"   if( light_count >= 1u ){\n"
+"      int index_0 = int( ((packed_index >>  2u) & 0x3ffu) * 3u );\n"
+"      int index_1 = int( ((packed_index >> 12u) & 0x3ffu) * 3u );\n"
+"      int index_2 = int( ((packed_index >> 22u) & 0x3ffu) * 3u );\n"
+"\n"
+"      l += scene_calculate_light( index_0, halfview, co, normal );\n"
+"\n"
+"      if( light_count >= 2u ){\n"
+"         l += scene_calculate_light( index_1, halfview, co, normal );\n"
+"\n"
+"         if( light_count >= 3u ){\n"
+"            l += scene_calculate_light( index_2, halfview, co, normal );\n"
+"         }\n"
+"      }\n"
+"   }\n"
+"\n"
+"   return l;\n"
+"}\n"
+"\n"
+"vec3 world_compute_lighting( vec3 diffuse, vec3 normal, vec3 co,\n"
+"                             float light_mask )\n"
+"{\n"
+"   if( g_light_preview == 1 )\n"
+"      diffuse = vec3(0.75);\n"
+"\n"
+"   // Lighting\n"
+"   vec3 halfview = uCamera - co;\n"
+"   float fdist = length(halfview);\n"
+"   halfview /= fdist;\n"
+"\n"
+"   float world_shadow = newlight_compute_sun_shadow( \n"
+"               co, g_sun_dir.xyz * (1.0/(max(g_sun_dir.y,0.0)+0.2)) );\n"
+"\n"
+"   vec3 total_light = clearskies_lighting( \n"
+"                           normal, min( light_mask, world_shadow ), halfview );\n"
+"\n"
+"   vec3 cube_coord = (co - g_cube_min.xyz) * g_cube_inv_range.xyz;\n"
+"        cube_coord = floor( cube_coord );\n"
+"\n"
+"   if( g_debug_indices == 1 )\n"
+"   {\n"
+"      return rand33(cube_coord);\n"
+"   }\n"
+"\n"
+"   if( g_debug_complexity == 1 )\n"
+"   {\n"
+"      ivec3 coord = ivec3( cube_coord );\n"
+"      uvec4 index_sample = texelFetch( uLightsIndex, coord, 0 );\n"
+"\n"
+"      uint light_count = (index_sample.x & 0x3u) + (index_sample.y & 0x3u);\n"
+"      return vec3( float(light_count)*(1.0/6.0), 0.0, 0.5 );\n"
+"   }\n"
+"\n"
+"   // FIXME: this coord should absolutely must be clamped!\n"
+"   \n"
+"   ivec3 coord = ivec3( cube_coord );\n"
+"   uvec4 index_sample = texelFetch( uLightsIndex, coord, 0 );\n"
+"\n"
+"   total_light += \n"
+"      scene_calculate_packed_light_patch( index_sample.x,\n"
+"                                          halfview, co, normal ) \n"
+"                                          * light_mask;\n"
+"   total_light += \n"
+"      scene_calculate_packed_light_patch( index_sample.y,\n"
+"                                          halfview, co, normal )\n"
+"                                          * light_mask;\n"
+"\n"
+"   // Take a section of the sky function to give us a matching fog colour\n"
+"\n"
+"   vec3 fog_colour  = clearskies_ambient( -halfview );\n"
+"   float sun_theta  = dot( -halfview, g_sun_dir.xyz );\n"
+"   float sun_size   = max( 0.0, sun_theta * 0.5 + 0.5 );\n"
+"   float sun_shape  = sun_size * max(g_sun_dir.y,0.0) * 0.5;\n"
+"         \n"
+"   vec3 sun_colour  = mix( vec3(1.0), g_sunset_colour.rgb, g_sunset_phase*0.5 );\n"
+"        sun_colour *= sun_shape;\n"
+"\n"
+"   fog_colour += sun_colour;\n"
+"   return scene_apply_fog( diffuse * total_light, fog_colour, fdist );\n"
+"}\n"
+"\n"
+"#line      9        0 \n"
+"\n"
+"float sdLine( vec3 p, vec3 a, vec3 b )\n"
+"{\n"
+"  vec3 pa = p - a;\n"
+"  vec3 ba = b - a;\n"
+"\n"
+"  float h = clamp( dot(pa,ba)/dot(ba,ba), 0.0, 1.0 );\n"
+"  return length( pa - ba*h );\n"
+"}\n"
+"\n"
+"float compute_board_shadow()\n"
+"{\n"
+"   // player shadow\n"
+"   float dist_to_player = max( 0.0, sdLine( aWorldCo, g_board_0.xyz,\n"
+"                                                      g_board_1.xyz )-0.1 );\n"
+"   float player_shadow = max( 1.0-dist_to_player*2.7, 0.0 );\n"
+"   player_shadow *= player_shadow*player_shadow*player_shadow;\n"
+"\n"
+"   return 1.0 - player_shadow*0.8;\n"
+"}\n"
+"\n"
+"vec3 scene_compute_lighting( vec3 diffuse, vec3 normal, vec3 co )\n"
+"{\n"
+"   return world_compute_lighting( diffuse, normal, co, compute_board_shadow() );\n"
+"}\n"
+"\n"
+"#line      6        0 \n"
+"#line       1        3 \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      7        0 \n"
+"\n"
+"void main(){\n"
+"   oMotionVec = vec2(0.0);\n"
+"\n"
+"   vec4 vsamplemain = texture( uTexMain, aUv );\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 = vec4( vsamplemain.rgb, 1.0 );\n"
+"}\n"
+""},
+};
+
+GLuint _uniform_scene_fxglow_uMdl;
+GLuint _uniform_scene_fxglow_uPv;
+GLuint _uniform_scene_fxglow_uPvmPrev;
+GLuint _uniform_scene_fxglow_uUvOffset;
+GLuint _uniform_scene_fxglow_uTexMain;
+GLuint _uniform_scene_fxglow_uCamera;
+GLuint _uniform_scene_fxglow_g_world_depth;
+GLuint _uniform_scene_fxglow_uLightsArray;
+GLuint _uniform_scene_fxglow_uLightsIndex;
+#include "shaders/scene_vertex_blend.h"
+struct vg_shader _shader_scene_vertex_blend = {
+   .name = "scene_vertex_blend",
+   .vs = 
+{
+.orig_file = "shaders/scene.vs",
+.static_src = 
+"layout (location=0) in vec3  a_co;\n"
+"layout (location=1) in vec4  a_norm;\n"
+"layout (location=2) in vec2  a_uv;\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      6        0 \n"
+"\n"
+"uniform mat4x3 uMdl;\n"
+"uniform mat4   uPv;\n"
+"uniform mat4   uPvmPrev;\n"
+"\n"
+"out vec2 aUv;\n"
+"out vec4 aNorm;\n"
+"out vec3 aCo;\n"
+"out vec3 aWorldCo;\n"
+"\n"
+"void main()\n"
+"{\n"
+"   vec3 world_pos0 = uMdl     * vec4( a_co, 1.0 );\n"
+"   vec4 vproj0     = uPv      * vec4( world_pos0, 1.0 );\n"
+"   vec4 vproj1     = uPvmPrev * vec4( a_co, 1.0 );\n"
+"\n"
+"   vs_motion_out( vproj0, vproj1 );\n"
+"\n"
+"   gl_Position = vproj0;\n"
+"\n"
+"   aUv = a_uv;\n"
+"   aNorm = vec4( mat3(uMdl) * a_norm.xyz, a_norm.w );\n"
+"   aCo = a_co;\n"
+"   aWorldCo = world_pos0;\n"
+"}\n"
+""},
+   .fs = 
+{
+.orig_file = "shaders/scene_vertex_blend.fs",
+.static_src = 
+"uniform sampler2D uTexGarbage;\n"
+"uniform sampler2D uTexGradients;\n"
+"uniform vec3 uCamera;\n"
+"\n"
+"#line       1        1 \n"
+"// :D\n"
+"const float CLEARSKIES_LIGHT_DOT_MIN = 0.0;\n"
+"\n"
+"#line      6        0 \n"
+"#line       1        2 \n"
+"// :D\n"
+"\n"
+"in vec2 aUv;\n"
+"in vec4 aNorm;\n"
+"in vec3 aCo;\n"
+"in vec3 aWorldCo;\n"
+"\n"
+"#line       1        1 \n"
+"layout (location = 0) out vec4 oColour;\n"
+"\n"
+"// OpenGL wiki: Recommends do not use vec3 because of drivers. hence the v4s...\n"
+"layout (std140) uniform ub_world_lighting\n"
+"{\n"
+"   vec4 g_cube_min;\n"
+"   vec4 g_cube_inv_range;\n"
+"\n"
+"   vec4 g_water_plane;\n"
+"   vec4 g_depth_bounds;\n"
+"\n"
+"   vec4 g_daysky_colour;\n"
+"   vec4 g_nightsky_colour;\n"
+"   vec4 g_sunset_colour;\n"
+"   vec4 g_ambient_colour;\n"
+"   vec4 g_sunset_ambient;\n"
+"   vec4 g_sun_colour;\n"
+"   vec4 g_sun_dir;\n"
+"   vec4 g_board_0;\n"
+"   vec4 g_board_1;\n"
+"\n"
+"   float g_water_fog;\n"
+"   float g_time;\n"
+"   float g_realtime;\n"
+"   float g_shadow_length;\n"
+"   float g_shadow_spread;\n"
+"\n"
+"   float g_time_of_day;\n"
+"   float g_day_phase;\n"
+"   float g_sunset_phase;\n"
+"\n"
+"   int g_light_preview;\n"
+"   int g_shadow_samples;\n"
+"\n"
+"   int g_debug_indices;\n"
+"   int g_debug_complexity;\n"
+"};\n"
+"\n"
+"uniform sampler2D g_world_depth;\n"
+"uniform samplerBuffer uLightsArray;\n"
+"uniform usampler3D uLightsIndex;\n"
+"\n"
+"#line       1        1 \n"
+"//const vec3  DAYSKY_COLOUR   = vec3( 0.37, 0.54, 0.97 );\n"
+"//const vec3  NIGHTSKY_COLOUR = vec3( 0.03, 0.05, 0.20 );\n"
+"//const vec3  SUNSET_COLOUR   = vec3( 1.00, 0.32, 0.01 );\n"
+"//const vec3  AMBIENT_COLOUR  = vec3( 0.13, 0.17, 0.35 );\n"
+"//const vec3  SUNSET_AMBIENT  = vec3( 0.25, 0.17, 0.51 );\n"
+"//const vec3  SUN_COLOUR      = vec3( 1.10, 0.89, 0.35 );\n"
+"\n"
+"const float SUN_ANGLE       = 0.0001;\n"
+"const float PI              = 3.14159265358979323846264;\n"
+"\n"
+"//struct world_info\n"
+"//{\n"
+"//   float time,\n"
+"//         time_of_day,\n"
+"//         day_phase,\n"
+"//         sunset_phase;\n"
+"//   \n"
+"//   vec3 sun_dir;\n"
+"//};\n"
+"\n"
+"vec3 rand33(vec3 p3)\n"
+"{\n"
+"      p3 = fract(p3 * vec3(.1031, .1030, .0973));\n"
+"   p3 += dot(p3, p3.yxz+33.33);\n"
+"   return fract((p3.xxy + p3.yxx)*p3.zyx);\n"
+"}\n"
+"\n"
+"float stars( vec3 rd, float rr, float size ){\n"
+"   vec3 co = rd * rr;\n"
+"\n"
+"   float a = atan(co.y, length(co.xz)) + 4.0 * PI;\n"
+"\n"
+"   float spaces = 1.0 / rr;\n"
+"   size = (rr * 0.0015) * fwidth(a) * 1000.0 * size;\n"
+"   a -= mod(a, spaces) - spaces * 0.5;\n"
+"\n"
+"   float count = floor(sqrt(pow(rr, 2.0) * (1.0 - pow(sin(a), 2.0))) * 3.0);\n"
+"   \n"
+"   float plane = atan(co.z, co.x) + 4.0 * PI;\n"
+"   plane = plane - mod(plane, PI / count);\n"
+"\n"
+"   vec2 delta = rand33(vec3(plane, a, 0.0)).xy;\n"
+"\n"
+"   float level = sin(a + spaces * (delta.y - 0.5) * (1.0 - size)) * rr;\n"
+"   float ydist = sqrt(rr * rr - level * level);\n"
+"   float angle = plane + (PI * (delta.x * (1.0-size) + size * 0.5) / count);\n"
+"   vec3 center = vec3(cos(angle) * ydist, level, sin(angle) * ydist);\n"
+"   float star = smoothstep(size, 0.0, distance(center, co));\n"
+"   return star;\n"
+"}\n"
+"\n"
+"float luminance( vec3 v )\n"
+"{\n"
+"   return dot( v, vec3(0.2126, 0.7152, 0.0722) );\n"
+"}\n"
+"\n"
+"vec3 clearskies_ambient( vec3 dir )\n"
+"{\n"
+"   float sun_azimuth  = g_sunset_phase * (dot( dir.xz, g_sun_dir.xz )*0.4+0.6);\n"
+"   float sky_gradient = dir.y;\n"
+"   \n"
+"   /* Blend phase colours */\n"
+"   vec3 ambient  = g_daysky_colour.rgb   * (g_day_phase-g_sunset_phase*0.1);\n"
+"        ambient += g_sunset_colour.rgb   * (1.0-dir.y*0.5)*sun_azimuth;\n"
+"        ambient += g_nightsky_colour.rgb * (1.0-g_day_phase);\n"
+"   \n"
+"   /* Add gradient */\n"
+"        ambient -= sky_gradient * luminance(ambient);\n"
+"        \n"
+"   return ambient;\n"
+"}\n"
+"\n"
+"vec3 clearskies_sky( vec3 ray_dir )\n"
+"{\n"
+"   ray_dir.y = abs( ray_dir.y );\n"
+"   vec3 sky_colour  = clearskies_ambient( ray_dir );\n"
+"   \n"
+"   /* Sun */\n"
+"   float sun_theta  = dot( ray_dir, g_sun_dir.xyz );\n"
+"   float sun_size   = max( 0.0, sun_theta * 0.5 + 0.5 + SUN_ANGLE );\n"
+"   float sun_shape  = pow( sun_size, 2000.0 );\n"
+"         sun_shape += sun_size * max(g_sun_dir.y,0.0) * 0.5;\n"
+"         \n"
+"   vec3 sun_colour  = mix( vec3(1.0), g_sunset_colour.rgb, g_sunset_phase*0.5 );\n"
+"        sun_colour *= sun_shape;\n"
+"\n"
+"   \n"
+"   float star = 0.0;\n"
+"   float star_blend = 10.0*max(0.0,(1.0-g_day_phase*2.0));\n"
+"\n"
+"   if( star_blend > 0.001 ){\n"
+"      for( float j = 1.0; j <= 4.1; j += 1.0 ){\n"
+"         float m = mix(0.6, 0.9, smoothstep(1.0, 2.0, j));\n"
+"         star += stars( ray_dir, 1.94 * pow( 1.64, j ), m ) * (1.0/pow(4.0, j));\n"
+"      }\n"
+"   }\n"
+"   \n"
+"   vec3 composite   = sky_colour + sun_colour + star*star_blend;\n"
+"   return composite;\n"
+"}\n"
+"\n"
+"vec3 clearskies_lighting( vec3 normal, float shadow, vec3 halfview )\n"
+"{\n"
+"   float fresnel = 1.0 - abs(dot(normal,halfview));\n"
+"\n"
+"   vec3  reflect_colour = mix( g_daysky_colour.rgb, g_sunset_colour.rgb, \n"
+"                               g_sunset_phase );\n"
+"\n"
+"   vec3  sky_reflection = 0.5 * fresnel * reflect_colour;\n"
+"   vec3  light_sun      = max( CLEARSKIES_LIGHT_DOT_MIN, \n"
+"                               dot(normal,g_sun_dir.xyz)*0.75+0.25\n"
+"                           ) * g_sun_colour.rgb * g_day_phase;\n"
+"\n"
+"   float scaled_shadow = max( shadow, 1.0 - max(g_sun_dir.y,0.0) );\n"
+"   vec3 ambient = mix( g_ambient_colour.rgb, g_sunset_ambient.rgb, \n"
+"                       g_sunset_phase );\n"
+"\n"
+"   return ambient + (light_sun + sky_reflection) * shadow;\n"
+"}\n"
+"\n"
+"#line     44        0 \n"
+"\n"
+"float world_depth_sample( vec3 pos )\n"
+"{\n"
+"   vec2 depth_coord = (pos.xz - g_depth_bounds.xy) * g_depth_bounds.zw; \n"
+"   return texture( g_world_depth, depth_coord ).r;\n"
+"}\n"
+"\n"
+"float world_water_depth( vec3 pos )\n"
+"{\n"
+"   float ref_depth = g_water_plane.y*g_water_plane.w;\n"
+"   return world_depth_sample( pos ) - ref_depth;\n"
+"}\n"
+"\n"
+"float shadow_sample( vec3 co ){\n"
+"   float height_sample = world_depth_sample( co );\n"
+"\n"
+"   float fdelta = height_sample - co.y;\n"
+"   return clamp( fdelta, 0.2, 0.4 )-0.2;\n"
+"}\n"
+"\n"
+"float newlight_compute_sun_shadow( vec3 co, vec3 dir ){\n"
+"   if( g_shadow_samples == 0 ){\n"
+"      return 1.0;\n"
+"   }\n"
+"\n"
+"   float fspread = g_shadow_spread;\n"
+"   float flength = g_shadow_length;\n"
+"\n"
+"   float famt = 0.0;\n"
+"   famt += shadow_sample(co+(dir+vec3(-0.56,0.55, 0.30)*fspread)*flength*0.1);\n"
+"   famt += shadow_sample(co+(dir+vec3( 0.80,0.68, 0.34)*fspread)*flength*0.2);\n"
+"   famt += shadow_sample(co+(dir+vec3( 0.78,0.07,-0.06)*fspread)*flength*0.3);\n"
+"   famt += shadow_sample(co+(dir+vec3(-0.59,0.07,-0.42)*fspread)*flength*0.4);\n"
+"\n"
+"   //famt+=shadow_sample(co+(dir+vec3(-0.790,-0.933,-0.875)*fspread)*flength*0.5);\n"
+"   //famt+=shadow_sample(co+(dir+vec3( 0.807,-0.690, 0.472)*fspread)*flength*0.6);\n"
+"   //famt+=shadow_sample(co+(dir+vec3( 0.522,-0.379, 0.350)*fspread)*flength*0.7);\n"
+"   //famt+=shadow_sample(co+(dir+vec3( 0.483, 0.201, 0.306)*fspread)*flength*0.8);\n"
+"\n"
+"   return 1.0 - famt;\n"
+"}\n"
+"\n"
+"float newlight_specular( vec3 wnormal, vec3 dir, vec3 halfview, float exponent )\n"
+"{\n"
+"   vec3 specdir = reflect( -dir, wnormal );\n"
+"   return pow(max(dot( halfview, specdir ), 0.0), exponent);\n"
+"}\n"
+"\n"
+"vec3 scene_apply_fog( vec3 vfrag, vec3 colour, float fdist ){\n"
+"   float dist = pow(fdist*0.0010,0.78);\n"
+"   return mix( vfrag, colour, min( 1.0, dist ) );\n"
+"}\n"
+"\n"
+"vec3 scene_calculate_light( int light_index, \n"
+"                            vec3 halfview, vec3 co, vec3 normal )\n"
+"{\n"
+"   vec4 light_colour = texelFetch( uLightsArray, light_index+0 );\n"
+"   vec4 light_co     = texelFetch( uLightsArray, light_index+1 );\n"
+"   vec4 light_dir    = texelFetch( uLightsArray, light_index+2 );\n"
+"\n"
+"   vec3 light_delta = light_co.xyz-co;\n"
+"   float dist2 = dot(light_delta,light_delta);\n"
+"\n"
+"   light_delta = normalize( light_delta );\n"
+"\n"
+"   float quadratic = dist2*100.0;\n"
+"   float attenuation  = 1.0/( 1.0 + quadratic );\n"
+"         attenuation *= max( dot( light_delta, normal ), 0.0 );\n"
+"\n"
+"   float falloff = max( 0.0, 1.0-(dist2*light_co.w) );\n"
+"\n"
+"   if( light_dir.w < 0.999999 ){\n"
+"      float spot_theta = max( 0.0, dot( light_delta, -light_dir.xyz ) );\n"
+"      falloff *= max( 0.0, (spot_theta - light_dir.w) / (1.0-light_dir.w) );\n"
+"   }\n"
+"\n"
+"   return light_colour.rgb * attenuation * falloff \n"
+"            * step( g_day_phase, light_colour.w );\n"
+"}\n"
+"\n"
+"vec3 scene_calculate_packed_light_patch( uint packed_index, \n"
+"                                         vec3 halfview, vec3 co, vec3 normal )\n"
+"{\n"
+"   uint light_count = packed_index & 0x3u;\n"
+"\n"
+"   vec3 l = vec3(0.0);\n"
+"\n"
+"   if( light_count >= 1u ){\n"
+"      int index_0 = int( ((packed_index >>  2u) & 0x3ffu) * 3u );\n"
+"      int index_1 = int( ((packed_index >> 12u) & 0x3ffu) * 3u );\n"
+"      int index_2 = int( ((packed_index >> 22u) & 0x3ffu) * 3u );\n"
+"\n"
+"      l += scene_calculate_light( index_0, halfview, co, normal );\n"
+"\n"
+"      if( light_count >= 2u ){\n"
+"         l += scene_calculate_light( index_1, halfview, co, normal );\n"
+"\n"
+"         if( light_count >= 3u ){\n"
+"            l += scene_calculate_light( index_2, halfview, co, normal );\n"
+"         }\n"
+"      }\n"
+"   }\n"
+"\n"
+"   return l;\n"
+"}\n"
+"\n"
+"vec3 world_compute_lighting( vec3 diffuse, vec3 normal, vec3 co,\n"
+"                             float light_mask )\n"
+"{\n"
+"   if( g_light_preview == 1 )\n"
+"      diffuse = vec3(0.75);\n"
+"\n"
+"   // Lighting\n"
+"   vec3 halfview = uCamera - co;\n"
+"   float fdist = length(halfview);\n"
+"   halfview /= fdist;\n"
+"\n"
+"   float world_shadow = newlight_compute_sun_shadow( \n"
+"               co, g_sun_dir.xyz * (1.0/(max(g_sun_dir.y,0.0)+0.2)) );\n"
+"\n"
+"   vec3 total_light = clearskies_lighting( \n"
+"                           normal, min( light_mask, world_shadow ), halfview );\n"
+"\n"
+"   vec3 cube_coord = (co - g_cube_min.xyz) * g_cube_inv_range.xyz;\n"
+"        cube_coord = floor( cube_coord );\n"
+"\n"
+"   if( g_debug_indices == 1 )\n"
+"   {\n"
+"      return rand33(cube_coord);\n"
+"   }\n"
+"\n"
+"   if( g_debug_complexity == 1 )\n"
+"   {\n"
+"      ivec3 coord = ivec3( cube_coord );\n"
+"      uvec4 index_sample = texelFetch( uLightsIndex, coord, 0 );\n"
+"\n"
+"      uint light_count = (index_sample.x & 0x3u) + (index_sample.y & 0x3u);\n"
+"      return vec3( float(light_count)*(1.0/6.0), 0.0, 0.5 );\n"
+"   }\n"
+"\n"
+"   // FIXME: this coord should absolutely must be clamped!\n"
+"   \n"
+"   ivec3 coord = ivec3( cube_coord );\n"
+"   uvec4 index_sample = texelFetch( uLightsIndex, coord, 0 );\n"
+"\n"
+"   total_light += \n"
+"      scene_calculate_packed_light_patch( index_sample.x,\n"
+"                                          halfview, co, normal ) \n"
+"                                          * light_mask;\n"
+"   total_light += \n"
+"      scene_calculate_packed_light_patch( index_sample.y,\n"
+"                                          halfview, co, normal )\n"
+"                                          * light_mask;\n"
+"\n"
+"   // Take a section of the sky function to give us a matching fog colour\n"
+"\n"
+"   vec3 fog_colour  = clearskies_ambient( -halfview );\n"
+"   float sun_theta  = dot( -halfview, g_sun_dir.xyz );\n"
+"   float sun_size   = max( 0.0, sun_theta * 0.5 + 0.5 );\n"
+"   float sun_shape  = sun_size * max(g_sun_dir.y,0.0) * 0.5;\n"
+"         \n"
+"   vec3 sun_colour  = mix( vec3(1.0), g_sunset_colour.rgb, g_sunset_phase*0.5 );\n"
+"        sun_colour *= sun_shape;\n"
+"\n"
+"   fog_colour += sun_colour;\n"
+"   return scene_apply_fog( diffuse * total_light, fog_colour, fdist );\n"
+"}\n"
+"\n"
+"#line      9        0 \n"
+"\n"
+"float sdLine( vec3 p, vec3 a, vec3 b )\n"
+"{\n"
+"  vec3 pa = p - a;\n"
+"  vec3 ba = b - a;\n"
+"\n"
+"  float h = clamp( dot(pa,ba)/dot(ba,ba), 0.0, 1.0 );\n"
+"  return length( pa - ba*h );\n"
+"}\n"
+"\n"
+"float compute_board_shadow()\n"
+"{\n"
+"   // player shadow\n"
+"   float dist_to_player = max( 0.0, sdLine( aWorldCo, g_board_0.xyz,\n"
+"                                                      g_board_1.xyz )-0.1 );\n"
+"   float player_shadow = max( 1.0-dist_to_player*2.7, 0.0 );\n"
+"   player_shadow *= player_shadow*player_shadow*player_shadow;\n"
+"\n"
+"   return 1.0 - player_shadow*0.8;\n"
+"}\n"
+"\n"
+"vec3 scene_compute_lighting( vec3 diffuse, vec3 normal, vec3 co )\n"
+"{\n"
+"   return world_compute_lighting( diffuse, normal, co, compute_board_shadow() );\n"
+"}\n"
+"\n"
+"#line      7        0 \n"
+"#line       1        3 \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      8        0 \n"
+"\n"
+"void main()\n"
+"{\n"
+"   compute_motion_vectors();\n"
+"\n"
+"   vec3 vfrag = vec3(0.5,0.5,0.5);\n"
+"\n"
+"   // ws modulation\n"
+"   vec4 wgarbage = vec4(0.5,0.5,0.5,1.0);\n"
+"   \n"
+"   // Creating normal patches\n"
+"   vec3 modnorm = (wgarbage.rgb-0.4) * 1.4;\n"
+"   vec3 qnorm = normalize(floor(aNorm.xyz*4.0+modnorm)*0.25);\n"
+"   qnorm += vec3(0.001,0.0,0.0);\n"
+"\n"
+"   vec3 tangent0 = normalize(cross(qnorm,vec3(0.0,1.0,0.0)));\n"
+"   vec3 tangent1 = cross(qnorm,tangent0);\n"
+"   vec2 uvdiffuse = vec2( dot(tangent0,aCo), dot(tangent1,aCo) ) * 0.160;\n"
+"   \n"
+"   // Patch local noise\n"
+"   vec4 rgarbage = texture( uTexGarbage, uvdiffuse );\n"
+"\n"
+"   // Colour blending\n"
+"   float fblendclip = step(0.380,aNorm.w + (rgarbage.r-0.5)*-1.740)*0.320;\n"
+"   vec2 uvgradients = aUv + vec2( fblendclip, 0.0 );\n"
+"\n"
+"   vfrag = texture( uTexGradients, uvgradients ).rgb;\n"
+"   vfrag -= rgarbage.a*0.04;\n"
+"\n"
+"   if( g_light_preview == 1 )\n"
+"   {\n"
+"      vfrag = vec3(0.5);\n"
+"   }\n"
+"\n"
+"   vfrag = scene_compute_lighting( vfrag, qnorm, aWorldCo );\n"
+"   oColour = vec4(vfrag, 1.0);\n"
+"}\n"
+""},
+};
+
+GLuint _uniform_scene_vertex_blend_uMdl;
+GLuint _uniform_scene_vertex_blend_uPv;
+GLuint _uniform_scene_vertex_blend_uPvmPrev;
+GLuint _uniform_scene_vertex_blend_uTexGarbage;
+GLuint _uniform_scene_vertex_blend_uTexGradients;
+GLuint _uniform_scene_vertex_blend_uCamera;
+GLuint _uniform_scene_vertex_blend_g_world_depth;
+GLuint _uniform_scene_vertex_blend_uLightsArray;
+GLuint _uniform_scene_vertex_blend_uLightsIndex;
+#include "shaders/scene_terrain.h"
+struct vg_shader _shader_scene_terrain = {
+   .name = "scene_terrain",
+   .vs = 
+{
+.orig_file = "shaders/scene.vs",
+.static_src = 
+"layout (location=0) in vec3  a_co;\n"
+"layout (location=1) in vec4  a_norm;\n"
+"layout (location=2) in vec2  a_uv;\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      6        0 \n"
+"\n"
+"uniform mat4x3 uMdl;\n"
+"uniform mat4   uPv;\n"
+"uniform mat4   uPvmPrev;\n"
+"\n"
+"out vec2 aUv;\n"
+"out vec4 aNorm;\n"
+"out vec3 aCo;\n"
+"out vec3 aWorldCo;\n"
+"\n"
+"void main()\n"
+"{\n"
+"   vec3 world_pos0 = uMdl     * vec4( a_co, 1.0 );\n"
+"   vec4 vproj0     = uPv      * vec4( world_pos0, 1.0 );\n"
+"   vec4 vproj1     = uPvmPrev * vec4( a_co, 1.0 );\n"
+"\n"
+"   vs_motion_out( vproj0, vproj1 );\n"
+"\n"
+"   gl_Position = vproj0;\n"
+"\n"
+"   aUv = a_uv;\n"
+"   aNorm = vec4( mat3(uMdl) * a_norm.xyz, a_norm.w );\n"
+"   aCo = a_co;\n"
+"   aWorldCo = world_pos0;\n"
+"}\n"
+""},
+   .fs = 
+{
+.orig_file = "shaders/scene_terrain.fs",
+.static_src = 
+"uniform sampler2D uTexGarbage;\n"
+"uniform sampler2D uTexGradients;\n"
+"uniform vec3 uCamera;\n"
+"uniform vec3 uSandColour;\n"
+"uniform vec2 uBlendOffset;\n"
+"\n"
+"#line       1        1 \n"
+"// :D\n"
+"const float CLEARSKIES_LIGHT_DOT_MIN = 0.0;\n"
+"\n"
+"#line      8        0 \n"
+"#line       1        2 \n"
+"// :D\n"
+"\n"
+"in vec2 aUv;\n"
+"in vec4 aNorm;\n"
+"in vec3 aCo;\n"
+"in vec3 aWorldCo;\n"
+"\n"
+"#line       1        1 \n"
+"layout (location = 0) out vec4 oColour;\n"
+"\n"
+"// OpenGL wiki: Recommends do not use vec3 because of drivers. hence the v4s...\n"
+"layout (std140) uniform ub_world_lighting\n"
+"{\n"
+"   vec4 g_cube_min;\n"
+"   vec4 g_cube_inv_range;\n"
+"\n"
+"   vec4 g_water_plane;\n"
+"   vec4 g_depth_bounds;\n"
+"\n"
+"   vec4 g_daysky_colour;\n"
+"   vec4 g_nightsky_colour;\n"
+"   vec4 g_sunset_colour;\n"
+"   vec4 g_ambient_colour;\n"
+"   vec4 g_sunset_ambient;\n"
+"   vec4 g_sun_colour;\n"
+"   vec4 g_sun_dir;\n"
+"   vec4 g_board_0;\n"
+"   vec4 g_board_1;\n"
+"\n"
+"   float g_water_fog;\n"
+"   float g_time;\n"
+"   float g_realtime;\n"
+"   float g_shadow_length;\n"
+"   float g_shadow_spread;\n"
+"\n"
+"   float g_time_of_day;\n"
+"   float g_day_phase;\n"
+"   float g_sunset_phase;\n"
+"\n"
+"   int g_light_preview;\n"
+"   int g_shadow_samples;\n"
+"\n"
+"   int g_debug_indices;\n"
+"   int g_debug_complexity;\n"
+"};\n"
+"\n"
+"uniform sampler2D g_world_depth;\n"
+"uniform samplerBuffer uLightsArray;\n"
+"uniform usampler3D uLightsIndex;\n"
+"\n"
+"#line       1        1 \n"
+"//const vec3  DAYSKY_COLOUR   = vec3( 0.37, 0.54, 0.97 );\n"
+"//const vec3  NIGHTSKY_COLOUR = vec3( 0.03, 0.05, 0.20 );\n"
+"//const vec3  SUNSET_COLOUR   = vec3( 1.00, 0.32, 0.01 );\n"
+"//const vec3  AMBIENT_COLOUR  = vec3( 0.13, 0.17, 0.35 );\n"
+"//const vec3  SUNSET_AMBIENT  = vec3( 0.25, 0.17, 0.51 );\n"
+"//const vec3  SUN_COLOUR      = vec3( 1.10, 0.89, 0.35 );\n"
+"\n"
+"const float SUN_ANGLE       = 0.0001;\n"
+"const float PI              = 3.14159265358979323846264;\n"
+"\n"
+"//struct world_info\n"
+"//{\n"
+"//   float time,\n"
+"//         time_of_day,\n"
+"//         day_phase,\n"
+"//         sunset_phase;\n"
+"//   \n"
+"//   vec3 sun_dir;\n"
+"//};\n"
+"\n"
+"vec3 rand33(vec3 p3)\n"
+"{\n"
+"      p3 = fract(p3 * vec3(.1031, .1030, .0973));\n"
+"   p3 += dot(p3, p3.yxz+33.33);\n"
+"   return fract((p3.xxy + p3.yxx)*p3.zyx);\n"
+"}\n"
+"\n"
+"float stars( vec3 rd, float rr, float size ){\n"
+"   vec3 co = rd * rr;\n"
+"\n"
+"   float a = atan(co.y, length(co.xz)) + 4.0 * PI;\n"
+"\n"
+"   float spaces = 1.0 / rr;\n"
+"   size = (rr * 0.0015) * fwidth(a) * 1000.0 * size;\n"
+"   a -= mod(a, spaces) - spaces * 0.5;\n"
+"\n"
+"   float count = floor(sqrt(pow(rr, 2.0) * (1.0 - pow(sin(a), 2.0))) * 3.0);\n"
+"   \n"
+"   float plane = atan(co.z, co.x) + 4.0 * PI;\n"
+"   plane = plane - mod(plane, PI / count);\n"
+"\n"
+"   vec2 delta = rand33(vec3(plane, a, 0.0)).xy;\n"
+"\n"
+"   float level = sin(a + spaces * (delta.y - 0.5) * (1.0 - size)) * rr;\n"
+"   float ydist = sqrt(rr * rr - level * level);\n"
+"   float angle = plane + (PI * (delta.x * (1.0-size) + size * 0.5) / count);\n"
+"   vec3 center = vec3(cos(angle) * ydist, level, sin(angle) * ydist);\n"
+"   float star = smoothstep(size, 0.0, distance(center, co));\n"
+"   return star;\n"
+"}\n"
+"\n"
+"float luminance( vec3 v )\n"
+"{\n"
+"   return dot( v, vec3(0.2126, 0.7152, 0.0722) );\n"
+"}\n"
+"\n"
+"vec3 clearskies_ambient( vec3 dir )\n"
+"{\n"
+"   float sun_azimuth  = g_sunset_phase * (dot( dir.xz, g_sun_dir.xz )*0.4+0.6);\n"
+"   float sky_gradient = dir.y;\n"
+"   \n"
+"   /* Blend phase colours */\n"
+"   vec3 ambient  = g_daysky_colour.rgb   * (g_day_phase-g_sunset_phase*0.1);\n"
+"        ambient += g_sunset_colour.rgb   * (1.0-dir.y*0.5)*sun_azimuth;\n"
+"        ambient += g_nightsky_colour.rgb * (1.0-g_day_phase);\n"
+"   \n"
+"   /* Add gradient */\n"
+"        ambient -= sky_gradient * luminance(ambient);\n"
+"        \n"
+"   return ambient;\n"
+"}\n"
+"\n"
+"vec3 clearskies_sky( vec3 ray_dir )\n"
+"{\n"
+"   ray_dir.y = abs( ray_dir.y );\n"
+"   vec3 sky_colour  = clearskies_ambient( ray_dir );\n"
+"   \n"
+"   /* Sun */\n"
+"   float sun_theta  = dot( ray_dir, g_sun_dir.xyz );\n"
+"   float sun_size   = max( 0.0, sun_theta * 0.5 + 0.5 + SUN_ANGLE );\n"
+"   float sun_shape  = pow( sun_size, 2000.0 );\n"
+"         sun_shape += sun_size * max(g_sun_dir.y,0.0) * 0.5;\n"
+"         \n"
+"   vec3 sun_colour  = mix( vec3(1.0), g_sunset_colour.rgb, g_sunset_phase*0.5 );\n"
+"        sun_colour *= sun_shape;\n"
+"\n"
+"   \n"
+"   float star = 0.0;\n"
+"   float star_blend = 10.0*max(0.0,(1.0-g_day_phase*2.0));\n"
+"\n"
+"   if( star_blend > 0.001 ){\n"
+"      for( float j = 1.0; j <= 4.1; j += 1.0 ){\n"
+"         float m = mix(0.6, 0.9, smoothstep(1.0, 2.0, j));\n"
+"         star += stars( ray_dir, 1.94 * pow( 1.64, j ), m ) * (1.0/pow(4.0, j));\n"
+"      }\n"
+"   }\n"
+"   \n"
+"   vec3 composite   = sky_colour + sun_colour + star*star_blend;\n"
+"   return composite;\n"
+"}\n"
+"\n"
+"vec3 clearskies_lighting( vec3 normal, float shadow, vec3 halfview )\n"
+"{\n"
+"   float fresnel = 1.0 - abs(dot(normal,halfview));\n"
+"\n"
+"   vec3  reflect_colour = mix( g_daysky_colour.rgb, g_sunset_colour.rgb, \n"
+"                               g_sunset_phase );\n"
+"\n"
+"   vec3  sky_reflection = 0.5 * fresnel * reflect_colour;\n"
+"   vec3  light_sun      = max( CLEARSKIES_LIGHT_DOT_MIN, \n"
+"                               dot(normal,g_sun_dir.xyz)*0.75+0.25\n"
+"                           ) * g_sun_colour.rgb * g_day_phase;\n"
+"\n"
+"   float scaled_shadow = max( shadow, 1.0 - max(g_sun_dir.y,0.0) );\n"
+"   vec3 ambient = mix( g_ambient_colour.rgb, g_sunset_ambient.rgb, \n"
+"                       g_sunset_phase );\n"
+"\n"
+"   return ambient + (light_sun + sky_reflection) * shadow;\n"
+"}\n"
+"\n"
+"#line     44        0 \n"
+"\n"
+"float world_depth_sample( vec3 pos )\n"
+"{\n"
+"   vec2 depth_coord = (pos.xz - g_depth_bounds.xy) * g_depth_bounds.zw; \n"
+"   return texture( g_world_depth, depth_coord ).r;\n"
+"}\n"
+"\n"
+"float world_water_depth( vec3 pos )\n"
+"{\n"
+"   float ref_depth = g_water_plane.y*g_water_plane.w;\n"
+"   return world_depth_sample( pos ) - ref_depth;\n"
+"}\n"
+"\n"
+"float shadow_sample( vec3 co ){\n"
+"   float height_sample = world_depth_sample( co );\n"
+"\n"
+"   float fdelta = height_sample - co.y;\n"
+"   return clamp( fdelta, 0.2, 0.4 )-0.2;\n"
+"}\n"
+"\n"
+"float newlight_compute_sun_shadow( vec3 co, vec3 dir ){\n"
+"   if( g_shadow_samples == 0 ){\n"
+"      return 1.0;\n"
+"   }\n"
+"\n"
+"   float fspread = g_shadow_spread;\n"
+"   float flength = g_shadow_length;\n"
+"\n"
+"   float famt = 0.0;\n"
+"   famt += shadow_sample(co+(dir+vec3(-0.56,0.55, 0.30)*fspread)*flength*0.1);\n"
+"   famt += shadow_sample(co+(dir+vec3( 0.80,0.68, 0.34)*fspread)*flength*0.2);\n"
+"   famt += shadow_sample(co+(dir+vec3( 0.78,0.07,-0.06)*fspread)*flength*0.3);\n"
+"   famt += shadow_sample(co+(dir+vec3(-0.59,0.07,-0.42)*fspread)*flength*0.4);\n"
+"\n"
+"   //famt+=shadow_sample(co+(dir+vec3(-0.790,-0.933,-0.875)*fspread)*flength*0.5);\n"
+"   //famt+=shadow_sample(co+(dir+vec3( 0.807,-0.690, 0.472)*fspread)*flength*0.6);\n"
+"   //famt+=shadow_sample(co+(dir+vec3( 0.522,-0.379, 0.350)*fspread)*flength*0.7);\n"
+"   //famt+=shadow_sample(co+(dir+vec3( 0.483, 0.201, 0.306)*fspread)*flength*0.8);\n"
+"\n"
+"   return 1.0 - famt;\n"
+"}\n"
+"\n"
+"float newlight_specular( vec3 wnormal, vec3 dir, vec3 halfview, float exponent )\n"
+"{\n"
+"   vec3 specdir = reflect( -dir, wnormal );\n"
+"   return pow(max(dot( halfview, specdir ), 0.0), exponent);\n"
+"}\n"
+"\n"
+"vec3 scene_apply_fog( vec3 vfrag, vec3 colour, float fdist ){\n"
+"   float dist = pow(fdist*0.0010,0.78);\n"
+"   return mix( vfrag, colour, min( 1.0, dist ) );\n"
+"}\n"
+"\n"
+"vec3 scene_calculate_light( int light_index, \n"
+"                            vec3 halfview, vec3 co, vec3 normal )\n"
+"{\n"
+"   vec4 light_colour = texelFetch( uLightsArray, light_index+0 );\n"
+"   vec4 light_co     = texelFetch( uLightsArray, light_index+1 );\n"
+"   vec4 light_dir    = texelFetch( uLightsArray, light_index+2 );\n"
+"\n"
+"   vec3 light_delta = light_co.xyz-co;\n"
+"   float dist2 = dot(light_delta,light_delta);\n"
+"\n"
+"   light_delta = normalize( light_delta );\n"
+"\n"
+"   float quadratic = dist2*100.0;\n"
+"   float attenuation  = 1.0/( 1.0 + quadratic );\n"
+"         attenuation *= max( dot( light_delta, normal ), 0.0 );\n"
+"\n"
+"   float falloff = max( 0.0, 1.0-(dist2*light_co.w) );\n"
+"\n"
+"   if( light_dir.w < 0.999999 ){\n"
+"      float spot_theta = max( 0.0, dot( light_delta, -light_dir.xyz ) );\n"
+"      falloff *= max( 0.0, (spot_theta - light_dir.w) / (1.0-light_dir.w) );\n"
+"   }\n"
+"\n"
+"   return light_colour.rgb * attenuation * falloff \n"
+"            * step( g_day_phase, light_colour.w );\n"
+"}\n"
+"\n"
+"vec3 scene_calculate_packed_light_patch( uint packed_index, \n"
+"                                         vec3 halfview, vec3 co, vec3 normal )\n"
+"{\n"
+"   uint light_count = packed_index & 0x3u;\n"
+"\n"
+"   vec3 l = vec3(0.0);\n"
+"\n"
+"   if( light_count >= 1u ){\n"
+"      int index_0 = int( ((packed_index >>  2u) & 0x3ffu) * 3u );\n"
+"      int index_1 = int( ((packed_index >> 12u) & 0x3ffu) * 3u );\n"
+"      int index_2 = int( ((packed_index >> 22u) & 0x3ffu) * 3u );\n"
+"\n"
+"      l += scene_calculate_light( index_0, halfview, co, normal );\n"
+"\n"
+"      if( light_count >= 2u ){\n"
+"         l += scene_calculate_light( index_1, halfview, co, normal );\n"
+"\n"
+"         if( light_count >= 3u ){\n"
+"            l += scene_calculate_light( index_2, halfview, co, normal );\n"
+"         }\n"
+"      }\n"
+"   }\n"
+"\n"
+"   return l;\n"
+"}\n"
+"\n"
+"vec3 world_compute_lighting( vec3 diffuse, vec3 normal, vec3 co,\n"
+"                             float light_mask )\n"
+"{\n"
+"   if( g_light_preview == 1 )\n"
+"      diffuse = vec3(0.75);\n"
+"\n"
+"   // Lighting\n"
+"   vec3 halfview = uCamera - co;\n"
+"   float fdist = length(halfview);\n"
+"   halfview /= fdist;\n"
+"\n"
+"   float world_shadow = newlight_compute_sun_shadow( \n"
+"               co, g_sun_dir.xyz * (1.0/(max(g_sun_dir.y,0.0)+0.2)) );\n"
+"\n"
+"   vec3 total_light = clearskies_lighting( \n"
+"                           normal, min( light_mask, world_shadow ), halfview );\n"
+"\n"
+"   vec3 cube_coord = (co - g_cube_min.xyz) * g_cube_inv_range.xyz;\n"
+"        cube_coord = floor( cube_coord );\n"
+"\n"
+"   if( g_debug_indices == 1 )\n"
+"   {\n"
+"      return rand33(cube_coord);\n"
+"   }\n"
+"\n"
+"   if( g_debug_complexity == 1 )\n"
+"   {\n"
+"      ivec3 coord = ivec3( cube_coord );\n"
+"      uvec4 index_sample = texelFetch( uLightsIndex, coord, 0 );\n"
+"\n"
+"      uint light_count = (index_sample.x & 0x3u) + (index_sample.y & 0x3u);\n"
+"      return vec3( float(light_count)*(1.0/6.0), 0.0, 0.5 );\n"
+"   }\n"
+"\n"
+"   // FIXME: this coord should absolutely must be clamped!\n"
+"   \n"
+"   ivec3 coord = ivec3( cube_coord );\n"
+"   uvec4 index_sample = texelFetch( uLightsIndex, coord, 0 );\n"
+"\n"
+"   total_light += \n"
+"      scene_calculate_packed_light_patch( index_sample.x,\n"
+"                                          halfview, co, normal ) \n"
+"                                          * light_mask;\n"
+"   total_light += \n"
+"      scene_calculate_packed_light_patch( index_sample.y,\n"
+"                                          halfview, co, normal )\n"
+"                                          * light_mask;\n"
+"\n"
+"   // Take a section of the sky function to give us a matching fog colour\n"
+"\n"
+"   vec3 fog_colour  = clearskies_ambient( -halfview );\n"
+"   float sun_theta  = dot( -halfview, g_sun_dir.xyz );\n"
+"   float sun_size   = max( 0.0, sun_theta * 0.5 + 0.5 );\n"
+"   float sun_shape  = sun_size * max(g_sun_dir.y,0.0) * 0.5;\n"
+"         \n"
+"   vec3 sun_colour  = mix( vec3(1.0), g_sunset_colour.rgb, g_sunset_phase*0.5 );\n"
+"        sun_colour *= sun_shape;\n"
+"\n"
+"   fog_colour += sun_colour;\n"
+"   return scene_apply_fog( diffuse * total_light, fog_colour, fdist );\n"
+"}\n"
+"\n"
+"#line      9        0 \n"
+"\n"
+"float sdLine( vec3 p, vec3 a, vec3 b )\n"
+"{\n"
+"  vec3 pa = p - a;\n"
+"  vec3 ba = b - a;\n"
+"\n"
+"  float h = clamp( dot(pa,ba)/dot(ba,ba), 0.0, 1.0 );\n"
+"  return length( pa - ba*h );\n"
+"}\n"
+"\n"
+"float compute_board_shadow()\n"
+"{\n"
+"   // player shadow\n"
+"   float dist_to_player = max( 0.0, sdLine( aWorldCo, g_board_0.xyz,\n"
+"                                                      g_board_1.xyz )-0.1 );\n"
+"   float player_shadow = max( 1.0-dist_to_player*2.7, 0.0 );\n"
+"   player_shadow *= player_shadow*player_shadow*player_shadow;\n"
+"\n"
+"   return 1.0 - player_shadow*0.8;\n"
+"}\n"
+"\n"
+"vec3 scene_compute_lighting( vec3 diffuse, vec3 normal, vec3 co )\n"
+"{\n"
+"   return world_compute_lighting( diffuse, normal, co, compute_board_shadow() );\n"
+"}\n"
+"\n"
+"#line      9        0 \n"
+"#line       1        3 \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     10        0 \n"
+"\n"
+"void main()\n"
+"{\n"
+"   compute_motion_vectors();\n"
+"\n"
+"   // Colour\n"
+"   // ------\n"
+"   vec3 vfrag = vec3(0.5,0.5,0.5);\n"
+"\n"
+"   // ws modulation\n"
+"   vec4 wgarbage = texture( uTexGarbage, aCo.xz * 0.015 );\n"
+"   \n"
+"   // Creating normal patches\n"
+"   vec3 modnorm = (wgarbage.rgb-0.4) * 1.4;\n"
+"   vec3 qnorm = normalize(floor(aNorm.xyz*4.0+modnorm)*0.25);\n"
+"   qnorm += vec3(0.001,0.0,0.0);\n"
+"\n"
+"   vec2 dir = normalize(qnorm.xz);\n"
+"   vec2 uvdiffuse = aCo.xz * 0.02;\n"
+"   uvdiffuse = mat2(dir.y, dir.x, -dir.x, dir.y) * uvdiffuse;\n"
+"   \n"
+"   // Patch local noise\n"
+"   vec4 rgarbage = texture( uTexGarbage, uvdiffuse );\n"
+"\n"
+"   // Colour blending\n"
+"   float amtgrass = step(qnorm.y,0.6);\n"
+"   float amtsand = min(max((aCo.y - 10.0) * -0.1,0.0)*qnorm.y,1.0);\n"
+"   vec2 uvgradients = aUv + vec2( amtgrass + rgarbage.a*0.8 )*uBlendOffset;\n"
+"   vfrag = texture( uTexGradients, uvgradients ).rgb;\n"
+"   vfrag = mix( vfrag, uSandColour, amtsand );\n"
+"\n"
+"   qnorm = mix( qnorm, aNorm.xyz, amtsand );\n"
+"   \n"
+"   if( g_light_preview == 1 )\n"
+"   {\n"
+"      vfrag = vec3(0.5);\n"
+"   }\n"
+"\n"
+"   vfrag = scene_compute_lighting( vfrag, qnorm, aWorldCo );\n"
+"   oColour = vec4(vfrag, 1.0);\n"
+"}\n"
+""},
+};
+
+GLuint _uniform_scene_terrain_uMdl;
+GLuint _uniform_scene_terrain_uPv;
+GLuint _uniform_scene_terrain_uPvmPrev;
+GLuint _uniform_scene_terrain_uTexGarbage;
+GLuint _uniform_scene_terrain_uTexGradients;
+GLuint _uniform_scene_terrain_uCamera;
+GLuint _uniform_scene_terrain_uSandColour;
+GLuint _uniform_scene_terrain_uBlendOffset;
+GLuint _uniform_scene_terrain_g_world_depth;
+GLuint _uniform_scene_terrain_uLightsArray;
+GLuint _uniform_scene_terrain_uLightsIndex;
+#include "shaders/scene_route.h"
+struct vg_shader _shader_scene_route = {
+   .name = "scene_route",
+   .vs = 
+{
+.orig_file = "shaders/scene_override.vs",
+.static_src = 
+"layout (location=0) in vec3  a_co;\n"
+"layout (location=1) in vec4  a_norm;\n"
+"layout (location=2) in vec2  a_uv;\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      6        0 \n"
+"\n"
+"uniform mat4x3 uMdl;\n"
+"uniform mat4   uPv;\n"
+"uniform mat4   uPvmPrev;\n"
+"uniform mat3   uNormalMtx;\n"
+"\n"
+"out vec2 aUv;\n"
+"out vec4 aNorm;\n"
+"out vec3 aCo;\n"
+"out vec3 aWorldCo;\n"
+"\n"
+"void main()\n"
+"{\n"
+"   vec3 world_pos0 = uMdl     * vec4( a_co, 1.0 );\n"
+"   vec4 vproj0     = uPv      * vec4( world_pos0, 1.0 );\n"
+"   vec4 vproj1     = uPvmPrev * vec4( a_co, 1.0 );\n"
+"\n"
+"   vs_motion_out( vproj0, vproj1 );\n"
+"\n"
+"   gl_Position = vproj0;\n"
+"\n"
+"   aUv = a_uv;\n"
+"   aNorm = vec4( uNormalMtx * a_norm.xyz, a_norm.w );\n"
+"   aCo = a_co;\n"
+"   aWorldCo = world_pos0;\n"
+"}\n"
+""},
+   .fs = 
+{
+.orig_file = "shaders/scene_route.fs",
+.static_src = 
+"uniform sampler2D uTexGarbage;\n"
+"uniform sampler2D uTexGradients;\n"
+"uniform vec3 uCamera;\n"
+"uniform vec4 uColour;\n"
+"\n"
+"#line       1        1 \n"
+"// :D\n"
+"const float CLEARSKIES_LIGHT_DOT_MIN = 0.0;\n"
+"\n"
+"#line      7        0 \n"
+"#line       1        2 \n"
+"// :D\n"
+"\n"
+"in vec2 aUv;\n"
+"in vec4 aNorm;\n"
+"in vec3 aCo;\n"
+"in vec3 aWorldCo;\n"
+"\n"
+"#line       1        1 \n"
+"layout (location = 0) out vec4 oColour;\n"
+"\n"
+"// OpenGL wiki: Recommends do not use vec3 because of drivers. hence the v4s...\n"
+"layout (std140) uniform ub_world_lighting\n"
+"{\n"
+"   vec4 g_cube_min;\n"
+"   vec4 g_cube_inv_range;\n"
+"\n"
+"   vec4 g_water_plane;\n"
+"   vec4 g_depth_bounds;\n"
+"\n"
+"   vec4 g_daysky_colour;\n"
+"   vec4 g_nightsky_colour;\n"
+"   vec4 g_sunset_colour;\n"
+"   vec4 g_ambient_colour;\n"
+"   vec4 g_sunset_ambient;\n"
+"   vec4 g_sun_colour;\n"
+"   vec4 g_sun_dir;\n"
+"   vec4 g_board_0;\n"
+"   vec4 g_board_1;\n"
+"\n"
+"   float g_water_fog;\n"
+"   float g_time;\n"
+"   float g_realtime;\n"
+"   float g_shadow_length;\n"
+"   float g_shadow_spread;\n"
+"\n"
+"   float g_time_of_day;\n"
+"   float g_day_phase;\n"
+"   float g_sunset_phase;\n"
+"\n"
+"   int g_light_preview;\n"
+"   int g_shadow_samples;\n"
+"\n"
+"   int g_debug_indices;\n"
+"   int g_debug_complexity;\n"
+"};\n"
+"\n"
+"uniform sampler2D g_world_depth;\n"
+"uniform samplerBuffer uLightsArray;\n"
+"uniform usampler3D uLightsIndex;\n"
+"\n"
+"#line       1        1 \n"
+"//const vec3  DAYSKY_COLOUR   = vec3( 0.37, 0.54, 0.97 );\n"
+"//const vec3  NIGHTSKY_COLOUR = vec3( 0.03, 0.05, 0.20 );\n"
+"//const vec3  SUNSET_COLOUR   = vec3( 1.00, 0.32, 0.01 );\n"
+"//const vec3  AMBIENT_COLOUR  = vec3( 0.13, 0.17, 0.35 );\n"
+"//const vec3  SUNSET_AMBIENT  = vec3( 0.25, 0.17, 0.51 );\n"
+"//const vec3  SUN_COLOUR      = vec3( 1.10, 0.89, 0.35 );\n"
+"\n"
+"const float SUN_ANGLE       = 0.0001;\n"
+"const float PI              = 3.14159265358979323846264;\n"
+"\n"
+"//struct world_info\n"
+"//{\n"
+"//   float time,\n"
+"//         time_of_day,\n"
+"//         day_phase,\n"
+"//         sunset_phase;\n"
+"//   \n"
+"//   vec3 sun_dir;\n"
+"//};\n"
+"\n"
+"vec3 rand33(vec3 p3)\n"
+"{\n"
+"      p3 = fract(p3 * vec3(.1031, .1030, .0973));\n"
+"   p3 += dot(p3, p3.yxz+33.33);\n"
+"   return fract((p3.xxy + p3.yxx)*p3.zyx);\n"
+"}\n"
+"\n"
+"float stars( vec3 rd, float rr, float size ){\n"
+"   vec3 co = rd * rr;\n"
+"\n"
+"   float a = atan(co.y, length(co.xz)) + 4.0 * PI;\n"
+"\n"
+"   float spaces = 1.0 / rr;\n"
+"   size = (rr * 0.0015) * fwidth(a) * 1000.0 * size;\n"
+"   a -= mod(a, spaces) - spaces * 0.5;\n"
+"\n"
+"   float count = floor(sqrt(pow(rr, 2.0) * (1.0 - pow(sin(a), 2.0))) * 3.0);\n"
+"   \n"
+"   float plane = atan(co.z, co.x) + 4.0 * PI;\n"
+"   plane = plane - mod(plane, PI / count);\n"
+"\n"
+"   vec2 delta = rand33(vec3(plane, a, 0.0)).xy;\n"
+"\n"
+"   float level = sin(a + spaces * (delta.y - 0.5) * (1.0 - size)) * rr;\n"
+"   float ydist = sqrt(rr * rr - level * level);\n"
+"   float angle = plane + (PI * (delta.x * (1.0-size) + size * 0.5) / count);\n"
+"   vec3 center = vec3(cos(angle) * ydist, level, sin(angle) * ydist);\n"
+"   float star = smoothstep(size, 0.0, distance(center, co));\n"
+"   return star;\n"
+"}\n"
+"\n"
+"float luminance( vec3 v )\n"
+"{\n"
+"   return dot( v, vec3(0.2126, 0.7152, 0.0722) );\n"
+"}\n"
+"\n"
+"vec3 clearskies_ambient( vec3 dir )\n"
+"{\n"
+"   float sun_azimuth  = g_sunset_phase * (dot( dir.xz, g_sun_dir.xz )*0.4+0.6);\n"
+"   float sky_gradient = dir.y;\n"
+"   \n"
+"   /* Blend phase colours */\n"
+"   vec3 ambient  = g_daysky_colour.rgb   * (g_day_phase-g_sunset_phase*0.1);\n"
+"        ambient += g_sunset_colour.rgb   * (1.0-dir.y*0.5)*sun_azimuth;\n"
+"        ambient += g_nightsky_colour.rgb * (1.0-g_day_phase);\n"
+"   \n"
+"   /* Add gradient */\n"
+"        ambient -= sky_gradient * luminance(ambient);\n"
+"        \n"
+"   return ambient;\n"
+"}\n"
+"\n"
+"vec3 clearskies_sky( vec3 ray_dir )\n"
+"{\n"
+"   ray_dir.y = abs( ray_dir.y );\n"
+"   vec3 sky_colour  = clearskies_ambient( ray_dir );\n"
+"   \n"
+"   /* Sun */\n"
+"   float sun_theta  = dot( ray_dir, g_sun_dir.xyz );\n"
+"   float sun_size   = max( 0.0, sun_theta * 0.5 + 0.5 + SUN_ANGLE );\n"
+"   float sun_shape  = pow( sun_size, 2000.0 );\n"
+"         sun_shape += sun_size * max(g_sun_dir.y,0.0) * 0.5;\n"
+"         \n"
+"   vec3 sun_colour  = mix( vec3(1.0), g_sunset_colour.rgb, g_sunset_phase*0.5 );\n"
+"        sun_colour *= sun_shape;\n"
+"\n"
+"   \n"
+"   float star = 0.0;\n"
+"   float star_blend = 10.0*max(0.0,(1.0-g_day_phase*2.0));\n"
+"\n"
+"   if( star_blend > 0.001 ){\n"
+"      for( float j = 1.0; j <= 4.1; j += 1.0 ){\n"
+"         float m = mix(0.6, 0.9, smoothstep(1.0, 2.0, j));\n"
+"         star += stars( ray_dir, 1.94 * pow( 1.64, j ), m ) * (1.0/pow(4.0, j));\n"
+"      }\n"
+"   }\n"
+"   \n"
+"   vec3 composite   = sky_colour + sun_colour + star*star_blend;\n"
+"   return composite;\n"
+"}\n"
+"\n"
+"vec3 clearskies_lighting( vec3 normal, float shadow, vec3 halfview )\n"
+"{\n"
+"   float fresnel = 1.0 - abs(dot(normal,halfview));\n"
+"\n"
+"   vec3  reflect_colour = mix( g_daysky_colour.rgb, g_sunset_colour.rgb, \n"
+"                               g_sunset_phase );\n"
+"\n"
+"   vec3  sky_reflection = 0.5 * fresnel * reflect_colour;\n"
+"   vec3  light_sun      = max( CLEARSKIES_LIGHT_DOT_MIN, \n"
+"                               dot(normal,g_sun_dir.xyz)*0.75+0.25\n"
+"                           ) * g_sun_colour.rgb * g_day_phase;\n"
+"\n"
+"   float scaled_shadow = max( shadow, 1.0 - max(g_sun_dir.y,0.0) );\n"
+"   vec3 ambient = mix( g_ambient_colour.rgb, g_sunset_ambient.rgb, \n"
+"                       g_sunset_phase );\n"
+"\n"
+"   return ambient + (light_sun + sky_reflection) * shadow;\n"
+"}\n"
+"\n"
+"#line     44        0 \n"
+"\n"
+"float world_depth_sample( vec3 pos )\n"
+"{\n"
+"   vec2 depth_coord = (pos.xz - g_depth_bounds.xy) * g_depth_bounds.zw; \n"
+"   return texture( g_world_depth, depth_coord ).r;\n"
+"}\n"
+"\n"
+"float world_water_depth( vec3 pos )\n"
+"{\n"
+"   float ref_depth = g_water_plane.y*g_water_plane.w;\n"
+"   return world_depth_sample( pos ) - ref_depth;\n"
+"}\n"
+"\n"
+"float shadow_sample( vec3 co ){\n"
+"   float height_sample = world_depth_sample( co );\n"
+"\n"
+"   float fdelta = height_sample - co.y;\n"
+"   return clamp( fdelta, 0.2, 0.4 )-0.2;\n"
+"}\n"
+"\n"
+"float newlight_compute_sun_shadow( vec3 co, vec3 dir ){\n"
+"   if( g_shadow_samples == 0 ){\n"
+"      return 1.0;\n"
+"   }\n"
+"\n"
+"   float fspread = g_shadow_spread;\n"
+"   float flength = g_shadow_length;\n"
+"\n"
+"   float famt = 0.0;\n"
+"   famt += shadow_sample(co+(dir+vec3(-0.56,0.55, 0.30)*fspread)*flength*0.1);\n"
+"   famt += shadow_sample(co+(dir+vec3( 0.80,0.68, 0.34)*fspread)*flength*0.2);\n"
+"   famt += shadow_sample(co+(dir+vec3( 0.78,0.07,-0.06)*fspread)*flength*0.3);\n"
+"   famt += shadow_sample(co+(dir+vec3(-0.59,0.07,-0.42)*fspread)*flength*0.4);\n"
+"\n"
+"   //famt+=shadow_sample(co+(dir+vec3(-0.790,-0.933,-0.875)*fspread)*flength*0.5);\n"
+"   //famt+=shadow_sample(co+(dir+vec3( 0.807,-0.690, 0.472)*fspread)*flength*0.6);\n"
+"   //famt+=shadow_sample(co+(dir+vec3( 0.522,-0.379, 0.350)*fspread)*flength*0.7);\n"
+"   //famt+=shadow_sample(co+(dir+vec3( 0.483, 0.201, 0.306)*fspread)*flength*0.8);\n"
+"\n"
+"   return 1.0 - famt;\n"
+"}\n"
+"\n"
+"float newlight_specular( vec3 wnormal, vec3 dir, vec3 halfview, float exponent )\n"
+"{\n"
+"   vec3 specdir = reflect( -dir, wnormal );\n"
+"   return pow(max(dot( halfview, specdir ), 0.0), exponent);\n"
+"}\n"
+"\n"
+"vec3 scene_apply_fog( vec3 vfrag, vec3 colour, float fdist ){\n"
+"   float dist = pow(fdist*0.0010,0.78);\n"
+"   return mix( vfrag, colour, min( 1.0, dist ) );\n"
+"}\n"
+"\n"
+"vec3 scene_calculate_light( int light_index, \n"
+"                            vec3 halfview, vec3 co, vec3 normal )\n"
+"{\n"
+"   vec4 light_colour = texelFetch( uLightsArray, light_index+0 );\n"
+"   vec4 light_co     = texelFetch( uLightsArray, light_index+1 );\n"
+"   vec4 light_dir    = texelFetch( uLightsArray, light_index+2 );\n"
+"\n"
+"   vec3 light_delta = light_co.xyz-co;\n"
+"   float dist2 = dot(light_delta,light_delta);\n"
+"\n"
+"   light_delta = normalize( light_delta );\n"
+"\n"
+"   float quadratic = dist2*100.0;\n"
+"   float attenuation  = 1.0/( 1.0 + quadratic );\n"
+"         attenuation *= max( dot( light_delta, normal ), 0.0 );\n"
+"\n"
+"   float falloff = max( 0.0, 1.0-(dist2*light_co.w) );\n"
+"\n"
+"   if( light_dir.w < 0.999999 ){\n"
+"      float spot_theta = max( 0.0, dot( light_delta, -light_dir.xyz ) );\n"
+"      falloff *= max( 0.0, (spot_theta - light_dir.w) / (1.0-light_dir.w) );\n"
+"   }\n"
+"\n"
+"   return light_colour.rgb * attenuation * falloff \n"
+"            * step( g_day_phase, light_colour.w );\n"
+"}\n"
+"\n"
+"vec3 scene_calculate_packed_light_patch( uint packed_index, \n"
+"                                         vec3 halfview, vec3 co, vec3 normal )\n"
+"{\n"
+"   uint light_count = packed_index & 0x3u;\n"
+"\n"
+"   vec3 l = vec3(0.0);\n"
+"\n"
+"   if( light_count >= 1u ){\n"
+"      int index_0 = int( ((packed_index >>  2u) & 0x3ffu) * 3u );\n"
+"      int index_1 = int( ((packed_index >> 12u) & 0x3ffu) * 3u );\n"
+"      int index_2 = int( ((packed_index >> 22u) & 0x3ffu) * 3u );\n"
+"\n"
+"      l += scene_calculate_light( index_0, halfview, co, normal );\n"
+"\n"
+"      if( light_count >= 2u ){\n"
+"         l += scene_calculate_light( index_1, halfview, co, normal );\n"
+"\n"
+"         if( light_count >= 3u ){\n"
+"            l += scene_calculate_light( index_2, halfview, co, normal );\n"
+"         }\n"
+"      }\n"
+"   }\n"
+"\n"
+"   return l;\n"
+"}\n"
+"\n"
+"vec3 world_compute_lighting( vec3 diffuse, vec3 normal, vec3 co,\n"
+"                             float light_mask )\n"
+"{\n"
+"   if( g_light_preview == 1 )\n"
+"      diffuse = vec3(0.75);\n"
+"\n"
+"   // Lighting\n"
+"   vec3 halfview = uCamera - co;\n"
+"   float fdist = length(halfview);\n"
+"   halfview /= fdist;\n"
+"\n"
+"   float world_shadow = newlight_compute_sun_shadow( \n"
+"               co, g_sun_dir.xyz * (1.0/(max(g_sun_dir.y,0.0)+0.2)) );\n"
+"\n"
+"   vec3 total_light = clearskies_lighting( \n"
+"                           normal, min( light_mask, world_shadow ), halfview );\n"
+"\n"
+"   vec3 cube_coord = (co - g_cube_min.xyz) * g_cube_inv_range.xyz;\n"
+"        cube_coord = floor( cube_coord );\n"
+"\n"
+"   if( g_debug_indices == 1 )\n"
+"   {\n"
+"      return rand33(cube_coord);\n"
+"   }\n"
+"\n"
+"   if( g_debug_complexity == 1 )\n"
+"   {\n"
+"      ivec3 coord = ivec3( cube_coord );\n"
+"      uvec4 index_sample = texelFetch( uLightsIndex, coord, 0 );\n"
+"\n"
+"      uint light_count = (index_sample.x & 0x3u) + (index_sample.y & 0x3u);\n"
+"      return vec3( float(light_count)*(1.0/6.0), 0.0, 0.5 );\n"
+"   }\n"
+"\n"
+"   // FIXME: this coord should absolutely must be clamped!\n"
+"   \n"
+"   ivec3 coord = ivec3( cube_coord );\n"
+"   uvec4 index_sample = texelFetch( uLightsIndex, coord, 0 );\n"
+"\n"
+"   total_light += \n"
+"      scene_calculate_packed_light_patch( index_sample.x,\n"
+"                                          halfview, co, normal ) \n"
+"                                          * light_mask;\n"
+"   total_light += \n"
+"      scene_calculate_packed_light_patch( index_sample.y,\n"
+"                                          halfview, co, normal )\n"
+"                                          * light_mask;\n"
+"\n"
+"   // Take a section of the sky function to give us a matching fog colour\n"
+"\n"
+"   vec3 fog_colour  = clearskies_ambient( -halfview );\n"
+"   float sun_theta  = dot( -halfview, g_sun_dir.xyz );\n"
+"   float sun_size   = max( 0.0, sun_theta * 0.5 + 0.5 );\n"
+"   float sun_shape  = sun_size * max(g_sun_dir.y,0.0) * 0.5;\n"
+"         \n"
+"   vec3 sun_colour  = mix( vec3(1.0), g_sunset_colour.rgb, g_sunset_phase*0.5 );\n"
+"        sun_colour *= sun_shape;\n"
+"\n"
+"   fog_colour += sun_colour;\n"
+"   return scene_apply_fog( diffuse * total_light, fog_colour, fdist );\n"
+"}\n"
+"\n"
+"#line      9        0 \n"
+"\n"
+"float sdLine( vec3 p, vec3 a, vec3 b )\n"
+"{\n"
+"  vec3 pa = p - a;\n"
+"  vec3 ba = b - a;\n"
+"\n"
+"  float h = clamp( dot(pa,ba)/dot(ba,ba), 0.0, 1.0 );\n"
+"  return length( pa - ba*h );\n"
+"}\n"
+"\n"
+"float compute_board_shadow()\n"
+"{\n"
+"   // player shadow\n"
+"   float dist_to_player = max( 0.0, sdLine( aWorldCo, g_board_0.xyz,\n"
+"                                                      g_board_1.xyz )-0.1 );\n"
+"   float player_shadow = max( 1.0-dist_to_player*2.7, 0.0 );\n"
+"   player_shadow *= player_shadow*player_shadow*player_shadow;\n"
+"\n"
+"   return 1.0 - player_shadow*0.8;\n"
+"}\n"
+"\n"
+"vec3 scene_compute_lighting( vec3 diffuse, vec3 normal, vec3 co )\n"
+"{\n"
+"   return world_compute_lighting( diffuse, normal, co, compute_board_shadow() );\n"
+"}\n"
+"\n"
+"#line      8        0 \n"
+"#line       1        3 \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      9        0 \n"
+"\n"
+"float filtered_stripe( in float p, in float ddx, in float ddy )\n"
+"{\n"
+"   float w = max(abs(ddx), abs(ddy)) + 0.02;\n"
+"   float i = (abs(fract((p-0.5*w)/2.0)-0.5)-abs(fract((p+0.5*w)/2.0)-0.5))/w;\n"
+"   return 0.5 - i;\n"
+"}\n"
+"\n"
+"void main()\n"
+"{\n"
+"   compute_motion_vectors();\n"
+"\n"
+"   vec3 vfrag = vec3(0.5,0.5,0.5);\n"
+"\n"
+"   // ws modulation\n"
+"   vec4 wgarbage = texture( uTexGarbage, aCo.xz * 0.015 );\n"
+"\n"
+"   // Creating normal patches\n"
+"   vec3 modnorm = (wgarbage.rgb-0.4) * 1.4;\n"
+"   vec3 qnorm = normalize(floor(aNorm.xyz*4.0+modnorm)*0.25);\n"
+"   qnorm += vec3(0.001,0.0,0.0);\n"
+"\n"
+"   vec3 tangent0 = normalize(cross(qnorm,vec3(0.0,1.0,0.0)));\n"
+"   vec3 tangent1 = cross(qnorm,tangent0);\n"
+"   vec2 uvdiffuse = vec2( dot(tangent0,aCo), dot(tangent1,aCo) ) * 0.035;\n"
+"   \n"
+"   // Patch local noise\n"
+"   vec4 rgarbage = texture( uTexGarbage, uvdiffuse );\n"
+"\n"
+"   vfrag = pow(uColour.rgb,vec3(1.0/2.2));\n"
+"   vfrag -= rgarbage.a*0.1;\n"
+"\n"
+"   if( wgarbage.g < 0.1 )\n"
+"      discard;\n"
+"\n"
+"   float movep = (aUv.x + abs(aUv.y-0.5)*0.4 - g_realtime)*2.0;\n"
+"   float stripe = filtered_stripe( movep, dFdx(movep), dFdy(movep) );\n"
+"   vfrag *= 0.9+stripe*uColour.a; \n"
+"\n"
+"   if( g_light_preview == 1 )\n"
+"   {\n"
+"      vfrag = vec3(0.5);\n"
+"   }\n"
+"\n"
+"   // Lighting\n"
+"   oColour = vec4( scene_compute_lighting( vfrag, qnorm, aWorldCo ), 1.0 );\n"
+"}\n"
+""},
+};
+
+GLuint _uniform_scene_route_uMdl;
+GLuint _uniform_scene_route_uPv;
+GLuint _uniform_scene_route_uPvmPrev;
+GLuint _uniform_scene_route_uNormalMtx;
+GLuint _uniform_scene_route_uTexGarbage;
+GLuint _uniform_scene_route_uTexGradients;
+GLuint _uniform_scene_route_uCamera;
+GLuint _uniform_scene_route_uColour;
+GLuint _uniform_scene_route_g_world_depth;
+GLuint _uniform_scene_route_uLightsArray;
+GLuint _uniform_scene_route_uLightsIndex;
+#include "shaders/scene_depth.h"
+struct vg_shader _shader_scene_depth = {
+   .name = "scene_depth",
+   .vs = 
+{
+.orig_file = "shaders/scene.vs",
+.static_src = 
+"layout (location=0) in vec3  a_co;\n"
+"layout (location=1) in vec4  a_norm;\n"
+"layout (location=2) in vec2  a_uv;\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      6        0 \n"
+"\n"
+"uniform mat4x3 uMdl;\n"
+"uniform mat4   uPv;\n"
+"uniform mat4   uPvmPrev;\n"
+"\n"
+"out vec2 aUv;\n"
+"out vec4 aNorm;\n"
+"out vec3 aCo;\n"
+"out vec3 aWorldCo;\n"
+"\n"
+"void main()\n"
+"{\n"
+"   vec3 world_pos0 = uMdl     * vec4( a_co, 1.0 );\n"
+"   vec4 vproj0     = uPv      * vec4( world_pos0, 1.0 );\n"
+"   vec4 vproj1     = uPvmPrev * vec4( a_co, 1.0 );\n"
+"\n"
+"   vs_motion_out( vproj0, vproj1 );\n"
+"\n"
+"   gl_Position = vproj0;\n"
+"\n"
+"   aUv = a_uv;\n"
+"   aNorm = vec4( mat3(uMdl) * a_norm.xyz, a_norm.w );\n"
+"   aCo = a_co;\n"
+"   aWorldCo = world_pos0;\n"
+"}\n"
+""},
+   .fs = 
+{
+.orig_file = "shaders/scene_depth.fs",
+.static_src = 
+"out vec4 FragColor;\n"
+"\n"
+"uniform vec3 uCamera;\n"
+"uniform vec3 uBoard0;\n"
+"uniform vec3 uBoard1;\n"
+"\n"
+"#line       1        1 \n"
+"// :D\n"
+"const float CLEARSKIES_LIGHT_DOT_MIN = 0.0;\n"
+"\n"
+"#line      8        0 \n"
+"#line       1        2 \n"
+"// :D\n"
+"\n"
+"in vec2 aUv;\n"
+"in vec4 aNorm;\n"
+"in vec3 aCo;\n"
+"in vec3 aWorldCo;\n"
+"\n"
+"#line       1        1 \n"
+"layout (location = 0) out vec4 oColour;\n"
+"\n"
+"// OpenGL wiki: Recommends do not use vec3 because of drivers. hence the v4s...\n"
+"layout (std140) uniform ub_world_lighting\n"
+"{\n"
+"   vec4 g_cube_min;\n"
+"   vec4 g_cube_inv_range;\n"
+"\n"
+"   vec4 g_water_plane;\n"
+"   vec4 g_depth_bounds;\n"
+"\n"
+"   vec4 g_daysky_colour;\n"
+"   vec4 g_nightsky_colour;\n"
+"   vec4 g_sunset_colour;\n"
+"   vec4 g_ambient_colour;\n"
+"   vec4 g_sunset_ambient;\n"
+"   vec4 g_sun_colour;\n"
+"   vec4 g_sun_dir;\n"
+"   vec4 g_board_0;\n"
+"   vec4 g_board_1;\n"
+"\n"
+"   float g_water_fog;\n"
+"   float g_time;\n"
+"   float g_realtime;\n"
+"   float g_shadow_length;\n"
+"   float g_shadow_spread;\n"
+"\n"
+"   float g_time_of_day;\n"
+"   float g_day_phase;\n"
+"   float g_sunset_phase;\n"
+"\n"
+"   int g_light_preview;\n"
+"   int g_shadow_samples;\n"
+"\n"
+"   int g_debug_indices;\n"
+"   int g_debug_complexity;\n"
+"};\n"
+"\n"
+"uniform sampler2D g_world_depth;\n"
+"uniform samplerBuffer uLightsArray;\n"
+"uniform usampler3D uLightsIndex;\n"
+"\n"
+"#line       1        1 \n"
+"//const vec3  DAYSKY_COLOUR   = vec3( 0.37, 0.54, 0.97 );\n"
+"//const vec3  NIGHTSKY_COLOUR = vec3( 0.03, 0.05, 0.20 );\n"
+"//const vec3  SUNSET_COLOUR   = vec3( 1.00, 0.32, 0.01 );\n"
+"//const vec3  AMBIENT_COLOUR  = vec3( 0.13, 0.17, 0.35 );\n"
+"//const vec3  SUNSET_AMBIENT  = vec3( 0.25, 0.17, 0.51 );\n"
+"//const vec3  SUN_COLOUR      = vec3( 1.10, 0.89, 0.35 );\n"
+"\n"
+"const float SUN_ANGLE       = 0.0001;\n"
+"const float PI              = 3.14159265358979323846264;\n"
+"\n"
+"//struct world_info\n"
+"//{\n"
+"//   float time,\n"
+"//         time_of_day,\n"
+"//         day_phase,\n"
+"//         sunset_phase;\n"
+"//   \n"
+"//   vec3 sun_dir;\n"
+"//};\n"
+"\n"
+"vec3 rand33(vec3 p3)\n"
+"{\n"
+"      p3 = fract(p3 * vec3(.1031, .1030, .0973));\n"
+"   p3 += dot(p3, p3.yxz+33.33);\n"
+"   return fract((p3.xxy + p3.yxx)*p3.zyx);\n"
+"}\n"
+"\n"
+"float stars( vec3 rd, float rr, float size ){\n"
+"   vec3 co = rd * rr;\n"
+"\n"
+"   float a = atan(co.y, length(co.xz)) + 4.0 * PI;\n"
+"\n"
+"   float spaces = 1.0 / rr;\n"
+"   size = (rr * 0.0015) * fwidth(a) * 1000.0 * size;\n"
+"   a -= mod(a, spaces) - spaces * 0.5;\n"
+"\n"
+"   float count = floor(sqrt(pow(rr, 2.0) * (1.0 - pow(sin(a), 2.0))) * 3.0);\n"
+"   \n"
+"   float plane = atan(co.z, co.x) + 4.0 * PI;\n"
+"   plane = plane - mod(plane, PI / count);\n"
+"\n"
+"   vec2 delta = rand33(vec3(plane, a, 0.0)).xy;\n"
+"\n"
+"   float level = sin(a + spaces * (delta.y - 0.5) * (1.0 - size)) * rr;\n"
+"   float ydist = sqrt(rr * rr - level * level);\n"
+"   float angle = plane + (PI * (delta.x * (1.0-size) + size * 0.5) / count);\n"
+"   vec3 center = vec3(cos(angle) * ydist, level, sin(angle) * ydist);\n"
+"   float star = smoothstep(size, 0.0, distance(center, co));\n"
+"   return star;\n"
+"}\n"
+"\n"
+"float luminance( vec3 v )\n"
+"{\n"
+"   return dot( v, vec3(0.2126, 0.7152, 0.0722) );\n"
+"}\n"
+"\n"
+"vec3 clearskies_ambient( vec3 dir )\n"
+"{\n"
+"   float sun_azimuth  = g_sunset_phase * (dot( dir.xz, g_sun_dir.xz )*0.4+0.6);\n"
+"   float sky_gradient = dir.y;\n"
+"   \n"
+"   /* Blend phase colours */\n"
+"   vec3 ambient  = g_daysky_colour.rgb   * (g_day_phase-g_sunset_phase*0.1);\n"
+"        ambient += g_sunset_colour.rgb   * (1.0-dir.y*0.5)*sun_azimuth;\n"
+"        ambient += g_nightsky_colour.rgb * (1.0-g_day_phase);\n"
+"   \n"
+"   /* Add gradient */\n"
+"        ambient -= sky_gradient * luminance(ambient);\n"
+"        \n"
+"   return ambient;\n"
+"}\n"
+"\n"
+"vec3 clearskies_sky( vec3 ray_dir )\n"
+"{\n"
+"   ray_dir.y = abs( ray_dir.y );\n"
+"   vec3 sky_colour  = clearskies_ambient( ray_dir );\n"
+"   \n"
+"   /* Sun */\n"
+"   float sun_theta  = dot( ray_dir, g_sun_dir.xyz );\n"
+"   float sun_size   = max( 0.0, sun_theta * 0.5 + 0.5 + SUN_ANGLE );\n"
+"   float sun_shape  = pow( sun_size, 2000.0 );\n"
+"         sun_shape += sun_size * max(g_sun_dir.y,0.0) * 0.5;\n"
+"         \n"
+"   vec3 sun_colour  = mix( vec3(1.0), g_sunset_colour.rgb, g_sunset_phase*0.5 );\n"
+"        sun_colour *= sun_shape;\n"
+"\n"
+"   \n"
+"   float star = 0.0;\n"
+"   float star_blend = 10.0*max(0.0,(1.0-g_day_phase*2.0));\n"
+"\n"
+"   if( star_blend > 0.001 ){\n"
+"      for( float j = 1.0; j <= 4.1; j += 1.0 ){\n"
+"         float m = mix(0.6, 0.9, smoothstep(1.0, 2.0, j));\n"
+"         star += stars( ray_dir, 1.94 * pow( 1.64, j ), m ) * (1.0/pow(4.0, j));\n"
+"      }\n"
+"   }\n"
+"   \n"
+"   vec3 composite   = sky_colour + sun_colour + star*star_blend;\n"
+"   return composite;\n"
+"}\n"
+"\n"
+"vec3 clearskies_lighting( vec3 normal, float shadow, vec3 halfview )\n"
+"{\n"
+"   float fresnel = 1.0 - abs(dot(normal,halfview));\n"
+"\n"
+"   vec3  reflect_colour = mix( g_daysky_colour.rgb, g_sunset_colour.rgb, \n"
+"                               g_sunset_phase );\n"
+"\n"
+"   vec3  sky_reflection = 0.5 * fresnel * reflect_colour;\n"
+"   vec3  light_sun      = max( CLEARSKIES_LIGHT_DOT_MIN, \n"
+"                               dot(normal,g_sun_dir.xyz)*0.75+0.25\n"
+"                           ) * g_sun_colour.rgb * g_day_phase;\n"
+"\n"
+"   float scaled_shadow = max( shadow, 1.0 - max(g_sun_dir.y,0.0) );\n"
+"   vec3 ambient = mix( g_ambient_colour.rgb, g_sunset_ambient.rgb, \n"
+"                       g_sunset_phase );\n"
+"\n"
+"   return ambient + (light_sun + sky_reflection) * shadow;\n"
+"}\n"
+"\n"
+"#line     44        0 \n"
+"\n"
+"float world_depth_sample( vec3 pos )\n"
+"{\n"
+"   vec2 depth_coord = (pos.xz - g_depth_bounds.xy) * g_depth_bounds.zw; \n"
+"   return texture( g_world_depth, depth_coord ).r;\n"
+"}\n"
+"\n"
+"float world_water_depth( vec3 pos )\n"
+"{\n"
+"   float ref_depth = g_water_plane.y*g_water_plane.w;\n"
+"   return world_depth_sample( pos ) - ref_depth;\n"
+"}\n"
+"\n"
+"float shadow_sample( vec3 co ){\n"
+"   float height_sample = world_depth_sample( co );\n"
+"\n"
+"   float fdelta = height_sample - co.y;\n"
+"   return clamp( fdelta, 0.2, 0.4 )-0.2;\n"
+"}\n"
+"\n"
+"float newlight_compute_sun_shadow( vec3 co, vec3 dir ){\n"
+"   if( g_shadow_samples == 0 ){\n"
+"      return 1.0;\n"
+"   }\n"
+"\n"
+"   float fspread = g_shadow_spread;\n"
+"   float flength = g_shadow_length;\n"
+"\n"
+"   float famt = 0.0;\n"
+"   famt += shadow_sample(co+(dir+vec3(-0.56,0.55, 0.30)*fspread)*flength*0.1);\n"
+"   famt += shadow_sample(co+(dir+vec3( 0.80,0.68, 0.34)*fspread)*flength*0.2);\n"
+"   famt += shadow_sample(co+(dir+vec3( 0.78,0.07,-0.06)*fspread)*flength*0.3);\n"
+"   famt += shadow_sample(co+(dir+vec3(-0.59,0.07,-0.42)*fspread)*flength*0.4);\n"
+"\n"
+"   //famt+=shadow_sample(co+(dir+vec3(-0.790,-0.933,-0.875)*fspread)*flength*0.5);\n"
+"   //famt+=shadow_sample(co+(dir+vec3( 0.807,-0.690, 0.472)*fspread)*flength*0.6);\n"
+"   //famt+=shadow_sample(co+(dir+vec3( 0.522,-0.379, 0.350)*fspread)*flength*0.7);\n"
+"   //famt+=shadow_sample(co+(dir+vec3( 0.483, 0.201, 0.306)*fspread)*flength*0.8);\n"
+"\n"
+"   return 1.0 - famt;\n"
+"}\n"
+"\n"
+"float newlight_specular( vec3 wnormal, vec3 dir, vec3 halfview, float exponent )\n"
+"{\n"
+"   vec3 specdir = reflect( -dir, wnormal );\n"
+"   return pow(max(dot( halfview, specdir ), 0.0), exponent);\n"
+"}\n"
+"\n"
+"vec3 scene_apply_fog( vec3 vfrag, vec3 colour, float fdist ){\n"
+"   float dist = pow(fdist*0.0010,0.78);\n"
+"   return mix( vfrag, colour, min( 1.0, dist ) );\n"
+"}\n"
+"\n"
+"vec3 scene_calculate_light( int light_index, \n"
+"                            vec3 halfview, vec3 co, vec3 normal )\n"
+"{\n"
+"   vec4 light_colour = texelFetch( uLightsArray, light_index+0 );\n"
+"   vec4 light_co     = texelFetch( uLightsArray, light_index+1 );\n"
+"   vec4 light_dir    = texelFetch( uLightsArray, light_index+2 );\n"
+"\n"
+"   vec3 light_delta = light_co.xyz-co;\n"
+"   float dist2 = dot(light_delta,light_delta);\n"
+"\n"
+"   light_delta = normalize( light_delta );\n"
+"\n"
+"   float quadratic = dist2*100.0;\n"
+"   float attenuation  = 1.0/( 1.0 + quadratic );\n"
+"         attenuation *= max( dot( light_delta, normal ), 0.0 );\n"
+"\n"
+"   float falloff = max( 0.0, 1.0-(dist2*light_co.w) );\n"
+"\n"
+"   if( light_dir.w < 0.999999 ){\n"
+"      float spot_theta = max( 0.0, dot( light_delta, -light_dir.xyz ) );\n"
+"      falloff *= max( 0.0, (spot_theta - light_dir.w) / (1.0-light_dir.w) );\n"
+"   }\n"
+"\n"
+"   return light_colour.rgb * attenuation * falloff \n"
+"            * step( g_day_phase, light_colour.w );\n"
+"}\n"
+"\n"
+"vec3 scene_calculate_packed_light_patch( uint packed_index, \n"
+"                                         vec3 halfview, vec3 co, vec3 normal )\n"
+"{\n"
+"   uint light_count = packed_index & 0x3u;\n"
+"\n"
+"   vec3 l = vec3(0.0);\n"
+"\n"
+"   if( light_count >= 1u ){\n"
+"      int index_0 = int( ((packed_index >>  2u) & 0x3ffu) * 3u );\n"
+"      int index_1 = int( ((packed_index >> 12u) & 0x3ffu) * 3u );\n"
+"      int index_2 = int( ((packed_index >> 22u) & 0x3ffu) * 3u );\n"
+"\n"
+"      l += scene_calculate_light( index_0, halfview, co, normal );\n"
+"\n"
+"      if( light_count >= 2u ){\n"
+"         l += scene_calculate_light( index_1, halfview, co, normal );\n"
+"\n"
+"         if( light_count >= 3u ){\n"
+"            l += scene_calculate_light( index_2, halfview, co, normal );\n"
+"         }\n"
+"      }\n"
+"   }\n"
+"\n"
+"   return l;\n"
+"}\n"
+"\n"
+"vec3 world_compute_lighting( vec3 diffuse, vec3 normal, vec3 co,\n"
+"                             float light_mask )\n"
+"{\n"
+"   if( g_light_preview == 1 )\n"
+"      diffuse = vec3(0.75);\n"
+"\n"
+"   // Lighting\n"
+"   vec3 halfview = uCamera - co;\n"
+"   float fdist = length(halfview);\n"
+"   halfview /= fdist;\n"
+"\n"
+"   float world_shadow = newlight_compute_sun_shadow( \n"
+"               co, g_sun_dir.xyz * (1.0/(max(g_sun_dir.y,0.0)+0.2)) );\n"
+"\n"
+"   vec3 total_light = clearskies_lighting( \n"
+"                           normal, min( light_mask, world_shadow ), halfview );\n"
+"\n"
+"   vec3 cube_coord = (co - g_cube_min.xyz) * g_cube_inv_range.xyz;\n"
+"        cube_coord = floor( cube_coord );\n"
+"\n"
+"   if( g_debug_indices == 1 )\n"
+"   {\n"
+"      return rand33(cube_coord);\n"
+"   }\n"
+"\n"
+"   if( g_debug_complexity == 1 )\n"
+"   {\n"
+"      ivec3 coord = ivec3( cube_coord );\n"
+"      uvec4 index_sample = texelFetch( uLightsIndex, coord, 0 );\n"
+"\n"
+"      uint light_count = (index_sample.x & 0x3u) + (index_sample.y & 0x3u);\n"
+"      return vec3( float(light_count)*(1.0/6.0), 0.0, 0.5 );\n"
+"   }\n"
+"\n"
+"   // FIXME: this coord should absolutely must be clamped!\n"
+"   \n"
+"   ivec3 coord = ivec3( cube_coord );\n"
+"   uvec4 index_sample = texelFetch( uLightsIndex, coord, 0 );\n"
+"\n"
+"   total_light += \n"
+"      scene_calculate_packed_light_patch( index_sample.x,\n"
+"                                          halfview, co, normal ) \n"
+"                                          * light_mask;\n"
+"   total_light += \n"
+"      scene_calculate_packed_light_patch( index_sample.y,\n"
+"                                          halfview, co, normal )\n"
+"                                          * light_mask;\n"
+"\n"
+"   // Take a section of the sky function to give us a matching fog colour\n"
+"\n"
+"   vec3 fog_colour  = clearskies_ambient( -halfview );\n"
+"   float sun_theta  = dot( -halfview, g_sun_dir.xyz );\n"
+"   float sun_size   = max( 0.0, sun_theta * 0.5 + 0.5 );\n"
+"   float sun_shape  = sun_size * max(g_sun_dir.y,0.0) * 0.5;\n"
+"         \n"
+"   vec3 sun_colour  = mix( vec3(1.0), g_sunset_colour.rgb, g_sunset_phase*0.5 );\n"
+"        sun_colour *= sun_shape;\n"
+"\n"
+"   fog_colour += sun_colour;\n"
+"   return scene_apply_fog( diffuse * total_light, fog_colour, fdist );\n"
+"}\n"
+"\n"
+"#line      9        0 \n"
+"\n"
+"float sdLine( vec3 p, vec3 a, vec3 b )\n"
+"{\n"
+"  vec3 pa = p - a;\n"
+"  vec3 ba = b - a;\n"
+"\n"
+"  float h = clamp( dot(pa,ba)/dot(ba,ba), 0.0, 1.0 );\n"
+"  return length( pa - ba*h );\n"
+"}\n"
+"\n"
+"float compute_board_shadow()\n"
+"{\n"
+"   // player shadow\n"
+"   float dist_to_player = max( 0.0, sdLine( aWorldCo, g_board_0.xyz,\n"
+"                                                      g_board_1.xyz )-0.1 );\n"
+"   float player_shadow = max( 1.0-dist_to_player*2.7, 0.0 );\n"
+"   player_shadow *= player_shadow*player_shadow*player_shadow;\n"
+"\n"
+"   return 1.0 - player_shadow*0.8;\n"
+"}\n"
+"\n"
+"vec3 scene_compute_lighting( vec3 diffuse, vec3 normal, vec3 co )\n"
+"{\n"
+"   return world_compute_lighting( diffuse, normal, co, compute_board_shadow() );\n"
+"}\n"
+"\n"
+"#line      9        0 \n"
+"\n"
+"// Water blending\n"
+"// ==============\n"
+"\n"
+"float water_depth( vec3 pos, vec3 halfview )\n"
+"{\n"
+"   vec3 pnorm = g_water_plane.xyz;\n"
+"   float pdist = g_water_plane.w;\n"
+"\n"
+"   float d = dot( pnorm, halfview );\n"
+"   float t = dot((pnorm*pdist - pos), pnorm) / d;\n"
+"   return t * g_water_fog;\n"
+"}\n"
+"\n"
+"void main()\n"
+"{\n"
+"   vec3 halfview = normalize( uCamera - aWorldCo );\n"
+"   float depth = water_depth( aWorldCo, halfview );\n"
+"   FragColor = vec4( depth, 0.0, 0.0, 0.0 );\n"
+"}\n"
+""},
+};
+
+GLuint _uniform_scene_depth_uMdl;
+GLuint _uniform_scene_depth_uPv;
+GLuint _uniform_scene_depth_uPvmPrev;
+GLuint _uniform_scene_depth_uCamera;
+GLuint _uniform_scene_depth_uBoard0;
+GLuint _uniform_scene_depth_uBoard1;
+GLuint _uniform_scene_depth_g_world_depth;
+GLuint _uniform_scene_depth_uLightsArray;
+GLuint _uniform_scene_depth_uLightsIndex;
+#include "shaders/scene_position.h"
+struct vg_shader _shader_scene_position = {
+   .name = "scene_position",
+   .vs = 
+{
+.orig_file = "shaders/scene.vs",
+.static_src = 
+"layout (location=0) in vec3  a_co;\n"
+"layout (location=1) in vec4  a_norm;\n"
+"layout (location=2) in vec2  a_uv;\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      6        0 \n"
+"\n"
+"uniform mat4x3 uMdl;\n"
+"uniform mat4   uPv;\n"
+"uniform mat4   uPvmPrev;\n"
+"\n"
+"out vec2 aUv;\n"
+"out vec4 aNorm;\n"
+"out vec3 aCo;\n"
+"out vec3 aWorldCo;\n"
+"\n"
+"void main()\n"
+"{\n"
+"   vec3 world_pos0 = uMdl     * vec4( a_co, 1.0 );\n"
+"   vec4 vproj0     = uPv      * vec4( world_pos0, 1.0 );\n"
+"   vec4 vproj1     = uPvmPrev * vec4( a_co, 1.0 );\n"
+"\n"
+"   vs_motion_out( vproj0, vproj1 );\n"
+"\n"
+"   gl_Position = vproj0;\n"
+"\n"
+"   aUv = a_uv;\n"
+"   aNorm = vec4( mat3(uMdl) * a_norm.xyz, a_norm.w );\n"
+"   aCo = a_co;\n"
+"   aWorldCo = world_pos0;\n"
+"}\n"
+""},
+   .fs = 
+{
+.orig_file = "shaders/scene_position.fs",
+.static_src = 
+"out vec4 FragColor;\n"
+"\n"
+"uniform vec3 uCamera;\n"
+"uniform vec3 uBoard0;\n"
+"uniform vec3 uBoard1;\n"
+"\n"
+"#line       1        1 \n"
+"// :D\n"
+"const float CLEARSKIES_LIGHT_DOT_MIN = 0.0;\n"
+"\n"
+"#line      8        0 \n"
+"#line       1        2 \n"
+"// :D\n"
+"\n"
+"in vec2 aUv;\n"
+"in vec4 aNorm;\n"
+"in vec3 aCo;\n"
+"in vec3 aWorldCo;\n"
+"\n"
+"#line       1        1 \n"
+"layout (location = 0) out vec4 oColour;\n"
+"\n"
+"// OpenGL wiki: Recommends do not use vec3 because of drivers. hence the v4s...\n"
+"layout (std140) uniform ub_world_lighting\n"
+"{\n"
+"   vec4 g_cube_min;\n"
+"   vec4 g_cube_inv_range;\n"
+"\n"
+"   vec4 g_water_plane;\n"
+"   vec4 g_depth_bounds;\n"
+"\n"
+"   vec4 g_daysky_colour;\n"
+"   vec4 g_nightsky_colour;\n"
+"   vec4 g_sunset_colour;\n"
+"   vec4 g_ambient_colour;\n"
+"   vec4 g_sunset_ambient;\n"
+"   vec4 g_sun_colour;\n"
+"   vec4 g_sun_dir;\n"
+"   vec4 g_board_0;\n"
+"   vec4 g_board_1;\n"
+"\n"
+"   float g_water_fog;\n"
+"   float g_time;\n"
+"   float g_realtime;\n"
+"   float g_shadow_length;\n"
+"   float g_shadow_spread;\n"
+"\n"
+"   float g_time_of_day;\n"
+"   float g_day_phase;\n"
+"   float g_sunset_phase;\n"
+"\n"
+"   int g_light_preview;\n"
+"   int g_shadow_samples;\n"
+"\n"
+"   int g_debug_indices;\n"
+"   int g_debug_complexity;\n"
+"};\n"
+"\n"
+"uniform sampler2D g_world_depth;\n"
+"uniform samplerBuffer uLightsArray;\n"
+"uniform usampler3D uLightsIndex;\n"
+"\n"
+"#line       1        1 \n"
+"//const vec3  DAYSKY_COLOUR   = vec3( 0.37, 0.54, 0.97 );\n"
+"//const vec3  NIGHTSKY_COLOUR = vec3( 0.03, 0.05, 0.20 );\n"
+"//const vec3  SUNSET_COLOUR   = vec3( 1.00, 0.32, 0.01 );\n"
+"//const vec3  AMBIENT_COLOUR  = vec3( 0.13, 0.17, 0.35 );\n"
+"//const vec3  SUNSET_AMBIENT  = vec3( 0.25, 0.17, 0.51 );\n"
+"//const vec3  SUN_COLOUR      = vec3( 1.10, 0.89, 0.35 );\n"
+"\n"
+"const float SUN_ANGLE       = 0.0001;\n"
+"const float PI              = 3.14159265358979323846264;\n"
+"\n"
+"//struct world_info\n"
+"//{\n"
+"//   float time,\n"
+"//         time_of_day,\n"
+"//         day_phase,\n"
+"//         sunset_phase;\n"
+"//   \n"
+"//   vec3 sun_dir;\n"
+"//};\n"
+"\n"
+"vec3 rand33(vec3 p3)\n"
+"{\n"
+"      p3 = fract(p3 * vec3(.1031, .1030, .0973));\n"
+"   p3 += dot(p3, p3.yxz+33.33);\n"
+"   return fract((p3.xxy + p3.yxx)*p3.zyx);\n"
+"}\n"
+"\n"
+"float stars( vec3 rd, float rr, float size ){\n"
+"   vec3 co = rd * rr;\n"
+"\n"
+"   float a = atan(co.y, length(co.xz)) + 4.0 * PI;\n"
+"\n"
+"   float spaces = 1.0 / rr;\n"
+"   size = (rr * 0.0015) * fwidth(a) * 1000.0 * size;\n"
+"   a -= mod(a, spaces) - spaces * 0.5;\n"
+"\n"
+"   float count = floor(sqrt(pow(rr, 2.0) * (1.0 - pow(sin(a), 2.0))) * 3.0);\n"
+"   \n"
+"   float plane = atan(co.z, co.x) + 4.0 * PI;\n"
+"   plane = plane - mod(plane, PI / count);\n"
+"\n"
+"   vec2 delta = rand33(vec3(plane, a, 0.0)).xy;\n"
+"\n"
+"   float level = sin(a + spaces * (delta.y - 0.5) * (1.0 - size)) * rr;\n"
+"   float ydist = sqrt(rr * rr - level * level);\n"
+"   float angle = plane + (PI * (delta.x * (1.0-size) + size * 0.5) / count);\n"
+"   vec3 center = vec3(cos(angle) * ydist, level, sin(angle) * ydist);\n"
+"   float star = smoothstep(size, 0.0, distance(center, co));\n"
+"   return star;\n"
+"}\n"
+"\n"
+"float luminance( vec3 v )\n"
+"{\n"
+"   return dot( v, vec3(0.2126, 0.7152, 0.0722) );\n"
+"}\n"
+"\n"
+"vec3 clearskies_ambient( vec3 dir )\n"
+"{\n"
+"   float sun_azimuth  = g_sunset_phase * (dot( dir.xz, g_sun_dir.xz )*0.4+0.6);\n"
+"   float sky_gradient = dir.y;\n"
+"   \n"
+"   /* Blend phase colours */\n"
+"   vec3 ambient  = g_daysky_colour.rgb   * (g_day_phase-g_sunset_phase*0.1);\n"
+"        ambient += g_sunset_colour.rgb   * (1.0-dir.y*0.5)*sun_azimuth;\n"
+"        ambient += g_nightsky_colour.rgb * (1.0-g_day_phase);\n"
+"   \n"
+"   /* Add gradient */\n"
+"        ambient -= sky_gradient * luminance(ambient);\n"
+"        \n"
+"   return ambient;\n"
+"}\n"
+"\n"
+"vec3 clearskies_sky( vec3 ray_dir )\n"
+"{\n"
+"   ray_dir.y = abs( ray_dir.y );\n"
+"   vec3 sky_colour  = clearskies_ambient( ray_dir );\n"
+"   \n"
+"   /* Sun */\n"
+"   float sun_theta  = dot( ray_dir, g_sun_dir.xyz );\n"
+"   float sun_size   = max( 0.0, sun_theta * 0.5 + 0.5 + SUN_ANGLE );\n"
+"   float sun_shape  = pow( sun_size, 2000.0 );\n"
+"         sun_shape += sun_size * max(g_sun_dir.y,0.0) * 0.5;\n"
+"         \n"
+"   vec3 sun_colour  = mix( vec3(1.0), g_sunset_colour.rgb, g_sunset_phase*0.5 );\n"
+"        sun_colour *= sun_shape;\n"
+"\n"
+"   \n"
+"   float star = 0.0;\n"
+"   float star_blend = 10.0*max(0.0,(1.0-g_day_phase*2.0));\n"
+"\n"
+"   if( star_blend > 0.001 ){\n"
+"      for( float j = 1.0; j <= 4.1; j += 1.0 ){\n"
+"         float m = mix(0.6, 0.9, smoothstep(1.0, 2.0, j));\n"
+"         star += stars( ray_dir, 1.94 * pow( 1.64, j ), m ) * (1.0/pow(4.0, j));\n"
+"      }\n"
+"   }\n"
+"   \n"
+"   vec3 composite   = sky_colour + sun_colour + star*star_blend;\n"
+"   return composite;\n"
+"}\n"
+"\n"
+"vec3 clearskies_lighting( vec3 normal, float shadow, vec3 halfview )\n"
+"{\n"
+"   float fresnel = 1.0 - abs(dot(normal,halfview));\n"
+"\n"
+"   vec3  reflect_colour = mix( g_daysky_colour.rgb, g_sunset_colour.rgb, \n"
+"                               g_sunset_phase );\n"
+"\n"
+"   vec3  sky_reflection = 0.5 * fresnel * reflect_colour;\n"
+"   vec3  light_sun      = max( CLEARSKIES_LIGHT_DOT_MIN, \n"
+"                               dot(normal,g_sun_dir.xyz)*0.75+0.25\n"
+"                           ) * g_sun_colour.rgb * g_day_phase;\n"
+"\n"
+"   float scaled_shadow = max( shadow, 1.0 - max(g_sun_dir.y,0.0) );\n"
+"   vec3 ambient = mix( g_ambient_colour.rgb, g_sunset_ambient.rgb, \n"
+"                       g_sunset_phase );\n"
+"\n"
+"   return ambient + (light_sun + sky_reflection) * shadow;\n"
+"}\n"
+"\n"
+"#line     44        0 \n"
+"\n"
+"float world_depth_sample( vec3 pos )\n"
+"{\n"
+"   vec2 depth_coord = (pos.xz - g_depth_bounds.xy) * g_depth_bounds.zw; \n"
+"   return texture( g_world_depth, depth_coord ).r;\n"
+"}\n"
+"\n"
+"float world_water_depth( vec3 pos )\n"
+"{\n"
+"   float ref_depth = g_water_plane.y*g_water_plane.w;\n"
+"   return world_depth_sample( pos ) - ref_depth;\n"
+"}\n"
+"\n"
+"float shadow_sample( vec3 co ){\n"
+"   float height_sample = world_depth_sample( co );\n"
+"\n"
+"   float fdelta = height_sample - co.y;\n"
+"   return clamp( fdelta, 0.2, 0.4 )-0.2;\n"
+"}\n"
+"\n"
+"float newlight_compute_sun_shadow( vec3 co, vec3 dir ){\n"
+"   if( g_shadow_samples == 0 ){\n"
+"      return 1.0;\n"
+"   }\n"
+"\n"
+"   float fspread = g_shadow_spread;\n"
+"   float flength = g_shadow_length;\n"
+"\n"
+"   float famt = 0.0;\n"
+"   famt += shadow_sample(co+(dir+vec3(-0.56,0.55, 0.30)*fspread)*flength*0.1);\n"
+"   famt += shadow_sample(co+(dir+vec3( 0.80,0.68, 0.34)*fspread)*flength*0.2);\n"
+"   famt += shadow_sample(co+(dir+vec3( 0.78,0.07,-0.06)*fspread)*flength*0.3);\n"
+"   famt += shadow_sample(co+(dir+vec3(-0.59,0.07,-0.42)*fspread)*flength*0.4);\n"
+"\n"
+"   //famt+=shadow_sample(co+(dir+vec3(-0.790,-0.933,-0.875)*fspread)*flength*0.5);\n"
+"   //famt+=shadow_sample(co+(dir+vec3( 0.807,-0.690, 0.472)*fspread)*flength*0.6);\n"
+"   //famt+=shadow_sample(co+(dir+vec3( 0.522,-0.379, 0.350)*fspread)*flength*0.7);\n"
+"   //famt+=shadow_sample(co+(dir+vec3( 0.483, 0.201, 0.306)*fspread)*flength*0.8);\n"
+"\n"
+"   return 1.0 - famt;\n"
+"}\n"
+"\n"
+"float newlight_specular( vec3 wnormal, vec3 dir, vec3 halfview, float exponent )\n"
+"{\n"
+"   vec3 specdir = reflect( -dir, wnormal );\n"
+"   return pow(max(dot( halfview, specdir ), 0.0), exponent);\n"
+"}\n"
+"\n"
+"vec3 scene_apply_fog( vec3 vfrag, vec3 colour, float fdist ){\n"
+"   float dist = pow(fdist*0.0010,0.78);\n"
+"   return mix( vfrag, colour, min( 1.0, dist ) );\n"
+"}\n"
+"\n"
+"vec3 scene_calculate_light( int light_index, \n"
+"                            vec3 halfview, vec3 co, vec3 normal )\n"
+"{\n"
+"   vec4 light_colour = texelFetch( uLightsArray, light_index+0 );\n"
+"   vec4 light_co     = texelFetch( uLightsArray, light_index+1 );\n"
+"   vec4 light_dir    = texelFetch( uLightsArray, light_index+2 );\n"
+"\n"
+"   vec3 light_delta = light_co.xyz-co;\n"
+"   float dist2 = dot(light_delta,light_delta);\n"
+"\n"
+"   light_delta = normalize( light_delta );\n"
+"\n"
+"   float quadratic = dist2*100.0;\n"
+"   float attenuation  = 1.0/( 1.0 + quadratic );\n"
+"         attenuation *= max( dot( light_delta, normal ), 0.0 );\n"
+"\n"
+"   float falloff = max( 0.0, 1.0-(dist2*light_co.w) );\n"
+"\n"
+"   if( light_dir.w < 0.999999 ){\n"
+"      float spot_theta = max( 0.0, dot( light_delta, -light_dir.xyz ) );\n"
+"      falloff *= max( 0.0, (spot_theta - light_dir.w) / (1.0-light_dir.w) );\n"
+"   }\n"
+"\n"
+"   return light_colour.rgb * attenuation * falloff \n"
+"            * step( g_day_phase, light_colour.w );\n"
+"}\n"
+"\n"
+"vec3 scene_calculate_packed_light_patch( uint packed_index, \n"
+"                                         vec3 halfview, vec3 co, vec3 normal )\n"
+"{\n"
+"   uint light_count = packed_index & 0x3u;\n"
+"\n"
+"   vec3 l = vec3(0.0);\n"
+"\n"
+"   if( light_count >= 1u ){\n"
+"      int index_0 = int( ((packed_index >>  2u) & 0x3ffu) * 3u );\n"
+"      int index_1 = int( ((packed_index >> 12u) & 0x3ffu) * 3u );\n"
+"      int index_2 = int( ((packed_index >> 22u) & 0x3ffu) * 3u );\n"
+"\n"
+"      l += scene_calculate_light( index_0, halfview, co, normal );\n"
+"\n"
+"      if( light_count >= 2u ){\n"
+"         l += scene_calculate_light( index_1, halfview, co, normal );\n"
+"\n"
+"         if( light_count >= 3u ){\n"
+"            l += scene_calculate_light( index_2, halfview, co, normal );\n"
+"         }\n"
+"      }\n"
+"   }\n"
+"\n"
+"   return l;\n"
+"}\n"
+"\n"
+"vec3 world_compute_lighting( vec3 diffuse, vec3 normal, vec3 co,\n"
+"                             float light_mask )\n"
+"{\n"
+"   if( g_light_preview == 1 )\n"
+"      diffuse = vec3(0.75);\n"
+"\n"
+"   // Lighting\n"
+"   vec3 halfview = uCamera - co;\n"
+"   float fdist = length(halfview);\n"
+"   halfview /= fdist;\n"
+"\n"
+"   float world_shadow = newlight_compute_sun_shadow( \n"
+"               co, g_sun_dir.xyz * (1.0/(max(g_sun_dir.y,0.0)+0.2)) );\n"
+"\n"
+"   vec3 total_light = clearskies_lighting( \n"
+"                           normal, min( light_mask, world_shadow ), halfview );\n"
+"\n"
+"   vec3 cube_coord = (co - g_cube_min.xyz) * g_cube_inv_range.xyz;\n"
+"        cube_coord = floor( cube_coord );\n"
+"\n"
+"   if( g_debug_indices == 1 )\n"
+"   {\n"
+"      return rand33(cube_coord);\n"
+"   }\n"
+"\n"
+"   if( g_debug_complexity == 1 )\n"
+"   {\n"
+"      ivec3 coord = ivec3( cube_coord );\n"
+"      uvec4 index_sample = texelFetch( uLightsIndex, coord, 0 );\n"
+"\n"
+"      uint light_count = (index_sample.x & 0x3u) + (index_sample.y & 0x3u);\n"
+"      return vec3( float(light_count)*(1.0/6.0), 0.0, 0.5 );\n"
+"   }\n"
+"\n"
+"   // FIXME: this coord should absolutely must be clamped!\n"
+"   \n"
+"   ivec3 coord = ivec3( cube_coord );\n"
+"   uvec4 index_sample = texelFetch( uLightsIndex, coord, 0 );\n"
+"\n"
+"   total_light += \n"
+"      scene_calculate_packed_light_patch( index_sample.x,\n"
+"                                          halfview, co, normal ) \n"
+"                                          * light_mask;\n"
+"   total_light += \n"
+"      scene_calculate_packed_light_patch( index_sample.y,\n"
+"                                          halfview, co, normal )\n"
+"                                          * light_mask;\n"
+"\n"
+"   // Take a section of the sky function to give us a matching fog colour\n"
+"\n"
+"   vec3 fog_colour  = clearskies_ambient( -halfview );\n"
+"   float sun_theta  = dot( -halfview, g_sun_dir.xyz );\n"
+"   float sun_size   = max( 0.0, sun_theta * 0.5 + 0.5 );\n"
+"   float sun_shape  = sun_size * max(g_sun_dir.y,0.0) * 0.5;\n"
+"         \n"
+"   vec3 sun_colour  = mix( vec3(1.0), g_sunset_colour.rgb, g_sunset_phase*0.5 );\n"
+"        sun_colour *= sun_shape;\n"
+"\n"
+"   fog_colour += sun_colour;\n"
+"   return scene_apply_fog( diffuse * total_light, fog_colour, fdist );\n"
+"}\n"
+"\n"
+"#line      9        0 \n"
+"\n"
+"float sdLine( vec3 p, vec3 a, vec3 b )\n"
+"{\n"
+"  vec3 pa = p - a;\n"
+"  vec3 ba = b - a;\n"
+"\n"
+"  float h = clamp( dot(pa,ba)/dot(ba,ba), 0.0, 1.0 );\n"
+"  return length( pa - ba*h );\n"
+"}\n"
+"\n"
+"float compute_board_shadow()\n"
+"{\n"
+"   // player shadow\n"
+"   float dist_to_player = max( 0.0, sdLine( aWorldCo, g_board_0.xyz,\n"
+"                                                      g_board_1.xyz )-0.1 );\n"
+"   float player_shadow = max( 1.0-dist_to_player*2.7, 0.0 );\n"
+"   player_shadow *= player_shadow*player_shadow*player_shadow;\n"
+"\n"
+"   return 1.0 - player_shadow*0.8;\n"
+"}\n"
+"\n"
+"vec3 scene_compute_lighting( vec3 diffuse, vec3 normal, vec3 co )\n"
+"{\n"
+"   return world_compute_lighting( diffuse, normal, co, compute_board_shadow() );\n"
+"}\n"
+"\n"
+"#line      9        0 \n"
+"\n"
+"void main()\n"
+"{\n"
+"   float height_full = aWorldCo.y;\n"
+"   float height_water = height_full;\n"
+"\n"
+"   if( height_water > (g_water_plane.y * g_water_plane.w) + 2.0 )\n"
+"      height_water = -99999.9;\n"
+"\n"
+"   FragColor = vec4( height_full, height_water, 0.0, 0.0 );\n"
+"}\n"
+""},
+};
+
+GLuint _uniform_scene_position_uMdl;
+GLuint _uniform_scene_position_uPv;
+GLuint _uniform_scene_position_uPvmPrev;
+GLuint _uniform_scene_position_uCamera;
+GLuint _uniform_scene_position_uBoard0;
+GLuint _uniform_scene_position_uBoard1;
+GLuint _uniform_scene_position_g_world_depth;
+GLuint _uniform_scene_position_uLightsArray;
+GLuint _uniform_scene_position_uLightsIndex;
+#include "shaders/scene_cubemapped.h"
+struct vg_shader _shader_scene_cubemapped = {
+   .name = "scene_cubemapped",
+   .vs = 
+{
+.orig_file = "shaders/scene.vs",
+.static_src = 
+"layout (location=0) in vec3  a_co;\n"
+"layout (location=1) in vec4  a_norm;\n"
+"layout (location=2) in vec2  a_uv;\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      6        0 \n"
+"\n"
+"uniform mat4x3 uMdl;\n"
+"uniform mat4   uPv;\n"
+"uniform mat4   uPvmPrev;\n"
+"\n"
+"out vec2 aUv;\n"
+"out vec4 aNorm;\n"
+"out vec3 aCo;\n"
+"out vec3 aWorldCo;\n"
+"\n"
+"void main()\n"
+"{\n"
+"   vec3 world_pos0 = uMdl     * vec4( a_co, 1.0 );\n"
+"   vec4 vproj0     = uPv      * vec4( world_pos0, 1.0 );\n"
+"   vec4 vproj1     = uPvmPrev * vec4( a_co, 1.0 );\n"
+"\n"
+"   vs_motion_out( vproj0, vproj1 );\n"
+"\n"
+"   gl_Position = vproj0;\n"
+"\n"
+"   aUv = a_uv;\n"
+"   aNorm = vec4( mat3(uMdl) * a_norm.xyz, a_norm.w );\n"
+"   aCo = a_co;\n"
+"   aWorldCo = world_pos0;\n"
+"}\n"
+""},
+   .fs = 
+{
+.orig_file = "shaders/scene_cubemapped.fs",
+.static_src = 
+"uniform sampler2D uTexGarbage;\n"
+"uniform sampler2D uTexMain;\n"
+"uniform samplerCube uTexCubemap;\n"
+"uniform vec3 uCamera;\n"
+"uniform vec4 uPlane;\n"
+"uniform vec4 uColour;\n"
+"\n"
+"#line       1        1 \n"
+"// :D\n"
+"const float CLEARSKIES_LIGHT_DOT_MIN = 0.0;\n"
+"\n"
+"#line      9        0 \n"
+"#line       1        2 \n"
+"// :D\n"
+"\n"
+"in vec2 aUv;\n"
+"in vec4 aNorm;\n"
+"in vec3 aCo;\n"
+"in vec3 aWorldCo;\n"
+"\n"
+"#line       1        1 \n"
+"layout (location = 0) out vec4 oColour;\n"
+"\n"
+"// OpenGL wiki: Recommends do not use vec3 because of drivers. hence the v4s...\n"
+"layout (std140) uniform ub_world_lighting\n"
+"{\n"
+"   vec4 g_cube_min;\n"
+"   vec4 g_cube_inv_range;\n"
+"\n"
+"   vec4 g_water_plane;\n"
+"   vec4 g_depth_bounds;\n"
+"\n"
+"   vec4 g_daysky_colour;\n"
+"   vec4 g_nightsky_colour;\n"
+"   vec4 g_sunset_colour;\n"
+"   vec4 g_ambient_colour;\n"
+"   vec4 g_sunset_ambient;\n"
+"   vec4 g_sun_colour;\n"
+"   vec4 g_sun_dir;\n"
+"   vec4 g_board_0;\n"
+"   vec4 g_board_1;\n"
+"\n"
+"   float g_water_fog;\n"
+"   float g_time;\n"
+"   float g_realtime;\n"
+"   float g_shadow_length;\n"
+"   float g_shadow_spread;\n"
+"\n"
+"   float g_time_of_day;\n"
+"   float g_day_phase;\n"
+"   float g_sunset_phase;\n"
+"\n"
+"   int g_light_preview;\n"
+"   int g_shadow_samples;\n"
+"\n"
+"   int g_debug_indices;\n"
+"   int g_debug_complexity;\n"
+"};\n"
+"\n"
+"uniform sampler2D g_world_depth;\n"
+"uniform samplerBuffer uLightsArray;\n"
+"uniform usampler3D uLightsIndex;\n"
+"\n"
+"#line       1        1 \n"
+"//const vec3  DAYSKY_COLOUR   = vec3( 0.37, 0.54, 0.97 );\n"
+"//const vec3  NIGHTSKY_COLOUR = vec3( 0.03, 0.05, 0.20 );\n"
+"//const vec3  SUNSET_COLOUR   = vec3( 1.00, 0.32, 0.01 );\n"
+"//const vec3  AMBIENT_COLOUR  = vec3( 0.13, 0.17, 0.35 );\n"
+"//const vec3  SUNSET_AMBIENT  = vec3( 0.25, 0.17, 0.51 );\n"
+"//const vec3  SUN_COLOUR      = vec3( 1.10, 0.89, 0.35 );\n"
+"\n"
+"const float SUN_ANGLE       = 0.0001;\n"
+"const float PI              = 3.14159265358979323846264;\n"
+"\n"
+"//struct world_info\n"
+"//{\n"
+"//   float time,\n"
+"//         time_of_day,\n"
+"//         day_phase,\n"
+"//         sunset_phase;\n"
+"//   \n"
+"//   vec3 sun_dir;\n"
+"//};\n"
+"\n"
+"vec3 rand33(vec3 p3)\n"
+"{\n"
+"      p3 = fract(p3 * vec3(.1031, .1030, .0973));\n"
+"   p3 += dot(p3, p3.yxz+33.33);\n"
+"   return fract((p3.xxy + p3.yxx)*p3.zyx);\n"
+"}\n"
+"\n"
+"float stars( vec3 rd, float rr, float size ){\n"
+"   vec3 co = rd * rr;\n"
+"\n"
+"   float a = atan(co.y, length(co.xz)) + 4.0 * PI;\n"
+"\n"
+"   float spaces = 1.0 / rr;\n"
+"   size = (rr * 0.0015) * fwidth(a) * 1000.0 * size;\n"
+"   a -= mod(a, spaces) - spaces * 0.5;\n"
+"\n"
+"   float count = floor(sqrt(pow(rr, 2.0) * (1.0 - pow(sin(a), 2.0))) * 3.0);\n"
+"   \n"
+"   float plane = atan(co.z, co.x) + 4.0 * PI;\n"
+"   plane = plane - mod(plane, PI / count);\n"
+"\n"
+"   vec2 delta = rand33(vec3(plane, a, 0.0)).xy;\n"
+"\n"
+"   float level = sin(a + spaces * (delta.y - 0.5) * (1.0 - size)) * rr;\n"
+"   float ydist = sqrt(rr * rr - level * level);\n"
+"   float angle = plane + (PI * (delta.x * (1.0-size) + size * 0.5) / count);\n"
+"   vec3 center = vec3(cos(angle) * ydist, level, sin(angle) * ydist);\n"
+"   float star = smoothstep(size, 0.0, distance(center, co));\n"
+"   return star;\n"
+"}\n"
+"\n"
+"float luminance( vec3 v )\n"
+"{\n"
+"   return dot( v, vec3(0.2126, 0.7152, 0.0722) );\n"
+"}\n"
+"\n"
+"vec3 clearskies_ambient( vec3 dir )\n"
+"{\n"
+"   float sun_azimuth  = g_sunset_phase * (dot( dir.xz, g_sun_dir.xz )*0.4+0.6);\n"
+"   float sky_gradient = dir.y;\n"
+"   \n"
+"   /* Blend phase colours */\n"
+"   vec3 ambient  = g_daysky_colour.rgb   * (g_day_phase-g_sunset_phase*0.1);\n"
+"        ambient += g_sunset_colour.rgb   * (1.0-dir.y*0.5)*sun_azimuth;\n"
+"        ambient += g_nightsky_colour.rgb * (1.0-g_day_phase);\n"
+"   \n"
+"   /* Add gradient */\n"
+"        ambient -= sky_gradient * luminance(ambient);\n"
+"        \n"
+"   return ambient;\n"
+"}\n"
+"\n"
+"vec3 clearskies_sky( vec3 ray_dir )\n"
+"{\n"
+"   ray_dir.y = abs( ray_dir.y );\n"
+"   vec3 sky_colour  = clearskies_ambient( ray_dir );\n"
+"   \n"
+"   /* Sun */\n"
+"   float sun_theta  = dot( ray_dir, g_sun_dir.xyz );\n"
+"   float sun_size   = max( 0.0, sun_theta * 0.5 + 0.5 + SUN_ANGLE );\n"
+"   float sun_shape  = pow( sun_size, 2000.0 );\n"
+"         sun_shape += sun_size * max(g_sun_dir.y,0.0) * 0.5;\n"
+"         \n"
+"   vec3 sun_colour  = mix( vec3(1.0), g_sunset_colour.rgb, g_sunset_phase*0.5 );\n"
+"        sun_colour *= sun_shape;\n"
+"\n"
+"   \n"
+"   float star = 0.0;\n"
+"   float star_blend = 10.0*max(0.0,(1.0-g_day_phase*2.0));\n"
+"\n"
+"   if( star_blend > 0.001 ){\n"
+"      for( float j = 1.0; j <= 4.1; j += 1.0 ){\n"
+"         float m = mix(0.6, 0.9, smoothstep(1.0, 2.0, j));\n"
+"         star += stars( ray_dir, 1.94 * pow( 1.64, j ), m ) * (1.0/pow(4.0, j));\n"
+"      }\n"
+"   }\n"
+"   \n"
+"   vec3 composite   = sky_colour + sun_colour + star*star_blend;\n"
+"   return composite;\n"
+"}\n"
+"\n"
+"vec3 clearskies_lighting( vec3 normal, float shadow, vec3 halfview )\n"
+"{\n"
+"   float fresnel = 1.0 - abs(dot(normal,halfview));\n"
+"\n"
+"   vec3  reflect_colour = mix( g_daysky_colour.rgb, g_sunset_colour.rgb, \n"
+"                               g_sunset_phase );\n"
+"\n"
+"   vec3  sky_reflection = 0.5 * fresnel * reflect_colour;\n"
+"   vec3  light_sun      = max( CLEARSKIES_LIGHT_DOT_MIN, \n"
+"                               dot(normal,g_sun_dir.xyz)*0.75+0.25\n"
+"                           ) * g_sun_colour.rgb * g_day_phase;\n"
+"\n"
+"   float scaled_shadow = max( shadow, 1.0 - max(g_sun_dir.y,0.0) );\n"
+"   vec3 ambient = mix( g_ambient_colour.rgb, g_sunset_ambient.rgb, \n"
+"                       g_sunset_phase );\n"
+"\n"
+"   return ambient + (light_sun + sky_reflection) * shadow;\n"
+"}\n"
+"\n"
+"#line     44        0 \n"
+"\n"
+"float world_depth_sample( vec3 pos )\n"
+"{\n"
+"   vec2 depth_coord = (pos.xz - g_depth_bounds.xy) * g_depth_bounds.zw; \n"
+"   return texture( g_world_depth, depth_coord ).r;\n"
+"}\n"
+"\n"
+"float world_water_depth( vec3 pos )\n"
+"{\n"
+"   float ref_depth = g_water_plane.y*g_water_plane.w;\n"
+"   return world_depth_sample( pos ) - ref_depth;\n"
+"}\n"
+"\n"
+"float shadow_sample( vec3 co ){\n"
+"   float height_sample = world_depth_sample( co );\n"
+"\n"
+"   float fdelta = height_sample - co.y;\n"
+"   return clamp( fdelta, 0.2, 0.4 )-0.2;\n"
+"}\n"
+"\n"
+"float newlight_compute_sun_shadow( vec3 co, vec3 dir ){\n"
+"   if( g_shadow_samples == 0 ){\n"
+"      return 1.0;\n"
+"   }\n"
+"\n"
+"   float fspread = g_shadow_spread;\n"
+"   float flength = g_shadow_length;\n"
+"\n"
+"   float famt = 0.0;\n"
+"   famt += shadow_sample(co+(dir+vec3(-0.56,0.55, 0.30)*fspread)*flength*0.1);\n"
+"   famt += shadow_sample(co+(dir+vec3( 0.80,0.68, 0.34)*fspread)*flength*0.2);\n"
+"   famt += shadow_sample(co+(dir+vec3( 0.78,0.07,-0.06)*fspread)*flength*0.3);\n"
+"   famt += shadow_sample(co+(dir+vec3(-0.59,0.07,-0.42)*fspread)*flength*0.4);\n"
+"\n"
+"   //famt+=shadow_sample(co+(dir+vec3(-0.790,-0.933,-0.875)*fspread)*flength*0.5);\n"
+"   //famt+=shadow_sample(co+(dir+vec3( 0.807,-0.690, 0.472)*fspread)*flength*0.6);\n"
+"   //famt+=shadow_sample(co+(dir+vec3( 0.522,-0.379, 0.350)*fspread)*flength*0.7);\n"
+"   //famt+=shadow_sample(co+(dir+vec3( 0.483, 0.201, 0.306)*fspread)*flength*0.8);\n"
+"\n"
+"   return 1.0 - famt;\n"
+"}\n"
+"\n"
+"float newlight_specular( vec3 wnormal, vec3 dir, vec3 halfview, float exponent )\n"
+"{\n"
+"   vec3 specdir = reflect( -dir, wnormal );\n"
+"   return pow(max(dot( halfview, specdir ), 0.0), exponent);\n"
+"}\n"
+"\n"
+"vec3 scene_apply_fog( vec3 vfrag, vec3 colour, float fdist ){\n"
+"   float dist = pow(fdist*0.0010,0.78);\n"
+"   return mix( vfrag, colour, min( 1.0, dist ) );\n"
+"}\n"
+"\n"
+"vec3 scene_calculate_light( int light_index, \n"
+"                            vec3 halfview, vec3 co, vec3 normal )\n"
+"{\n"
+"   vec4 light_colour = texelFetch( uLightsArray, light_index+0 );\n"
+"   vec4 light_co     = texelFetch( uLightsArray, light_index+1 );\n"
+"   vec4 light_dir    = texelFetch( uLightsArray, light_index+2 );\n"
+"\n"
+"   vec3 light_delta = light_co.xyz-co;\n"
+"   float dist2 = dot(light_delta,light_delta);\n"
+"\n"
+"   light_delta = normalize( light_delta );\n"
+"\n"
+"   float quadratic = dist2*100.0;\n"
+"   float attenuation  = 1.0/( 1.0 + quadratic );\n"
+"         attenuation *= max( dot( light_delta, normal ), 0.0 );\n"
+"\n"
+"   float falloff = max( 0.0, 1.0-(dist2*light_co.w) );\n"
+"\n"
+"   if( light_dir.w < 0.999999 ){\n"
+"      float spot_theta = max( 0.0, dot( light_delta, -light_dir.xyz ) );\n"
+"      falloff *= max( 0.0, (spot_theta - light_dir.w) / (1.0-light_dir.w) );\n"
+"   }\n"
+"\n"
+"   return light_colour.rgb * attenuation * falloff \n"
+"            * step( g_day_phase, light_colour.w );\n"
+"}\n"
+"\n"
+"vec3 scene_calculate_packed_light_patch( uint packed_index, \n"
+"                                         vec3 halfview, vec3 co, vec3 normal )\n"
+"{\n"
+"   uint light_count = packed_index & 0x3u;\n"
+"\n"
+"   vec3 l = vec3(0.0);\n"
+"\n"
+"   if( light_count >= 1u ){\n"
+"      int index_0 = int( ((packed_index >>  2u) & 0x3ffu) * 3u );\n"
+"      int index_1 = int( ((packed_index >> 12u) & 0x3ffu) * 3u );\n"
+"      int index_2 = int( ((packed_index >> 22u) & 0x3ffu) * 3u );\n"
+"\n"
+"      l += scene_calculate_light( index_0, halfview, co, normal );\n"
+"\n"
+"      if( light_count >= 2u ){\n"
+"         l += scene_calculate_light( index_1, halfview, co, normal );\n"
+"\n"
+"         if( light_count >= 3u ){\n"
+"            l += scene_calculate_light( index_2, halfview, co, normal );\n"
+"         }\n"
+"      }\n"
+"   }\n"
+"\n"
+"   return l;\n"
+"}\n"
+"\n"
+"vec3 world_compute_lighting( vec3 diffuse, vec3 normal, vec3 co,\n"
+"                             float light_mask )\n"
+"{\n"
+"   if( g_light_preview == 1 )\n"
+"      diffuse = vec3(0.75);\n"
+"\n"
+"   // Lighting\n"
+"   vec3 halfview = uCamera - co;\n"
+"   float fdist = length(halfview);\n"
+"   halfview /= fdist;\n"
+"\n"
+"   float world_shadow = newlight_compute_sun_shadow( \n"
+"               co, g_sun_dir.xyz * (1.0/(max(g_sun_dir.y,0.0)+0.2)) );\n"
+"\n"
+"   vec3 total_light = clearskies_lighting( \n"
+"                           normal, min( light_mask, world_shadow ), halfview );\n"
+"\n"
+"   vec3 cube_coord = (co - g_cube_min.xyz) * g_cube_inv_range.xyz;\n"
+"        cube_coord = floor( cube_coord );\n"
+"\n"
+"   if( g_debug_indices == 1 )\n"
+"   {\n"
+"      return rand33(cube_coord);\n"
+"   }\n"
+"\n"
+"   if( g_debug_complexity == 1 )\n"
+"   {\n"
+"      ivec3 coord = ivec3( cube_coord );\n"
+"      uvec4 index_sample = texelFetch( uLightsIndex, coord, 0 );\n"
+"\n"
+"      uint light_count = (index_sample.x & 0x3u) + (index_sample.y & 0x3u);\n"
+"      return vec3( float(light_count)*(1.0/6.0), 0.0, 0.5 );\n"
+"   }\n"
+"\n"
+"   // FIXME: this coord should absolutely must be clamped!\n"
+"   \n"
+"   ivec3 coord = ivec3( cube_coord );\n"
+"   uvec4 index_sample = texelFetch( uLightsIndex, coord, 0 );\n"
+"\n"
+"   total_light += \n"
+"      scene_calculate_packed_light_patch( index_sample.x,\n"
+"                                          halfview, co, normal ) \n"
+"                                          * light_mask;\n"
+"   total_light += \n"
+"      scene_calculate_packed_light_patch( index_sample.y,\n"
+"                                          halfview, co, normal )\n"
+"                                          * light_mask;\n"
+"\n"
+"   // Take a section of the sky function to give us a matching fog colour\n"
+"\n"
+"   vec3 fog_colour  = clearskies_ambient( -halfview );\n"
+"   float sun_theta  = dot( -halfview, g_sun_dir.xyz );\n"
+"   float sun_size   = max( 0.0, sun_theta * 0.5 + 0.5 );\n"
+"   float sun_shape  = sun_size * max(g_sun_dir.y,0.0) * 0.5;\n"
+"         \n"
+"   vec3 sun_colour  = mix( vec3(1.0), g_sunset_colour.rgb, g_sunset_phase*0.5 );\n"
+"        sun_colour *= sun_shape;\n"
+"\n"
+"   fog_colour += sun_colour;\n"
+"   return scene_apply_fog( diffuse * total_light, fog_colour, fdist );\n"
+"}\n"
+"\n"
+"#line      9        0 \n"
+"\n"
+"float sdLine( vec3 p, vec3 a, vec3 b )\n"
+"{\n"
+"  vec3 pa = p - a;\n"
+"  vec3 ba = b - a;\n"
+"\n"
+"  float h = clamp( dot(pa,ba)/dot(ba,ba), 0.0, 1.0 );\n"
+"  return length( pa - ba*h );\n"
+"}\n"
+"\n"
+"float compute_board_shadow()\n"
+"{\n"
+"   // player shadow\n"
+"   float dist_to_player = max( 0.0, sdLine( aWorldCo, g_board_0.xyz,\n"
+"                                                      g_board_1.xyz )-0.1 );\n"
+"   float player_shadow = max( 1.0-dist_to_player*2.7, 0.0 );\n"
+"   player_shadow *= player_shadow*player_shadow*player_shadow;\n"
+"\n"
+"   return 1.0 - player_shadow*0.8;\n"
+"}\n"
+"\n"
+"vec3 scene_compute_lighting( vec3 diffuse, vec3 normal, vec3 co )\n"
+"{\n"
+"   return world_compute_lighting( diffuse, normal, co, compute_board_shadow() );\n"
+"}\n"
+"\n"
+"#line     10        0 \n"
+"#line       1        3 \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     11        0 \n"
+"\n"
+"void main()\n"
+"{\n"
+"   compute_motion_vectors();\n"
+"\n"
+"   vec3 vfrag = vec3(0.5,0.5,0.5);\n"
+"   vec4 vsamplemain = texture( uTexMain, aUv );\n"
+"   vec4 wgarbage = texture( uTexGarbage, aCo.xz * 0.0015 + aCo.yx*0.002 );\n"
+"   vec3 qnorm = aNorm.xyz;\n"
+"   vfrag = vsamplemain.rgb;\n"
+"\n"
+"   if( g_light_preview == 1 ){\n"
+"      vfrag = vec3(0.5);\n"
+"   }\n"
+"\n"
+"   vfrag = scene_compute_lighting( vfrag, qnorm, aWorldCo );\n"
+"   oColour = vec4( vfrag, 1.0 );\n"
+"\n"
+"   vec3 halfdir = normalize( aWorldCo - uCamera );\n"
+"   vec3 reflectdir = reflect( halfdir, qnorm );\n"
+"   oColour = mix( oColour, \n"
+"                  vec4(texture(uTexCubemap,reflectdir).rgb * uColour.rgb, 1.0),\n"
+"                  uColour.a*wgarbage.b );\n"
+"}\n"
+""},
+};
+
+GLuint _uniform_scene_cubemapped_uMdl;
+GLuint _uniform_scene_cubemapped_uPv;
+GLuint _uniform_scene_cubemapped_uPvmPrev;
+GLuint _uniform_scene_cubemapped_uTexGarbage;
+GLuint _uniform_scene_cubemapped_uTexMain;
+GLuint _uniform_scene_cubemapped_uTexCubemap;
+GLuint _uniform_scene_cubemapped_uCamera;
+GLuint _uniform_scene_cubemapped_uPlane;
+GLuint _uniform_scene_cubemapped_uColour;
+GLuint _uniform_scene_cubemapped_g_world_depth;
+GLuint _uniform_scene_cubemapped_uLightsArray;
+GLuint _uniform_scene_cubemapped_uLightsIndex;
+#include "shaders/scene_water.h"
+struct vg_shader _shader_scene_water = {
+   .name = "scene_water",
+   .vs = 
+{
+.orig_file = "shaders/scene.vs",
+.static_src = 
+"layout (location=0) in vec3  a_co;\n"
+"layout (location=1) in vec4  a_norm;\n"
+"layout (location=2) in vec2  a_uv;\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      6        0 \n"
+"\n"
+"uniform mat4x3 uMdl;\n"
+"uniform mat4   uPv;\n"
+"uniform mat4   uPvmPrev;\n"
+"\n"
+"out vec2 aUv;\n"
+"out vec4 aNorm;\n"
+"out vec3 aCo;\n"
+"out vec3 aWorldCo;\n"
+"\n"
+"void main()\n"
+"{\n"
+"   vec3 world_pos0 = uMdl     * vec4( a_co, 1.0 );\n"
+"   vec4 vproj0     = uPv      * vec4( world_pos0, 1.0 );\n"
+"   vec4 vproj1     = uPvmPrev * vec4( a_co, 1.0 );\n"
+"\n"
+"   vs_motion_out( vproj0, vproj1 );\n"
+"\n"
+"   gl_Position = vproj0;\n"
+"\n"
+"   aUv = a_uv;\n"
+"   aNorm = vec4( mat3(uMdl) * a_norm.xyz, a_norm.w );\n"
+"   aCo = a_co;\n"
+"   aWorldCo = world_pos0;\n"
+"}\n"
+""},
+   .fs = 
+{
+.orig_file = "shaders/scene_water.fs",
+.static_src = 
+"uniform sampler2D uTexMain;\n"
+"uniform sampler2D uTexDudv;\n"
+"uniform sampler2D uTexBack;\n"
+"\n"
+"uniform vec2 uInvRes;\n"
+"uniform float uTime;\n"
+"uniform vec3 uCamera;\n"
+"uniform float uSurfaceY;\n"
+"uniform vec3 uBoard0;\n"
+"uniform vec3 uBoard1;\n"
+"\n"
+"uniform vec3 uShoreColour;\n"
+"uniform vec3 uOceanColour;\n"
+"\n"
+"#line       1        1 \n"
+"// :D\n"
+"const float CLEARSKIES_LIGHT_DOT_MIN = 0.0;\n"
+"\n"
+"#line     16        0 \n"
+"#line       1        2 \n"
+"// :D\n"
+"\n"
+"in vec2 aUv;\n"
+"in vec4 aNorm;\n"
+"in vec3 aCo;\n"
+"in vec3 aWorldCo;\n"
+"\n"
+"#line       1        1 \n"
+"layout (location = 0) out vec4 oColour;\n"
+"\n"
+"// OpenGL wiki: Recommends do not use vec3 because of drivers. hence the v4s...\n"
+"layout (std140) uniform ub_world_lighting\n"
+"{\n"
+"   vec4 g_cube_min;\n"
+"   vec4 g_cube_inv_range;\n"
+"\n"
+"   vec4 g_water_plane;\n"
+"   vec4 g_depth_bounds;\n"
+"\n"
+"   vec4 g_daysky_colour;\n"
+"   vec4 g_nightsky_colour;\n"
+"   vec4 g_sunset_colour;\n"
+"   vec4 g_ambient_colour;\n"
+"   vec4 g_sunset_ambient;\n"
+"   vec4 g_sun_colour;\n"
+"   vec4 g_sun_dir;\n"
+"   vec4 g_board_0;\n"
+"   vec4 g_board_1;\n"
+"\n"
+"   float g_water_fog;\n"
+"   float g_time;\n"
+"   float g_realtime;\n"
+"   float g_shadow_length;\n"
+"   float g_shadow_spread;\n"
+"\n"
+"   float g_time_of_day;\n"
+"   float g_day_phase;\n"
+"   float g_sunset_phase;\n"
+"\n"
+"   int g_light_preview;\n"
+"   int g_shadow_samples;\n"
+"\n"
+"   int g_debug_indices;\n"
+"   int g_debug_complexity;\n"
+"};\n"
+"\n"
+"uniform sampler2D g_world_depth;\n"
+"uniform samplerBuffer uLightsArray;\n"
+"uniform usampler3D uLightsIndex;\n"
+"\n"
+"#line       1        1 \n"
+"//const vec3  DAYSKY_COLOUR   = vec3( 0.37, 0.54, 0.97 );\n"
+"//const vec3  NIGHTSKY_COLOUR = vec3( 0.03, 0.05, 0.20 );\n"
+"//const vec3  SUNSET_COLOUR   = vec3( 1.00, 0.32, 0.01 );\n"
+"//const vec3  AMBIENT_COLOUR  = vec3( 0.13, 0.17, 0.35 );\n"
+"//const vec3  SUNSET_AMBIENT  = vec3( 0.25, 0.17, 0.51 );\n"
+"//const vec3  SUN_COLOUR      = vec3( 1.10, 0.89, 0.35 );\n"
+"\n"
+"const float SUN_ANGLE       = 0.0001;\n"
+"const float PI              = 3.14159265358979323846264;\n"
+"\n"
+"//struct world_info\n"
+"//{\n"
+"//   float time,\n"
+"//         time_of_day,\n"
+"//         day_phase,\n"
+"//         sunset_phase;\n"
+"//   \n"
+"//   vec3 sun_dir;\n"
+"//};\n"
+"\n"
+"vec3 rand33(vec3 p3)\n"
+"{\n"
+"      p3 = fract(p3 * vec3(.1031, .1030, .0973));\n"
+"   p3 += dot(p3, p3.yxz+33.33);\n"
+"   return fract((p3.xxy + p3.yxx)*p3.zyx);\n"
+"}\n"
+"\n"
+"float stars( vec3 rd, float rr, float size ){\n"
+"   vec3 co = rd * rr;\n"
+"\n"
+"   float a = atan(co.y, length(co.xz)) + 4.0 * PI;\n"
+"\n"
+"   float spaces = 1.0 / rr;\n"
+"   size = (rr * 0.0015) * fwidth(a) * 1000.0 * size;\n"
+"   a -= mod(a, spaces) - spaces * 0.5;\n"
+"\n"
+"   float count = floor(sqrt(pow(rr, 2.0) * (1.0 - pow(sin(a), 2.0))) * 3.0);\n"
+"   \n"
+"   float plane = atan(co.z, co.x) + 4.0 * PI;\n"
+"   plane = plane - mod(plane, PI / count);\n"
+"\n"
+"   vec2 delta = rand33(vec3(plane, a, 0.0)).xy;\n"
+"\n"
+"   float level = sin(a + spaces * (delta.y - 0.5) * (1.0 - size)) * rr;\n"
+"   float ydist = sqrt(rr * rr - level * level);\n"
+"   float angle = plane + (PI * (delta.x * (1.0-size) + size * 0.5) / count);\n"
+"   vec3 center = vec3(cos(angle) * ydist, level, sin(angle) * ydist);\n"
+"   float star = smoothstep(size, 0.0, distance(center, co));\n"
+"   return star;\n"
+"}\n"
+"\n"
+"float luminance( vec3 v )\n"
+"{\n"
+"   return dot( v, vec3(0.2126, 0.7152, 0.0722) );\n"
+"}\n"
+"\n"
+"vec3 clearskies_ambient( vec3 dir )\n"
+"{\n"
+"   float sun_azimuth  = g_sunset_phase * (dot( dir.xz, g_sun_dir.xz )*0.4+0.6);\n"
+"   float sky_gradient = dir.y;\n"
+"   \n"
+"   /* Blend phase colours */\n"
+"   vec3 ambient  = g_daysky_colour.rgb   * (g_day_phase-g_sunset_phase*0.1);\n"
+"        ambient += g_sunset_colour.rgb   * (1.0-dir.y*0.5)*sun_azimuth;\n"
+"        ambient += g_nightsky_colour.rgb * (1.0-g_day_phase);\n"
+"   \n"
+"   /* Add gradient */\n"
+"        ambient -= sky_gradient * luminance(ambient);\n"
+"        \n"
+"   return ambient;\n"
+"}\n"
+"\n"
+"vec3 clearskies_sky( vec3 ray_dir )\n"
+"{\n"
+"   ray_dir.y = abs( ray_dir.y );\n"
+"   vec3 sky_colour  = clearskies_ambient( ray_dir );\n"
+"   \n"
+"   /* Sun */\n"
+"   float sun_theta  = dot( ray_dir, g_sun_dir.xyz );\n"
+"   float sun_size   = max( 0.0, sun_theta * 0.5 + 0.5 + SUN_ANGLE );\n"
+"   float sun_shape  = pow( sun_size, 2000.0 );\n"
+"         sun_shape += sun_size * max(g_sun_dir.y,0.0) * 0.5;\n"
+"         \n"
+"   vec3 sun_colour  = mix( vec3(1.0), g_sunset_colour.rgb, g_sunset_phase*0.5 );\n"
+"        sun_colour *= sun_shape;\n"
+"\n"
+"   \n"
+"   float star = 0.0;\n"
+"   float star_blend = 10.0*max(0.0,(1.0-g_day_phase*2.0));\n"
+"\n"
+"   if( star_blend > 0.001 ){\n"
+"      for( float j = 1.0; j <= 4.1; j += 1.0 ){\n"
+"         float m = mix(0.6, 0.9, smoothstep(1.0, 2.0, j));\n"
+"         star += stars( ray_dir, 1.94 * pow( 1.64, j ), m ) * (1.0/pow(4.0, j));\n"
+"      }\n"
+"   }\n"
+"   \n"
+"   vec3 composite   = sky_colour + sun_colour + star*star_blend;\n"
+"   return composite;\n"
+"}\n"
+"\n"
+"vec3 clearskies_lighting( vec3 normal, float shadow, vec3 halfview )\n"
+"{\n"
+"   float fresnel = 1.0 - abs(dot(normal,halfview));\n"
+"\n"
+"   vec3  reflect_colour = mix( g_daysky_colour.rgb, g_sunset_colour.rgb, \n"
+"                               g_sunset_phase );\n"
+"\n"
+"   vec3  sky_reflection = 0.5 * fresnel * reflect_colour;\n"
+"   vec3  light_sun      = max( CLEARSKIES_LIGHT_DOT_MIN, \n"
+"                               dot(normal,g_sun_dir.xyz)*0.75+0.25\n"
+"                           ) * g_sun_colour.rgb * g_day_phase;\n"
+"\n"
+"   float scaled_shadow = max( shadow, 1.0 - max(g_sun_dir.y,0.0) );\n"
+"   vec3 ambient = mix( g_ambient_colour.rgb, g_sunset_ambient.rgb, \n"
+"                       g_sunset_phase );\n"
+"\n"
+"   return ambient + (light_sun + sky_reflection) * shadow;\n"
+"}\n"
+"\n"
+"#line     44        0 \n"
+"\n"
+"float world_depth_sample( vec3 pos )\n"
+"{\n"
+"   vec2 depth_coord = (pos.xz - g_depth_bounds.xy) * g_depth_bounds.zw; \n"
+"   return texture( g_world_depth, depth_coord ).r;\n"
+"}\n"
+"\n"
+"float world_water_depth( vec3 pos )\n"
+"{\n"
+"   float ref_depth = g_water_plane.y*g_water_plane.w;\n"
+"   return world_depth_sample( pos ) - ref_depth;\n"
+"}\n"
+"\n"
+"float shadow_sample( vec3 co ){\n"
+"   float height_sample = world_depth_sample( co );\n"
+"\n"
+"   float fdelta = height_sample - co.y;\n"
+"   return clamp( fdelta, 0.2, 0.4 )-0.2;\n"
+"}\n"
+"\n"
+"float newlight_compute_sun_shadow( vec3 co, vec3 dir ){\n"
+"   if( g_shadow_samples == 0 ){\n"
+"      return 1.0;\n"
+"   }\n"
+"\n"
+"   float fspread = g_shadow_spread;\n"
+"   float flength = g_shadow_length;\n"
+"\n"
+"   float famt = 0.0;\n"
+"   famt += shadow_sample(co+(dir+vec3(-0.56,0.55, 0.30)*fspread)*flength*0.1);\n"
+"   famt += shadow_sample(co+(dir+vec3( 0.80,0.68, 0.34)*fspread)*flength*0.2);\n"
+"   famt += shadow_sample(co+(dir+vec3( 0.78,0.07,-0.06)*fspread)*flength*0.3);\n"
+"   famt += shadow_sample(co+(dir+vec3(-0.59,0.07,-0.42)*fspread)*flength*0.4);\n"
+"\n"
+"   //famt+=shadow_sample(co+(dir+vec3(-0.790,-0.933,-0.875)*fspread)*flength*0.5);\n"
+"   //famt+=shadow_sample(co+(dir+vec3( 0.807,-0.690, 0.472)*fspread)*flength*0.6);\n"
+"   //famt+=shadow_sample(co+(dir+vec3( 0.522,-0.379, 0.350)*fspread)*flength*0.7);\n"
+"   //famt+=shadow_sample(co+(dir+vec3( 0.483, 0.201, 0.306)*fspread)*flength*0.8);\n"
+"\n"
+"   return 1.0 - famt;\n"
+"}\n"
+"\n"
+"float newlight_specular( vec3 wnormal, vec3 dir, vec3 halfview, float exponent )\n"
+"{\n"
+"   vec3 specdir = reflect( -dir, wnormal );\n"
+"   return pow(max(dot( halfview, specdir ), 0.0), exponent);\n"
+"}\n"
+"\n"
+"vec3 scene_apply_fog( vec3 vfrag, vec3 colour, float fdist ){\n"
+"   float dist = pow(fdist*0.0010,0.78);\n"
+"   return mix( vfrag, colour, min( 1.0, dist ) );\n"
+"}\n"
+"\n"
+"vec3 scene_calculate_light( int light_index, \n"
+"                            vec3 halfview, vec3 co, vec3 normal )\n"
+"{\n"
+"   vec4 light_colour = texelFetch( uLightsArray, light_index+0 );\n"
+"   vec4 light_co     = texelFetch( uLightsArray, light_index+1 );\n"
+"   vec4 light_dir    = texelFetch( uLightsArray, light_index+2 );\n"
+"\n"
+"   vec3 light_delta = light_co.xyz-co;\n"
+"   float dist2 = dot(light_delta,light_delta);\n"
+"\n"
+"   light_delta = normalize( light_delta );\n"
+"\n"
+"   float quadratic = dist2*100.0;\n"
+"   float attenuation  = 1.0/( 1.0 + quadratic );\n"
+"         attenuation *= max( dot( light_delta, normal ), 0.0 );\n"
+"\n"
+"   float falloff = max( 0.0, 1.0-(dist2*light_co.w) );\n"
+"\n"
+"   if( light_dir.w < 0.999999 ){\n"
+"      float spot_theta = max( 0.0, dot( light_delta, -light_dir.xyz ) );\n"
+"      falloff *= max( 0.0, (spot_theta - light_dir.w) / (1.0-light_dir.w) );\n"
+"   }\n"
+"\n"
+"   return light_colour.rgb * attenuation * falloff \n"
+"            * step( g_day_phase, light_colour.w );\n"
+"}\n"
+"\n"
+"vec3 scene_calculate_packed_light_patch( uint packed_index, \n"
+"                                         vec3 halfview, vec3 co, vec3 normal )\n"
+"{\n"
+"   uint light_count = packed_index & 0x3u;\n"
+"\n"
+"   vec3 l = vec3(0.0);\n"
+"\n"
+"   if( light_count >= 1u ){\n"
+"      int index_0 = int( ((packed_index >>  2u) & 0x3ffu) * 3u );\n"
+"      int index_1 = int( ((packed_index >> 12u) & 0x3ffu) * 3u );\n"
+"      int index_2 = int( ((packed_index >> 22u) & 0x3ffu) * 3u );\n"
+"\n"
+"      l += scene_calculate_light( index_0, halfview, co, normal );\n"
+"\n"
+"      if( light_count >= 2u ){\n"
+"         l += scene_calculate_light( index_1, halfview, co, normal );\n"
+"\n"
+"         if( light_count >= 3u ){\n"
+"            l += scene_calculate_light( index_2, halfview, co, normal );\n"
+"         }\n"
+"      }\n"
+"   }\n"
+"\n"
+"   return l;\n"
+"}\n"
+"\n"
+"vec3 world_compute_lighting( vec3 diffuse, vec3 normal, vec3 co,\n"
+"                             float light_mask )\n"
+"{\n"
+"   if( g_light_preview == 1 )\n"
+"      diffuse = vec3(0.75);\n"
+"\n"
+"   // Lighting\n"
+"   vec3 halfview = uCamera - co;\n"
+"   float fdist = length(halfview);\n"
+"   halfview /= fdist;\n"
+"\n"
+"   float world_shadow = newlight_compute_sun_shadow( \n"
+"               co, g_sun_dir.xyz * (1.0/(max(g_sun_dir.y,0.0)+0.2)) );\n"
+"\n"
+"   vec3 total_light = clearskies_lighting( \n"
+"                           normal, min( light_mask, world_shadow ), halfview );\n"
+"\n"
+"   vec3 cube_coord = (co - g_cube_min.xyz) * g_cube_inv_range.xyz;\n"
+"        cube_coord = floor( cube_coord );\n"
+"\n"
+"   if( g_debug_indices == 1 )\n"
+"   {\n"
+"      return rand33(cube_coord);\n"
+"   }\n"
+"\n"
+"   if( g_debug_complexity == 1 )\n"
+"   {\n"
+"      ivec3 coord = ivec3( cube_coord );\n"
+"      uvec4 index_sample = texelFetch( uLightsIndex, coord, 0 );\n"
+"\n"
+"      uint light_count = (index_sample.x & 0x3u) + (index_sample.y & 0x3u);\n"
+"      return vec3( float(light_count)*(1.0/6.0), 0.0, 0.5 );\n"
+"   }\n"
+"\n"
+"   // FIXME: this coord should absolutely must be clamped!\n"
+"   \n"
+"   ivec3 coord = ivec3( cube_coord );\n"
+"   uvec4 index_sample = texelFetch( uLightsIndex, coord, 0 );\n"
+"\n"
+"   total_light += \n"
+"      scene_calculate_packed_light_patch( index_sample.x,\n"
+"                                          halfview, co, normal ) \n"
+"                                          * light_mask;\n"
+"   total_light += \n"
+"      scene_calculate_packed_light_patch( index_sample.y,\n"
+"                                          halfview, co, normal )\n"
+"                                          * light_mask;\n"
+"\n"
+"   // Take a section of the sky function to give us a matching fog colour\n"
+"\n"
+"   vec3 fog_colour  = clearskies_ambient( -halfview );\n"
+"   float sun_theta  = dot( -halfview, g_sun_dir.xyz );\n"
+"   float sun_size   = max( 0.0, sun_theta * 0.5 + 0.5 );\n"
+"   float sun_shape  = sun_size * max(g_sun_dir.y,0.0) * 0.5;\n"
+"         \n"
+"   vec3 sun_colour  = mix( vec3(1.0), g_sunset_colour.rgb, g_sunset_phase*0.5 );\n"
+"        sun_colour *= sun_shape;\n"
+"\n"
+"   fog_colour += sun_colour;\n"
+"   return scene_apply_fog( diffuse * total_light, fog_colour, fdist );\n"
+"}\n"
+"\n"
+"#line      9        0 \n"
+"\n"
+"float sdLine( vec3 p, vec3 a, vec3 b )\n"
+"{\n"
+"  vec3 pa = p - a;\n"
+"  vec3 ba = b - a;\n"
+"\n"
+"  float h = clamp( dot(pa,ba)/dot(ba,ba), 0.0, 1.0 );\n"
+"  return length( pa - ba*h );\n"
+"}\n"
+"\n"
+"float compute_board_shadow()\n"
+"{\n"
+"   // player shadow\n"
+"   float dist_to_player = max( 0.0, sdLine( aWorldCo, g_board_0.xyz,\n"
+"                                                      g_board_1.xyz )-0.1 );\n"
+"   float player_shadow = max( 1.0-dist_to_player*2.7, 0.0 );\n"
+"   player_shadow *= player_shadow*player_shadow*player_shadow;\n"
+"\n"
+"   return 1.0 - player_shadow*0.8;\n"
+"}\n"
+"\n"
+"vec3 scene_compute_lighting( vec3 diffuse, vec3 normal, vec3 co )\n"
+"{\n"
+"   return world_compute_lighting( diffuse, normal, co, compute_board_shadow() );\n"
+"}\n"
+"\n"
+"#line     17        0 \n"
+"#line       1        3 \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     18        0 \n"
+"\n"
+"vec4 water_surf( vec3 halfview, vec3 vnorm, float depthvalue, \n"
+"                 vec4 beneath, vec4 above )\n"
+"{\n"
+"   vec3 surface_tint = mix(uShoreColour, uOceanColour, depthvalue);\n"
+"\n"
+"   float ffresnel = pow(1.0-dot( vnorm, halfview ),5.0);\n"
+"\n"
+"   vec3 lightdir = vec3(0.95,0.0,-0.3);\n"
+"   vec3 specdir = reflect( -lightdir, vnorm );\n"
+"   float spec = pow(max(dot(halfview,specdir),0.0),20.0)*0.3;\n"
+"   \n"
+"   // Depth \n"
+"   float depthblend = pow( beneath.r, 0.8 );\n"
+"\n"
+"   // Composite\n"
+"   vec3 vsurface = mix(surface_tint, above.rgb, ffresnel );\n"
+"   //vsurface += spec;\n"
+"\n"
+"   return vec4( vsurface,depthblend );\n"
+"}\n"
+"\n"
+"void main()\n"
+"{\n"
+"   compute_motion_vectors();\n"
+"\n"
+"   // Create texture coords\n"
+"   vec2 ssuv = gl_FragCoord.xy*uInvRes;\n"
+"   \n"
+"   // Surface colour composite\n"
+"   float depthvalue = clamp( -world_water_depth(aCo)*(1.0/25.0), 0.0,1.0 );\n"
+"\n"
+"   vec2 world_coord = aCo.xz * 0.008;\n"
+"   vec4 time_offsets = vec4( uTime ) * vec4( 0.008, 0.006, 0.003, 0.03 );\n"
+"   vec4 dudva = texture( uTexDudv, world_coord + time_offsets.xy )-0.5;\n"
+"   vec4 dudvb = texture( uTexDudv, world_coord *7.0 - time_offsets.zw )-0.5;\n"
+"\n"
+"   vec3 surfnorm = dudva.rgb + dudvb.rgb;\n"
+"   surfnorm = normalize(vec3(0.0,1.0,0.0) + dudva.xyz*0.4 + dudvb.xyz*0.1);\n"
+"   \n"
+"   // Foam\n"
+"   float fband = fract( aCo.z*0.02+uTime*0.1+depthvalue*10.0 );\n"
+"   fband = step( fband+dudva.a*0.8, 0.3 ) * max((1.0-depthvalue*4.0),0.0);\n"
+"\n"
+"   // Lighting\n"
+"   vec3 halfview = -normalize( aCo-uCamera );\n"
+"\n"
+"   // Sample textures\n"
+"   vec4 above = texture( uTexMain, ssuv+ surfnorm.xz*0.2 );\n"
+"   vec4 beneath = texture( uTexBack, ssuv );\n"
+"\n"
+"   // Fog\n"
+"   float fdist = pow(length( aCo.xz-uCamera.xz ) * 0.00047, 2.6);\n"
+"\n"
+"   // Composite\n"
+"   vec4 vsurface = water_surf( halfview, surfnorm, depthvalue, beneath, above );\n"
+"   vsurface.a -= fdist;\n"
+"   oColour = mix( vsurface, vec4(1.0,1.0,1.0,0.5), fband );\n"
+"   oColour.rgb = scene_compute_lighting( oColour.rgb, aNorm.xyz, aWorldCo );\n"
+"}\n"
+""},
+};
+
+GLuint _uniform_scene_water_uMdl;
+GLuint _uniform_scene_water_uPv;
+GLuint _uniform_scene_water_uPvmPrev;
+GLuint _uniform_scene_water_uTexMain;
+GLuint _uniform_scene_water_uTexDudv;
+GLuint _uniform_scene_water_uTexBack;
+GLuint _uniform_scene_water_uInvRes;
+GLuint _uniform_scene_water_uTime;
+GLuint _uniform_scene_water_uCamera;
+GLuint _uniform_scene_water_uSurfaceY;
+GLuint _uniform_scene_water_uBoard0;
+GLuint _uniform_scene_water_uBoard1;
+GLuint _uniform_scene_water_uShoreColour;
+GLuint _uniform_scene_water_uOceanColour;
+GLuint _uniform_scene_water_g_world_depth;
+GLuint _uniform_scene_water_uLightsArray;
+GLuint _uniform_scene_water_uLightsIndex;
+#include "shaders/scene_water_fast.h"
+struct vg_shader _shader_scene_water_fast = {
+   .name = "scene_water_fast",
+   .vs = 
+{
+.orig_file = "shaders/scene.vs",
+.static_src = 
+"layout (location=0) in vec3  a_co;\n"
+"layout (location=1) in vec4  a_norm;\n"
+"layout (location=2) in vec2  a_uv;\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      6        0 \n"
+"\n"
+"uniform mat4x3 uMdl;\n"
+"uniform mat4   uPv;\n"
+"uniform mat4   uPvmPrev;\n"
+"\n"
+"out vec2 aUv;\n"
+"out vec4 aNorm;\n"
+"out vec3 aCo;\n"
+"out vec3 aWorldCo;\n"
+"\n"
+"void main()\n"
+"{\n"
+"   vec3 world_pos0 = uMdl     * vec4( a_co, 1.0 );\n"
+"   vec4 vproj0     = uPv      * vec4( world_pos0, 1.0 );\n"
+"   vec4 vproj1     = uPvmPrev * vec4( a_co, 1.0 );\n"
+"\n"
+"   vs_motion_out( vproj0, vproj1 );\n"
+"\n"
+"   gl_Position = vproj0;\n"
+"\n"
+"   aUv = a_uv;\n"
+"   aNorm = vec4( mat3(uMdl) * a_norm.xyz, a_norm.w );\n"
+"   aCo = a_co;\n"
+"   aWorldCo = world_pos0;\n"
+"}\n"
+""},
+   .fs = 
+{
+.orig_file = "shaders/scene_water_fast.fs",
+.static_src = 
+"uniform sampler2D uTexDudv;\n"
+"\n"
+"uniform float uTime;\n"
+"uniform vec3 uCamera;\n"
+"uniform float uSurfaceY;\n"
+"uniform vec3 uBoard0;\n"
+"uniform vec3 uBoard1;\n"
+"\n"
+"uniform vec3 uShoreColour;\n"
+"uniform vec3 uOceanColour;\n"
+"\n"
+"#line       1        1 \n"
+"// :D\n"
+"const float CLEARSKIES_LIGHT_DOT_MIN = 0.0;\n"
+"\n"
+"#line     13        0 \n"
+"#line       1        2 \n"
+"// :D\n"
+"\n"
+"in vec2 aUv;\n"
+"in vec4 aNorm;\n"
+"in vec3 aCo;\n"
+"in vec3 aWorldCo;\n"
+"\n"
+"#line       1        1 \n"
+"layout (location = 0) out vec4 oColour;\n"
+"\n"
+"// OpenGL wiki: Recommends do not use vec3 because of drivers. hence the v4s...\n"
+"layout (std140) uniform ub_world_lighting\n"
+"{\n"
+"   vec4 g_cube_min;\n"
+"   vec4 g_cube_inv_range;\n"
+"\n"
+"   vec4 g_water_plane;\n"
+"   vec4 g_depth_bounds;\n"
+"\n"
+"   vec4 g_daysky_colour;\n"
+"   vec4 g_nightsky_colour;\n"
+"   vec4 g_sunset_colour;\n"
+"   vec4 g_ambient_colour;\n"
+"   vec4 g_sunset_ambient;\n"
+"   vec4 g_sun_colour;\n"
+"   vec4 g_sun_dir;\n"
+"   vec4 g_board_0;\n"
+"   vec4 g_board_1;\n"
+"\n"
+"   float g_water_fog;\n"
+"   float g_time;\n"
+"   float g_realtime;\n"
+"   float g_shadow_length;\n"
+"   float g_shadow_spread;\n"
+"\n"
+"   float g_time_of_day;\n"
+"   float g_day_phase;\n"
+"   float g_sunset_phase;\n"
+"\n"
+"   int g_light_preview;\n"
+"   int g_shadow_samples;\n"
+"\n"
+"   int g_debug_indices;\n"
+"   int g_debug_complexity;\n"
+"};\n"
+"\n"
+"uniform sampler2D g_world_depth;\n"
+"uniform samplerBuffer uLightsArray;\n"
+"uniform usampler3D uLightsIndex;\n"
+"\n"
+"#line       1        1 \n"
+"//const vec3  DAYSKY_COLOUR   = vec3( 0.37, 0.54, 0.97 );\n"
+"//const vec3  NIGHTSKY_COLOUR = vec3( 0.03, 0.05, 0.20 );\n"
+"//const vec3  SUNSET_COLOUR   = vec3( 1.00, 0.32, 0.01 );\n"
+"//const vec3  AMBIENT_COLOUR  = vec3( 0.13, 0.17, 0.35 );\n"
+"//const vec3  SUNSET_AMBIENT  = vec3( 0.25, 0.17, 0.51 );\n"
+"//const vec3  SUN_COLOUR      = vec3( 1.10, 0.89, 0.35 );\n"
+"\n"
+"const float SUN_ANGLE       = 0.0001;\n"
+"const float PI              = 3.14159265358979323846264;\n"
+"\n"
+"//struct world_info\n"
+"//{\n"
+"//   float time,\n"
+"//         time_of_day,\n"
+"//         day_phase,\n"
+"//         sunset_phase;\n"
+"//   \n"
+"//   vec3 sun_dir;\n"
+"//};\n"
+"\n"
+"vec3 rand33(vec3 p3)\n"
+"{\n"
+"      p3 = fract(p3 * vec3(.1031, .1030, .0973));\n"
+"   p3 += dot(p3, p3.yxz+33.33);\n"
+"   return fract((p3.xxy + p3.yxx)*p3.zyx);\n"
+"}\n"
+"\n"
+"float stars( vec3 rd, float rr, float size ){\n"
+"   vec3 co = rd * rr;\n"
+"\n"
+"   float a = atan(co.y, length(co.xz)) + 4.0 * PI;\n"
+"\n"
+"   float spaces = 1.0 / rr;\n"
+"   size = (rr * 0.0015) * fwidth(a) * 1000.0 * size;\n"
+"   a -= mod(a, spaces) - spaces * 0.5;\n"
+"\n"
+"   float count = floor(sqrt(pow(rr, 2.0) * (1.0 - pow(sin(a), 2.0))) * 3.0);\n"
+"   \n"
+"   float plane = atan(co.z, co.x) + 4.0 * PI;\n"
+"   plane = plane - mod(plane, PI / count);\n"
+"\n"
+"   vec2 delta = rand33(vec3(plane, a, 0.0)).xy;\n"
+"\n"
+"   float level = sin(a + spaces * (delta.y - 0.5) * (1.0 - size)) * rr;\n"
+"   float ydist = sqrt(rr * rr - level * level);\n"
+"   float angle = plane + (PI * (delta.x * (1.0-size) + size * 0.5) / count);\n"
+"   vec3 center = vec3(cos(angle) * ydist, level, sin(angle) * ydist);\n"
+"   float star = smoothstep(size, 0.0, distance(center, co));\n"
+"   return star;\n"
+"}\n"
+"\n"
+"float luminance( vec3 v )\n"
+"{\n"
+"   return dot( v, vec3(0.2126, 0.7152, 0.0722) );\n"
+"}\n"
+"\n"
+"vec3 clearskies_ambient( vec3 dir )\n"
+"{\n"
+"   float sun_azimuth  = g_sunset_phase * (dot( dir.xz, g_sun_dir.xz )*0.4+0.6);\n"
+"   float sky_gradient = dir.y;\n"
+"   \n"
+"   /* Blend phase colours */\n"
+"   vec3 ambient  = g_daysky_colour.rgb   * (g_day_phase-g_sunset_phase*0.1);\n"
+"        ambient += g_sunset_colour.rgb   * (1.0-dir.y*0.5)*sun_azimuth;\n"
+"        ambient += g_nightsky_colour.rgb * (1.0-g_day_phase);\n"
+"   \n"
+"   /* Add gradient */\n"
+"        ambient -= sky_gradient * luminance(ambient);\n"
+"        \n"
+"   return ambient;\n"
+"}\n"
+"\n"
+"vec3 clearskies_sky( vec3 ray_dir )\n"
+"{\n"
+"   ray_dir.y = abs( ray_dir.y );\n"
+"   vec3 sky_colour  = clearskies_ambient( ray_dir );\n"
+"   \n"
+"   /* Sun */\n"
+"   float sun_theta  = dot( ray_dir, g_sun_dir.xyz );\n"
+"   float sun_size   = max( 0.0, sun_theta * 0.5 + 0.5 + SUN_ANGLE );\n"
+"   float sun_shape  = pow( sun_size, 2000.0 );\n"
+"         sun_shape += sun_size * max(g_sun_dir.y,0.0) * 0.5;\n"
+"         \n"
+"   vec3 sun_colour  = mix( vec3(1.0), g_sunset_colour.rgb, g_sunset_phase*0.5 );\n"
+"        sun_colour *= sun_shape;\n"
+"\n"
+"   \n"
+"   float star = 0.0;\n"
+"   float star_blend = 10.0*max(0.0,(1.0-g_day_phase*2.0));\n"
+"\n"
+"   if( star_blend > 0.001 ){\n"
+"      for( float j = 1.0; j <= 4.1; j += 1.0 ){\n"
+"         float m = mix(0.6, 0.9, smoothstep(1.0, 2.0, j));\n"
+"         star += stars( ray_dir, 1.94 * pow( 1.64, j ), m ) * (1.0/pow(4.0, j));\n"
+"      }\n"
+"   }\n"
+"   \n"
+"   vec3 composite   = sky_colour + sun_colour + star*star_blend;\n"
+"   return composite;\n"
+"}\n"
+"\n"
+"vec3 clearskies_lighting( vec3 normal, float shadow, vec3 halfview )\n"
+"{\n"
+"   float fresnel = 1.0 - abs(dot(normal,halfview));\n"
+"\n"
+"   vec3  reflect_colour = mix( g_daysky_colour.rgb, g_sunset_colour.rgb, \n"
+"                               g_sunset_phase );\n"
+"\n"
+"   vec3  sky_reflection = 0.5 * fresnel * reflect_colour;\n"
+"   vec3  light_sun      = max( CLEARSKIES_LIGHT_DOT_MIN, \n"
+"                               dot(normal,g_sun_dir.xyz)*0.75+0.25\n"
+"                           ) * g_sun_colour.rgb * g_day_phase;\n"
+"\n"
+"   float scaled_shadow = max( shadow, 1.0 - max(g_sun_dir.y,0.0) );\n"
+"   vec3 ambient = mix( g_ambient_colour.rgb, g_sunset_ambient.rgb, \n"
+"                       g_sunset_phase );\n"
+"\n"
+"   return ambient + (light_sun + sky_reflection) * shadow;\n"
+"}\n"
+"\n"
+"#line     44        0 \n"
+"\n"
+"float world_depth_sample( vec3 pos )\n"
+"{\n"
+"   vec2 depth_coord = (pos.xz - g_depth_bounds.xy) * g_depth_bounds.zw; \n"
+"   return texture( g_world_depth, depth_coord ).r;\n"
+"}\n"
+"\n"
+"float world_water_depth( vec3 pos )\n"
+"{\n"
+"   float ref_depth = g_water_plane.y*g_water_plane.w;\n"
+"   return world_depth_sample( pos ) - ref_depth;\n"
+"}\n"
+"\n"
+"float shadow_sample( vec3 co ){\n"
+"   float height_sample = world_depth_sample( co );\n"
+"\n"
+"   float fdelta = height_sample - co.y;\n"
+"   return clamp( fdelta, 0.2, 0.4 )-0.2;\n"
+"}\n"
+"\n"
+"float newlight_compute_sun_shadow( vec3 co, vec3 dir ){\n"
+"   if( g_shadow_samples == 0 ){\n"
+"      return 1.0;\n"
+"   }\n"
+"\n"
+"   float fspread = g_shadow_spread;\n"
+"   float flength = g_shadow_length;\n"
+"\n"
+"   float famt = 0.0;\n"
+"   famt += shadow_sample(co+(dir+vec3(-0.56,0.55, 0.30)*fspread)*flength*0.1);\n"
+"   famt += shadow_sample(co+(dir+vec3( 0.80,0.68, 0.34)*fspread)*flength*0.2);\n"
+"   famt += shadow_sample(co+(dir+vec3( 0.78,0.07,-0.06)*fspread)*flength*0.3);\n"
+"   famt += shadow_sample(co+(dir+vec3(-0.59,0.07,-0.42)*fspread)*flength*0.4);\n"
+"\n"
+"   //famt+=shadow_sample(co+(dir+vec3(-0.790,-0.933,-0.875)*fspread)*flength*0.5);\n"
+"   //famt+=shadow_sample(co+(dir+vec3( 0.807,-0.690, 0.472)*fspread)*flength*0.6);\n"
+"   //famt+=shadow_sample(co+(dir+vec3( 0.522,-0.379, 0.350)*fspread)*flength*0.7);\n"
+"   //famt+=shadow_sample(co+(dir+vec3( 0.483, 0.201, 0.306)*fspread)*flength*0.8);\n"
+"\n"
+"   return 1.0 - famt;\n"
+"}\n"
+"\n"
+"float newlight_specular( vec3 wnormal, vec3 dir, vec3 halfview, float exponent )\n"
+"{\n"
+"   vec3 specdir = reflect( -dir, wnormal );\n"
+"   return pow(max(dot( halfview, specdir ), 0.0), exponent);\n"
+"}\n"
+"\n"
+"vec3 scene_apply_fog( vec3 vfrag, vec3 colour, float fdist ){\n"
+"   float dist = pow(fdist*0.0010,0.78);\n"
+"   return mix( vfrag, colour, min( 1.0, dist ) );\n"
+"}\n"
+"\n"
+"vec3 scene_calculate_light( int light_index, \n"
+"                            vec3 halfview, vec3 co, vec3 normal )\n"
+"{\n"
+"   vec4 light_colour = texelFetch( uLightsArray, light_index+0 );\n"
+"   vec4 light_co     = texelFetch( uLightsArray, light_index+1 );\n"
+"   vec4 light_dir    = texelFetch( uLightsArray, light_index+2 );\n"
+"\n"
+"   vec3 light_delta = light_co.xyz-co;\n"
+"   float dist2 = dot(light_delta,light_delta);\n"
+"\n"
+"   light_delta = normalize( light_delta );\n"
+"\n"
+"   float quadratic = dist2*100.0;\n"
+"   float attenuation  = 1.0/( 1.0 + quadratic );\n"
+"         attenuation *= max( dot( light_delta, normal ), 0.0 );\n"
+"\n"
+"   float falloff = max( 0.0, 1.0-(dist2*light_co.w) );\n"
+"\n"
+"   if( light_dir.w < 0.999999 ){\n"
+"      float spot_theta = max( 0.0, dot( light_delta, -light_dir.xyz ) );\n"
+"      falloff *= max( 0.0, (spot_theta - light_dir.w) / (1.0-light_dir.w) );\n"
+"   }\n"
+"\n"
+"   return light_colour.rgb * attenuation * falloff \n"
+"            * step( g_day_phase, light_colour.w );\n"
+"}\n"
+"\n"
+"vec3 scene_calculate_packed_light_patch( uint packed_index, \n"
+"                                         vec3 halfview, vec3 co, vec3 normal )\n"
+"{\n"
+"   uint light_count = packed_index & 0x3u;\n"
+"\n"
+"   vec3 l = vec3(0.0);\n"
+"\n"
+"   if( light_count >= 1u ){\n"
+"      int index_0 = int( ((packed_index >>  2u) & 0x3ffu) * 3u );\n"
+"      int index_1 = int( ((packed_index >> 12u) & 0x3ffu) * 3u );\n"
+"      int index_2 = int( ((packed_index >> 22u) & 0x3ffu) * 3u );\n"
+"\n"
+"      l += scene_calculate_light( index_0, halfview, co, normal );\n"
+"\n"
+"      if( light_count >= 2u ){\n"
+"         l += scene_calculate_light( index_1, halfview, co, normal );\n"
+"\n"
+"         if( light_count >= 3u ){\n"
+"            l += scene_calculate_light( index_2, halfview, co, normal );\n"
+"         }\n"
+"      }\n"
+"   }\n"
+"\n"
+"   return l;\n"
+"}\n"
+"\n"
+"vec3 world_compute_lighting( vec3 diffuse, vec3 normal, vec3 co,\n"
+"                             float light_mask )\n"
+"{\n"
+"   if( g_light_preview == 1 )\n"
+"      diffuse = vec3(0.75);\n"
+"\n"
+"   // Lighting\n"
+"   vec3 halfview = uCamera - co;\n"
+"   float fdist = length(halfview);\n"
+"   halfview /= fdist;\n"
+"\n"
+"   float world_shadow = newlight_compute_sun_shadow( \n"
+"               co, g_sun_dir.xyz * (1.0/(max(g_sun_dir.y,0.0)+0.2)) );\n"
+"\n"
+"   vec3 total_light = clearskies_lighting( \n"
+"                           normal, min( light_mask, world_shadow ), halfview );\n"
+"\n"
+"   vec3 cube_coord = (co - g_cube_min.xyz) * g_cube_inv_range.xyz;\n"
+"        cube_coord = floor( cube_coord );\n"
+"\n"
+"   if( g_debug_indices == 1 )\n"
+"   {\n"
+"      return rand33(cube_coord);\n"
+"   }\n"
+"\n"
+"   if( g_debug_complexity == 1 )\n"
+"   {\n"
+"      ivec3 coord = ivec3( cube_coord );\n"
+"      uvec4 index_sample = texelFetch( uLightsIndex, coord, 0 );\n"
+"\n"
+"      uint light_count = (index_sample.x & 0x3u) + (index_sample.y & 0x3u);\n"
+"      return vec3( float(light_count)*(1.0/6.0), 0.0, 0.5 );\n"
+"   }\n"
+"\n"
+"   // FIXME: this coord should absolutely must be clamped!\n"
+"   \n"
+"   ivec3 coord = ivec3( cube_coord );\n"
+"   uvec4 index_sample = texelFetch( uLightsIndex, coord, 0 );\n"
+"\n"
+"   total_light += \n"
+"      scene_calculate_packed_light_patch( index_sample.x,\n"
+"                                          halfview, co, normal ) \n"
+"                                          * light_mask;\n"
+"   total_light += \n"
+"      scene_calculate_packed_light_patch( index_sample.y,\n"
+"                                          halfview, co, normal )\n"
+"                                          * light_mask;\n"
+"\n"
+"   // Take a section of the sky function to give us a matching fog colour\n"
+"\n"
+"   vec3 fog_colour  = clearskies_ambient( -halfview );\n"
+"   float sun_theta  = dot( -halfview, g_sun_dir.xyz );\n"
+"   float sun_size   = max( 0.0, sun_theta * 0.5 + 0.5 );\n"
+"   float sun_shape  = sun_size * max(g_sun_dir.y,0.0) * 0.5;\n"
+"         \n"
+"   vec3 sun_colour  = mix( vec3(1.0), g_sunset_colour.rgb, g_sunset_phase*0.5 );\n"
+"        sun_colour *= sun_shape;\n"
+"\n"
+"   fog_colour += sun_colour;\n"
+"   return scene_apply_fog( diffuse * total_light, fog_colour, fdist );\n"
+"}\n"
+"\n"
+"#line      9        0 \n"
+"\n"
+"float sdLine( vec3 p, vec3 a, vec3 b )\n"
+"{\n"
+"  vec3 pa = p - a;\n"
+"  vec3 ba = b - a;\n"
+"\n"
+"  float h = clamp( dot(pa,ba)/dot(ba,ba), 0.0, 1.0 );\n"
+"  return length( pa - ba*h );\n"
+"}\n"
+"\n"
+"float compute_board_shadow()\n"
+"{\n"
+"   // player shadow\n"
+"   float dist_to_player = max( 0.0, sdLine( aWorldCo, g_board_0.xyz,\n"
+"                                                      g_board_1.xyz )-0.1 );\n"
+"   float player_shadow = max( 1.0-dist_to_player*2.7, 0.0 );\n"
+"   player_shadow *= player_shadow*player_shadow*player_shadow;\n"
+"\n"
+"   return 1.0 - player_shadow*0.8;\n"
+"}\n"
+"\n"
+"vec3 scene_compute_lighting( vec3 diffuse, vec3 normal, vec3 co )\n"
+"{\n"
+"   return world_compute_lighting( diffuse, normal, co, compute_board_shadow() );\n"
+"}\n"
+"\n"
+"#line     14        0 \n"
+"#line       1        3 \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     15        0 \n"
+"\n"
+"vec4 water_surf( vec3 halfview, vec3 vnorm, float depthvalue )\n"
+"{\n"
+"   vec3 surface_tint = mix(uShoreColour, uOceanColour, depthvalue);\n"
+"\n"
+"   float ffresnel = pow(1.0-dot( vnorm, halfview ),5.0);\n"
+"\n"
+"   vec3 lightdir = vec3(0.95,0.0,-0.3);\n"
+"   vec3 specdir = reflect( -lightdir, vnorm );\n"
+"   float spec = pow(max(dot(halfview,specdir),0.0),20.0)*0.3;\n"
+"   \n"
+"   return vec4( surface_tint + spec, max(min(depthvalue*4.0, 1.0),0.0) );\n"
+"}\n"
+"\n"
+"void main()\n"
+"{\n"
+"   compute_motion_vectors();\n"
+"\n"
+"   // Surface colour composite\n"
+"   float depthvalue = clamp( -world_water_depth( aCo )*(1.0/25.0), 0.0, 1.0 );\n"
+"\n"
+"   vec2 world_coord = aCo.xz * 0.008;\n"
+"   vec4 time_offsets = vec4( uTime ) * vec4( 0.008, 0.006, 0.003, 0.03 );\n"
+"   vec4 dudva = texture( uTexDudv, world_coord + time_offsets.xy )-0.5;\n"
+"   vec4 dudvb = texture( uTexDudv, world_coord *7.0 - time_offsets.zw )-0.5;\n"
+"\n"
+"   vec3 surfnorm = dudva.rgb + dudvb.rgb;\n"
+"   surfnorm = normalize(vec3(0.0,1.0,0.0) + dudva.xyz*0.4 + dudvb.xyz*0.1);\n"
+"   \n"
+"   // Foam\n"
+"   float fband = fract( aCo.z*0.02+uTime*0.1+depthvalue*10.0 );\n"
+"   fband = step( fband+dudva.a*0.8, 0.3 ) * max((1.0-depthvalue*4.0),0.0);\n"
+"\n"
+"   // Lighting\n"
+"   vec3 halfview = -normalize( aCo-uCamera );\n"
+"\n"
+"   // Fog\n"
+"   float fdist = pow(length( aCo.xz-uCamera.xz ) * 0.00047, 2.6);\n"
+"\n"
+"   // Composite\n"
+"   vec4 vsurface = water_surf( halfview, surfnorm, depthvalue );\n"
+"   vsurface.a -= fdist;\n"
+"   oColour = mix( vsurface, vec4(1.0,1.0,1.0,0.5), fband );\n"
+"   oColour.rgb = scene_compute_lighting( oColour.rgb, aNorm.xyz, aWorldCo );\n"
+"}\n"
+""},
+};
+
+GLuint _uniform_scene_water_fast_uMdl;
+GLuint _uniform_scene_water_fast_uPv;
+GLuint _uniform_scene_water_fast_uPvmPrev;
+GLuint _uniform_scene_water_fast_uTexDudv;
+GLuint _uniform_scene_water_fast_uTime;
+GLuint _uniform_scene_water_fast_uCamera;
+GLuint _uniform_scene_water_fast_uSurfaceY;
+GLuint _uniform_scene_water_fast_uBoard0;
+GLuint _uniform_scene_water_fast_uBoard1;
+GLuint _uniform_scene_water_fast_uShoreColour;
+GLuint _uniform_scene_water_fast_uOceanColour;
+GLuint _uniform_scene_water_fast_g_world_depth;
+GLuint _uniform_scene_water_fast_uLightsArray;
+GLuint _uniform_scene_water_fast_uLightsIndex;
+#include "shaders/scene_scoretext.h"
+struct vg_shader _shader_scene_scoretext = {
+   .name = "scene_scoretext",
+   .vs = 
+{
+.orig_file = "shaders/scene_sfd.vs",
+.static_src = 
+"layout (location=0) in vec3  a_co;\n"
+"layout (location=1) in vec4  a_norm;\n"
+"layout (location=2) in vec2  a_uv;\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      6        0 \n"
+"\n"
+"uniform mat4x3 uMdl;\n"
+"uniform mat4   uPv;\n"
+"uniform mat4   uPvmPrev;\n"
+"uniform vec3   uInfo;\n"
+"\n"
+"out vec2 aUv;\n"
+"out vec4 aNorm;\n"
+"out vec3 aCo;\n"
+"out vec3 aWorldCo;\n"
+"\n"
+"void main()\n"
+"{\n"
+"   float w = ((a_norm.w)-0.5)*2.0 + fract(uInfo.z) - 0.0;\n"
+"   float c = -cos(w*0.6);\n"
+"   float s = -sin(w*0.6);\n"
+"   float r = 0.2;\n"
+"\n"
+"   float w1 = clamp( w*4.0 - a_co.y*10.0, -1.0, 1.0 ) * (3.14159265*0.5);\n"
+"   float c1 = cos(w1);\n"
+"   float s1 = sin(w1);\n"
+"\n"
+"   float yoff = step(0.01,fract(uInfo.z))*-0.5;\n"
+"\n"
+"   mat4x3 mlocal;\n"
+"   mlocal[0] = vec3(c1, s1,0.0);\n"
+"   mlocal[1] = vec3(-s1,c1,0.0);\n"
+"   mlocal[2] = vec3(0.0,0.0,1.0);\n"
+"   mlocal[3] = vec3(c*r,uInfo.y*0.875 + s*r,uInfo.x*0.5);\n"
+"\n"
+"   vec3 local_pos0 = mlocal * vec4( a_co, 1.0 );\n"
+"   vec3 world_pos0 = uMdl * vec4( local_pos0, 1.0 );\n"
+"\n"
+"   vec4 vproj0     = uPv      * vec4( world_pos0, 1.0 );\n"
+"   vec4 vproj1     = uPvmPrev * vec4( local_pos0, 1.0 );\n"
+"\n"
+"   vs_motion_out( vproj0, vproj1 );\n"
+"\n"
+"   gl_Position = vproj0;\n"
+"\n"
+"   aUv = a_uv + vec2( floor(uInfo.z+0.5)*(1.0/64.0), yoff );\n"
+"   aNorm = vec4( mat3(uMdl) * mat3(mlocal) * a_norm.xyz, a_norm.w );\n"
+"   aCo = a_co;\n"
+"   aWorldCo = world_pos0;\n"
+"}\n"
+""},
+   .fs = 
+{
+.orig_file = "shaders/scene_standard.fs",
+.static_src = 
+"uniform sampler2D uTexGarbage;\n"
+"uniform sampler2D uTexMain;\n"
+"uniform vec3 uCamera;\n"
+"uniform vec4 uPlane;\n"
+"\n"
+"#line       1        1 \n"
+"// :D\n"
+"const float CLEARSKIES_LIGHT_DOT_MIN = 0.0;\n"
+"\n"
+"#line      7        0 \n"
+"#line       1        2 \n"
+"// :D\n"
+"\n"
+"in vec2 aUv;\n"
+"in vec4 aNorm;\n"
+"in vec3 aCo;\n"
+"in vec3 aWorldCo;\n"
+"\n"
+"#line       1        1 \n"
+"layout (location = 0) out vec4 oColour;\n"
+"\n"
+"// OpenGL wiki: Recommends do not use vec3 because of drivers. hence the v4s...\n"
+"layout (std140) uniform ub_world_lighting\n"
+"{\n"
+"   vec4 g_cube_min;\n"
+"   vec4 g_cube_inv_range;\n"
+"\n"
+"   vec4 g_water_plane;\n"
+"   vec4 g_depth_bounds;\n"
+"\n"
+"   vec4 g_daysky_colour;\n"
+"   vec4 g_nightsky_colour;\n"
+"   vec4 g_sunset_colour;\n"
+"   vec4 g_ambient_colour;\n"
+"   vec4 g_sunset_ambient;\n"
+"   vec4 g_sun_colour;\n"
+"   vec4 g_sun_dir;\n"
+"   vec4 g_board_0;\n"
+"   vec4 g_board_1;\n"
+"\n"
+"   float g_water_fog;\n"
+"   float g_time;\n"
+"   float g_realtime;\n"
+"   float g_shadow_length;\n"
+"   float g_shadow_spread;\n"
+"\n"
+"   float g_time_of_day;\n"
+"   float g_day_phase;\n"
+"   float g_sunset_phase;\n"
+"\n"
+"   int g_light_preview;\n"
+"   int g_shadow_samples;\n"
+"\n"
+"   int g_debug_indices;\n"
+"   int g_debug_complexity;\n"
+"};\n"
+"\n"
+"uniform sampler2D g_world_depth;\n"
+"uniform samplerBuffer uLightsArray;\n"
+"uniform usampler3D uLightsIndex;\n"
+"\n"
+"#line       1        1 \n"
+"//const vec3  DAYSKY_COLOUR   = vec3( 0.37, 0.54, 0.97 );\n"
+"//const vec3  NIGHTSKY_COLOUR = vec3( 0.03, 0.05, 0.20 );\n"
+"//const vec3  SUNSET_COLOUR   = vec3( 1.00, 0.32, 0.01 );\n"
+"//const vec3  AMBIENT_COLOUR  = vec3( 0.13, 0.17, 0.35 );\n"
+"//const vec3  SUNSET_AMBIENT  = vec3( 0.25, 0.17, 0.51 );\n"
+"//const vec3  SUN_COLOUR      = vec3( 1.10, 0.89, 0.35 );\n"
+"\n"
+"const float SUN_ANGLE       = 0.0001;\n"
+"const float PI              = 3.14159265358979323846264;\n"
+"\n"
+"//struct world_info\n"
+"//{\n"
+"//   float time,\n"
+"//         time_of_day,\n"
+"//         day_phase,\n"
+"//         sunset_phase;\n"
+"//   \n"
+"//   vec3 sun_dir;\n"
+"//};\n"
+"\n"
+"vec3 rand33(vec3 p3)\n"
+"{\n"
+"      p3 = fract(p3 * vec3(.1031, .1030, .0973));\n"
+"   p3 += dot(p3, p3.yxz+33.33);\n"
+"   return fract((p3.xxy + p3.yxx)*p3.zyx);\n"
+"}\n"
+"\n"
+"float stars( vec3 rd, float rr, float size ){\n"
+"   vec3 co = rd * rr;\n"
+"\n"
+"   float a = atan(co.y, length(co.xz)) + 4.0 * PI;\n"
+"\n"
+"   float spaces = 1.0 / rr;\n"
+"   size = (rr * 0.0015) * fwidth(a) * 1000.0 * size;\n"
+"   a -= mod(a, spaces) - spaces * 0.5;\n"
+"\n"
+"   float count = floor(sqrt(pow(rr, 2.0) * (1.0 - pow(sin(a), 2.0))) * 3.0);\n"
+"   \n"
+"   float plane = atan(co.z, co.x) + 4.0 * PI;\n"
+"   plane = plane - mod(plane, PI / count);\n"
+"\n"
+"   vec2 delta = rand33(vec3(plane, a, 0.0)).xy;\n"
+"\n"
+"   float level = sin(a + spaces * (delta.y - 0.5) * (1.0 - size)) * rr;\n"
+"   float ydist = sqrt(rr * rr - level * level);\n"
+"   float angle = plane + (PI * (delta.x * (1.0-size) + size * 0.5) / count);\n"
+"   vec3 center = vec3(cos(angle) * ydist, level, sin(angle) * ydist);\n"
+"   float star = smoothstep(size, 0.0, distance(center, co));\n"
+"   return star;\n"
+"}\n"
+"\n"
+"float luminance( vec3 v )\n"
+"{\n"
+"   return dot( v, vec3(0.2126, 0.7152, 0.0722) );\n"
+"}\n"
+"\n"
+"vec3 clearskies_ambient( vec3 dir )\n"
+"{\n"
+"   float sun_azimuth  = g_sunset_phase * (dot( dir.xz, g_sun_dir.xz )*0.4+0.6);\n"
+"   float sky_gradient = dir.y;\n"
+"   \n"
+"   /* Blend phase colours */\n"
+"   vec3 ambient  = g_daysky_colour.rgb   * (g_day_phase-g_sunset_phase*0.1);\n"
+"        ambient += g_sunset_colour.rgb   * (1.0-dir.y*0.5)*sun_azimuth;\n"
+"        ambient += g_nightsky_colour.rgb * (1.0-g_day_phase);\n"
+"   \n"
+"   /* Add gradient */\n"
+"        ambient -= sky_gradient * luminance(ambient);\n"
+"        \n"
+"   return ambient;\n"
+"}\n"
+"\n"
+"vec3 clearskies_sky( vec3 ray_dir )\n"
+"{\n"
+"   ray_dir.y = abs( ray_dir.y );\n"
+"   vec3 sky_colour  = clearskies_ambient( ray_dir );\n"
+"   \n"
+"   /* Sun */\n"
+"   float sun_theta  = dot( ray_dir, g_sun_dir.xyz );\n"
+"   float sun_size   = max( 0.0, sun_theta * 0.5 + 0.5 + SUN_ANGLE );\n"
+"   float sun_shape  = pow( sun_size, 2000.0 );\n"
+"         sun_shape += sun_size * max(g_sun_dir.y,0.0) * 0.5;\n"
+"         \n"
+"   vec3 sun_colour  = mix( vec3(1.0), g_sunset_colour.rgb, g_sunset_phase*0.5 );\n"
+"        sun_colour *= sun_shape;\n"
+"\n"
+"   \n"
+"   float star = 0.0;\n"
+"   float star_blend = 10.0*max(0.0,(1.0-g_day_phase*2.0));\n"
+"\n"
+"   if( star_blend > 0.001 ){\n"
+"      for( float j = 1.0; j <= 4.1; j += 1.0 ){\n"
+"         float m = mix(0.6, 0.9, smoothstep(1.0, 2.0, j));\n"
+"         star += stars( ray_dir, 1.94 * pow( 1.64, j ), m ) * (1.0/pow(4.0, j));\n"
+"      }\n"
+"   }\n"
+"   \n"
+"   vec3 composite   = sky_colour + sun_colour + star*star_blend;\n"
+"   return composite;\n"
+"}\n"
+"\n"
+"vec3 clearskies_lighting( vec3 normal, float shadow, vec3 halfview )\n"
+"{\n"
+"   float fresnel = 1.0 - abs(dot(normal,halfview));\n"
+"\n"
+"   vec3  reflect_colour = mix( g_daysky_colour.rgb, g_sunset_colour.rgb, \n"
+"                               g_sunset_phase );\n"
+"\n"
+"   vec3  sky_reflection = 0.5 * fresnel * reflect_colour;\n"
+"   vec3  light_sun      = max( CLEARSKIES_LIGHT_DOT_MIN, \n"
+"                               dot(normal,g_sun_dir.xyz)*0.75+0.25\n"
+"                           ) * g_sun_colour.rgb * g_day_phase;\n"
+"\n"
+"   float scaled_shadow = max( shadow, 1.0 - max(g_sun_dir.y,0.0) );\n"
+"   vec3 ambient = mix( g_ambient_colour.rgb, g_sunset_ambient.rgb, \n"
+"                       g_sunset_phase );\n"
+"\n"
+"   return ambient + (light_sun + sky_reflection) * shadow;\n"
+"}\n"
+"\n"
+"#line     44        0 \n"
+"\n"
+"float world_depth_sample( vec3 pos )\n"
+"{\n"
+"   vec2 depth_coord = (pos.xz - g_depth_bounds.xy) * g_depth_bounds.zw; \n"
+"   return texture( g_world_depth, depth_coord ).r;\n"
+"}\n"
+"\n"
+"float world_water_depth( vec3 pos )\n"
+"{\n"
+"   float ref_depth = g_water_plane.y*g_water_plane.w;\n"
+"   return world_depth_sample( pos ) - ref_depth;\n"
+"}\n"
+"\n"
+"float shadow_sample( vec3 co ){\n"
+"   float height_sample = world_depth_sample( co );\n"
+"\n"
+"   float fdelta = height_sample - co.y;\n"
+"   return clamp( fdelta, 0.2, 0.4 )-0.2;\n"
+"}\n"
+"\n"
+"float newlight_compute_sun_shadow( vec3 co, vec3 dir ){\n"
+"   if( g_shadow_samples == 0 ){\n"
+"      return 1.0;\n"
+"   }\n"
+"\n"
+"   float fspread = g_shadow_spread;\n"
+"   float flength = g_shadow_length;\n"
+"\n"
+"   float famt = 0.0;\n"
+"   famt += shadow_sample(co+(dir+vec3(-0.56,0.55, 0.30)*fspread)*flength*0.1);\n"
+"   famt += shadow_sample(co+(dir+vec3( 0.80,0.68, 0.34)*fspread)*flength*0.2);\n"
+"   famt += shadow_sample(co+(dir+vec3( 0.78,0.07,-0.06)*fspread)*flength*0.3);\n"
+"   famt += shadow_sample(co+(dir+vec3(-0.59,0.07,-0.42)*fspread)*flength*0.4);\n"
+"\n"
+"   //famt+=shadow_sample(co+(dir+vec3(-0.790,-0.933,-0.875)*fspread)*flength*0.5);\n"
+"   //famt+=shadow_sample(co+(dir+vec3( 0.807,-0.690, 0.472)*fspread)*flength*0.6);\n"
+"   //famt+=shadow_sample(co+(dir+vec3( 0.522,-0.379, 0.350)*fspread)*flength*0.7);\n"
+"   //famt+=shadow_sample(co+(dir+vec3( 0.483, 0.201, 0.306)*fspread)*flength*0.8);\n"
+"\n"
+"   return 1.0 - famt;\n"
+"}\n"
+"\n"
+"float newlight_specular( vec3 wnormal, vec3 dir, vec3 halfview, float exponent )\n"
+"{\n"
+"   vec3 specdir = reflect( -dir, wnormal );\n"
+"   return pow(max(dot( halfview, specdir ), 0.0), exponent);\n"
+"}\n"
+"\n"
+"vec3 scene_apply_fog( vec3 vfrag, vec3 colour, float fdist ){\n"
+"   float dist = pow(fdist*0.0010,0.78);\n"
+"   return mix( vfrag, colour, min( 1.0, dist ) );\n"
+"}\n"
+"\n"
+"vec3 scene_calculate_light( int light_index, \n"
+"                            vec3 halfview, vec3 co, vec3 normal )\n"
+"{\n"
+"   vec4 light_colour = texelFetch( uLightsArray, light_index+0 );\n"
+"   vec4 light_co     = texelFetch( uLightsArray, light_index+1 );\n"
+"   vec4 light_dir    = texelFetch( uLightsArray, light_index+2 );\n"
+"\n"
+"   vec3 light_delta = light_co.xyz-co;\n"
+"   float dist2 = dot(light_delta,light_delta);\n"
+"\n"
+"   light_delta = normalize( light_delta );\n"
+"\n"
+"   float quadratic = dist2*100.0;\n"
+"   float attenuation  = 1.0/( 1.0 + quadratic );\n"
+"         attenuation *= max( dot( light_delta, normal ), 0.0 );\n"
+"\n"
+"   float falloff = max( 0.0, 1.0-(dist2*light_co.w) );\n"
+"\n"
+"   if( light_dir.w < 0.999999 ){\n"
+"      float spot_theta = max( 0.0, dot( light_delta, -light_dir.xyz ) );\n"
+"      falloff *= max( 0.0, (spot_theta - light_dir.w) / (1.0-light_dir.w) );\n"
+"   }\n"
+"\n"
+"   return light_colour.rgb * attenuation * falloff \n"
+"            * step( g_day_phase, light_colour.w );\n"
+"}\n"
+"\n"
+"vec3 scene_calculate_packed_light_patch( uint packed_index, \n"
+"                                         vec3 halfview, vec3 co, vec3 normal )\n"
+"{\n"
+"   uint light_count = packed_index & 0x3u;\n"
+"\n"
+"   vec3 l = vec3(0.0);\n"
+"\n"
+"   if( light_count >= 1u ){\n"
+"      int index_0 = int( ((packed_index >>  2u) & 0x3ffu) * 3u );\n"
+"      int index_1 = int( ((packed_index >> 12u) & 0x3ffu) * 3u );\n"
+"      int index_2 = int( ((packed_index >> 22u) & 0x3ffu) * 3u );\n"
+"\n"
+"      l += scene_calculate_light( index_0, halfview, co, normal );\n"
+"\n"
+"      if( light_count >= 2u ){\n"
+"         l += scene_calculate_light( index_1, halfview, co, normal );\n"
+"\n"
+"         if( light_count >= 3u ){\n"
+"            l += scene_calculate_light( index_2, halfview, co, normal );\n"
+"         }\n"
+"      }\n"
+"   }\n"
+"\n"
+"   return l;\n"
+"}\n"
+"\n"
+"vec3 world_compute_lighting( vec3 diffuse, vec3 normal, vec3 co,\n"
+"                             float light_mask )\n"
+"{\n"
+"   if( g_light_preview == 1 )\n"
+"      diffuse = vec3(0.75);\n"
+"\n"
+"   // Lighting\n"
+"   vec3 halfview = uCamera - co;\n"
+"   float fdist = length(halfview);\n"
+"   halfview /= fdist;\n"
+"\n"
+"   float world_shadow = newlight_compute_sun_shadow( \n"
+"               co, g_sun_dir.xyz * (1.0/(max(g_sun_dir.y,0.0)+0.2)) );\n"
+"\n"
+"   vec3 total_light = clearskies_lighting( \n"
+"                           normal, min( light_mask, world_shadow ), halfview );\n"
+"\n"
+"   vec3 cube_coord = (co - g_cube_min.xyz) * g_cube_inv_range.xyz;\n"
+"        cube_coord = floor( cube_coord );\n"
+"\n"
+"   if( g_debug_indices == 1 )\n"
+"   {\n"
+"      return rand33(cube_coord);\n"
+"   }\n"
+"\n"
+"   if( g_debug_complexity == 1 )\n"
+"   {\n"
+"      ivec3 coord = ivec3( cube_coord );\n"
+"      uvec4 index_sample = texelFetch( uLightsIndex, coord, 0 );\n"
+"\n"
+"      uint light_count = (index_sample.x & 0x3u) + (index_sample.y & 0x3u);\n"
+"      return vec3( float(light_count)*(1.0/6.0), 0.0, 0.5 );\n"
+"   }\n"
+"\n"
+"   // FIXME: this coord should absolutely must be clamped!\n"
+"   \n"
+"   ivec3 coord = ivec3( cube_coord );\n"
+"   uvec4 index_sample = texelFetch( uLightsIndex, coord, 0 );\n"
+"\n"
+"   total_light += \n"
+"      scene_calculate_packed_light_patch( index_sample.x,\n"
+"                                          halfview, co, normal ) \n"
+"                                          * light_mask;\n"
+"   total_light += \n"
+"      scene_calculate_packed_light_patch( index_sample.y,\n"
+"                                          halfview, co, normal )\n"
+"                                          * light_mask;\n"
+"\n"
+"   // Take a section of the sky function to give us a matching fog colour\n"
+"\n"
+"   vec3 fog_colour  = clearskies_ambient( -halfview );\n"
+"   float sun_theta  = dot( -halfview, g_sun_dir.xyz );\n"
+"   float sun_size   = max( 0.0, sun_theta * 0.5 + 0.5 );\n"
+"   float sun_shape  = sun_size * max(g_sun_dir.y,0.0) * 0.5;\n"
+"         \n"
+"   vec3 sun_colour  = mix( vec3(1.0), g_sunset_colour.rgb, g_sunset_phase*0.5 );\n"
+"        sun_colour *= sun_shape;\n"
+"\n"
+"   fog_colour += sun_colour;\n"
+"   return scene_apply_fog( diffuse * total_light, fog_colour, fdist );\n"
+"}\n"
+"\n"
+"#line      9        0 \n"
+"\n"
+"float sdLine( vec3 p, vec3 a, vec3 b )\n"
+"{\n"
+"  vec3 pa = p - a;\n"
+"  vec3 ba = b - a;\n"
+"\n"
+"  float h = clamp( dot(pa,ba)/dot(ba,ba), 0.0, 1.0 );\n"
+"  return length( pa - ba*h );\n"
+"}\n"
+"\n"
+"float compute_board_shadow()\n"
+"{\n"
+"   // player shadow\n"
+"   float dist_to_player = max( 0.0, sdLine( aWorldCo, g_board_0.xyz,\n"
+"                                                      g_board_1.xyz )-0.1 );\n"
+"   float player_shadow = max( 1.0-dist_to_player*2.7, 0.0 );\n"
+"   player_shadow *= player_shadow*player_shadow*player_shadow;\n"
+"\n"
+"   return 1.0 - player_shadow*0.8;\n"
+"}\n"
+"\n"
+"vec3 scene_compute_lighting( vec3 diffuse, vec3 normal, vec3 co )\n"
+"{\n"
+"   return world_compute_lighting( diffuse, normal, co, compute_board_shadow() );\n"
+"}\n"
+"\n"
+"#line      8        0 \n"
+"#line       1        3 \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      9        0 \n"
+"\n"
+"void main()\n"
+"{\n"
+"   compute_motion_vectors();\n"
+"\n"
+"   vec3 vfrag = vec3(0.5,0.5,0.5);\n"
+"   vec4 vsamplemain = texture( uTexMain, aUv );\n"
+"   vec3 qnorm = aNorm.xyz;\n"
+"\n"
+"   vfrag = vsamplemain.rgb;\n"
+"\n"
+"   if( g_light_preview == 1 )\n"
+"   {\n"
+"      vfrag = vec3(0.5);\n"
+"   }\n"
+"\n"
+"   vfrag = scene_compute_lighting( vfrag, qnorm, aWorldCo );\n"
+"   oColour = vec4( vfrag, 1.0 );\n"
+"}\n"
+""},
+};
+
+GLuint _uniform_scene_scoretext_uMdl;
+GLuint _uniform_scene_scoretext_uPv;
+GLuint _uniform_scene_scoretext_uPvmPrev;
+GLuint _uniform_scene_scoretext_uInfo;
+GLuint _uniform_scene_scoretext_uTexGarbage;
+GLuint _uniform_scene_scoretext_uTexMain;
+GLuint _uniform_scene_scoretext_uCamera;
+GLuint _uniform_scene_scoretext_uPlane;
+GLuint _uniform_scene_scoretext_g_world_depth;
+GLuint _uniform_scene_scoretext_uLightsArray;
+GLuint _uniform_scene_scoretext_uLightsIndex;
+#include "shaders/scene_font.h"
+struct vg_shader _shader_scene_font = {
+   .name = "scene_font",
+   .vs = 
+{
+.orig_file = "shaders/model_font.vs",
+.static_src = 
+"layout (location=0) in vec3 a_co;\n"
+"layout (location=1) in vec3 a_norm;\n"
+"layout (location=2) in vec2 a_uv;\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      6        0 \n"
+"\n"
+"uniform mat4x3 uMdl;\n"
+"uniform mat4 uPv;\n"
+"uniform mat4 uPvmPrev;\n"
+"uniform vec4 uOffset;\n"
+"\n"
+"out vec2 aUv;\n"
+"out vec4 aNorm;\n"
+"out vec3 aCo;\n"
+"out vec3 aWorldCo;\n"
+"\n"
+"void main()\n"
+"{\n"
+"   vec3 co = a_co*uOffset.w+uOffset.xyz;\n"
+"   vec3 world_pos0 = uMdl     * vec4( co, 1.0 );\n"
+"   vec4 vproj0     = uPv      * vec4( world_pos0, 1.0 );\n"
+"   vec4 vproj1     = uPvmPrev * vec4( co, 1.0 );\n"
+"\n"
+"   vs_motion_out( vproj0, vproj1 );\n"
+"\n"
+"   gl_Position = vproj0;\n"
+"\n"
+"   aUv = a_uv;\n"
+"   aNorm = vec4( mat3(uMdl) * a_norm, 0.0 );\n"
+"   aCo = co;\n"
+"   aWorldCo = world_pos0;\n"
+"}\n"
+""},
+   .fs = 
+{
+.orig_file = "shaders/scene_font.fs",
+.static_src = 
+"uniform sampler2D uTexGarbage; // unused\n"
+"uniform sampler2D uTexMain;    // unused\n"
+"uniform vec3 uCamera;\n"
+"uniform float uTime;\n"
+"uniform float uOpacity;\n"
+"uniform float uColourize;\n"
+"\n"
+"#line       1        1 \n"
+"// :D\n"
+"const float CLEARSKIES_LIGHT_DOT_MIN = 0.0;\n"
+"\n"
+"#line      9        0 \n"
+"#line       1        2 \n"
+"// :D\n"
+"\n"
+"in vec2 aUv;\n"
+"in vec4 aNorm;\n"
+"in vec3 aCo;\n"
+"in vec3 aWorldCo;\n"
+"\n"
+"#line       1        1 \n"
+"layout (location = 0) out vec4 oColour;\n"
+"\n"
+"// OpenGL wiki: Recommends do not use vec3 because of drivers. hence the v4s...\n"
+"layout (std140) uniform ub_world_lighting\n"
+"{\n"
+"   vec4 g_cube_min;\n"
+"   vec4 g_cube_inv_range;\n"
+"\n"
+"   vec4 g_water_plane;\n"
+"   vec4 g_depth_bounds;\n"
+"\n"
+"   vec4 g_daysky_colour;\n"
+"   vec4 g_nightsky_colour;\n"
+"   vec4 g_sunset_colour;\n"
+"   vec4 g_ambient_colour;\n"
+"   vec4 g_sunset_ambient;\n"
+"   vec4 g_sun_colour;\n"
+"   vec4 g_sun_dir;\n"
+"   vec4 g_board_0;\n"
+"   vec4 g_board_1;\n"
+"\n"
+"   float g_water_fog;\n"
+"   float g_time;\n"
+"   float g_realtime;\n"
+"   float g_shadow_length;\n"
+"   float g_shadow_spread;\n"
+"\n"
+"   float g_time_of_day;\n"
+"   float g_day_phase;\n"
+"   float g_sunset_phase;\n"
+"\n"
+"   int g_light_preview;\n"
+"   int g_shadow_samples;\n"
+"\n"
+"   int g_debug_indices;\n"
+"   int g_debug_complexity;\n"
+"};\n"
+"\n"
+"uniform sampler2D g_world_depth;\n"
+"uniform samplerBuffer uLightsArray;\n"
+"uniform usampler3D uLightsIndex;\n"
+"\n"
+"#line       1        1 \n"
+"//const vec3  DAYSKY_COLOUR   = vec3( 0.37, 0.54, 0.97 );\n"
+"//const vec3  NIGHTSKY_COLOUR = vec3( 0.03, 0.05, 0.20 );\n"
+"//const vec3  SUNSET_COLOUR   = vec3( 1.00, 0.32, 0.01 );\n"
+"//const vec3  AMBIENT_COLOUR  = vec3( 0.13, 0.17, 0.35 );\n"
+"//const vec3  SUNSET_AMBIENT  = vec3( 0.25, 0.17, 0.51 );\n"
+"//const vec3  SUN_COLOUR      = vec3( 1.10, 0.89, 0.35 );\n"
+"\n"
+"const float SUN_ANGLE       = 0.0001;\n"
+"const float PI              = 3.14159265358979323846264;\n"
+"\n"
+"//struct world_info\n"
+"//{\n"
+"//   float time,\n"
+"//         time_of_day,\n"
+"//         day_phase,\n"
+"//         sunset_phase;\n"
+"//   \n"
+"//   vec3 sun_dir;\n"
+"//};\n"
+"\n"
+"vec3 rand33(vec3 p3)\n"
+"{\n"
+"      p3 = fract(p3 * vec3(.1031, .1030, .0973));\n"
+"   p3 += dot(p3, p3.yxz+33.33);\n"
+"   return fract((p3.xxy + p3.yxx)*p3.zyx);\n"
+"}\n"
+"\n"
+"float stars( vec3 rd, float rr, float size ){\n"
+"   vec3 co = rd * rr;\n"
+"\n"
+"   float a = atan(co.y, length(co.xz)) + 4.0 * PI;\n"
+"\n"
+"   float spaces = 1.0 / rr;\n"
+"   size = (rr * 0.0015) * fwidth(a) * 1000.0 * size;\n"
+"   a -= mod(a, spaces) - spaces * 0.5;\n"
+"\n"
+"   float count = floor(sqrt(pow(rr, 2.0) * (1.0 - pow(sin(a), 2.0))) * 3.0);\n"
+"   \n"
+"   float plane = atan(co.z, co.x) + 4.0 * PI;\n"
+"   plane = plane - mod(plane, PI / count);\n"
+"\n"
+"   vec2 delta = rand33(vec3(plane, a, 0.0)).xy;\n"
+"\n"
+"   float level = sin(a + spaces * (delta.y - 0.5) * (1.0 - size)) * rr;\n"
+"   float ydist = sqrt(rr * rr - level * level);\n"
+"   float angle = plane + (PI * (delta.x * (1.0-size) + size * 0.5) / count);\n"
+"   vec3 center = vec3(cos(angle) * ydist, level, sin(angle) * ydist);\n"
+"   float star = smoothstep(size, 0.0, distance(center, co));\n"
+"   return star;\n"
+"}\n"
+"\n"
+"float luminance( vec3 v )\n"
+"{\n"
+"   return dot( v, vec3(0.2126, 0.7152, 0.0722) );\n"
+"}\n"
+"\n"
+"vec3 clearskies_ambient( vec3 dir )\n"
+"{\n"
+"   float sun_azimuth  = g_sunset_phase * (dot( dir.xz, g_sun_dir.xz )*0.4+0.6);\n"
+"   float sky_gradient = dir.y;\n"
+"   \n"
+"   /* Blend phase colours */\n"
+"   vec3 ambient  = g_daysky_colour.rgb   * (g_day_phase-g_sunset_phase*0.1);\n"
+"        ambient += g_sunset_colour.rgb   * (1.0-dir.y*0.5)*sun_azimuth;\n"
+"        ambient += g_nightsky_colour.rgb * (1.0-g_day_phase);\n"
+"   \n"
+"   /* Add gradient */\n"
+"        ambient -= sky_gradient * luminance(ambient);\n"
+"        \n"
+"   return ambient;\n"
+"}\n"
+"\n"
+"vec3 clearskies_sky( vec3 ray_dir )\n"
+"{\n"
+"   ray_dir.y = abs( ray_dir.y );\n"
+"   vec3 sky_colour  = clearskies_ambient( ray_dir );\n"
+"   \n"
+"   /* Sun */\n"
+"   float sun_theta  = dot( ray_dir, g_sun_dir.xyz );\n"
+"   float sun_size   = max( 0.0, sun_theta * 0.5 + 0.5 + SUN_ANGLE );\n"
+"   float sun_shape  = pow( sun_size, 2000.0 );\n"
+"         sun_shape += sun_size * max(g_sun_dir.y,0.0) * 0.5;\n"
+"         \n"
+"   vec3 sun_colour  = mix( vec3(1.0), g_sunset_colour.rgb, g_sunset_phase*0.5 );\n"
+"        sun_colour *= sun_shape;\n"
+"\n"
+"   \n"
+"   float star = 0.0;\n"
+"   float star_blend = 10.0*max(0.0,(1.0-g_day_phase*2.0));\n"
+"\n"
+"   if( star_blend > 0.001 ){\n"
+"      for( float j = 1.0; j <= 4.1; j += 1.0 ){\n"
+"         float m = mix(0.6, 0.9, smoothstep(1.0, 2.0, j));\n"
+"         star += stars( ray_dir, 1.94 * pow( 1.64, j ), m ) * (1.0/pow(4.0, j));\n"
+"      }\n"
+"   }\n"
+"   \n"
+"   vec3 composite   = sky_colour + sun_colour + star*star_blend;\n"
+"   return composite;\n"
+"}\n"
+"\n"
+"vec3 clearskies_lighting( vec3 normal, float shadow, vec3 halfview )\n"
+"{\n"
+"   float fresnel = 1.0 - abs(dot(normal,halfview));\n"
+"\n"
+"   vec3  reflect_colour = mix( g_daysky_colour.rgb, g_sunset_colour.rgb, \n"
+"                               g_sunset_phase );\n"
+"\n"
+"   vec3  sky_reflection = 0.5 * fresnel * reflect_colour;\n"
+"   vec3  light_sun      = max( CLEARSKIES_LIGHT_DOT_MIN, \n"
+"                               dot(normal,g_sun_dir.xyz)*0.75+0.25\n"
+"                           ) * g_sun_colour.rgb * g_day_phase;\n"
+"\n"
+"   float scaled_shadow = max( shadow, 1.0 - max(g_sun_dir.y,0.0) );\n"
+"   vec3 ambient = mix( g_ambient_colour.rgb, g_sunset_ambient.rgb, \n"
+"                       g_sunset_phase );\n"
+"\n"
+"   return ambient + (light_sun + sky_reflection) * shadow;\n"
+"}\n"
+"\n"
+"#line     44        0 \n"
+"\n"
+"float world_depth_sample( vec3 pos )\n"
+"{\n"
+"   vec2 depth_coord = (pos.xz - g_depth_bounds.xy) * g_depth_bounds.zw; \n"
+"   return texture( g_world_depth, depth_coord ).r;\n"
+"}\n"
+"\n"
+"float world_water_depth( vec3 pos )\n"
+"{\n"
+"   float ref_depth = g_water_plane.y*g_water_plane.w;\n"
+"   return world_depth_sample( pos ) - ref_depth;\n"
+"}\n"
+"\n"
+"float shadow_sample( vec3 co ){\n"
+"   float height_sample = world_depth_sample( co );\n"
+"\n"
+"   float fdelta = height_sample - co.y;\n"
+"   return clamp( fdelta, 0.2, 0.4 )-0.2;\n"
+"}\n"
+"\n"
+"float newlight_compute_sun_shadow( vec3 co, vec3 dir ){\n"
+"   if( g_shadow_samples == 0 ){\n"
+"      return 1.0;\n"
+"   }\n"
+"\n"
+"   float fspread = g_shadow_spread;\n"
+"   float flength = g_shadow_length;\n"
+"\n"
+"   float famt = 0.0;\n"
+"   famt += shadow_sample(co+(dir+vec3(-0.56,0.55, 0.30)*fspread)*flength*0.1);\n"
+"   famt += shadow_sample(co+(dir+vec3( 0.80,0.68, 0.34)*fspread)*flength*0.2);\n"
+"   famt += shadow_sample(co+(dir+vec3( 0.78,0.07,-0.06)*fspread)*flength*0.3);\n"
+"   famt += shadow_sample(co+(dir+vec3(-0.59,0.07,-0.42)*fspread)*flength*0.4);\n"
+"\n"
+"   //famt+=shadow_sample(co+(dir+vec3(-0.790,-0.933,-0.875)*fspread)*flength*0.5);\n"
+"   //famt+=shadow_sample(co+(dir+vec3( 0.807,-0.690, 0.472)*fspread)*flength*0.6);\n"
+"   //famt+=shadow_sample(co+(dir+vec3( 0.522,-0.379, 0.350)*fspread)*flength*0.7);\n"
+"   //famt+=shadow_sample(co+(dir+vec3( 0.483, 0.201, 0.306)*fspread)*flength*0.8);\n"
+"\n"
+"   return 1.0 - famt;\n"
+"}\n"
+"\n"
+"float newlight_specular( vec3 wnormal, vec3 dir, vec3 halfview, float exponent )\n"
+"{\n"
+"   vec3 specdir = reflect( -dir, wnormal );\n"
+"   return pow(max(dot( halfview, specdir ), 0.0), exponent);\n"
+"}\n"
+"\n"
+"vec3 scene_apply_fog( vec3 vfrag, vec3 colour, float fdist ){\n"
+"   float dist = pow(fdist*0.0010,0.78);\n"
+"   return mix( vfrag, colour, min( 1.0, dist ) );\n"
+"}\n"
+"\n"
+"vec3 scene_calculate_light( int light_index, \n"
+"                            vec3 halfview, vec3 co, vec3 normal )\n"
+"{\n"
+"   vec4 light_colour = texelFetch( uLightsArray, light_index+0 );\n"
+"   vec4 light_co     = texelFetch( uLightsArray, light_index+1 );\n"
+"   vec4 light_dir    = texelFetch( uLightsArray, light_index+2 );\n"
+"\n"
+"   vec3 light_delta = light_co.xyz-co;\n"
+"   float dist2 = dot(light_delta,light_delta);\n"
+"\n"
+"   light_delta = normalize( light_delta );\n"
+"\n"
+"   float quadratic = dist2*100.0;\n"
+"   float attenuation  = 1.0/( 1.0 + quadratic );\n"
+"         attenuation *= max( dot( light_delta, normal ), 0.0 );\n"
+"\n"
+"   float falloff = max( 0.0, 1.0-(dist2*light_co.w) );\n"
+"\n"
+"   if( light_dir.w < 0.999999 ){\n"
+"      float spot_theta = max( 0.0, dot( light_delta, -light_dir.xyz ) );\n"
+"      falloff *= max( 0.0, (spot_theta - light_dir.w) / (1.0-light_dir.w) );\n"
+"   }\n"
+"\n"
+"   return light_colour.rgb * attenuation * falloff \n"
+"            * step( g_day_phase, light_colour.w );\n"
+"}\n"
+"\n"
+"vec3 scene_calculate_packed_light_patch( uint packed_index, \n"
+"                                         vec3 halfview, vec3 co, vec3 normal )\n"
+"{\n"
+"   uint light_count = packed_index & 0x3u;\n"
+"\n"
+"   vec3 l = vec3(0.0);\n"
+"\n"
+"   if( light_count >= 1u ){\n"
+"      int index_0 = int( ((packed_index >>  2u) & 0x3ffu) * 3u );\n"
+"      int index_1 = int( ((packed_index >> 12u) & 0x3ffu) * 3u );\n"
+"      int index_2 = int( ((packed_index >> 22u) & 0x3ffu) * 3u );\n"
+"\n"
+"      l += scene_calculate_light( index_0, halfview, co, normal );\n"
+"\n"
+"      if( light_count >= 2u ){\n"
+"         l += scene_calculate_light( index_1, halfview, co, normal );\n"
+"\n"
+"         if( light_count >= 3u ){\n"
+"            l += scene_calculate_light( index_2, halfview, co, normal );\n"
+"         }\n"
+"      }\n"
+"   }\n"
+"\n"
+"   return l;\n"
+"}\n"
+"\n"
+"vec3 world_compute_lighting( vec3 diffuse, vec3 normal, vec3 co,\n"
+"                             float light_mask )\n"
+"{\n"
+"   if( g_light_preview == 1 )\n"
+"      diffuse = vec3(0.75);\n"
+"\n"
+"   // Lighting\n"
+"   vec3 halfview = uCamera - co;\n"
+"   float fdist = length(halfview);\n"
+"   halfview /= fdist;\n"
+"\n"
+"   float world_shadow = newlight_compute_sun_shadow( \n"
+"               co, g_sun_dir.xyz * (1.0/(max(g_sun_dir.y,0.0)+0.2)) );\n"
+"\n"
+"   vec3 total_light = clearskies_lighting( \n"
+"                           normal, min( light_mask, world_shadow ), halfview );\n"
+"\n"
+"   vec3 cube_coord = (co - g_cube_min.xyz) * g_cube_inv_range.xyz;\n"
+"        cube_coord = floor( cube_coord );\n"
+"\n"
+"   if( g_debug_indices == 1 )\n"
+"   {\n"
+"      return rand33(cube_coord);\n"
+"   }\n"
+"\n"
+"   if( g_debug_complexity == 1 )\n"
+"   {\n"
+"      ivec3 coord = ivec3( cube_coord );\n"
+"      uvec4 index_sample = texelFetch( uLightsIndex, coord, 0 );\n"
+"\n"
+"      uint light_count = (index_sample.x & 0x3u) + (index_sample.y & 0x3u);\n"
+"      return vec3( float(light_count)*(1.0/6.0), 0.0, 0.5 );\n"
+"   }\n"
+"\n"
+"   // FIXME: this coord should absolutely must be clamped!\n"
+"   \n"
+"   ivec3 coord = ivec3( cube_coord );\n"
+"   uvec4 index_sample = texelFetch( uLightsIndex, coord, 0 );\n"
+"\n"
+"   total_light += \n"
+"      scene_calculate_packed_light_patch( index_sample.x,\n"
+"                                          halfview, co, normal ) \n"
+"                                          * light_mask;\n"
+"   total_light += \n"
+"      scene_calculate_packed_light_patch( index_sample.y,\n"
+"                                          halfview, co, normal )\n"
+"                                          * light_mask;\n"
+"\n"
+"   // Take a section of the sky function to give us a matching fog colour\n"
+"\n"
+"   vec3 fog_colour  = clearskies_ambient( -halfview );\n"
+"   float sun_theta  = dot( -halfview, g_sun_dir.xyz );\n"
+"   float sun_size   = max( 0.0, sun_theta * 0.5 + 0.5 );\n"
+"   float sun_shape  = sun_size * max(g_sun_dir.y,0.0) * 0.5;\n"
+"         \n"
+"   vec3 sun_colour  = mix( vec3(1.0), g_sunset_colour.rgb, g_sunset_phase*0.5 );\n"
+"        sun_colour *= sun_shape;\n"
+"\n"
+"   fog_colour += sun_colour;\n"
+"   return scene_apply_fog( diffuse * total_light, fog_colour, fdist );\n"
+"}\n"
+"\n"
+"#line      9        0 \n"
+"\n"
+"float sdLine( vec3 p, vec3 a, vec3 b )\n"
+"{\n"
+"  vec3 pa = p - a;\n"
+"  vec3 ba = b - a;\n"
+"\n"
+"  float h = clamp( dot(pa,ba)/dot(ba,ba), 0.0, 1.0 );\n"
+"  return length( pa - ba*h );\n"
+"}\n"
+"\n"
+"float compute_board_shadow()\n"
+"{\n"
+"   // player shadow\n"
+"   float dist_to_player = max( 0.0, sdLine( aWorldCo, g_board_0.xyz,\n"
+"                                                      g_board_1.xyz )-0.1 );\n"
+"   float player_shadow = max( 1.0-dist_to_player*2.7, 0.0 );\n"
+"   player_shadow *= player_shadow*player_shadow*player_shadow;\n"
+"\n"
+"   return 1.0 - player_shadow*0.8;\n"
+"}\n"
+"\n"
+"vec3 scene_compute_lighting( vec3 diffuse, vec3 normal, vec3 co )\n"
+"{\n"
+"   return world_compute_lighting( diffuse, normal, co, compute_board_shadow() );\n"
+"}\n"
+"\n"
+"#line     10        0 \n"
+"#line       1        3 \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     11        0 \n"
+"\n"
+"vec3 pal( float t ){\n"
+"   vec3 a = vec3(0.30,0.3,0.3);\n"
+"   vec3 b = vec3(0.8);\n"
+"   vec3 c = vec3(0.28,0.3,0.4);\n"
+"   vec3 d = vec3(0.00,0.1,0.1);\n"
+"   return a + b*cos( 6.28318*(c*t+d) );\n"
+"}\n"
+"\n"
+"void main(){\n"
+"   compute_motion_vectors();\n"
+"   vec3 vfrag = vec3(0.5,0.5,0.5);\n"
+"   vec3 qnorm = aNorm.xyz;\n"
+"\n"
+"   //vec4 vsamplemain = texture( uTexMain, aUv );\n"
+"   //vfrag = vsamplemain.rgb;\n"
+"\n"
+"   vec4 spread0 = uTime*0.0002*vec4(  17.3,-19.6, 23.2,-47.7 );\n"
+"   vec4 spread1 = uTime*0.0002*vec4( -13.3, 12.6,-28.2, 14.7 );\n"
+"\n"
+"   vec2 p = aCo.xy + vec2(0.3);\n"
+"   float a = atan( p.y/p.x );\n"
+"   vec4 v0 = step( vec4(0.5), fract(vec4(a) + spread0) );\n"
+"   vec4 v1 = step( vec4(0.5), fract(vec4(a) + spread1) );\n"
+"\n"
+"   float d = ( v0.x+v0.y+v0.z+v0.w +\n"
+"               v1.x+v1.y+v1.z+v1.w ) * 0.125;\n"
+"   \n"
+"   float dither = fract(dot(vec2(171.0,231.0),gl_FragCoord.xy)/71.0);\n"
+"   float x = d*0.8+length(p)*0.3;\n"
+"   x = (floor(x*8.0) + step(dither, fract(x * 8.0))) / 8.0;\n"
+"\n"
+"   if( x + (uOpacity*2.0-1.0) < 0.5 ) \n"
+"      discard;\n"
+"\n"
+"   vfrag = mix( vec3(x), pal( x ), uColourize );\n"
+"\n"
+"   if( g_light_preview == 1 ){\n"
+"      vfrag = vec3(0.5);\n"
+"   }\n"
+"\n"
+"   vfrag = scene_compute_lighting( vfrag, qnorm, aWorldCo );\n"
+"   oColour = vec4( vfrag, 1.0 );\n"
+"}\n"
+""},
+};
+
+GLuint _uniform_scene_font_uMdl;
+GLuint _uniform_scene_font_uPv;
+GLuint _uniform_scene_font_uPvmPrev;
+GLuint _uniform_scene_font_uOffset;
+GLuint _uniform_scene_font_uTexGarbage;
+GLuint _uniform_scene_font_uTexMain;
+GLuint _uniform_scene_font_uCamera;
+GLuint _uniform_scene_font_uTime;
+GLuint _uniform_scene_font_uOpacity;
+GLuint _uniform_scene_font_uColourize;
+GLuint _uniform_scene_font_g_world_depth;
+GLuint _uniform_scene_font_uLightsArray;
+GLuint _uniform_scene_font_uLightsIndex;
+#include "shaders/model_sky.h"
+struct vg_shader _shader_model_sky = {
+   .name = "model_sky",
+   .vs = 
+{
+.orig_file = "shaders/model.vs",
+.static_src = 
+"layout (location=0) in vec3 a_co;\n"
+"layout (location=1) in vec3 a_norm;\n"
+"layout (location=2) in vec2 a_uv;\n"
+"layout (location=3) in vec4 a_colour;\n"
+"layout (location=4) in vec4 a_weights;\n"
+"layout (location=5) in ivec4 a_groups;\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      9        0 \n"
+"\n"
+"uniform mat4x3 uMdl;\n"
+"uniform mat4 uPv;\n"
+"uniform mat4 uPvmPrev;\n"
+"\n"
+"out vec4 aColour;\n"
+"out vec2 aUv;\n"
+"out vec3 aNorm;\n"
+"out vec3 aCo;\n"
+"out vec3 aWorldCo;\n"
+"\n"
+"void main()\n"
+"{\n"
+"   vec3 world_pos0 = uMdl     * vec4( a_co, 1.0 );\n"
+"   vec4 vproj0     = uPv      * vec4( world_pos0, 1.0 );\n"
+"   vec4 vproj1     = uPvmPrev * vec4( a_co, 1.0 );\n"
+"\n"
+"   vs_motion_out( vproj0, vproj1 );\n"
+"\n"
+"   gl_Position = vproj0;\n"
+"   aWorldCo = world_pos0;\n"
+"   aColour = a_colour;\n"
+"   aUv = a_uv;\n"
+"   aNorm = normalize( mat3(uMdl) * a_norm );\n"
+"   aCo = a_co;\n"
+"}\n"
+""},
+   .fs = 
+{
+.orig_file = "shaders/model_sky.fs",
+.static_src = 
+"uniform sampler2D uTexGarbage;\n"
+"\n"
+"in vec4 aColour;\n"
+"in vec2 aUv;\n"
+"in vec3 aNorm;\n"
+"in vec3 aCo;\n"
+"in vec3 aWorldCo;\n"
+"\n"
+"// Spooky!\n"
+"const vec3 uCamera = vec3(0.0);\n"
+"\n"
+"#line       1        1 \n"
+"// :D\n"
+"const float CLEARSKIES_LIGHT_DOT_MIN = 0.0;\n"
+"\n"
+"#line     13        0 \n"
+"#line       1        2 \n"
+"layout (location = 0) out vec4 oColour;\n"
+"\n"
+"// OpenGL wiki: Recommends do not use vec3 because of drivers. hence the v4s...\n"
+"layout (std140) uniform ub_world_lighting\n"
+"{\n"
+"   vec4 g_cube_min;\n"
+"   vec4 g_cube_inv_range;\n"
+"\n"
+"   vec4 g_water_plane;\n"
+"   vec4 g_depth_bounds;\n"
+"\n"
+"   vec4 g_daysky_colour;\n"
+"   vec4 g_nightsky_colour;\n"
+"   vec4 g_sunset_colour;\n"
+"   vec4 g_ambient_colour;\n"
+"   vec4 g_sunset_ambient;\n"
+"   vec4 g_sun_colour;\n"
+"   vec4 g_sun_dir;\n"
+"   vec4 g_board_0;\n"
+"   vec4 g_board_1;\n"
+"\n"
+"   float g_water_fog;\n"
+"   float g_time;\n"
+"   float g_realtime;\n"
+"   float g_shadow_length;\n"
+"   float g_shadow_spread;\n"
+"\n"
+"   float g_time_of_day;\n"
+"   float g_day_phase;\n"
+"   float g_sunset_phase;\n"
+"\n"
+"   int g_light_preview;\n"
+"   int g_shadow_samples;\n"
+"\n"
+"   int g_debug_indices;\n"
+"   int g_debug_complexity;\n"
+"};\n"
+"\n"
+"uniform sampler2D g_world_depth;\n"
+"uniform samplerBuffer uLightsArray;\n"
+"uniform usampler3D uLightsIndex;\n"
+"\n"
+"#line       1        1 \n"
+"//const vec3  DAYSKY_COLOUR   = vec3( 0.37, 0.54, 0.97 );\n"
+"//const vec3  NIGHTSKY_COLOUR = vec3( 0.03, 0.05, 0.20 );\n"
+"//const vec3  SUNSET_COLOUR   = vec3( 1.00, 0.32, 0.01 );\n"
+"//const vec3  AMBIENT_COLOUR  = vec3( 0.13, 0.17, 0.35 );\n"
+"//const vec3  SUNSET_AMBIENT  = vec3( 0.25, 0.17, 0.51 );\n"
+"//const vec3  SUN_COLOUR      = vec3( 1.10, 0.89, 0.35 );\n"
+"\n"
+"const float SUN_ANGLE       = 0.0001;\n"
+"const float PI              = 3.14159265358979323846264;\n"
+"\n"
+"//struct world_info\n"
+"//{\n"
+"//   float time,\n"
+"//         time_of_day,\n"
+"//         day_phase,\n"
+"//         sunset_phase;\n"
+"//   \n"
+"//   vec3 sun_dir;\n"
+"//};\n"
+"\n"
+"vec3 rand33(vec3 p3)\n"
+"{\n"
+"      p3 = fract(p3 * vec3(.1031, .1030, .0973));\n"
+"   p3 += dot(p3, p3.yxz+33.33);\n"
+"   return fract((p3.xxy + p3.yxx)*p3.zyx);\n"
+"}\n"
+"\n"
+"float stars( vec3 rd, float rr, float size ){\n"
+"   vec3 co = rd * rr;\n"
+"\n"
+"   float a = atan(co.y, length(co.xz)) + 4.0 * PI;\n"
+"\n"
+"   float spaces = 1.0 / rr;\n"
+"   size = (rr * 0.0015) * fwidth(a) * 1000.0 * size;\n"
+"   a -= mod(a, spaces) - spaces * 0.5;\n"
+"\n"
+"   float count = floor(sqrt(pow(rr, 2.0) * (1.0 - pow(sin(a), 2.0))) * 3.0);\n"
+"   \n"
+"   float plane = atan(co.z, co.x) + 4.0 * PI;\n"
+"   plane = plane - mod(plane, PI / count);\n"
+"\n"
+"   vec2 delta = rand33(vec3(plane, a, 0.0)).xy;\n"
+"\n"
+"   float level = sin(a + spaces * (delta.y - 0.5) * (1.0 - size)) * rr;\n"
+"   float ydist = sqrt(rr * rr - level * level);\n"
+"   float angle = plane + (PI * (delta.x * (1.0-size) + size * 0.5) / count);\n"
+"   vec3 center = vec3(cos(angle) * ydist, level, sin(angle) * ydist);\n"
+"   float star = smoothstep(size, 0.0, distance(center, co));\n"
+"   return star;\n"
+"}\n"
+"\n"
+"float luminance( vec3 v )\n"
+"{\n"
+"   return dot( v, vec3(0.2126, 0.7152, 0.0722) );\n"
+"}\n"
+"\n"
+"vec3 clearskies_ambient( vec3 dir )\n"
+"{\n"
+"   float sun_azimuth  = g_sunset_phase * (dot( dir.xz, g_sun_dir.xz )*0.4+0.6);\n"
+"   float sky_gradient = dir.y;\n"
+"   \n"
+"   /* Blend phase colours */\n"
+"   vec3 ambient  = g_daysky_colour.rgb   * (g_day_phase-g_sunset_phase*0.1);\n"
+"        ambient += g_sunset_colour.rgb   * (1.0-dir.y*0.5)*sun_azimuth;\n"
+"        ambient += g_nightsky_colour.rgb * (1.0-g_day_phase);\n"
+"   \n"
+"   /* Add gradient */\n"
+"        ambient -= sky_gradient * luminance(ambient);\n"
+"        \n"
+"   return ambient;\n"
+"}\n"
+"\n"
+"vec3 clearskies_sky( vec3 ray_dir )\n"
+"{\n"
+"   ray_dir.y = abs( ray_dir.y );\n"
+"   vec3 sky_colour  = clearskies_ambient( ray_dir );\n"
+"   \n"
+"   /* Sun */\n"
+"   float sun_theta  = dot( ray_dir, g_sun_dir.xyz );\n"
+"   float sun_size   = max( 0.0, sun_theta * 0.5 + 0.5 + SUN_ANGLE );\n"
+"   float sun_shape  = pow( sun_size, 2000.0 );\n"
+"         sun_shape += sun_size * max(g_sun_dir.y,0.0) * 0.5;\n"
+"         \n"
+"   vec3 sun_colour  = mix( vec3(1.0), g_sunset_colour.rgb, g_sunset_phase*0.5 );\n"
+"        sun_colour *= sun_shape;\n"
+"\n"
+"   \n"
+"   float star = 0.0;\n"
+"   float star_blend = 10.0*max(0.0,(1.0-g_day_phase*2.0));\n"
+"\n"
+"   if( star_blend > 0.001 ){\n"
+"      for( float j = 1.0; j <= 4.1; j += 1.0 ){\n"
+"         float m = mix(0.6, 0.9, smoothstep(1.0, 2.0, j));\n"
+"         star += stars( ray_dir, 1.94 * pow( 1.64, j ), m ) * (1.0/pow(4.0, j));\n"
+"      }\n"
+"   }\n"
+"   \n"
+"   vec3 composite   = sky_colour + sun_colour + star*star_blend;\n"
+"   return composite;\n"
+"}\n"
+"\n"
+"vec3 clearskies_lighting( vec3 normal, float shadow, vec3 halfview )\n"
+"{\n"
+"   float fresnel = 1.0 - abs(dot(normal,halfview));\n"
+"\n"
+"   vec3  reflect_colour = mix( g_daysky_colour.rgb, g_sunset_colour.rgb, \n"
+"                               g_sunset_phase );\n"
+"\n"
+"   vec3  sky_reflection = 0.5 * fresnel * reflect_colour;\n"
+"   vec3  light_sun      = max( CLEARSKIES_LIGHT_DOT_MIN, \n"
+"                               dot(normal,g_sun_dir.xyz)*0.75+0.25\n"
+"                           ) * g_sun_colour.rgb * g_day_phase;\n"
+"\n"
+"   float scaled_shadow = max( shadow, 1.0 - max(g_sun_dir.y,0.0) );\n"
+"   vec3 ambient = mix( g_ambient_colour.rgb, g_sunset_ambient.rgb, \n"
+"                       g_sunset_phase );\n"
+"\n"
+"   return ambient + (light_sun + sky_reflection) * shadow;\n"
+"}\n"
+"\n"
+"#line     44        0 \n"
+"\n"
+"float world_depth_sample( vec3 pos )\n"
+"{\n"
+"   vec2 depth_coord = (pos.xz - g_depth_bounds.xy) * g_depth_bounds.zw; \n"
+"   return texture( g_world_depth, depth_coord ).r;\n"
+"}\n"
+"\n"
+"float world_water_depth( vec3 pos )\n"
+"{\n"
+"   float ref_depth = g_water_plane.y*g_water_plane.w;\n"
+"   return world_depth_sample( pos ) - ref_depth;\n"
+"}\n"
+"\n"
+"float shadow_sample( vec3 co ){\n"
+"   float height_sample = world_depth_sample( co );\n"
+"\n"
+"   float fdelta = height_sample - co.y;\n"
+"   return clamp( fdelta, 0.2, 0.4 )-0.2;\n"
+"}\n"
+"\n"
+"float newlight_compute_sun_shadow( vec3 co, vec3 dir ){\n"
+"   if( g_shadow_samples == 0 ){\n"
+"      return 1.0;\n"
+"   }\n"
+"\n"
+"   float fspread = g_shadow_spread;\n"
+"   float flength = g_shadow_length;\n"
+"\n"
+"   float famt = 0.0;\n"
+"   famt += shadow_sample(co+(dir+vec3(-0.56,0.55, 0.30)*fspread)*flength*0.1);\n"
+"   famt += shadow_sample(co+(dir+vec3( 0.80,0.68, 0.34)*fspread)*flength*0.2);\n"
+"   famt += shadow_sample(co+(dir+vec3( 0.78,0.07,-0.06)*fspread)*flength*0.3);\n"
+"   famt += shadow_sample(co+(dir+vec3(-0.59,0.07,-0.42)*fspread)*flength*0.4);\n"
+"\n"
+"   //famt+=shadow_sample(co+(dir+vec3(-0.790,-0.933,-0.875)*fspread)*flength*0.5);\n"
+"   //famt+=shadow_sample(co+(dir+vec3( 0.807,-0.690, 0.472)*fspread)*flength*0.6);\n"
+"   //famt+=shadow_sample(co+(dir+vec3( 0.522,-0.379, 0.350)*fspread)*flength*0.7);\n"
+"   //famt+=shadow_sample(co+(dir+vec3( 0.483, 0.201, 0.306)*fspread)*flength*0.8);\n"
+"\n"
+"   return 1.0 - famt;\n"
+"}\n"
+"\n"
+"float newlight_specular( vec3 wnormal, vec3 dir, vec3 halfview, float exponent )\n"
+"{\n"
+"   vec3 specdir = reflect( -dir, wnormal );\n"
+"   return pow(max(dot( halfview, specdir ), 0.0), exponent);\n"
+"}\n"
+"\n"
+"vec3 scene_apply_fog( vec3 vfrag, vec3 colour, float fdist ){\n"
+"   float dist = pow(fdist*0.0010,0.78);\n"
+"   return mix( vfrag, colour, min( 1.0, dist ) );\n"
+"}\n"
+"\n"
+"vec3 scene_calculate_light( int light_index, \n"
+"                            vec3 halfview, vec3 co, vec3 normal )\n"
+"{\n"
+"   vec4 light_colour = texelFetch( uLightsArray, light_index+0 );\n"
+"   vec4 light_co     = texelFetch( uLightsArray, light_index+1 );\n"
+"   vec4 light_dir    = texelFetch( uLightsArray, light_index+2 );\n"
+"\n"
+"   vec3 light_delta = light_co.xyz-co;\n"
+"   float dist2 = dot(light_delta,light_delta);\n"
+"\n"
+"   light_delta = normalize( light_delta );\n"
+"\n"
+"   float quadratic = dist2*100.0;\n"
+"   float attenuation  = 1.0/( 1.0 + quadratic );\n"
+"         attenuation *= max( dot( light_delta, normal ), 0.0 );\n"
+"\n"
+"   float falloff = max( 0.0, 1.0-(dist2*light_co.w) );\n"
+"\n"
+"   if( light_dir.w < 0.999999 ){\n"
+"      float spot_theta = max( 0.0, dot( light_delta, -light_dir.xyz ) );\n"
+"      falloff *= max( 0.0, (spot_theta - light_dir.w) / (1.0-light_dir.w) );\n"
+"   }\n"
+"\n"
+"   return light_colour.rgb * attenuation * falloff \n"
+"            * step( g_day_phase, light_colour.w );\n"
+"}\n"
+"\n"
+"vec3 scene_calculate_packed_light_patch( uint packed_index, \n"
+"                                         vec3 halfview, vec3 co, vec3 normal )\n"
+"{\n"
+"   uint light_count = packed_index & 0x3u;\n"
+"\n"
+"   vec3 l = vec3(0.0);\n"
+"\n"
+"   if( light_count >= 1u ){\n"
+"      int index_0 = int( ((packed_index >>  2u) & 0x3ffu) * 3u );\n"
+"      int index_1 = int( ((packed_index >> 12u) & 0x3ffu) * 3u );\n"
+"      int index_2 = int( ((packed_index >> 22u) & 0x3ffu) * 3u );\n"
+"\n"
+"      l += scene_calculate_light( index_0, halfview, co, normal );\n"
+"\n"
+"      if( light_count >= 2u ){\n"
+"         l += scene_calculate_light( index_1, halfview, co, normal );\n"
+"\n"
+"         if( light_count >= 3u ){\n"
+"            l += scene_calculate_light( index_2, halfview, co, normal );\n"
+"         }\n"
+"      }\n"
+"   }\n"
+"\n"
+"   return l;\n"
+"}\n"
+"\n"
+"vec3 world_compute_lighting( vec3 diffuse, vec3 normal, vec3 co,\n"
+"                             float light_mask )\n"
+"{\n"
+"   if( g_light_preview == 1 )\n"
+"      diffuse = vec3(0.75);\n"
+"\n"
+"   // Lighting\n"
+"   vec3 halfview = uCamera - co;\n"
+"   float fdist = length(halfview);\n"
+"   halfview /= fdist;\n"
+"\n"
+"   float world_shadow = newlight_compute_sun_shadow( \n"
+"               co, g_sun_dir.xyz * (1.0/(max(g_sun_dir.y,0.0)+0.2)) );\n"
+"\n"
+"   vec3 total_light = clearskies_lighting( \n"
+"                           normal, min( light_mask, world_shadow ), halfview );\n"
+"\n"
+"   vec3 cube_coord = (co - g_cube_min.xyz) * g_cube_inv_range.xyz;\n"
+"        cube_coord = floor( cube_coord );\n"
+"\n"
+"   if( g_debug_indices == 1 )\n"
+"   {\n"
+"      return rand33(cube_coord);\n"
+"   }\n"
+"\n"
+"   if( g_debug_complexity == 1 )\n"
+"   {\n"
+"      ivec3 coord = ivec3( cube_coord );\n"
+"      uvec4 index_sample = texelFetch( uLightsIndex, coord, 0 );\n"
+"\n"
+"      uint light_count = (index_sample.x & 0x3u) + (index_sample.y & 0x3u);\n"
+"      return vec3( float(light_count)*(1.0/6.0), 0.0, 0.5 );\n"
+"   }\n"
+"\n"
+"   // FIXME: this coord should absolutely must be clamped!\n"
+"   \n"
+"   ivec3 coord = ivec3( cube_coord );\n"
+"   uvec4 index_sample = texelFetch( uLightsIndex, coord, 0 );\n"
+"\n"
+"   total_light += \n"
+"      scene_calculate_packed_light_patch( index_sample.x,\n"
+"                                          halfview, co, normal ) \n"
+"                                          * light_mask;\n"
+"   total_light += \n"
+"      scene_calculate_packed_light_patch( index_sample.y,\n"
+"                                          halfview, co, normal )\n"
+"                                          * light_mask;\n"
+"\n"
+"   // Take a section of the sky function to give us a matching fog colour\n"
+"\n"
+"   vec3 fog_colour  = clearskies_ambient( -halfview );\n"
+"   float sun_theta  = dot( -halfview, g_sun_dir.xyz );\n"
+"   float sun_size   = max( 0.0, sun_theta * 0.5 + 0.5 );\n"
+"   float sun_shape  = sun_size * max(g_sun_dir.y,0.0) * 0.5;\n"
+"         \n"
+"   vec3 sun_colour  = mix( vec3(1.0), g_sunset_colour.rgb, g_sunset_phase*0.5 );\n"
+"        sun_colour *= sun_shape;\n"
+"\n"
+"   fog_colour += sun_colour;\n"
+"   return scene_apply_fog( diffuse * total_light, fog_colour, fdist );\n"
+"}\n"
+"\n"
+"#line     14        0 \n"
+"#line       1        3 \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     15        0 \n"
+"\n"
+"void main()\n"
+"{\n"
+"   compute_motion_vectors();\n"
+"\n"
+"   vec3 rd = normalize(aNorm);\n"
+"\n"
+"   float fmove = g_time * 5.0;\n"
+"   vec2 cloudplane = (rd.xz / (rd.y*sign(rd.y))) * 0.025;\n"
+"   vec4 clouds1 = texture( uTexGarbage, cloudplane + vec2(0.1,0.4)*fmove*2.0 );\n"
+"   vec4 clouds2 = texture( uTexGarbage, cloudplane*2.0 + vec2(0.3,0.1)*fmove );\n"
+"\n"
+"   float cloud_d = max(clouds1.b*clouds2.r -0.2 - clouds2.g*0.4,0.0);\n"
+"   float cloud_e = pow(cloud_d,1.5)*pow(abs(rd.y),0.3)*2.0;\n"
+"\n"
+"   oColour = vec4( clearskies_sky( -rd ) ,1.0);\n"
+"\n"
+"   vec3 cloud_colour = mix( mix(g_nightsky_colour.rgb,vec3(1.0),g_day_phase), \n"
+"                                g_sunset_colour.rgb, g_sunset_phase );\n"
+"\n"
+"   oColour.rgb = mix( oColour.rgb, cloud_colour, cloud_e );\n"
+"}\n"
+""},
+};
+
+GLuint _uniform_model_sky_uMdl;
+GLuint _uniform_model_sky_uPv;
+GLuint _uniform_model_sky_uPvmPrev;
+GLuint _uniform_model_sky_uTexGarbage;
+GLuint _uniform_model_sky_g_world_depth;
+GLuint _uniform_model_sky_uLightsArray;
+GLuint _uniform_model_sky_uLightsIndex;
+#include "shaders/model_sky_space.h"
+struct vg_shader _shader_model_sky_space = {
+   .name = "model_sky_space",
+   .vs = 
+{
+.orig_file = "shaders/model.vs",
+.static_src = 
+"layout (location=0) in vec3 a_co;\n"
+"layout (location=1) in vec3 a_norm;\n"
+"layout (location=2) in vec2 a_uv;\n"
+"layout (location=3) in vec4 a_colour;\n"
+"layout (location=4) in vec4 a_weights;\n"
+"layout (location=5) in ivec4 a_groups;\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      9        0 \n"
+"\n"
+"uniform mat4x3 uMdl;\n"
+"uniform mat4 uPv;\n"
+"uniform mat4 uPvmPrev;\n"
+"\n"
+"out vec4 aColour;\n"
+"out vec2 aUv;\n"
+"out vec3 aNorm;\n"
+"out vec3 aCo;\n"
+"out vec3 aWorldCo;\n"
+"\n"
+"void main()\n"
+"{\n"
+"   vec3 world_pos0 = uMdl     * vec4( a_co, 1.0 );\n"
+"   vec4 vproj0     = uPv      * vec4( world_pos0, 1.0 );\n"
+"   vec4 vproj1     = uPvmPrev * vec4( a_co, 1.0 );\n"
+"\n"
+"   vs_motion_out( vproj0, vproj1 );\n"
+"\n"
+"   gl_Position = vproj0;\n"
+"   aWorldCo = world_pos0;\n"
+"   aColour = a_colour;\n"
+"   aUv = a_uv;\n"
+"   aNorm = normalize( mat3(uMdl) * a_norm );\n"
+"   aCo = a_co;\n"
+"}\n"
+""},
+   .fs = 
+{
+.orig_file = "shaders/model_sky_space.fs",
+.static_src = 
+"uniform sampler2D uTexGarbage;\n"
+"\n"
+"in vec4 aColour;\n"
+"in vec2 aUv;\n"
+"in vec3 aNorm;\n"
+"in vec3 aCo;\n"
+"in vec3 aWorldCo;\n"
+"\n"
+"// Spooky!\n"
+"const vec3 uCamera = vec3(0.0);\n"
+"\n"
+"#line       1        1 \n"
+"// :D\n"
+"const float CLEARSKIES_LIGHT_DOT_MIN = 0.0;\n"
+"\n"
+"#line     13        0 \n"
+"#line       1        2 \n"
+"layout (location = 0) out vec4 oColour;\n"
+"\n"
+"// OpenGL wiki: Recommends do not use vec3 because of drivers. hence the v4s...\n"
+"layout (std140) uniform ub_world_lighting\n"
+"{\n"
+"   vec4 g_cube_min;\n"
+"   vec4 g_cube_inv_range;\n"
+"\n"
+"   vec4 g_water_plane;\n"
+"   vec4 g_depth_bounds;\n"
+"\n"
+"   vec4 g_daysky_colour;\n"
+"   vec4 g_nightsky_colour;\n"
+"   vec4 g_sunset_colour;\n"
+"   vec4 g_ambient_colour;\n"
+"   vec4 g_sunset_ambient;\n"
+"   vec4 g_sun_colour;\n"
+"   vec4 g_sun_dir;\n"
+"   vec4 g_board_0;\n"
+"   vec4 g_board_1;\n"
+"\n"
+"   float g_water_fog;\n"
+"   float g_time;\n"
+"   float g_realtime;\n"
+"   float g_shadow_length;\n"
+"   float g_shadow_spread;\n"
+"\n"
+"   float g_time_of_day;\n"
+"   float g_day_phase;\n"
+"   float g_sunset_phase;\n"
+"\n"
+"   int g_light_preview;\n"
+"   int g_shadow_samples;\n"
+"\n"
+"   int g_debug_indices;\n"
+"   int g_debug_complexity;\n"
+"};\n"
+"\n"
+"uniform sampler2D g_world_depth;\n"
+"uniform samplerBuffer uLightsArray;\n"
+"uniform usampler3D uLightsIndex;\n"
+"\n"
+"#line       1        1 \n"
+"//const vec3  DAYSKY_COLOUR   = vec3( 0.37, 0.54, 0.97 );\n"
+"//const vec3  NIGHTSKY_COLOUR = vec3( 0.03, 0.05, 0.20 );\n"
+"//const vec3  SUNSET_COLOUR   = vec3( 1.00, 0.32, 0.01 );\n"
+"//const vec3  AMBIENT_COLOUR  = vec3( 0.13, 0.17, 0.35 );\n"
+"//const vec3  SUNSET_AMBIENT  = vec3( 0.25, 0.17, 0.51 );\n"
+"//const vec3  SUN_COLOUR      = vec3( 1.10, 0.89, 0.35 );\n"
+"\n"
+"const float SUN_ANGLE       = 0.0001;\n"
+"const float PI              = 3.14159265358979323846264;\n"
+"\n"
+"//struct world_info\n"
+"//{\n"
+"//   float time,\n"
+"//         time_of_day,\n"
+"//         day_phase,\n"
+"//         sunset_phase;\n"
+"//   \n"
+"//   vec3 sun_dir;\n"
+"//};\n"
+"\n"
+"vec3 rand33(vec3 p3)\n"
+"{\n"
+"      p3 = fract(p3 * vec3(.1031, .1030, .0973));\n"
+"   p3 += dot(p3, p3.yxz+33.33);\n"
+"   return fract((p3.xxy + p3.yxx)*p3.zyx);\n"
+"}\n"
+"\n"
+"float stars( vec3 rd, float rr, float size ){\n"
+"   vec3 co = rd * rr;\n"
+"\n"
+"   float a = atan(co.y, length(co.xz)) + 4.0 * PI;\n"
+"\n"
+"   float spaces = 1.0 / rr;\n"
+"   size = (rr * 0.0015) * fwidth(a) * 1000.0 * size;\n"
+"   a -= mod(a, spaces) - spaces * 0.5;\n"
+"\n"
+"   float count = floor(sqrt(pow(rr, 2.0) * (1.0 - pow(sin(a), 2.0))) * 3.0);\n"
+"   \n"
+"   float plane = atan(co.z, co.x) + 4.0 * PI;\n"
+"   plane = plane - mod(plane, PI / count);\n"
+"\n"
+"   vec2 delta = rand33(vec3(plane, a, 0.0)).xy;\n"
+"\n"
+"   float level = sin(a + spaces * (delta.y - 0.5) * (1.0 - size)) * rr;\n"
+"   float ydist = sqrt(rr * rr - level * level);\n"
+"   float angle = plane + (PI * (delta.x * (1.0-size) + size * 0.5) / count);\n"
+"   vec3 center = vec3(cos(angle) * ydist, level, sin(angle) * ydist);\n"
+"   float star = smoothstep(size, 0.0, distance(center, co));\n"
+"   return star;\n"
+"}\n"
+"\n"
+"float luminance( vec3 v )\n"
+"{\n"
+"   return dot( v, vec3(0.2126, 0.7152, 0.0722) );\n"
+"}\n"
+"\n"
+"vec3 clearskies_ambient( vec3 dir )\n"
+"{\n"
+"   float sun_azimuth  = g_sunset_phase * (dot( dir.xz, g_sun_dir.xz )*0.4+0.6);\n"
+"   float sky_gradient = dir.y;\n"
+"   \n"
+"   /* Blend phase colours */\n"
+"   vec3 ambient  = g_daysky_colour.rgb   * (g_day_phase-g_sunset_phase*0.1);\n"
+"        ambient += g_sunset_colour.rgb   * (1.0-dir.y*0.5)*sun_azimuth;\n"
+"        ambient += g_nightsky_colour.rgb * (1.0-g_day_phase);\n"
+"   \n"
+"   /* Add gradient */\n"
+"        ambient -= sky_gradient * luminance(ambient);\n"
+"        \n"
+"   return ambient;\n"
+"}\n"
+"\n"
+"vec3 clearskies_sky( vec3 ray_dir )\n"
+"{\n"
+"   ray_dir.y = abs( ray_dir.y );\n"
+"   vec3 sky_colour  = clearskies_ambient( ray_dir );\n"
+"   \n"
+"   /* Sun */\n"
+"   float sun_theta  = dot( ray_dir, g_sun_dir.xyz );\n"
+"   float sun_size   = max( 0.0, sun_theta * 0.5 + 0.5 + SUN_ANGLE );\n"
+"   float sun_shape  = pow( sun_size, 2000.0 );\n"
+"         sun_shape += sun_size * max(g_sun_dir.y,0.0) * 0.5;\n"
+"         \n"
+"   vec3 sun_colour  = mix( vec3(1.0), g_sunset_colour.rgb, g_sunset_phase*0.5 );\n"
+"        sun_colour *= sun_shape;\n"
+"\n"
+"   \n"
+"   float star = 0.0;\n"
+"   float star_blend = 10.0*max(0.0,(1.0-g_day_phase*2.0));\n"
+"\n"
+"   if( star_blend > 0.001 ){\n"
+"      for( float j = 1.0; j <= 4.1; j += 1.0 ){\n"
+"         float m = mix(0.6, 0.9, smoothstep(1.0, 2.0, j));\n"
+"         star += stars( ray_dir, 1.94 * pow( 1.64, j ), m ) * (1.0/pow(4.0, j));\n"
+"      }\n"
+"   }\n"
+"   \n"
+"   vec3 composite   = sky_colour + sun_colour + star*star_blend;\n"
+"   return composite;\n"
+"}\n"
+"\n"
+"vec3 clearskies_lighting( vec3 normal, float shadow, vec3 halfview )\n"
+"{\n"
+"   float fresnel = 1.0 - abs(dot(normal,halfview));\n"
+"\n"
+"   vec3  reflect_colour = mix( g_daysky_colour.rgb, g_sunset_colour.rgb, \n"
+"                               g_sunset_phase );\n"
+"\n"
+"   vec3  sky_reflection = 0.5 * fresnel * reflect_colour;\n"
+"   vec3  light_sun      = max( CLEARSKIES_LIGHT_DOT_MIN, \n"
+"                               dot(normal,g_sun_dir.xyz)*0.75+0.25\n"
+"                           ) * g_sun_colour.rgb * g_day_phase;\n"
+"\n"
+"   float scaled_shadow = max( shadow, 1.0 - max(g_sun_dir.y,0.0) );\n"
+"   vec3 ambient = mix( g_ambient_colour.rgb, g_sunset_ambient.rgb, \n"
+"                       g_sunset_phase );\n"
+"\n"
+"   return ambient + (light_sun + sky_reflection) * shadow;\n"
+"}\n"
+"\n"
+"#line     44        0 \n"
+"\n"
+"float world_depth_sample( vec3 pos )\n"
+"{\n"
+"   vec2 depth_coord = (pos.xz - g_depth_bounds.xy) * g_depth_bounds.zw; \n"
+"   return texture( g_world_depth, depth_coord ).r;\n"
+"}\n"
+"\n"
+"float world_water_depth( vec3 pos )\n"
+"{\n"
+"   float ref_depth = g_water_plane.y*g_water_plane.w;\n"
+"   return world_depth_sample( pos ) - ref_depth;\n"
+"}\n"
+"\n"
+"float shadow_sample( vec3 co ){\n"
+"   float height_sample = world_depth_sample( co );\n"
+"\n"
+"   float fdelta = height_sample - co.y;\n"
+"   return clamp( fdelta, 0.2, 0.4 )-0.2;\n"
+"}\n"
+"\n"
+"float newlight_compute_sun_shadow( vec3 co, vec3 dir ){\n"
+"   if( g_shadow_samples == 0 ){\n"
+"      return 1.0;\n"
+"   }\n"
+"\n"
+"   float fspread = g_shadow_spread;\n"
+"   float flength = g_shadow_length;\n"
+"\n"
+"   float famt = 0.0;\n"
+"   famt += shadow_sample(co+(dir+vec3(-0.56,0.55, 0.30)*fspread)*flength*0.1);\n"
+"   famt += shadow_sample(co+(dir+vec3( 0.80,0.68, 0.34)*fspread)*flength*0.2);\n"
+"   famt += shadow_sample(co+(dir+vec3( 0.78,0.07,-0.06)*fspread)*flength*0.3);\n"
+"   famt += shadow_sample(co+(dir+vec3(-0.59,0.07,-0.42)*fspread)*flength*0.4);\n"
+"\n"
+"   //famt+=shadow_sample(co+(dir+vec3(-0.790,-0.933,-0.875)*fspread)*flength*0.5);\n"
+"   //famt+=shadow_sample(co+(dir+vec3( 0.807,-0.690, 0.472)*fspread)*flength*0.6);\n"
+"   //famt+=shadow_sample(co+(dir+vec3( 0.522,-0.379, 0.350)*fspread)*flength*0.7);\n"
+"   //famt+=shadow_sample(co+(dir+vec3( 0.483, 0.201, 0.306)*fspread)*flength*0.8);\n"
+"\n"
+"   return 1.0 - famt;\n"
+"}\n"
+"\n"
+"float newlight_specular( vec3 wnormal, vec3 dir, vec3 halfview, float exponent )\n"
+"{\n"
+"   vec3 specdir = reflect( -dir, wnormal );\n"
+"   return pow(max(dot( halfview, specdir ), 0.0), exponent);\n"
+"}\n"
+"\n"
+"vec3 scene_apply_fog( vec3 vfrag, vec3 colour, float fdist ){\n"
+"   float dist = pow(fdist*0.0010,0.78);\n"
+"   return mix( vfrag, colour, min( 1.0, dist ) );\n"
+"}\n"
+"\n"
+"vec3 scene_calculate_light( int light_index, \n"
+"                            vec3 halfview, vec3 co, vec3 normal )\n"
+"{\n"
+"   vec4 light_colour = texelFetch( uLightsArray, light_index+0 );\n"
+"   vec4 light_co     = texelFetch( uLightsArray, light_index+1 );\n"
+"   vec4 light_dir    = texelFetch( uLightsArray, light_index+2 );\n"
+"\n"
+"   vec3 light_delta = light_co.xyz-co;\n"
+"   float dist2 = dot(light_delta,light_delta);\n"
+"\n"
+"   light_delta = normalize( light_delta );\n"
+"\n"
+"   float quadratic = dist2*100.0;\n"
+"   float attenuation  = 1.0/( 1.0 + quadratic );\n"
+"         attenuation *= max( dot( light_delta, normal ), 0.0 );\n"
+"\n"
+"   float falloff = max( 0.0, 1.0-(dist2*light_co.w) );\n"
+"\n"
+"   if( light_dir.w < 0.999999 ){\n"
+"      float spot_theta = max( 0.0, dot( light_delta, -light_dir.xyz ) );\n"
+"      falloff *= max( 0.0, (spot_theta - light_dir.w) / (1.0-light_dir.w) );\n"
+"   }\n"
+"\n"
+"   return light_colour.rgb * attenuation * falloff \n"
+"            * step( g_day_phase, light_colour.w );\n"
+"}\n"
+"\n"
+"vec3 scene_calculate_packed_light_patch( uint packed_index, \n"
+"                                         vec3 halfview, vec3 co, vec3 normal )\n"
+"{\n"
+"   uint light_count = packed_index & 0x3u;\n"
+"\n"
+"   vec3 l = vec3(0.0);\n"
+"\n"
+"   if( light_count >= 1u ){\n"
+"      int index_0 = int( ((packed_index >>  2u) & 0x3ffu) * 3u );\n"
+"      int index_1 = int( ((packed_index >> 12u) & 0x3ffu) * 3u );\n"
+"      int index_2 = int( ((packed_index >> 22u) & 0x3ffu) * 3u );\n"
+"\n"
+"      l += scene_calculate_light( index_0, halfview, co, normal );\n"
+"\n"
+"      if( light_count >= 2u ){\n"
+"         l += scene_calculate_light( index_1, halfview, co, normal );\n"
+"\n"
+"         if( light_count >= 3u ){\n"
+"            l += scene_calculate_light( index_2, halfview, co, normal );\n"
+"         }\n"
+"      }\n"
+"   }\n"
+"\n"
+"   return l;\n"
+"}\n"
+"\n"
+"vec3 world_compute_lighting( vec3 diffuse, vec3 normal, vec3 co,\n"
+"                             float light_mask )\n"
+"{\n"
+"   if( g_light_preview == 1 )\n"
+"      diffuse = vec3(0.75);\n"
+"\n"
+"   // Lighting\n"
+"   vec3 halfview = uCamera - co;\n"
+"   float fdist = length(halfview);\n"
+"   halfview /= fdist;\n"
+"\n"
+"   float world_shadow = newlight_compute_sun_shadow( \n"
+"               co, g_sun_dir.xyz * (1.0/(max(g_sun_dir.y,0.0)+0.2)) );\n"
+"\n"
+"   vec3 total_light = clearskies_lighting( \n"
+"                           normal, min( light_mask, world_shadow ), halfview );\n"
+"\n"
+"   vec3 cube_coord = (co - g_cube_min.xyz) * g_cube_inv_range.xyz;\n"
+"        cube_coord = floor( cube_coord );\n"
+"\n"
+"   if( g_debug_indices == 1 )\n"
+"   {\n"
+"      return rand33(cube_coord);\n"
+"   }\n"
+"\n"
+"   if( g_debug_complexity == 1 )\n"
+"   {\n"
+"      ivec3 coord = ivec3( cube_coord );\n"
+"      uvec4 index_sample = texelFetch( uLightsIndex, coord, 0 );\n"
+"\n"
+"      uint light_count = (index_sample.x & 0x3u) + (index_sample.y & 0x3u);\n"
+"      return vec3( float(light_count)*(1.0/6.0), 0.0, 0.5 );\n"
+"   }\n"
+"\n"
+"   // FIXME: this coord should absolutely must be clamped!\n"
+"   \n"
+"   ivec3 coord = ivec3( cube_coord );\n"
+"   uvec4 index_sample = texelFetch( uLightsIndex, coord, 0 );\n"
+"\n"
+"   total_light += \n"
+"      scene_calculate_packed_light_patch( index_sample.x,\n"
+"                                          halfview, co, normal ) \n"
+"                                          * light_mask;\n"
+"   total_light += \n"
+"      scene_calculate_packed_light_patch( index_sample.y,\n"
+"                                          halfview, co, normal )\n"
+"                                          * light_mask;\n"
+"\n"
+"   // Take a section of the sky function to give us a matching fog colour\n"
+"\n"
+"   vec3 fog_colour  = clearskies_ambient( -halfview );\n"
+"   float sun_theta  = dot( -halfview, g_sun_dir.xyz );\n"
+"   float sun_size   = max( 0.0, sun_theta * 0.5 + 0.5 );\n"
+"   float sun_shape  = sun_size * max(g_sun_dir.y,0.0) * 0.5;\n"
+"         \n"
+"   vec3 sun_colour  = mix( vec3(1.0), g_sunset_colour.rgb, g_sunset_phase*0.5 );\n"
+"        sun_colour *= sun_shape;\n"
+"\n"
+"   fog_colour += sun_colour;\n"
+"   return scene_apply_fog( diffuse * total_light, fog_colour, fdist );\n"
+"}\n"
+"\n"
+"#line     14        0 \n"
+"#line       1        3 \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     15        0 \n"
+"\n"
+"float stars1( vec3 rd, float rr, float size ){\n"
+"   vec3 co = rd * rr;\n"
+"\n"
+"   float a = atan(co.y, length(co.xz)) + 4.0 * PI;\n"
+"\n"
+"   float spaces = 1.0 / rr;\n"
+"   size = (rr * 0.0015) * fwidth(a) * 1000.0 * size;\n"
+"   a -= mod(a, spaces) - spaces * 0.5;\n"
+"\n"
+"   float count = floor(sqrt(pow(rr, 2.0) * (1.0 - pow(sin(a), 2.0))) * 3.0);\n"
+"   \n"
+"   float plane = atan(co.z, co.x) + 4.0 * PI;\n"
+"   plane = plane - mod(plane, PI / count);\n"
+"\n"
+"   vec2 delta = rand33(vec3(plane, a, 0.0)).xy;\n"
+"\n"
+"   float level = sin(a + spaces * (delta.y - 0.5) * (1.0 - size)) * rr;\n"
+"   float ydist = sqrt(rr * rr - level * level);\n"
+"   float angle = plane + (PI * (delta.x * (1.0-size) + size * 0.5) / count);\n"
+"   vec3 center = vec3(cos(angle) * ydist, level, sin(angle) * ydist);\n"
+"   float star = smoothstep(size, 0.0, distance(center, co));\n"
+"   return star;\n"
+"}\n"
+"\n"
+"void main(){\n"
+"   compute_motion_vectors();\n"
+"\n"
+"   vec3 rd = -normalize(aNorm);\n"
+"\n"
+"   float star = 0.0;\n"
+"   for( float j = 1.0; j <= 4.1; j += 1.0 ){\n"
+"      float m = mix(0.6, 0.9, smoothstep(1.0, 2.0, j));\n"
+"      star += stars( rd, 1.94 * pow( 1.64, j ), m ) * (1.0 / pow(4.0, j));\n"
+"   }\n"
+"\n"
+"   oColour = vec4( vec3(star*20.0), 1.0);\n"
+"}\n"
+""},
+};
+
+GLuint _uniform_model_sky_space_uMdl;
+GLuint _uniform_model_sky_space_uPv;
+GLuint _uniform_model_sky_space_uPvmPrev;
+GLuint _uniform_model_sky_space_uTexGarbage;
+GLuint _uniform_model_sky_space_g_world_depth;
+GLuint _uniform_model_sky_space_uLightsArray;
+GLuint _uniform_model_sky_space_uLightsIndex;
+#include "shaders/model_menu.h"
+struct vg_shader _shader_model_menu = {
+   .name = "model_menu",
+   .vs = 
+{
+.orig_file = "shaders/model.vs",
+.static_src = 
+"layout (location=0) in vec3 a_co;\n"
+"layout (location=1) in vec3 a_norm;\n"
+"layout (location=2) in vec2 a_uv;\n"
+"layout (location=3) in vec4 a_colour;\n"
+"layout (location=4) in vec4 a_weights;\n"
+"layout (location=5) in ivec4 a_groups;\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      9        0 \n"
+"\n"
+"uniform mat4x3 uMdl;\n"
+"uniform mat4 uPv;\n"
+"uniform mat4 uPvmPrev;\n"
+"\n"
+"out vec4 aColour;\n"
+"out vec2 aUv;\n"
+"out vec3 aNorm;\n"
+"out vec3 aCo;\n"
+"out vec3 aWorldCo;\n"
+"\n"
+"void main()\n"
+"{\n"
+"   vec3 world_pos0 = uMdl     * vec4( a_co, 1.0 );\n"
+"   vec4 vproj0     = uPv      * vec4( world_pos0, 1.0 );\n"
+"   vec4 vproj1     = uPvmPrev * vec4( a_co, 1.0 );\n"
+"\n"
+"   vs_motion_out( vproj0, vproj1 );\n"
+"\n"
+"   gl_Position = vproj0;\n"
+"   aWorldCo = world_pos0;\n"
+"   aColour = a_colour;\n"
+"   aUv = a_uv;\n"
+"   aNorm = normalize( mat3(uMdl) * a_norm );\n"
+"   aCo = a_co;\n"
+"}\n"
+""},
+   .fs = 
+{
+.orig_file = "shaders/model_menu.fs",
+.static_src = 
+"out vec4 FragColor;\n"
+"\n"
+"uniform sampler2D uTexMain;\n"
+"uniform vec4 uColour;\n"
+"\n"
+"in vec4 aColour;\n"
+"in vec2 aUv;\n"
+"in vec3 aNorm;\n"
+"in vec3 aCo;\n"
+"\n"
+"void main()\n"
+"{\n"
+"   vec4 diffuse = texture( uTexMain, aUv );\n"
+"\n"
+"   if( diffuse.a < 0.5 )\n"
+"      discard;\n"
+"\n"
+"   FragColor = vec4( diffuse.rgb, 1.0 ) * uColour;\n"
+"}\n"
+""},
+};
+
+GLuint _uniform_model_menu_uMdl;
+GLuint _uniform_model_menu_uPv;
+GLuint _uniform_model_menu_uPvmPrev;
+GLuint _uniform_model_menu_uTexMain;
+GLuint _uniform_model_menu_uColour;
+#include "shaders/model_character_view.h"
+struct vg_shader _shader_model_character_view = {
+   .name = "model_character_view",
+   .vs = 
+{
+.orig_file = "shaders/model_skinned.vs",
+.static_src = 
+"layout (location=0) in vec3 a_co;\n"
+"layout (location=1) in vec3 a_norm;\n"
+"layout (location=2) in vec2 a_uv;\n"
+"layout (location=3) in vec4 a_colour;\n"
+"layout (location=4) in vec4 a_weights;\n"
+"layout (location=5) in ivec4 a_groups;\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      9        0 \n"
+"\n"
+"uniform mat4 uPv;\n"
+"uniform mat4x3 uTransforms[32];\n"
+"\n"
+"out vec4 aColour;\n"
+"out vec2 aUv;\n"
+"out vec3 aNorm;\n"
+"out vec3 aCo;\n"
+"out vec3 aWorldCo;\n"
+"\n"
+"void main()\n"
+"{\n"
+"   vec4 co_local = vec4( a_co, 1.0 );\n"
+"   vec3 co0 = uTransforms[ a_groups[0] ] * co_local;\n"
+"   vec3 co1 = uTransforms[ a_groups[1] ] * co_local;\n"
+"   vec3 co2 = uTransforms[ a_groups[2] ] * co_local;\n"
+"   vec3 n0  = mat3(uTransforms[ a_groups[0] ]) * a_norm;\n"
+"   vec3 n1  = mat3(uTransforms[ a_groups[1] ]) * a_norm;\n"
+"   vec3 n2  = mat3(uTransforms[ a_groups[2] ]) * a_norm;\n"
+"\n"
+"   vec3 world_pos    = co0*a_weights[0] + co1*a_weights[1] + co2*a_weights[2];\n"
+"   vec3 world_normal = n0*a_weights[0]  + n1*a_weights[1]  + n2*a_weights[2];\n"
+"   \n"
+"   gl_Position = uPv * vec4( world_pos, 1.0 );\n"
+"   aColour = a_colour;\n"
+"   aUv = a_uv;\n"
+"   aNorm = world_normal;\n"
+"   aCo = a_co;\n"
+"   aWorldCo = world_pos;\n"
+"\n"
+"   // TODO: motion vectors\n"
+"   aMotionVec0 = vec3(1.0);\n"
+"   aMotionVec1 = vec3(1.0);\n"
+"}\n"
+""},
+   .fs = 
+{
+.orig_file = "shaders/model_character_view.fs",
+.static_src = 
+"uniform sampler2D uTexMain;\n"
+"uniform vec3 uCamera;\n"
+"\n"
+"in vec4 aColour;\n"
+"in vec2 aUv;\n"
+"in vec3 aNorm;\n"
+"in vec3 aCo;\n"
+"in vec3 aWorldCo;\n"
+"\n"
+"#line       1        1 \n"
+"// :D\n"
+"const float CLEARSKIES_LIGHT_DOT_MIN = 0.0;\n"
+"\n"
+"#line     11        0 \n"
+"#line       1        2 \n"
+"layout (location = 0) out vec4 oColour;\n"
+"\n"
+"// OpenGL wiki: Recommends do not use vec3 because of drivers. hence the v4s...\n"
+"layout (std140) uniform ub_world_lighting\n"
+"{\n"
+"   vec4 g_cube_min;\n"
+"   vec4 g_cube_inv_range;\n"
+"\n"
+"   vec4 g_water_plane;\n"
+"   vec4 g_depth_bounds;\n"
+"\n"
+"   vec4 g_daysky_colour;\n"
+"   vec4 g_nightsky_colour;\n"
+"   vec4 g_sunset_colour;\n"
+"   vec4 g_ambient_colour;\n"
+"   vec4 g_sunset_ambient;\n"
+"   vec4 g_sun_colour;\n"
+"   vec4 g_sun_dir;\n"
+"   vec4 g_board_0;\n"
+"   vec4 g_board_1;\n"
+"\n"
+"   float g_water_fog;\n"
+"   float g_time;\n"
+"   float g_realtime;\n"
+"   float g_shadow_length;\n"
+"   float g_shadow_spread;\n"
+"\n"
+"   float g_time_of_day;\n"
+"   float g_day_phase;\n"
+"   float g_sunset_phase;\n"
+"\n"
+"   int g_light_preview;\n"
+"   int g_shadow_samples;\n"
+"\n"
+"   int g_debug_indices;\n"
+"   int g_debug_complexity;\n"
+"};\n"
+"\n"
+"uniform sampler2D g_world_depth;\n"
+"uniform samplerBuffer uLightsArray;\n"
+"uniform usampler3D uLightsIndex;\n"
+"\n"
+"#line       1        1 \n"
+"//const vec3  DAYSKY_COLOUR   = vec3( 0.37, 0.54, 0.97 );\n"
+"//const vec3  NIGHTSKY_COLOUR = vec3( 0.03, 0.05, 0.20 );\n"
+"//const vec3  SUNSET_COLOUR   = vec3( 1.00, 0.32, 0.01 );\n"
+"//const vec3  AMBIENT_COLOUR  = vec3( 0.13, 0.17, 0.35 );\n"
+"//const vec3  SUNSET_AMBIENT  = vec3( 0.25, 0.17, 0.51 );\n"
+"//const vec3  SUN_COLOUR      = vec3( 1.10, 0.89, 0.35 );\n"
+"\n"
+"const float SUN_ANGLE       = 0.0001;\n"
+"const float PI              = 3.14159265358979323846264;\n"
+"\n"
+"//struct world_info\n"
+"//{\n"
+"//   float time,\n"
+"//         time_of_day,\n"
+"//         day_phase,\n"
+"//         sunset_phase;\n"
+"//   \n"
+"//   vec3 sun_dir;\n"
+"//};\n"
+"\n"
+"vec3 rand33(vec3 p3)\n"
+"{\n"
+"      p3 = fract(p3 * vec3(.1031, .1030, .0973));\n"
+"   p3 += dot(p3, p3.yxz+33.33);\n"
+"   return fract((p3.xxy + p3.yxx)*p3.zyx);\n"
+"}\n"
+"\n"
+"float stars( vec3 rd, float rr, float size ){\n"
+"   vec3 co = rd * rr;\n"
+"\n"
+"   float a = atan(co.y, length(co.xz)) + 4.0 * PI;\n"
+"\n"
+"   float spaces = 1.0 / rr;\n"
+"   size = (rr * 0.0015) * fwidth(a) * 1000.0 * size;\n"
+"   a -= mod(a, spaces) - spaces * 0.5;\n"
+"\n"
+"   float count = floor(sqrt(pow(rr, 2.0) * (1.0 - pow(sin(a), 2.0))) * 3.0);\n"
+"   \n"
+"   float plane = atan(co.z, co.x) + 4.0 * PI;\n"
+"   plane = plane - mod(plane, PI / count);\n"
+"\n"
+"   vec2 delta = rand33(vec3(plane, a, 0.0)).xy;\n"
+"\n"
+"   float level = sin(a + spaces * (delta.y - 0.5) * (1.0 - size)) * rr;\n"
+"   float ydist = sqrt(rr * rr - level * level);\n"
+"   float angle = plane + (PI * (delta.x * (1.0-size) + size * 0.5) / count);\n"
+"   vec3 center = vec3(cos(angle) * ydist, level, sin(angle) * ydist);\n"
+"   float star = smoothstep(size, 0.0, distance(center, co));\n"
+"   return star;\n"
+"}\n"
+"\n"
+"float luminance( vec3 v )\n"
+"{\n"
+"   return dot( v, vec3(0.2126, 0.7152, 0.0722) );\n"
+"}\n"
+"\n"
+"vec3 clearskies_ambient( vec3 dir )\n"
+"{\n"
+"   float sun_azimuth  = g_sunset_phase * (dot( dir.xz, g_sun_dir.xz )*0.4+0.6);\n"
+"   float sky_gradient = dir.y;\n"
+"   \n"
+"   /* Blend phase colours */\n"
+"   vec3 ambient  = g_daysky_colour.rgb   * (g_day_phase-g_sunset_phase*0.1);\n"
+"        ambient += g_sunset_colour.rgb   * (1.0-dir.y*0.5)*sun_azimuth;\n"
+"        ambient += g_nightsky_colour.rgb * (1.0-g_day_phase);\n"
+"   \n"
+"   /* Add gradient */\n"
+"        ambient -= sky_gradient * luminance(ambient);\n"
+"        \n"
+"   return ambient;\n"
+"}\n"
+"\n"
+"vec3 clearskies_sky( vec3 ray_dir )\n"
+"{\n"
+"   ray_dir.y = abs( ray_dir.y );\n"
+"   vec3 sky_colour  = clearskies_ambient( ray_dir );\n"
+"   \n"
+"   /* Sun */\n"
+"   float sun_theta  = dot( ray_dir, g_sun_dir.xyz );\n"
+"   float sun_size   = max( 0.0, sun_theta * 0.5 + 0.5 + SUN_ANGLE );\n"
+"   float sun_shape  = pow( sun_size, 2000.0 );\n"
+"         sun_shape += sun_size * max(g_sun_dir.y,0.0) * 0.5;\n"
+"         \n"
+"   vec3 sun_colour  = mix( vec3(1.0), g_sunset_colour.rgb, g_sunset_phase*0.5 );\n"
+"        sun_colour *= sun_shape;\n"
+"\n"
+"   \n"
+"   float star = 0.0;\n"
+"   float star_blend = 10.0*max(0.0,(1.0-g_day_phase*2.0));\n"
+"\n"
+"   if( star_blend > 0.001 ){\n"
+"      for( float j = 1.0; j <= 4.1; j += 1.0 ){\n"
+"         float m = mix(0.6, 0.9, smoothstep(1.0, 2.0, j));\n"
+"         star += stars( ray_dir, 1.94 * pow( 1.64, j ), m ) * (1.0/pow(4.0, j));\n"
+"      }\n"
+"   }\n"
+"   \n"
+"   vec3 composite   = sky_colour + sun_colour + star*star_blend;\n"
+"   return composite;\n"
+"}\n"
+"\n"
+"vec3 clearskies_lighting( vec3 normal, float shadow, vec3 halfview )\n"
+"{\n"
+"   float fresnel = 1.0 - abs(dot(normal,halfview));\n"
+"\n"
+"   vec3  reflect_colour = mix( g_daysky_colour.rgb, g_sunset_colour.rgb, \n"
+"                               g_sunset_phase );\n"
+"\n"
+"   vec3  sky_reflection = 0.5 * fresnel * reflect_colour;\n"
+"   vec3  light_sun      = max( CLEARSKIES_LIGHT_DOT_MIN, \n"
+"                               dot(normal,g_sun_dir.xyz)*0.75+0.25\n"
+"                           ) * g_sun_colour.rgb * g_day_phase;\n"
+"\n"
+"   float scaled_shadow = max( shadow, 1.0 - max(g_sun_dir.y,0.0) );\n"
+"   vec3 ambient = mix( g_ambient_colour.rgb, g_sunset_ambient.rgb, \n"
+"                       g_sunset_phase );\n"
+"\n"
+"   return ambient + (light_sun + sky_reflection) * shadow;\n"
+"}\n"
+"\n"
+"#line     44        0 \n"
+"\n"
+"float world_depth_sample( vec3 pos )\n"
+"{\n"
+"   vec2 depth_coord = (pos.xz - g_depth_bounds.xy) * g_depth_bounds.zw; \n"
+"   return texture( g_world_depth, depth_coord ).r;\n"
+"}\n"
+"\n"
+"float world_water_depth( vec3 pos )\n"
+"{\n"
+"   float ref_depth = g_water_plane.y*g_water_plane.w;\n"
+"   return world_depth_sample( pos ) - ref_depth;\n"
+"}\n"
+"\n"
+"float shadow_sample( vec3 co ){\n"
+"   float height_sample = world_depth_sample( co );\n"
+"\n"
+"   float fdelta = height_sample - co.y;\n"
+"   return clamp( fdelta, 0.2, 0.4 )-0.2;\n"
+"}\n"
+"\n"
+"float newlight_compute_sun_shadow( vec3 co, vec3 dir ){\n"
+"   if( g_shadow_samples == 0 ){\n"
+"      return 1.0;\n"
+"   }\n"
+"\n"
+"   float fspread = g_shadow_spread;\n"
+"   float flength = g_shadow_length;\n"
+"\n"
+"   float famt = 0.0;\n"
+"   famt += shadow_sample(co+(dir+vec3(-0.56,0.55, 0.30)*fspread)*flength*0.1);\n"
+"   famt += shadow_sample(co+(dir+vec3( 0.80,0.68, 0.34)*fspread)*flength*0.2);\n"
+"   famt += shadow_sample(co+(dir+vec3( 0.78,0.07,-0.06)*fspread)*flength*0.3);\n"
+"   famt += shadow_sample(co+(dir+vec3(-0.59,0.07,-0.42)*fspread)*flength*0.4);\n"
+"\n"
+"   //famt+=shadow_sample(co+(dir+vec3(-0.790,-0.933,-0.875)*fspread)*flength*0.5);\n"
+"   //famt+=shadow_sample(co+(dir+vec3( 0.807,-0.690, 0.472)*fspread)*flength*0.6);\n"
+"   //famt+=shadow_sample(co+(dir+vec3( 0.522,-0.379, 0.350)*fspread)*flength*0.7);\n"
+"   //famt+=shadow_sample(co+(dir+vec3( 0.483, 0.201, 0.306)*fspread)*flength*0.8);\n"
+"\n"
+"   return 1.0 - famt;\n"
+"}\n"
+"\n"
+"float newlight_specular( vec3 wnormal, vec3 dir, vec3 halfview, float exponent )\n"
+"{\n"
+"   vec3 specdir = reflect( -dir, wnormal );\n"
+"   return pow(max(dot( halfview, specdir ), 0.0), exponent);\n"
+"}\n"
+"\n"
+"vec3 scene_apply_fog( vec3 vfrag, vec3 colour, float fdist ){\n"
+"   float dist = pow(fdist*0.0010,0.78);\n"
+"   return mix( vfrag, colour, min( 1.0, dist ) );\n"
+"}\n"
+"\n"
+"vec3 scene_calculate_light( int light_index, \n"
+"                            vec3 halfview, vec3 co, vec3 normal )\n"
+"{\n"
+"   vec4 light_colour = texelFetch( uLightsArray, light_index+0 );\n"
+"   vec4 light_co     = texelFetch( uLightsArray, light_index+1 );\n"
+"   vec4 light_dir    = texelFetch( uLightsArray, light_index+2 );\n"
+"\n"
+"   vec3 light_delta = light_co.xyz-co;\n"
+"   float dist2 = dot(light_delta,light_delta);\n"
+"\n"
+"   light_delta = normalize( light_delta );\n"
+"\n"
+"   float quadratic = dist2*100.0;\n"
+"   float attenuation  = 1.0/( 1.0 + quadratic );\n"
+"         attenuation *= max( dot( light_delta, normal ), 0.0 );\n"
+"\n"
+"   float falloff = max( 0.0, 1.0-(dist2*light_co.w) );\n"
+"\n"
+"   if( light_dir.w < 0.999999 ){\n"
+"      float spot_theta = max( 0.0, dot( light_delta, -light_dir.xyz ) );\n"
+"      falloff *= max( 0.0, (spot_theta - light_dir.w) / (1.0-light_dir.w) );\n"
+"   }\n"
+"\n"
+"   return light_colour.rgb * attenuation * falloff \n"
+"            * step( g_day_phase, light_colour.w );\n"
+"}\n"
+"\n"
+"vec3 scene_calculate_packed_light_patch( uint packed_index, \n"
+"                                         vec3 halfview, vec3 co, vec3 normal )\n"
+"{\n"
+"   uint light_count = packed_index & 0x3u;\n"
+"\n"
+"   vec3 l = vec3(0.0);\n"
+"\n"
+"   if( light_count >= 1u ){\n"
+"      int index_0 = int( ((packed_index >>  2u) & 0x3ffu) * 3u );\n"
+"      int index_1 = int( ((packed_index >> 12u) & 0x3ffu) * 3u );\n"
+"      int index_2 = int( ((packed_index >> 22u) & 0x3ffu) * 3u );\n"
+"\n"
+"      l += scene_calculate_light( index_0, halfview, co, normal );\n"
+"\n"
+"      if( light_count >= 2u ){\n"
+"         l += scene_calculate_light( index_1, halfview, co, normal );\n"
+"\n"
+"         if( light_count >= 3u ){\n"
+"            l += scene_calculate_light( index_2, halfview, co, normal );\n"
+"         }\n"
+"      }\n"
+"   }\n"
+"\n"
+"   return l;\n"
+"}\n"
+"\n"
+"vec3 world_compute_lighting( vec3 diffuse, vec3 normal, vec3 co,\n"
+"                             float light_mask )\n"
+"{\n"
+"   if( g_light_preview == 1 )\n"
+"      diffuse = vec3(0.75);\n"
+"\n"
+"   // Lighting\n"
+"   vec3 halfview = uCamera - co;\n"
+"   float fdist = length(halfview);\n"
+"   halfview /= fdist;\n"
+"\n"
+"   float world_shadow = newlight_compute_sun_shadow( \n"
+"               co, g_sun_dir.xyz * (1.0/(max(g_sun_dir.y,0.0)+0.2)) );\n"
+"\n"
+"   vec3 total_light = clearskies_lighting( \n"
+"                           normal, min( light_mask, world_shadow ), halfview );\n"
+"\n"
+"   vec3 cube_coord = (co - g_cube_min.xyz) * g_cube_inv_range.xyz;\n"
+"        cube_coord = floor( cube_coord );\n"
+"\n"
+"   if( g_debug_indices == 1 )\n"
+"   {\n"
+"      return rand33(cube_coord);\n"
+"   }\n"
+"\n"
+"   if( g_debug_complexity == 1 )\n"
+"   {\n"
+"      ivec3 coord = ivec3( cube_coord );\n"
+"      uvec4 index_sample = texelFetch( uLightsIndex, coord, 0 );\n"
+"\n"
+"      uint light_count = (index_sample.x & 0x3u) + (index_sample.y & 0x3u);\n"
+"      return vec3( float(light_count)*(1.0/6.0), 0.0, 0.5 );\n"
+"   }\n"
+"\n"
+"   // FIXME: this coord should absolutely must be clamped!\n"
+"   \n"
+"   ivec3 coord = ivec3( cube_coord );\n"
+"   uvec4 index_sample = texelFetch( uLightsIndex, coord, 0 );\n"
+"\n"
+"   total_light += \n"
+"      scene_calculate_packed_light_patch( index_sample.x,\n"
+"                                          halfview, co, normal ) \n"
+"                                          * light_mask;\n"
+"   total_light += \n"
+"      scene_calculate_packed_light_patch( index_sample.y,\n"
+"                                          halfview, co, normal )\n"
+"                                          * light_mask;\n"
+"\n"
+"   // Take a section of the sky function to give us a matching fog colour\n"
+"\n"
+"   vec3 fog_colour  = clearskies_ambient( -halfview );\n"
+"   float sun_theta  = dot( -halfview, g_sun_dir.xyz );\n"
+"   float sun_size   = max( 0.0, sun_theta * 0.5 + 0.5 );\n"
+"   float sun_shape  = sun_size * max(g_sun_dir.y,0.0) * 0.5;\n"
+"         \n"
+"   vec3 sun_colour  = mix( vec3(1.0), g_sunset_colour.rgb, g_sunset_phase*0.5 );\n"
+"        sun_colour *= sun_shape;\n"
+"\n"
+"   fog_colour += sun_colour;\n"
+"   return scene_apply_fog( diffuse * total_light, fog_colour, fdist );\n"
+"}\n"
+"\n"
+"#line     12        0 \n"
+"#line       1        3 \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     13        0 \n"
+"#line       1        4 \n"
+"uniform sampler2D uTexSceneDepth;\n"
+"uniform vec3 uInverseRatioDepth;\n"
+"uniform vec3 uInverseRatioMain;\n"
+"uniform bool uDepthCompare;\n"
+"\n"
+"float linear_depth( float depth, float near, float far ) {\n"
+"   float z = depth * 2.0 - 1.0;\n"
+"   return (2.0 * near * far) / (far + near - z * (far - near));       \n"
+"}\n"
+"\n"
+"void depth_compare_dither(){\n"
+"   if( uDepthCompare ){\n"
+"      vec2 back_coord = gl_FragCoord.xy * uInverseRatioMain.xy \n"
+"                                        * uInverseRatioDepth.xy;\n"
+"      float back_depth = texture( uTexSceneDepth, back_coord ).r;\n"
+"      float front_depth = gl_FragCoord.z/gl_FragCoord.w;\n"
+"\n"
+"      back_depth = linear_depth( back_depth, 0.1, 2100.0 );\n"
+"      float diff = back_depth - front_depth;\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( step(0.0,diff)+dither<0.3 )\n"
+"         discard;\n"
+"   }\n"
+"}\n"
+"\n"
+"#line     14        0 \n"
+"\n"
+"vec3 character_clearskies_lighting( vec3 normal, float shadow, vec3 halfview )\n"
+"{\n"
+"   float fresnel = 1.0 - abs(dot(normal,halfview));\n"
+"\n"
+"   vec3  reflect_colour = mix( g_daysky_colour.rgb, g_sunset_colour.rgb, \n"
+"                               g_sunset_phase );\n"
+"\n"
+"\n"
+"   vec3  sky_reflection = 0.5 * fresnel * reflect_colour;\n"
+"   vec3  light_sun      = max(0.0, dot(normal,g_sun_dir.xyz)*0.5+0.5) \n"
+"                           * g_sun_colour.rgb * g_day_phase;\n"
+"\n"
+"   float scaled_shadow = max( shadow, 1.0 - max(g_sun_dir.y,0.0) );\n"
+"   vec3 ambient = mix( g_ambient_colour.rgb, g_sunset_ambient.rgb, \n"
+"                       g_sunset_phase );\n"
+"\n"
+"   return ambient + (light_sun + sky_reflection) * shadow;\n"
+"}\n"
+"\n"
+"vec3 character_compute_lighting( vec3 diffuse, vec3 normal, vec3 co,\n"
+"                                 float light_mask )\n"
+"{\n"
+"   if( g_light_preview == 1 )\n"
+"      diffuse = vec3(0.75);\n"
+"\n"
+"   // Lighting\n"
+"   vec3 halfview = uCamera - co;\n"
+"   float fdist = length(halfview);\n"
+"   halfview /= fdist;\n"
+"\n"
+"   float world_shadow = newlight_compute_sun_shadow( \n"
+"               co, g_sun_dir.xyz * (1.0/(max(g_sun_dir.y,0.0)+0.2)) );\n"
+"\n"
+"   vec3 total_light = character_clearskies_lighting( \n"
+"                           normal, min( light_mask, world_shadow ), halfview );\n"
+"\n"
+"   vec3 cube_coord = (co - g_cube_min.xyz) * g_cube_inv_range.xyz;\n"
+"        cube_coord = floor( cube_coord );\n"
+"\n"
+"   if( g_debug_indices == 1 )\n"
+"   {\n"
+"      return rand33(cube_coord);\n"
+"   }\n"
+"\n"
+"   if( g_debug_complexity == 1 )\n"
+"   {\n"
+"      ivec3 coord = ivec3( cube_coord );\n"
+"      uvec4 index_sample = texelFetch( uLightsIndex, coord, 0 );\n"
+"\n"
+"      uint light_count = (index_sample.x & 0x3u) + (index_sample.y & 0x3u);\n"
+"      return vec3( float(light_count)*(1.0/6.0), 0.0, 0.5 );\n"
+"   }\n"
+"\n"
+"   // FIXME: this coord should absolutely must be clamped!\n"
+"   \n"
+"   ivec3 coord = ivec3( cube_coord );\n"
+"   uvec4 index_sample = texelFetch( uLightsIndex, coord, 0 );\n"
+"\n"
+"   total_light += \n"
+"      scene_calculate_packed_light_patch( index_sample.x,\n"
+"                                          halfview, co, normal ) \n"
+"                                          * light_mask;\n"
+"   total_light += \n"
+"      scene_calculate_packed_light_patch( index_sample.y,\n"
+"                                          halfview, co, normal )\n"
+"                                          * light_mask;\n"
+"\n"
+"   // Take a section of the sky function to give us a matching fog colour\n"
+"\n"
+"   vec3 fog_colour  = clearskies_ambient( -halfview );\n"
+"   float sun_theta  = dot( -halfview, g_sun_dir.xyz );\n"
+"   float sun_size   = max( 0.0, sun_theta * 0.5 + 0.5 );\n"
+"   float sun_shape  = sun_size * max(g_sun_dir.y,0.0) * 0.5;\n"
+"         \n"
+"   vec3 sun_colour  = mix( vec3(1.0), g_sunset_colour.rgb, g_sunset_phase*0.5 );\n"
+"        sun_colour *= sun_shape;\n"
+"\n"
+"   fog_colour += sun_colour;\n"
+"   return scene_apply_fog( diffuse * total_light, fog_colour, fdist );\n"
+"}\n"
+"\n"
+"void main(){\n"
+"   depth_compare_dither();\n"
+"   compute_motion_vectors();\n"
+"\n"
+"   vec3 qnorm     = aNorm;\n"
+"   vec3 diffuse   = texture( uTexMain, aUv ).rgb;\n"
+"   vec3 composite = character_compute_lighting( diffuse, qnorm, aWorldCo, 1.0 );\n"
+"\n"
+"   float dist    = distance( aWorldCo, uCamera ) - 0.08;\n"
+"   float opacity = clamp( dist*dist, 0.0, 1.0 );\n"
+"\n"
+"   oColour = vec4( composite, opacity );\n"
+"}\n"
+""},
+};
+
+GLuint _uniform_model_character_view_uPv;
+GLuint _uniform_model_character_view_uTransforms;
+GLuint _uniform_model_character_view_uTexMain;
+GLuint _uniform_model_character_view_uCamera;
+GLuint _uniform_model_character_view_g_world_depth;
+GLuint _uniform_model_character_view_uLightsArray;
+GLuint _uniform_model_character_view_uLightsIndex;
+GLuint _uniform_model_character_view_uTexSceneDepth;
+GLuint _uniform_model_character_view_uInverseRatioDepth;
+GLuint _uniform_model_character_view_uInverseRatioMain;
+GLuint _uniform_model_character_view_uDepthCompare;
+#include "shaders/model_board_view.h"
+struct vg_shader _shader_model_board_view = {
+   .name = "model_board_view",
+   .vs = 
+{
+.orig_file = "shaders/model.vs",
+.static_src = 
+"layout (location=0) in vec3 a_co;\n"
+"layout (location=1) in vec3 a_norm;\n"
+"layout (location=2) in vec2 a_uv;\n"
+"layout (location=3) in vec4 a_colour;\n"
+"layout (location=4) in vec4 a_weights;\n"
+"layout (location=5) in ivec4 a_groups;\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      9        0 \n"
+"\n"
+"uniform mat4x3 uMdl;\n"
+"uniform mat4 uPv;\n"
+"uniform mat4 uPvmPrev;\n"
+"\n"
+"out vec4 aColour;\n"
+"out vec2 aUv;\n"
+"out vec3 aNorm;\n"
+"out vec3 aCo;\n"
+"out vec3 aWorldCo;\n"
+"\n"
+"void main()\n"
+"{\n"
+"   vec3 world_pos0 = uMdl     * vec4( a_co, 1.0 );\n"
+"   vec4 vproj0     = uPv      * vec4( world_pos0, 1.0 );\n"
+"   vec4 vproj1     = uPvmPrev * vec4( a_co, 1.0 );\n"
+"\n"
+"   vs_motion_out( vproj0, vproj1 );\n"
+"\n"
+"   gl_Position = vproj0;\n"
+"   aWorldCo = world_pos0;\n"
+"   aColour = a_colour;\n"
+"   aUv = a_uv;\n"
+"   aNorm = normalize( mat3(uMdl) * a_norm );\n"
+"   aCo = a_co;\n"
+"}\n"
+""},
+   .fs = 
+{
+.orig_file = "shaders/model_character_view.fs",
+.static_src = 
+"uniform sampler2D uTexMain;\n"
+"uniform vec3 uCamera;\n"
+"\n"
+"in vec4 aColour;\n"
+"in vec2 aUv;\n"
+"in vec3 aNorm;\n"
+"in vec3 aCo;\n"
+"in vec3 aWorldCo;\n"
+"\n"
+"#line       1        1 \n"
+"// :D\n"
+"const float CLEARSKIES_LIGHT_DOT_MIN = 0.0;\n"
+"\n"
+"#line     11        0 \n"
+"#line       1        2 \n"
+"layout (location = 0) out vec4 oColour;\n"
+"\n"
+"// OpenGL wiki: Recommends do not use vec3 because of drivers. hence the v4s...\n"
+"layout (std140) uniform ub_world_lighting\n"
+"{\n"
+"   vec4 g_cube_min;\n"
+"   vec4 g_cube_inv_range;\n"
+"\n"
+"   vec4 g_water_plane;\n"
+"   vec4 g_depth_bounds;\n"
+"\n"
+"   vec4 g_daysky_colour;\n"
+"   vec4 g_nightsky_colour;\n"
+"   vec4 g_sunset_colour;\n"
+"   vec4 g_ambient_colour;\n"
+"   vec4 g_sunset_ambient;\n"
+"   vec4 g_sun_colour;\n"
+"   vec4 g_sun_dir;\n"
+"   vec4 g_board_0;\n"
+"   vec4 g_board_1;\n"
+"\n"
+"   float g_water_fog;\n"
+"   float g_time;\n"
+"   float g_realtime;\n"
+"   float g_shadow_length;\n"
+"   float g_shadow_spread;\n"
+"\n"
+"   float g_time_of_day;\n"
+"   float g_day_phase;\n"
+"   float g_sunset_phase;\n"
+"\n"
+"   int g_light_preview;\n"
+"   int g_shadow_samples;\n"
+"\n"
+"   int g_debug_indices;\n"
+"   int g_debug_complexity;\n"
+"};\n"
+"\n"
+"uniform sampler2D g_world_depth;\n"
+"uniform samplerBuffer uLightsArray;\n"
+"uniform usampler3D uLightsIndex;\n"
+"\n"
+"#line       1        1 \n"
+"//const vec3  DAYSKY_COLOUR   = vec3( 0.37, 0.54, 0.97 );\n"
+"//const vec3  NIGHTSKY_COLOUR = vec3( 0.03, 0.05, 0.20 );\n"
+"//const vec3  SUNSET_COLOUR   = vec3( 1.00, 0.32, 0.01 );\n"
+"//const vec3  AMBIENT_COLOUR  = vec3( 0.13, 0.17, 0.35 );\n"
+"//const vec3  SUNSET_AMBIENT  = vec3( 0.25, 0.17, 0.51 );\n"
+"//const vec3  SUN_COLOUR      = vec3( 1.10, 0.89, 0.35 );\n"
+"\n"
+"const float SUN_ANGLE       = 0.0001;\n"
+"const float PI              = 3.14159265358979323846264;\n"
+"\n"
+"//struct world_info\n"
+"//{\n"
+"//   float time,\n"
+"//         time_of_day,\n"
+"//         day_phase,\n"
+"//         sunset_phase;\n"
+"//   \n"
+"//   vec3 sun_dir;\n"
+"//};\n"
+"\n"
+"vec3 rand33(vec3 p3)\n"
+"{\n"
+"      p3 = fract(p3 * vec3(.1031, .1030, .0973));\n"
+"   p3 += dot(p3, p3.yxz+33.33);\n"
+"   return fract((p3.xxy + p3.yxx)*p3.zyx);\n"
+"}\n"
+"\n"
+"float stars( vec3 rd, float rr, float size ){\n"
+"   vec3 co = rd * rr;\n"
+"\n"
+"   float a = atan(co.y, length(co.xz)) + 4.0 * PI;\n"
+"\n"
+"   float spaces = 1.0 / rr;\n"
+"   size = (rr * 0.0015) * fwidth(a) * 1000.0 * size;\n"
+"   a -= mod(a, spaces) - spaces * 0.5;\n"
+"\n"
+"   float count = floor(sqrt(pow(rr, 2.0) * (1.0 - pow(sin(a), 2.0))) * 3.0);\n"
+"   \n"
+"   float plane = atan(co.z, co.x) + 4.0 * PI;\n"
+"   plane = plane - mod(plane, PI / count);\n"
+"\n"
+"   vec2 delta = rand33(vec3(plane, a, 0.0)).xy;\n"
+"\n"
+"   float level = sin(a + spaces * (delta.y - 0.5) * (1.0 - size)) * rr;\n"
+"   float ydist = sqrt(rr * rr - level * level);\n"
+"   float angle = plane + (PI * (delta.x * (1.0-size) + size * 0.5) / count);\n"
+"   vec3 center = vec3(cos(angle) * ydist, level, sin(angle) * ydist);\n"
+"   float star = smoothstep(size, 0.0, distance(center, co));\n"
+"   return star;\n"
+"}\n"
+"\n"
+"float luminance( vec3 v )\n"
+"{\n"
+"   return dot( v, vec3(0.2126, 0.7152, 0.0722) );\n"
+"}\n"
+"\n"
+"vec3 clearskies_ambient( vec3 dir )\n"
+"{\n"
+"   float sun_azimuth  = g_sunset_phase * (dot( dir.xz, g_sun_dir.xz )*0.4+0.6);\n"
+"   float sky_gradient = dir.y;\n"
+"   \n"
+"   /* Blend phase colours */\n"
+"   vec3 ambient  = g_daysky_colour.rgb   * (g_day_phase-g_sunset_phase*0.1);\n"
+"        ambient += g_sunset_colour.rgb   * (1.0-dir.y*0.5)*sun_azimuth;\n"
+"        ambient += g_nightsky_colour.rgb * (1.0-g_day_phase);\n"
+"   \n"
+"   /* Add gradient */\n"
+"        ambient -= sky_gradient * luminance(ambient);\n"
+"        \n"
+"   return ambient;\n"
+"}\n"
+"\n"
+"vec3 clearskies_sky( vec3 ray_dir )\n"
+"{\n"
+"   ray_dir.y = abs( ray_dir.y );\n"
+"   vec3 sky_colour  = clearskies_ambient( ray_dir );\n"
+"   \n"
+"   /* Sun */\n"
+"   float sun_theta  = dot( ray_dir, g_sun_dir.xyz );\n"
+"   float sun_size   = max( 0.0, sun_theta * 0.5 + 0.5 + SUN_ANGLE );\n"
+"   float sun_shape  = pow( sun_size, 2000.0 );\n"
+"         sun_shape += sun_size * max(g_sun_dir.y,0.0) * 0.5;\n"
+"         \n"
+"   vec3 sun_colour  = mix( vec3(1.0), g_sunset_colour.rgb, g_sunset_phase*0.5 );\n"
+"        sun_colour *= sun_shape;\n"
+"\n"
+"   \n"
+"   float star = 0.0;\n"
+"   float star_blend = 10.0*max(0.0,(1.0-g_day_phase*2.0));\n"
+"\n"
+"   if( star_blend > 0.001 ){\n"
+"      for( float j = 1.0; j <= 4.1; j += 1.0 ){\n"
+"         float m = mix(0.6, 0.9, smoothstep(1.0, 2.0, j));\n"
+"         star += stars( ray_dir, 1.94 * pow( 1.64, j ), m ) * (1.0/pow(4.0, j));\n"
+"      }\n"
+"   }\n"
+"   \n"
+"   vec3 composite   = sky_colour + sun_colour + star*star_blend;\n"
+"   return composite;\n"
+"}\n"
+"\n"
+"vec3 clearskies_lighting( vec3 normal, float shadow, vec3 halfview )\n"
+"{\n"
+"   float fresnel = 1.0 - abs(dot(normal,halfview));\n"
+"\n"
+"   vec3  reflect_colour = mix( g_daysky_colour.rgb, g_sunset_colour.rgb, \n"
+"                               g_sunset_phase );\n"
+"\n"
+"   vec3  sky_reflection = 0.5 * fresnel * reflect_colour;\n"
+"   vec3  light_sun      = max( CLEARSKIES_LIGHT_DOT_MIN, \n"
+"                               dot(normal,g_sun_dir.xyz)*0.75+0.25\n"
+"                           ) * g_sun_colour.rgb * g_day_phase;\n"
+"\n"
+"   float scaled_shadow = max( shadow, 1.0 - max(g_sun_dir.y,0.0) );\n"
+"   vec3 ambient = mix( g_ambient_colour.rgb, g_sunset_ambient.rgb, \n"
+"                       g_sunset_phase );\n"
+"\n"
+"   return ambient + (light_sun + sky_reflection) * shadow;\n"
+"}\n"
+"\n"
+"#line     44        0 \n"
+"\n"
+"float world_depth_sample( vec3 pos )\n"
+"{\n"
+"   vec2 depth_coord = (pos.xz - g_depth_bounds.xy) * g_depth_bounds.zw; \n"
+"   return texture( g_world_depth, depth_coord ).r;\n"
+"}\n"
+"\n"
+"float world_water_depth( vec3 pos )\n"
+"{\n"
+"   float ref_depth = g_water_plane.y*g_water_plane.w;\n"
+"   return world_depth_sample( pos ) - ref_depth;\n"
+"}\n"
+"\n"
+"float shadow_sample( vec3 co ){\n"
+"   float height_sample = world_depth_sample( co );\n"
+"\n"
+"   float fdelta = height_sample - co.y;\n"
+"   return clamp( fdelta, 0.2, 0.4 )-0.2;\n"
+"}\n"
+"\n"
+"float newlight_compute_sun_shadow( vec3 co, vec3 dir ){\n"
+"   if( g_shadow_samples == 0 ){\n"
+"      return 1.0;\n"
+"   }\n"
+"\n"
+"   float fspread = g_shadow_spread;\n"
+"   float flength = g_shadow_length;\n"
+"\n"
+"   float famt = 0.0;\n"
+"   famt += shadow_sample(co+(dir+vec3(-0.56,0.55, 0.30)*fspread)*flength*0.1);\n"
+"   famt += shadow_sample(co+(dir+vec3( 0.80,0.68, 0.34)*fspread)*flength*0.2);\n"
+"   famt += shadow_sample(co+(dir+vec3( 0.78,0.07,-0.06)*fspread)*flength*0.3);\n"
+"   famt += shadow_sample(co+(dir+vec3(-0.59,0.07,-0.42)*fspread)*flength*0.4);\n"
+"\n"
+"   //famt+=shadow_sample(co+(dir+vec3(-0.790,-0.933,-0.875)*fspread)*flength*0.5);\n"
+"   //famt+=shadow_sample(co+(dir+vec3( 0.807,-0.690, 0.472)*fspread)*flength*0.6);\n"
+"   //famt+=shadow_sample(co+(dir+vec3( 0.522,-0.379, 0.350)*fspread)*flength*0.7);\n"
+"   //famt+=shadow_sample(co+(dir+vec3( 0.483, 0.201, 0.306)*fspread)*flength*0.8);\n"
+"\n"
+"   return 1.0 - famt;\n"
+"}\n"
+"\n"
+"float newlight_specular( vec3 wnormal, vec3 dir, vec3 halfview, float exponent )\n"
+"{\n"
+"   vec3 specdir = reflect( -dir, wnormal );\n"
+"   return pow(max(dot( halfview, specdir ), 0.0), exponent);\n"
+"}\n"
+"\n"
+"vec3 scene_apply_fog( vec3 vfrag, vec3 colour, float fdist ){\n"
+"   float dist = pow(fdist*0.0010,0.78);\n"
+"   return mix( vfrag, colour, min( 1.0, dist ) );\n"
+"}\n"
+"\n"
+"vec3 scene_calculate_light( int light_index, \n"
+"                            vec3 halfview, vec3 co, vec3 normal )\n"
+"{\n"
+"   vec4 light_colour = texelFetch( uLightsArray, light_index+0 );\n"
+"   vec4 light_co     = texelFetch( uLightsArray, light_index+1 );\n"
+"   vec4 light_dir    = texelFetch( uLightsArray, light_index+2 );\n"
+"\n"
+"   vec3 light_delta = light_co.xyz-co;\n"
+"   float dist2 = dot(light_delta,light_delta);\n"
+"\n"
+"   light_delta = normalize( light_delta );\n"
+"\n"
+"   float quadratic = dist2*100.0;\n"
+"   float attenuation  = 1.0/( 1.0 + quadratic );\n"
+"         attenuation *= max( dot( light_delta, normal ), 0.0 );\n"
+"\n"
+"   float falloff = max( 0.0, 1.0-(dist2*light_co.w) );\n"
+"\n"
+"   if( light_dir.w < 0.999999 ){\n"
+"      float spot_theta = max( 0.0, dot( light_delta, -light_dir.xyz ) );\n"
+"      falloff *= max( 0.0, (spot_theta - light_dir.w) / (1.0-light_dir.w) );\n"
+"   }\n"
+"\n"
+"   return light_colour.rgb * attenuation * falloff \n"
+"            * step( g_day_phase, light_colour.w );\n"
+"}\n"
+"\n"
+"vec3 scene_calculate_packed_light_patch( uint packed_index, \n"
+"                                         vec3 halfview, vec3 co, vec3 normal )\n"
+"{\n"
+"   uint light_count = packed_index & 0x3u;\n"
+"\n"
+"   vec3 l = vec3(0.0);\n"
+"\n"
+"   if( light_count >= 1u ){\n"
+"      int index_0 = int( ((packed_index >>  2u) & 0x3ffu) * 3u );\n"
+"      int index_1 = int( ((packed_index >> 12u) & 0x3ffu) * 3u );\n"
+"      int index_2 = int( ((packed_index >> 22u) & 0x3ffu) * 3u );\n"
+"\n"
+"      l += scene_calculate_light( index_0, halfview, co, normal );\n"
+"\n"
+"      if( light_count >= 2u ){\n"
+"         l += scene_calculate_light( index_1, halfview, co, normal );\n"
+"\n"
+"         if( light_count >= 3u ){\n"
+"            l += scene_calculate_light( index_2, halfview, co, normal );\n"
+"         }\n"
+"      }\n"
+"   }\n"
+"\n"
+"   return l;\n"
+"}\n"
+"\n"
+"vec3 world_compute_lighting( vec3 diffuse, vec3 normal, vec3 co,\n"
+"                             float light_mask )\n"
+"{\n"
+"   if( g_light_preview == 1 )\n"
+"      diffuse = vec3(0.75);\n"
+"\n"
+"   // Lighting\n"
+"   vec3 halfview = uCamera - co;\n"
+"   float fdist = length(halfview);\n"
+"   halfview /= fdist;\n"
+"\n"
+"   float world_shadow = newlight_compute_sun_shadow( \n"
+"               co, g_sun_dir.xyz * (1.0/(max(g_sun_dir.y,0.0)+0.2)) );\n"
+"\n"
+"   vec3 total_light = clearskies_lighting( \n"
+"                           normal, min( light_mask, world_shadow ), halfview );\n"
+"\n"
+"   vec3 cube_coord = (co - g_cube_min.xyz) * g_cube_inv_range.xyz;\n"
+"        cube_coord = floor( cube_coord );\n"
+"\n"
+"   if( g_debug_indices == 1 )\n"
+"   {\n"
+"      return rand33(cube_coord);\n"
+"   }\n"
+"\n"
+"   if( g_debug_complexity == 1 )\n"
+"   {\n"
+"      ivec3 coord = ivec3( cube_coord );\n"
+"      uvec4 index_sample = texelFetch( uLightsIndex, coord, 0 );\n"
+"\n"
+"      uint light_count = (index_sample.x & 0x3u) + (index_sample.y & 0x3u);\n"
+"      return vec3( float(light_count)*(1.0/6.0), 0.0, 0.5 );\n"
+"   }\n"
+"\n"
+"   // FIXME: this coord should absolutely must be clamped!\n"
+"   \n"
+"   ivec3 coord = ivec3( cube_coord );\n"
+"   uvec4 index_sample = texelFetch( uLightsIndex, coord, 0 );\n"
+"\n"
+"   total_light += \n"
+"      scene_calculate_packed_light_patch( index_sample.x,\n"
+"                                          halfview, co, normal ) \n"
+"                                          * light_mask;\n"
+"   total_light += \n"
+"      scene_calculate_packed_light_patch( index_sample.y,\n"
+"                                          halfview, co, normal )\n"
+"                                          * light_mask;\n"
+"\n"
+"   // Take a section of the sky function to give us a matching fog colour\n"
+"\n"
+"   vec3 fog_colour  = clearskies_ambient( -halfview );\n"
+"   float sun_theta  = dot( -halfview, g_sun_dir.xyz );\n"
+"   float sun_size   = max( 0.0, sun_theta * 0.5 + 0.5 );\n"
+"   float sun_shape  = sun_size * max(g_sun_dir.y,0.0) * 0.5;\n"
+"         \n"
+"   vec3 sun_colour  = mix( vec3(1.0), g_sunset_colour.rgb, g_sunset_phase*0.5 );\n"
+"        sun_colour *= sun_shape;\n"
+"\n"
+"   fog_colour += sun_colour;\n"
+"   return scene_apply_fog( diffuse * total_light, fog_colour, fdist );\n"
+"}\n"
+"\n"
+"#line     12        0 \n"
+"#line       1        3 \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     13        0 \n"
+"#line       1        4 \n"
+"uniform sampler2D uTexSceneDepth;\n"
+"uniform vec3 uInverseRatioDepth;\n"
+"uniform vec3 uInverseRatioMain;\n"
+"uniform bool uDepthCompare;\n"
+"\n"
+"float linear_depth( float depth, float near, float far ) {\n"
+"   float z = depth * 2.0 - 1.0;\n"
+"   return (2.0 * near * far) / (far + near - z * (far - near));       \n"
+"}\n"
+"\n"
+"void depth_compare_dither(){\n"
+"   if( uDepthCompare ){\n"
+"      vec2 back_coord = gl_FragCoord.xy * uInverseRatioMain.xy \n"
+"                                        * uInverseRatioDepth.xy;\n"
+"      float back_depth = texture( uTexSceneDepth, back_coord ).r;\n"
+"      float front_depth = gl_FragCoord.z/gl_FragCoord.w;\n"
+"\n"
+"      back_depth = linear_depth( back_depth, 0.1, 2100.0 );\n"
+"      float diff = back_depth - front_depth;\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( step(0.0,diff)+dither<0.3 )\n"
+"         discard;\n"
+"   }\n"
+"}\n"
+"\n"
+"#line     14        0 \n"
+"\n"
+"vec3 character_clearskies_lighting( vec3 normal, float shadow, vec3 halfview )\n"
+"{\n"
+"   float fresnel = 1.0 - abs(dot(normal,halfview));\n"
+"\n"
+"   vec3  reflect_colour = mix( g_daysky_colour.rgb, g_sunset_colour.rgb, \n"
+"                               g_sunset_phase );\n"
+"\n"
+"\n"
+"   vec3  sky_reflection = 0.5 * fresnel * reflect_colour;\n"
+"   vec3  light_sun      = max(0.0, dot(normal,g_sun_dir.xyz)*0.5+0.5) \n"
+"                           * g_sun_colour.rgb * g_day_phase;\n"
+"\n"
+"   float scaled_shadow = max( shadow, 1.0 - max(g_sun_dir.y,0.0) );\n"
+"   vec3 ambient = mix( g_ambient_colour.rgb, g_sunset_ambient.rgb, \n"
+"                       g_sunset_phase );\n"
+"\n"
+"   return ambient + (light_sun + sky_reflection) * shadow;\n"
+"}\n"
+"\n"
+"vec3 character_compute_lighting( vec3 diffuse, vec3 normal, vec3 co,\n"
+"                                 float light_mask )\n"
+"{\n"
+"   if( g_light_preview == 1 )\n"
+"      diffuse = vec3(0.75);\n"
+"\n"
+"   // Lighting\n"
+"   vec3 halfview = uCamera - co;\n"
+"   float fdist = length(halfview);\n"
+"   halfview /= fdist;\n"
+"\n"
+"   float world_shadow = newlight_compute_sun_shadow( \n"
+"               co, g_sun_dir.xyz * (1.0/(max(g_sun_dir.y,0.0)+0.2)) );\n"
+"\n"
+"   vec3 total_light = character_clearskies_lighting( \n"
+"                           normal, min( light_mask, world_shadow ), halfview );\n"
+"\n"
+"   vec3 cube_coord = (co - g_cube_min.xyz) * g_cube_inv_range.xyz;\n"
+"        cube_coord = floor( cube_coord );\n"
+"\n"
+"   if( g_debug_indices == 1 )\n"
+"   {\n"
+"      return rand33(cube_coord);\n"
+"   }\n"
+"\n"
+"   if( g_debug_complexity == 1 )\n"
+"   {\n"
+"      ivec3 coord = ivec3( cube_coord );\n"
+"      uvec4 index_sample = texelFetch( uLightsIndex, coord, 0 );\n"
+"\n"
+"      uint light_count = (index_sample.x & 0x3u) + (index_sample.y & 0x3u);\n"
+"      return vec3( float(light_count)*(1.0/6.0), 0.0, 0.5 );\n"
+"   }\n"
+"\n"
+"   // FIXME: this coord should absolutely must be clamped!\n"
+"   \n"
+"   ivec3 coord = ivec3( cube_coord );\n"
+"   uvec4 index_sample = texelFetch( uLightsIndex, coord, 0 );\n"
+"\n"
+"   total_light += \n"
+"      scene_calculate_packed_light_patch( index_sample.x,\n"
+"                                          halfview, co, normal ) \n"
+"                                          * light_mask;\n"
+"   total_light += \n"
+"      scene_calculate_packed_light_patch( index_sample.y,\n"
+"                                          halfview, co, normal )\n"
+"                                          * light_mask;\n"
+"\n"
+"   // Take a section of the sky function to give us a matching fog colour\n"
+"\n"
+"   vec3 fog_colour  = clearskies_ambient( -halfview );\n"
+"   float sun_theta  = dot( -halfview, g_sun_dir.xyz );\n"
+"   float sun_size   = max( 0.0, sun_theta * 0.5 + 0.5 );\n"
+"   float sun_shape  = sun_size * max(g_sun_dir.y,0.0) * 0.5;\n"
+"         \n"
+"   vec3 sun_colour  = mix( vec3(1.0), g_sunset_colour.rgb, g_sunset_phase*0.5 );\n"
+"        sun_colour *= sun_shape;\n"
+"\n"
+"   fog_colour += sun_colour;\n"
+"   return scene_apply_fog( diffuse * total_light, fog_colour, fdist );\n"
+"}\n"
+"\n"
+"void main(){\n"
+"   depth_compare_dither();\n"
+"   compute_motion_vectors();\n"
+"\n"
+"   vec3 qnorm     = aNorm;\n"
+"   vec3 diffuse   = texture( uTexMain, aUv ).rgb;\n"
+"   vec3 composite = character_compute_lighting( diffuse, qnorm, aWorldCo, 1.0 );\n"
+"\n"
+"   float dist    = distance( aWorldCo, uCamera ) - 0.08;\n"
+"   float opacity = clamp( dist*dist, 0.0, 1.0 );\n"
+"\n"
+"   oColour = vec4( composite, opacity );\n"
+"}\n"
+""},
+};
+
+GLuint _uniform_model_board_view_uMdl;
+GLuint _uniform_model_board_view_uPv;
+GLuint _uniform_model_board_view_uPvmPrev;
+GLuint _uniform_model_board_view_uTexMain;
+GLuint _uniform_model_board_view_uCamera;
+GLuint _uniform_model_board_view_g_world_depth;
+GLuint _uniform_model_board_view_uLightsArray;
+GLuint _uniform_model_board_view_uLightsIndex;
+GLuint _uniform_model_board_view_uTexSceneDepth;
+GLuint _uniform_model_board_view_uInverseRatioDepth;
+GLuint _uniform_model_board_view_uInverseRatioMain;
+GLuint _uniform_model_board_view_uDepthCompare;
+#include "shaders/model_entity.h"
+struct vg_shader _shader_model_entity = {
+   .name = "model_entity",
+   .vs = 
+{
+.orig_file = "shaders/model.vs",
+.static_src = 
+"layout (location=0) in vec3 a_co;\n"
+"layout (location=1) in vec3 a_norm;\n"
+"layout (location=2) in vec2 a_uv;\n"
+"layout (location=3) in vec4 a_colour;\n"
+"layout (location=4) in vec4 a_weights;\n"
+"layout (location=5) in ivec4 a_groups;\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      9        0 \n"
+"\n"
+"uniform mat4x3 uMdl;\n"
+"uniform mat4 uPv;\n"
+"uniform mat4 uPvmPrev;\n"
+"\n"
+"out vec4 aColour;\n"
+"out vec2 aUv;\n"
+"out vec3 aNorm;\n"
+"out vec3 aCo;\n"
+"out vec3 aWorldCo;\n"
+"\n"
+"void main()\n"
+"{\n"
+"   vec3 world_pos0 = uMdl     * vec4( a_co, 1.0 );\n"
+"   vec4 vproj0     = uPv      * vec4( world_pos0, 1.0 );\n"
+"   vec4 vproj1     = uPvmPrev * vec4( a_co, 1.0 );\n"
+"\n"
+"   vs_motion_out( vproj0, vproj1 );\n"
+"\n"
+"   gl_Position = vproj0;\n"
+"   aWorldCo = world_pos0;\n"
+"   aColour = a_colour;\n"
+"   aUv = a_uv;\n"
+"   aNorm = normalize( mat3(uMdl) * a_norm );\n"
+"   aCo = a_co;\n"
+"}\n"
+""},
+   .fs = 
+{
+.orig_file = "shaders/model_entity.fs",
+.static_src = 
+"uniform sampler2D uTexMain;\n"
+"uniform vec3 uCamera;\n"
+"\n"
+"in vec4 aColour;\n"
+"in vec2 aUv;\n"
+"in vec3 aNorm;\n"
+"in vec3 aCo;\n"
+"in vec3 aWorldCo;\n"
+"\n"
+"#line       1        1 \n"
+"// :D\n"
+"const float CLEARSKIES_LIGHT_DOT_MIN = 0.0;\n"
+"\n"
+"#line     11        0 \n"
+"#line       1        2 \n"
+"layout (location = 0) out vec4 oColour;\n"
+"\n"
+"// OpenGL wiki: Recommends do not use vec3 because of drivers. hence the v4s...\n"
+"layout (std140) uniform ub_world_lighting\n"
+"{\n"
+"   vec4 g_cube_min;\n"
+"   vec4 g_cube_inv_range;\n"
+"\n"
+"   vec4 g_water_plane;\n"
+"   vec4 g_depth_bounds;\n"
+"\n"
+"   vec4 g_daysky_colour;\n"
+"   vec4 g_nightsky_colour;\n"
+"   vec4 g_sunset_colour;\n"
+"   vec4 g_ambient_colour;\n"
+"   vec4 g_sunset_ambient;\n"
+"   vec4 g_sun_colour;\n"
+"   vec4 g_sun_dir;\n"
+"   vec4 g_board_0;\n"
+"   vec4 g_board_1;\n"
+"\n"
+"   float g_water_fog;\n"
+"   float g_time;\n"
+"   float g_realtime;\n"
+"   float g_shadow_length;\n"
+"   float g_shadow_spread;\n"
+"\n"
+"   float g_time_of_day;\n"
+"   float g_day_phase;\n"
+"   float g_sunset_phase;\n"
+"\n"
+"   int g_light_preview;\n"
+"   int g_shadow_samples;\n"
+"\n"
+"   int g_debug_indices;\n"
+"   int g_debug_complexity;\n"
+"};\n"
+"\n"
+"uniform sampler2D g_world_depth;\n"
+"uniform samplerBuffer uLightsArray;\n"
+"uniform usampler3D uLightsIndex;\n"
+"\n"
+"#line       1        1 \n"
+"//const vec3  DAYSKY_COLOUR   = vec3( 0.37, 0.54, 0.97 );\n"
+"//const vec3  NIGHTSKY_COLOUR = vec3( 0.03, 0.05, 0.20 );\n"
+"//const vec3  SUNSET_COLOUR   = vec3( 1.00, 0.32, 0.01 );\n"
+"//const vec3  AMBIENT_COLOUR  = vec3( 0.13, 0.17, 0.35 );\n"
+"//const vec3  SUNSET_AMBIENT  = vec3( 0.25, 0.17, 0.51 );\n"
+"//const vec3  SUN_COLOUR      = vec3( 1.10, 0.89, 0.35 );\n"
+"\n"
+"const float SUN_ANGLE       = 0.0001;\n"
+"const float PI              = 3.14159265358979323846264;\n"
+"\n"
+"//struct world_info\n"
+"//{\n"
+"//   float time,\n"
+"//         time_of_day,\n"
+"//         day_phase,\n"
+"//         sunset_phase;\n"
+"//   \n"
+"//   vec3 sun_dir;\n"
+"//};\n"
+"\n"
+"vec3 rand33(vec3 p3)\n"
+"{\n"
+"      p3 = fract(p3 * vec3(.1031, .1030, .0973));\n"
+"   p3 += dot(p3, p3.yxz+33.33);\n"
+"   return fract((p3.xxy + p3.yxx)*p3.zyx);\n"
+"}\n"
+"\n"
+"float stars( vec3 rd, float rr, float size ){\n"
+"   vec3 co = rd * rr;\n"
+"\n"
+"   float a = atan(co.y, length(co.xz)) + 4.0 * PI;\n"
+"\n"
+"   float spaces = 1.0 / rr;\n"
+"   size = (rr * 0.0015) * fwidth(a) * 1000.0 * size;\n"
+"   a -= mod(a, spaces) - spaces * 0.5;\n"
+"\n"
+"   float count = floor(sqrt(pow(rr, 2.0) * (1.0 - pow(sin(a), 2.0))) * 3.0);\n"
+"   \n"
+"   float plane = atan(co.z, co.x) + 4.0 * PI;\n"
+"   plane = plane - mod(plane, PI / count);\n"
+"\n"
+"   vec2 delta = rand33(vec3(plane, a, 0.0)).xy;\n"
+"\n"
+"   float level = sin(a + spaces * (delta.y - 0.5) * (1.0 - size)) * rr;\n"
+"   float ydist = sqrt(rr * rr - level * level);\n"
+"   float angle = plane + (PI * (delta.x * (1.0-size) + size * 0.5) / count);\n"
+"   vec3 center = vec3(cos(angle) * ydist, level, sin(angle) * ydist);\n"
+"   float star = smoothstep(size, 0.0, distance(center, co));\n"
+"   return star;\n"
+"}\n"
+"\n"
+"float luminance( vec3 v )\n"
+"{\n"
+"   return dot( v, vec3(0.2126, 0.7152, 0.0722) );\n"
+"}\n"
+"\n"
+"vec3 clearskies_ambient( vec3 dir )\n"
+"{\n"
+"   float sun_azimuth  = g_sunset_phase * (dot( dir.xz, g_sun_dir.xz )*0.4+0.6);\n"
+"   float sky_gradient = dir.y;\n"
+"   \n"
+"   /* Blend phase colours */\n"
+"   vec3 ambient  = g_daysky_colour.rgb   * (g_day_phase-g_sunset_phase*0.1);\n"
+"        ambient += g_sunset_colour.rgb   * (1.0-dir.y*0.5)*sun_azimuth;\n"
+"        ambient += g_nightsky_colour.rgb * (1.0-g_day_phase);\n"
+"   \n"
+"   /* Add gradient */\n"
+"        ambient -= sky_gradient * luminance(ambient);\n"
+"        \n"
+"   return ambient;\n"
+"}\n"
+"\n"
+"vec3 clearskies_sky( vec3 ray_dir )\n"
+"{\n"
+"   ray_dir.y = abs( ray_dir.y );\n"
+"   vec3 sky_colour  = clearskies_ambient( ray_dir );\n"
+"   \n"
+"   /* Sun */\n"
+"   float sun_theta  = dot( ray_dir, g_sun_dir.xyz );\n"
+"   float sun_size   = max( 0.0, sun_theta * 0.5 + 0.5 + SUN_ANGLE );\n"
+"   float sun_shape  = pow( sun_size, 2000.0 );\n"
+"         sun_shape += sun_size * max(g_sun_dir.y,0.0) * 0.5;\n"
+"         \n"
+"   vec3 sun_colour  = mix( vec3(1.0), g_sunset_colour.rgb, g_sunset_phase*0.5 );\n"
+"        sun_colour *= sun_shape;\n"
+"\n"
+"   \n"
+"   float star = 0.0;\n"
+"   float star_blend = 10.0*max(0.0,(1.0-g_day_phase*2.0));\n"
+"\n"
+"   if( star_blend > 0.001 ){\n"
+"      for( float j = 1.0; j <= 4.1; j += 1.0 ){\n"
+"         float m = mix(0.6, 0.9, smoothstep(1.0, 2.0, j));\n"
+"         star += stars( ray_dir, 1.94 * pow( 1.64, j ), m ) * (1.0/pow(4.0, j));\n"
+"      }\n"
+"   }\n"
+"   \n"
+"   vec3 composite   = sky_colour + sun_colour + star*star_blend;\n"
+"   return composite;\n"
+"}\n"
+"\n"
+"vec3 clearskies_lighting( vec3 normal, float shadow, vec3 halfview )\n"
+"{\n"
+"   float fresnel = 1.0 - abs(dot(normal,halfview));\n"
+"\n"
+"   vec3  reflect_colour = mix( g_daysky_colour.rgb, g_sunset_colour.rgb, \n"
+"                               g_sunset_phase );\n"
+"\n"
+"   vec3  sky_reflection = 0.5 * fresnel * reflect_colour;\n"
+"   vec3  light_sun      = max( CLEARSKIES_LIGHT_DOT_MIN, \n"
+"                               dot(normal,g_sun_dir.xyz)*0.75+0.25\n"
+"                           ) * g_sun_colour.rgb * g_day_phase;\n"
+"\n"
+"   float scaled_shadow = max( shadow, 1.0 - max(g_sun_dir.y,0.0) );\n"
+"   vec3 ambient = mix( g_ambient_colour.rgb, g_sunset_ambient.rgb, \n"
+"                       g_sunset_phase );\n"
+"\n"
+"   return ambient + (light_sun + sky_reflection) * shadow;\n"
+"}\n"
+"\n"
+"#line     44        0 \n"
+"\n"
+"float world_depth_sample( vec3 pos )\n"
+"{\n"
+"   vec2 depth_coord = (pos.xz - g_depth_bounds.xy) * g_depth_bounds.zw; \n"
+"   return texture( g_world_depth, depth_coord ).r;\n"
+"}\n"
+"\n"
+"float world_water_depth( vec3 pos )\n"
+"{\n"
+"   float ref_depth = g_water_plane.y*g_water_plane.w;\n"
+"   return world_depth_sample( pos ) - ref_depth;\n"
+"}\n"
+"\n"
+"float shadow_sample( vec3 co ){\n"
+"   float height_sample = world_depth_sample( co );\n"
+"\n"
+"   float fdelta = height_sample - co.y;\n"
+"   return clamp( fdelta, 0.2, 0.4 )-0.2;\n"
+"}\n"
+"\n"
+"float newlight_compute_sun_shadow( vec3 co, vec3 dir ){\n"
+"   if( g_shadow_samples == 0 ){\n"
+"      return 1.0;\n"
+"   }\n"
+"\n"
+"   float fspread = g_shadow_spread;\n"
+"   float flength = g_shadow_length;\n"
+"\n"
+"   float famt = 0.0;\n"
+"   famt += shadow_sample(co+(dir+vec3(-0.56,0.55, 0.30)*fspread)*flength*0.1);\n"
+"   famt += shadow_sample(co+(dir+vec3( 0.80,0.68, 0.34)*fspread)*flength*0.2);\n"
+"   famt += shadow_sample(co+(dir+vec3( 0.78,0.07,-0.06)*fspread)*flength*0.3);\n"
+"   famt += shadow_sample(co+(dir+vec3(-0.59,0.07,-0.42)*fspread)*flength*0.4);\n"
+"\n"
+"   //famt+=shadow_sample(co+(dir+vec3(-0.790,-0.933,-0.875)*fspread)*flength*0.5);\n"
+"   //famt+=shadow_sample(co+(dir+vec3( 0.807,-0.690, 0.472)*fspread)*flength*0.6);\n"
+"   //famt+=shadow_sample(co+(dir+vec3( 0.522,-0.379, 0.350)*fspread)*flength*0.7);\n"
+"   //famt+=shadow_sample(co+(dir+vec3( 0.483, 0.201, 0.306)*fspread)*flength*0.8);\n"
+"\n"
+"   return 1.0 - famt;\n"
+"}\n"
+"\n"
+"float newlight_specular( vec3 wnormal, vec3 dir, vec3 halfview, float exponent )\n"
+"{\n"
+"   vec3 specdir = reflect( -dir, wnormal );\n"
+"   return pow(max(dot( halfview, specdir ), 0.0), exponent);\n"
+"}\n"
+"\n"
+"vec3 scene_apply_fog( vec3 vfrag, vec3 colour, float fdist ){\n"
+"   float dist = pow(fdist*0.0010,0.78);\n"
+"   return mix( vfrag, colour, min( 1.0, dist ) );\n"
+"}\n"
+"\n"
+"vec3 scene_calculate_light( int light_index, \n"
+"                            vec3 halfview, vec3 co, vec3 normal )\n"
+"{\n"
+"   vec4 light_colour = texelFetch( uLightsArray, light_index+0 );\n"
+"   vec4 light_co     = texelFetch( uLightsArray, light_index+1 );\n"
+"   vec4 light_dir    = texelFetch( uLightsArray, light_index+2 );\n"
+"\n"
+"   vec3 light_delta = light_co.xyz-co;\n"
+"   float dist2 = dot(light_delta,light_delta);\n"
+"\n"
+"   light_delta = normalize( light_delta );\n"
+"\n"
+"   float quadratic = dist2*100.0;\n"
+"   float attenuation  = 1.0/( 1.0 + quadratic );\n"
+"         attenuation *= max( dot( light_delta, normal ), 0.0 );\n"
+"\n"
+"   float falloff = max( 0.0, 1.0-(dist2*light_co.w) );\n"
+"\n"
+"   if( light_dir.w < 0.999999 ){\n"
+"      float spot_theta = max( 0.0, dot( light_delta, -light_dir.xyz ) );\n"
+"      falloff *= max( 0.0, (spot_theta - light_dir.w) / (1.0-light_dir.w) );\n"
+"   }\n"
+"\n"
+"   return light_colour.rgb * attenuation * falloff \n"
+"            * step( g_day_phase, light_colour.w );\n"
+"}\n"
+"\n"
+"vec3 scene_calculate_packed_light_patch( uint packed_index, \n"
+"                                         vec3 halfview, vec3 co, vec3 normal )\n"
+"{\n"
+"   uint light_count = packed_index & 0x3u;\n"
+"\n"
+"   vec3 l = vec3(0.0);\n"
+"\n"
+"   if( light_count >= 1u ){\n"
+"      int index_0 = int( ((packed_index >>  2u) & 0x3ffu) * 3u );\n"
+"      int index_1 = int( ((packed_index >> 12u) & 0x3ffu) * 3u );\n"
+"      int index_2 = int( ((packed_index >> 22u) & 0x3ffu) * 3u );\n"
+"\n"
+"      l += scene_calculate_light( index_0, halfview, co, normal );\n"
+"\n"
+"      if( light_count >= 2u ){\n"
+"         l += scene_calculate_light( index_1, halfview, co, normal );\n"
+"\n"
+"         if( light_count >= 3u ){\n"
+"            l += scene_calculate_light( index_2, halfview, co, normal );\n"
+"         }\n"
+"      }\n"
+"   }\n"
+"\n"
+"   return l;\n"
+"}\n"
+"\n"
+"vec3 world_compute_lighting( vec3 diffuse, vec3 normal, vec3 co,\n"
+"                             float light_mask )\n"
+"{\n"
+"   if( g_light_preview == 1 )\n"
+"      diffuse = vec3(0.75);\n"
+"\n"
+"   // Lighting\n"
+"   vec3 halfview = uCamera - co;\n"
+"   float fdist = length(halfview);\n"
+"   halfview /= fdist;\n"
+"\n"
+"   float world_shadow = newlight_compute_sun_shadow( \n"
+"               co, g_sun_dir.xyz * (1.0/(max(g_sun_dir.y,0.0)+0.2)) );\n"
+"\n"
+"   vec3 total_light = clearskies_lighting( \n"
+"                           normal, min( light_mask, world_shadow ), halfview );\n"
+"\n"
+"   vec3 cube_coord = (co - g_cube_min.xyz) * g_cube_inv_range.xyz;\n"
+"        cube_coord = floor( cube_coord );\n"
+"\n"
+"   if( g_debug_indices == 1 )\n"
+"   {\n"
+"      return rand33(cube_coord);\n"
+"   }\n"
+"\n"
+"   if( g_debug_complexity == 1 )\n"
+"   {\n"
+"      ivec3 coord = ivec3( cube_coord );\n"
+"      uvec4 index_sample = texelFetch( uLightsIndex, coord, 0 );\n"
+"\n"
+"      uint light_count = (index_sample.x & 0x3u) + (index_sample.y & 0x3u);\n"
+"      return vec3( float(light_count)*(1.0/6.0), 0.0, 0.5 );\n"
+"   }\n"
+"\n"
+"   // FIXME: this coord should absolutely must be clamped!\n"
+"   \n"
+"   ivec3 coord = ivec3( cube_coord );\n"
+"   uvec4 index_sample = texelFetch( uLightsIndex, coord, 0 );\n"
+"\n"
+"   total_light += \n"
+"      scene_calculate_packed_light_patch( index_sample.x,\n"
+"                                          halfview, co, normal ) \n"
+"                                          * light_mask;\n"
+"   total_light += \n"
+"      scene_calculate_packed_light_patch( index_sample.y,\n"
+"                                          halfview, co, normal )\n"
+"                                          * light_mask;\n"
+"\n"
+"   // Take a section of the sky function to give us a matching fog colour\n"
+"\n"
+"   vec3 fog_colour  = clearskies_ambient( -halfview );\n"
+"   float sun_theta  = dot( -halfview, g_sun_dir.xyz );\n"
+"   float sun_size   = max( 0.0, sun_theta * 0.5 + 0.5 );\n"
+"   float sun_shape  = sun_size * max(g_sun_dir.y,0.0) * 0.5;\n"
+"         \n"
+"   vec3 sun_colour  = mix( vec3(1.0), g_sunset_colour.rgb, g_sunset_phase*0.5 );\n"
+"        sun_colour *= sun_shape;\n"
+"\n"
+"   fog_colour += sun_colour;\n"
+"   return scene_apply_fog( diffuse * total_light, fog_colour, fdist );\n"
+"}\n"
+"\n"
+"#line     12        0 \n"
+"#line       1        3 \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     13        0 \n"
+"\n"
+"void main()\n"
+"{\n"
+"   compute_motion_vectors();\n"
+"\n"
+"   vec3 qnorm     = normalize(floor(aNorm*2.0)*0.5) + vec3(0.001,0.0,0.0);\n"
+"   vec3 diffuse   = texture( uTexMain, aUv ).rgb;\n"
+"   vec3 composite = world_compute_lighting( diffuse, qnorm, aWorldCo, 1.0 );\n"
+"\n"
+"   oColour = vec4( composite, 1.0 );\n"
+"}\n"
+""},
+};
+
+GLuint _uniform_model_entity_uMdl;
+GLuint _uniform_model_entity_uPv;
+GLuint _uniform_model_entity_uPvmPrev;
+GLuint _uniform_model_entity_uTexMain;
+GLuint _uniform_model_entity_uCamera;
+GLuint _uniform_model_entity_g_world_depth;
+GLuint _uniform_model_entity_uLightsArray;
+GLuint _uniform_model_entity_uLightsIndex;
+#include "shaders/model_gate.h"
+struct vg_shader _shader_model_gate = {
+   .name = "model_gate",
+   .vs = 
+{
+.orig_file = "shaders/model.vs",
+.static_src = 
+"layout (location=0) in vec3 a_co;\n"
+"layout (location=1) in vec3 a_norm;\n"
+"layout (location=2) in vec2 a_uv;\n"
+"layout (location=3) in vec4 a_colour;\n"
+"layout (location=4) in vec4 a_weights;\n"
+"layout (location=5) in ivec4 a_groups;\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      9        0 \n"
+"\n"
+"uniform mat4x3 uMdl;\n"
+"uniform mat4 uPv;\n"
+"uniform mat4 uPvmPrev;\n"
+"\n"
+"out vec4 aColour;\n"
+"out vec2 aUv;\n"
+"out vec3 aNorm;\n"
+"out vec3 aCo;\n"
+"out vec3 aWorldCo;\n"
+"\n"
+"void main()\n"
+"{\n"
+"   vec3 world_pos0 = uMdl     * vec4( a_co, 1.0 );\n"
+"   vec4 vproj0     = uPv      * vec4( world_pos0, 1.0 );\n"
+"   vec4 vproj1     = uPvmPrev * vec4( a_co, 1.0 );\n"
+"\n"
+"   vs_motion_out( vproj0, vproj1 );\n"
+"\n"
+"   gl_Position = vproj0;\n"
+"   aWorldCo = world_pos0;\n"
+"   aColour = a_colour;\n"
+"   aUv = a_uv;\n"
+"   aNorm = normalize( mat3(uMdl) * a_norm );\n"
+"   aCo = a_co;\n"
+"}\n"
+""},
+   .fs = 
+{
+.orig_file = "shaders/model_gate_lq.fs",
+.static_src = 
+"out vec4 FragColor;\n"
+"\n"
+"uniform float uTime;\n"
+"uniform vec3 uCam;\n"
+"uniform vec2 uInvRes;\n"
+"uniform vec4 uColour;\n"
+"\n"
+"in vec3 aNorm;\n"
+"in vec2 aUv;\n"
+"in vec3 aCo;\n"
+"\n"
+"void main()\n"
+"{\n"
+"   vec2 ssuv = gl_FragCoord.xy;\n"
+"   float opacity = 1.0-smoothstep(0.0,1.0,aUv.y+uColour.a);\n"
+"   \n"
+"   vec3 vDither = vec3( dot( vec2( 171.0, 231.0 ), ssuv) );\n"
+"   float dither = fract( vDither.g / 71.0 ) - 0.5;\n"
+"\n"
+"   if( opacity+dither<0.5 )\n"
+"      discard;\n"
+"\n"
+"   FragColor = uColour;\n"
+"}\n"
+""},
+};
+
+GLuint _uniform_model_gate_uMdl;
+GLuint _uniform_model_gate_uPv;
+GLuint _uniform_model_gate_uPvmPrev;
+GLuint _uniform_model_gate_uTime;
+GLuint _uniform_model_gate_uCam;
+GLuint _uniform_model_gate_uInvRes;
+GLuint _uniform_model_gate_uColour;
+#include "shaders/model_gate_unlinked.h"
+struct vg_shader _shader_model_gate_unlinked = {
+   .name = "model_gate_unlinked",
+   .vs = 
+{
+.orig_file = "shaders/model.vs",
+.static_src = 
+"layout (location=0) in vec3 a_co;\n"
+"layout (location=1) in vec3 a_norm;\n"
+"layout (location=2) in vec2 a_uv;\n"
+"layout (location=3) in vec4 a_colour;\n"
+"layout (location=4) in vec4 a_weights;\n"
+"layout (location=5) in ivec4 a_groups;\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      9        0 \n"
+"\n"
+"uniform mat4x3 uMdl;\n"
+"uniform mat4 uPv;\n"
+"uniform mat4 uPvmPrev;\n"
+"\n"
+"out vec4 aColour;\n"
+"out vec2 aUv;\n"
+"out vec3 aNorm;\n"
+"out vec3 aCo;\n"
+"out vec3 aWorldCo;\n"
+"\n"
+"void main()\n"
+"{\n"
+"   vec3 world_pos0 = uMdl     * vec4( a_co, 1.0 );\n"
+"   vec4 vproj0     = uPv      * vec4( world_pos0, 1.0 );\n"
+"   vec4 vproj1     = uPvmPrev * vec4( a_co, 1.0 );\n"
+"\n"
+"   vs_motion_out( vproj0, vproj1 );\n"
+"\n"
+"   gl_Position = vproj0;\n"
+"   aWorldCo = world_pos0;\n"
+"   aColour = a_colour;\n"
+"   aUv = a_uv;\n"
+"   aNorm = normalize( mat3(uMdl) * a_norm );\n"
+"   aCo = a_co;\n"
+"}\n"
+""},
+   .fs = 
+{
+.orig_file = "shaders/model_gate_unlinked.fs",
+.static_src = 
+"out vec4 FragColor;\n"
+"\n"
+"uniform float uTime;\n"
+"uniform vec3 uCam;\n"
+"uniform vec4 uColour;\n"
+"\n"
+"in vec3 aNorm;\n"
+"in vec2 aUv;\n"
+"in vec3 aCo;\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     12        0 \n"
+"\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"
+"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"
+"   compute_motion_vectors();\n"
+"\n"
+"   vec2 ssuv = gl_FragCoord.xy;\n"
+"   float grad = 1.0-aUv.y*0.1;\n"
+"   float opacity = rand_hash22( vec2(floor(aUv.y*100.0),floor(aCo.z*10.0+uTime*40.0)) ).r*grad;\n"
+"   \n"
+"   vec3 vDither = vec3( dot( vec2( 171.0, 231.0 ), ssuv) );\n"
+"   float dither = fract( vDither.g / 71.0 ) - 0.5;\n"
+"\n"
+"   if( opacity<0.9 )\n"
+"      discard;\n"
+"\n"
+"   FragColor = vec4(0.7,0.5,0.5,1.0);\n"
+"}\n"
+""},
+};
+
+GLuint _uniform_model_gate_unlinked_uMdl;
+GLuint _uniform_model_gate_unlinked_uPv;
+GLuint _uniform_model_gate_unlinked_uPvmPrev;
+GLuint _uniform_model_gate_unlinked_uTime;
+GLuint _uniform_model_gate_unlinked_uCam;
+GLuint _uniform_model_gate_unlinked_uColour;
+#include "shaders/model_font.h"
+struct vg_shader _shader_model_font = {
+   .name = "model_font",
+   .vs = 
+{
+.orig_file = "shaders/model_font.vs",
+.static_src = 
+"layout (location=0) in vec3 a_co;\n"
+"layout (location=1) in vec3 a_norm;\n"
+"layout (location=2) in vec2 a_uv;\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      6        0 \n"
+"\n"
+"uniform mat4x3 uMdl;\n"
+"uniform mat4 uPv;\n"
+"uniform mat4 uPvmPrev;\n"
+"uniform vec4 uOffset;\n"
+"\n"
+"out vec2 aUv;\n"
+"out vec4 aNorm;\n"
+"out vec3 aCo;\n"
+"out vec3 aWorldCo;\n"
+"\n"
+"void main()\n"
+"{\n"
+"   vec3 co = a_co*uOffset.w+uOffset.xyz;\n"
+"   vec3 world_pos0 = uMdl     * vec4( co, 1.0 );\n"
+"   vec4 vproj0     = uPv      * vec4( world_pos0, 1.0 );\n"
+"   vec4 vproj1     = uPvmPrev * vec4( co, 1.0 );\n"
+"\n"
+"   vs_motion_out( vproj0, vproj1 );\n"
+"\n"
+"   gl_Position = vproj0;\n"
+"\n"
+"   aUv = a_uv;\n"
+"   aNorm = vec4( mat3(uMdl) * a_norm, 0.0 );\n"
+"   aCo = co;\n"
+"   aWorldCo = world_pos0;\n"
+"}\n"
+""},
+   .fs = 
+{
+.orig_file = "shaders/model_font.fs",
+.static_src = 
+"layout (location = 0) out vec4 oColour;\n"
+"\n"
+"uniform sampler2D uTexMain;\n"
+"uniform vec4 uColour;\n"
+"\n"
+"in vec2 aUv;\n"
+"in vec4 aNorm;\n"
+"in vec3 aCo;\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     11        0 \n"
+"#line       1        2 \n"
+"uniform sampler2D uTexSceneDepth;\n"
+"uniform vec3 uInverseRatioDepth;\n"
+"uniform vec3 uInverseRatioMain;\n"
+"uniform bool uDepthCompare;\n"
+"\n"
+"float linear_depth( float depth, float near, float far ) {\n"
+"   float z = depth * 2.0 - 1.0;\n"
+"   return (2.0 * near * far) / (far + near - z * (far - near));       \n"
+"}\n"
+"\n"
+"void depth_compare_dither(){\n"
+"   if( uDepthCompare ){\n"
+"      vec2 back_coord = gl_FragCoord.xy * uInverseRatioMain.xy \n"
+"                                        * uInverseRatioDepth.xy;\n"
+"      float back_depth = texture( uTexSceneDepth, back_coord ).r;\n"
+"      float front_depth = gl_FragCoord.z/gl_FragCoord.w;\n"
+"\n"
+"      back_depth = linear_depth( back_depth, 0.1, 2100.0 );\n"
+"      float diff = back_depth - front_depth;\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( step(0.0,diff)+dither<0.3 )\n"
+"         discard;\n"
+"   }\n"
+"}\n"
+"\n"
+"#line     12        0 \n"
+"\n"
+"void main(){\n"
+"   depth_compare_dither();\n"
+"   compute_motion_vectors();\n"
+"   oColour = texture( uTexMain, aUv ) * uColour;\n"
+"}\n"
+""},
+};
+
+GLuint _uniform_model_font_uMdl;
+GLuint _uniform_model_font_uPv;
+GLuint _uniform_model_font_uPvmPrev;
+GLuint _uniform_model_font_uOffset;
+GLuint _uniform_model_font_uTexMain;
+GLuint _uniform_model_font_uColour;
+GLuint _uniform_model_font_uTexSceneDepth;
+GLuint _uniform_model_font_uInverseRatioDepth;
+GLuint _uniform_model_font_uInverseRatioMain;
+GLuint _uniform_model_font_uDepthCompare;
+#include "shaders/particle.h"
+struct vg_shader _shader_particle = {
+   .name = "particle",
+   .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"
+""},
+};
+
+GLuint _uniform_particle_uPv;
+GLuint _uniform_particle_uPvPrev;
+#include "shaders/trail.h"
+struct vg_shader _shader_trail = {
+   .name = "trail",
+   .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"
+""},
+};
+
+GLuint _uniform_trail_uPv;
+GLuint _uniform_trail_uPvPrev;
+GLuint _uniform_trail_uColour;
+#include "shaders/blit.h"
+struct vg_shader _shader_blit = {
+   .name = "blit",
+   .vs = 
+{
+.orig_file = "shaders/blit.vs",
+.static_src = 
+"layout (location=0) in vec2 a_co;\n"
+"out vec2 aUv;\n"
+"\n"
+"uniform vec2 uInverseRatio;\n"
+"\n"
+"void main()\n"
+"{\n"
+"   gl_Position = vec4(a_co*2.0-1.0,0.0,1.0);\n"
+"   aUv = a_co * uInverseRatio;\n"
+"}\n"
+""},
+   .fs = 
+{
+.orig_file = "shaders/blit.fs",
+.static_src = 
+"out vec4 FragColor;\n"
+"uniform sampler2D uTexMain;\n"
+"\n"
+"in vec2 aUv;\n"
+"\n"
+"float kPi = 3.14159265358979;\n"
+"\n"
+"vec2 fisheye_distort(vec2 xy)\n"
+"{\n"
+"   float aperture = 1350.0;\n"
+"   float apertureHalf = 0.5 * aperture * (kPi / 180.0);\n"
+"   float maxFactor = sin(apertureHalf);\n"
+"\n"
+"   vec2 uv;\n"
+"   float d = length(xy);\n"
+"   if(d < (2.0-maxFactor))\n"
+"   {\n"
+"      d = length(xy * maxFactor);\n"
+"      float z = sqrt(1.0 - d * d);\n"
+"      float r = atan(d, z) / kPi;\n"
+"      float phi = atan(xy.y, xy.x);\n"
+"\n"
+"      uv.x = r * cos(phi) + 0.5;\n"
+"      uv.y = r * sin(phi) + 0.5;\n"
+"   }\n"
+"   else\n"
+"   {\n"
+"      uv = 0.5*xy + 0.5;\n"
+"   }\n"
+"   \n"
+"   return uv;\n"
+"}\n"
+"\n"
+"\n"
+"void main()\n"
+"{\n"
+"   vec2 vwarp = 2.0*aUv - 1.0;\n"
+"   vwarp = fisheye_distort( vwarp );\n"
+"\n"
+"   FragColor = texture( uTexMain, aUv );\n"
+"}\n"
+""},
+};
+
+GLuint _uniform_blit_uInverseRatio;
+GLuint _uniform_blit_uTexMain;
+#include "shaders/blitblur.h"
+struct vg_shader _shader_blitblur = {
+   .name = "blitblur",
+   .vs = 
+{
+.orig_file = "shaders/blit.vs",
+.static_src = 
+"layout (location=0) in vec2 a_co;\n"
+"out vec2 aUv;\n"
+"\n"
+"uniform vec2 uInverseRatio;\n"
+"\n"
+"void main()\n"
+"{\n"
+"   gl_Position = vec4(a_co*2.0-1.0,0.0,1.0);\n"
+"   aUv = a_co * uInverseRatio;\n"
+"}\n"
+""},
+   .fs = 
+{
+.orig_file = "shaders/blitblur.fs",
+.static_src = 
+"out vec4 FragColor;\n"
+"uniform sampler2D uTexMain;\n"
+"uniform sampler2D uTexMotion;\n"
+"uniform float uBlurStrength;\n"
+"uniform vec2 uOverrideDir;\n"
+"uniform float uTime;\n"
+"uniform float uGlitchStrength;\n"
+"uniform vec2 uClampUv;\n"
+"\n"
+"in vec2 aUv;\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"
+"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, vuv ).xy * uBlurStrength + uOverrideDir;\n"
+"\n"
+"   vec4 vcolour0 = texture( uTexMain, min(vuv + vdir*vrand.x,uClampUv) );\n"
+"   vec4 vcolour1 = texture( uTexMain, min(vuv + vdir*vrand.y,uClampUv) );\n"
+"   vec4 vcolour2 = texture( uTexMain, min(vuv + vdir*vrand1.x,uClampUv) );\n"
+"   vec4 vcolour3 = texture( uTexMain, min(vuv + vdir*vrand1.y,uClampUv) );\n"
+"\n"
+"   FragColor = ( vcolour0 + vcolour1 + vcolour2 + vcolour3 ) * 0.25;\n"
+"}\n"
+""},
+};
+
+GLuint _uniform_blitblur_uInverseRatio;
+GLuint _uniform_blitblur_uTexMain;
+GLuint _uniform_blitblur_uTexMotion;
+GLuint _uniform_blitblur_uBlurStrength;
+GLuint _uniform_blitblur_uOverrideDir;
+GLuint _uniform_blitblur_uTime;
+GLuint _uniform_blitblur_uGlitchStrength;
+GLuint _uniform_blitblur_uClampUv;
+#include "shaders/blitcolour.h"
+struct vg_shader _shader_blitcolour = {
+   .name = "blitcolour",
+   .vs = 
+{
+.orig_file = "shaders/blit.vs",
+.static_src = 
+"layout (location=0) in vec2 a_co;\n"
+"out vec2 aUv;\n"
+"\n"
+"uniform vec2 uInverseRatio;\n"
+"\n"
+"void main()\n"
+"{\n"
+"   gl_Position = vec4(a_co*2.0-1.0,0.0,1.0);\n"
+"   aUv = a_co * uInverseRatio;\n"
+"}\n"
+""},
+   .fs = 
+{
+.orig_file = "shaders/colour.fs",
+.static_src = 
+"out vec4 FragColor;\n"
+"uniform vec4 uColour;\n"
+"\n"
+"in vec2 aUv;\n"
+"\n"
+"void main()\n"
+"{\n"
+"   FragColor = uColour;\n"
+"}\n"
+""},
+};
+
+GLuint _uniform_blitcolour_uInverseRatio;
+GLuint _uniform_blitcolour_uColour;
+#include "shaders/blit_transition.h"
+struct vg_shader _shader_blit_transition = {
+   .name = "blit_transition",
+   .vs = 
+{
+.orig_file = "shaders/blit.vs",
+.static_src = 
+"layout (location=0) in vec2 a_co;\n"
+"out vec2 aUv;\n"
+"\n"
+"uniform vec2 uInverseRatio;\n"
+"\n"
+"void main()\n"
+"{\n"
+"   gl_Position = vec4(a_co*2.0-1.0,0.0,1.0);\n"
+"   aUv = a_co * uInverseRatio;\n"
+"}\n"
+""},
+   .fs = 
+{
+.orig_file = "shaders/blit_transition.fs",
+.static_src = 
+"out vec4 FragColor;\n"
+"in vec2 aUv;\n"
+"uniform float uT;\n"
+"\n"
+"void main(){\n"
+"   float d = uT + distance( aUv, vec2(0.5,0.5) );\n"
+"\n"
+"   vec3 vDither = vec3( dot( vec2( 171.0, 231.0 ), gl_FragCoord.xy) );\n"
+"   float dither = fract( vDither.g / 71.0 ) - 0.5;\n"
+"\n"
+"   if( d+dither < -0.5 )\n"
+"      discard;\n"
+"\n"
+"   FragColor = vec4( 1.0, 0.0, 0.0, 1.0 );\n"
+"}\n"
+""},
+};
+
+GLuint _uniform_blit_transition_uInverseRatio;
+GLuint _uniform_blit_transition_uT;
+#include "shaders/routeui.h"
+struct vg_shader _shader_routeui = {
+   .name = "routeui",
+   .vs = 
+{
+.orig_file = "shaders/routeui.vs",
+.static_src = 
+"layout (location=0) in vec2 a_co;\n"
+"\n"
+"uniform vec4 uOffset;\n"
+"\n"
+"void main()\n"
+"{\n"
+"   vec2 vpos = a_co * uOffset.zw + uOffset.xy;\n"
+"   gl_Position = vec4(vpos,0.0,1.0);\n"
+"}\n"
+""},
+   .fs = 
+{
+.orig_file = "shaders/routeui.fs",
+.static_src = 
+"out vec4 FragColor;\n"
+"\n"
+"uniform vec4 uColour;\n"
+"\n"
+"void main()\n"
+"{\n"
+"   FragColor = uColour;\n"
+"}\n"
+""},
+};
+
+GLuint _uniform_routeui_uOffset;
+GLuint _uniform_routeui_uColour;
+
+
+void vg_auto_shader_link(void)
+{
+   _uniform_scene_standard_uMdl = glGetUniformLocation( _shader_scene_standard.id, "uMdl" );
+   _uniform_scene_standard_uPv = glGetUniformLocation( _shader_scene_standard.id, "uPv" );
+   _uniform_scene_standard_uPvmPrev = glGetUniformLocation( _shader_scene_standard.id, "uPvmPrev" );
+   _uniform_scene_standard_uTexGarbage = glGetUniformLocation( _shader_scene_standard.id, "uTexGarbage" );
+   _uniform_scene_standard_uTexMain = glGetUniformLocation( _shader_scene_standard.id, "uTexMain" );
+   _uniform_scene_standard_uCamera = glGetUniformLocation( _shader_scene_standard.id, "uCamera" );
+   _uniform_scene_standard_uPlane = glGetUniformLocation( _shader_scene_standard.id, "uPlane" );
+   _uniform_scene_standard_g_world_depth = glGetUniformLocation( _shader_scene_standard.id, "g_world_depth" );
+   _uniform_scene_standard_uLightsArray = glGetUniformLocation( _shader_scene_standard.id, "uLightsArray" );
+   _uniform_scene_standard_uLightsIndex = glGetUniformLocation( _shader_scene_standard.id, "uLightsIndex" );
+   _uniform_scene_standard_alphatest_uMdl = glGetUniformLocation( _shader_scene_standard_alphatest.id, "uMdl" );
+   _uniform_scene_standard_alphatest_uPv = glGetUniformLocation( _shader_scene_standard_alphatest.id, "uPv" );
+   _uniform_scene_standard_alphatest_uPvmPrev = glGetUniformLocation( _shader_scene_standard_alphatest.id, "uPvmPrev" );
+   _uniform_scene_standard_alphatest_uTexGarbage = glGetUniformLocation( _shader_scene_standard_alphatest.id, "uTexGarbage" );
+   _uniform_scene_standard_alphatest_uTexMain = glGetUniformLocation( _shader_scene_standard_alphatest.id, "uTexMain" );
+   _uniform_scene_standard_alphatest_uCamera = glGetUniformLocation( _shader_scene_standard_alphatest.id, "uCamera" );
+   _uniform_scene_standard_alphatest_uPlane = glGetUniformLocation( _shader_scene_standard_alphatest.id, "uPlane" );
+   _uniform_scene_standard_alphatest_g_world_depth = glGetUniformLocation( _shader_scene_standard_alphatest.id, "g_world_depth" );
+   _uniform_scene_standard_alphatest_uLightsArray = glGetUniformLocation( _shader_scene_standard_alphatest.id, "uLightsArray" );
+   _uniform_scene_standard_alphatest_uLightsIndex = glGetUniformLocation( _shader_scene_standard_alphatest.id, "uLightsIndex" );
+   _uniform_scene_foliage_uMdl = glGetUniformLocation( _shader_scene_foliage.id, "uMdl" );
+   _uniform_scene_foliage_uPv = glGetUniformLocation( _shader_scene_foliage.id, "uPv" );
+   _uniform_scene_foliage_uPvmPrev = glGetUniformLocation( _shader_scene_foliage.id, "uPvmPrev" );
+   _uniform_scene_foliage_uTime = glGetUniformLocation( _shader_scene_foliage.id, "uTime" );
+   _uniform_scene_foliage_uTexGarbage = glGetUniformLocation( _shader_scene_foliage.id, "uTexGarbage" );
+   _uniform_scene_foliage_uTexMain = glGetUniformLocation( _shader_scene_foliage.id, "uTexMain" );
+   _uniform_scene_foliage_uCamera = glGetUniformLocation( _shader_scene_foliage.id, "uCamera" );
+   _uniform_scene_foliage_uPlane = glGetUniformLocation( _shader_scene_foliage.id, "uPlane" );
+   _uniform_scene_foliage_g_world_depth = glGetUniformLocation( _shader_scene_foliage.id, "g_world_depth" );
+   _uniform_scene_foliage_uLightsArray = glGetUniformLocation( _shader_scene_foliage.id, "uLightsArray" );
+   _uniform_scene_foliage_uLightsIndex = glGetUniformLocation( _shader_scene_foliage.id, "uLightsIndex" );
+   _uniform_scene_override_uMdl = glGetUniformLocation( _shader_scene_override.id, "uMdl" );
+   _uniform_scene_override_uPv = glGetUniformLocation( _shader_scene_override.id, "uPv" );
+   _uniform_scene_override_uPvmPrev = glGetUniformLocation( _shader_scene_override.id, "uPvmPrev" );
+   _uniform_scene_override_uNormalMtx = glGetUniformLocation( _shader_scene_override.id, "uNormalMtx" );
+   _uniform_scene_override_uTexGarbage = glGetUniformLocation( _shader_scene_override.id, "uTexGarbage" );
+   _uniform_scene_override_uTexMain = glGetUniformLocation( _shader_scene_override.id, "uTexMain" );
+   _uniform_scene_override_uCamera = glGetUniformLocation( _shader_scene_override.id, "uCamera" );
+   _uniform_scene_override_uPlane = glGetUniformLocation( _shader_scene_override.id, "uPlane" );
+   _uniform_scene_override_uPlayerPos = glGetUniformLocation( _shader_scene_override.id, "uPlayerPos" );
+   _uniform_scene_override_uSpawnPos = glGetUniformLocation( _shader_scene_override.id, "uSpawnPos" );
+   _uniform_scene_override_uAlphatest = glGetUniformLocation( _shader_scene_override.id, "uAlphatest" );
+   _uniform_scene_override_uMapInfo = glGetUniformLocation( _shader_scene_override.id, "uMapInfo" );
+   _uniform_scene_override_g_world_depth = glGetUniformLocation( _shader_scene_override.id, "g_world_depth" );
+   _uniform_scene_override_uLightsArray = glGetUniformLocation( _shader_scene_override.id, "uLightsArray" );
+   _uniform_scene_override_uLightsIndex = glGetUniformLocation( _shader_scene_override.id, "uLightsIndex" );
+   _uniform_scene_fxglow_uMdl = glGetUniformLocation( _shader_scene_fxglow.id, "uMdl" );
+   _uniform_scene_fxglow_uPv = glGetUniformLocation( _shader_scene_fxglow.id, "uPv" );
+   _uniform_scene_fxglow_uPvmPrev = glGetUniformLocation( _shader_scene_fxglow.id, "uPvmPrev" );
+   _uniform_scene_fxglow_uUvOffset = glGetUniformLocation( _shader_scene_fxglow.id, "uUvOffset" );
+   _uniform_scene_fxglow_uTexMain = glGetUniformLocation( _shader_scene_fxglow.id, "uTexMain" );
+   _uniform_scene_fxglow_uCamera = glGetUniformLocation( _shader_scene_fxglow.id, "uCamera" );
+   _uniform_scene_fxglow_g_world_depth = glGetUniformLocation( _shader_scene_fxglow.id, "g_world_depth" );
+   _uniform_scene_fxglow_uLightsArray = glGetUniformLocation( _shader_scene_fxglow.id, "uLightsArray" );
+   _uniform_scene_fxglow_uLightsIndex = glGetUniformLocation( _shader_scene_fxglow.id, "uLightsIndex" );
+   _uniform_scene_vertex_blend_uMdl = glGetUniformLocation( _shader_scene_vertex_blend.id, "uMdl" );
+   _uniform_scene_vertex_blend_uPv = glGetUniformLocation( _shader_scene_vertex_blend.id, "uPv" );
+   _uniform_scene_vertex_blend_uPvmPrev = glGetUniformLocation( _shader_scene_vertex_blend.id, "uPvmPrev" );
+   _uniform_scene_vertex_blend_uTexGarbage = glGetUniformLocation( _shader_scene_vertex_blend.id, "uTexGarbage" );
+   _uniform_scene_vertex_blend_uTexGradients = glGetUniformLocation( _shader_scene_vertex_blend.id, "uTexGradients" );
+   _uniform_scene_vertex_blend_uCamera = glGetUniformLocation( _shader_scene_vertex_blend.id, "uCamera" );
+   _uniform_scene_vertex_blend_g_world_depth = glGetUniformLocation( _shader_scene_vertex_blend.id, "g_world_depth" );
+   _uniform_scene_vertex_blend_uLightsArray = glGetUniformLocation( _shader_scene_vertex_blend.id, "uLightsArray" );
+   _uniform_scene_vertex_blend_uLightsIndex = glGetUniformLocation( _shader_scene_vertex_blend.id, "uLightsIndex" );
+   _uniform_scene_terrain_uMdl = glGetUniformLocation( _shader_scene_terrain.id, "uMdl" );
+   _uniform_scene_terrain_uPv = glGetUniformLocation( _shader_scene_terrain.id, "uPv" );
+   _uniform_scene_terrain_uPvmPrev = glGetUniformLocation( _shader_scene_terrain.id, "uPvmPrev" );
+   _uniform_scene_terrain_uTexGarbage = glGetUniformLocation( _shader_scene_terrain.id, "uTexGarbage" );
+   _uniform_scene_terrain_uTexGradients = glGetUniformLocation( _shader_scene_terrain.id, "uTexGradients" );
+   _uniform_scene_terrain_uCamera = glGetUniformLocation( _shader_scene_terrain.id, "uCamera" );
+   _uniform_scene_terrain_uSandColour = glGetUniformLocation( _shader_scene_terrain.id, "uSandColour" );
+   _uniform_scene_terrain_uBlendOffset = glGetUniformLocation( _shader_scene_terrain.id, "uBlendOffset" );
+   _uniform_scene_terrain_g_world_depth = glGetUniformLocation( _shader_scene_terrain.id, "g_world_depth" );
+   _uniform_scene_terrain_uLightsArray = glGetUniformLocation( _shader_scene_terrain.id, "uLightsArray" );
+   _uniform_scene_terrain_uLightsIndex = glGetUniformLocation( _shader_scene_terrain.id, "uLightsIndex" );
+   _uniform_scene_route_uMdl = glGetUniformLocation( _shader_scene_route.id, "uMdl" );
+   _uniform_scene_route_uPv = glGetUniformLocation( _shader_scene_route.id, "uPv" );
+   _uniform_scene_route_uPvmPrev = glGetUniformLocation( _shader_scene_route.id, "uPvmPrev" );
+   _uniform_scene_route_uNormalMtx = glGetUniformLocation( _shader_scene_route.id, "uNormalMtx" );
+   _uniform_scene_route_uTexGarbage = glGetUniformLocation( _shader_scene_route.id, "uTexGarbage" );
+   _uniform_scene_route_uTexGradients = glGetUniformLocation( _shader_scene_route.id, "uTexGradients" );
+   _uniform_scene_route_uCamera = glGetUniformLocation( _shader_scene_route.id, "uCamera" );
+   _uniform_scene_route_uColour = glGetUniformLocation( _shader_scene_route.id, "uColour" );
+   _uniform_scene_route_g_world_depth = glGetUniformLocation( _shader_scene_route.id, "g_world_depth" );
+   _uniform_scene_route_uLightsArray = glGetUniformLocation( _shader_scene_route.id, "uLightsArray" );
+   _uniform_scene_route_uLightsIndex = glGetUniformLocation( _shader_scene_route.id, "uLightsIndex" );
+   _uniform_scene_depth_uMdl = glGetUniformLocation( _shader_scene_depth.id, "uMdl" );
+   _uniform_scene_depth_uPv = glGetUniformLocation( _shader_scene_depth.id, "uPv" );
+   _uniform_scene_depth_uPvmPrev = glGetUniformLocation( _shader_scene_depth.id, "uPvmPrev" );
+   _uniform_scene_depth_uCamera = glGetUniformLocation( _shader_scene_depth.id, "uCamera" );
+   _uniform_scene_depth_uBoard0 = glGetUniformLocation( _shader_scene_depth.id, "uBoard0" );
+   _uniform_scene_depth_uBoard1 = glGetUniformLocation( _shader_scene_depth.id, "uBoard1" );
+   _uniform_scene_depth_g_world_depth = glGetUniformLocation( _shader_scene_depth.id, "g_world_depth" );
+   _uniform_scene_depth_uLightsArray = glGetUniformLocation( _shader_scene_depth.id, "uLightsArray" );
+   _uniform_scene_depth_uLightsIndex = glGetUniformLocation( _shader_scene_depth.id, "uLightsIndex" );
+   _uniform_scene_position_uMdl = glGetUniformLocation( _shader_scene_position.id, "uMdl" );
+   _uniform_scene_position_uPv = glGetUniformLocation( _shader_scene_position.id, "uPv" );
+   _uniform_scene_position_uPvmPrev = glGetUniformLocation( _shader_scene_position.id, "uPvmPrev" );
+   _uniform_scene_position_uCamera = glGetUniformLocation( _shader_scene_position.id, "uCamera" );
+   _uniform_scene_position_uBoard0 = glGetUniformLocation( _shader_scene_position.id, "uBoard0" );
+   _uniform_scene_position_uBoard1 = glGetUniformLocation( _shader_scene_position.id, "uBoard1" );
+   _uniform_scene_position_g_world_depth = glGetUniformLocation( _shader_scene_position.id, "g_world_depth" );
+   _uniform_scene_position_uLightsArray = glGetUniformLocation( _shader_scene_position.id, "uLightsArray" );
+   _uniform_scene_position_uLightsIndex = glGetUniformLocation( _shader_scene_position.id, "uLightsIndex" );
+   _uniform_scene_cubemapped_uMdl = glGetUniformLocation( _shader_scene_cubemapped.id, "uMdl" );
+   _uniform_scene_cubemapped_uPv = glGetUniformLocation( _shader_scene_cubemapped.id, "uPv" );
+   _uniform_scene_cubemapped_uPvmPrev = glGetUniformLocation( _shader_scene_cubemapped.id, "uPvmPrev" );
+   _uniform_scene_cubemapped_uTexGarbage = glGetUniformLocation( _shader_scene_cubemapped.id, "uTexGarbage" );
+   _uniform_scene_cubemapped_uTexMain = glGetUniformLocation( _shader_scene_cubemapped.id, "uTexMain" );
+   _uniform_scene_cubemapped_uTexCubemap = glGetUniformLocation( _shader_scene_cubemapped.id, "uTexCubemap" );
+   _uniform_scene_cubemapped_uCamera = glGetUniformLocation( _shader_scene_cubemapped.id, "uCamera" );
+   _uniform_scene_cubemapped_uPlane = glGetUniformLocation( _shader_scene_cubemapped.id, "uPlane" );
+   _uniform_scene_cubemapped_uColour = glGetUniformLocation( _shader_scene_cubemapped.id, "uColour" );
+   _uniform_scene_cubemapped_g_world_depth = glGetUniformLocation( _shader_scene_cubemapped.id, "g_world_depth" );
+   _uniform_scene_cubemapped_uLightsArray = glGetUniformLocation( _shader_scene_cubemapped.id, "uLightsArray" );
+   _uniform_scene_cubemapped_uLightsIndex = glGetUniformLocation( _shader_scene_cubemapped.id, "uLightsIndex" );
+   _uniform_scene_water_uMdl = glGetUniformLocation( _shader_scene_water.id, "uMdl" );
+   _uniform_scene_water_uPv = glGetUniformLocation( _shader_scene_water.id, "uPv" );
+   _uniform_scene_water_uPvmPrev = glGetUniformLocation( _shader_scene_water.id, "uPvmPrev" );
+   _uniform_scene_water_uTexMain = glGetUniformLocation( _shader_scene_water.id, "uTexMain" );
+   _uniform_scene_water_uTexDudv = glGetUniformLocation( _shader_scene_water.id, "uTexDudv" );
+   _uniform_scene_water_uTexBack = glGetUniformLocation( _shader_scene_water.id, "uTexBack" );
+   _uniform_scene_water_uInvRes = glGetUniformLocation( _shader_scene_water.id, "uInvRes" );
+   _uniform_scene_water_uTime = glGetUniformLocation( _shader_scene_water.id, "uTime" );
+   _uniform_scene_water_uCamera = glGetUniformLocation( _shader_scene_water.id, "uCamera" );
+   _uniform_scene_water_uSurfaceY = glGetUniformLocation( _shader_scene_water.id, "uSurfaceY" );
+   _uniform_scene_water_uBoard0 = glGetUniformLocation( _shader_scene_water.id, "uBoard0" );
+   _uniform_scene_water_uBoard1 = glGetUniformLocation( _shader_scene_water.id, "uBoard1" );
+   _uniform_scene_water_uShoreColour = glGetUniformLocation( _shader_scene_water.id, "uShoreColour" );
+   _uniform_scene_water_uOceanColour = glGetUniformLocation( _shader_scene_water.id, "uOceanColour" );
+   _uniform_scene_water_g_world_depth = glGetUniformLocation( _shader_scene_water.id, "g_world_depth" );
+   _uniform_scene_water_uLightsArray = glGetUniformLocation( _shader_scene_water.id, "uLightsArray" );
+   _uniform_scene_water_uLightsIndex = glGetUniformLocation( _shader_scene_water.id, "uLightsIndex" );
+   _uniform_scene_water_fast_uMdl = glGetUniformLocation( _shader_scene_water_fast.id, "uMdl" );
+   _uniform_scene_water_fast_uPv = glGetUniformLocation( _shader_scene_water_fast.id, "uPv" );
+   _uniform_scene_water_fast_uPvmPrev = glGetUniformLocation( _shader_scene_water_fast.id, "uPvmPrev" );
+   _uniform_scene_water_fast_uTexDudv = glGetUniformLocation( _shader_scene_water_fast.id, "uTexDudv" );
+   _uniform_scene_water_fast_uTime = glGetUniformLocation( _shader_scene_water_fast.id, "uTime" );
+   _uniform_scene_water_fast_uCamera = glGetUniformLocation( _shader_scene_water_fast.id, "uCamera" );
+   _uniform_scene_water_fast_uSurfaceY = glGetUniformLocation( _shader_scene_water_fast.id, "uSurfaceY" );
+   _uniform_scene_water_fast_uBoard0 = glGetUniformLocation( _shader_scene_water_fast.id, "uBoard0" );
+   _uniform_scene_water_fast_uBoard1 = glGetUniformLocation( _shader_scene_water_fast.id, "uBoard1" );
+   _uniform_scene_water_fast_uShoreColour = glGetUniformLocation( _shader_scene_water_fast.id, "uShoreColour" );
+   _uniform_scene_water_fast_uOceanColour = glGetUniformLocation( _shader_scene_water_fast.id, "uOceanColour" );
+   _uniform_scene_water_fast_g_world_depth = glGetUniformLocation( _shader_scene_water_fast.id, "g_world_depth" );
+   _uniform_scene_water_fast_uLightsArray = glGetUniformLocation( _shader_scene_water_fast.id, "uLightsArray" );
+   _uniform_scene_water_fast_uLightsIndex = glGetUniformLocation( _shader_scene_water_fast.id, "uLightsIndex" );
+   _uniform_scene_scoretext_uMdl = glGetUniformLocation( _shader_scene_scoretext.id, "uMdl" );
+   _uniform_scene_scoretext_uPv = glGetUniformLocation( _shader_scene_scoretext.id, "uPv" );
+   _uniform_scene_scoretext_uPvmPrev = glGetUniformLocation( _shader_scene_scoretext.id, "uPvmPrev" );
+   _uniform_scene_scoretext_uInfo = glGetUniformLocation( _shader_scene_scoretext.id, "uInfo" );
+   _uniform_scene_scoretext_uTexGarbage = glGetUniformLocation( _shader_scene_scoretext.id, "uTexGarbage" );
+   _uniform_scene_scoretext_uTexMain = glGetUniformLocation( _shader_scene_scoretext.id, "uTexMain" );
+   _uniform_scene_scoretext_uCamera = glGetUniformLocation( _shader_scene_scoretext.id, "uCamera" );
+   _uniform_scene_scoretext_uPlane = glGetUniformLocation( _shader_scene_scoretext.id, "uPlane" );
+   _uniform_scene_scoretext_g_world_depth = glGetUniformLocation( _shader_scene_scoretext.id, "g_world_depth" );
+   _uniform_scene_scoretext_uLightsArray = glGetUniformLocation( _shader_scene_scoretext.id, "uLightsArray" );
+   _uniform_scene_scoretext_uLightsIndex = glGetUniformLocation( _shader_scene_scoretext.id, "uLightsIndex" );
+   _uniform_scene_font_uMdl = glGetUniformLocation( _shader_scene_font.id, "uMdl" );
+   _uniform_scene_font_uPv = glGetUniformLocation( _shader_scene_font.id, "uPv" );
+   _uniform_scene_font_uPvmPrev = glGetUniformLocation( _shader_scene_font.id, "uPvmPrev" );
+   _uniform_scene_font_uOffset = glGetUniformLocation( _shader_scene_font.id, "uOffset" );
+   _uniform_scene_font_uTexGarbage = glGetUniformLocation( _shader_scene_font.id, "uTexGarbage" );
+   _uniform_scene_font_uTexMain = glGetUniformLocation( _shader_scene_font.id, "uTexMain" );
+   _uniform_scene_font_uCamera = glGetUniformLocation( _shader_scene_font.id, "uCamera" );
+   _uniform_scene_font_uTime = glGetUniformLocation( _shader_scene_font.id, "uTime" );
+   _uniform_scene_font_uOpacity = glGetUniformLocation( _shader_scene_font.id, "uOpacity" );
+   _uniform_scene_font_uColourize = glGetUniformLocation( _shader_scene_font.id, "uColourize" );
+   _uniform_scene_font_g_world_depth = glGetUniformLocation( _shader_scene_font.id, "g_world_depth" );
+   _uniform_scene_font_uLightsArray = glGetUniformLocation( _shader_scene_font.id, "uLightsArray" );
+   _uniform_scene_font_uLightsIndex = glGetUniformLocation( _shader_scene_font.id, "uLightsIndex" );
+   _uniform_model_sky_uMdl = glGetUniformLocation( _shader_model_sky.id, "uMdl" );
+   _uniform_model_sky_uPv = glGetUniformLocation( _shader_model_sky.id, "uPv" );
+   _uniform_model_sky_uPvmPrev = glGetUniformLocation( _shader_model_sky.id, "uPvmPrev" );
+   _uniform_model_sky_uTexGarbage = glGetUniformLocation( _shader_model_sky.id, "uTexGarbage" );
+   _uniform_model_sky_g_world_depth = glGetUniformLocation( _shader_model_sky.id, "g_world_depth" );
+   _uniform_model_sky_uLightsArray = glGetUniformLocation( _shader_model_sky.id, "uLightsArray" );
+   _uniform_model_sky_uLightsIndex = glGetUniformLocation( _shader_model_sky.id, "uLightsIndex" );
+   _uniform_model_sky_space_uMdl = glGetUniformLocation( _shader_model_sky_space.id, "uMdl" );
+   _uniform_model_sky_space_uPv = glGetUniformLocation( _shader_model_sky_space.id, "uPv" );
+   _uniform_model_sky_space_uPvmPrev = glGetUniformLocation( _shader_model_sky_space.id, "uPvmPrev" );
+   _uniform_model_sky_space_uTexGarbage = glGetUniformLocation( _shader_model_sky_space.id, "uTexGarbage" );
+   _uniform_model_sky_space_g_world_depth = glGetUniformLocation( _shader_model_sky_space.id, "g_world_depth" );
+   _uniform_model_sky_space_uLightsArray = glGetUniformLocation( _shader_model_sky_space.id, "uLightsArray" );
+   _uniform_model_sky_space_uLightsIndex = glGetUniformLocation( _shader_model_sky_space.id, "uLightsIndex" );
+   _uniform_model_menu_uMdl = glGetUniformLocation( _shader_model_menu.id, "uMdl" );
+   _uniform_model_menu_uPv = glGetUniformLocation( _shader_model_menu.id, "uPv" );
+   _uniform_model_menu_uPvmPrev = glGetUniformLocation( _shader_model_menu.id, "uPvmPrev" );
+   _uniform_model_menu_uTexMain = glGetUniformLocation( _shader_model_menu.id, "uTexMain" );
+   _uniform_model_menu_uColour = glGetUniformLocation( _shader_model_menu.id, "uColour" );
+   _uniform_model_character_view_uPv = glGetUniformLocation( _shader_model_character_view.id, "uPv" );
+   _uniform_model_character_view_uTransforms = glGetUniformLocation( _shader_model_character_view.id, "uTransforms" );
+   _uniform_model_character_view_uTexMain = glGetUniformLocation( _shader_model_character_view.id, "uTexMain" );
+   _uniform_model_character_view_uCamera = glGetUniformLocation( _shader_model_character_view.id, "uCamera" );
+   _uniform_model_character_view_g_world_depth = glGetUniformLocation( _shader_model_character_view.id, "g_world_depth" );
+   _uniform_model_character_view_uLightsArray = glGetUniformLocation( _shader_model_character_view.id, "uLightsArray" );
+   _uniform_model_character_view_uLightsIndex = glGetUniformLocation( _shader_model_character_view.id, "uLightsIndex" );
+   _uniform_model_character_view_uTexSceneDepth = glGetUniformLocation( _shader_model_character_view.id, "uTexSceneDepth" );
+   _uniform_model_character_view_uInverseRatioDepth = glGetUniformLocation( _shader_model_character_view.id, "uInverseRatioDepth" );
+   _uniform_model_character_view_uInverseRatioMain = glGetUniformLocation( _shader_model_character_view.id, "uInverseRatioMain" );
+   _uniform_model_character_view_uDepthCompare = glGetUniformLocation( _shader_model_character_view.id, "uDepthCompare" );
+   _uniform_model_board_view_uMdl = glGetUniformLocation( _shader_model_board_view.id, "uMdl" );
+   _uniform_model_board_view_uPv = glGetUniformLocation( _shader_model_board_view.id, "uPv" );
+   _uniform_model_board_view_uPvmPrev = glGetUniformLocation( _shader_model_board_view.id, "uPvmPrev" );
+   _uniform_model_board_view_uTexMain = glGetUniformLocation( _shader_model_board_view.id, "uTexMain" );
+   _uniform_model_board_view_uCamera = glGetUniformLocation( _shader_model_board_view.id, "uCamera" );
+   _uniform_model_board_view_g_world_depth = glGetUniformLocation( _shader_model_board_view.id, "g_world_depth" );
+   _uniform_model_board_view_uLightsArray = glGetUniformLocation( _shader_model_board_view.id, "uLightsArray" );
+   _uniform_model_board_view_uLightsIndex = glGetUniformLocation( _shader_model_board_view.id, "uLightsIndex" );
+   _uniform_model_board_view_uTexSceneDepth = glGetUniformLocation( _shader_model_board_view.id, "uTexSceneDepth" );
+   _uniform_model_board_view_uInverseRatioDepth = glGetUniformLocation( _shader_model_board_view.id, "uInverseRatioDepth" );
+   _uniform_model_board_view_uInverseRatioMain = glGetUniformLocation( _shader_model_board_view.id, "uInverseRatioMain" );
+   _uniform_model_board_view_uDepthCompare = glGetUniformLocation( _shader_model_board_view.id, "uDepthCompare" );
+   _uniform_model_entity_uMdl = glGetUniformLocation( _shader_model_entity.id, "uMdl" );
+   _uniform_model_entity_uPv = glGetUniformLocation( _shader_model_entity.id, "uPv" );
+   _uniform_model_entity_uPvmPrev = glGetUniformLocation( _shader_model_entity.id, "uPvmPrev" );
+   _uniform_model_entity_uTexMain = glGetUniformLocation( _shader_model_entity.id, "uTexMain" );
+   _uniform_model_entity_uCamera = glGetUniformLocation( _shader_model_entity.id, "uCamera" );
+   _uniform_model_entity_g_world_depth = glGetUniformLocation( _shader_model_entity.id, "g_world_depth" );
+   _uniform_model_entity_uLightsArray = glGetUniformLocation( _shader_model_entity.id, "uLightsArray" );
+   _uniform_model_entity_uLightsIndex = glGetUniformLocation( _shader_model_entity.id, "uLightsIndex" );
+   _uniform_model_gate_uMdl = glGetUniformLocation( _shader_model_gate.id, "uMdl" );
+   _uniform_model_gate_uPv = glGetUniformLocation( _shader_model_gate.id, "uPv" );
+   _uniform_model_gate_uPvmPrev = glGetUniformLocation( _shader_model_gate.id, "uPvmPrev" );
+   _uniform_model_gate_uTime = glGetUniformLocation( _shader_model_gate.id, "uTime" );
+   _uniform_model_gate_uCam = glGetUniformLocation( _shader_model_gate.id, "uCam" );
+   _uniform_model_gate_uInvRes = glGetUniformLocation( _shader_model_gate.id, "uInvRes" );
+   _uniform_model_gate_uColour = glGetUniformLocation( _shader_model_gate.id, "uColour" );
+   _uniform_model_gate_unlinked_uMdl = glGetUniformLocation( _shader_model_gate_unlinked.id, "uMdl" );
+   _uniform_model_gate_unlinked_uPv = glGetUniformLocation( _shader_model_gate_unlinked.id, "uPv" );
+   _uniform_model_gate_unlinked_uPvmPrev = glGetUniformLocation( _shader_model_gate_unlinked.id, "uPvmPrev" );
+   _uniform_model_gate_unlinked_uTime = glGetUniformLocation( _shader_model_gate_unlinked.id, "uTime" );
+   _uniform_model_gate_unlinked_uCam = glGetUniformLocation( _shader_model_gate_unlinked.id, "uCam" );
+   _uniform_model_gate_unlinked_uColour = glGetUniformLocation( _shader_model_gate_unlinked.id, "uColour" );
+   _uniform_model_font_uMdl = glGetUniformLocation( _shader_model_font.id, "uMdl" );
+   _uniform_model_font_uPv = glGetUniformLocation( _shader_model_font.id, "uPv" );
+   _uniform_model_font_uPvmPrev = glGetUniformLocation( _shader_model_font.id, "uPvmPrev" );
+   _uniform_model_font_uOffset = glGetUniformLocation( _shader_model_font.id, "uOffset" );
+   _uniform_model_font_uTexMain = glGetUniformLocation( _shader_model_font.id, "uTexMain" );
+   _uniform_model_font_uColour = glGetUniformLocation( _shader_model_font.id, "uColour" );
+   _uniform_model_font_uTexSceneDepth = glGetUniformLocation( _shader_model_font.id, "uTexSceneDepth" );
+   _uniform_model_font_uInverseRatioDepth = glGetUniformLocation( _shader_model_font.id, "uInverseRatioDepth" );
+   _uniform_model_font_uInverseRatioMain = glGetUniformLocation( _shader_model_font.id, "uInverseRatioMain" );
+   _uniform_model_font_uDepthCompare = glGetUniformLocation( _shader_model_font.id, "uDepthCompare" );
+   _uniform_particle_uPv = glGetUniformLocation( _shader_particle.id, "uPv" );
+   _uniform_particle_uPvPrev = glGetUniformLocation( _shader_particle.id, "uPvPrev" );
+   _uniform_trail_uPv = glGetUniformLocation( _shader_trail.id, "uPv" );
+   _uniform_trail_uPvPrev = glGetUniformLocation( _shader_trail.id, "uPvPrev" );
+   _uniform_trail_uColour = glGetUniformLocation( _shader_trail.id, "uColour" );
+   _uniform_blit_uInverseRatio = glGetUniformLocation( _shader_blit.id, "uInverseRatio" );
+   _uniform_blit_uTexMain = glGetUniformLocation( _shader_blit.id, "uTexMain" );
+   _uniform_blitblur_uInverseRatio = glGetUniformLocation( _shader_blitblur.id, "uInverseRatio" );
+   _uniform_blitblur_uTexMain = glGetUniformLocation( _shader_blitblur.id, "uTexMain" );
+   _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" );
+   _uniform_blitblur_uClampUv = glGetUniformLocation( _shader_blitblur.id, "uClampUv" );
+   _uniform_blitcolour_uInverseRatio = glGetUniformLocation( _shader_blitcolour.id, "uInverseRatio" );
+   _uniform_blitcolour_uColour = glGetUniformLocation( _shader_blitcolour.id, "uColour" );
+   _uniform_blit_transition_uInverseRatio = glGetUniformLocation( _shader_blit_transition.id, "uInverseRatio" );
+   _uniform_blit_transition_uT = glGetUniformLocation( _shader_blit_transition.id, "uT" );
+   _uniform_routeui_uOffset = glGetUniformLocation( _shader_routeui.id, "uOffset" );
+   _uniform_routeui_uColour = glGetUniformLocation( _shader_routeui.id, "uColour" );
+}
+
+void vg_auto_shader_register(void)
+{
+   vg_shader_register( &_shader_scene_standard );
+   vg_shader_register( &_shader_scene_standard_alphatest );
+   vg_shader_register( &_shader_scene_foliage );
+   vg_shader_register( &_shader_scene_override );
+   vg_shader_register( &_shader_scene_fxglow );
+   vg_shader_register( &_shader_scene_vertex_blend );
+   vg_shader_register( &_shader_scene_terrain );
+   vg_shader_register( &_shader_scene_route );
+   vg_shader_register( &_shader_scene_depth );
+   vg_shader_register( &_shader_scene_position );
+   vg_shader_register( &_shader_scene_cubemapped );
+   vg_shader_register( &_shader_scene_water );
+   vg_shader_register( &_shader_scene_water_fast );
+   vg_shader_register( &_shader_scene_scoretext );
+   vg_shader_register( &_shader_scene_font );
+   vg_shader_register( &_shader_model_sky );
+   vg_shader_register( &_shader_model_sky_space );
+   vg_shader_register( &_shader_model_menu );
+   vg_shader_register( &_shader_model_character_view );
+   vg_shader_register( &_shader_model_board_view );
+   vg_shader_register( &_shader_model_entity );
+   vg_shader_register( &_shader_model_gate );
+   vg_shader_register( &_shader_model_gate_unlinked );
+   vg_shader_register( &_shader_model_font );
+   vg_shader_register( &_shader_particle );
+   vg_shader_register( &_shader_trail );
+   vg_shader_register( &_shader_blit );
+   vg_shader_register( &_shader_blitblur );
+   vg_shader_register( &_shader_blitcolour );
+   vg_shader_register( &_shader_blit_transition );
+   vg_shader_register( &_shader_routeui );
+}
+
index abbc42f1da28b27af31b9c7c65486479e91b7b0e..42eac9e604b089f3bdbe79e091c87ef51bdc417f 100644 (file)
-#ifndef SHADER_model_board_view_H
-#define SHADER_model_board_view_H
-static void shader_model_board_view_link(void);
-static void shader_model_board_view_register(void);
-static struct vg_shader _shader_model_board_view = {
-   .name = "model_board_view",
-   .link = shader_model_board_view_link,
-   .vs = 
+#pragma once
+#include "vg/vg_engine.h"
+extern struct vg_shader _shader_model_board_view;
+extern GLuint _uniform_model_board_view_uMdl;
+extern GLuint _uniform_model_board_view_uPv;
+extern GLuint _uniform_model_board_view_uPvmPrev;
+extern GLuint _uniform_model_board_view_uTexMain;
+extern GLuint _uniform_model_board_view_uCamera;
+extern GLuint _uniform_model_board_view_g_world_depth;
+extern GLuint _uniform_model_board_view_uLightsArray;
+extern GLuint _uniform_model_board_view_uLightsIndex;
+extern GLuint _uniform_model_board_view_uTexSceneDepth;
+extern GLuint _uniform_model_board_view_uInverseRatioDepth;
+extern GLuint _uniform_model_board_view_uInverseRatioMain;
+extern GLuint _uniform_model_board_view_uDepthCompare;
+static inline void shader_model_board_view_uMdl(m4x3f m)
 {
-.orig_file = "shaders/model.vs",
-.static_src = 
-"layout (location=0) in vec3 a_co;\n"
-"layout (location=1) in vec3 a_norm;\n"
-"layout (location=2) in vec2 a_uv;\n"
-"layout (location=3) in vec4 a_colour;\n"
-"layout (location=4) in vec4 a_weights;\n"
-"layout (location=5) in ivec4 a_groups;\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      9        0 \n"
-"\n"
-"uniform mat4x3 uMdl;\n"
-"uniform mat4 uPv;\n"
-"uniform mat4 uPvmPrev;\n"
-"\n"
-"out vec4 aColour;\n"
-"out vec2 aUv;\n"
-"out vec3 aNorm;\n"
-"out vec3 aCo;\n"
-"out vec3 aWorldCo;\n"
-"\n"
-"void main()\n"
-"{\n"
-"   vec3 world_pos0 = uMdl     * vec4( a_co, 1.0 );\n"
-"   vec4 vproj0     = uPv      * vec4( world_pos0, 1.0 );\n"
-"   vec4 vproj1     = uPvmPrev * vec4( a_co, 1.0 );\n"
-"\n"
-"   vs_motion_out( vproj0, vproj1 );\n"
-"\n"
-"   gl_Position = vproj0;\n"
-"   aWorldCo = world_pos0;\n"
-"   aColour = a_colour;\n"
-"   aUv = a_uv;\n"
-"   aNorm = normalize( mat3(uMdl) * a_norm );\n"
-"   aCo = a_co;\n"
-"}\n"
-""},
-   .fs = 
-{
-.orig_file = "shaders/model_character_view.fs",
-.static_src = 
-"uniform sampler2D uTexMain;\n"
-"uniform vec3 uCamera;\n"
-"\n"
-"in vec4 aColour;\n"
-"in vec2 aUv;\n"
-"in vec3 aNorm;\n"
-"in vec3 aCo;\n"
-"in vec3 aWorldCo;\n"
-"\n"
-"#line       1        1 \n"
-"// :D\n"
-"const float CLEARSKIES_LIGHT_DOT_MIN = 0.0;\n"
-"\n"
-"#line     11        0 \n"
-"#line       1        2 \n"
-"layout (location = 0) out vec4 oColour;\n"
-"\n"
-"// OpenGL wiki: Recommends do not use vec3 because of drivers. hence the v4s...\n"
-"layout (std140) uniform ub_world_lighting\n"
-"{\n"
-"   vec4 g_cube_min;\n"
-"   vec4 g_cube_inv_range;\n"
-"\n"
-"   vec4 g_water_plane;\n"
-"   vec4 g_depth_bounds;\n"
-"\n"
-"   vec4 g_daysky_colour;\n"
-"   vec4 g_nightsky_colour;\n"
-"   vec4 g_sunset_colour;\n"
-"   vec4 g_ambient_colour;\n"
-"   vec4 g_sunset_ambient;\n"
-"   vec4 g_sun_colour;\n"
-"   vec4 g_sun_dir;\n"
-"   vec4 g_board_0;\n"
-"   vec4 g_board_1;\n"
-"\n"
-"   float g_water_fog;\n"
-"   float g_time;\n"
-"   float g_realtime;\n"
-"   float g_shadow_length;\n"
-"   float g_shadow_spread;\n"
-"\n"
-"   float g_time_of_day;\n"
-"   float g_day_phase;\n"
-"   float g_sunset_phase;\n"
-"\n"
-"   int g_light_preview;\n"
-"   int g_shadow_samples;\n"
-"\n"
-"   int g_debug_indices;\n"
-"   int g_debug_complexity;\n"
-"};\n"
-"\n"
-"uniform sampler2D g_world_depth;\n"
-"uniform samplerBuffer uLightsArray;\n"
-"uniform usampler3D uLightsIndex;\n"
-"\n"
-"#line       1        1 \n"
-"//const vec3  DAYSKY_COLOUR   = vec3( 0.37, 0.54, 0.97 );\n"
-"//const vec3  NIGHTSKY_COLOUR = vec3( 0.03, 0.05, 0.20 );\n"
-"//const vec3  SUNSET_COLOUR   = vec3( 1.00, 0.32, 0.01 );\n"
-"//const vec3  AMBIENT_COLOUR  = vec3( 0.13, 0.17, 0.35 );\n"
-"//const vec3  SUNSET_AMBIENT  = vec3( 0.25, 0.17, 0.51 );\n"
-"//const vec3  SUN_COLOUR      = vec3( 1.10, 0.89, 0.35 );\n"
-"\n"
-"const float SUN_ANGLE       = 0.0001;\n"
-"const float PI              = 3.14159265358979323846264;\n"
-"\n"
-"//struct world_info\n"
-"//{\n"
-"//   float time,\n"
-"//         time_of_day,\n"
-"//         day_phase,\n"
-"//         sunset_phase;\n"
-"//   \n"
-"//   vec3 sun_dir;\n"
-"//};\n"
-"\n"
-"vec3 rand33(vec3 p3)\n"
-"{\n"
-"      p3 = fract(p3 * vec3(.1031, .1030, .0973));\n"
-"   p3 += dot(p3, p3.yxz+33.33);\n"
-"   return fract((p3.xxy + p3.yxx)*p3.zyx);\n"
-"}\n"
-"\n"
-"float stars( vec3 rd, float rr, float size ){\n"
-"   vec3 co = rd * rr;\n"
-"\n"
-"   float a = atan(co.y, length(co.xz)) + 4.0 * PI;\n"
-"\n"
-"   float spaces = 1.0 / rr;\n"
-"   size = (rr * 0.0015) * fwidth(a) * 1000.0 * size;\n"
-"   a -= mod(a, spaces) - spaces * 0.5;\n"
-"\n"
-"   float count = floor(sqrt(pow(rr, 2.0) * (1.0 - pow(sin(a), 2.0))) * 3.0);\n"
-"   \n"
-"   float plane = atan(co.z, co.x) + 4.0 * PI;\n"
-"   plane = plane - mod(plane, PI / count);\n"
-"\n"
-"   vec2 delta = rand33(vec3(plane, a, 0.0)).xy;\n"
-"\n"
-"   float level = sin(a + spaces * (delta.y - 0.5) * (1.0 - size)) * rr;\n"
-"   float ydist = sqrt(rr * rr - level * level);\n"
-"   float angle = plane + (PI * (delta.x * (1.0-size) + size * 0.5) / count);\n"
-"   vec3 center = vec3(cos(angle) * ydist, level, sin(angle) * ydist);\n"
-"   float star = smoothstep(size, 0.0, distance(center, co));\n"
-"   return star;\n"
-"}\n"
-"\n"
-"float luminance( vec3 v )\n"
-"{\n"
-"   return dot( v, vec3(0.2126, 0.7152, 0.0722) );\n"
-"}\n"
-"\n"
-"vec3 clearskies_ambient( vec3 dir )\n"
-"{\n"
-"   float sun_azimuth  = g_sunset_phase * (dot( dir.xz, g_sun_dir.xz )*0.4+0.6);\n"
-"   float sky_gradient = dir.y;\n"
-"   \n"
-"   /* Blend phase colours */\n"
-"   vec3 ambient  = g_daysky_colour.rgb   * (g_day_phase-g_sunset_phase*0.1);\n"
-"        ambient += g_sunset_colour.rgb   * (1.0-dir.y*0.5)*sun_azimuth;\n"
-"        ambient += g_nightsky_colour.rgb * (1.0-g_day_phase);\n"
-"   \n"
-"   /* Add gradient */\n"
-"        ambient -= sky_gradient * luminance(ambient);\n"
-"        \n"
-"   return ambient;\n"
-"}\n"
-"\n"
-"vec3 clearskies_sky( vec3 ray_dir )\n"
-"{\n"
-"   ray_dir.y = abs( ray_dir.y );\n"
-"   vec3 sky_colour  = clearskies_ambient( ray_dir );\n"
-"   \n"
-"   /* Sun */\n"
-"   float sun_theta  = dot( ray_dir, g_sun_dir.xyz );\n"
-"   float sun_size   = max( 0.0, sun_theta * 0.5 + 0.5 + SUN_ANGLE );\n"
-"   float sun_shape  = pow( sun_size, 2000.0 );\n"
-"         sun_shape += sun_size * max(g_sun_dir.y,0.0) * 0.5;\n"
-"         \n"
-"   vec3 sun_colour  = mix( vec3(1.0), g_sunset_colour.rgb, g_sunset_phase*0.5 );\n"
-"        sun_colour *= sun_shape;\n"
-"\n"
-"   \n"
-"   float star = 0.0;\n"
-"   float star_blend = 10.0*max(0.0,(1.0-g_day_phase*2.0));\n"
-"\n"
-"   if( star_blend > 0.001 ){\n"
-"      for( float j = 1.0; j <= 4.1; j += 1.0 ){\n"
-"         float m = mix(0.6, 0.9, smoothstep(1.0, 2.0, j));\n"
-"         star += stars( ray_dir, 1.94 * pow( 1.64, j ), m ) * (1.0/pow(4.0, j));\n"
-"      }\n"
-"   }\n"
-"   \n"
-"   vec3 composite   = sky_colour + sun_colour + star*star_blend;\n"
-"   return composite;\n"
-"}\n"
-"\n"
-"vec3 clearskies_lighting( vec3 normal, float shadow, vec3 halfview )\n"
-"{\n"
-"   float fresnel = 1.0 - abs(dot(normal,halfview));\n"
-"\n"
-"   vec3  reflect_colour = mix( g_daysky_colour.rgb, g_sunset_colour.rgb, \n"
-"                               g_sunset_phase );\n"
-"\n"
-"   vec3  sky_reflection = 0.5 * fresnel * reflect_colour;\n"
-"   vec3  light_sun      = max( CLEARSKIES_LIGHT_DOT_MIN, \n"
-"                               dot(normal,g_sun_dir.xyz)*0.75+0.25\n"
-"                           ) * g_sun_colour.rgb * g_day_phase;\n"
-"\n"
-"   float scaled_shadow = max( shadow, 1.0 - max(g_sun_dir.y,0.0) );\n"
-"   vec3 ambient = mix( g_ambient_colour.rgb, g_sunset_ambient.rgb, \n"
-"                       g_sunset_phase );\n"
-"\n"
-"   return ambient + (light_sun + sky_reflection) * shadow;\n"
-"}\n"
-"\n"
-"#line     44        0 \n"
-"\n"
-"float world_depth_sample( vec3 pos )\n"
-"{\n"
-"   vec2 depth_coord = (pos.xz - g_depth_bounds.xy) * g_depth_bounds.zw; \n"
-"   return texture( g_world_depth, depth_coord ).r;\n"
-"}\n"
-"\n"
-"float world_water_depth( vec3 pos )\n"
-"{\n"
-"   float ref_depth = g_water_plane.y*g_water_plane.w;\n"
-"   return world_depth_sample( pos ) - ref_depth;\n"
-"}\n"
-"\n"
-"float shadow_sample( vec3 co ){\n"
-"   float height_sample = world_depth_sample( co );\n"
-"\n"
-"   float fdelta = height_sample - co.y;\n"
-"   return clamp( fdelta, 0.2, 0.4 )-0.2;\n"
-"}\n"
-"\n"
-"float newlight_compute_sun_shadow( vec3 co, vec3 dir ){\n"
-"   if( g_shadow_samples == 0 ){\n"
-"      return 1.0;\n"
-"   }\n"
-"\n"
-"   float fspread = g_shadow_spread;\n"
-"   float flength = g_shadow_length;\n"
-"\n"
-"   float famt = 0.0;\n"
-"   famt += shadow_sample(co+(dir+vec3(-0.56,0.55, 0.30)*fspread)*flength*0.1);\n"
-"   famt += shadow_sample(co+(dir+vec3( 0.80,0.68, 0.34)*fspread)*flength*0.2);\n"
-"   famt += shadow_sample(co+(dir+vec3( 0.78,0.07,-0.06)*fspread)*flength*0.3);\n"
-"   famt += shadow_sample(co+(dir+vec3(-0.59,0.07,-0.42)*fspread)*flength*0.4);\n"
-"\n"
-"   //famt+=shadow_sample(co+(dir+vec3(-0.790,-0.933,-0.875)*fspread)*flength*0.5);\n"
-"   //famt+=shadow_sample(co+(dir+vec3( 0.807,-0.690, 0.472)*fspread)*flength*0.6);\n"
-"   //famt+=shadow_sample(co+(dir+vec3( 0.522,-0.379, 0.350)*fspread)*flength*0.7);\n"
-"   //famt+=shadow_sample(co+(dir+vec3( 0.483, 0.201, 0.306)*fspread)*flength*0.8);\n"
-"\n"
-"   return 1.0 - famt;\n"
-"}\n"
-"\n"
-"float newlight_specular( vec3 wnormal, vec3 dir, vec3 halfview, float exponent )\n"
-"{\n"
-"   vec3 specdir = reflect( -dir, wnormal );\n"
-"   return pow(max(dot( halfview, specdir ), 0.0), exponent);\n"
-"}\n"
-"\n"
-"vec3 scene_apply_fog( vec3 vfrag, vec3 colour, float fdist ){\n"
-"   float dist = pow(fdist*0.0010,0.78);\n"
-"   return mix( vfrag, colour, min( 1.0, dist ) );\n"
-"}\n"
-"\n"
-"vec3 scene_calculate_light( int light_index, \n"
-"                            vec3 halfview, vec3 co, vec3 normal )\n"
-"{\n"
-"   vec4 light_colour = texelFetch( uLightsArray, light_index+0 );\n"
-"   vec4 light_co     = texelFetch( uLightsArray, light_index+1 );\n"
-"   vec4 light_dir    = texelFetch( uLightsArray, light_index+2 );\n"
-"\n"
-"   vec3 light_delta = light_co.xyz-co;\n"
-"   float dist2 = dot(light_delta,light_delta);\n"
-"\n"
-"   light_delta = normalize( light_delta );\n"
-"\n"
-"   float quadratic = dist2*100.0;\n"
-"   float attenuation  = 1.0/( 1.0 + quadratic );\n"
-"         attenuation *= max( dot( light_delta, normal ), 0.0 );\n"
-"\n"
-"   float falloff = max( 0.0, 1.0-(dist2*light_co.w) );\n"
-"\n"
-"   if( light_dir.w < 0.999999 ){\n"
-"      float spot_theta = max( 0.0, dot( light_delta, -light_dir.xyz ) );\n"
-"      falloff *= max( 0.0, (spot_theta - light_dir.w) / (1.0-light_dir.w) );\n"
-"   }\n"
-"\n"
-"   return light_colour.rgb * attenuation * falloff \n"
-"            * step( g_day_phase, light_colour.w );\n"
-"}\n"
-"\n"
-"vec3 scene_calculate_packed_light_patch( uint packed_index, \n"
-"                                         vec3 halfview, vec3 co, vec3 normal )\n"
-"{\n"
-"   uint light_count = packed_index & 0x3u;\n"
-"\n"
-"   vec3 l = vec3(0.0);\n"
-"\n"
-"   if( light_count >= 1u ){\n"
-"      int index_0 = int( ((packed_index >>  2u) & 0x3ffu) * 3u );\n"
-"      int index_1 = int( ((packed_index >> 12u) & 0x3ffu) * 3u );\n"
-"      int index_2 = int( ((packed_index >> 22u) & 0x3ffu) * 3u );\n"
-"\n"
-"      l += scene_calculate_light( index_0, halfview, co, normal );\n"
-"\n"
-"      if( light_count >= 2u ){\n"
-"         l += scene_calculate_light( index_1, halfview, co, normal );\n"
-"\n"
-"         if( light_count >= 3u ){\n"
-"            l += scene_calculate_light( index_2, halfview, co, normal );\n"
-"         }\n"
-"      }\n"
-"   }\n"
-"\n"
-"   return l;\n"
-"}\n"
-"\n"
-"vec3 world_compute_lighting( vec3 diffuse, vec3 normal, vec3 co,\n"
-"                             float light_mask )\n"
-"{\n"
-"   if( g_light_preview == 1 )\n"
-"      diffuse = vec3(0.75);\n"
-"\n"
-"   // Lighting\n"
-"   vec3 halfview = uCamera - co;\n"
-"   float fdist = length(halfview);\n"
-"   halfview /= fdist;\n"
-"\n"
-"   float world_shadow = newlight_compute_sun_shadow( \n"
-"               co, g_sun_dir.xyz * (1.0/(max(g_sun_dir.y,0.0)+0.2)) );\n"
-"\n"
-"   vec3 total_light = clearskies_lighting( \n"
-"                           normal, min( light_mask, world_shadow ), halfview );\n"
-"\n"
-"   vec3 cube_coord = (co - g_cube_min.xyz) * g_cube_inv_range.xyz;\n"
-"        cube_coord = floor( cube_coord );\n"
-"\n"
-"   if( g_debug_indices == 1 )\n"
-"   {\n"
-"      return rand33(cube_coord);\n"
-"   }\n"
-"\n"
-"   if( g_debug_complexity == 1 )\n"
-"   {\n"
-"      ivec3 coord = ivec3( cube_coord );\n"
-"      uvec4 index_sample = texelFetch( uLightsIndex, coord, 0 );\n"
-"\n"
-"      uint light_count = (index_sample.x & 0x3u) + (index_sample.y & 0x3u);\n"
-"      return vec3( float(light_count)*(1.0/6.0), 0.0, 0.5 );\n"
-"   }\n"
-"\n"
-"   // FIXME: this coord should absolutely must be clamped!\n"
-"   \n"
-"   ivec3 coord = ivec3( cube_coord );\n"
-"   uvec4 index_sample = texelFetch( uLightsIndex, coord, 0 );\n"
-"\n"
-"   total_light += \n"
-"      scene_calculate_packed_light_patch( index_sample.x,\n"
-"                                          halfview, co, normal ) \n"
-"                                          * light_mask;\n"
-"   total_light += \n"
-"      scene_calculate_packed_light_patch( index_sample.y,\n"
-"                                          halfview, co, normal )\n"
-"                                          * light_mask;\n"
-"\n"
-"   // Take a section of the sky function to give us a matching fog colour\n"
-"\n"
-"   vec3 fog_colour  = clearskies_ambient( -halfview );\n"
-"   float sun_theta  = dot( -halfview, g_sun_dir.xyz );\n"
-"   float sun_size   = max( 0.0, sun_theta * 0.5 + 0.5 );\n"
-"   float sun_shape  = sun_size * max(g_sun_dir.y,0.0) * 0.5;\n"
-"         \n"
-"   vec3 sun_colour  = mix( vec3(1.0), g_sunset_colour.rgb, g_sunset_phase*0.5 );\n"
-"        sun_colour *= sun_shape;\n"
-"\n"
-"   fog_colour += sun_colour;\n"
-"   return scene_apply_fog( diffuse * total_light, fog_colour, fdist );\n"
-"}\n"
-"\n"
-"#line     12        0 \n"
-"#line       1        3 \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     13        0 \n"
-"#line       1        4 \n"
-"uniform sampler2D uTexSceneDepth;\n"
-"uniform vec3 uInverseRatioDepth;\n"
-"uniform vec3 uInverseRatioMain;\n"
-"uniform bool uDepthCompare;\n"
-"\n"
-"float linear_depth( float depth, float near, float far ) {\n"
-"   float z = depth * 2.0 - 1.0;\n"
-"   return (2.0 * near * far) / (far + near - z * (far - near));       \n"
-"}\n"
-"\n"
-"void depth_compare_dither(){\n"
-"   if( uDepthCompare ){\n"
-"      vec2 back_coord = gl_FragCoord.xy * uInverseRatioMain.xy \n"
-"                                        * uInverseRatioDepth.xy;\n"
-"      float back_depth = texture( uTexSceneDepth, back_coord ).r;\n"
-"      float front_depth = gl_FragCoord.z/gl_FragCoord.w;\n"
-"\n"
-"      back_depth = linear_depth( back_depth, 0.1, 2100.0 );\n"
-"      float diff = back_depth - front_depth;\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( step(0.0,diff)+dither<0.3 )\n"
-"         discard;\n"
-"   }\n"
-"}\n"
-"\n"
-"#line     14        0 \n"
-"\n"
-"vec3 character_clearskies_lighting( vec3 normal, float shadow, vec3 halfview )\n"
-"{\n"
-"   float fresnel = 1.0 - abs(dot(normal,halfview));\n"
-"\n"
-"   vec3  reflect_colour = mix( g_daysky_colour.rgb, g_sunset_colour.rgb, \n"
-"                               g_sunset_phase );\n"
-"\n"
-"\n"
-"   vec3  sky_reflection = 0.5 * fresnel * reflect_colour;\n"
-"   vec3  light_sun      = max(0.0, dot(normal,g_sun_dir.xyz)*0.5+0.5) \n"
-"                           * g_sun_colour.rgb * g_day_phase;\n"
-"\n"
-"   float scaled_shadow = max( shadow, 1.0 - max(g_sun_dir.y,0.0) );\n"
-"   vec3 ambient = mix( g_ambient_colour.rgb, g_sunset_ambient.rgb, \n"
-"                       g_sunset_phase );\n"
-"\n"
-"   return ambient + (light_sun + sky_reflection) * shadow;\n"
-"}\n"
-"\n"
-"vec3 character_compute_lighting( vec3 diffuse, vec3 normal, vec3 co,\n"
-"                                 float light_mask )\n"
-"{\n"
-"   if( g_light_preview == 1 )\n"
-"      diffuse = vec3(0.75);\n"
-"\n"
-"   // Lighting\n"
-"   vec3 halfview = uCamera - co;\n"
-"   float fdist = length(halfview);\n"
-"   halfview /= fdist;\n"
-"\n"
-"   float world_shadow = newlight_compute_sun_shadow( \n"
-"               co, g_sun_dir.xyz * (1.0/(max(g_sun_dir.y,0.0)+0.2)) );\n"
-"\n"
-"   vec3 total_light = character_clearskies_lighting( \n"
-"                           normal, min( light_mask, world_shadow ), halfview );\n"
-"\n"
-"   vec3 cube_coord = (co - g_cube_min.xyz) * g_cube_inv_range.xyz;\n"
-"        cube_coord = floor( cube_coord );\n"
-"\n"
-"   if( g_debug_indices == 1 )\n"
-"   {\n"
-"      return rand33(cube_coord);\n"
-"   }\n"
-"\n"
-"   if( g_debug_complexity == 1 )\n"
-"   {\n"
-"      ivec3 coord = ivec3( cube_coord );\n"
-"      uvec4 index_sample = texelFetch( uLightsIndex, coord, 0 );\n"
-"\n"
-"      uint light_count = (index_sample.x & 0x3u) + (index_sample.y & 0x3u);\n"
-"      return vec3( float(light_count)*(1.0/6.0), 0.0, 0.5 );\n"
-"   }\n"
-"\n"
-"   // FIXME: this coord should absolutely must be clamped!\n"
-"   \n"
-"   ivec3 coord = ivec3( cube_coord );\n"
-"   uvec4 index_sample = texelFetch( uLightsIndex, coord, 0 );\n"
-"\n"
-"   total_light += \n"
-"      scene_calculate_packed_light_patch( index_sample.x,\n"
-"                                          halfview, co, normal ) \n"
-"                                          * light_mask;\n"
-"   total_light += \n"
-"      scene_calculate_packed_light_patch( index_sample.y,\n"
-"                                          halfview, co, normal )\n"
-"                                          * light_mask;\n"
-"\n"
-"   // Take a section of the sky function to give us a matching fog colour\n"
-"\n"
-"   vec3 fog_colour  = clearskies_ambient( -halfview );\n"
-"   float sun_theta  = dot( -halfview, g_sun_dir.xyz );\n"
-"   float sun_size   = max( 0.0, sun_theta * 0.5 + 0.5 );\n"
-"   float sun_shape  = sun_size * max(g_sun_dir.y,0.0) * 0.5;\n"
-"         \n"
-"   vec3 sun_colour  = mix( vec3(1.0), g_sunset_colour.rgb, g_sunset_phase*0.5 );\n"
-"        sun_colour *= sun_shape;\n"
-"\n"
-"   fog_colour += sun_colour;\n"
-"   return scene_apply_fog( diffuse * total_light, fog_colour, fdist );\n"
-"}\n"
-"\n"
-"void main(){\n"
-"   depth_compare_dither();\n"
-"   compute_motion_vectors();\n"
-"\n"
-"   vec3 qnorm     = aNorm;\n"
-"   vec3 diffuse   = texture( uTexMain, aUv ).rgb;\n"
-"   vec3 composite = character_compute_lighting( diffuse, qnorm, aWorldCo, 1.0 );\n"
-"\n"
-"   float dist    = distance( aWorldCo, uCamera ) - 0.08;\n"
-"   float opacity = clamp( dist*dist, 0.0, 1.0 );\n"
-"\n"
-"   oColour = vec4( composite, opacity );\n"
-"}\n"
-""},
-};
-
-static GLuint _uniform_model_board_view_uMdl;
-static GLuint _uniform_model_board_view_uPv;
-static GLuint _uniform_model_board_view_uPvmPrev;
-static GLuint _uniform_model_board_view_uTexMain;
-static GLuint _uniform_model_board_view_uCamera;
-static GLuint _uniform_model_board_view_g_world_depth;
-static GLuint _uniform_model_board_view_uLightsArray;
-static GLuint _uniform_model_board_view_uLightsIndex;
-static GLuint _uniform_model_board_view_uTexSceneDepth;
-static GLuint _uniform_model_board_view_uInverseRatioDepth;
-static GLuint _uniform_model_board_view_uInverseRatioMain;
-static GLuint _uniform_model_board_view_uDepthCompare;
-static void shader_model_board_view_uMdl(m4x3f m){
-   glUniformMatrix4x3fv(_uniform_model_board_view_uMdl,1,GL_FALSE,(float*)m);
+   glUniformMatrix4x3fv(_uniform_model_board_view_uMdl,1,GL_FALSE,(f32*)m);
 }
-static void shader_model_board_view_uPv(m4x4f m){
-   glUniformMatrix4fv(_uniform_model_board_view_uPv,1,GL_FALSE,(float*)m);
+static inline void shader_model_board_view_uPv(m4x4f m)
+{
+   glUniformMatrix4fv(_uniform_model_board_view_uPv,1,GL_FALSE,(f32*)m);
 }
-static void shader_model_board_view_uPvmPrev(m4x4f m){
-   glUniformMatrix4fv(_uniform_model_board_view_uPvmPrev,1,GL_FALSE,(float*)m);
+static inline void shader_model_board_view_uPvmPrev(m4x4f m)
+{
+   glUniformMatrix4fv(_uniform_model_board_view_uPvmPrev,1,GL_FALSE,(f32*)m);
 }
-static void shader_model_board_view_uTexMain(int i){
+static inline void shader_model_board_view_uTexMain(int i)
+{
    glUniform1i(_uniform_model_board_view_uTexMain,i);
 }
-static void shader_model_board_view_uCamera(v3f v){
+static inline void shader_model_board_view_uCamera(v3f v)
+{
    glUniform3fv(_uniform_model_board_view_uCamera,1,v);
 }
-static void shader_model_board_view_g_world_depth(int i){
+static inline void shader_model_board_view_g_world_depth(int i)
+{
    glUniform1i(_uniform_model_board_view_g_world_depth,i);
 }
-static void shader_model_board_view_uTexSceneDepth(int i){
+static inline void shader_model_board_view_uTexSceneDepth(int i)
+{
    glUniform1i(_uniform_model_board_view_uTexSceneDepth,i);
 }
-static void shader_model_board_view_uInverseRatioDepth(v3f v){
+static inline void shader_model_board_view_uInverseRatioDepth(v3f v)
+{
    glUniform3fv(_uniform_model_board_view_uInverseRatioDepth,1,v);
 }
-static void shader_model_board_view_uInverseRatioMain(v3f v){
+static inline void shader_model_board_view_uInverseRatioMain(v3f v)
+{
    glUniform3fv(_uniform_model_board_view_uInverseRatioMain,1,v);
 }
-static void shader_model_board_view_uDepthCompare(int b){
+static inline void shader_model_board_view_uDepthCompare(int b)
+{
    glUniform1i(_uniform_model_board_view_uDepthCompare,b);
 }
-static void shader_model_board_view_register(void){
-   vg_shader_register( &_shader_model_board_view );
-}
-static void shader_model_board_view_use(void){ glUseProgram(_shader_model_board_view.id); }
-static void shader_model_board_view_link(void){
-   _uniform_model_board_view_uMdl = glGetUniformLocation( _shader_model_board_view.id, "uMdl" );
-   _uniform_model_board_view_uPv = glGetUniformLocation( _shader_model_board_view.id, "uPv" );
-   _uniform_model_board_view_uPvmPrev = glGetUniformLocation( _shader_model_board_view.id, "uPvmPrev" );
-   _uniform_model_board_view_uTexMain = glGetUniformLocation( _shader_model_board_view.id, "uTexMain" );
-   _uniform_model_board_view_uCamera = glGetUniformLocation( _shader_model_board_view.id, "uCamera" );
-   _uniform_model_board_view_g_world_depth = glGetUniformLocation( _shader_model_board_view.id, "g_world_depth" );
-   _uniform_model_board_view_uLightsArray = glGetUniformLocation( _shader_model_board_view.id, "uLightsArray" );
-   _uniform_model_board_view_uLightsIndex = glGetUniformLocation( _shader_model_board_view.id, "uLightsIndex" );
-   _uniform_model_board_view_uTexSceneDepth = glGetUniformLocation( _shader_model_board_view.id, "uTexSceneDepth" );
-   _uniform_model_board_view_uInverseRatioDepth = glGetUniformLocation( _shader_model_board_view.id, "uInverseRatioDepth" );
-   _uniform_model_board_view_uInverseRatioMain = glGetUniformLocation( _shader_model_board_view.id, "uInverseRatioMain" );
-   _uniform_model_board_view_uDepthCompare = glGetUniformLocation( _shader_model_board_view.id, "uDepthCompare" );
+static inline void shader_model_board_view_use(void);
+static inline void shader_model_board_view_use(void)
+{
+   glUseProgram(_shader_model_board_view.id);
 }
-#endif /* SHADER_model_board_view_H */
index 2af1bfe9d22eb4d2f0718fe070aba77b46880604..9489520c51b8f1fc33e33cd257742570ce395e7a 100644 (file)
-#ifndef SHADER_model_character_view_H
-#define SHADER_model_character_view_H
-static void shader_model_character_view_link(void);
-static void shader_model_character_view_register(void);
-static struct vg_shader _shader_model_character_view = {
-   .name = "model_character_view",
-   .link = shader_model_character_view_link,
-   .vs = 
+#pragma once
+#include "vg/vg_engine.h"
+extern struct vg_shader _shader_model_character_view;
+extern GLuint _uniform_model_character_view_uPv;
+extern GLuint _uniform_model_character_view_uTransforms;
+extern GLuint _uniform_model_character_view_uTexMain;
+extern GLuint _uniform_model_character_view_uCamera;
+extern GLuint _uniform_model_character_view_g_world_depth;
+extern GLuint _uniform_model_character_view_uLightsArray;
+extern GLuint _uniform_model_character_view_uLightsIndex;
+extern GLuint _uniform_model_character_view_uTexSceneDepth;
+extern GLuint _uniform_model_character_view_uInverseRatioDepth;
+extern GLuint _uniform_model_character_view_uInverseRatioMain;
+extern GLuint _uniform_model_character_view_uDepthCompare;
+static inline void shader_model_character_view_uPv(m4x4f m)
 {
-.orig_file = "shaders/model_skinned.vs",
-.static_src = 
-"layout (location=0) in vec3 a_co;\n"
-"layout (location=1) in vec3 a_norm;\n"
-"layout (location=2) in vec2 a_uv;\n"
-"layout (location=3) in vec4 a_colour;\n"
-"layout (location=4) in vec4 a_weights;\n"
-"layout (location=5) in ivec4 a_groups;\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      9        0 \n"
-"\n"
-"uniform mat4 uPv;\n"
-"uniform mat4x3 uTransforms[32];\n"
-"\n"
-"out vec4 aColour;\n"
-"out vec2 aUv;\n"
-"out vec3 aNorm;\n"
-"out vec3 aCo;\n"
-"out vec3 aWorldCo;\n"
-"\n"
-"void main()\n"
-"{\n"
-"   vec4 co_local = vec4( a_co, 1.0 );\n"
-"   vec3 co0 = uTransforms[ a_groups[0] ] * co_local;\n"
-"   vec3 co1 = uTransforms[ a_groups[1] ] * co_local;\n"
-"   vec3 co2 = uTransforms[ a_groups[2] ] * co_local;\n"
-"   vec3 n0  = mat3(uTransforms[ a_groups[0] ]) * a_norm;\n"
-"   vec3 n1  = mat3(uTransforms[ a_groups[1] ]) * a_norm;\n"
-"   vec3 n2  = mat3(uTransforms[ a_groups[2] ]) * a_norm;\n"
-"\n"
-"   vec3 world_pos    = co0*a_weights[0] + co1*a_weights[1] + co2*a_weights[2];\n"
-"   vec3 world_normal = n0*a_weights[0]  + n1*a_weights[1]  + n2*a_weights[2];\n"
-"   \n"
-"   gl_Position = uPv * vec4( world_pos, 1.0 );\n"
-"   aColour = a_colour;\n"
-"   aUv = a_uv;\n"
-"   aNorm = world_normal;\n"
-"   aCo = a_co;\n"
-"   aWorldCo = world_pos;\n"
-"\n"
-"   // TODO: motion vectors\n"
-"   aMotionVec0 = vec3(1.0);\n"
-"   aMotionVec1 = vec3(1.0);\n"
-"}\n"
-""},
-   .fs = 
-{
-.orig_file = "shaders/model_character_view.fs",
-.static_src = 
-"uniform sampler2D uTexMain;\n"
-"uniform vec3 uCamera;\n"
-"\n"
-"in vec4 aColour;\n"
-"in vec2 aUv;\n"
-"in vec3 aNorm;\n"
-"in vec3 aCo;\n"
-"in vec3 aWorldCo;\n"
-"\n"
-"#line       1        1 \n"
-"// :D\n"
-"const float CLEARSKIES_LIGHT_DOT_MIN = 0.0;\n"
-"\n"
-"#line     11        0 \n"
-"#line       1        2 \n"
-"layout (location = 0) out vec4 oColour;\n"
-"\n"
-"// OpenGL wiki: Recommends do not use vec3 because of drivers. hence the v4s...\n"
-"layout (std140) uniform ub_world_lighting\n"
-"{\n"
-"   vec4 g_cube_min;\n"
-"   vec4 g_cube_inv_range;\n"
-"\n"
-"   vec4 g_water_plane;\n"
-"   vec4 g_depth_bounds;\n"
-"\n"
-"   vec4 g_daysky_colour;\n"
-"   vec4 g_nightsky_colour;\n"
-"   vec4 g_sunset_colour;\n"
-"   vec4 g_ambient_colour;\n"
-"   vec4 g_sunset_ambient;\n"
-"   vec4 g_sun_colour;\n"
-"   vec4 g_sun_dir;\n"
-"   vec4 g_board_0;\n"
-"   vec4 g_board_1;\n"
-"\n"
-"   float g_water_fog;\n"
-"   float g_time;\n"
-"   float g_realtime;\n"
-"   float g_shadow_length;\n"
-"   float g_shadow_spread;\n"
-"\n"
-"   float g_time_of_day;\n"
-"   float g_day_phase;\n"
-"   float g_sunset_phase;\n"
-"\n"
-"   int g_light_preview;\n"
-"   int g_shadow_samples;\n"
-"\n"
-"   int g_debug_indices;\n"
-"   int g_debug_complexity;\n"
-"};\n"
-"\n"
-"uniform sampler2D g_world_depth;\n"
-"uniform samplerBuffer uLightsArray;\n"
-"uniform usampler3D uLightsIndex;\n"
-"\n"
-"#line       1        1 \n"
-"//const vec3  DAYSKY_COLOUR   = vec3( 0.37, 0.54, 0.97 );\n"
-"//const vec3  NIGHTSKY_COLOUR = vec3( 0.03, 0.05, 0.20 );\n"
-"//const vec3  SUNSET_COLOUR   = vec3( 1.00, 0.32, 0.01 );\n"
-"//const vec3  AMBIENT_COLOUR  = vec3( 0.13, 0.17, 0.35 );\n"
-"//const vec3  SUNSET_AMBIENT  = vec3( 0.25, 0.17, 0.51 );\n"
-"//const vec3  SUN_COLOUR      = vec3( 1.10, 0.89, 0.35 );\n"
-"\n"
-"const float SUN_ANGLE       = 0.0001;\n"
-"const float PI              = 3.14159265358979323846264;\n"
-"\n"
-"//struct world_info\n"
-"//{\n"
-"//   float time,\n"
-"//         time_of_day,\n"
-"//         day_phase,\n"
-"//         sunset_phase;\n"
-"//   \n"
-"//   vec3 sun_dir;\n"
-"//};\n"
-"\n"
-"vec3 rand33(vec3 p3)\n"
-"{\n"
-"      p3 = fract(p3 * vec3(.1031, .1030, .0973));\n"
-"   p3 += dot(p3, p3.yxz+33.33);\n"
-"   return fract((p3.xxy + p3.yxx)*p3.zyx);\n"
-"}\n"
-"\n"
-"float stars( vec3 rd, float rr, float size ){\n"
-"   vec3 co = rd * rr;\n"
-"\n"
-"   float a = atan(co.y, length(co.xz)) + 4.0 * PI;\n"
-"\n"
-"   float spaces = 1.0 / rr;\n"
-"   size = (rr * 0.0015) * fwidth(a) * 1000.0 * size;\n"
-"   a -= mod(a, spaces) - spaces * 0.5;\n"
-"\n"
-"   float count = floor(sqrt(pow(rr, 2.0) * (1.0 - pow(sin(a), 2.0))) * 3.0);\n"
-"   \n"
-"   float plane = atan(co.z, co.x) + 4.0 * PI;\n"
-"   plane = plane - mod(plane, PI / count);\n"
-"\n"
-"   vec2 delta = rand33(vec3(plane, a, 0.0)).xy;\n"
-"\n"
-"   float level = sin(a + spaces * (delta.y - 0.5) * (1.0 - size)) * rr;\n"
-"   float ydist = sqrt(rr * rr - level * level);\n"
-"   float angle = plane + (PI * (delta.x * (1.0-size) + size * 0.5) / count);\n"
-"   vec3 center = vec3(cos(angle) * ydist, level, sin(angle) * ydist);\n"
-"   float star = smoothstep(size, 0.0, distance(center, co));\n"
-"   return star;\n"
-"}\n"
-"\n"
-"float luminance( vec3 v )\n"
-"{\n"
-"   return dot( v, vec3(0.2126, 0.7152, 0.0722) );\n"
-"}\n"
-"\n"
-"vec3 clearskies_ambient( vec3 dir )\n"
-"{\n"
-"   float sun_azimuth  = g_sunset_phase * (dot( dir.xz, g_sun_dir.xz )*0.4+0.6);\n"
-"   float sky_gradient = dir.y;\n"
-"   \n"
-"   /* Blend phase colours */\n"
-"   vec3 ambient  = g_daysky_colour.rgb   * (g_day_phase-g_sunset_phase*0.1);\n"
-"        ambient += g_sunset_colour.rgb   * (1.0-dir.y*0.5)*sun_azimuth;\n"
-"        ambient += g_nightsky_colour.rgb * (1.0-g_day_phase);\n"
-"   \n"
-"   /* Add gradient */\n"
-"        ambient -= sky_gradient * luminance(ambient);\n"
-"        \n"
-"   return ambient;\n"
-"}\n"
-"\n"
-"vec3 clearskies_sky( vec3 ray_dir )\n"
-"{\n"
-"   ray_dir.y = abs( ray_dir.y );\n"
-"   vec3 sky_colour  = clearskies_ambient( ray_dir );\n"
-"   \n"
-"   /* Sun */\n"
-"   float sun_theta  = dot( ray_dir, g_sun_dir.xyz );\n"
-"   float sun_size   = max( 0.0, sun_theta * 0.5 + 0.5 + SUN_ANGLE );\n"
-"   float sun_shape  = pow( sun_size, 2000.0 );\n"
-"         sun_shape += sun_size * max(g_sun_dir.y,0.0) * 0.5;\n"
-"         \n"
-"   vec3 sun_colour  = mix( vec3(1.0), g_sunset_colour.rgb, g_sunset_phase*0.5 );\n"
-"        sun_colour *= sun_shape;\n"
-"\n"
-"   \n"
-"   float star = 0.0;\n"
-"   float star_blend = 10.0*max(0.0,(1.0-g_day_phase*2.0));\n"
-"\n"
-"   if( star_blend > 0.001 ){\n"
-"      for( float j = 1.0; j <= 4.1; j += 1.0 ){\n"
-"         float m = mix(0.6, 0.9, smoothstep(1.0, 2.0, j));\n"
-"         star += stars( ray_dir, 1.94 * pow( 1.64, j ), m ) * (1.0/pow(4.0, j));\n"
-"      }\n"
-"   }\n"
-"   \n"
-"   vec3 composite   = sky_colour + sun_colour + star*star_blend;\n"
-"   return composite;\n"
-"}\n"
-"\n"
-"vec3 clearskies_lighting( vec3 normal, float shadow, vec3 halfview )\n"
-"{\n"
-"   float fresnel = 1.0 - abs(dot(normal,halfview));\n"
-"\n"
-"   vec3  reflect_colour = mix( g_daysky_colour.rgb, g_sunset_colour.rgb, \n"
-"                               g_sunset_phase );\n"
-"\n"
-"   vec3  sky_reflection = 0.5 * fresnel * reflect_colour;\n"
-"   vec3  light_sun      = max( CLEARSKIES_LIGHT_DOT_MIN, \n"
-"                               dot(normal,g_sun_dir.xyz)*0.75+0.25\n"
-"                           ) * g_sun_colour.rgb * g_day_phase;\n"
-"\n"
-"   float scaled_shadow = max( shadow, 1.0 - max(g_sun_dir.y,0.0) );\n"
-"   vec3 ambient = mix( g_ambient_colour.rgb, g_sunset_ambient.rgb, \n"
-"                       g_sunset_phase );\n"
-"\n"
-"   return ambient + (light_sun + sky_reflection) * shadow;\n"
-"}\n"
-"\n"
-"#line     44        0 \n"
-"\n"
-"float world_depth_sample( vec3 pos )\n"
-"{\n"
-"   vec2 depth_coord = (pos.xz - g_depth_bounds.xy) * g_depth_bounds.zw; \n"
-"   return texture( g_world_depth, depth_coord ).r;\n"
-"}\n"
-"\n"
-"float world_water_depth( vec3 pos )\n"
-"{\n"
-"   float ref_depth = g_water_plane.y*g_water_plane.w;\n"
-"   return world_depth_sample( pos ) - ref_depth;\n"
-"}\n"
-"\n"
-"float shadow_sample( vec3 co ){\n"
-"   float height_sample = world_depth_sample( co );\n"
-"\n"
-"   float fdelta = height_sample - co.y;\n"
-"   return clamp( fdelta, 0.2, 0.4 )-0.2;\n"
-"}\n"
-"\n"
-"float newlight_compute_sun_shadow( vec3 co, vec3 dir ){\n"
-"   if( g_shadow_samples == 0 ){\n"
-"      return 1.0;\n"
-"   }\n"
-"\n"
-"   float fspread = g_shadow_spread;\n"
-"   float flength = g_shadow_length;\n"
-"\n"
-"   float famt = 0.0;\n"
-"   famt += shadow_sample(co+(dir+vec3(-0.56,0.55, 0.30)*fspread)*flength*0.1);\n"
-"   famt += shadow_sample(co+(dir+vec3( 0.80,0.68, 0.34)*fspread)*flength*0.2);\n"
-"   famt += shadow_sample(co+(dir+vec3( 0.78,0.07,-0.06)*fspread)*flength*0.3);\n"
-"   famt += shadow_sample(co+(dir+vec3(-0.59,0.07,-0.42)*fspread)*flength*0.4);\n"
-"\n"
-"   //famt+=shadow_sample(co+(dir+vec3(-0.790,-0.933,-0.875)*fspread)*flength*0.5);\n"
-"   //famt+=shadow_sample(co+(dir+vec3( 0.807,-0.690, 0.472)*fspread)*flength*0.6);\n"
-"   //famt+=shadow_sample(co+(dir+vec3( 0.522,-0.379, 0.350)*fspread)*flength*0.7);\n"
-"   //famt+=shadow_sample(co+(dir+vec3( 0.483, 0.201, 0.306)*fspread)*flength*0.8);\n"
-"\n"
-"   return 1.0 - famt;\n"
-"}\n"
-"\n"
-"float newlight_specular( vec3 wnormal, vec3 dir, vec3 halfview, float exponent )\n"
-"{\n"
-"   vec3 specdir = reflect( -dir, wnormal );\n"
-"   return pow(max(dot( halfview, specdir ), 0.0), exponent);\n"
-"}\n"
-"\n"
-"vec3 scene_apply_fog( vec3 vfrag, vec3 colour, float fdist ){\n"
-"   float dist = pow(fdist*0.0010,0.78);\n"
-"   return mix( vfrag, colour, min( 1.0, dist ) );\n"
-"}\n"
-"\n"
-"vec3 scene_calculate_light( int light_index, \n"
-"                            vec3 halfview, vec3 co, vec3 normal )\n"
-"{\n"
-"   vec4 light_colour = texelFetch( uLightsArray, light_index+0 );\n"
-"   vec4 light_co     = texelFetch( uLightsArray, light_index+1 );\n"
-"   vec4 light_dir    = texelFetch( uLightsArray, light_index+2 );\n"
-"\n"
-"   vec3 light_delta = light_co.xyz-co;\n"
-"   float dist2 = dot(light_delta,light_delta);\n"
-"\n"
-"   light_delta = normalize( light_delta );\n"
-"\n"
-"   float quadratic = dist2*100.0;\n"
-"   float attenuation  = 1.0/( 1.0 + quadratic );\n"
-"         attenuation *= max( dot( light_delta, normal ), 0.0 );\n"
-"\n"
-"   float falloff = max( 0.0, 1.0-(dist2*light_co.w) );\n"
-"\n"
-"   if( light_dir.w < 0.999999 ){\n"
-"      float spot_theta = max( 0.0, dot( light_delta, -light_dir.xyz ) );\n"
-"      falloff *= max( 0.0, (spot_theta - light_dir.w) / (1.0-light_dir.w) );\n"
-"   }\n"
-"\n"
-"   return light_colour.rgb * attenuation * falloff \n"
-"            * step( g_day_phase, light_colour.w );\n"
-"}\n"
-"\n"
-"vec3 scene_calculate_packed_light_patch( uint packed_index, \n"
-"                                         vec3 halfview, vec3 co, vec3 normal )\n"
-"{\n"
-"   uint light_count = packed_index & 0x3u;\n"
-"\n"
-"   vec3 l = vec3(0.0);\n"
-"\n"
-"   if( light_count >= 1u ){\n"
-"      int index_0 = int( ((packed_index >>  2u) & 0x3ffu) * 3u );\n"
-"      int index_1 = int( ((packed_index >> 12u) & 0x3ffu) * 3u );\n"
-"      int index_2 = int( ((packed_index >> 22u) & 0x3ffu) * 3u );\n"
-"\n"
-"      l += scene_calculate_light( index_0, halfview, co, normal );\n"
-"\n"
-"      if( light_count >= 2u ){\n"
-"         l += scene_calculate_light( index_1, halfview, co, normal );\n"
-"\n"
-"         if( light_count >= 3u ){\n"
-"            l += scene_calculate_light( index_2, halfview, co, normal );\n"
-"         }\n"
-"      }\n"
-"   }\n"
-"\n"
-"   return l;\n"
-"}\n"
-"\n"
-"vec3 world_compute_lighting( vec3 diffuse, vec3 normal, vec3 co,\n"
-"                             float light_mask )\n"
-"{\n"
-"   if( g_light_preview == 1 )\n"
-"      diffuse = vec3(0.75);\n"
-"\n"
-"   // Lighting\n"
-"   vec3 halfview = uCamera - co;\n"
-"   float fdist = length(halfview);\n"
-"   halfview /= fdist;\n"
-"\n"
-"   float world_shadow = newlight_compute_sun_shadow( \n"
-"               co, g_sun_dir.xyz * (1.0/(max(g_sun_dir.y,0.0)+0.2)) );\n"
-"\n"
-"   vec3 total_light = clearskies_lighting( \n"
-"                           normal, min( light_mask, world_shadow ), halfview );\n"
-"\n"
-"   vec3 cube_coord = (co - g_cube_min.xyz) * g_cube_inv_range.xyz;\n"
-"        cube_coord = floor( cube_coord );\n"
-"\n"
-"   if( g_debug_indices == 1 )\n"
-"   {\n"
-"      return rand33(cube_coord);\n"
-"   }\n"
-"\n"
-"   if( g_debug_complexity == 1 )\n"
-"   {\n"
-"      ivec3 coord = ivec3( cube_coord );\n"
-"      uvec4 index_sample = texelFetch( uLightsIndex, coord, 0 );\n"
-"\n"
-"      uint light_count = (index_sample.x & 0x3u) + (index_sample.y & 0x3u);\n"
-"      return vec3( float(light_count)*(1.0/6.0), 0.0, 0.5 );\n"
-"   }\n"
-"\n"
-"   // FIXME: this coord should absolutely must be clamped!\n"
-"   \n"
-"   ivec3 coord = ivec3( cube_coord );\n"
-"   uvec4 index_sample = texelFetch( uLightsIndex, coord, 0 );\n"
-"\n"
-"   total_light += \n"
-"      scene_calculate_packed_light_patch( index_sample.x,\n"
-"                                          halfview, co, normal ) \n"
-"                                          * light_mask;\n"
-"   total_light += \n"
-"      scene_calculate_packed_light_patch( index_sample.y,\n"
-"                                          halfview, co, normal )\n"
-"                                          * light_mask;\n"
-"\n"
-"   // Take a section of the sky function to give us a matching fog colour\n"
-"\n"
-"   vec3 fog_colour  = clearskies_ambient( -halfview );\n"
-"   float sun_theta  = dot( -halfview, g_sun_dir.xyz );\n"
-"   float sun_size   = max( 0.0, sun_theta * 0.5 + 0.5 );\n"
-"   float sun_shape  = sun_size * max(g_sun_dir.y,0.0) * 0.5;\n"
-"         \n"
-"   vec3 sun_colour  = mix( vec3(1.0), g_sunset_colour.rgb, g_sunset_phase*0.5 );\n"
-"        sun_colour *= sun_shape;\n"
-"\n"
-"   fog_colour += sun_colour;\n"
-"   return scene_apply_fog( diffuse * total_light, fog_colour, fdist );\n"
-"}\n"
-"\n"
-"#line     12        0 \n"
-"#line       1        3 \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     13        0 \n"
-"#line       1        4 \n"
-"uniform sampler2D uTexSceneDepth;\n"
-"uniform vec3 uInverseRatioDepth;\n"
-"uniform vec3 uInverseRatioMain;\n"
-"uniform bool uDepthCompare;\n"
-"\n"
-"float linear_depth( float depth, float near, float far ) {\n"
-"   float z = depth * 2.0 - 1.0;\n"
-"   return (2.0 * near * far) / (far + near - z * (far - near));       \n"
-"}\n"
-"\n"
-"void depth_compare_dither(){\n"
-"   if( uDepthCompare ){\n"
-"      vec2 back_coord = gl_FragCoord.xy * uInverseRatioMain.xy \n"
-"                                        * uInverseRatioDepth.xy;\n"
-"      float back_depth = texture( uTexSceneDepth, back_coord ).r;\n"
-"      float front_depth = gl_FragCoord.z/gl_FragCoord.w;\n"
-"\n"
-"      back_depth = linear_depth( back_depth, 0.1, 2100.0 );\n"
-"      float diff = back_depth - front_depth;\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( step(0.0,diff)+dither<0.3 )\n"
-"         discard;\n"
-"   }\n"
-"}\n"
-"\n"
-"#line     14        0 \n"
-"\n"
-"vec3 character_clearskies_lighting( vec3 normal, float shadow, vec3 halfview )\n"
-"{\n"
-"   float fresnel = 1.0 - abs(dot(normal,halfview));\n"
-"\n"
-"   vec3  reflect_colour = mix( g_daysky_colour.rgb, g_sunset_colour.rgb, \n"
-"                               g_sunset_phase );\n"
-"\n"
-"\n"
-"   vec3  sky_reflection = 0.5 * fresnel * reflect_colour;\n"
-"   vec3  light_sun      = max(0.0, dot(normal,g_sun_dir.xyz)*0.5+0.5) \n"
-"                           * g_sun_colour.rgb * g_day_phase;\n"
-"\n"
-"   float scaled_shadow = max( shadow, 1.0 - max(g_sun_dir.y,0.0) );\n"
-"   vec3 ambient = mix( g_ambient_colour.rgb, g_sunset_ambient.rgb, \n"
-"                       g_sunset_phase );\n"
-"\n"
-"   return ambient + (light_sun + sky_reflection) * shadow;\n"
-"}\n"
-"\n"
-"vec3 character_compute_lighting( vec3 diffuse, vec3 normal, vec3 co,\n"
-"                                 float light_mask )\n"
-"{\n"
-"   if( g_light_preview == 1 )\n"
-"      diffuse = vec3(0.75);\n"
-"\n"
-"   // Lighting\n"
-"   vec3 halfview = uCamera - co;\n"
-"   float fdist = length(halfview);\n"
-"   halfview /= fdist;\n"
-"\n"
-"   float world_shadow = newlight_compute_sun_shadow( \n"
-"               co, g_sun_dir.xyz * (1.0/(max(g_sun_dir.y,0.0)+0.2)) );\n"
-"\n"
-"   vec3 total_light = character_clearskies_lighting( \n"
-"                           normal, min( light_mask, world_shadow ), halfview );\n"
-"\n"
-"   vec3 cube_coord = (co - g_cube_min.xyz) * g_cube_inv_range.xyz;\n"
-"        cube_coord = floor( cube_coord );\n"
-"\n"
-"   if( g_debug_indices == 1 )\n"
-"   {\n"
-"      return rand33(cube_coord);\n"
-"   }\n"
-"\n"
-"   if( g_debug_complexity == 1 )\n"
-"   {\n"
-"      ivec3 coord = ivec3( cube_coord );\n"
-"      uvec4 index_sample = texelFetch( uLightsIndex, coord, 0 );\n"
-"\n"
-"      uint light_count = (index_sample.x & 0x3u) + (index_sample.y & 0x3u);\n"
-"      return vec3( float(light_count)*(1.0/6.0), 0.0, 0.5 );\n"
-"   }\n"
-"\n"
-"   // FIXME: this coord should absolutely must be clamped!\n"
-"   \n"
-"   ivec3 coord = ivec3( cube_coord );\n"
-"   uvec4 index_sample = texelFetch( uLightsIndex, coord, 0 );\n"
-"\n"
-"   total_light += \n"
-"      scene_calculate_packed_light_patch( index_sample.x,\n"
-"                                          halfview, co, normal ) \n"
-"                                          * light_mask;\n"
-"   total_light += \n"
-"      scene_calculate_packed_light_patch( index_sample.y,\n"
-"                                          halfview, co, normal )\n"
-"                                          * light_mask;\n"
-"\n"
-"   // Take a section of the sky function to give us a matching fog colour\n"
-"\n"
-"   vec3 fog_colour  = clearskies_ambient( -halfview );\n"
-"   float sun_theta  = dot( -halfview, g_sun_dir.xyz );\n"
-"   float sun_size   = max( 0.0, sun_theta * 0.5 + 0.5 );\n"
-"   float sun_shape  = sun_size * max(g_sun_dir.y,0.0) * 0.5;\n"
-"         \n"
-"   vec3 sun_colour  = mix( vec3(1.0), g_sunset_colour.rgb, g_sunset_phase*0.5 );\n"
-"        sun_colour *= sun_shape;\n"
-"\n"
-"   fog_colour += sun_colour;\n"
-"   return scene_apply_fog( diffuse * total_light, fog_colour, fdist );\n"
-"}\n"
-"\n"
-"void main(){\n"
-"   depth_compare_dither();\n"
-"   compute_motion_vectors();\n"
-"\n"
-"   vec3 qnorm     = aNorm;\n"
-"   vec3 diffuse   = texture( uTexMain, aUv ).rgb;\n"
-"   vec3 composite = character_compute_lighting( diffuse, qnorm, aWorldCo, 1.0 );\n"
-"\n"
-"   float dist    = distance( aWorldCo, uCamera ) - 0.08;\n"
-"   float opacity = clamp( dist*dist, 0.0, 1.0 );\n"
-"\n"
-"   oColour = vec4( composite, opacity );\n"
-"}\n"
-""},
-};
-
-static GLuint _uniform_model_character_view_uPv;
-static GLuint _uniform_model_character_view_uTransforms;
-static GLuint _uniform_model_character_view_uTexMain;
-static GLuint _uniform_model_character_view_uCamera;
-static GLuint _uniform_model_character_view_g_world_depth;
-static GLuint _uniform_model_character_view_uLightsArray;
-static GLuint _uniform_model_character_view_uLightsIndex;
-static GLuint _uniform_model_character_view_uTexSceneDepth;
-static GLuint _uniform_model_character_view_uInverseRatioDepth;
-static GLuint _uniform_model_character_view_uInverseRatioMain;
-static GLuint _uniform_model_character_view_uDepthCompare;
-static void shader_model_character_view_uPv(m4x4f m){
-   glUniformMatrix4fv(_uniform_model_character_view_uPv,1,GL_FALSE,(float*)m);
+   glUniformMatrix4fv(_uniform_model_character_view_uPv,1,GL_FALSE,(f32*)m);
 }
-static void shader_model_character_view_uTexMain(int i){
+static inline void shader_model_character_view_uTexMain(int i)
+{
    glUniform1i(_uniform_model_character_view_uTexMain,i);
 }
-static void shader_model_character_view_uCamera(v3f v){
+static inline void shader_model_character_view_uCamera(v3f v)
+{
    glUniform3fv(_uniform_model_character_view_uCamera,1,v);
 }
-static void shader_model_character_view_g_world_depth(int i){
+static inline void shader_model_character_view_g_world_depth(int i)
+{
    glUniform1i(_uniform_model_character_view_g_world_depth,i);
 }
-static void shader_model_character_view_uTexSceneDepth(int i){
+static inline void shader_model_character_view_uTexSceneDepth(int i)
+{
    glUniform1i(_uniform_model_character_view_uTexSceneDepth,i);
 }
-static void shader_model_character_view_uInverseRatioDepth(v3f v){
+static inline void shader_model_character_view_uInverseRatioDepth(v3f v)
+{
    glUniform3fv(_uniform_model_character_view_uInverseRatioDepth,1,v);
 }
-static void shader_model_character_view_uInverseRatioMain(v3f v){
+static inline void shader_model_character_view_uInverseRatioMain(v3f v)
+{
    glUniform3fv(_uniform_model_character_view_uInverseRatioMain,1,v);
 }
-static void shader_model_character_view_uDepthCompare(int b){
+static inline void shader_model_character_view_uDepthCompare(int b)
+{
    glUniform1i(_uniform_model_character_view_uDepthCompare,b);
 }
-static void shader_model_character_view_register(void){
-   vg_shader_register( &_shader_model_character_view );
-}
-static void shader_model_character_view_use(void){ glUseProgram(_shader_model_character_view.id); }
-static void shader_model_character_view_link(void){
-   _uniform_model_character_view_uPv = glGetUniformLocation( _shader_model_character_view.id, "uPv" );
-   _uniform_model_character_view_uTransforms = glGetUniformLocation( _shader_model_character_view.id, "uTransforms" );
-   _uniform_model_character_view_uTexMain = glGetUniformLocation( _shader_model_character_view.id, "uTexMain" );
-   _uniform_model_character_view_uCamera = glGetUniformLocation( _shader_model_character_view.id, "uCamera" );
-   _uniform_model_character_view_g_world_depth = glGetUniformLocation( _shader_model_character_view.id, "g_world_depth" );
-   _uniform_model_character_view_uLightsArray = glGetUniformLocation( _shader_model_character_view.id, "uLightsArray" );
-   _uniform_model_character_view_uLightsIndex = glGetUniformLocation( _shader_model_character_view.id, "uLightsIndex" );
-   _uniform_model_character_view_uTexSceneDepth = glGetUniformLocation( _shader_model_character_view.id, "uTexSceneDepth" );
-   _uniform_model_character_view_uInverseRatioDepth = glGetUniformLocation( _shader_model_character_view.id, "uInverseRatioDepth" );
-   _uniform_model_character_view_uInverseRatioMain = glGetUniformLocation( _shader_model_character_view.id, "uInverseRatioMain" );
-   _uniform_model_character_view_uDepthCompare = glGetUniformLocation( _shader_model_character_view.id, "uDepthCompare" );
+static inline void shader_model_character_view_use(void);
+static inline void shader_model_character_view_use(void)
+{
+   glUseProgram(_shader_model_character_view.id);
 }
-#endif /* SHADER_model_character_view_H */
index a9700388f0e4783c2d9eed4dec3be0423bbb3621..e198e0385d829511d7f196df57fb775d5dbd8f5d 100644 (file)
-#ifndef SHADER_model_entity_H
-#define SHADER_model_entity_H
-static void shader_model_entity_link(void);
-static void shader_model_entity_register(void);
-static struct vg_shader _shader_model_entity = {
-   .name = "model_entity",
-   .link = shader_model_entity_link,
-   .vs = 
+#pragma once
+#include "vg/vg_engine.h"
+extern struct vg_shader _shader_model_entity;
+extern GLuint _uniform_model_entity_uMdl;
+extern GLuint _uniform_model_entity_uPv;
+extern GLuint _uniform_model_entity_uPvmPrev;
+extern GLuint _uniform_model_entity_uTexMain;
+extern GLuint _uniform_model_entity_uCamera;
+extern GLuint _uniform_model_entity_g_world_depth;
+extern GLuint _uniform_model_entity_uLightsArray;
+extern GLuint _uniform_model_entity_uLightsIndex;
+static inline void shader_model_entity_uMdl(m4x3f m)
 {
-.orig_file = "shaders/model.vs",
-.static_src = 
-"layout (location=0) in vec3 a_co;\n"
-"layout (location=1) in vec3 a_norm;\n"
-"layout (location=2) in vec2 a_uv;\n"
-"layout (location=3) in vec4 a_colour;\n"
-"layout (location=4) in vec4 a_weights;\n"
-"layout (location=5) in ivec4 a_groups;\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      9        0 \n"
-"\n"
-"uniform mat4x3 uMdl;\n"
-"uniform mat4 uPv;\n"
-"uniform mat4 uPvmPrev;\n"
-"\n"
-"out vec4 aColour;\n"
-"out vec2 aUv;\n"
-"out vec3 aNorm;\n"
-"out vec3 aCo;\n"
-"out vec3 aWorldCo;\n"
-"\n"
-"void main()\n"
-"{\n"
-"   vec3 world_pos0 = uMdl     * vec4( a_co, 1.0 );\n"
-"   vec4 vproj0     = uPv      * vec4( world_pos0, 1.0 );\n"
-"   vec4 vproj1     = uPvmPrev * vec4( a_co, 1.0 );\n"
-"\n"
-"   vs_motion_out( vproj0, vproj1 );\n"
-"\n"
-"   gl_Position = vproj0;\n"
-"   aWorldCo = world_pos0;\n"
-"   aColour = a_colour;\n"
-"   aUv = a_uv;\n"
-"   aNorm = normalize( mat3(uMdl) * a_norm );\n"
-"   aCo = a_co;\n"
-"}\n"
-""},
-   .fs = 
-{
-.orig_file = "shaders/model_entity.fs",
-.static_src = 
-"uniform sampler2D uTexMain;\n"
-"uniform vec3 uCamera;\n"
-"\n"
-"in vec4 aColour;\n"
-"in vec2 aUv;\n"
-"in vec3 aNorm;\n"
-"in vec3 aCo;\n"
-"in vec3 aWorldCo;\n"
-"\n"
-"#line       1        1 \n"
-"// :D\n"
-"const float CLEARSKIES_LIGHT_DOT_MIN = 0.0;\n"
-"\n"
-"#line     11        0 \n"
-"#line       1        2 \n"
-"layout (location = 0) out vec4 oColour;\n"
-"\n"
-"// OpenGL wiki: Recommends do not use vec3 because of drivers. hence the v4s...\n"
-"layout (std140) uniform ub_world_lighting\n"
-"{\n"
-"   vec4 g_cube_min;\n"
-"   vec4 g_cube_inv_range;\n"
-"\n"
-"   vec4 g_water_plane;\n"
-"   vec4 g_depth_bounds;\n"
-"\n"
-"   vec4 g_daysky_colour;\n"
-"   vec4 g_nightsky_colour;\n"
-"   vec4 g_sunset_colour;\n"
-"   vec4 g_ambient_colour;\n"
-"   vec4 g_sunset_ambient;\n"
-"   vec4 g_sun_colour;\n"
-"   vec4 g_sun_dir;\n"
-"   vec4 g_board_0;\n"
-"   vec4 g_board_1;\n"
-"\n"
-"   float g_water_fog;\n"
-"   float g_time;\n"
-"   float g_realtime;\n"
-"   float g_shadow_length;\n"
-"   float g_shadow_spread;\n"
-"\n"
-"   float g_time_of_day;\n"
-"   float g_day_phase;\n"
-"   float g_sunset_phase;\n"
-"\n"
-"   int g_light_preview;\n"
-"   int g_shadow_samples;\n"
-"\n"
-"   int g_debug_indices;\n"
-"   int g_debug_complexity;\n"
-"};\n"
-"\n"
-"uniform sampler2D g_world_depth;\n"
-"uniform samplerBuffer uLightsArray;\n"
-"uniform usampler3D uLightsIndex;\n"
-"\n"
-"#line       1        1 \n"
-"//const vec3  DAYSKY_COLOUR   = vec3( 0.37, 0.54, 0.97 );\n"
-"//const vec3  NIGHTSKY_COLOUR = vec3( 0.03, 0.05, 0.20 );\n"
-"//const vec3  SUNSET_COLOUR   = vec3( 1.00, 0.32, 0.01 );\n"
-"//const vec3  AMBIENT_COLOUR  = vec3( 0.13, 0.17, 0.35 );\n"
-"//const vec3  SUNSET_AMBIENT  = vec3( 0.25, 0.17, 0.51 );\n"
-"//const vec3  SUN_COLOUR      = vec3( 1.10, 0.89, 0.35 );\n"
-"\n"
-"const float SUN_ANGLE       = 0.0001;\n"
-"const float PI              = 3.14159265358979323846264;\n"
-"\n"
-"//struct world_info\n"
-"//{\n"
-"//   float time,\n"
-"//         time_of_day,\n"
-"//         day_phase,\n"
-"//         sunset_phase;\n"
-"//   \n"
-"//   vec3 sun_dir;\n"
-"//};\n"
-"\n"
-"vec3 rand33(vec3 p3)\n"
-"{\n"
-"      p3 = fract(p3 * vec3(.1031, .1030, .0973));\n"
-"   p3 += dot(p3, p3.yxz+33.33);\n"
-"   return fract((p3.xxy + p3.yxx)*p3.zyx);\n"
-"}\n"
-"\n"
-"float stars( vec3 rd, float rr, float size ){\n"
-"   vec3 co = rd * rr;\n"
-"\n"
-"   float a = atan(co.y, length(co.xz)) + 4.0 * PI;\n"
-"\n"
-"   float spaces = 1.0 / rr;\n"
-"   size = (rr * 0.0015) * fwidth(a) * 1000.0 * size;\n"
-"   a -= mod(a, spaces) - spaces * 0.5;\n"
-"\n"
-"   float count = floor(sqrt(pow(rr, 2.0) * (1.0 - pow(sin(a), 2.0))) * 3.0);\n"
-"   \n"
-"   float plane = atan(co.z, co.x) + 4.0 * PI;\n"
-"   plane = plane - mod(plane, PI / count);\n"
-"\n"
-"   vec2 delta = rand33(vec3(plane, a, 0.0)).xy;\n"
-"\n"
-"   float level = sin(a + spaces * (delta.y - 0.5) * (1.0 - size)) * rr;\n"
-"   float ydist = sqrt(rr * rr - level * level);\n"
-"   float angle = plane + (PI * (delta.x * (1.0-size) + size * 0.5) / count);\n"
-"   vec3 center = vec3(cos(angle) * ydist, level, sin(angle) * ydist);\n"
-"   float star = smoothstep(size, 0.0, distance(center, co));\n"
-"   return star;\n"
-"}\n"
-"\n"
-"float luminance( vec3 v )\n"
-"{\n"
-"   return dot( v, vec3(0.2126, 0.7152, 0.0722) );\n"
-"}\n"
-"\n"
-"vec3 clearskies_ambient( vec3 dir )\n"
-"{\n"
-"   float sun_azimuth  = g_sunset_phase * (dot( dir.xz, g_sun_dir.xz )*0.4+0.6);\n"
-"   float sky_gradient = dir.y;\n"
-"   \n"
-"   /* Blend phase colours */\n"
-"   vec3 ambient  = g_daysky_colour.rgb   * (g_day_phase-g_sunset_phase*0.1);\n"
-"        ambient += g_sunset_colour.rgb   * (1.0-dir.y*0.5)*sun_azimuth;\n"
-"        ambient += g_nightsky_colour.rgb * (1.0-g_day_phase);\n"
-"   \n"
-"   /* Add gradient */\n"
-"        ambient -= sky_gradient * luminance(ambient);\n"
-"        \n"
-"   return ambient;\n"
-"}\n"
-"\n"
-"vec3 clearskies_sky( vec3 ray_dir )\n"
-"{\n"
-"   ray_dir.y = abs( ray_dir.y );\n"
-"   vec3 sky_colour  = clearskies_ambient( ray_dir );\n"
-"   \n"
-"   /* Sun */\n"
-"   float sun_theta  = dot( ray_dir, g_sun_dir.xyz );\n"
-"   float sun_size   = max( 0.0, sun_theta * 0.5 + 0.5 + SUN_ANGLE );\n"
-"   float sun_shape  = pow( sun_size, 2000.0 );\n"
-"         sun_shape += sun_size * max(g_sun_dir.y,0.0) * 0.5;\n"
-"         \n"
-"   vec3 sun_colour  = mix( vec3(1.0), g_sunset_colour.rgb, g_sunset_phase*0.5 );\n"
-"        sun_colour *= sun_shape;\n"
-"\n"
-"   \n"
-"   float star = 0.0;\n"
-"   float star_blend = 10.0*max(0.0,(1.0-g_day_phase*2.0));\n"
-"\n"
-"   if( star_blend > 0.001 ){\n"
-"      for( float j = 1.0; j <= 4.1; j += 1.0 ){\n"
-"         float m = mix(0.6, 0.9, smoothstep(1.0, 2.0, j));\n"
-"         star += stars( ray_dir, 1.94 * pow( 1.64, j ), m ) * (1.0/pow(4.0, j));\n"
-"      }\n"
-"   }\n"
-"   \n"
-"   vec3 composite   = sky_colour + sun_colour + star*star_blend;\n"
-"   return composite;\n"
-"}\n"
-"\n"
-"vec3 clearskies_lighting( vec3 normal, float shadow, vec3 halfview )\n"
-"{\n"
-"   float fresnel = 1.0 - abs(dot(normal,halfview));\n"
-"\n"
-"   vec3  reflect_colour = mix( g_daysky_colour.rgb, g_sunset_colour.rgb, \n"
-"                               g_sunset_phase );\n"
-"\n"
-"   vec3  sky_reflection = 0.5 * fresnel * reflect_colour;\n"
-"   vec3  light_sun      = max( CLEARSKIES_LIGHT_DOT_MIN, \n"
-"                               dot(normal,g_sun_dir.xyz)*0.75+0.25\n"
-"                           ) * g_sun_colour.rgb * g_day_phase;\n"
-"\n"
-"   float scaled_shadow = max( shadow, 1.0 - max(g_sun_dir.y,0.0) );\n"
-"   vec3 ambient = mix( g_ambient_colour.rgb, g_sunset_ambient.rgb, \n"
-"                       g_sunset_phase );\n"
-"\n"
-"   return ambient + (light_sun + sky_reflection) * shadow;\n"
-"}\n"
-"\n"
-"#line     44        0 \n"
-"\n"
-"float world_depth_sample( vec3 pos )\n"
-"{\n"
-"   vec2 depth_coord = (pos.xz - g_depth_bounds.xy) * g_depth_bounds.zw; \n"
-"   return texture( g_world_depth, depth_coord ).r;\n"
-"}\n"
-"\n"
-"float world_water_depth( vec3 pos )\n"
-"{\n"
-"   float ref_depth = g_water_plane.y*g_water_plane.w;\n"
-"   return world_depth_sample( pos ) - ref_depth;\n"
-"}\n"
-"\n"
-"float shadow_sample( vec3 co ){\n"
-"   float height_sample = world_depth_sample( co );\n"
-"\n"
-"   float fdelta = height_sample - co.y;\n"
-"   return clamp( fdelta, 0.2, 0.4 )-0.2;\n"
-"}\n"
-"\n"
-"float newlight_compute_sun_shadow( vec3 co, vec3 dir ){\n"
-"   if( g_shadow_samples == 0 ){\n"
-"      return 1.0;\n"
-"   }\n"
-"\n"
-"   float fspread = g_shadow_spread;\n"
-"   float flength = g_shadow_length;\n"
-"\n"
-"   float famt = 0.0;\n"
-"   famt += shadow_sample(co+(dir+vec3(-0.56,0.55, 0.30)*fspread)*flength*0.1);\n"
-"   famt += shadow_sample(co+(dir+vec3( 0.80,0.68, 0.34)*fspread)*flength*0.2);\n"
-"   famt += shadow_sample(co+(dir+vec3( 0.78,0.07,-0.06)*fspread)*flength*0.3);\n"
-"   famt += shadow_sample(co+(dir+vec3(-0.59,0.07,-0.42)*fspread)*flength*0.4);\n"
-"\n"
-"   //famt+=shadow_sample(co+(dir+vec3(-0.790,-0.933,-0.875)*fspread)*flength*0.5);\n"
-"   //famt+=shadow_sample(co+(dir+vec3( 0.807,-0.690, 0.472)*fspread)*flength*0.6);\n"
-"   //famt+=shadow_sample(co+(dir+vec3( 0.522,-0.379, 0.350)*fspread)*flength*0.7);\n"
-"   //famt+=shadow_sample(co+(dir+vec3( 0.483, 0.201, 0.306)*fspread)*flength*0.8);\n"
-"\n"
-"   return 1.0 - famt;\n"
-"}\n"
-"\n"
-"float newlight_specular( vec3 wnormal, vec3 dir, vec3 halfview, float exponent )\n"
-"{\n"
-"   vec3 specdir = reflect( -dir, wnormal );\n"
-"   return pow(max(dot( halfview, specdir ), 0.0), exponent);\n"
-"}\n"
-"\n"
-"vec3 scene_apply_fog( vec3 vfrag, vec3 colour, float fdist ){\n"
-"   float dist = pow(fdist*0.0010,0.78);\n"
-"   return mix( vfrag, colour, min( 1.0, dist ) );\n"
-"}\n"
-"\n"
-"vec3 scene_calculate_light( int light_index, \n"
-"                            vec3 halfview, vec3 co, vec3 normal )\n"
-"{\n"
-"   vec4 light_colour = texelFetch( uLightsArray, light_index+0 );\n"
-"   vec4 light_co     = texelFetch( uLightsArray, light_index+1 );\n"
-"   vec4 light_dir    = texelFetch( uLightsArray, light_index+2 );\n"
-"\n"
-"   vec3 light_delta = light_co.xyz-co;\n"
-"   float dist2 = dot(light_delta,light_delta);\n"
-"\n"
-"   light_delta = normalize( light_delta );\n"
-"\n"
-"   float quadratic = dist2*100.0;\n"
-"   float attenuation  = 1.0/( 1.0 + quadratic );\n"
-"         attenuation *= max( dot( light_delta, normal ), 0.0 );\n"
-"\n"
-"   float falloff = max( 0.0, 1.0-(dist2*light_co.w) );\n"
-"\n"
-"   if( light_dir.w < 0.999999 ){\n"
-"      float spot_theta = max( 0.0, dot( light_delta, -light_dir.xyz ) );\n"
-"      falloff *= max( 0.0, (spot_theta - light_dir.w) / (1.0-light_dir.w) );\n"
-"   }\n"
-"\n"
-"   return light_colour.rgb * attenuation * falloff \n"
-"            * step( g_day_phase, light_colour.w );\n"
-"}\n"
-"\n"
-"vec3 scene_calculate_packed_light_patch( uint packed_index, \n"
-"                                         vec3 halfview, vec3 co, vec3 normal )\n"
-"{\n"
-"   uint light_count = packed_index & 0x3u;\n"
-"\n"
-"   vec3 l = vec3(0.0);\n"
-"\n"
-"   if( light_count >= 1u ){\n"
-"      int index_0 = int( ((packed_index >>  2u) & 0x3ffu) * 3u );\n"
-"      int index_1 = int( ((packed_index >> 12u) & 0x3ffu) * 3u );\n"
-"      int index_2 = int( ((packed_index >> 22u) & 0x3ffu) * 3u );\n"
-"\n"
-"      l += scene_calculate_light( index_0, halfview, co, normal );\n"
-"\n"
-"      if( light_count >= 2u ){\n"
-"         l += scene_calculate_light( index_1, halfview, co, normal );\n"
-"\n"
-"         if( light_count >= 3u ){\n"
-"            l += scene_calculate_light( index_2, halfview, co, normal );\n"
-"         }\n"
-"      }\n"
-"   }\n"
-"\n"
-"   return l;\n"
-"}\n"
-"\n"
-"vec3 world_compute_lighting( vec3 diffuse, vec3 normal, vec3 co,\n"
-"                             float light_mask )\n"
-"{\n"
-"   if( g_light_preview == 1 )\n"
-"      diffuse = vec3(0.75);\n"
-"\n"
-"   // Lighting\n"
-"   vec3 halfview = uCamera - co;\n"
-"   float fdist = length(halfview);\n"
-"   halfview /= fdist;\n"
-"\n"
-"   float world_shadow = newlight_compute_sun_shadow( \n"
-"               co, g_sun_dir.xyz * (1.0/(max(g_sun_dir.y,0.0)+0.2)) );\n"
-"\n"
-"   vec3 total_light = clearskies_lighting( \n"
-"                           normal, min( light_mask, world_shadow ), halfview );\n"
-"\n"
-"   vec3 cube_coord = (co - g_cube_min.xyz) * g_cube_inv_range.xyz;\n"
-"        cube_coord = floor( cube_coord );\n"
-"\n"
-"   if( g_debug_indices == 1 )\n"
-"   {\n"
-"      return rand33(cube_coord);\n"
-"   }\n"
-"\n"
-"   if( g_debug_complexity == 1 )\n"
-"   {\n"
-"      ivec3 coord = ivec3( cube_coord );\n"
-"      uvec4 index_sample = texelFetch( uLightsIndex, coord, 0 );\n"
-"\n"
-"      uint light_count = (index_sample.x & 0x3u) + (index_sample.y & 0x3u);\n"
-"      return vec3( float(light_count)*(1.0/6.0), 0.0, 0.5 );\n"
-"   }\n"
-"\n"
-"   // FIXME: this coord should absolutely must be clamped!\n"
-"   \n"
-"   ivec3 coord = ivec3( cube_coord );\n"
-"   uvec4 index_sample = texelFetch( uLightsIndex, coord, 0 );\n"
-"\n"
-"   total_light += \n"
-"      scene_calculate_packed_light_patch( index_sample.x,\n"
-"                                          halfview, co, normal ) \n"
-"                                          * light_mask;\n"
-"   total_light += \n"
-"      scene_calculate_packed_light_patch( index_sample.y,\n"
-"                                          halfview, co, normal )\n"
-"                                          * light_mask;\n"
-"\n"
-"   // Take a section of the sky function to give us a matching fog colour\n"
-"\n"
-"   vec3 fog_colour  = clearskies_ambient( -halfview );\n"
-"   float sun_theta  = dot( -halfview, g_sun_dir.xyz );\n"
-"   float sun_size   = max( 0.0, sun_theta * 0.5 + 0.5 );\n"
-"   float sun_shape  = sun_size * max(g_sun_dir.y,0.0) * 0.5;\n"
-"         \n"
-"   vec3 sun_colour  = mix( vec3(1.0), g_sunset_colour.rgb, g_sunset_phase*0.5 );\n"
-"        sun_colour *= sun_shape;\n"
-"\n"
-"   fog_colour += sun_colour;\n"
-"   return scene_apply_fog( diffuse * total_light, fog_colour, fdist );\n"
-"}\n"
-"\n"
-"#line     12        0 \n"
-"#line       1        3 \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     13        0 \n"
-"\n"
-"void main()\n"
-"{\n"
-"   compute_motion_vectors();\n"
-"\n"
-"   vec3 qnorm     = normalize(floor(aNorm*2.0)*0.5) + vec3(0.001,0.0,0.0);\n"
-"   vec3 diffuse   = texture( uTexMain, aUv ).rgb;\n"
-"   vec3 composite = world_compute_lighting( diffuse, qnorm, aWorldCo, 1.0 );\n"
-"\n"
-"   oColour = vec4( composite, 1.0 );\n"
-"}\n"
-""},
-};
-
-static GLuint _uniform_model_entity_uMdl;
-static GLuint _uniform_model_entity_uPv;
-static GLuint _uniform_model_entity_uPvmPrev;
-static GLuint _uniform_model_entity_uTexMain;
-static GLuint _uniform_model_entity_uCamera;
-static GLuint _uniform_model_entity_g_world_depth;
-static GLuint _uniform_model_entity_uLightsArray;
-static GLuint _uniform_model_entity_uLightsIndex;
-static void shader_model_entity_uMdl(m4x3f m){
-   glUniformMatrix4x3fv(_uniform_model_entity_uMdl,1,GL_FALSE,(float*)m);
+   glUniformMatrix4x3fv(_uniform_model_entity_uMdl,1,GL_FALSE,(f32*)m);
 }
-static void shader_model_entity_uPv(m4x4f m){
-   glUniformMatrix4fv(_uniform_model_entity_uPv,1,GL_FALSE,(float*)m);
+static inline void shader_model_entity_uPv(m4x4f m)
+{
+   glUniformMatrix4fv(_uniform_model_entity_uPv,1,GL_FALSE,(f32*)m);
 }
-static void shader_model_entity_uPvmPrev(m4x4f m){
-   glUniformMatrix4fv(_uniform_model_entity_uPvmPrev,1,GL_FALSE,(float*)m);
+static inline void shader_model_entity_uPvmPrev(m4x4f m)
+{
+   glUniformMatrix4fv(_uniform_model_entity_uPvmPrev,1,GL_FALSE,(f32*)m);
 }
-static void shader_model_entity_uTexMain(int i){
+static inline void shader_model_entity_uTexMain(int i)
+{
    glUniform1i(_uniform_model_entity_uTexMain,i);
 }
-static void shader_model_entity_uCamera(v3f v){
+static inline void shader_model_entity_uCamera(v3f v)
+{
    glUniform3fv(_uniform_model_entity_uCamera,1,v);
 }
-static void shader_model_entity_g_world_depth(int i){
+static inline void shader_model_entity_g_world_depth(int i)
+{
    glUniform1i(_uniform_model_entity_g_world_depth,i);
 }
-static void shader_model_entity_register(void){
-   vg_shader_register( &_shader_model_entity );
-}
-static void shader_model_entity_use(void){ glUseProgram(_shader_model_entity.id); }
-static void shader_model_entity_link(void){
-   _uniform_model_entity_uMdl = glGetUniformLocation( _shader_model_entity.id, "uMdl" );
-   _uniform_model_entity_uPv = glGetUniformLocation( _shader_model_entity.id, "uPv" );
-   _uniform_model_entity_uPvmPrev = glGetUniformLocation( _shader_model_entity.id, "uPvmPrev" );
-   _uniform_model_entity_uTexMain = glGetUniformLocation( _shader_model_entity.id, "uTexMain" );
-   _uniform_model_entity_uCamera = glGetUniformLocation( _shader_model_entity.id, "uCamera" );
-   _uniform_model_entity_g_world_depth = glGetUniformLocation( _shader_model_entity.id, "g_world_depth" );
-   _uniform_model_entity_uLightsArray = glGetUniformLocation( _shader_model_entity.id, "uLightsArray" );
-   _uniform_model_entity_uLightsIndex = glGetUniformLocation( _shader_model_entity.id, "uLightsIndex" );
+static inline void shader_model_entity_use(void);
+static inline void shader_model_entity_use(void)
+{
+   glUseProgram(_shader_model_entity.id);
 }
-#endif /* SHADER_model_entity_H */
index 67ce50d090f32deaac5e64a5495a14f88fa034a3..8ba6c7a20bde0308ad1f116c644b453a1f1b400c 100644 (file)
-#ifndef SHADER_model_font_H
-#define SHADER_model_font_H
-static void shader_model_font_link(void);
-static void shader_model_font_register(void);
-static struct vg_shader _shader_model_font = {
-   .name = "model_font",
-   .link = shader_model_font_link,
-   .vs = 
+#pragma once
+#include "vg/vg_engine.h"
+extern struct vg_shader _shader_model_font;
+extern GLuint _uniform_model_font_uMdl;
+extern GLuint _uniform_model_font_uPv;
+extern GLuint _uniform_model_font_uPvmPrev;
+extern GLuint _uniform_model_font_uOffset;
+extern GLuint _uniform_model_font_uTexMain;
+extern GLuint _uniform_model_font_uColour;
+extern GLuint _uniform_model_font_uTexSceneDepth;
+extern GLuint _uniform_model_font_uInverseRatioDepth;
+extern GLuint _uniform_model_font_uInverseRatioMain;
+extern GLuint _uniform_model_font_uDepthCompare;
+static inline void shader_model_font_uMdl(m4x3f m)
 {
-.orig_file = "shaders/model_font.vs",
-.static_src = 
-"layout (location=0) in vec3 a_co;\n"
-"layout (location=1) in vec3 a_norm;\n"
-"layout (location=2) in vec2 a_uv;\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      6        0 \n"
-"\n"
-"uniform mat4x3 uMdl;\n"
-"uniform mat4 uPv;\n"
-"uniform mat4 uPvmPrev;\n"
-"uniform vec4 uOffset;\n"
-"\n"
-"out vec2 aUv;\n"
-"out vec4 aNorm;\n"
-"out vec3 aCo;\n"
-"out vec3 aWorldCo;\n"
-"\n"
-"void main()\n"
-"{\n"
-"   vec3 co = a_co*uOffset.w+uOffset.xyz;\n"
-"   vec3 world_pos0 = uMdl     * vec4( co, 1.0 );\n"
-"   vec4 vproj0     = uPv      * vec4( world_pos0, 1.0 );\n"
-"   vec4 vproj1     = uPvmPrev * vec4( co, 1.0 );\n"
-"\n"
-"   vs_motion_out( vproj0, vproj1 );\n"
-"\n"
-"   gl_Position = vproj0;\n"
-"\n"
-"   aUv = a_uv;\n"
-"   aNorm = vec4( mat3(uMdl) * a_norm, 0.0 );\n"
-"   aCo = co;\n"
-"   aWorldCo = world_pos0;\n"
-"}\n"
-""},
-   .fs = 
-{
-.orig_file = "shaders/model_font.fs",
-.static_src = 
-"layout (location = 0) out vec4 oColour;\n"
-"\n"
-"uniform sampler2D uTexMain;\n"
-"uniform vec4 uColour;\n"
-"\n"
-"in vec2 aUv;\n"
-"in vec4 aNorm;\n"
-"in vec3 aCo;\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     11        0 \n"
-"#line       1        2 \n"
-"uniform sampler2D uTexSceneDepth;\n"
-"uniform vec3 uInverseRatioDepth;\n"
-"uniform vec3 uInverseRatioMain;\n"
-"uniform bool uDepthCompare;\n"
-"\n"
-"float linear_depth( float depth, float near, float far ) {\n"
-"   float z = depth * 2.0 - 1.0;\n"
-"   return (2.0 * near * far) / (far + near - z * (far - near));       \n"
-"}\n"
-"\n"
-"void depth_compare_dither(){\n"
-"   if( uDepthCompare ){\n"
-"      vec2 back_coord = gl_FragCoord.xy * uInverseRatioMain.xy \n"
-"                                        * uInverseRatioDepth.xy;\n"
-"      float back_depth = texture( uTexSceneDepth, back_coord ).r;\n"
-"      float front_depth = gl_FragCoord.z/gl_FragCoord.w;\n"
-"\n"
-"      back_depth = linear_depth( back_depth, 0.1, 2100.0 );\n"
-"      float diff = back_depth - front_depth;\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( step(0.0,diff)+dither<0.3 )\n"
-"         discard;\n"
-"   }\n"
-"}\n"
-"\n"
-"#line     12        0 \n"
-"\n"
-"void main(){\n"
-"   depth_compare_dither();\n"
-"   compute_motion_vectors();\n"
-"   oColour = texture( uTexMain, aUv ) * uColour;\n"
-"}\n"
-""},
-};
-
-static GLuint _uniform_model_font_uMdl;
-static GLuint _uniform_model_font_uPv;
-static GLuint _uniform_model_font_uPvmPrev;
-static GLuint _uniform_model_font_uOffset;
-static GLuint _uniform_model_font_uTexMain;
-static GLuint _uniform_model_font_uColour;
-static GLuint _uniform_model_font_uTexSceneDepth;
-static GLuint _uniform_model_font_uInverseRatioDepth;
-static GLuint _uniform_model_font_uInverseRatioMain;
-static GLuint _uniform_model_font_uDepthCompare;
-static void shader_model_font_uMdl(m4x3f m){
-   glUniformMatrix4x3fv(_uniform_model_font_uMdl,1,GL_FALSE,(float*)m);
+   glUniformMatrix4x3fv(_uniform_model_font_uMdl,1,GL_FALSE,(f32*)m);
 }
-static void shader_model_font_uPv(m4x4f m){
-   glUniformMatrix4fv(_uniform_model_font_uPv,1,GL_FALSE,(float*)m);
+static inline void shader_model_font_uPv(m4x4f m)
+{
+   glUniformMatrix4fv(_uniform_model_font_uPv,1,GL_FALSE,(f32*)m);
 }
-static void shader_model_font_uPvmPrev(m4x4f m){
-   glUniformMatrix4fv(_uniform_model_font_uPvmPrev,1,GL_FALSE,(float*)m);
+static inline void shader_model_font_uPvmPrev(m4x4f m)
+{
+   glUniformMatrix4fv(_uniform_model_font_uPvmPrev,1,GL_FALSE,(f32*)m);
 }
-static void shader_model_font_uOffset(v4f v){
+static inline void shader_model_font_uOffset(v4f v)
+{
    glUniform4fv(_uniform_model_font_uOffset,1,v);
 }
-static void shader_model_font_uTexMain(int i){
+static inline void shader_model_font_uTexMain(int i)
+{
    glUniform1i(_uniform_model_font_uTexMain,i);
 }
-static void shader_model_font_uColour(v4f v){
+static inline void shader_model_font_uColour(v4f v)
+{
    glUniform4fv(_uniform_model_font_uColour,1,v);
 }
-static void shader_model_font_uTexSceneDepth(int i){
+static inline void shader_model_font_uTexSceneDepth(int i)
+{
    glUniform1i(_uniform_model_font_uTexSceneDepth,i);
 }
-static void shader_model_font_uInverseRatioDepth(v3f v){
+static inline void shader_model_font_uInverseRatioDepth(v3f v)
+{
    glUniform3fv(_uniform_model_font_uInverseRatioDepth,1,v);
 }
-static void shader_model_font_uInverseRatioMain(v3f v){
+static inline void shader_model_font_uInverseRatioMain(v3f v)
+{
    glUniform3fv(_uniform_model_font_uInverseRatioMain,1,v);
 }
-static void shader_model_font_uDepthCompare(int b){
+static inline void shader_model_font_uDepthCompare(int b)
+{
    glUniform1i(_uniform_model_font_uDepthCompare,b);
 }
-static void shader_model_font_register(void){
-   vg_shader_register( &_shader_model_font );
-}
-static void shader_model_font_use(void){ glUseProgram(_shader_model_font.id); }
-static void shader_model_font_link(void){
-   _uniform_model_font_uMdl = glGetUniformLocation( _shader_model_font.id, "uMdl" );
-   _uniform_model_font_uPv = glGetUniformLocation( _shader_model_font.id, "uPv" );
-   _uniform_model_font_uPvmPrev = glGetUniformLocation( _shader_model_font.id, "uPvmPrev" );
-   _uniform_model_font_uOffset = glGetUniformLocation( _shader_model_font.id, "uOffset" );
-   _uniform_model_font_uTexMain = glGetUniformLocation( _shader_model_font.id, "uTexMain" );
-   _uniform_model_font_uColour = glGetUniformLocation( _shader_model_font.id, "uColour" );
-   _uniform_model_font_uTexSceneDepth = glGetUniformLocation( _shader_model_font.id, "uTexSceneDepth" );
-   _uniform_model_font_uInverseRatioDepth = glGetUniformLocation( _shader_model_font.id, "uInverseRatioDepth" );
-   _uniform_model_font_uInverseRatioMain = glGetUniformLocation( _shader_model_font.id, "uInverseRatioMain" );
-   _uniform_model_font_uDepthCompare = glGetUniformLocation( _shader_model_font.id, "uDepthCompare" );
+static inline void shader_model_font_use(void);
+static inline void shader_model_font_use(void)
+{
+   glUseProgram(_shader_model_font.id);
 }
-#endif /* SHADER_model_font_H */
index 1bc558fd5e0be8bba07fe2603a89a7b4f63a6658..49986ba43a2a08c3fe574a193cd6c61d6460e02b 100644 (file)
-#ifndef SHADER_model_gate_H
-#define SHADER_model_gate_H
-static void shader_model_gate_link(void);
-static void shader_model_gate_register(void);
-static struct vg_shader _shader_model_gate = {
-   .name = "model_gate",
-   .link = shader_model_gate_link,
-   .vs = 
+#pragma once
+#include "vg/vg_engine.h"
+extern struct vg_shader _shader_model_gate;
+extern GLuint _uniform_model_gate_uMdl;
+extern GLuint _uniform_model_gate_uPv;
+extern GLuint _uniform_model_gate_uPvmPrev;
+extern GLuint _uniform_model_gate_uTime;
+extern GLuint _uniform_model_gate_uCam;
+extern GLuint _uniform_model_gate_uInvRes;
+extern GLuint _uniform_model_gate_uColour;
+static inline void shader_model_gate_uMdl(m4x3f m)
 {
-.orig_file = "shaders/model.vs",
-.static_src = 
-"layout (location=0) in vec3 a_co;\n"
-"layout (location=1) in vec3 a_norm;\n"
-"layout (location=2) in vec2 a_uv;\n"
-"layout (location=3) in vec4 a_colour;\n"
-"layout (location=4) in vec4 a_weights;\n"
-"layout (location=5) in ivec4 a_groups;\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      9        0 \n"
-"\n"
-"uniform mat4x3 uMdl;\n"
-"uniform mat4 uPv;\n"
-"uniform mat4 uPvmPrev;\n"
-"\n"
-"out vec4 aColour;\n"
-"out vec2 aUv;\n"
-"out vec3 aNorm;\n"
-"out vec3 aCo;\n"
-"out vec3 aWorldCo;\n"
-"\n"
-"void main()\n"
-"{\n"
-"   vec3 world_pos0 = uMdl     * vec4( a_co, 1.0 );\n"
-"   vec4 vproj0     = uPv      * vec4( world_pos0, 1.0 );\n"
-"   vec4 vproj1     = uPvmPrev * vec4( a_co, 1.0 );\n"
-"\n"
-"   vs_motion_out( vproj0, vproj1 );\n"
-"\n"
-"   gl_Position = vproj0;\n"
-"   aWorldCo = world_pos0;\n"
-"   aColour = a_colour;\n"
-"   aUv = a_uv;\n"
-"   aNorm = normalize( mat3(uMdl) * a_norm );\n"
-"   aCo = a_co;\n"
-"}\n"
-""},
-   .fs = 
-{
-.orig_file = "shaders/model_gate_lq.fs",
-.static_src = 
-"out vec4 FragColor;\n"
-"\n"
-"uniform float uTime;\n"
-"uniform vec3 uCam;\n"
-"uniform vec2 uInvRes;\n"
-"uniform vec4 uColour;\n"
-"\n"
-"in vec3 aNorm;\n"
-"in vec2 aUv;\n"
-"in vec3 aCo;\n"
-"\n"
-"void main()\n"
-"{\n"
-"   vec2 ssuv = gl_FragCoord.xy;\n"
-"   float opacity = 1.0-smoothstep(0.0,1.0,aUv.y+uColour.a);\n"
-"   \n"
-"   vec3 vDither = vec3( dot( vec2( 171.0, 231.0 ), ssuv) );\n"
-"   float dither = fract( vDither.g / 71.0 ) - 0.5;\n"
-"\n"
-"   if( opacity+dither<0.5 )\n"
-"      discard;\n"
-"\n"
-"   FragColor = uColour;\n"
-"}\n"
-""},
-};
-
-static GLuint _uniform_model_gate_uMdl;
-static GLuint _uniform_model_gate_uPv;
-static GLuint _uniform_model_gate_uPvmPrev;
-static GLuint _uniform_model_gate_uTime;
-static GLuint _uniform_model_gate_uCam;
-static GLuint _uniform_model_gate_uInvRes;
-static GLuint _uniform_model_gate_uColour;
-static void shader_model_gate_uMdl(m4x3f m){
-   glUniformMatrix4x3fv(_uniform_model_gate_uMdl,1,GL_FALSE,(float*)m);
+   glUniformMatrix4x3fv(_uniform_model_gate_uMdl,1,GL_FALSE,(f32*)m);
 }
-static void shader_model_gate_uPv(m4x4f m){
-   glUniformMatrix4fv(_uniform_model_gate_uPv,1,GL_FALSE,(float*)m);
+static inline void shader_model_gate_uPv(m4x4f m)
+{
+   glUniformMatrix4fv(_uniform_model_gate_uPv,1,GL_FALSE,(f32*)m);
 }
-static void shader_model_gate_uPvmPrev(m4x4f m){
-   glUniformMatrix4fv(_uniform_model_gate_uPvmPrev,1,GL_FALSE,(float*)m);
+static inline void shader_model_gate_uPvmPrev(m4x4f m)
+{
+   glUniformMatrix4fv(_uniform_model_gate_uPvmPrev,1,GL_FALSE,(f32*)m);
 }
-static void shader_model_gate_uTime(float f){
+static inline void shader_model_gate_uTime(f32 f)
+{
    glUniform1f(_uniform_model_gate_uTime,f);
 }
-static void shader_model_gate_uCam(v3f v){
+static inline void shader_model_gate_uCam(v3f v)
+{
    glUniform3fv(_uniform_model_gate_uCam,1,v);
 }
-static void shader_model_gate_uInvRes(v2f v){
+static inline void shader_model_gate_uInvRes(v2f v)
+{
    glUniform2fv(_uniform_model_gate_uInvRes,1,v);
 }
-static void shader_model_gate_uColour(v4f v){
+static inline void shader_model_gate_uColour(v4f v)
+{
    glUniform4fv(_uniform_model_gate_uColour,1,v);
 }
-static void shader_model_gate_register(void){
-   vg_shader_register( &_shader_model_gate );
-}
-static void shader_model_gate_use(void){ glUseProgram(_shader_model_gate.id); }
-static void shader_model_gate_link(void){
-   _uniform_model_gate_uMdl = glGetUniformLocation( _shader_model_gate.id, "uMdl" );
-   _uniform_model_gate_uPv = glGetUniformLocation( _shader_model_gate.id, "uPv" );
-   _uniform_model_gate_uPvmPrev = glGetUniformLocation( _shader_model_gate.id, "uPvmPrev" );
-   _uniform_model_gate_uTime = glGetUniformLocation( _shader_model_gate.id, "uTime" );
-   _uniform_model_gate_uCam = glGetUniformLocation( _shader_model_gate.id, "uCam" );
-   _uniform_model_gate_uInvRes = glGetUniformLocation( _shader_model_gate.id, "uInvRes" );
-   _uniform_model_gate_uColour = glGetUniformLocation( _shader_model_gate.id, "uColour" );
+static inline void shader_model_gate_use(void);
+static inline void shader_model_gate_use(void)
+{
+   glUseProgram(_shader_model_gate.id);
 }
-#endif /* SHADER_model_gate_H */
index 449322aa95a2368792442e9ed59582dd8a6861d5..93ab1e32de8240bf985f5c857af8f22770479187 100644 (file)
-#ifndef SHADER_model_gate_unlinked_H
-#define SHADER_model_gate_unlinked_H
-static void shader_model_gate_unlinked_link(void);
-static void shader_model_gate_unlinked_register(void);
-static struct vg_shader _shader_model_gate_unlinked = {
-   .name = "model_gate_unlinked",
-   .link = shader_model_gate_unlinked_link,
-   .vs = 
+#pragma once
+#include "vg/vg_engine.h"
+extern struct vg_shader _shader_model_gate_unlinked;
+extern GLuint _uniform_model_gate_unlinked_uMdl;
+extern GLuint _uniform_model_gate_unlinked_uPv;
+extern GLuint _uniform_model_gate_unlinked_uPvmPrev;
+extern GLuint _uniform_model_gate_unlinked_uTime;
+extern GLuint _uniform_model_gate_unlinked_uCam;
+extern GLuint _uniform_model_gate_unlinked_uColour;
+static inline void shader_model_gate_unlinked_uMdl(m4x3f m)
 {
-.orig_file = "shaders/model.vs",
-.static_src = 
-"layout (location=0) in vec3 a_co;\n"
-"layout (location=1) in vec3 a_norm;\n"
-"layout (location=2) in vec2 a_uv;\n"
-"layout (location=3) in vec4 a_colour;\n"
-"layout (location=4) in vec4 a_weights;\n"
-"layout (location=5) in ivec4 a_groups;\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      9        0 \n"
-"\n"
-"uniform mat4x3 uMdl;\n"
-"uniform mat4 uPv;\n"
-"uniform mat4 uPvmPrev;\n"
-"\n"
-"out vec4 aColour;\n"
-"out vec2 aUv;\n"
-"out vec3 aNorm;\n"
-"out vec3 aCo;\n"
-"out vec3 aWorldCo;\n"
-"\n"
-"void main()\n"
-"{\n"
-"   vec3 world_pos0 = uMdl     * vec4( a_co, 1.0 );\n"
-"   vec4 vproj0     = uPv      * vec4( world_pos0, 1.0 );\n"
-"   vec4 vproj1     = uPvmPrev * vec4( a_co, 1.0 );\n"
-"\n"
-"   vs_motion_out( vproj0, vproj1 );\n"
-"\n"
-"   gl_Position = vproj0;\n"
-"   aWorldCo = world_pos0;\n"
-"   aColour = a_colour;\n"
-"   aUv = a_uv;\n"
-"   aNorm = normalize( mat3(uMdl) * a_norm );\n"
-"   aCo = a_co;\n"
-"}\n"
-""},
-   .fs = 
-{
-.orig_file = "shaders/model_gate_unlinked.fs",
-.static_src = 
-"out vec4 FragColor;\n"
-"\n"
-"uniform float uTime;\n"
-"uniform vec3 uCam;\n"
-"uniform vec4 uColour;\n"
-"\n"
-"in vec3 aNorm;\n"
-"in vec2 aUv;\n"
-"in vec3 aCo;\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     12        0 \n"
-"\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"
-"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"
-"   compute_motion_vectors();\n"
-"\n"
-"   vec2 ssuv = gl_FragCoord.xy;\n"
-"   float grad = 1.0-aUv.y*0.1;\n"
-"   float opacity = rand_hash22( vec2(floor(aUv.y*100.0),floor(aCo.z*10.0+uTime*40.0)) ).r*grad;\n"
-"   \n"
-"   vec3 vDither = vec3( dot( vec2( 171.0, 231.0 ), ssuv) );\n"
-"   float dither = fract( vDither.g / 71.0 ) - 0.5;\n"
-"\n"
-"   if( opacity<0.9 )\n"
-"      discard;\n"
-"\n"
-"   FragColor = vec4(0.7,0.5,0.5,1.0);\n"
-"}\n"
-""},
-};
-
-static GLuint _uniform_model_gate_unlinked_uMdl;
-static GLuint _uniform_model_gate_unlinked_uPv;
-static GLuint _uniform_model_gate_unlinked_uPvmPrev;
-static GLuint _uniform_model_gate_unlinked_uTime;
-static GLuint _uniform_model_gate_unlinked_uCam;
-static GLuint _uniform_model_gate_unlinked_uColour;
-static void shader_model_gate_unlinked_uMdl(m4x3f m){
-   glUniformMatrix4x3fv(_uniform_model_gate_unlinked_uMdl,1,GL_FALSE,(float*)m);
+   glUniformMatrix4x3fv(_uniform_model_gate_unlinked_uMdl,1,GL_FALSE,(f32*)m);
 }
-static void shader_model_gate_unlinked_uPv(m4x4f m){
-   glUniformMatrix4fv(_uniform_model_gate_unlinked_uPv,1,GL_FALSE,(float*)m);
+static inline void shader_model_gate_unlinked_uPv(m4x4f m)
+{
+   glUniformMatrix4fv(_uniform_model_gate_unlinked_uPv,1,GL_FALSE,(f32*)m);
 }
-static void shader_model_gate_unlinked_uPvmPrev(m4x4f m){
-   glUniformMatrix4fv(_uniform_model_gate_unlinked_uPvmPrev,1,GL_FALSE,(float*)m);
+static inline void shader_model_gate_unlinked_uPvmPrev(m4x4f m)
+{
+   glUniformMatrix4fv(_uniform_model_gate_unlinked_uPvmPrev,1,GL_FALSE,(f32*)m);
 }
-static void shader_model_gate_unlinked_uTime(float f){
+static inline void shader_model_gate_unlinked_uTime(f32 f)
+{
    glUniform1f(_uniform_model_gate_unlinked_uTime,f);
 }
-static void shader_model_gate_unlinked_uCam(v3f v){
+static inline void shader_model_gate_unlinked_uCam(v3f v)
+{
    glUniform3fv(_uniform_model_gate_unlinked_uCam,1,v);
 }
-static void shader_model_gate_unlinked_uColour(v4f v){
+static inline void shader_model_gate_unlinked_uColour(v4f v)
+{
    glUniform4fv(_uniform_model_gate_unlinked_uColour,1,v);
 }
-static void shader_model_gate_unlinked_register(void){
-   vg_shader_register( &_shader_model_gate_unlinked );
-}
-static void shader_model_gate_unlinked_use(void){ glUseProgram(_shader_model_gate_unlinked.id); }
-static void shader_model_gate_unlinked_link(void){
-   _uniform_model_gate_unlinked_uMdl = glGetUniformLocation( _shader_model_gate_unlinked.id, "uMdl" );
-   _uniform_model_gate_unlinked_uPv = glGetUniformLocation( _shader_model_gate_unlinked.id, "uPv" );
-   _uniform_model_gate_unlinked_uPvmPrev = glGetUniformLocation( _shader_model_gate_unlinked.id, "uPvmPrev" );
-   _uniform_model_gate_unlinked_uTime = glGetUniformLocation( _shader_model_gate_unlinked.id, "uTime" );
-   _uniform_model_gate_unlinked_uCam = glGetUniformLocation( _shader_model_gate_unlinked.id, "uCam" );
-   _uniform_model_gate_unlinked_uColour = glGetUniformLocation( _shader_model_gate_unlinked.id, "uColour" );
+static inline void shader_model_gate_unlinked_use(void);
+static inline void shader_model_gate_unlinked_use(void)
+{
+   glUseProgram(_shader_model_gate_unlinked.id);
 }
-#endif /* SHADER_model_gate_unlinked_H */
index 0ee6ad39f0aca1044922ebf3f6b28a79991cb35b..774d4c8f407906fb992c469e72cb61524abce750 100644 (file)
-#ifndef SHADER_model_menu_H
-#define SHADER_model_menu_H
-static void shader_model_menu_link(void);
-static void shader_model_menu_register(void);
-static struct vg_shader _shader_model_menu = {
-   .name = "model_menu",
-   .link = shader_model_menu_link,
-   .vs = 
+#pragma once
+#include "vg/vg_engine.h"
+extern struct vg_shader _shader_model_menu;
+extern GLuint _uniform_model_menu_uMdl;
+extern GLuint _uniform_model_menu_uPv;
+extern GLuint _uniform_model_menu_uPvmPrev;
+extern GLuint _uniform_model_menu_uTexMain;
+extern GLuint _uniform_model_menu_uColour;
+static inline void shader_model_menu_uMdl(m4x3f m)
 {
-.orig_file = "shaders/model.vs",
-.static_src = 
-"layout (location=0) in vec3 a_co;\n"
-"layout (location=1) in vec3 a_norm;\n"
-"layout (location=2) in vec2 a_uv;\n"
-"layout (location=3) in vec4 a_colour;\n"
-"layout (location=4) in vec4 a_weights;\n"
-"layout (location=5) in ivec4 a_groups;\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      9        0 \n"
-"\n"
-"uniform mat4x3 uMdl;\n"
-"uniform mat4 uPv;\n"
-"uniform mat4 uPvmPrev;\n"
-"\n"
-"out vec4 aColour;\n"
-"out vec2 aUv;\n"
-"out vec3 aNorm;\n"
-"out vec3 aCo;\n"
-"out vec3 aWorldCo;\n"
-"\n"
-"void main()\n"
-"{\n"
-"   vec3 world_pos0 = uMdl     * vec4( a_co, 1.0 );\n"
-"   vec4 vproj0     = uPv      * vec4( world_pos0, 1.0 );\n"
-"   vec4 vproj1     = uPvmPrev * vec4( a_co, 1.0 );\n"
-"\n"
-"   vs_motion_out( vproj0, vproj1 );\n"
-"\n"
-"   gl_Position = vproj0;\n"
-"   aWorldCo = world_pos0;\n"
-"   aColour = a_colour;\n"
-"   aUv = a_uv;\n"
-"   aNorm = normalize( mat3(uMdl) * a_norm );\n"
-"   aCo = a_co;\n"
-"}\n"
-""},
-   .fs = 
-{
-.orig_file = "shaders/model_menu.fs",
-.static_src = 
-"out vec4 FragColor;\n"
-"\n"
-"uniform sampler2D uTexMain;\n"
-"uniform vec4 uColour;\n"
-"\n"
-"in vec4 aColour;\n"
-"in vec2 aUv;\n"
-"in vec3 aNorm;\n"
-"in vec3 aCo;\n"
-"\n"
-"void main()\n"
-"{\n"
-"   vec4 diffuse = texture( uTexMain, aUv );\n"
-"\n"
-"   if( diffuse.a < 0.5 )\n"
-"      discard;\n"
-"\n"
-"   FragColor = vec4( diffuse.rgb, 1.0 ) * uColour;\n"
-"}\n"
-""},
-};
-
-static GLuint _uniform_model_menu_uMdl;
-static GLuint _uniform_model_menu_uPv;
-static GLuint _uniform_model_menu_uPvmPrev;
-static GLuint _uniform_model_menu_uTexMain;
-static GLuint _uniform_model_menu_uColour;
-static void shader_model_menu_uMdl(m4x3f m){
-   glUniformMatrix4x3fv(_uniform_model_menu_uMdl,1,GL_FALSE,(float*)m);
+   glUniformMatrix4x3fv(_uniform_model_menu_uMdl,1,GL_FALSE,(f32*)m);
 }
-static void shader_model_menu_uPv(m4x4f m){
-   glUniformMatrix4fv(_uniform_model_menu_uPv,1,GL_FALSE,(float*)m);
+static inline void shader_model_menu_uPv(m4x4f m)
+{
+   glUniformMatrix4fv(_uniform_model_menu_uPv,1,GL_FALSE,(f32*)m);
 }
-static void shader_model_menu_uPvmPrev(m4x4f m){
-   glUniformMatrix4fv(_uniform_model_menu_uPvmPrev,1,GL_FALSE,(float*)m);
+static inline void shader_model_menu_uPvmPrev(m4x4f m)
+{
+   glUniformMatrix4fv(_uniform_model_menu_uPvmPrev,1,GL_FALSE,(f32*)m);
 }
-static void shader_model_menu_uTexMain(int i){
+static inline void shader_model_menu_uTexMain(int i)
+{
    glUniform1i(_uniform_model_menu_uTexMain,i);
 }
-static void shader_model_menu_uColour(v4f v){
+static inline void shader_model_menu_uColour(v4f v)
+{
    glUniform4fv(_uniform_model_menu_uColour,1,v);
 }
-static void shader_model_menu_register(void){
-   vg_shader_register( &_shader_model_menu );
-}
-static void shader_model_menu_use(void){ glUseProgram(_shader_model_menu.id); }
-static void shader_model_menu_link(void){
-   _uniform_model_menu_uMdl = glGetUniformLocation( _shader_model_menu.id, "uMdl" );
-   _uniform_model_menu_uPv = glGetUniformLocation( _shader_model_menu.id, "uPv" );
-   _uniform_model_menu_uPvmPrev = glGetUniformLocation( _shader_model_menu.id, "uPvmPrev" );
-   _uniform_model_menu_uTexMain = glGetUniformLocation( _shader_model_menu.id, "uTexMain" );
-   _uniform_model_menu_uColour = glGetUniformLocation( _shader_model_menu.id, "uColour" );
+static inline void shader_model_menu_use(void);
+static inline void shader_model_menu_use(void)
+{
+   glUseProgram(_shader_model_menu.id);
 }
-#endif /* SHADER_model_menu_H */
index 88612b2bb7ac06a48729f3abd551d95d6175653f..534d6939add1db6e121b13aad467a9d14bcfc5a1 100644 (file)
-#ifndef SHADER_model_sky_H
-#define SHADER_model_sky_H
-static void shader_model_sky_link(void);
-static void shader_model_sky_register(void);
-static struct vg_shader _shader_model_sky = {
-   .name = "model_sky",
-   .link = shader_model_sky_link,
-   .vs = 
+#pragma once
+#include "vg/vg_engine.h"
+extern struct vg_shader _shader_model_sky;
+extern GLuint _uniform_model_sky_uMdl;
+extern GLuint _uniform_model_sky_uPv;
+extern GLuint _uniform_model_sky_uPvmPrev;
+extern GLuint _uniform_model_sky_uTexGarbage;
+extern GLuint _uniform_model_sky_g_world_depth;
+extern GLuint _uniform_model_sky_uLightsArray;
+extern GLuint _uniform_model_sky_uLightsIndex;
+static inline void shader_model_sky_uMdl(m4x3f m)
 {
-.orig_file = "shaders/model.vs",
-.static_src = 
-"layout (location=0) in vec3 a_co;\n"
-"layout (location=1) in vec3 a_norm;\n"
-"layout (location=2) in vec2 a_uv;\n"
-"layout (location=3) in vec4 a_colour;\n"
-"layout (location=4) in vec4 a_weights;\n"
-"layout (location=5) in ivec4 a_groups;\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      9        0 \n"
-"\n"
-"uniform mat4x3 uMdl;\n"
-"uniform mat4 uPv;\n"
-"uniform mat4 uPvmPrev;\n"
-"\n"
-"out vec4 aColour;\n"
-"out vec2 aUv;\n"
-"out vec3 aNorm;\n"
-"out vec3 aCo;\n"
-"out vec3 aWorldCo;\n"
-"\n"
-"void main()\n"
-"{\n"
-"   vec3 world_pos0 = uMdl     * vec4( a_co, 1.0 );\n"
-"   vec4 vproj0     = uPv      * vec4( world_pos0, 1.0 );\n"
-"   vec4 vproj1     = uPvmPrev * vec4( a_co, 1.0 );\n"
-"\n"
-"   vs_motion_out( vproj0, vproj1 );\n"
-"\n"
-"   gl_Position = vproj0;\n"
-"   aWorldCo = world_pos0;\n"
-"   aColour = a_colour;\n"
-"   aUv = a_uv;\n"
-"   aNorm = normalize( mat3(uMdl) * a_norm );\n"
-"   aCo = a_co;\n"
-"}\n"
-""},
-   .fs = 
-{
-.orig_file = "shaders/model_sky.fs",
-.static_src = 
-"uniform sampler2D uTexGarbage;\n"
-"\n"
-"in vec4 aColour;\n"
-"in vec2 aUv;\n"
-"in vec3 aNorm;\n"
-"in vec3 aCo;\n"
-"in vec3 aWorldCo;\n"
-"\n"
-"// Spooky!\n"
-"const vec3 uCamera = vec3(0.0);\n"
-"\n"
-"#line       1        1 \n"
-"// :D\n"
-"const float CLEARSKIES_LIGHT_DOT_MIN = 0.0;\n"
-"\n"
-"#line     13        0 \n"
-"#line       1        2 \n"
-"layout (location = 0) out vec4 oColour;\n"
-"\n"
-"// OpenGL wiki: Recommends do not use vec3 because of drivers. hence the v4s...\n"
-"layout (std140) uniform ub_world_lighting\n"
-"{\n"
-"   vec4 g_cube_min;\n"
-"   vec4 g_cube_inv_range;\n"
-"\n"
-"   vec4 g_water_plane;\n"
-"   vec4 g_depth_bounds;\n"
-"\n"
-"   vec4 g_daysky_colour;\n"
-"   vec4 g_nightsky_colour;\n"
-"   vec4 g_sunset_colour;\n"
-"   vec4 g_ambient_colour;\n"
-"   vec4 g_sunset_ambient;\n"
-"   vec4 g_sun_colour;\n"
-"   vec4 g_sun_dir;\n"
-"   vec4 g_board_0;\n"
-"   vec4 g_board_1;\n"
-"\n"
-"   float g_water_fog;\n"
-"   float g_time;\n"
-"   float g_realtime;\n"
-"   float g_shadow_length;\n"
-"   float g_shadow_spread;\n"
-"\n"
-"   float g_time_of_day;\n"
-"   float g_day_phase;\n"
-"   float g_sunset_phase;\n"
-"\n"
-"   int g_light_preview;\n"
-"   int g_shadow_samples;\n"
-"\n"
-"   int g_debug_indices;\n"
-"   int g_debug_complexity;\n"
-"};\n"
-"\n"
-"uniform sampler2D g_world_depth;\n"
-"uniform samplerBuffer uLightsArray;\n"
-"uniform usampler3D uLightsIndex;\n"
-"\n"
-"#line       1        1 \n"
-"//const vec3  DAYSKY_COLOUR   = vec3( 0.37, 0.54, 0.97 );\n"
-"//const vec3  NIGHTSKY_COLOUR = vec3( 0.03, 0.05, 0.20 );\n"
-"//const vec3  SUNSET_COLOUR   = vec3( 1.00, 0.32, 0.01 );\n"
-"//const vec3  AMBIENT_COLOUR  = vec3( 0.13, 0.17, 0.35 );\n"
-"//const vec3  SUNSET_AMBIENT  = vec3( 0.25, 0.17, 0.51 );\n"
-"//const vec3  SUN_COLOUR      = vec3( 1.10, 0.89, 0.35 );\n"
-"\n"
-"const float SUN_ANGLE       = 0.0001;\n"
-"const float PI              = 3.14159265358979323846264;\n"
-"\n"
-"//struct world_info\n"
-"//{\n"
-"//   float time,\n"
-"//         time_of_day,\n"
-"//         day_phase,\n"
-"//         sunset_phase;\n"
-"//   \n"
-"//   vec3 sun_dir;\n"
-"//};\n"
-"\n"
-"vec3 rand33(vec3 p3)\n"
-"{\n"
-"      p3 = fract(p3 * vec3(.1031, .1030, .0973));\n"
-"   p3 += dot(p3, p3.yxz+33.33);\n"
-"   return fract((p3.xxy + p3.yxx)*p3.zyx);\n"
-"}\n"
-"\n"
-"float stars( vec3 rd, float rr, float size ){\n"
-"   vec3 co = rd * rr;\n"
-"\n"
-"   float a = atan(co.y, length(co.xz)) + 4.0 * PI;\n"
-"\n"
-"   float spaces = 1.0 / rr;\n"
-"   size = (rr * 0.0015) * fwidth(a) * 1000.0 * size;\n"
-"   a -= mod(a, spaces) - spaces * 0.5;\n"
-"\n"
-"   float count = floor(sqrt(pow(rr, 2.0) * (1.0 - pow(sin(a), 2.0))) * 3.0);\n"
-"   \n"
-"   float plane = atan(co.z, co.x) + 4.0 * PI;\n"
-"   plane = plane - mod(plane, PI / count);\n"
-"\n"
-"   vec2 delta = rand33(vec3(plane, a, 0.0)).xy;\n"
-"\n"
-"   float level = sin(a + spaces * (delta.y - 0.5) * (1.0 - size)) * rr;\n"
-"   float ydist = sqrt(rr * rr - level * level);\n"
-"   float angle = plane + (PI * (delta.x * (1.0-size) + size * 0.5) / count);\n"
-"   vec3 center = vec3(cos(angle) * ydist, level, sin(angle) * ydist);\n"
-"   float star = smoothstep(size, 0.0, distance(center, co));\n"
-"   return star;\n"
-"}\n"
-"\n"
-"float luminance( vec3 v )\n"
-"{\n"
-"   return dot( v, vec3(0.2126, 0.7152, 0.0722) );\n"
-"}\n"
-"\n"
-"vec3 clearskies_ambient( vec3 dir )\n"
-"{\n"
-"   float sun_azimuth  = g_sunset_phase * (dot( dir.xz, g_sun_dir.xz )*0.4+0.6);\n"
-"   float sky_gradient = dir.y;\n"
-"   \n"
-"   /* Blend phase colours */\n"
-"   vec3 ambient  = g_daysky_colour.rgb   * (g_day_phase-g_sunset_phase*0.1);\n"
-"        ambient += g_sunset_colour.rgb   * (1.0-dir.y*0.5)*sun_azimuth;\n"
-"        ambient += g_nightsky_colour.rgb * (1.0-g_day_phase);\n"
-"   \n"
-"   /* Add gradient */\n"
-"        ambient -= sky_gradient * luminance(ambient);\n"
-"        \n"
-"   return ambient;\n"
-"}\n"
-"\n"
-"vec3 clearskies_sky( vec3 ray_dir )\n"
-"{\n"
-"   ray_dir.y = abs( ray_dir.y );\n"
-"   vec3 sky_colour  = clearskies_ambient( ray_dir );\n"
-"   \n"
-"   /* Sun */\n"
-"   float sun_theta  = dot( ray_dir, g_sun_dir.xyz );\n"
-"   float sun_size   = max( 0.0, sun_theta * 0.5 + 0.5 + SUN_ANGLE );\n"
-"   float sun_shape  = pow( sun_size, 2000.0 );\n"
-"         sun_shape += sun_size * max(g_sun_dir.y,0.0) * 0.5;\n"
-"         \n"
-"   vec3 sun_colour  = mix( vec3(1.0), g_sunset_colour.rgb, g_sunset_phase*0.5 );\n"
-"        sun_colour *= sun_shape;\n"
-"\n"
-"   \n"
-"   float star = 0.0;\n"
-"   float star_blend = 10.0*max(0.0,(1.0-g_day_phase*2.0));\n"
-"\n"
-"   if( star_blend > 0.001 ){\n"
-"      for( float j = 1.0; j <= 4.1; j += 1.0 ){\n"
-"         float m = mix(0.6, 0.9, smoothstep(1.0, 2.0, j));\n"
-"         star += stars( ray_dir, 1.94 * pow( 1.64, j ), m ) * (1.0/pow(4.0, j));\n"
-"      }\n"
-"   }\n"
-"   \n"
-"   vec3 composite   = sky_colour + sun_colour + star*star_blend;\n"
-"   return composite;\n"
-"}\n"
-"\n"
-"vec3 clearskies_lighting( vec3 normal, float shadow, vec3 halfview )\n"
-"{\n"
-"   float fresnel = 1.0 - abs(dot(normal,halfview));\n"
-"\n"
-"   vec3  reflect_colour = mix( g_daysky_colour.rgb, g_sunset_colour.rgb, \n"
-"                               g_sunset_phase );\n"
-"\n"
-"   vec3  sky_reflection = 0.5 * fresnel * reflect_colour;\n"
-"   vec3  light_sun      = max( CLEARSKIES_LIGHT_DOT_MIN, \n"
-"                               dot(normal,g_sun_dir.xyz)*0.75+0.25\n"
-"                           ) * g_sun_colour.rgb * g_day_phase;\n"
-"\n"
-"   float scaled_shadow = max( shadow, 1.0 - max(g_sun_dir.y,0.0) );\n"
-"   vec3 ambient = mix( g_ambient_colour.rgb, g_sunset_ambient.rgb, \n"
-"                       g_sunset_phase );\n"
-"\n"
-"   return ambient + (light_sun + sky_reflection) * shadow;\n"
-"}\n"
-"\n"
-"#line     44        0 \n"
-"\n"
-"float world_depth_sample( vec3 pos )\n"
-"{\n"
-"   vec2 depth_coord = (pos.xz - g_depth_bounds.xy) * g_depth_bounds.zw; \n"
-"   return texture( g_world_depth, depth_coord ).r;\n"
-"}\n"
-"\n"
-"float world_water_depth( vec3 pos )\n"
-"{\n"
-"   float ref_depth = g_water_plane.y*g_water_plane.w;\n"
-"   return world_depth_sample( pos ) - ref_depth;\n"
-"}\n"
-"\n"
-"float shadow_sample( vec3 co ){\n"
-"   float height_sample = world_depth_sample( co );\n"
-"\n"
-"   float fdelta = height_sample - co.y;\n"
-"   return clamp( fdelta, 0.2, 0.4 )-0.2;\n"
-"}\n"
-"\n"
-"float newlight_compute_sun_shadow( vec3 co, vec3 dir ){\n"
-"   if( g_shadow_samples == 0 ){\n"
-"      return 1.0;\n"
-"   }\n"
-"\n"
-"   float fspread = g_shadow_spread;\n"
-"   float flength = g_shadow_length;\n"
-"\n"
-"   float famt = 0.0;\n"
-"   famt += shadow_sample(co+(dir+vec3(-0.56,0.55, 0.30)*fspread)*flength*0.1);\n"
-"   famt += shadow_sample(co+(dir+vec3( 0.80,0.68, 0.34)*fspread)*flength*0.2);\n"
-"   famt += shadow_sample(co+(dir+vec3( 0.78,0.07,-0.06)*fspread)*flength*0.3);\n"
-"   famt += shadow_sample(co+(dir+vec3(-0.59,0.07,-0.42)*fspread)*flength*0.4);\n"
-"\n"
-"   //famt+=shadow_sample(co+(dir+vec3(-0.790,-0.933,-0.875)*fspread)*flength*0.5);\n"
-"   //famt+=shadow_sample(co+(dir+vec3( 0.807,-0.690, 0.472)*fspread)*flength*0.6);\n"
-"   //famt+=shadow_sample(co+(dir+vec3( 0.522,-0.379, 0.350)*fspread)*flength*0.7);\n"
-"   //famt+=shadow_sample(co+(dir+vec3( 0.483, 0.201, 0.306)*fspread)*flength*0.8);\n"
-"\n"
-"   return 1.0 - famt;\n"
-"}\n"
-"\n"
-"float newlight_specular( vec3 wnormal, vec3 dir, vec3 halfview, float exponent )\n"
-"{\n"
-"   vec3 specdir = reflect( -dir, wnormal );\n"
-"   return pow(max(dot( halfview, specdir ), 0.0), exponent);\n"
-"}\n"
-"\n"
-"vec3 scene_apply_fog( vec3 vfrag, vec3 colour, float fdist ){\n"
-"   float dist = pow(fdist*0.0010,0.78);\n"
-"   return mix( vfrag, colour, min( 1.0, dist ) );\n"
-"}\n"
-"\n"
-"vec3 scene_calculate_light( int light_index, \n"
-"                            vec3 halfview, vec3 co, vec3 normal )\n"
-"{\n"
-"   vec4 light_colour = texelFetch( uLightsArray, light_index+0 );\n"
-"   vec4 light_co     = texelFetch( uLightsArray, light_index+1 );\n"
-"   vec4 light_dir    = texelFetch( uLightsArray, light_index+2 );\n"
-"\n"
-"   vec3 light_delta = light_co.xyz-co;\n"
-"   float dist2 = dot(light_delta,light_delta);\n"
-"\n"
-"   light_delta = normalize( light_delta );\n"
-"\n"
-"   float quadratic = dist2*100.0;\n"
-"   float attenuation  = 1.0/( 1.0 + quadratic );\n"
-"         attenuation *= max( dot( light_delta, normal ), 0.0 );\n"
-"\n"
-"   float falloff = max( 0.0, 1.0-(dist2*light_co.w) );\n"
-"\n"
-"   if( light_dir.w < 0.999999 ){\n"
-"      float spot_theta = max( 0.0, dot( light_delta, -light_dir.xyz ) );\n"
-"      falloff *= max( 0.0, (spot_theta - light_dir.w) / (1.0-light_dir.w) );\n"
-"   }\n"
-"\n"
-"   return light_colour.rgb * attenuation * falloff \n"
-"            * step( g_day_phase, light_colour.w );\n"
-"}\n"
-"\n"
-"vec3 scene_calculate_packed_light_patch( uint packed_index, \n"
-"                                         vec3 halfview, vec3 co, vec3 normal )\n"
-"{\n"
-"   uint light_count = packed_index & 0x3u;\n"
-"\n"
-"   vec3 l = vec3(0.0);\n"
-"\n"
-"   if( light_count >= 1u ){\n"
-"      int index_0 = int( ((packed_index >>  2u) & 0x3ffu) * 3u );\n"
-"      int index_1 = int( ((packed_index >> 12u) & 0x3ffu) * 3u );\n"
-"      int index_2 = int( ((packed_index >> 22u) & 0x3ffu) * 3u );\n"
-"\n"
-"      l += scene_calculate_light( index_0, halfview, co, normal );\n"
-"\n"
-"      if( light_count >= 2u ){\n"
-"         l += scene_calculate_light( index_1, halfview, co, normal );\n"
-"\n"
-"         if( light_count >= 3u ){\n"
-"            l += scene_calculate_light( index_2, halfview, co, normal );\n"
-"         }\n"
-"      }\n"
-"   }\n"
-"\n"
-"   return l;\n"
-"}\n"
-"\n"
-"vec3 world_compute_lighting( vec3 diffuse, vec3 normal, vec3 co,\n"
-"                             float light_mask )\n"
-"{\n"
-"   if( g_light_preview == 1 )\n"
-"      diffuse = vec3(0.75);\n"
-"\n"
-"   // Lighting\n"
-"   vec3 halfview = uCamera - co;\n"
-"   float fdist = length(halfview);\n"
-"   halfview /= fdist;\n"
-"\n"
-"   float world_shadow = newlight_compute_sun_shadow( \n"
-"               co, g_sun_dir.xyz * (1.0/(max(g_sun_dir.y,0.0)+0.2)) );\n"
-"\n"
-"   vec3 total_light = clearskies_lighting( \n"
-"                           normal, min( light_mask, world_shadow ), halfview );\n"
-"\n"
-"   vec3 cube_coord = (co - g_cube_min.xyz) * g_cube_inv_range.xyz;\n"
-"        cube_coord = floor( cube_coord );\n"
-"\n"
-"   if( g_debug_indices == 1 )\n"
-"   {\n"
-"      return rand33(cube_coord);\n"
-"   }\n"
-"\n"
-"   if( g_debug_complexity == 1 )\n"
-"   {\n"
-"      ivec3 coord = ivec3( cube_coord );\n"
-"      uvec4 index_sample = texelFetch( uLightsIndex, coord, 0 );\n"
-"\n"
-"      uint light_count = (index_sample.x & 0x3u) + (index_sample.y & 0x3u);\n"
-"      return vec3( float(light_count)*(1.0/6.0), 0.0, 0.5 );\n"
-"   }\n"
-"\n"
-"   // FIXME: this coord should absolutely must be clamped!\n"
-"   \n"
-"   ivec3 coord = ivec3( cube_coord );\n"
-"   uvec4 index_sample = texelFetch( uLightsIndex, coord, 0 );\n"
-"\n"
-"   total_light += \n"
-"      scene_calculate_packed_light_patch( index_sample.x,\n"
-"                                          halfview, co, normal ) \n"
-"                                          * light_mask;\n"
-"   total_light += \n"
-"      scene_calculate_packed_light_patch( index_sample.y,\n"
-"                                          halfview, co, normal )\n"
-"                                          * light_mask;\n"
-"\n"
-"   // Take a section of the sky function to give us a matching fog colour\n"
-"\n"
-"   vec3 fog_colour  = clearskies_ambient( -halfview );\n"
-"   float sun_theta  = dot( -halfview, g_sun_dir.xyz );\n"
-"   float sun_size   = max( 0.0, sun_theta * 0.5 + 0.5 );\n"
-"   float sun_shape  = sun_size * max(g_sun_dir.y,0.0) * 0.5;\n"
-"         \n"
-"   vec3 sun_colour  = mix( vec3(1.0), g_sunset_colour.rgb, g_sunset_phase*0.5 );\n"
-"        sun_colour *= sun_shape;\n"
-"\n"
-"   fog_colour += sun_colour;\n"
-"   return scene_apply_fog( diffuse * total_light, fog_colour, fdist );\n"
-"}\n"
-"\n"
-"#line     14        0 \n"
-"#line       1        3 \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     15        0 \n"
-"\n"
-"void main()\n"
-"{\n"
-"   compute_motion_vectors();\n"
-"\n"
-"   vec3 rd = normalize(aNorm);\n"
-"\n"
-"   float fmove = g_time * 5.0;\n"
-"   vec2 cloudplane = (rd.xz / (rd.y*sign(rd.y))) * 0.025;\n"
-"   vec4 clouds1 = texture( uTexGarbage, cloudplane + vec2(0.1,0.4)*fmove*2.0 );\n"
-"   vec4 clouds2 = texture( uTexGarbage, cloudplane*2.0 + vec2(0.3,0.1)*fmove );\n"
-"\n"
-"   float cloud_d = max(clouds1.b*clouds2.r -0.2 - clouds2.g*0.4,0.0);\n"
-"   float cloud_e = pow(cloud_d,1.5)*pow(abs(rd.y),0.3)*2.0;\n"
-"\n"
-"   oColour = vec4( clearskies_sky( -rd ) ,1.0);\n"
-"\n"
-"   vec3 cloud_colour = mix( mix(g_nightsky_colour.rgb,vec3(1.0),g_day_phase), \n"
-"                                g_sunset_colour.rgb, g_sunset_phase );\n"
-"\n"
-"   oColour.rgb = mix( oColour.rgb, cloud_colour, cloud_e );\n"
-"}\n"
-""},
-};
-
-static GLuint _uniform_model_sky_uMdl;
-static GLuint _uniform_model_sky_uPv;
-static GLuint _uniform_model_sky_uPvmPrev;
-static GLuint _uniform_model_sky_uTexGarbage;
-static GLuint _uniform_model_sky_g_world_depth;
-static GLuint _uniform_model_sky_uLightsArray;
-static GLuint _uniform_model_sky_uLightsIndex;
-static void shader_model_sky_uMdl(m4x3f m){
-   glUniformMatrix4x3fv(_uniform_model_sky_uMdl,1,GL_FALSE,(float*)m);
+   glUniformMatrix4x3fv(_uniform_model_sky_uMdl,1,GL_FALSE,(f32*)m);
 }
-static void shader_model_sky_uPv(m4x4f m){
-   glUniformMatrix4fv(_uniform_model_sky_uPv,1,GL_FALSE,(float*)m);
+static inline void shader_model_sky_uPv(m4x4f m)
+{
+   glUniformMatrix4fv(_uniform_model_sky_uPv,1,GL_FALSE,(f32*)m);
 }
-static void shader_model_sky_uPvmPrev(m4x4f m){
-   glUniformMatrix4fv(_uniform_model_sky_uPvmPrev,1,GL_FALSE,(float*)m);
+static inline void shader_model_sky_uPvmPrev(m4x4f m)
+{
+   glUniformMatrix4fv(_uniform_model_sky_uPvmPrev,1,GL_FALSE,(f32*)m);
 }
-static void shader_model_sky_uTexGarbage(int i){
+static inline void shader_model_sky_uTexGarbage(int i)
+{
    glUniform1i(_uniform_model_sky_uTexGarbage,i);
 }
-static void shader_model_sky_g_world_depth(int i){
+static inline void shader_model_sky_g_world_depth(int i)
+{
    glUniform1i(_uniform_model_sky_g_world_depth,i);
 }
-static void shader_model_sky_register(void){
-   vg_shader_register( &_shader_model_sky );
-}
-static void shader_model_sky_use(void){ glUseProgram(_shader_model_sky.id); }
-static void shader_model_sky_link(void){
-   _uniform_model_sky_uMdl = glGetUniformLocation( _shader_model_sky.id, "uMdl" );
-   _uniform_model_sky_uPv = glGetUniformLocation( _shader_model_sky.id, "uPv" );
-   _uniform_model_sky_uPvmPrev = glGetUniformLocation( _shader_model_sky.id, "uPvmPrev" );
-   _uniform_model_sky_uTexGarbage = glGetUniformLocation( _shader_model_sky.id, "uTexGarbage" );
-   _uniform_model_sky_g_world_depth = glGetUniformLocation( _shader_model_sky.id, "g_world_depth" );
-   _uniform_model_sky_uLightsArray = glGetUniformLocation( _shader_model_sky.id, "uLightsArray" );
-   _uniform_model_sky_uLightsIndex = glGetUniformLocation( _shader_model_sky.id, "uLightsIndex" );
+static inline void shader_model_sky_use(void);
+static inline void shader_model_sky_use(void)
+{
+   glUseProgram(_shader_model_sky.id);
 }
-#endif /* SHADER_model_sky_H */
index c96f2c4bb19531453a7f51ebec84f5018ef97124..474d0728fb62cf598f691cf2b85caa38fb08387b 100644 (file)
-#ifndef SHADER_model_sky_space_H
-#define SHADER_model_sky_space_H
-static void shader_model_sky_space_link(void);
-static void shader_model_sky_space_register(void);
-static struct vg_shader _shader_model_sky_space = {
-   .name = "model_sky_space",
-   .link = shader_model_sky_space_link,
-   .vs = 
+#pragma once
+#include "vg/vg_engine.h"
+extern struct vg_shader _shader_model_sky_space;
+extern GLuint _uniform_model_sky_space_uMdl;
+extern GLuint _uniform_model_sky_space_uPv;
+extern GLuint _uniform_model_sky_space_uPvmPrev;
+extern GLuint _uniform_model_sky_space_uTexGarbage;
+extern GLuint _uniform_model_sky_space_g_world_depth;
+extern GLuint _uniform_model_sky_space_uLightsArray;
+extern GLuint _uniform_model_sky_space_uLightsIndex;
+static inline void shader_model_sky_space_uMdl(m4x3f m)
 {
-.orig_file = "shaders/model.vs",
-.static_src = 
-"layout (location=0) in vec3 a_co;\n"
-"layout (location=1) in vec3 a_norm;\n"
-"layout (location=2) in vec2 a_uv;\n"
-"layout (location=3) in vec4 a_colour;\n"
-"layout (location=4) in vec4 a_weights;\n"
-"layout (location=5) in ivec4 a_groups;\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      9        0 \n"
-"\n"
-"uniform mat4x3 uMdl;\n"
-"uniform mat4 uPv;\n"
-"uniform mat4 uPvmPrev;\n"
-"\n"
-"out vec4 aColour;\n"
-"out vec2 aUv;\n"
-"out vec3 aNorm;\n"
-"out vec3 aCo;\n"
-"out vec3 aWorldCo;\n"
-"\n"
-"void main()\n"
-"{\n"
-"   vec3 world_pos0 = uMdl     * vec4( a_co, 1.0 );\n"
-"   vec4 vproj0     = uPv      * vec4( world_pos0, 1.0 );\n"
-"   vec4 vproj1     = uPvmPrev * vec4( a_co, 1.0 );\n"
-"\n"
-"   vs_motion_out( vproj0, vproj1 );\n"
-"\n"
-"   gl_Position = vproj0;\n"
-"   aWorldCo = world_pos0;\n"
-"   aColour = a_colour;\n"
-"   aUv = a_uv;\n"
-"   aNorm = normalize( mat3(uMdl) * a_norm );\n"
-"   aCo = a_co;\n"
-"}\n"
-""},
-   .fs = 
-{
-.orig_file = "shaders/model_sky_space.fs",
-.static_src = 
-"uniform sampler2D uTexGarbage;\n"
-"\n"
-"in vec4 aColour;\n"
-"in vec2 aUv;\n"
-"in vec3 aNorm;\n"
-"in vec3 aCo;\n"
-"in vec3 aWorldCo;\n"
-"\n"
-"// Spooky!\n"
-"const vec3 uCamera = vec3(0.0);\n"
-"\n"
-"#line       1        1 \n"
-"// :D\n"
-"const float CLEARSKIES_LIGHT_DOT_MIN = 0.0;\n"
-"\n"
-"#line     13        0 \n"
-"#line       1        2 \n"
-"layout (location = 0) out vec4 oColour;\n"
-"\n"
-"// OpenGL wiki: Recommends do not use vec3 because of drivers. hence the v4s...\n"
-"layout (std140) uniform ub_world_lighting\n"
-"{\n"
-"   vec4 g_cube_min;\n"
-"   vec4 g_cube_inv_range;\n"
-"\n"
-"   vec4 g_water_plane;\n"
-"   vec4 g_depth_bounds;\n"
-"\n"
-"   vec4 g_daysky_colour;\n"
-"   vec4 g_nightsky_colour;\n"
-"   vec4 g_sunset_colour;\n"
-"   vec4 g_ambient_colour;\n"
-"   vec4 g_sunset_ambient;\n"
-"   vec4 g_sun_colour;\n"
-"   vec4 g_sun_dir;\n"
-"   vec4 g_board_0;\n"
-"   vec4 g_board_1;\n"
-"\n"
-"   float g_water_fog;\n"
-"   float g_time;\n"
-"   float g_realtime;\n"
-"   float g_shadow_length;\n"
-"   float g_shadow_spread;\n"
-"\n"
-"   float g_time_of_day;\n"
-"   float g_day_phase;\n"
-"   float g_sunset_phase;\n"
-"\n"
-"   int g_light_preview;\n"
-"   int g_shadow_samples;\n"
-"\n"
-"   int g_debug_indices;\n"
-"   int g_debug_complexity;\n"
-"};\n"
-"\n"
-"uniform sampler2D g_world_depth;\n"
-"uniform samplerBuffer uLightsArray;\n"
-"uniform usampler3D uLightsIndex;\n"
-"\n"
-"#line       1        1 \n"
-"//const vec3  DAYSKY_COLOUR   = vec3( 0.37, 0.54, 0.97 );\n"
-"//const vec3  NIGHTSKY_COLOUR = vec3( 0.03, 0.05, 0.20 );\n"
-"//const vec3  SUNSET_COLOUR   = vec3( 1.00, 0.32, 0.01 );\n"
-"//const vec3  AMBIENT_COLOUR  = vec3( 0.13, 0.17, 0.35 );\n"
-"//const vec3  SUNSET_AMBIENT  = vec3( 0.25, 0.17, 0.51 );\n"
-"//const vec3  SUN_COLOUR      = vec3( 1.10, 0.89, 0.35 );\n"
-"\n"
-"const float SUN_ANGLE       = 0.0001;\n"
-"const float PI              = 3.14159265358979323846264;\n"
-"\n"
-"//struct world_info\n"
-"//{\n"
-"//   float time,\n"
-"//         time_of_day,\n"
-"//         day_phase,\n"
-"//         sunset_phase;\n"
-"//   \n"
-"//   vec3 sun_dir;\n"
-"//};\n"
-"\n"
-"vec3 rand33(vec3 p3)\n"
-"{\n"
-"      p3 = fract(p3 * vec3(.1031, .1030, .0973));\n"
-"   p3 += dot(p3, p3.yxz+33.33);\n"
-"   return fract((p3.xxy + p3.yxx)*p3.zyx);\n"
-"}\n"
-"\n"
-"float stars( vec3 rd, float rr, float size ){\n"
-"   vec3 co = rd * rr;\n"
-"\n"
-"   float a = atan(co.y, length(co.xz)) + 4.0 * PI;\n"
-"\n"
-"   float spaces = 1.0 / rr;\n"
-"   size = (rr * 0.0015) * fwidth(a) * 1000.0 * size;\n"
-"   a -= mod(a, spaces) - spaces * 0.5;\n"
-"\n"
-"   float count = floor(sqrt(pow(rr, 2.0) * (1.0 - pow(sin(a), 2.0))) * 3.0);\n"
-"   \n"
-"   float plane = atan(co.z, co.x) + 4.0 * PI;\n"
-"   plane = plane - mod(plane, PI / count);\n"
-"\n"
-"   vec2 delta = rand33(vec3(plane, a, 0.0)).xy;\n"
-"\n"
-"   float level = sin(a + spaces * (delta.y - 0.5) * (1.0 - size)) * rr;\n"
-"   float ydist = sqrt(rr * rr - level * level);\n"
-"   float angle = plane + (PI * (delta.x * (1.0-size) + size * 0.5) / count);\n"
-"   vec3 center = vec3(cos(angle) * ydist, level, sin(angle) * ydist);\n"
-"   float star = smoothstep(size, 0.0, distance(center, co));\n"
-"   return star;\n"
-"}\n"
-"\n"
-"float luminance( vec3 v )\n"
-"{\n"
-"   return dot( v, vec3(0.2126, 0.7152, 0.0722) );\n"
-"}\n"
-"\n"
-"vec3 clearskies_ambient( vec3 dir )\n"
-"{\n"
-"   float sun_azimuth  = g_sunset_phase * (dot( dir.xz, g_sun_dir.xz )*0.4+0.6);\n"
-"   float sky_gradient = dir.y;\n"
-"   \n"
-"   /* Blend phase colours */\n"
-"   vec3 ambient  = g_daysky_colour.rgb   * (g_day_phase-g_sunset_phase*0.1);\n"
-"        ambient += g_sunset_colour.rgb   * (1.0-dir.y*0.5)*sun_azimuth;\n"
-"        ambient += g_nightsky_colour.rgb * (1.0-g_day_phase);\n"
-"   \n"
-"   /* Add gradient */\n"
-"        ambient -= sky_gradient * luminance(ambient);\n"
-"        \n"
-"   return ambient;\n"
-"}\n"
-"\n"
-"vec3 clearskies_sky( vec3 ray_dir )\n"
-"{\n"
-"   ray_dir.y = abs( ray_dir.y );\n"
-"   vec3 sky_colour  = clearskies_ambient( ray_dir );\n"
-"   \n"
-"   /* Sun */\n"
-"   float sun_theta  = dot( ray_dir, g_sun_dir.xyz );\n"
-"   float sun_size   = max( 0.0, sun_theta * 0.5 + 0.5 + SUN_ANGLE );\n"
-"   float sun_shape  = pow( sun_size, 2000.0 );\n"
-"         sun_shape += sun_size * max(g_sun_dir.y,0.0) * 0.5;\n"
-"         \n"
-"   vec3 sun_colour  = mix( vec3(1.0), g_sunset_colour.rgb, g_sunset_phase*0.5 );\n"
-"        sun_colour *= sun_shape;\n"
-"\n"
-"   \n"
-"   float star = 0.0;\n"
-"   float star_blend = 10.0*max(0.0,(1.0-g_day_phase*2.0));\n"
-"\n"
-"   if( star_blend > 0.001 ){\n"
-"      for( float j = 1.0; j <= 4.1; j += 1.0 ){\n"
-"         float m = mix(0.6, 0.9, smoothstep(1.0, 2.0, j));\n"
-"         star += stars( ray_dir, 1.94 * pow( 1.64, j ), m ) * (1.0/pow(4.0, j));\n"
-"      }\n"
-"   }\n"
-"   \n"
-"   vec3 composite   = sky_colour + sun_colour + star*star_blend;\n"
-"   return composite;\n"
-"}\n"
-"\n"
-"vec3 clearskies_lighting( vec3 normal, float shadow, vec3 halfview )\n"
-"{\n"
-"   float fresnel = 1.0 - abs(dot(normal,halfview));\n"
-"\n"
-"   vec3  reflect_colour = mix( g_daysky_colour.rgb, g_sunset_colour.rgb, \n"
-"                               g_sunset_phase );\n"
-"\n"
-"   vec3  sky_reflection = 0.5 * fresnel * reflect_colour;\n"
-"   vec3  light_sun      = max( CLEARSKIES_LIGHT_DOT_MIN, \n"
-"                               dot(normal,g_sun_dir.xyz)*0.75+0.25\n"
-"                           ) * g_sun_colour.rgb * g_day_phase;\n"
-"\n"
-"   float scaled_shadow = max( shadow, 1.0 - max(g_sun_dir.y,0.0) );\n"
-"   vec3 ambient = mix( g_ambient_colour.rgb, g_sunset_ambient.rgb, \n"
-"                       g_sunset_phase );\n"
-"\n"
-"   return ambient + (light_sun + sky_reflection) * shadow;\n"
-"}\n"
-"\n"
-"#line     44        0 \n"
-"\n"
-"float world_depth_sample( vec3 pos )\n"
-"{\n"
-"   vec2 depth_coord = (pos.xz - g_depth_bounds.xy) * g_depth_bounds.zw; \n"
-"   return texture( g_world_depth, depth_coord ).r;\n"
-"}\n"
-"\n"
-"float world_water_depth( vec3 pos )\n"
-"{\n"
-"   float ref_depth = g_water_plane.y*g_water_plane.w;\n"
-"   return world_depth_sample( pos ) - ref_depth;\n"
-"}\n"
-"\n"
-"float shadow_sample( vec3 co ){\n"
-"   float height_sample = world_depth_sample( co );\n"
-"\n"
-"   float fdelta = height_sample - co.y;\n"
-"   return clamp( fdelta, 0.2, 0.4 )-0.2;\n"
-"}\n"
-"\n"
-"float newlight_compute_sun_shadow( vec3 co, vec3 dir ){\n"
-"   if( g_shadow_samples == 0 ){\n"
-"      return 1.0;\n"
-"   }\n"
-"\n"
-"   float fspread = g_shadow_spread;\n"
-"   float flength = g_shadow_length;\n"
-"\n"
-"   float famt = 0.0;\n"
-"   famt += shadow_sample(co+(dir+vec3(-0.56,0.55, 0.30)*fspread)*flength*0.1);\n"
-"   famt += shadow_sample(co+(dir+vec3( 0.80,0.68, 0.34)*fspread)*flength*0.2);\n"
-"   famt += shadow_sample(co+(dir+vec3( 0.78,0.07,-0.06)*fspread)*flength*0.3);\n"
-"   famt += shadow_sample(co+(dir+vec3(-0.59,0.07,-0.42)*fspread)*flength*0.4);\n"
-"\n"
-"   //famt+=shadow_sample(co+(dir+vec3(-0.790,-0.933,-0.875)*fspread)*flength*0.5);\n"
-"   //famt+=shadow_sample(co+(dir+vec3( 0.807,-0.690, 0.472)*fspread)*flength*0.6);\n"
-"   //famt+=shadow_sample(co+(dir+vec3( 0.522,-0.379, 0.350)*fspread)*flength*0.7);\n"
-"   //famt+=shadow_sample(co+(dir+vec3( 0.483, 0.201, 0.306)*fspread)*flength*0.8);\n"
-"\n"
-"   return 1.0 - famt;\n"
-"}\n"
-"\n"
-"float newlight_specular( vec3 wnormal, vec3 dir, vec3 halfview, float exponent )\n"
-"{\n"
-"   vec3 specdir = reflect( -dir, wnormal );\n"
-"   return pow(max(dot( halfview, specdir ), 0.0), exponent);\n"
-"}\n"
-"\n"
-"vec3 scene_apply_fog( vec3 vfrag, vec3 colour, float fdist ){\n"
-"   float dist = pow(fdist*0.0010,0.78);\n"
-"   return mix( vfrag, colour, min( 1.0, dist ) );\n"
-"}\n"
-"\n"
-"vec3 scene_calculate_light( int light_index, \n"
-"                            vec3 halfview, vec3 co, vec3 normal )\n"
-"{\n"
-"   vec4 light_colour = texelFetch( uLightsArray, light_index+0 );\n"
-"   vec4 light_co     = texelFetch( uLightsArray, light_index+1 );\n"
-"   vec4 light_dir    = texelFetch( uLightsArray, light_index+2 );\n"
-"\n"
-"   vec3 light_delta = light_co.xyz-co;\n"
-"   float dist2 = dot(light_delta,light_delta);\n"
-"\n"
-"   light_delta = normalize( light_delta );\n"
-"\n"
-"   float quadratic = dist2*100.0;\n"
-"   float attenuation  = 1.0/( 1.0 + quadratic );\n"
-"         attenuation *= max( dot( light_delta, normal ), 0.0 );\n"
-"\n"
-"   float falloff = max( 0.0, 1.0-(dist2*light_co.w) );\n"
-"\n"
-"   if( light_dir.w < 0.999999 ){\n"
-"      float spot_theta = max( 0.0, dot( light_delta, -light_dir.xyz ) );\n"
-"      falloff *= max( 0.0, (spot_theta - light_dir.w) / (1.0-light_dir.w) );\n"
-"   }\n"
-"\n"
-"   return light_colour.rgb * attenuation * falloff \n"
-"            * step( g_day_phase, light_colour.w );\n"
-"}\n"
-"\n"
-"vec3 scene_calculate_packed_light_patch( uint packed_index, \n"
-"                                         vec3 halfview, vec3 co, vec3 normal )\n"
-"{\n"
-"   uint light_count = packed_index & 0x3u;\n"
-"\n"
-"   vec3 l = vec3(0.0);\n"
-"\n"
-"   if( light_count >= 1u ){\n"
-"      int index_0 = int( ((packed_index >>  2u) & 0x3ffu) * 3u );\n"
-"      int index_1 = int( ((packed_index >> 12u) & 0x3ffu) * 3u );\n"
-"      int index_2 = int( ((packed_index >> 22u) & 0x3ffu) * 3u );\n"
-"\n"
-"      l += scene_calculate_light( index_0, halfview, co, normal );\n"
-"\n"
-"      if( light_count >= 2u ){\n"
-"         l += scene_calculate_light( index_1, halfview, co, normal );\n"
-"\n"
-"         if( light_count >= 3u ){\n"
-"            l += scene_calculate_light( index_2, halfview, co, normal );\n"
-"         }\n"
-"      }\n"
-"   }\n"
-"\n"
-"   return l;\n"
-"}\n"
-"\n"
-"vec3 world_compute_lighting( vec3 diffuse, vec3 normal, vec3 co,\n"
-"                             float light_mask )\n"
-"{\n"
-"   if( g_light_preview == 1 )\n"
-"      diffuse = vec3(0.75);\n"
-"\n"
-"   // Lighting\n"
-"   vec3 halfview = uCamera - co;\n"
-"   float fdist = length(halfview);\n"
-"   halfview /= fdist;\n"
-"\n"
-"   float world_shadow = newlight_compute_sun_shadow( \n"
-"               co, g_sun_dir.xyz * (1.0/(max(g_sun_dir.y,0.0)+0.2)) );\n"
-"\n"
-"   vec3 total_light = clearskies_lighting( \n"
-"                           normal, min( light_mask, world_shadow ), halfview );\n"
-"\n"
-"   vec3 cube_coord = (co - g_cube_min.xyz) * g_cube_inv_range.xyz;\n"
-"        cube_coord = floor( cube_coord );\n"
-"\n"
-"   if( g_debug_indices == 1 )\n"
-"   {\n"
-"      return rand33(cube_coord);\n"
-"   }\n"
-"\n"
-"   if( g_debug_complexity == 1 )\n"
-"   {\n"
-"      ivec3 coord = ivec3( cube_coord );\n"
-"      uvec4 index_sample = texelFetch( uLightsIndex, coord, 0 );\n"
-"\n"
-"      uint light_count = (index_sample.x & 0x3u) + (index_sample.y & 0x3u);\n"
-"      return vec3( float(light_count)*(1.0/6.0), 0.0, 0.5 );\n"
-"   }\n"
-"\n"
-"   // FIXME: this coord should absolutely must be clamped!\n"
-"   \n"
-"   ivec3 coord = ivec3( cube_coord );\n"
-"   uvec4 index_sample = texelFetch( uLightsIndex, coord, 0 );\n"
-"\n"
-"   total_light += \n"
-"      scene_calculate_packed_light_patch( index_sample.x,\n"
-"                                          halfview, co, normal ) \n"
-"                                          * light_mask;\n"
-"   total_light += \n"
-"      scene_calculate_packed_light_patch( index_sample.y,\n"
-"                                          halfview, co, normal )\n"
-"                                          * light_mask;\n"
-"\n"
-"   // Take a section of the sky function to give us a matching fog colour\n"
-"\n"
-"   vec3 fog_colour  = clearskies_ambient( -halfview );\n"
-"   float sun_theta  = dot( -halfview, g_sun_dir.xyz );\n"
-"   float sun_size   = max( 0.0, sun_theta * 0.5 + 0.5 );\n"
-"   float sun_shape  = sun_size * max(g_sun_dir.y,0.0) * 0.5;\n"
-"         \n"
-"   vec3 sun_colour  = mix( vec3(1.0), g_sunset_colour.rgb, g_sunset_phase*0.5 );\n"
-"        sun_colour *= sun_shape;\n"
-"\n"
-"   fog_colour += sun_colour;\n"
-"   return scene_apply_fog( diffuse * total_light, fog_colour, fdist );\n"
-"}\n"
-"\n"
-"#line     14        0 \n"
-"#line       1        3 \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     15        0 \n"
-"\n"
-"float stars1( vec3 rd, float rr, float size ){\n"
-"   vec3 co = rd * rr;\n"
-"\n"
-"   float a = atan(co.y, length(co.xz)) + 4.0 * PI;\n"
-"\n"
-"   float spaces = 1.0 / rr;\n"
-"   size = (rr * 0.0015) * fwidth(a) * 1000.0 * size;\n"
-"   a -= mod(a, spaces) - spaces * 0.5;\n"
-"\n"
-"   float count = floor(sqrt(pow(rr, 2.0) * (1.0 - pow(sin(a), 2.0))) * 3.0);\n"
-"   \n"
-"   float plane = atan(co.z, co.x) + 4.0 * PI;\n"
-"   plane = plane - mod(plane, PI / count);\n"
-"\n"
-"   vec2 delta = rand33(vec3(plane, a, 0.0)).xy;\n"
-"\n"
-"   float level = sin(a + spaces * (delta.y - 0.5) * (1.0 - size)) * rr;\n"
-"   float ydist = sqrt(rr * rr - level * level);\n"
-"   float angle = plane + (PI * (delta.x * (1.0-size) + size * 0.5) / count);\n"
-"   vec3 center = vec3(cos(angle) * ydist, level, sin(angle) * ydist);\n"
-"   float star = smoothstep(size, 0.0, distance(center, co));\n"
-"   return star;\n"
-"}\n"
-"\n"
-"void main(){\n"
-"   compute_motion_vectors();\n"
-"\n"
-"   vec3 rd = -normalize(aNorm);\n"
-"\n"
-"   float star = 0.0;\n"
-"   for( float j = 1.0; j <= 4.1; j += 1.0 ){\n"
-"      float m = mix(0.6, 0.9, smoothstep(1.0, 2.0, j));\n"
-"      star += stars( rd, 1.94 * pow( 1.64, j ), m ) * (1.0 / pow(4.0, j));\n"
-"   }\n"
-"\n"
-"   oColour = vec4( vec3(star*20.0), 1.0);\n"
-"}\n"
-""},
-};
-
-static GLuint _uniform_model_sky_space_uMdl;
-static GLuint _uniform_model_sky_space_uPv;
-static GLuint _uniform_model_sky_space_uPvmPrev;
-static GLuint _uniform_model_sky_space_uTexGarbage;
-static GLuint _uniform_model_sky_space_g_world_depth;
-static GLuint _uniform_model_sky_space_uLightsArray;
-static GLuint _uniform_model_sky_space_uLightsIndex;
-static void shader_model_sky_space_uMdl(m4x3f m){
-   glUniformMatrix4x3fv(_uniform_model_sky_space_uMdl,1,GL_FALSE,(float*)m);
+   glUniformMatrix4x3fv(_uniform_model_sky_space_uMdl,1,GL_FALSE,(f32*)m);
 }
-static void shader_model_sky_space_uPv(m4x4f m){
-   glUniformMatrix4fv(_uniform_model_sky_space_uPv,1,GL_FALSE,(float*)m);
+static inline void shader_model_sky_space_uPv(m4x4f m)
+{
+   glUniformMatrix4fv(_uniform_model_sky_space_uPv,1,GL_FALSE,(f32*)m);
 }
-static void shader_model_sky_space_uPvmPrev(m4x4f m){
-   glUniformMatrix4fv(_uniform_model_sky_space_uPvmPrev,1,GL_FALSE,(float*)m);
+static inline void shader_model_sky_space_uPvmPrev(m4x4f m)
+{
+   glUniformMatrix4fv(_uniform_model_sky_space_uPvmPrev,1,GL_FALSE,(f32*)m);
 }
-static void shader_model_sky_space_uTexGarbage(int i){
+static inline void shader_model_sky_space_uTexGarbage(int i)
+{
    glUniform1i(_uniform_model_sky_space_uTexGarbage,i);
 }
-static void shader_model_sky_space_g_world_depth(int i){
+static inline void shader_model_sky_space_g_world_depth(int i)
+{
    glUniform1i(_uniform_model_sky_space_g_world_depth,i);
 }
-static void shader_model_sky_space_register(void){
-   vg_shader_register( &_shader_model_sky_space );
-}
-static void shader_model_sky_space_use(void){ glUseProgram(_shader_model_sky_space.id); }
-static void shader_model_sky_space_link(void){
-   _uniform_model_sky_space_uMdl = glGetUniformLocation( _shader_model_sky_space.id, "uMdl" );
-   _uniform_model_sky_space_uPv = glGetUniformLocation( _shader_model_sky_space.id, "uPv" );
-   _uniform_model_sky_space_uPvmPrev = glGetUniformLocation( _shader_model_sky_space.id, "uPvmPrev" );
-   _uniform_model_sky_space_uTexGarbage = glGetUniformLocation( _shader_model_sky_space.id, "uTexGarbage" );
-   _uniform_model_sky_space_g_world_depth = glGetUniformLocation( _shader_model_sky_space.id, "g_world_depth" );
-   _uniform_model_sky_space_uLightsArray = glGetUniformLocation( _shader_model_sky_space.id, "uLightsArray" );
-   _uniform_model_sky_space_uLightsIndex = glGetUniformLocation( _shader_model_sky_space.id, "uLightsIndex" );
+static inline void shader_model_sky_space_use(void);
+static inline void shader_model_sky_space_use(void)
+{
+   glUseProgram(_shader_model_sky_space.id);
 }
-#endif /* SHADER_model_sky_space_H */
index 60bc981577f042071b7829fcef8800a9b716522f..43ad3ace5b7eb2c8be9cfbfafb367fa21b72853e 100644 (file)
-#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 = 
+#pragma once
+#include "vg/vg_engine.h"
+extern struct vg_shader _shader_particle;
+extern GLuint _uniform_particle_uPv;
+extern GLuint _uniform_particle_uPvPrev;
+static inline void shader_particle_uPv(m4x4f m)
 {
-.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);
+   glUniformMatrix4fv(_uniform_particle_uPv,1,GL_FALSE,(f32*)m);
 }
-static void shader_particle_register(void){
-   vg_shader_register( &_shader_particle );
+static inline void shader_particle_uPvPrev(m4x4f m)
+{
+   glUniformMatrix4fv(_uniform_particle_uPvPrev,1,GL_FALSE,(f32*)m);
 }
-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" );
+static inline void shader_particle_use(void);
+static inline void shader_particle_use(void)
+{
+   glUseProgram(_shader_particle.id);
 }
-#endif /* SHADER_particle_H */
index 9e571aba42ede7dcb32a8a6c7d06dc8bbf45d9e9..9be8ddccd6438281eb86316a2e60113e42443caf 100644 (file)
@@ -1,53 +1,18 @@
-#ifndef SHADER_routeui_H
-#define SHADER_routeui_H
-static void shader_routeui_link(void);
-static void shader_routeui_register(void);
-static struct vg_shader _shader_routeui = {
-   .name = "routeui",
-   .link = shader_routeui_link,
-   .vs = 
+#pragma once
+#include "vg/vg_engine.h"
+extern struct vg_shader _shader_routeui;
+extern GLuint _uniform_routeui_uOffset;
+extern GLuint _uniform_routeui_uColour;
+static inline void shader_routeui_uOffset(v4f v)
 {
-.orig_file = "shaders/routeui.vs",
-.static_src = 
-"layout (location=0) in vec2 a_co;\n"
-"\n"
-"uniform vec4 uOffset;\n"
-"\n"
-"void main()\n"
-"{\n"
-"   vec2 vpos = a_co * uOffset.zw + uOffset.xy;\n"
-"   gl_Position = vec4(vpos,0.0,1.0);\n"
-"}\n"
-""},
-   .fs = 
-{
-.orig_file = "shaders/routeui.fs",
-.static_src = 
-"out vec4 FragColor;\n"
-"\n"
-"uniform vec4 uColour;\n"
-"\n"
-"void main()\n"
-"{\n"
-"   FragColor = uColour;\n"
-"}\n"
-""},
-};
-
-static GLuint _uniform_routeui_uOffset;
-static GLuint _uniform_routeui_uColour;
-static void shader_routeui_uOffset(v4f v){
    glUniform4fv(_uniform_routeui_uOffset,1,v);
 }
-static void shader_routeui_uColour(v4f v){
+static inline void shader_routeui_uColour(v4f v)
+{
    glUniform4fv(_uniform_routeui_uColour,1,v);
 }
-static void shader_routeui_register(void){
-   vg_shader_register( &_shader_routeui );
-}
-static void shader_routeui_use(void){ glUseProgram(_shader_routeui.id); }
-static void shader_routeui_link(void){
-   _uniform_routeui_uOffset = glGetUniformLocation( _shader_routeui.id, "uOffset" );
-   _uniform_routeui_uColour = glGetUniformLocation( _shader_routeui.id, "uColour" );
+static inline void shader_routeui_use(void);
+static inline void shader_routeui_use(void)
+{
+   glUseProgram(_shader_routeui.id);
 }
-#endif /* SHADER_routeui_H */
index 544ac63cf743ecf7ff80aea139452c8ff45d3bef..f7dfbbd42683bf26baa09bbeea593145802e402e 100644 (file)
-#ifndef SHADER_scene_cubemapped_H
-#define SHADER_scene_cubemapped_H
-static void shader_scene_cubemapped_link(void);
-static void shader_scene_cubemapped_register(void);
-static struct vg_shader _shader_scene_cubemapped = {
-   .name = "scene_cubemapped",
-   .link = shader_scene_cubemapped_link,
-   .vs = 
+#pragma once
+#include "vg/vg_engine.h"
+extern struct vg_shader _shader_scene_cubemapped;
+extern GLuint _uniform_scene_cubemapped_uMdl;
+extern GLuint _uniform_scene_cubemapped_uPv;
+extern GLuint _uniform_scene_cubemapped_uPvmPrev;
+extern GLuint _uniform_scene_cubemapped_uTexGarbage;
+extern GLuint _uniform_scene_cubemapped_uTexMain;
+extern GLuint _uniform_scene_cubemapped_uTexCubemap;
+extern GLuint _uniform_scene_cubemapped_uCamera;
+extern GLuint _uniform_scene_cubemapped_uPlane;
+extern GLuint _uniform_scene_cubemapped_uColour;
+extern GLuint _uniform_scene_cubemapped_g_world_depth;
+extern GLuint _uniform_scene_cubemapped_uLightsArray;
+extern GLuint _uniform_scene_cubemapped_uLightsIndex;
+static inline void shader_scene_cubemapped_uMdl(m4x3f m)
 {
-.orig_file = "shaders/scene.vs",
-.static_src = 
-"layout (location=0) in vec3  a_co;\n"
-"layout (location=1) in vec4  a_norm;\n"
-"layout (location=2) in vec2  a_uv;\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      6        0 \n"
-"\n"
-"uniform mat4x3 uMdl;\n"
-"uniform mat4   uPv;\n"
-"uniform mat4   uPvmPrev;\n"
-"\n"
-"out vec2 aUv;\n"
-"out vec4 aNorm;\n"
-"out vec3 aCo;\n"
-"out vec3 aWorldCo;\n"
-"\n"
-"void main()\n"
-"{\n"
-"   vec3 world_pos0 = uMdl     * vec4( a_co, 1.0 );\n"
-"   vec4 vproj0     = uPv      * vec4( world_pos0, 1.0 );\n"
-"   vec4 vproj1     = uPvmPrev * vec4( a_co, 1.0 );\n"
-"\n"
-"   vs_motion_out( vproj0, vproj1 );\n"
-"\n"
-"   gl_Position = vproj0;\n"
-"\n"
-"   aUv = a_uv;\n"
-"   aNorm = vec4( mat3(uMdl) * a_norm.xyz, a_norm.w );\n"
-"   aCo = a_co;\n"
-"   aWorldCo = world_pos0;\n"
-"}\n"
-""},
-   .fs = 
-{
-.orig_file = "shaders/scene_cubemapped.fs",
-.static_src = 
-"uniform sampler2D uTexGarbage;\n"
-"uniform sampler2D uTexMain;\n"
-"uniform samplerCube uTexCubemap;\n"
-"uniform vec3 uCamera;\n"
-"uniform vec4 uPlane;\n"
-"uniform vec4 uColour;\n"
-"\n"
-"#line       1        1 \n"
-"// :D\n"
-"const float CLEARSKIES_LIGHT_DOT_MIN = 0.0;\n"
-"\n"
-"#line      9        0 \n"
-"#line       1        2 \n"
-"// :D\n"
-"\n"
-"in vec2 aUv;\n"
-"in vec4 aNorm;\n"
-"in vec3 aCo;\n"
-"in vec3 aWorldCo;\n"
-"\n"
-"#line       1        1 \n"
-"layout (location = 0) out vec4 oColour;\n"
-"\n"
-"// OpenGL wiki: Recommends do not use vec3 because of drivers. hence the v4s...\n"
-"layout (std140) uniform ub_world_lighting\n"
-"{\n"
-"   vec4 g_cube_min;\n"
-"   vec4 g_cube_inv_range;\n"
-"\n"
-"   vec4 g_water_plane;\n"
-"   vec4 g_depth_bounds;\n"
-"\n"
-"   vec4 g_daysky_colour;\n"
-"   vec4 g_nightsky_colour;\n"
-"   vec4 g_sunset_colour;\n"
-"   vec4 g_ambient_colour;\n"
-"   vec4 g_sunset_ambient;\n"
-"   vec4 g_sun_colour;\n"
-"   vec4 g_sun_dir;\n"
-"   vec4 g_board_0;\n"
-"   vec4 g_board_1;\n"
-"\n"
-"   float g_water_fog;\n"
-"   float g_time;\n"
-"   float g_realtime;\n"
-"   float g_shadow_length;\n"
-"   float g_shadow_spread;\n"
-"\n"
-"   float g_time_of_day;\n"
-"   float g_day_phase;\n"
-"   float g_sunset_phase;\n"
-"\n"
-"   int g_light_preview;\n"
-"   int g_shadow_samples;\n"
-"\n"
-"   int g_debug_indices;\n"
-"   int g_debug_complexity;\n"
-"};\n"
-"\n"
-"uniform sampler2D g_world_depth;\n"
-"uniform samplerBuffer uLightsArray;\n"
-"uniform usampler3D uLightsIndex;\n"
-"\n"
-"#line       1        1 \n"
-"//const vec3  DAYSKY_COLOUR   = vec3( 0.37, 0.54, 0.97 );\n"
-"//const vec3  NIGHTSKY_COLOUR = vec3( 0.03, 0.05, 0.20 );\n"
-"//const vec3  SUNSET_COLOUR   = vec3( 1.00, 0.32, 0.01 );\n"
-"//const vec3  AMBIENT_COLOUR  = vec3( 0.13, 0.17, 0.35 );\n"
-"//const vec3  SUNSET_AMBIENT  = vec3( 0.25, 0.17, 0.51 );\n"
-"//const vec3  SUN_COLOUR      = vec3( 1.10, 0.89, 0.35 );\n"
-"\n"
-"const float SUN_ANGLE       = 0.0001;\n"
-"const float PI              = 3.14159265358979323846264;\n"
-"\n"
-"//struct world_info\n"
-"//{\n"
-"//   float time,\n"
-"//         time_of_day,\n"
-"//         day_phase,\n"
-"//         sunset_phase;\n"
-"//   \n"
-"//   vec3 sun_dir;\n"
-"//};\n"
-"\n"
-"vec3 rand33(vec3 p3)\n"
-"{\n"
-"      p3 = fract(p3 * vec3(.1031, .1030, .0973));\n"
-"   p3 += dot(p3, p3.yxz+33.33);\n"
-"   return fract((p3.xxy + p3.yxx)*p3.zyx);\n"
-"}\n"
-"\n"
-"float stars( vec3 rd, float rr, float size ){\n"
-"   vec3 co = rd * rr;\n"
-"\n"
-"   float a = atan(co.y, length(co.xz)) + 4.0 * PI;\n"
-"\n"
-"   float spaces = 1.0 / rr;\n"
-"   size = (rr * 0.0015) * fwidth(a) * 1000.0 * size;\n"
-"   a -= mod(a, spaces) - spaces * 0.5;\n"
-"\n"
-"   float count = floor(sqrt(pow(rr, 2.0) * (1.0 - pow(sin(a), 2.0))) * 3.0);\n"
-"   \n"
-"   float plane = atan(co.z, co.x) + 4.0 * PI;\n"
-"   plane = plane - mod(plane, PI / count);\n"
-"\n"
-"   vec2 delta = rand33(vec3(plane, a, 0.0)).xy;\n"
-"\n"
-"   float level = sin(a + spaces * (delta.y - 0.5) * (1.0 - size)) * rr;\n"
-"   float ydist = sqrt(rr * rr - level * level);\n"
-"   float angle = plane + (PI * (delta.x * (1.0-size) + size * 0.5) / count);\n"
-"   vec3 center = vec3(cos(angle) * ydist, level, sin(angle) * ydist);\n"
-"   float star = smoothstep(size, 0.0, distance(center, co));\n"
-"   return star;\n"
-"}\n"
-"\n"
-"float luminance( vec3 v )\n"
-"{\n"
-"   return dot( v, vec3(0.2126, 0.7152, 0.0722) );\n"
-"}\n"
-"\n"
-"vec3 clearskies_ambient( vec3 dir )\n"
-"{\n"
-"   float sun_azimuth  = g_sunset_phase * (dot( dir.xz, g_sun_dir.xz )*0.4+0.6);\n"
-"   float sky_gradient = dir.y;\n"
-"   \n"
-"   /* Blend phase colours */\n"
-"   vec3 ambient  = g_daysky_colour.rgb   * (g_day_phase-g_sunset_phase*0.1);\n"
-"        ambient += g_sunset_colour.rgb   * (1.0-dir.y*0.5)*sun_azimuth;\n"
-"        ambient += g_nightsky_colour.rgb * (1.0-g_day_phase);\n"
-"   \n"
-"   /* Add gradient */\n"
-"        ambient -= sky_gradient * luminance(ambient);\n"
-"        \n"
-"   return ambient;\n"
-"}\n"
-"\n"
-"vec3 clearskies_sky( vec3 ray_dir )\n"
-"{\n"
-"   ray_dir.y = abs( ray_dir.y );\n"
-"   vec3 sky_colour  = clearskies_ambient( ray_dir );\n"
-"   \n"
-"   /* Sun */\n"
-"   float sun_theta  = dot( ray_dir, g_sun_dir.xyz );\n"
-"   float sun_size   = max( 0.0, sun_theta * 0.5 + 0.5 + SUN_ANGLE );\n"
-"   float sun_shape  = pow( sun_size, 2000.0 );\n"
-"         sun_shape += sun_size * max(g_sun_dir.y,0.0) * 0.5;\n"
-"         \n"
-"   vec3 sun_colour  = mix( vec3(1.0), g_sunset_colour.rgb, g_sunset_phase*0.5 );\n"
-"        sun_colour *= sun_shape;\n"
-"\n"
-"   \n"
-"   float star = 0.0;\n"
-"   float star_blend = 10.0*max(0.0,(1.0-g_day_phase*2.0));\n"
-"\n"
-"   if( star_blend > 0.001 ){\n"
-"      for( float j = 1.0; j <= 4.1; j += 1.0 ){\n"
-"         float m = mix(0.6, 0.9, smoothstep(1.0, 2.0, j));\n"
-"         star += stars( ray_dir, 1.94 * pow( 1.64, j ), m ) * (1.0/pow(4.0, j));\n"
-"      }\n"
-"   }\n"
-"   \n"
-"   vec3 composite   = sky_colour + sun_colour + star*star_blend;\n"
-"   return composite;\n"
-"}\n"
-"\n"
-"vec3 clearskies_lighting( vec3 normal, float shadow, vec3 halfview )\n"
-"{\n"
-"   float fresnel = 1.0 - abs(dot(normal,halfview));\n"
-"\n"
-"   vec3  reflect_colour = mix( g_daysky_colour.rgb, g_sunset_colour.rgb, \n"
-"                               g_sunset_phase );\n"
-"\n"
-"   vec3  sky_reflection = 0.5 * fresnel * reflect_colour;\n"
-"   vec3  light_sun      = max( CLEARSKIES_LIGHT_DOT_MIN, \n"
-"                               dot(normal,g_sun_dir.xyz)*0.75+0.25\n"
-"                           ) * g_sun_colour.rgb * g_day_phase;\n"
-"\n"
-"   float scaled_shadow = max( shadow, 1.0 - max(g_sun_dir.y,0.0) );\n"
-"   vec3 ambient = mix( g_ambient_colour.rgb, g_sunset_ambient.rgb, \n"
-"                       g_sunset_phase );\n"
-"\n"
-"   return ambient + (light_sun + sky_reflection) * shadow;\n"
-"}\n"
-"\n"
-"#line     44        0 \n"
-"\n"
-"float world_depth_sample( vec3 pos )\n"
-"{\n"
-"   vec2 depth_coord = (pos.xz - g_depth_bounds.xy) * g_depth_bounds.zw; \n"
-"   return texture( g_world_depth, depth_coord ).r;\n"
-"}\n"
-"\n"
-"float world_water_depth( vec3 pos )\n"
-"{\n"
-"   float ref_depth = g_water_plane.y*g_water_plane.w;\n"
-"   return world_depth_sample( pos ) - ref_depth;\n"
-"}\n"
-"\n"
-"float shadow_sample( vec3 co ){\n"
-"   float height_sample = world_depth_sample( co );\n"
-"\n"
-"   float fdelta = height_sample - co.y;\n"
-"   return clamp( fdelta, 0.2, 0.4 )-0.2;\n"
-"}\n"
-"\n"
-"float newlight_compute_sun_shadow( vec3 co, vec3 dir ){\n"
-"   if( g_shadow_samples == 0 ){\n"
-"      return 1.0;\n"
-"   }\n"
-"\n"
-"   float fspread = g_shadow_spread;\n"
-"   float flength = g_shadow_length;\n"
-"\n"
-"   float famt = 0.0;\n"
-"   famt += shadow_sample(co+(dir+vec3(-0.56,0.55, 0.30)*fspread)*flength*0.1);\n"
-"   famt += shadow_sample(co+(dir+vec3( 0.80,0.68, 0.34)*fspread)*flength*0.2);\n"
-"   famt += shadow_sample(co+(dir+vec3( 0.78,0.07,-0.06)*fspread)*flength*0.3);\n"
-"   famt += shadow_sample(co+(dir+vec3(-0.59,0.07,-0.42)*fspread)*flength*0.4);\n"
-"\n"
-"   //famt+=shadow_sample(co+(dir+vec3(-0.790,-0.933,-0.875)*fspread)*flength*0.5);\n"
-"   //famt+=shadow_sample(co+(dir+vec3( 0.807,-0.690, 0.472)*fspread)*flength*0.6);\n"
-"   //famt+=shadow_sample(co+(dir+vec3( 0.522,-0.379, 0.350)*fspread)*flength*0.7);\n"
-"   //famt+=shadow_sample(co+(dir+vec3( 0.483, 0.201, 0.306)*fspread)*flength*0.8);\n"
-"\n"
-"   return 1.0 - famt;\n"
-"}\n"
-"\n"
-"float newlight_specular( vec3 wnormal, vec3 dir, vec3 halfview, float exponent )\n"
-"{\n"
-"   vec3 specdir = reflect( -dir, wnormal );\n"
-"   return pow(max(dot( halfview, specdir ), 0.0), exponent);\n"
-"}\n"
-"\n"
-"vec3 scene_apply_fog( vec3 vfrag, vec3 colour, float fdist ){\n"
-"   float dist = pow(fdist*0.0010,0.78);\n"
-"   return mix( vfrag, colour, min( 1.0, dist ) );\n"
-"}\n"
-"\n"
-"vec3 scene_calculate_light( int light_index, \n"
-"                            vec3 halfview, vec3 co, vec3 normal )\n"
-"{\n"
-"   vec4 light_colour = texelFetch( uLightsArray, light_index+0 );\n"
-"   vec4 light_co     = texelFetch( uLightsArray, light_index+1 );\n"
-"   vec4 light_dir    = texelFetch( uLightsArray, light_index+2 );\n"
-"\n"
-"   vec3 light_delta = light_co.xyz-co;\n"
-"   float dist2 = dot(light_delta,light_delta);\n"
-"\n"
-"   light_delta = normalize( light_delta );\n"
-"\n"
-"   float quadratic = dist2*100.0;\n"
-"   float attenuation  = 1.0/( 1.0 + quadratic );\n"
-"         attenuation *= max( dot( light_delta, normal ), 0.0 );\n"
-"\n"
-"   float falloff = max( 0.0, 1.0-(dist2*light_co.w) );\n"
-"\n"
-"   if( light_dir.w < 0.999999 ){\n"
-"      float spot_theta = max( 0.0, dot( light_delta, -light_dir.xyz ) );\n"
-"      falloff *= max( 0.0, (spot_theta - light_dir.w) / (1.0-light_dir.w) );\n"
-"   }\n"
-"\n"
-"   return light_colour.rgb * attenuation * falloff \n"
-"            * step( g_day_phase, light_colour.w );\n"
-"}\n"
-"\n"
-"vec3 scene_calculate_packed_light_patch( uint packed_index, \n"
-"                                         vec3 halfview, vec3 co, vec3 normal )\n"
-"{\n"
-"   uint light_count = packed_index & 0x3u;\n"
-"\n"
-"   vec3 l = vec3(0.0);\n"
-"\n"
-"   if( light_count >= 1u ){\n"
-"      int index_0 = int( ((packed_index >>  2u) & 0x3ffu) * 3u );\n"
-"      int index_1 = int( ((packed_index >> 12u) & 0x3ffu) * 3u );\n"
-"      int index_2 = int( ((packed_index >> 22u) & 0x3ffu) * 3u );\n"
-"\n"
-"      l += scene_calculate_light( index_0, halfview, co, normal );\n"
-"\n"
-"      if( light_count >= 2u ){\n"
-"         l += scene_calculate_light( index_1, halfview, co, normal );\n"
-"\n"
-"         if( light_count >= 3u ){\n"
-"            l += scene_calculate_light( index_2, halfview, co, normal );\n"
-"         }\n"
-"      }\n"
-"   }\n"
-"\n"
-"   return l;\n"
-"}\n"
-"\n"
-"vec3 world_compute_lighting( vec3 diffuse, vec3 normal, vec3 co,\n"
-"                             float light_mask )\n"
-"{\n"
-"   if( g_light_preview == 1 )\n"
-"      diffuse = vec3(0.75);\n"
-"\n"
-"   // Lighting\n"
-"   vec3 halfview = uCamera - co;\n"
-"   float fdist = length(halfview);\n"
-"   halfview /= fdist;\n"
-"\n"
-"   float world_shadow = newlight_compute_sun_shadow( \n"
-"               co, g_sun_dir.xyz * (1.0/(max(g_sun_dir.y,0.0)+0.2)) );\n"
-"\n"
-"   vec3 total_light = clearskies_lighting( \n"
-"                           normal, min( light_mask, world_shadow ), halfview );\n"
-"\n"
-"   vec3 cube_coord = (co - g_cube_min.xyz) * g_cube_inv_range.xyz;\n"
-"        cube_coord = floor( cube_coord );\n"
-"\n"
-"   if( g_debug_indices == 1 )\n"
-"   {\n"
-"      return rand33(cube_coord);\n"
-"   }\n"
-"\n"
-"   if( g_debug_complexity == 1 )\n"
-"   {\n"
-"      ivec3 coord = ivec3( cube_coord );\n"
-"      uvec4 index_sample = texelFetch( uLightsIndex, coord, 0 );\n"
-"\n"
-"      uint light_count = (index_sample.x & 0x3u) + (index_sample.y & 0x3u);\n"
-"      return vec3( float(light_count)*(1.0/6.0), 0.0, 0.5 );\n"
-"   }\n"
-"\n"
-"   // FIXME: this coord should absolutely must be clamped!\n"
-"   \n"
-"   ivec3 coord = ivec3( cube_coord );\n"
-"   uvec4 index_sample = texelFetch( uLightsIndex, coord, 0 );\n"
-"\n"
-"   total_light += \n"
-"      scene_calculate_packed_light_patch( index_sample.x,\n"
-"                                          halfview, co, normal ) \n"
-"                                          * light_mask;\n"
-"   total_light += \n"
-"      scene_calculate_packed_light_patch( index_sample.y,\n"
-"                                          halfview, co, normal )\n"
-"                                          * light_mask;\n"
-"\n"
-"   // Take a section of the sky function to give us a matching fog colour\n"
-"\n"
-"   vec3 fog_colour  = clearskies_ambient( -halfview );\n"
-"   float sun_theta  = dot( -halfview, g_sun_dir.xyz );\n"
-"   float sun_size   = max( 0.0, sun_theta * 0.5 + 0.5 );\n"
-"   float sun_shape  = sun_size * max(g_sun_dir.y,0.0) * 0.5;\n"
-"         \n"
-"   vec3 sun_colour  = mix( vec3(1.0), g_sunset_colour.rgb, g_sunset_phase*0.5 );\n"
-"        sun_colour *= sun_shape;\n"
-"\n"
-"   fog_colour += sun_colour;\n"
-"   return scene_apply_fog( diffuse * total_light, fog_colour, fdist );\n"
-"}\n"
-"\n"
-"#line      9        0 \n"
-"\n"
-"float sdLine( vec3 p, vec3 a, vec3 b )\n"
-"{\n"
-"  vec3 pa = p - a;\n"
-"  vec3 ba = b - a;\n"
-"\n"
-"  float h = clamp( dot(pa,ba)/dot(ba,ba), 0.0, 1.0 );\n"
-"  return length( pa - ba*h );\n"
-"}\n"
-"\n"
-"float compute_board_shadow()\n"
-"{\n"
-"   // player shadow\n"
-"   float dist_to_player = max( 0.0, sdLine( aWorldCo, g_board_0.xyz,\n"
-"                                                      g_board_1.xyz )-0.1 );\n"
-"   float player_shadow = max( 1.0-dist_to_player*2.7, 0.0 );\n"
-"   player_shadow *= player_shadow*player_shadow*player_shadow;\n"
-"\n"
-"   return 1.0 - player_shadow*0.8;\n"
-"}\n"
-"\n"
-"vec3 scene_compute_lighting( vec3 diffuse, vec3 normal, vec3 co )\n"
-"{\n"
-"   return world_compute_lighting( diffuse, normal, co, compute_board_shadow() );\n"
-"}\n"
-"\n"
-"#line     10        0 \n"
-"#line       1        3 \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     11        0 \n"
-"\n"
-"void main()\n"
-"{\n"
-"   compute_motion_vectors();\n"
-"\n"
-"   vec3 vfrag = vec3(0.5,0.5,0.5);\n"
-"   vec4 vsamplemain = texture( uTexMain, aUv );\n"
-"   vec4 wgarbage = texture( uTexGarbage, aCo.xz * 0.0015 + aCo.yx*0.002 );\n"
-"   vec3 qnorm = aNorm.xyz;\n"
-"   vfrag = vsamplemain.rgb;\n"
-"\n"
-"   if( g_light_preview == 1 ){\n"
-"      vfrag = vec3(0.5);\n"
-"   }\n"
-"\n"
-"   vfrag = scene_compute_lighting( vfrag, qnorm, aWorldCo );\n"
-"   oColour = vec4( vfrag, 1.0 );\n"
-"\n"
-"   vec3 halfdir = normalize( aWorldCo - uCamera );\n"
-"   vec3 reflectdir = reflect( halfdir, qnorm );\n"
-"   oColour = mix( oColour, \n"
-"                  vec4(texture(uTexCubemap,reflectdir).rgb * uColour.rgb, 1.0),\n"
-"                  uColour.a*wgarbage.b );\n"
-"}\n"
-""},
-};
-
-static GLuint _uniform_scene_cubemapped_uMdl;
-static GLuint _uniform_scene_cubemapped_uPv;
-static GLuint _uniform_scene_cubemapped_uPvmPrev;
-static GLuint _uniform_scene_cubemapped_uTexGarbage;
-static GLuint _uniform_scene_cubemapped_uTexMain;
-static GLuint _uniform_scene_cubemapped_uTexCubemap;
-static GLuint _uniform_scene_cubemapped_uCamera;
-static GLuint _uniform_scene_cubemapped_uPlane;
-static GLuint _uniform_scene_cubemapped_uColour;
-static GLuint _uniform_scene_cubemapped_g_world_depth;
-static GLuint _uniform_scene_cubemapped_uLightsArray;
-static GLuint _uniform_scene_cubemapped_uLightsIndex;
-static void shader_scene_cubemapped_uMdl(m4x3f m){
-   glUniformMatrix4x3fv(_uniform_scene_cubemapped_uMdl,1,GL_FALSE,(float*)m);
+   glUniformMatrix4x3fv(_uniform_scene_cubemapped_uMdl,1,GL_FALSE,(f32*)m);
 }
-static void shader_scene_cubemapped_uPv(m4x4f m){
-   glUniformMatrix4fv(_uniform_scene_cubemapped_uPv,1,GL_FALSE,(float*)m);
+static inline void shader_scene_cubemapped_uPv(m4x4f m)
+{
+   glUniformMatrix4fv(_uniform_scene_cubemapped_uPv,1,GL_FALSE,(f32*)m);
 }
-static void shader_scene_cubemapped_uPvmPrev(m4x4f m){
-   glUniformMatrix4fv(_uniform_scene_cubemapped_uPvmPrev,1,GL_FALSE,(float*)m);
+static inline void shader_scene_cubemapped_uPvmPrev(m4x4f m)
+{
+   glUniformMatrix4fv(_uniform_scene_cubemapped_uPvmPrev,1,GL_FALSE,(f32*)m);
 }
-static void shader_scene_cubemapped_uTexGarbage(int i){
+static inline void shader_scene_cubemapped_uTexGarbage(int i)
+{
    glUniform1i(_uniform_scene_cubemapped_uTexGarbage,i);
 }
-static void shader_scene_cubemapped_uTexMain(int i){
+static inline void shader_scene_cubemapped_uTexMain(int i)
+{
    glUniform1i(_uniform_scene_cubemapped_uTexMain,i);
 }
-static void shader_scene_cubemapped_uTexCubemap(int i){
+static inline void shader_scene_cubemapped_uTexCubemap(int i)
+{
    glUniform1i(_uniform_scene_cubemapped_uTexCubemap,i);
 }
-static void shader_scene_cubemapped_uCamera(v3f v){
+static inline void shader_scene_cubemapped_uCamera(v3f v)
+{
    glUniform3fv(_uniform_scene_cubemapped_uCamera,1,v);
 }
-static void shader_scene_cubemapped_uPlane(v4f v){
+static inline void shader_scene_cubemapped_uPlane(v4f v)
+{
    glUniform4fv(_uniform_scene_cubemapped_uPlane,1,v);
 }
-static void shader_scene_cubemapped_uColour(v4f v){
+static inline void shader_scene_cubemapped_uColour(v4f v)
+{
    glUniform4fv(_uniform_scene_cubemapped_uColour,1,v);
 }
-static void shader_scene_cubemapped_g_world_depth(int i){
+static inline void shader_scene_cubemapped_g_world_depth(int i)
+{
    glUniform1i(_uniform_scene_cubemapped_g_world_depth,i);
 }
-static void shader_scene_cubemapped_register(void){
-   vg_shader_register( &_shader_scene_cubemapped );
-}
-static void shader_scene_cubemapped_use(void){ glUseProgram(_shader_scene_cubemapped.id); }
-static void shader_scene_cubemapped_link(void){
-   _uniform_scene_cubemapped_uMdl = glGetUniformLocation( _shader_scene_cubemapped.id, "uMdl" );
-   _uniform_scene_cubemapped_uPv = glGetUniformLocation( _shader_scene_cubemapped.id, "uPv" );
-   _uniform_scene_cubemapped_uPvmPrev = glGetUniformLocation( _shader_scene_cubemapped.id, "uPvmPrev" );
-   _uniform_scene_cubemapped_uTexGarbage = glGetUniformLocation( _shader_scene_cubemapped.id, "uTexGarbage" );
-   _uniform_scene_cubemapped_uTexMain = glGetUniformLocation( _shader_scene_cubemapped.id, "uTexMain" );
-   _uniform_scene_cubemapped_uTexCubemap = glGetUniformLocation( _shader_scene_cubemapped.id, "uTexCubemap" );
-   _uniform_scene_cubemapped_uCamera = glGetUniformLocation( _shader_scene_cubemapped.id, "uCamera" );
-   _uniform_scene_cubemapped_uPlane = glGetUniformLocation( _shader_scene_cubemapped.id, "uPlane" );
-   _uniform_scene_cubemapped_uColour = glGetUniformLocation( _shader_scene_cubemapped.id, "uColour" );
-   _uniform_scene_cubemapped_g_world_depth = glGetUniformLocation( _shader_scene_cubemapped.id, "g_world_depth" );
-   _uniform_scene_cubemapped_uLightsArray = glGetUniformLocation( _shader_scene_cubemapped.id, "uLightsArray" );
-   _uniform_scene_cubemapped_uLightsIndex = glGetUniformLocation( _shader_scene_cubemapped.id, "uLightsIndex" );
+static inline void shader_scene_cubemapped_use(void);
+static inline void shader_scene_cubemapped_use(void)
+{
+   glUseProgram(_shader_scene_cubemapped.id);
 }
-#endif /* SHADER_scene_cubemapped_H */
index 6f28ad438928cd9e66e3bafb71f92e362d4546c6..d760b339b657c16227daefd48fdfc4766c7281c0 100644 (file)
-#ifndef SHADER_scene_depth_H
-#define SHADER_scene_depth_H
-static void shader_scene_depth_link(void);
-static void shader_scene_depth_register(void);
-static struct vg_shader _shader_scene_depth = {
-   .name = "scene_depth",
-   .link = shader_scene_depth_link,
-   .vs = 
+#pragma once
+#include "vg/vg_engine.h"
+extern struct vg_shader _shader_scene_depth;
+extern GLuint _uniform_scene_depth_uMdl;
+extern GLuint _uniform_scene_depth_uPv;
+extern GLuint _uniform_scene_depth_uPvmPrev;
+extern GLuint _uniform_scene_depth_uCamera;
+extern GLuint _uniform_scene_depth_uBoard0;
+extern GLuint _uniform_scene_depth_uBoard1;
+extern GLuint _uniform_scene_depth_g_world_depth;
+extern GLuint _uniform_scene_depth_uLightsArray;
+extern GLuint _uniform_scene_depth_uLightsIndex;
+static inline void shader_scene_depth_uMdl(m4x3f m)
 {
-.orig_file = "shaders/scene.vs",
-.static_src = 
-"layout (location=0) in vec3  a_co;\n"
-"layout (location=1) in vec4  a_norm;\n"
-"layout (location=2) in vec2  a_uv;\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      6        0 \n"
-"\n"
-"uniform mat4x3 uMdl;\n"
-"uniform mat4   uPv;\n"
-"uniform mat4   uPvmPrev;\n"
-"\n"
-"out vec2 aUv;\n"
-"out vec4 aNorm;\n"
-"out vec3 aCo;\n"
-"out vec3 aWorldCo;\n"
-"\n"
-"void main()\n"
-"{\n"
-"   vec3 world_pos0 = uMdl     * vec4( a_co, 1.0 );\n"
-"   vec4 vproj0     = uPv      * vec4( world_pos0, 1.0 );\n"
-"   vec4 vproj1     = uPvmPrev * vec4( a_co, 1.0 );\n"
-"\n"
-"   vs_motion_out( vproj0, vproj1 );\n"
-"\n"
-"   gl_Position = vproj0;\n"
-"\n"
-"   aUv = a_uv;\n"
-"   aNorm = vec4( mat3(uMdl) * a_norm.xyz, a_norm.w );\n"
-"   aCo = a_co;\n"
-"   aWorldCo = world_pos0;\n"
-"}\n"
-""},
-   .fs = 
-{
-.orig_file = "shaders/scene_depth.fs",
-.static_src = 
-"out vec4 FragColor;\n"
-"\n"
-"uniform vec3 uCamera;\n"
-"uniform vec3 uBoard0;\n"
-"uniform vec3 uBoard1;\n"
-"\n"
-"#line       1        1 \n"
-"// :D\n"
-"const float CLEARSKIES_LIGHT_DOT_MIN = 0.0;\n"
-"\n"
-"#line      8        0 \n"
-"#line       1        2 \n"
-"// :D\n"
-"\n"
-"in vec2 aUv;\n"
-"in vec4 aNorm;\n"
-"in vec3 aCo;\n"
-"in vec3 aWorldCo;\n"
-"\n"
-"#line       1        1 \n"
-"layout (location = 0) out vec4 oColour;\n"
-"\n"
-"// OpenGL wiki: Recommends do not use vec3 because of drivers. hence the v4s...\n"
-"layout (std140) uniform ub_world_lighting\n"
-"{\n"
-"   vec4 g_cube_min;\n"
-"   vec4 g_cube_inv_range;\n"
-"\n"
-"   vec4 g_water_plane;\n"
-"   vec4 g_depth_bounds;\n"
-"\n"
-"   vec4 g_daysky_colour;\n"
-"   vec4 g_nightsky_colour;\n"
-"   vec4 g_sunset_colour;\n"
-"   vec4 g_ambient_colour;\n"
-"   vec4 g_sunset_ambient;\n"
-"   vec4 g_sun_colour;\n"
-"   vec4 g_sun_dir;\n"
-"   vec4 g_board_0;\n"
-"   vec4 g_board_1;\n"
-"\n"
-"   float g_water_fog;\n"
-"   float g_time;\n"
-"   float g_realtime;\n"
-"   float g_shadow_length;\n"
-"   float g_shadow_spread;\n"
-"\n"
-"   float g_time_of_day;\n"
-"   float g_day_phase;\n"
-"   float g_sunset_phase;\n"
-"\n"
-"   int g_light_preview;\n"
-"   int g_shadow_samples;\n"
-"\n"
-"   int g_debug_indices;\n"
-"   int g_debug_complexity;\n"
-"};\n"
-"\n"
-"uniform sampler2D g_world_depth;\n"
-"uniform samplerBuffer uLightsArray;\n"
-"uniform usampler3D uLightsIndex;\n"
-"\n"
-"#line       1        1 \n"
-"//const vec3  DAYSKY_COLOUR   = vec3( 0.37, 0.54, 0.97 );\n"
-"//const vec3  NIGHTSKY_COLOUR = vec3( 0.03, 0.05, 0.20 );\n"
-"//const vec3  SUNSET_COLOUR   = vec3( 1.00, 0.32, 0.01 );\n"
-"//const vec3  AMBIENT_COLOUR  = vec3( 0.13, 0.17, 0.35 );\n"
-"//const vec3  SUNSET_AMBIENT  = vec3( 0.25, 0.17, 0.51 );\n"
-"//const vec3  SUN_COLOUR      = vec3( 1.10, 0.89, 0.35 );\n"
-"\n"
-"const float SUN_ANGLE       = 0.0001;\n"
-"const float PI              = 3.14159265358979323846264;\n"
-"\n"
-"//struct world_info\n"
-"//{\n"
-"//   float time,\n"
-"//         time_of_day,\n"
-"//         day_phase,\n"
-"//         sunset_phase;\n"
-"//   \n"
-"//   vec3 sun_dir;\n"
-"//};\n"
-"\n"
-"vec3 rand33(vec3 p3)\n"
-"{\n"
-"      p3 = fract(p3 * vec3(.1031, .1030, .0973));\n"
-"   p3 += dot(p3, p3.yxz+33.33);\n"
-"   return fract((p3.xxy + p3.yxx)*p3.zyx);\n"
-"}\n"
-"\n"
-"float stars( vec3 rd, float rr, float size ){\n"
-"   vec3 co = rd * rr;\n"
-"\n"
-"   float a = atan(co.y, length(co.xz)) + 4.0 * PI;\n"
-"\n"
-"   float spaces = 1.0 / rr;\n"
-"   size = (rr * 0.0015) * fwidth(a) * 1000.0 * size;\n"
-"   a -= mod(a, spaces) - spaces * 0.5;\n"
-"\n"
-"   float count = floor(sqrt(pow(rr, 2.0) * (1.0 - pow(sin(a), 2.0))) * 3.0);\n"
-"   \n"
-"   float plane = atan(co.z, co.x) + 4.0 * PI;\n"
-"   plane = plane - mod(plane, PI / count);\n"
-"\n"
-"   vec2 delta = rand33(vec3(plane, a, 0.0)).xy;\n"
-"\n"
-"   float level = sin(a + spaces * (delta.y - 0.5) * (1.0 - size)) * rr;\n"
-"   float ydist = sqrt(rr * rr - level * level);\n"
-"   float angle = plane + (PI * (delta.x * (1.0-size) + size * 0.5) / count);\n"
-"   vec3 center = vec3(cos(angle) * ydist, level, sin(angle) * ydist);\n"
-"   float star = smoothstep(size, 0.0, distance(center, co));\n"
-"   return star;\n"
-"}\n"
-"\n"
-"float luminance( vec3 v )\n"
-"{\n"
-"   return dot( v, vec3(0.2126, 0.7152, 0.0722) );\n"
-"}\n"
-"\n"
-"vec3 clearskies_ambient( vec3 dir )\n"
-"{\n"
-"   float sun_azimuth  = g_sunset_phase * (dot( dir.xz, g_sun_dir.xz )*0.4+0.6);\n"
-"   float sky_gradient = dir.y;\n"
-"   \n"
-"   /* Blend phase colours */\n"
-"   vec3 ambient  = g_daysky_colour.rgb   * (g_day_phase-g_sunset_phase*0.1);\n"
-"        ambient += g_sunset_colour.rgb   * (1.0-dir.y*0.5)*sun_azimuth;\n"
-"        ambient += g_nightsky_colour.rgb * (1.0-g_day_phase);\n"
-"   \n"
-"   /* Add gradient */\n"
-"        ambient -= sky_gradient * luminance(ambient);\n"
-"        \n"
-"   return ambient;\n"
-"}\n"
-"\n"
-"vec3 clearskies_sky( vec3 ray_dir )\n"
-"{\n"
-"   ray_dir.y = abs( ray_dir.y );\n"
-"   vec3 sky_colour  = clearskies_ambient( ray_dir );\n"
-"   \n"
-"   /* Sun */\n"
-"   float sun_theta  = dot( ray_dir, g_sun_dir.xyz );\n"
-"   float sun_size   = max( 0.0, sun_theta * 0.5 + 0.5 + SUN_ANGLE );\n"
-"   float sun_shape  = pow( sun_size, 2000.0 );\n"
-"         sun_shape += sun_size * max(g_sun_dir.y,0.0) * 0.5;\n"
-"         \n"
-"   vec3 sun_colour  = mix( vec3(1.0), g_sunset_colour.rgb, g_sunset_phase*0.5 );\n"
-"        sun_colour *= sun_shape;\n"
-"\n"
-"   \n"
-"   float star = 0.0;\n"
-"   float star_blend = 10.0*max(0.0,(1.0-g_day_phase*2.0));\n"
-"\n"
-"   if( star_blend > 0.001 ){\n"
-"      for( float j = 1.0; j <= 4.1; j += 1.0 ){\n"
-"         float m = mix(0.6, 0.9, smoothstep(1.0, 2.0, j));\n"
-"         star += stars( ray_dir, 1.94 * pow( 1.64, j ), m ) * (1.0/pow(4.0, j));\n"
-"      }\n"
-"   }\n"
-"   \n"
-"   vec3 composite   = sky_colour + sun_colour + star*star_blend;\n"
-"   return composite;\n"
-"}\n"
-"\n"
-"vec3 clearskies_lighting( vec3 normal, float shadow, vec3 halfview )\n"
-"{\n"
-"   float fresnel = 1.0 - abs(dot(normal,halfview));\n"
-"\n"
-"   vec3  reflect_colour = mix( g_daysky_colour.rgb, g_sunset_colour.rgb, \n"
-"                               g_sunset_phase );\n"
-"\n"
-"   vec3  sky_reflection = 0.5 * fresnel * reflect_colour;\n"
-"   vec3  light_sun      = max( CLEARSKIES_LIGHT_DOT_MIN, \n"
-"                               dot(normal,g_sun_dir.xyz)*0.75+0.25\n"
-"                           ) * g_sun_colour.rgb * g_day_phase;\n"
-"\n"
-"   float scaled_shadow = max( shadow, 1.0 - max(g_sun_dir.y,0.0) );\n"
-"   vec3 ambient = mix( g_ambient_colour.rgb, g_sunset_ambient.rgb, \n"
-"                       g_sunset_phase );\n"
-"\n"
-"   return ambient + (light_sun + sky_reflection) * shadow;\n"
-"}\n"
-"\n"
-"#line     44        0 \n"
-"\n"
-"float world_depth_sample( vec3 pos )\n"
-"{\n"
-"   vec2 depth_coord = (pos.xz - g_depth_bounds.xy) * g_depth_bounds.zw; \n"
-"   return texture( g_world_depth, depth_coord ).r;\n"
-"}\n"
-"\n"
-"float world_water_depth( vec3 pos )\n"
-"{\n"
-"   float ref_depth = g_water_plane.y*g_water_plane.w;\n"
-"   return world_depth_sample( pos ) - ref_depth;\n"
-"}\n"
-"\n"
-"float shadow_sample( vec3 co ){\n"
-"   float height_sample = world_depth_sample( co );\n"
-"\n"
-"   float fdelta = height_sample - co.y;\n"
-"   return clamp( fdelta, 0.2, 0.4 )-0.2;\n"
-"}\n"
-"\n"
-"float newlight_compute_sun_shadow( vec3 co, vec3 dir ){\n"
-"   if( g_shadow_samples == 0 ){\n"
-"      return 1.0;\n"
-"   }\n"
-"\n"
-"   float fspread = g_shadow_spread;\n"
-"   float flength = g_shadow_length;\n"
-"\n"
-"   float famt = 0.0;\n"
-"   famt += shadow_sample(co+(dir+vec3(-0.56,0.55, 0.30)*fspread)*flength*0.1);\n"
-"   famt += shadow_sample(co+(dir+vec3( 0.80,0.68, 0.34)*fspread)*flength*0.2);\n"
-"   famt += shadow_sample(co+(dir+vec3( 0.78,0.07,-0.06)*fspread)*flength*0.3);\n"
-"   famt += shadow_sample(co+(dir+vec3(-0.59,0.07,-0.42)*fspread)*flength*0.4);\n"
-"\n"
-"   //famt+=shadow_sample(co+(dir+vec3(-0.790,-0.933,-0.875)*fspread)*flength*0.5);\n"
-"   //famt+=shadow_sample(co+(dir+vec3( 0.807,-0.690, 0.472)*fspread)*flength*0.6);\n"
-"   //famt+=shadow_sample(co+(dir+vec3( 0.522,-0.379, 0.350)*fspread)*flength*0.7);\n"
-"   //famt+=shadow_sample(co+(dir+vec3( 0.483, 0.201, 0.306)*fspread)*flength*0.8);\n"
-"\n"
-"   return 1.0 - famt;\n"
-"}\n"
-"\n"
-"float newlight_specular( vec3 wnormal, vec3 dir, vec3 halfview, float exponent )\n"
-"{\n"
-"   vec3 specdir = reflect( -dir, wnormal );\n"
-"   return pow(max(dot( halfview, specdir ), 0.0), exponent);\n"
-"}\n"
-"\n"
-"vec3 scene_apply_fog( vec3 vfrag, vec3 colour, float fdist ){\n"
-"   float dist = pow(fdist*0.0010,0.78);\n"
-"   return mix( vfrag, colour, min( 1.0, dist ) );\n"
-"}\n"
-"\n"
-"vec3 scene_calculate_light( int light_index, \n"
-"                            vec3 halfview, vec3 co, vec3 normal )\n"
-"{\n"
-"   vec4 light_colour = texelFetch( uLightsArray, light_index+0 );\n"
-"   vec4 light_co     = texelFetch( uLightsArray, light_index+1 );\n"
-"   vec4 light_dir    = texelFetch( uLightsArray, light_index+2 );\n"
-"\n"
-"   vec3 light_delta = light_co.xyz-co;\n"
-"   float dist2 = dot(light_delta,light_delta);\n"
-"\n"
-"   light_delta = normalize( light_delta );\n"
-"\n"
-"   float quadratic = dist2*100.0;\n"
-"   float attenuation  = 1.0/( 1.0 + quadratic );\n"
-"         attenuation *= max( dot( light_delta, normal ), 0.0 );\n"
-"\n"
-"   float falloff = max( 0.0, 1.0-(dist2*light_co.w) );\n"
-"\n"
-"   if( light_dir.w < 0.999999 ){\n"
-"      float spot_theta = max( 0.0, dot( light_delta, -light_dir.xyz ) );\n"
-"      falloff *= max( 0.0, (spot_theta - light_dir.w) / (1.0-light_dir.w) );\n"
-"   }\n"
-"\n"
-"   return light_colour.rgb * attenuation * falloff \n"
-"            * step( g_day_phase, light_colour.w );\n"
-"}\n"
-"\n"
-"vec3 scene_calculate_packed_light_patch( uint packed_index, \n"
-"                                         vec3 halfview, vec3 co, vec3 normal )\n"
-"{\n"
-"   uint light_count = packed_index & 0x3u;\n"
-"\n"
-"   vec3 l = vec3(0.0);\n"
-"\n"
-"   if( light_count >= 1u ){\n"
-"      int index_0 = int( ((packed_index >>  2u) & 0x3ffu) * 3u );\n"
-"      int index_1 = int( ((packed_index >> 12u) & 0x3ffu) * 3u );\n"
-"      int index_2 = int( ((packed_index >> 22u) & 0x3ffu) * 3u );\n"
-"\n"
-"      l += scene_calculate_light( index_0, halfview, co, normal );\n"
-"\n"
-"      if( light_count >= 2u ){\n"
-"         l += scene_calculate_light( index_1, halfview, co, normal );\n"
-"\n"
-"         if( light_count >= 3u ){\n"
-"            l += scene_calculate_light( index_2, halfview, co, normal );\n"
-"         }\n"
-"      }\n"
-"   }\n"
-"\n"
-"   return l;\n"
-"}\n"
-"\n"
-"vec3 world_compute_lighting( vec3 diffuse, vec3 normal, vec3 co,\n"
-"                             float light_mask )\n"
-"{\n"
-"   if( g_light_preview == 1 )\n"
-"      diffuse = vec3(0.75);\n"
-"\n"
-"   // Lighting\n"
-"   vec3 halfview = uCamera - co;\n"
-"   float fdist = length(halfview);\n"
-"   halfview /= fdist;\n"
-"\n"
-"   float world_shadow = newlight_compute_sun_shadow( \n"
-"               co, g_sun_dir.xyz * (1.0/(max(g_sun_dir.y,0.0)+0.2)) );\n"
-"\n"
-"   vec3 total_light = clearskies_lighting( \n"
-"                           normal, min( light_mask, world_shadow ), halfview );\n"
-"\n"
-"   vec3 cube_coord = (co - g_cube_min.xyz) * g_cube_inv_range.xyz;\n"
-"        cube_coord = floor( cube_coord );\n"
-"\n"
-"   if( g_debug_indices == 1 )\n"
-"   {\n"
-"      return rand33(cube_coord);\n"
-"   }\n"
-"\n"
-"   if( g_debug_complexity == 1 )\n"
-"   {\n"
-"      ivec3 coord = ivec3( cube_coord );\n"
-"      uvec4 index_sample = texelFetch( uLightsIndex, coord, 0 );\n"
-"\n"
-"      uint light_count = (index_sample.x & 0x3u) + (index_sample.y & 0x3u);\n"
-"      return vec3( float(light_count)*(1.0/6.0), 0.0, 0.5 );\n"
-"   }\n"
-"\n"
-"   // FIXME: this coord should absolutely must be clamped!\n"
-"   \n"
-"   ivec3 coord = ivec3( cube_coord );\n"
-"   uvec4 index_sample = texelFetch( uLightsIndex, coord, 0 );\n"
-"\n"
-"   total_light += \n"
-"      scene_calculate_packed_light_patch( index_sample.x,\n"
-"                                          halfview, co, normal ) \n"
-"                                          * light_mask;\n"
-"   total_light += \n"
-"      scene_calculate_packed_light_patch( index_sample.y,\n"
-"                                          halfview, co, normal )\n"
-"                                          * light_mask;\n"
-"\n"
-"   // Take a section of the sky function to give us a matching fog colour\n"
-"\n"
-"   vec3 fog_colour  = clearskies_ambient( -halfview );\n"
-"   float sun_theta  = dot( -halfview, g_sun_dir.xyz );\n"
-"   float sun_size   = max( 0.0, sun_theta * 0.5 + 0.5 );\n"
-"   float sun_shape  = sun_size * max(g_sun_dir.y,0.0) * 0.5;\n"
-"         \n"
-"   vec3 sun_colour  = mix( vec3(1.0), g_sunset_colour.rgb, g_sunset_phase*0.5 );\n"
-"        sun_colour *= sun_shape;\n"
-"\n"
-"   fog_colour += sun_colour;\n"
-"   return scene_apply_fog( diffuse * total_light, fog_colour, fdist );\n"
-"}\n"
-"\n"
-"#line      9        0 \n"
-"\n"
-"float sdLine( vec3 p, vec3 a, vec3 b )\n"
-"{\n"
-"  vec3 pa = p - a;\n"
-"  vec3 ba = b - a;\n"
-"\n"
-"  float h = clamp( dot(pa,ba)/dot(ba,ba), 0.0, 1.0 );\n"
-"  return length( pa - ba*h );\n"
-"}\n"
-"\n"
-"float compute_board_shadow()\n"
-"{\n"
-"   // player shadow\n"
-"   float dist_to_player = max( 0.0, sdLine( aWorldCo, g_board_0.xyz,\n"
-"                                                      g_board_1.xyz )-0.1 );\n"
-"   float player_shadow = max( 1.0-dist_to_player*2.7, 0.0 );\n"
-"   player_shadow *= player_shadow*player_shadow*player_shadow;\n"
-"\n"
-"   return 1.0 - player_shadow*0.8;\n"
-"}\n"
-"\n"
-"vec3 scene_compute_lighting( vec3 diffuse, vec3 normal, vec3 co )\n"
-"{\n"
-"   return world_compute_lighting( diffuse, normal, co, compute_board_shadow() );\n"
-"}\n"
-"\n"
-"#line      9        0 \n"
-"\n"
-"// Water blending\n"
-"// ==============\n"
-"\n"
-"float water_depth( vec3 pos, vec3 halfview )\n"
-"{\n"
-"   vec3 pnorm = g_water_plane.xyz;\n"
-"   float pdist = g_water_plane.w;\n"
-"\n"
-"   float d = dot( pnorm, halfview );\n"
-"   float t = dot((pnorm*pdist - pos), pnorm) / d;\n"
-"   return t * g_water_fog;\n"
-"}\n"
-"\n"
-"void main()\n"
-"{\n"
-"   vec3 halfview = normalize( uCamera - aWorldCo );\n"
-"   float depth = water_depth( aWorldCo, halfview );\n"
-"   FragColor = vec4( depth, 0.0, 0.0, 0.0 );\n"
-"}\n"
-""},
-};
-
-static GLuint _uniform_scene_depth_uMdl;
-static GLuint _uniform_scene_depth_uPv;
-static GLuint _uniform_scene_depth_uPvmPrev;
-static GLuint _uniform_scene_depth_uCamera;
-static GLuint _uniform_scene_depth_uBoard0;
-static GLuint _uniform_scene_depth_uBoard1;
-static GLuint _uniform_scene_depth_g_world_depth;
-static GLuint _uniform_scene_depth_uLightsArray;
-static GLuint _uniform_scene_depth_uLightsIndex;
-static void shader_scene_depth_uMdl(m4x3f m){
-   glUniformMatrix4x3fv(_uniform_scene_depth_uMdl,1,GL_FALSE,(float*)m);
+   glUniformMatrix4x3fv(_uniform_scene_depth_uMdl,1,GL_FALSE,(f32*)m);
 }
-static void shader_scene_depth_uPv(m4x4f m){
-   glUniformMatrix4fv(_uniform_scene_depth_uPv,1,GL_FALSE,(float*)m);
+static inline void shader_scene_depth_uPv(m4x4f m)
+{
+   glUniformMatrix4fv(_uniform_scene_depth_uPv,1,GL_FALSE,(f32*)m);
 }
-static void shader_scene_depth_uPvmPrev(m4x4f m){
-   glUniformMatrix4fv(_uniform_scene_depth_uPvmPrev,1,GL_FALSE,(float*)m);
+static inline void shader_scene_depth_uPvmPrev(m4x4f m)
+{
+   glUniformMatrix4fv(_uniform_scene_depth_uPvmPrev,1,GL_FALSE,(f32*)m);
 }
-static void shader_scene_depth_uCamera(v3f v){
+static inline void shader_scene_depth_uCamera(v3f v)
+{
    glUniform3fv(_uniform_scene_depth_uCamera,1,v);
 }
-static void shader_scene_depth_uBoard0(v3f v){
+static inline void shader_scene_depth_uBoard0(v3f v)
+{
    glUniform3fv(_uniform_scene_depth_uBoard0,1,v);
 }
-static void shader_scene_depth_uBoard1(v3f v){
+static inline void shader_scene_depth_uBoard1(v3f v)
+{
    glUniform3fv(_uniform_scene_depth_uBoard1,1,v);
 }
-static void shader_scene_depth_g_world_depth(int i){
+static inline void shader_scene_depth_g_world_depth(int i)
+{
    glUniform1i(_uniform_scene_depth_g_world_depth,i);
 }
-static void shader_scene_depth_register(void){
-   vg_shader_register( &_shader_scene_depth );
-}
-static void shader_scene_depth_use(void){ glUseProgram(_shader_scene_depth.id); }
-static void shader_scene_depth_link(void){
-   _uniform_scene_depth_uMdl = glGetUniformLocation( _shader_scene_depth.id, "uMdl" );
-   _uniform_scene_depth_uPv = glGetUniformLocation( _shader_scene_depth.id, "uPv" );
-   _uniform_scene_depth_uPvmPrev = glGetUniformLocation( _shader_scene_depth.id, "uPvmPrev" );
-   _uniform_scene_depth_uCamera = glGetUniformLocation( _shader_scene_depth.id, "uCamera" );
-   _uniform_scene_depth_uBoard0 = glGetUniformLocation( _shader_scene_depth.id, "uBoard0" );
-   _uniform_scene_depth_uBoard1 = glGetUniformLocation( _shader_scene_depth.id, "uBoard1" );
-   _uniform_scene_depth_g_world_depth = glGetUniformLocation( _shader_scene_depth.id, "g_world_depth" );
-   _uniform_scene_depth_uLightsArray = glGetUniformLocation( _shader_scene_depth.id, "uLightsArray" );
-   _uniform_scene_depth_uLightsIndex = glGetUniformLocation( _shader_scene_depth.id, "uLightsIndex" );
+static inline void shader_scene_depth_use(void);
+static inline void shader_scene_depth_use(void)
+{
+   glUseProgram(_shader_scene_depth.id);
 }
-#endif /* SHADER_scene_depth_H */
index 041dcd89af8104e7f0e06fd4c315dbe3857632a0..2f4249ecc84ef90648ae760f3f03742dac8e697a 100644 (file)
-#ifndef SHADER_scene_foliage_H
-#define SHADER_scene_foliage_H
-static void shader_scene_foliage_link(void);
-static void shader_scene_foliage_register(void);
-static struct vg_shader _shader_scene_foliage = {
-   .name = "scene_foliage",
-   .link = shader_scene_foliage_link,
-   .vs = 
+#pragma once
+#include "vg/vg_engine.h"
+extern struct vg_shader _shader_scene_foliage;
+extern GLuint _uniform_scene_foliage_uMdl;
+extern GLuint _uniform_scene_foliage_uPv;
+extern GLuint _uniform_scene_foliage_uPvmPrev;
+extern GLuint _uniform_scene_foliage_uTime;
+extern GLuint _uniform_scene_foliage_uTexGarbage;
+extern GLuint _uniform_scene_foliage_uTexMain;
+extern GLuint _uniform_scene_foliage_uCamera;
+extern GLuint _uniform_scene_foliage_uPlane;
+extern GLuint _uniform_scene_foliage_g_world_depth;
+extern GLuint _uniform_scene_foliage_uLightsArray;
+extern GLuint _uniform_scene_foliage_uLightsIndex;
+static inline void shader_scene_foliage_uMdl(m4x3f m)
 {
-.orig_file = "shaders/scene_foliage.vs",
-.static_src = 
-"layout (location=0) in vec3  a_co;\n"
-"layout (location=1) in vec4  a_norm;\n"
-"layout (location=2) in vec2  a_uv;\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      6        0 \n"
-"\n"
-"uniform mat4x3 uMdl;\n"
-"uniform mat4   uPv;\n"
-"uniform mat4   uPvmPrev;\n"
-"uniform float uTime;\n"
-"\n"
-"out vec2 aUv;\n"
-"out vec4 aNorm;\n"
-"out vec3 aCo;\n"
-"out vec3 aWorldCo;\n"
-"\n"
-"void main(){\n"
-"   vec4 vsine = sin(vec4(uTime + a_co.x, uTime*0.7 + a_co.z,uTime,uTime*1.3));\n"
-"   vec3 co = a_co + vsine.xyz * a_norm.w * 0.5;\n"
-"   \n"
-"   vec3 world_pos0 = uMdl     * vec4( co, 1.0 );\n"
-"   vec4 vproj0     = uPv      * vec4( world_pos0, 1.0 );\n"
-"   vec4 vproj1     = uPvmPrev * vec4( co, 1.0 );\n"
-"\n"
-"   vs_motion_out( vproj0, vproj1 );\n"
-"\n"
-"   gl_Position = vproj0;\n"
-"\n"
-"   aUv = a_uv;\n"
-"   aNorm = vec4( mat3(uMdl) * a_norm.xyz, a_norm.w );\n"
-"   aCo = a_co;\n"
-"   aWorldCo = world_pos0;\n"
-"}\n"
-""},
-   .fs = 
-{
-.orig_file = "shaders/scene_foliage.fs",
-.static_src = 
-"uniform sampler2D uTexGarbage;\n"
-"uniform sampler2D uTexMain;\n"
-"uniform vec3 uCamera;\n"
-"uniform vec4 uPlane;\n"
-"\n"
-"const float CLEARSKIES_LIGHT_DOT_MIN = 0.4;\n"
-"#line       1        1 \n"
-"// :D\n"
-"\n"
-"in vec2 aUv;\n"
-"in vec4 aNorm;\n"
-"in vec3 aCo;\n"
-"in vec3 aWorldCo;\n"
-"\n"
-"#line       1        1 \n"
-"layout (location = 0) out vec4 oColour;\n"
-"\n"
-"// OpenGL wiki: Recommends do not use vec3 because of drivers. hence the v4s...\n"
-"layout (std140) uniform ub_world_lighting\n"
-"{\n"
-"   vec4 g_cube_min;\n"
-"   vec4 g_cube_inv_range;\n"
-"\n"
-"   vec4 g_water_plane;\n"
-"   vec4 g_depth_bounds;\n"
-"\n"
-"   vec4 g_daysky_colour;\n"
-"   vec4 g_nightsky_colour;\n"
-"   vec4 g_sunset_colour;\n"
-"   vec4 g_ambient_colour;\n"
-"   vec4 g_sunset_ambient;\n"
-"   vec4 g_sun_colour;\n"
-"   vec4 g_sun_dir;\n"
-"   vec4 g_board_0;\n"
-"   vec4 g_board_1;\n"
-"\n"
-"   float g_water_fog;\n"
-"   float g_time;\n"
-"   float g_realtime;\n"
-"   float g_shadow_length;\n"
-"   float g_shadow_spread;\n"
-"\n"
-"   float g_time_of_day;\n"
-"   float g_day_phase;\n"
-"   float g_sunset_phase;\n"
-"\n"
-"   int g_light_preview;\n"
-"   int g_shadow_samples;\n"
-"\n"
-"   int g_debug_indices;\n"
-"   int g_debug_complexity;\n"
-"};\n"
-"\n"
-"uniform sampler2D g_world_depth;\n"
-"uniform samplerBuffer uLightsArray;\n"
-"uniform usampler3D uLightsIndex;\n"
-"\n"
-"#line       1        1 \n"
-"//const vec3  DAYSKY_COLOUR   = vec3( 0.37, 0.54, 0.97 );\n"
-"//const vec3  NIGHTSKY_COLOUR = vec3( 0.03, 0.05, 0.20 );\n"
-"//const vec3  SUNSET_COLOUR   = vec3( 1.00, 0.32, 0.01 );\n"
-"//const vec3  AMBIENT_COLOUR  = vec3( 0.13, 0.17, 0.35 );\n"
-"//const vec3  SUNSET_AMBIENT  = vec3( 0.25, 0.17, 0.51 );\n"
-"//const vec3  SUN_COLOUR      = vec3( 1.10, 0.89, 0.35 );\n"
-"\n"
-"const float SUN_ANGLE       = 0.0001;\n"
-"const float PI              = 3.14159265358979323846264;\n"
-"\n"
-"//struct world_info\n"
-"//{\n"
-"//   float time,\n"
-"//         time_of_day,\n"
-"//         day_phase,\n"
-"//         sunset_phase;\n"
-"//   \n"
-"//   vec3 sun_dir;\n"
-"//};\n"
-"\n"
-"vec3 rand33(vec3 p3)\n"
-"{\n"
-"      p3 = fract(p3 * vec3(.1031, .1030, .0973));\n"
-"   p3 += dot(p3, p3.yxz+33.33);\n"
-"   return fract((p3.xxy + p3.yxx)*p3.zyx);\n"
-"}\n"
-"\n"
-"float stars( vec3 rd, float rr, float size ){\n"
-"   vec3 co = rd * rr;\n"
-"\n"
-"   float a = atan(co.y, length(co.xz)) + 4.0 * PI;\n"
-"\n"
-"   float spaces = 1.0 / rr;\n"
-"   size = (rr * 0.0015) * fwidth(a) * 1000.0 * size;\n"
-"   a -= mod(a, spaces) - spaces * 0.5;\n"
-"\n"
-"   float count = floor(sqrt(pow(rr, 2.0) * (1.0 - pow(sin(a), 2.0))) * 3.0);\n"
-"   \n"
-"   float plane = atan(co.z, co.x) + 4.0 * PI;\n"
-"   plane = plane - mod(plane, PI / count);\n"
-"\n"
-"   vec2 delta = rand33(vec3(plane, a, 0.0)).xy;\n"
-"\n"
-"   float level = sin(a + spaces * (delta.y - 0.5) * (1.0 - size)) * rr;\n"
-"   float ydist = sqrt(rr * rr - level * level);\n"
-"   float angle = plane + (PI * (delta.x * (1.0-size) + size * 0.5) / count);\n"
-"   vec3 center = vec3(cos(angle) * ydist, level, sin(angle) * ydist);\n"
-"   float star = smoothstep(size, 0.0, distance(center, co));\n"
-"   return star;\n"
-"}\n"
-"\n"
-"float luminance( vec3 v )\n"
-"{\n"
-"   return dot( v, vec3(0.2126, 0.7152, 0.0722) );\n"
-"}\n"
-"\n"
-"vec3 clearskies_ambient( vec3 dir )\n"
-"{\n"
-"   float sun_azimuth  = g_sunset_phase * (dot( dir.xz, g_sun_dir.xz )*0.4+0.6);\n"
-"   float sky_gradient = dir.y;\n"
-"   \n"
-"   /* Blend phase colours */\n"
-"   vec3 ambient  = g_daysky_colour.rgb   * (g_day_phase-g_sunset_phase*0.1);\n"
-"        ambient += g_sunset_colour.rgb   * (1.0-dir.y*0.5)*sun_azimuth;\n"
-"        ambient += g_nightsky_colour.rgb * (1.0-g_day_phase);\n"
-"   \n"
-"   /* Add gradient */\n"
-"        ambient -= sky_gradient * luminance(ambient);\n"
-"        \n"
-"   return ambient;\n"
-"}\n"
-"\n"
-"vec3 clearskies_sky( vec3 ray_dir )\n"
-"{\n"
-"   ray_dir.y = abs( ray_dir.y );\n"
-"   vec3 sky_colour  = clearskies_ambient( ray_dir );\n"
-"   \n"
-"   /* Sun */\n"
-"   float sun_theta  = dot( ray_dir, g_sun_dir.xyz );\n"
-"   float sun_size   = max( 0.0, sun_theta * 0.5 + 0.5 + SUN_ANGLE );\n"
-"   float sun_shape  = pow( sun_size, 2000.0 );\n"
-"         sun_shape += sun_size * max(g_sun_dir.y,0.0) * 0.5;\n"
-"         \n"
-"   vec3 sun_colour  = mix( vec3(1.0), g_sunset_colour.rgb, g_sunset_phase*0.5 );\n"
-"        sun_colour *= sun_shape;\n"
-"\n"
-"   \n"
-"   float star = 0.0;\n"
-"   float star_blend = 10.0*max(0.0,(1.0-g_day_phase*2.0));\n"
-"\n"
-"   if( star_blend > 0.001 ){\n"
-"      for( float j = 1.0; j <= 4.1; j += 1.0 ){\n"
-"         float m = mix(0.6, 0.9, smoothstep(1.0, 2.0, j));\n"
-"         star += stars( ray_dir, 1.94 * pow( 1.64, j ), m ) * (1.0/pow(4.0, j));\n"
-"      }\n"
-"   }\n"
-"   \n"
-"   vec3 composite   = sky_colour + sun_colour + star*star_blend;\n"
-"   return composite;\n"
-"}\n"
-"\n"
-"vec3 clearskies_lighting( vec3 normal, float shadow, vec3 halfview )\n"
-"{\n"
-"   float fresnel = 1.0 - abs(dot(normal,halfview));\n"
-"\n"
-"   vec3  reflect_colour = mix( g_daysky_colour.rgb, g_sunset_colour.rgb, \n"
-"                               g_sunset_phase );\n"
-"\n"
-"   vec3  sky_reflection = 0.5 * fresnel * reflect_colour;\n"
-"   vec3  light_sun      = max( CLEARSKIES_LIGHT_DOT_MIN, \n"
-"                               dot(normal,g_sun_dir.xyz)*0.75+0.25\n"
-"                           ) * g_sun_colour.rgb * g_day_phase;\n"
-"\n"
-"   float scaled_shadow = max( shadow, 1.0 - max(g_sun_dir.y,0.0) );\n"
-"   vec3 ambient = mix( g_ambient_colour.rgb, g_sunset_ambient.rgb, \n"
-"                       g_sunset_phase );\n"
-"\n"
-"   return ambient + (light_sun + sky_reflection) * shadow;\n"
-"}\n"
-"\n"
-"#line     44        0 \n"
-"\n"
-"float world_depth_sample( vec3 pos )\n"
-"{\n"
-"   vec2 depth_coord = (pos.xz - g_depth_bounds.xy) * g_depth_bounds.zw; \n"
-"   return texture( g_world_depth, depth_coord ).r;\n"
-"}\n"
-"\n"
-"float world_water_depth( vec3 pos )\n"
-"{\n"
-"   float ref_depth = g_water_plane.y*g_water_plane.w;\n"
-"   return world_depth_sample( pos ) - ref_depth;\n"
-"}\n"
-"\n"
-"float shadow_sample( vec3 co ){\n"
-"   float height_sample = world_depth_sample( co );\n"
-"\n"
-"   float fdelta = height_sample - co.y;\n"
-"   return clamp( fdelta, 0.2, 0.4 )-0.2;\n"
-"}\n"
-"\n"
-"float newlight_compute_sun_shadow( vec3 co, vec3 dir ){\n"
-"   if( g_shadow_samples == 0 ){\n"
-"      return 1.0;\n"
-"   }\n"
-"\n"
-"   float fspread = g_shadow_spread;\n"
-"   float flength = g_shadow_length;\n"
-"\n"
-"   float famt = 0.0;\n"
-"   famt += shadow_sample(co+(dir+vec3(-0.56,0.55, 0.30)*fspread)*flength*0.1);\n"
-"   famt += shadow_sample(co+(dir+vec3( 0.80,0.68, 0.34)*fspread)*flength*0.2);\n"
-"   famt += shadow_sample(co+(dir+vec3( 0.78,0.07,-0.06)*fspread)*flength*0.3);\n"
-"   famt += shadow_sample(co+(dir+vec3(-0.59,0.07,-0.42)*fspread)*flength*0.4);\n"
-"\n"
-"   //famt+=shadow_sample(co+(dir+vec3(-0.790,-0.933,-0.875)*fspread)*flength*0.5);\n"
-"   //famt+=shadow_sample(co+(dir+vec3( 0.807,-0.690, 0.472)*fspread)*flength*0.6);\n"
-"   //famt+=shadow_sample(co+(dir+vec3( 0.522,-0.379, 0.350)*fspread)*flength*0.7);\n"
-"   //famt+=shadow_sample(co+(dir+vec3( 0.483, 0.201, 0.306)*fspread)*flength*0.8);\n"
-"\n"
-"   return 1.0 - famt;\n"
-"}\n"
-"\n"
-"float newlight_specular( vec3 wnormal, vec3 dir, vec3 halfview, float exponent )\n"
-"{\n"
-"   vec3 specdir = reflect( -dir, wnormal );\n"
-"   return pow(max(dot( halfview, specdir ), 0.0), exponent);\n"
-"}\n"
-"\n"
-"vec3 scene_apply_fog( vec3 vfrag, vec3 colour, float fdist ){\n"
-"   float dist = pow(fdist*0.0010,0.78);\n"
-"   return mix( vfrag, colour, min( 1.0, dist ) );\n"
-"}\n"
-"\n"
-"vec3 scene_calculate_light( int light_index, \n"
-"                            vec3 halfview, vec3 co, vec3 normal )\n"
-"{\n"
-"   vec4 light_colour = texelFetch( uLightsArray, light_index+0 );\n"
-"   vec4 light_co     = texelFetch( uLightsArray, light_index+1 );\n"
-"   vec4 light_dir    = texelFetch( uLightsArray, light_index+2 );\n"
-"\n"
-"   vec3 light_delta = light_co.xyz-co;\n"
-"   float dist2 = dot(light_delta,light_delta);\n"
-"\n"
-"   light_delta = normalize( light_delta );\n"
-"\n"
-"   float quadratic = dist2*100.0;\n"
-"   float attenuation  = 1.0/( 1.0 + quadratic );\n"
-"         attenuation *= max( dot( light_delta, normal ), 0.0 );\n"
-"\n"
-"   float falloff = max( 0.0, 1.0-(dist2*light_co.w) );\n"
-"\n"
-"   if( light_dir.w < 0.999999 ){\n"
-"      float spot_theta = max( 0.0, dot( light_delta, -light_dir.xyz ) );\n"
-"      falloff *= max( 0.0, (spot_theta - light_dir.w) / (1.0-light_dir.w) );\n"
-"   }\n"
-"\n"
-"   return light_colour.rgb * attenuation * falloff \n"
-"            * step( g_day_phase, light_colour.w );\n"
-"}\n"
-"\n"
-"vec3 scene_calculate_packed_light_patch( uint packed_index, \n"
-"                                         vec3 halfview, vec3 co, vec3 normal )\n"
-"{\n"
-"   uint light_count = packed_index & 0x3u;\n"
-"\n"
-"   vec3 l = vec3(0.0);\n"
-"\n"
-"   if( light_count >= 1u ){\n"
-"      int index_0 = int( ((packed_index >>  2u) & 0x3ffu) * 3u );\n"
-"      int index_1 = int( ((packed_index >> 12u) & 0x3ffu) * 3u );\n"
-"      int index_2 = int( ((packed_index >> 22u) & 0x3ffu) * 3u );\n"
-"\n"
-"      l += scene_calculate_light( index_0, halfview, co, normal );\n"
-"\n"
-"      if( light_count >= 2u ){\n"
-"         l += scene_calculate_light( index_1, halfview, co, normal );\n"
-"\n"
-"         if( light_count >= 3u ){\n"
-"            l += scene_calculate_light( index_2, halfview, co, normal );\n"
-"         }\n"
-"      }\n"
-"   }\n"
-"\n"
-"   return l;\n"
-"}\n"
-"\n"
-"vec3 world_compute_lighting( vec3 diffuse, vec3 normal, vec3 co,\n"
-"                             float light_mask )\n"
-"{\n"
-"   if( g_light_preview == 1 )\n"
-"      diffuse = vec3(0.75);\n"
-"\n"
-"   // Lighting\n"
-"   vec3 halfview = uCamera - co;\n"
-"   float fdist = length(halfview);\n"
-"   halfview /= fdist;\n"
-"\n"
-"   float world_shadow = newlight_compute_sun_shadow( \n"
-"               co, g_sun_dir.xyz * (1.0/(max(g_sun_dir.y,0.0)+0.2)) );\n"
-"\n"
-"   vec3 total_light = clearskies_lighting( \n"
-"                           normal, min( light_mask, world_shadow ), halfview );\n"
-"\n"
-"   vec3 cube_coord = (co - g_cube_min.xyz) * g_cube_inv_range.xyz;\n"
-"        cube_coord = floor( cube_coord );\n"
-"\n"
-"   if( g_debug_indices == 1 )\n"
-"   {\n"
-"      return rand33(cube_coord);\n"
-"   }\n"
-"\n"
-"   if( g_debug_complexity == 1 )\n"
-"   {\n"
-"      ivec3 coord = ivec3( cube_coord );\n"
-"      uvec4 index_sample = texelFetch( uLightsIndex, coord, 0 );\n"
-"\n"
-"      uint light_count = (index_sample.x & 0x3u) + (index_sample.y & 0x3u);\n"
-"      return vec3( float(light_count)*(1.0/6.0), 0.0, 0.5 );\n"
-"   }\n"
-"\n"
-"   // FIXME: this coord should absolutely must be clamped!\n"
-"   \n"
-"   ivec3 coord = ivec3( cube_coord );\n"
-"   uvec4 index_sample = texelFetch( uLightsIndex, coord, 0 );\n"
-"\n"
-"   total_light += \n"
-"      scene_calculate_packed_light_patch( index_sample.x,\n"
-"                                          halfview, co, normal ) \n"
-"                                          * light_mask;\n"
-"   total_light += \n"
-"      scene_calculate_packed_light_patch( index_sample.y,\n"
-"                                          halfview, co, normal )\n"
-"                                          * light_mask;\n"
-"\n"
-"   // Take a section of the sky function to give us a matching fog colour\n"
-"\n"
-"   vec3 fog_colour  = clearskies_ambient( -halfview );\n"
-"   float sun_theta  = dot( -halfview, g_sun_dir.xyz );\n"
-"   float sun_size   = max( 0.0, sun_theta * 0.5 + 0.5 );\n"
-"   float sun_shape  = sun_size * max(g_sun_dir.y,0.0) * 0.5;\n"
-"         \n"
-"   vec3 sun_colour  = mix( vec3(1.0), g_sunset_colour.rgb, g_sunset_phase*0.5 );\n"
-"        sun_colour *= sun_shape;\n"
-"\n"
-"   fog_colour += sun_colour;\n"
-"   return scene_apply_fog( diffuse * total_light, fog_colour, fdist );\n"
-"}\n"
-"\n"
-"#line      9        0 \n"
-"\n"
-"float sdLine( vec3 p, vec3 a, vec3 b )\n"
-"{\n"
-"  vec3 pa = p - a;\n"
-"  vec3 ba = b - a;\n"
-"\n"
-"  float h = clamp( dot(pa,ba)/dot(ba,ba), 0.0, 1.0 );\n"
-"  return length( pa - ba*h );\n"
-"}\n"
-"\n"
-"float compute_board_shadow()\n"
-"{\n"
-"   // player shadow\n"
-"   float dist_to_player = max( 0.0, sdLine( aWorldCo, g_board_0.xyz,\n"
-"                                                      g_board_1.xyz )-0.1 );\n"
-"   float player_shadow = max( 1.0-dist_to_player*2.7, 0.0 );\n"
-"   player_shadow *= player_shadow*player_shadow*player_shadow;\n"
-"\n"
-"   return 1.0 - player_shadow*0.8;\n"
-"}\n"
-"\n"
-"vec3 scene_compute_lighting( vec3 diffuse, vec3 normal, vec3 co )\n"
-"{\n"
-"   return world_compute_lighting( diffuse, normal, co, compute_board_shadow() );\n"
-"}\n"
-"\n"
-"#line      8        0 \n"
-"#line       1        2 \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      9        0 \n"
-"\n"
-"void main(){\n"
-"   compute_motion_vectors();\n"
-"\n"
-"   vec3 vfrag = vec3(0.5,0.5,0.5);\n"
-"   vec4 vsamplemain = texture( uTexMain, aUv );\n"
-"   vec3 qnorm = aNorm.xyz;\n"
-"\n"
-"   if( vsamplemain.a < 0.15 )\n"
-"     discard;\n"
-"\n"
-"   vfrag = vsamplemain.rgb;\n"
-"\n"
-"   if( g_light_preview == 1 ){\n"
-"      vfrag = vec3(0.5);\n"
-"   }\n"
-"\n"
-"   vfrag = scene_compute_lighting( vfrag, qnorm, aWorldCo );\n"
-"   oColour = vec4(vfrag, 1.0);\n"
-"}\n"
-""},
-};
-
-static GLuint _uniform_scene_foliage_uMdl;
-static GLuint _uniform_scene_foliage_uPv;
-static GLuint _uniform_scene_foliage_uPvmPrev;
-static GLuint _uniform_scene_foliage_uTime;
-static GLuint _uniform_scene_foliage_uTexGarbage;
-static GLuint _uniform_scene_foliage_uTexMain;
-static GLuint _uniform_scene_foliage_uCamera;
-static GLuint _uniform_scene_foliage_uPlane;
-static GLuint _uniform_scene_foliage_g_world_depth;
-static GLuint _uniform_scene_foliage_uLightsArray;
-static GLuint _uniform_scene_foliage_uLightsIndex;
-static void shader_scene_foliage_uMdl(m4x3f m){
-   glUniformMatrix4x3fv(_uniform_scene_foliage_uMdl,1,GL_FALSE,(float*)m);
+   glUniformMatrix4x3fv(_uniform_scene_foliage_uMdl,1,GL_FALSE,(f32*)m);
 }
-static void shader_scene_foliage_uPv(m4x4f m){
-   glUniformMatrix4fv(_uniform_scene_foliage_uPv,1,GL_FALSE,(float*)m);
+static inline void shader_scene_foliage_uPv(m4x4f m)
+{
+   glUniformMatrix4fv(_uniform_scene_foliage_uPv,1,GL_FALSE,(f32*)m);
 }
-static void shader_scene_foliage_uPvmPrev(m4x4f m){
-   glUniformMatrix4fv(_uniform_scene_foliage_uPvmPrev,1,GL_FALSE,(float*)m);
+static inline void shader_scene_foliage_uPvmPrev(m4x4f m)
+{
+   glUniformMatrix4fv(_uniform_scene_foliage_uPvmPrev,1,GL_FALSE,(f32*)m);
 }
-static void shader_scene_foliage_uTime(float f){
+static inline void shader_scene_foliage_uTime(f32 f)
+{
    glUniform1f(_uniform_scene_foliage_uTime,f);
 }
-static void shader_scene_foliage_uTexGarbage(int i){
+static inline void shader_scene_foliage_uTexGarbage(int i)
+{
    glUniform1i(_uniform_scene_foliage_uTexGarbage,i);
 }
-static void shader_scene_foliage_uTexMain(int i){
+static inline void shader_scene_foliage_uTexMain(int i)
+{
    glUniform1i(_uniform_scene_foliage_uTexMain,i);
 }
-static void shader_scene_foliage_uCamera(v3f v){
+static inline void shader_scene_foliage_uCamera(v3f v)
+{
    glUniform3fv(_uniform_scene_foliage_uCamera,1,v);
 }
-static void shader_scene_foliage_uPlane(v4f v){
+static inline void shader_scene_foliage_uPlane(v4f v)
+{
    glUniform4fv(_uniform_scene_foliage_uPlane,1,v);
 }
-static void shader_scene_foliage_g_world_depth(int i){
+static inline void shader_scene_foliage_g_world_depth(int i)
+{
    glUniform1i(_uniform_scene_foliage_g_world_depth,i);
 }
-static void shader_scene_foliage_register(void){
-   vg_shader_register( &_shader_scene_foliage );
-}
-static void shader_scene_foliage_use(void){ glUseProgram(_shader_scene_foliage.id); }
-static void shader_scene_foliage_link(void){
-   _uniform_scene_foliage_uMdl = glGetUniformLocation( _shader_scene_foliage.id, "uMdl" );
-   _uniform_scene_foliage_uPv = glGetUniformLocation( _shader_scene_foliage.id, "uPv" );
-   _uniform_scene_foliage_uPvmPrev = glGetUniformLocation( _shader_scene_foliage.id, "uPvmPrev" );
-   _uniform_scene_foliage_uTime = glGetUniformLocation( _shader_scene_foliage.id, "uTime" );
-   _uniform_scene_foliage_uTexGarbage = glGetUniformLocation( _shader_scene_foliage.id, "uTexGarbage" );
-   _uniform_scene_foliage_uTexMain = glGetUniformLocation( _shader_scene_foliage.id, "uTexMain" );
-   _uniform_scene_foliage_uCamera = glGetUniformLocation( _shader_scene_foliage.id, "uCamera" );
-   _uniform_scene_foliage_uPlane = glGetUniformLocation( _shader_scene_foliage.id, "uPlane" );
-   _uniform_scene_foliage_g_world_depth = glGetUniformLocation( _shader_scene_foliage.id, "g_world_depth" );
-   _uniform_scene_foliage_uLightsArray = glGetUniformLocation( _shader_scene_foliage.id, "uLightsArray" );
-   _uniform_scene_foliage_uLightsIndex = glGetUniformLocation( _shader_scene_foliage.id, "uLightsIndex" );
+static inline void shader_scene_foliage_use(void);
+static inline void shader_scene_foliage_use(void)
+{
+   glUseProgram(_shader_scene_foliage.id);
 }
-#endif /* SHADER_scene_foliage_H */
index 891947d25f369d92d21f35bdb243413ae9fc603d..53f22c3d72467aa811ce78629e44a1fcaa26c0ae 100644 (file)
-#ifndef SHADER_scene_font_H
-#define SHADER_scene_font_H
-static void shader_scene_font_link(void);
-static void shader_scene_font_register(void);
-static struct vg_shader _shader_scene_font = {
-   .name = "scene_font",
-   .link = shader_scene_font_link,
-   .vs = 
+#pragma once
+#include "vg/vg_engine.h"
+extern struct vg_shader _shader_scene_font;
+extern GLuint _uniform_scene_font_uMdl;
+extern GLuint _uniform_scene_font_uPv;
+extern GLuint _uniform_scene_font_uPvmPrev;
+extern GLuint _uniform_scene_font_uOffset;
+extern GLuint _uniform_scene_font_uTexGarbage;
+extern GLuint _uniform_scene_font_uTexMain;
+extern GLuint _uniform_scene_font_uCamera;
+extern GLuint _uniform_scene_font_uTime;
+extern GLuint _uniform_scene_font_uOpacity;
+extern GLuint _uniform_scene_font_uColourize;
+extern GLuint _uniform_scene_font_g_world_depth;
+extern GLuint _uniform_scene_font_uLightsArray;
+extern GLuint _uniform_scene_font_uLightsIndex;
+static inline void shader_scene_font_uMdl(m4x3f m)
 {
-.orig_file = "shaders/model_font.vs",
-.static_src = 
-"layout (location=0) in vec3 a_co;\n"
-"layout (location=1) in vec3 a_norm;\n"
-"layout (location=2) in vec2 a_uv;\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      6        0 \n"
-"\n"
-"uniform mat4x3 uMdl;\n"
-"uniform mat4 uPv;\n"
-"uniform mat4 uPvmPrev;\n"
-"uniform vec4 uOffset;\n"
-"\n"
-"out vec2 aUv;\n"
-"out vec4 aNorm;\n"
-"out vec3 aCo;\n"
-"out vec3 aWorldCo;\n"
-"\n"
-"void main()\n"
-"{\n"
-"   vec3 co = a_co*uOffset.w+uOffset.xyz;\n"
-"   vec3 world_pos0 = uMdl     * vec4( co, 1.0 );\n"
-"   vec4 vproj0     = uPv      * vec4( world_pos0, 1.0 );\n"
-"   vec4 vproj1     = uPvmPrev * vec4( co, 1.0 );\n"
-"\n"
-"   vs_motion_out( vproj0, vproj1 );\n"
-"\n"
-"   gl_Position = vproj0;\n"
-"\n"
-"   aUv = a_uv;\n"
-"   aNorm = vec4( mat3(uMdl) * a_norm, 0.0 );\n"
-"   aCo = co;\n"
-"   aWorldCo = world_pos0;\n"
-"}\n"
-""},
-   .fs = 
-{
-.orig_file = "shaders/scene_font.fs",
-.static_src = 
-"uniform sampler2D uTexGarbage; // unused\n"
-"uniform sampler2D uTexMain;    // unused\n"
-"uniform vec3 uCamera;\n"
-"uniform float uTime;\n"
-"uniform float uOpacity;\n"
-"uniform float uColourize;\n"
-"\n"
-"#line       1        1 \n"
-"// :D\n"
-"const float CLEARSKIES_LIGHT_DOT_MIN = 0.0;\n"
-"\n"
-"#line      9        0 \n"
-"#line       1        2 \n"
-"// :D\n"
-"\n"
-"in vec2 aUv;\n"
-"in vec4 aNorm;\n"
-"in vec3 aCo;\n"
-"in vec3 aWorldCo;\n"
-"\n"
-"#line       1        1 \n"
-"layout (location = 0) out vec4 oColour;\n"
-"\n"
-"// OpenGL wiki: Recommends do not use vec3 because of drivers. hence the v4s...\n"
-"layout (std140) uniform ub_world_lighting\n"
-"{\n"
-"   vec4 g_cube_min;\n"
-"   vec4 g_cube_inv_range;\n"
-"\n"
-"   vec4 g_water_plane;\n"
-"   vec4 g_depth_bounds;\n"
-"\n"
-"   vec4 g_daysky_colour;\n"
-"   vec4 g_nightsky_colour;\n"
-"   vec4 g_sunset_colour;\n"
-"   vec4 g_ambient_colour;\n"
-"   vec4 g_sunset_ambient;\n"
-"   vec4 g_sun_colour;\n"
-"   vec4 g_sun_dir;\n"
-"   vec4 g_board_0;\n"
-"   vec4 g_board_1;\n"
-"\n"
-"   float g_water_fog;\n"
-"   float g_time;\n"
-"   float g_realtime;\n"
-"   float g_shadow_length;\n"
-"   float g_shadow_spread;\n"
-"\n"
-"   float g_time_of_day;\n"
-"   float g_day_phase;\n"
-"   float g_sunset_phase;\n"
-"\n"
-"   int g_light_preview;\n"
-"   int g_shadow_samples;\n"
-"\n"
-"   int g_debug_indices;\n"
-"   int g_debug_complexity;\n"
-"};\n"
-"\n"
-"uniform sampler2D g_world_depth;\n"
-"uniform samplerBuffer uLightsArray;\n"
-"uniform usampler3D uLightsIndex;\n"
-"\n"
-"#line       1        1 \n"
-"//const vec3  DAYSKY_COLOUR   = vec3( 0.37, 0.54, 0.97 );\n"
-"//const vec3  NIGHTSKY_COLOUR = vec3( 0.03, 0.05, 0.20 );\n"
-"//const vec3  SUNSET_COLOUR   = vec3( 1.00, 0.32, 0.01 );\n"
-"//const vec3  AMBIENT_COLOUR  = vec3( 0.13, 0.17, 0.35 );\n"
-"//const vec3  SUNSET_AMBIENT  = vec3( 0.25, 0.17, 0.51 );\n"
-"//const vec3  SUN_COLOUR      = vec3( 1.10, 0.89, 0.35 );\n"
-"\n"
-"const float SUN_ANGLE       = 0.0001;\n"
-"const float PI              = 3.14159265358979323846264;\n"
-"\n"
-"//struct world_info\n"
-"//{\n"
-"//   float time,\n"
-"//         time_of_day,\n"
-"//         day_phase,\n"
-"//         sunset_phase;\n"
-"//   \n"
-"//   vec3 sun_dir;\n"
-"//};\n"
-"\n"
-"vec3 rand33(vec3 p3)\n"
-"{\n"
-"      p3 = fract(p3 * vec3(.1031, .1030, .0973));\n"
-"   p3 += dot(p3, p3.yxz+33.33);\n"
-"   return fract((p3.xxy + p3.yxx)*p3.zyx);\n"
-"}\n"
-"\n"
-"float stars( vec3 rd, float rr, float size ){\n"
-"   vec3 co = rd * rr;\n"
-"\n"
-"   float a = atan(co.y, length(co.xz)) + 4.0 * PI;\n"
-"\n"
-"   float spaces = 1.0 / rr;\n"
-"   size = (rr * 0.0015) * fwidth(a) * 1000.0 * size;\n"
-"   a -= mod(a, spaces) - spaces * 0.5;\n"
-"\n"
-"   float count = floor(sqrt(pow(rr, 2.0) * (1.0 - pow(sin(a), 2.0))) * 3.0);\n"
-"   \n"
-"   float plane = atan(co.z, co.x) + 4.0 * PI;\n"
-"   plane = plane - mod(plane, PI / count);\n"
-"\n"
-"   vec2 delta = rand33(vec3(plane, a, 0.0)).xy;\n"
-"\n"
-"   float level = sin(a + spaces * (delta.y - 0.5) * (1.0 - size)) * rr;\n"
-"   float ydist = sqrt(rr * rr - level * level);\n"
-"   float angle = plane + (PI * (delta.x * (1.0-size) + size * 0.5) / count);\n"
-"   vec3 center = vec3(cos(angle) * ydist, level, sin(angle) * ydist);\n"
-"   float star = smoothstep(size, 0.0, distance(center, co));\n"
-"   return star;\n"
-"}\n"
-"\n"
-"float luminance( vec3 v )\n"
-"{\n"
-"   return dot( v, vec3(0.2126, 0.7152, 0.0722) );\n"
-"}\n"
-"\n"
-"vec3 clearskies_ambient( vec3 dir )\n"
-"{\n"
-"   float sun_azimuth  = g_sunset_phase * (dot( dir.xz, g_sun_dir.xz )*0.4+0.6);\n"
-"   float sky_gradient = dir.y;\n"
-"   \n"
-"   /* Blend phase colours */\n"
-"   vec3 ambient  = g_daysky_colour.rgb   * (g_day_phase-g_sunset_phase*0.1);\n"
-"        ambient += g_sunset_colour.rgb   * (1.0-dir.y*0.5)*sun_azimuth;\n"
-"        ambient += g_nightsky_colour.rgb * (1.0-g_day_phase);\n"
-"   \n"
-"   /* Add gradient */\n"
-"        ambient -= sky_gradient * luminance(ambient);\n"
-"        \n"
-"   return ambient;\n"
-"}\n"
-"\n"
-"vec3 clearskies_sky( vec3 ray_dir )\n"
-"{\n"
-"   ray_dir.y = abs( ray_dir.y );\n"
-"   vec3 sky_colour  = clearskies_ambient( ray_dir );\n"
-"   \n"
-"   /* Sun */\n"
-"   float sun_theta  = dot( ray_dir, g_sun_dir.xyz );\n"
-"   float sun_size   = max( 0.0, sun_theta * 0.5 + 0.5 + SUN_ANGLE );\n"
-"   float sun_shape  = pow( sun_size, 2000.0 );\n"
-"         sun_shape += sun_size * max(g_sun_dir.y,0.0) * 0.5;\n"
-"         \n"
-"   vec3 sun_colour  = mix( vec3(1.0), g_sunset_colour.rgb, g_sunset_phase*0.5 );\n"
-"        sun_colour *= sun_shape;\n"
-"\n"
-"   \n"
-"   float star = 0.0;\n"
-"   float star_blend = 10.0*max(0.0,(1.0-g_day_phase*2.0));\n"
-"\n"
-"   if( star_blend > 0.001 ){\n"
-"      for( float j = 1.0; j <= 4.1; j += 1.0 ){\n"
-"         float m = mix(0.6, 0.9, smoothstep(1.0, 2.0, j));\n"
-"         star += stars( ray_dir, 1.94 * pow( 1.64, j ), m ) * (1.0/pow(4.0, j));\n"
-"      }\n"
-"   }\n"
-"   \n"
-"   vec3 composite   = sky_colour + sun_colour + star*star_blend;\n"
-"   return composite;\n"
-"}\n"
-"\n"
-"vec3 clearskies_lighting( vec3 normal, float shadow, vec3 halfview )\n"
-"{\n"
-"   float fresnel = 1.0 - abs(dot(normal,halfview));\n"
-"\n"
-"   vec3  reflect_colour = mix( g_daysky_colour.rgb, g_sunset_colour.rgb, \n"
-"                               g_sunset_phase );\n"
-"\n"
-"   vec3  sky_reflection = 0.5 * fresnel * reflect_colour;\n"
-"   vec3  light_sun      = max( CLEARSKIES_LIGHT_DOT_MIN, \n"
-"                               dot(normal,g_sun_dir.xyz)*0.75+0.25\n"
-"                           ) * g_sun_colour.rgb * g_day_phase;\n"
-"\n"
-"   float scaled_shadow = max( shadow, 1.0 - max(g_sun_dir.y,0.0) );\n"
-"   vec3 ambient = mix( g_ambient_colour.rgb, g_sunset_ambient.rgb, \n"
-"                       g_sunset_phase );\n"
-"\n"
-"   return ambient + (light_sun + sky_reflection) * shadow;\n"
-"}\n"
-"\n"
-"#line     44        0 \n"
-"\n"
-"float world_depth_sample( vec3 pos )\n"
-"{\n"
-"   vec2 depth_coord = (pos.xz - g_depth_bounds.xy) * g_depth_bounds.zw; \n"
-"   return texture( g_world_depth, depth_coord ).r;\n"
-"}\n"
-"\n"
-"float world_water_depth( vec3 pos )\n"
-"{\n"
-"   float ref_depth = g_water_plane.y*g_water_plane.w;\n"
-"   return world_depth_sample( pos ) - ref_depth;\n"
-"}\n"
-"\n"
-"float shadow_sample( vec3 co ){\n"
-"   float height_sample = world_depth_sample( co );\n"
-"\n"
-"   float fdelta = height_sample - co.y;\n"
-"   return clamp( fdelta, 0.2, 0.4 )-0.2;\n"
-"}\n"
-"\n"
-"float newlight_compute_sun_shadow( vec3 co, vec3 dir ){\n"
-"   if( g_shadow_samples == 0 ){\n"
-"      return 1.0;\n"
-"   }\n"
-"\n"
-"   float fspread = g_shadow_spread;\n"
-"   float flength = g_shadow_length;\n"
-"\n"
-"   float famt = 0.0;\n"
-"   famt += shadow_sample(co+(dir+vec3(-0.56,0.55, 0.30)*fspread)*flength*0.1);\n"
-"   famt += shadow_sample(co+(dir+vec3( 0.80,0.68, 0.34)*fspread)*flength*0.2);\n"
-"   famt += shadow_sample(co+(dir+vec3( 0.78,0.07,-0.06)*fspread)*flength*0.3);\n"
-"   famt += shadow_sample(co+(dir+vec3(-0.59,0.07,-0.42)*fspread)*flength*0.4);\n"
-"\n"
-"   //famt+=shadow_sample(co+(dir+vec3(-0.790,-0.933,-0.875)*fspread)*flength*0.5);\n"
-"   //famt+=shadow_sample(co+(dir+vec3( 0.807,-0.690, 0.472)*fspread)*flength*0.6);\n"
-"   //famt+=shadow_sample(co+(dir+vec3( 0.522,-0.379, 0.350)*fspread)*flength*0.7);\n"
-"   //famt+=shadow_sample(co+(dir+vec3( 0.483, 0.201, 0.306)*fspread)*flength*0.8);\n"
-"\n"
-"   return 1.0 - famt;\n"
-"}\n"
-"\n"
-"float newlight_specular( vec3 wnormal, vec3 dir, vec3 halfview, float exponent )\n"
-"{\n"
-"   vec3 specdir = reflect( -dir, wnormal );\n"
-"   return pow(max(dot( halfview, specdir ), 0.0), exponent);\n"
-"}\n"
-"\n"
-"vec3 scene_apply_fog( vec3 vfrag, vec3 colour, float fdist ){\n"
-"   float dist = pow(fdist*0.0010,0.78);\n"
-"   return mix( vfrag, colour, min( 1.0, dist ) );\n"
-"}\n"
-"\n"
-"vec3 scene_calculate_light( int light_index, \n"
-"                            vec3 halfview, vec3 co, vec3 normal )\n"
-"{\n"
-"   vec4 light_colour = texelFetch( uLightsArray, light_index+0 );\n"
-"   vec4 light_co     = texelFetch( uLightsArray, light_index+1 );\n"
-"   vec4 light_dir    = texelFetch( uLightsArray, light_index+2 );\n"
-"\n"
-"   vec3 light_delta = light_co.xyz-co;\n"
-"   float dist2 = dot(light_delta,light_delta);\n"
-"\n"
-"   light_delta = normalize( light_delta );\n"
-"\n"
-"   float quadratic = dist2*100.0;\n"
-"   float attenuation  = 1.0/( 1.0 + quadratic );\n"
-"         attenuation *= max( dot( light_delta, normal ), 0.0 );\n"
-"\n"
-"   float falloff = max( 0.0, 1.0-(dist2*light_co.w) );\n"
-"\n"
-"   if( light_dir.w < 0.999999 ){\n"
-"      float spot_theta = max( 0.0, dot( light_delta, -light_dir.xyz ) );\n"
-"      falloff *= max( 0.0, (spot_theta - light_dir.w) / (1.0-light_dir.w) );\n"
-"   }\n"
-"\n"
-"   return light_colour.rgb * attenuation * falloff \n"
-"            * step( g_day_phase, light_colour.w );\n"
-"}\n"
-"\n"
-"vec3 scene_calculate_packed_light_patch( uint packed_index, \n"
-"                                         vec3 halfview, vec3 co, vec3 normal )\n"
-"{\n"
-"   uint light_count = packed_index & 0x3u;\n"
-"\n"
-"   vec3 l = vec3(0.0);\n"
-"\n"
-"   if( light_count >= 1u ){\n"
-"      int index_0 = int( ((packed_index >>  2u) & 0x3ffu) * 3u );\n"
-"      int index_1 = int( ((packed_index >> 12u) & 0x3ffu) * 3u );\n"
-"      int index_2 = int( ((packed_index >> 22u) & 0x3ffu) * 3u );\n"
-"\n"
-"      l += scene_calculate_light( index_0, halfview, co, normal );\n"
-"\n"
-"      if( light_count >= 2u ){\n"
-"         l += scene_calculate_light( index_1, halfview, co, normal );\n"
-"\n"
-"         if( light_count >= 3u ){\n"
-"            l += scene_calculate_light( index_2, halfview, co, normal );\n"
-"         }\n"
-"      }\n"
-"   }\n"
-"\n"
-"   return l;\n"
-"}\n"
-"\n"
-"vec3 world_compute_lighting( vec3 diffuse, vec3 normal, vec3 co,\n"
-"                             float light_mask )\n"
-"{\n"
-"   if( g_light_preview == 1 )\n"
-"      diffuse = vec3(0.75);\n"
-"\n"
-"   // Lighting\n"
-"   vec3 halfview = uCamera - co;\n"
-"   float fdist = length(halfview);\n"
-"   halfview /= fdist;\n"
-"\n"
-"   float world_shadow = newlight_compute_sun_shadow( \n"
-"               co, g_sun_dir.xyz * (1.0/(max(g_sun_dir.y,0.0)+0.2)) );\n"
-"\n"
-"   vec3 total_light = clearskies_lighting( \n"
-"                           normal, min( light_mask, world_shadow ), halfview );\n"
-"\n"
-"   vec3 cube_coord = (co - g_cube_min.xyz) * g_cube_inv_range.xyz;\n"
-"        cube_coord = floor( cube_coord );\n"
-"\n"
-"   if( g_debug_indices == 1 )\n"
-"   {\n"
-"      return rand33(cube_coord);\n"
-"   }\n"
-"\n"
-"   if( g_debug_complexity == 1 )\n"
-"   {\n"
-"      ivec3 coord = ivec3( cube_coord );\n"
-"      uvec4 index_sample = texelFetch( uLightsIndex, coord, 0 );\n"
-"\n"
-"      uint light_count = (index_sample.x & 0x3u) + (index_sample.y & 0x3u);\n"
-"      return vec3( float(light_count)*(1.0/6.0), 0.0, 0.5 );\n"
-"   }\n"
-"\n"
-"   // FIXME: this coord should absolutely must be clamped!\n"
-"   \n"
-"   ivec3 coord = ivec3( cube_coord );\n"
-"   uvec4 index_sample = texelFetch( uLightsIndex, coord, 0 );\n"
-"\n"
-"   total_light += \n"
-"      scene_calculate_packed_light_patch( index_sample.x,\n"
-"                                          halfview, co, normal ) \n"
-"                                          * light_mask;\n"
-"   total_light += \n"
-"      scene_calculate_packed_light_patch( index_sample.y,\n"
-"                                          halfview, co, normal )\n"
-"                                          * light_mask;\n"
-"\n"
-"   // Take a section of the sky function to give us a matching fog colour\n"
-"\n"
-"   vec3 fog_colour  = clearskies_ambient( -halfview );\n"
-"   float sun_theta  = dot( -halfview, g_sun_dir.xyz );\n"
-"   float sun_size   = max( 0.0, sun_theta * 0.5 + 0.5 );\n"
-"   float sun_shape  = sun_size * max(g_sun_dir.y,0.0) * 0.5;\n"
-"         \n"
-"   vec3 sun_colour  = mix( vec3(1.0), g_sunset_colour.rgb, g_sunset_phase*0.5 );\n"
-"        sun_colour *= sun_shape;\n"
-"\n"
-"   fog_colour += sun_colour;\n"
-"   return scene_apply_fog( diffuse * total_light, fog_colour, fdist );\n"
-"}\n"
-"\n"
-"#line      9        0 \n"
-"\n"
-"float sdLine( vec3 p, vec3 a, vec3 b )\n"
-"{\n"
-"  vec3 pa = p - a;\n"
-"  vec3 ba = b - a;\n"
-"\n"
-"  float h = clamp( dot(pa,ba)/dot(ba,ba), 0.0, 1.0 );\n"
-"  return length( pa - ba*h );\n"
-"}\n"
-"\n"
-"float compute_board_shadow()\n"
-"{\n"
-"   // player shadow\n"
-"   float dist_to_player = max( 0.0, sdLine( aWorldCo, g_board_0.xyz,\n"
-"                                                      g_board_1.xyz )-0.1 );\n"
-"   float player_shadow = max( 1.0-dist_to_player*2.7, 0.0 );\n"
-"   player_shadow *= player_shadow*player_shadow*player_shadow;\n"
-"\n"
-"   return 1.0 - player_shadow*0.8;\n"
-"}\n"
-"\n"
-"vec3 scene_compute_lighting( vec3 diffuse, vec3 normal, vec3 co )\n"
-"{\n"
-"   return world_compute_lighting( diffuse, normal, co, compute_board_shadow() );\n"
-"}\n"
-"\n"
-"#line     10        0 \n"
-"#line       1        3 \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     11        0 \n"
-"\n"
-"vec3 pal( float t ){\n"
-"   vec3 a = vec3(0.30,0.3,0.3);\n"
-"   vec3 b = vec3(0.8);\n"
-"   vec3 c = vec3(0.28,0.3,0.4);\n"
-"   vec3 d = vec3(0.00,0.1,0.1);\n"
-"   return a + b*cos( 6.28318*(c*t+d) );\n"
-"}\n"
-"\n"
-"void main(){\n"
-"   compute_motion_vectors();\n"
-"   vec3 vfrag = vec3(0.5,0.5,0.5);\n"
-"   vec3 qnorm = aNorm.xyz;\n"
-"\n"
-"   //vec4 vsamplemain = texture( uTexMain, aUv );\n"
-"   //vfrag = vsamplemain.rgb;\n"
-"\n"
-"   vec4 spread0 = uTime*0.0002*vec4(  17.3,-19.6, 23.2,-47.7 );\n"
-"   vec4 spread1 = uTime*0.0002*vec4( -13.3, 12.6,-28.2, 14.7 );\n"
-"\n"
-"   vec2 p = aCo.xy + vec2(0.3);\n"
-"   float a = atan( p.y/p.x );\n"
-"   vec4 v0 = step( vec4(0.5), fract(vec4(a) + spread0) );\n"
-"   vec4 v1 = step( vec4(0.5), fract(vec4(a) + spread1) );\n"
-"\n"
-"   float d = ( v0.x+v0.y+v0.z+v0.w +\n"
-"               v1.x+v1.y+v1.z+v1.w ) * 0.125;\n"
-"   \n"
-"   float dither = fract(dot(vec2(171.0,231.0),gl_FragCoord.xy)/71.0);\n"
-"   float x = d*0.8+length(p)*0.3;\n"
-"   x = (floor(x*8.0) + step(dither, fract(x * 8.0))) / 8.0;\n"
-"\n"
-"   if( x + (uOpacity*2.0-1.0) < 0.5 ) \n"
-"      discard;\n"
-"\n"
-"   vfrag = mix( vec3(x), pal( x ), uColourize );\n"
-"\n"
-"   if( g_light_preview == 1 ){\n"
-"      vfrag = vec3(0.5);\n"
-"   }\n"
-"\n"
-"   vfrag = scene_compute_lighting( vfrag, qnorm, aWorldCo );\n"
-"   oColour = vec4( vfrag, 1.0 );\n"
-"}\n"
-""},
-};
-
-static GLuint _uniform_scene_font_uMdl;
-static GLuint _uniform_scene_font_uPv;
-static GLuint _uniform_scene_font_uPvmPrev;
-static GLuint _uniform_scene_font_uOffset;
-static GLuint _uniform_scene_font_uTexGarbage;
-static GLuint _uniform_scene_font_uTexMain;
-static GLuint _uniform_scene_font_uCamera;
-static GLuint _uniform_scene_font_uTime;
-static GLuint _uniform_scene_font_uOpacity;
-static GLuint _uniform_scene_font_uColourize;
-static GLuint _uniform_scene_font_g_world_depth;
-static GLuint _uniform_scene_font_uLightsArray;
-static GLuint _uniform_scene_font_uLightsIndex;
-static void shader_scene_font_uMdl(m4x3f m){
-   glUniformMatrix4x3fv(_uniform_scene_font_uMdl,1,GL_FALSE,(float*)m);
+   glUniformMatrix4x3fv(_uniform_scene_font_uMdl,1,GL_FALSE,(f32*)m);
 }
-static void shader_scene_font_uPv(m4x4f m){
-   glUniformMatrix4fv(_uniform_scene_font_uPv,1,GL_FALSE,(float*)m);
+static inline void shader_scene_font_uPv(m4x4f m)
+{
+   glUniformMatrix4fv(_uniform_scene_font_uPv,1,GL_FALSE,(f32*)m);
 }
-static void shader_scene_font_uPvmPrev(m4x4f m){
-   glUniformMatrix4fv(_uniform_scene_font_uPvmPrev,1,GL_FALSE,(float*)m);
+static inline void shader_scene_font_uPvmPrev(m4x4f m)
+{
+   glUniformMatrix4fv(_uniform_scene_font_uPvmPrev,1,GL_FALSE,(f32*)m);
 }
-static void shader_scene_font_uOffset(v4f v){
+static inline void shader_scene_font_uOffset(v4f v)
+{
    glUniform4fv(_uniform_scene_font_uOffset,1,v);
 }
-static void shader_scene_font_uTexGarbage(int i){
+static inline void shader_scene_font_uTexGarbage(int i)
+{
    glUniform1i(_uniform_scene_font_uTexGarbage,i);
 }
-static void shader_scene_font_uTexMain(int i){
+static inline void shader_scene_font_uTexMain(int i)
+{
    glUniform1i(_uniform_scene_font_uTexMain,i);
 }
-static void shader_scene_font_uCamera(v3f v){
+static inline void shader_scene_font_uCamera(v3f v)
+{
    glUniform3fv(_uniform_scene_font_uCamera,1,v);
 }
-static void shader_scene_font_uTime(float f){
+static inline void shader_scene_font_uTime(f32 f)
+{
    glUniform1f(_uniform_scene_font_uTime,f);
 }
-static void shader_scene_font_uOpacity(float f){
+static inline void shader_scene_font_uOpacity(f32 f)
+{
    glUniform1f(_uniform_scene_font_uOpacity,f);
 }
-static void shader_scene_font_uColourize(float f){
+static inline void shader_scene_font_uColourize(f32 f)
+{
    glUniform1f(_uniform_scene_font_uColourize,f);
 }
-static void shader_scene_font_g_world_depth(int i){
+static inline void shader_scene_font_g_world_depth(int i)
+{
    glUniform1i(_uniform_scene_font_g_world_depth,i);
 }
-static void shader_scene_font_register(void){
-   vg_shader_register( &_shader_scene_font );
-}
-static void shader_scene_font_use(void){ glUseProgram(_shader_scene_font.id); }
-static void shader_scene_font_link(void){
-   _uniform_scene_font_uMdl = glGetUniformLocation( _shader_scene_font.id, "uMdl" );
-   _uniform_scene_font_uPv = glGetUniformLocation( _shader_scene_font.id, "uPv" );
-   _uniform_scene_font_uPvmPrev = glGetUniformLocation( _shader_scene_font.id, "uPvmPrev" );
-   _uniform_scene_font_uOffset = glGetUniformLocation( _shader_scene_font.id, "uOffset" );
-   _uniform_scene_font_uTexGarbage = glGetUniformLocation( _shader_scene_font.id, "uTexGarbage" );
-   _uniform_scene_font_uTexMain = glGetUniformLocation( _shader_scene_font.id, "uTexMain" );
-   _uniform_scene_font_uCamera = glGetUniformLocation( _shader_scene_font.id, "uCamera" );
-   _uniform_scene_font_uTime = glGetUniformLocation( _shader_scene_font.id, "uTime" );
-   _uniform_scene_font_uOpacity = glGetUniformLocation( _shader_scene_font.id, "uOpacity" );
-   _uniform_scene_font_uColourize = glGetUniformLocation( _shader_scene_font.id, "uColourize" );
-   _uniform_scene_font_g_world_depth = glGetUniformLocation( _shader_scene_font.id, "g_world_depth" );
-   _uniform_scene_font_uLightsArray = glGetUniformLocation( _shader_scene_font.id, "uLightsArray" );
-   _uniform_scene_font_uLightsIndex = glGetUniformLocation( _shader_scene_font.id, "uLightsIndex" );
+static inline void shader_scene_font_use(void);
+static inline void shader_scene_font_use(void)
+{
+   glUseProgram(_shader_scene_font.id);
 }
-#endif /* SHADER_scene_font_H */
index c47d6ab71a205cb23457362449bc083e1a286f50..81476396f7d8591b539962245dc3d4b7f07dab0b 100644 (file)
-#ifndef SHADER_scene_fxglow_H
-#define SHADER_scene_fxglow_H
-static void shader_scene_fxglow_link(void);
-static void shader_scene_fxglow_register(void);
-static struct vg_shader _shader_scene_fxglow = {
-   .name = "scene_fxglow",
-   .link = shader_scene_fxglow_link,
-   .vs = 
+#pragma once
+#include "vg/vg_engine.h"
+extern struct vg_shader _shader_scene_fxglow;
+extern GLuint _uniform_scene_fxglow_uMdl;
+extern GLuint _uniform_scene_fxglow_uPv;
+extern GLuint _uniform_scene_fxglow_uPvmPrev;
+extern GLuint _uniform_scene_fxglow_uUvOffset;
+extern GLuint _uniform_scene_fxglow_uTexMain;
+extern GLuint _uniform_scene_fxglow_uCamera;
+extern GLuint _uniform_scene_fxglow_g_world_depth;
+extern GLuint _uniform_scene_fxglow_uLightsArray;
+extern GLuint _uniform_scene_fxglow_uLightsIndex;
+static inline void shader_scene_fxglow_uMdl(m4x3f m)
 {
-.orig_file = "shaders/scene_fxglow.vs",
-.static_src = 
-"layout (location=0) in vec3  a_co;\n"
-"layout (location=1) in vec4  a_norm;\n"
-"layout (location=2) in vec2  a_uv;\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      6        0 \n"
-"\n"
-"uniform mat4x3 uMdl;\n"
-"uniform mat4   uPv;\n"
-"uniform mat4   uPvmPrev;\n"
-"uniform vec2   uUvOffset;\n"
-"\n"
-"out vec2 aUv;\n"
-"out vec4 aNorm;\n"
-"out vec3 aCo;\n"
-"out vec3 aWorldCo;\n"
-"\n"
-"void main()\n"
-"{\n"
-"   vec3 world_pos0 = uMdl     * vec4( a_co, 1.0 );\n"
-"   vec4 vproj0     = uPv      * vec4( world_pos0, 1.0 );\n"
-"   vec4 vproj1     = uPvmPrev * vec4( a_co, 1.0 );\n"
-"\n"
-"   vs_motion_out( vproj0, vproj1 );\n"
-"\n"
-"   gl_Position = vproj0;\n"
-"\n"
-"   aUv = a_uv + uUvOffset;\n"
-"   aNorm = vec4( mat3(uMdl) * a_norm.xyz, a_norm.w );\n"
-"   aCo = a_co;\n"
-"   aWorldCo = world_pos0;\n"
-"}\n"
-""},
-   .fs = 
-{
-.orig_file = "shaders/scene_fxglow.fs",
-.static_src = 
-"uniform sampler2D uTexMain;\n"
-"uniform vec3 uCamera;\n"
-"\n"
-"#line       1        1 \n"
-"// :D\n"
-"const float CLEARSKIES_LIGHT_DOT_MIN = 0.0;\n"
-"\n"
-"#line      5        0 \n"
-"#line       1        2 \n"
-"// :D\n"
-"\n"
-"in vec2 aUv;\n"
-"in vec4 aNorm;\n"
-"in vec3 aCo;\n"
-"in vec3 aWorldCo;\n"
-"\n"
-"#line       1        1 \n"
-"layout (location = 0) out vec4 oColour;\n"
-"\n"
-"// OpenGL wiki: Recommends do not use vec3 because of drivers. hence the v4s...\n"
-"layout (std140) uniform ub_world_lighting\n"
-"{\n"
-"   vec4 g_cube_min;\n"
-"   vec4 g_cube_inv_range;\n"
-"\n"
-"   vec4 g_water_plane;\n"
-"   vec4 g_depth_bounds;\n"
-"\n"
-"   vec4 g_daysky_colour;\n"
-"   vec4 g_nightsky_colour;\n"
-"   vec4 g_sunset_colour;\n"
-"   vec4 g_ambient_colour;\n"
-"   vec4 g_sunset_ambient;\n"
-"   vec4 g_sun_colour;\n"
-"   vec4 g_sun_dir;\n"
-"   vec4 g_board_0;\n"
-"   vec4 g_board_1;\n"
-"\n"
-"   float g_water_fog;\n"
-"   float g_time;\n"
-"   float g_realtime;\n"
-"   float g_shadow_length;\n"
-"   float g_shadow_spread;\n"
-"\n"
-"   float g_time_of_day;\n"
-"   float g_day_phase;\n"
-"   float g_sunset_phase;\n"
-"\n"
-"   int g_light_preview;\n"
-"   int g_shadow_samples;\n"
-"\n"
-"   int g_debug_indices;\n"
-"   int g_debug_complexity;\n"
-"};\n"
-"\n"
-"uniform sampler2D g_world_depth;\n"
-"uniform samplerBuffer uLightsArray;\n"
-"uniform usampler3D uLightsIndex;\n"
-"\n"
-"#line       1        1 \n"
-"//const vec3  DAYSKY_COLOUR   = vec3( 0.37, 0.54, 0.97 );\n"
-"//const vec3  NIGHTSKY_COLOUR = vec3( 0.03, 0.05, 0.20 );\n"
-"//const vec3  SUNSET_COLOUR   = vec3( 1.00, 0.32, 0.01 );\n"
-"//const vec3  AMBIENT_COLOUR  = vec3( 0.13, 0.17, 0.35 );\n"
-"//const vec3  SUNSET_AMBIENT  = vec3( 0.25, 0.17, 0.51 );\n"
-"//const vec3  SUN_COLOUR      = vec3( 1.10, 0.89, 0.35 );\n"
-"\n"
-"const float SUN_ANGLE       = 0.0001;\n"
-"const float PI              = 3.14159265358979323846264;\n"
-"\n"
-"//struct world_info\n"
-"//{\n"
-"//   float time,\n"
-"//         time_of_day,\n"
-"//         day_phase,\n"
-"//         sunset_phase;\n"
-"//   \n"
-"//   vec3 sun_dir;\n"
-"//};\n"
-"\n"
-"vec3 rand33(vec3 p3)\n"
-"{\n"
-"      p3 = fract(p3 * vec3(.1031, .1030, .0973));\n"
-"   p3 += dot(p3, p3.yxz+33.33);\n"
-"   return fract((p3.xxy + p3.yxx)*p3.zyx);\n"
-"}\n"
-"\n"
-"float stars( vec3 rd, float rr, float size ){\n"
-"   vec3 co = rd * rr;\n"
-"\n"
-"   float a = atan(co.y, length(co.xz)) + 4.0 * PI;\n"
-"\n"
-"   float spaces = 1.0 / rr;\n"
-"   size = (rr * 0.0015) * fwidth(a) * 1000.0 * size;\n"
-"   a -= mod(a, spaces) - spaces * 0.5;\n"
-"\n"
-"   float count = floor(sqrt(pow(rr, 2.0) * (1.0 - pow(sin(a), 2.0))) * 3.0);\n"
-"   \n"
-"   float plane = atan(co.z, co.x) + 4.0 * PI;\n"
-"   plane = plane - mod(plane, PI / count);\n"
-"\n"
-"   vec2 delta = rand33(vec3(plane, a, 0.0)).xy;\n"
-"\n"
-"   float level = sin(a + spaces * (delta.y - 0.5) * (1.0 - size)) * rr;\n"
-"   float ydist = sqrt(rr * rr - level * level);\n"
-"   float angle = plane + (PI * (delta.x * (1.0-size) + size * 0.5) / count);\n"
-"   vec3 center = vec3(cos(angle) * ydist, level, sin(angle) * ydist);\n"
-"   float star = smoothstep(size, 0.0, distance(center, co));\n"
-"   return star;\n"
-"}\n"
-"\n"
-"float luminance( vec3 v )\n"
-"{\n"
-"   return dot( v, vec3(0.2126, 0.7152, 0.0722) );\n"
-"}\n"
-"\n"
-"vec3 clearskies_ambient( vec3 dir )\n"
-"{\n"
-"   float sun_azimuth  = g_sunset_phase * (dot( dir.xz, g_sun_dir.xz )*0.4+0.6);\n"
-"   float sky_gradient = dir.y;\n"
-"   \n"
-"   /* Blend phase colours */\n"
-"   vec3 ambient  = g_daysky_colour.rgb   * (g_day_phase-g_sunset_phase*0.1);\n"
-"        ambient += g_sunset_colour.rgb   * (1.0-dir.y*0.5)*sun_azimuth;\n"
-"        ambient += g_nightsky_colour.rgb * (1.0-g_day_phase);\n"
-"   \n"
-"   /* Add gradient */\n"
-"        ambient -= sky_gradient * luminance(ambient);\n"
-"        \n"
-"   return ambient;\n"
-"}\n"
-"\n"
-"vec3 clearskies_sky( vec3 ray_dir )\n"
-"{\n"
-"   ray_dir.y = abs( ray_dir.y );\n"
-"   vec3 sky_colour  = clearskies_ambient( ray_dir );\n"
-"   \n"
-"   /* Sun */\n"
-"   float sun_theta  = dot( ray_dir, g_sun_dir.xyz );\n"
-"   float sun_size   = max( 0.0, sun_theta * 0.5 + 0.5 + SUN_ANGLE );\n"
-"   float sun_shape  = pow( sun_size, 2000.0 );\n"
-"         sun_shape += sun_size * max(g_sun_dir.y,0.0) * 0.5;\n"
-"         \n"
-"   vec3 sun_colour  = mix( vec3(1.0), g_sunset_colour.rgb, g_sunset_phase*0.5 );\n"
-"        sun_colour *= sun_shape;\n"
-"\n"
-"   \n"
-"   float star = 0.0;\n"
-"   float star_blend = 10.0*max(0.0,(1.0-g_day_phase*2.0));\n"
-"\n"
-"   if( star_blend > 0.001 ){\n"
-"      for( float j = 1.0; j <= 4.1; j += 1.0 ){\n"
-"         float m = mix(0.6, 0.9, smoothstep(1.0, 2.0, j));\n"
-"         star += stars( ray_dir, 1.94 * pow( 1.64, j ), m ) * (1.0/pow(4.0, j));\n"
-"      }\n"
-"   }\n"
-"   \n"
-"   vec3 composite   = sky_colour + sun_colour + star*star_blend;\n"
-"   return composite;\n"
-"}\n"
-"\n"
-"vec3 clearskies_lighting( vec3 normal, float shadow, vec3 halfview )\n"
-"{\n"
-"   float fresnel = 1.0 - abs(dot(normal,halfview));\n"
-"\n"
-"   vec3  reflect_colour = mix( g_daysky_colour.rgb, g_sunset_colour.rgb, \n"
-"                               g_sunset_phase );\n"
-"\n"
-"   vec3  sky_reflection = 0.5 * fresnel * reflect_colour;\n"
-"   vec3  light_sun      = max( CLEARSKIES_LIGHT_DOT_MIN, \n"
-"                               dot(normal,g_sun_dir.xyz)*0.75+0.25\n"
-"                           ) * g_sun_colour.rgb * g_day_phase;\n"
-"\n"
-"   float scaled_shadow = max( shadow, 1.0 - max(g_sun_dir.y,0.0) );\n"
-"   vec3 ambient = mix( g_ambient_colour.rgb, g_sunset_ambient.rgb, \n"
-"                       g_sunset_phase );\n"
-"\n"
-"   return ambient + (light_sun + sky_reflection) * shadow;\n"
-"}\n"
-"\n"
-"#line     44        0 \n"
-"\n"
-"float world_depth_sample( vec3 pos )\n"
-"{\n"
-"   vec2 depth_coord = (pos.xz - g_depth_bounds.xy) * g_depth_bounds.zw; \n"
-"   return texture( g_world_depth, depth_coord ).r;\n"
-"}\n"
-"\n"
-"float world_water_depth( vec3 pos )\n"
-"{\n"
-"   float ref_depth = g_water_plane.y*g_water_plane.w;\n"
-"   return world_depth_sample( pos ) - ref_depth;\n"
-"}\n"
-"\n"
-"float shadow_sample( vec3 co ){\n"
-"   float height_sample = world_depth_sample( co );\n"
-"\n"
-"   float fdelta = height_sample - co.y;\n"
-"   return clamp( fdelta, 0.2, 0.4 )-0.2;\n"
-"}\n"
-"\n"
-"float newlight_compute_sun_shadow( vec3 co, vec3 dir ){\n"
-"   if( g_shadow_samples == 0 ){\n"
-"      return 1.0;\n"
-"   }\n"
-"\n"
-"   float fspread = g_shadow_spread;\n"
-"   float flength = g_shadow_length;\n"
-"\n"
-"   float famt = 0.0;\n"
-"   famt += shadow_sample(co+(dir+vec3(-0.56,0.55, 0.30)*fspread)*flength*0.1);\n"
-"   famt += shadow_sample(co+(dir+vec3( 0.80,0.68, 0.34)*fspread)*flength*0.2);\n"
-"   famt += shadow_sample(co+(dir+vec3( 0.78,0.07,-0.06)*fspread)*flength*0.3);\n"
-"   famt += shadow_sample(co+(dir+vec3(-0.59,0.07,-0.42)*fspread)*flength*0.4);\n"
-"\n"
-"   //famt+=shadow_sample(co+(dir+vec3(-0.790,-0.933,-0.875)*fspread)*flength*0.5);\n"
-"   //famt+=shadow_sample(co+(dir+vec3( 0.807,-0.690, 0.472)*fspread)*flength*0.6);\n"
-"   //famt+=shadow_sample(co+(dir+vec3( 0.522,-0.379, 0.350)*fspread)*flength*0.7);\n"
-"   //famt+=shadow_sample(co+(dir+vec3( 0.483, 0.201, 0.306)*fspread)*flength*0.8);\n"
-"\n"
-"   return 1.0 - famt;\n"
-"}\n"
-"\n"
-"float newlight_specular( vec3 wnormal, vec3 dir, vec3 halfview, float exponent )\n"
-"{\n"
-"   vec3 specdir = reflect( -dir, wnormal );\n"
-"   return pow(max(dot( halfview, specdir ), 0.0), exponent);\n"
-"}\n"
-"\n"
-"vec3 scene_apply_fog( vec3 vfrag, vec3 colour, float fdist ){\n"
-"   float dist = pow(fdist*0.0010,0.78);\n"
-"   return mix( vfrag, colour, min( 1.0, dist ) );\n"
-"}\n"
-"\n"
-"vec3 scene_calculate_light( int light_index, \n"
-"                            vec3 halfview, vec3 co, vec3 normal )\n"
-"{\n"
-"   vec4 light_colour = texelFetch( uLightsArray, light_index+0 );\n"
-"   vec4 light_co     = texelFetch( uLightsArray, light_index+1 );\n"
-"   vec4 light_dir    = texelFetch( uLightsArray, light_index+2 );\n"
-"\n"
-"   vec3 light_delta = light_co.xyz-co;\n"
-"   float dist2 = dot(light_delta,light_delta);\n"
-"\n"
-"   light_delta = normalize( light_delta );\n"
-"\n"
-"   float quadratic = dist2*100.0;\n"
-"   float attenuation  = 1.0/( 1.0 + quadratic );\n"
-"         attenuation *= max( dot( light_delta, normal ), 0.0 );\n"
-"\n"
-"   float falloff = max( 0.0, 1.0-(dist2*light_co.w) );\n"
-"\n"
-"   if( light_dir.w < 0.999999 ){\n"
-"      float spot_theta = max( 0.0, dot( light_delta, -light_dir.xyz ) );\n"
-"      falloff *= max( 0.0, (spot_theta - light_dir.w) / (1.0-light_dir.w) );\n"
-"   }\n"
-"\n"
-"   return light_colour.rgb * attenuation * falloff \n"
-"            * step( g_day_phase, light_colour.w );\n"
-"}\n"
-"\n"
-"vec3 scene_calculate_packed_light_patch( uint packed_index, \n"
-"                                         vec3 halfview, vec3 co, vec3 normal )\n"
-"{\n"
-"   uint light_count = packed_index & 0x3u;\n"
-"\n"
-"   vec3 l = vec3(0.0);\n"
-"\n"
-"   if( light_count >= 1u ){\n"
-"      int index_0 = int( ((packed_index >>  2u) & 0x3ffu) * 3u );\n"
-"      int index_1 = int( ((packed_index >> 12u) & 0x3ffu) * 3u );\n"
-"      int index_2 = int( ((packed_index >> 22u) & 0x3ffu) * 3u );\n"
-"\n"
-"      l += scene_calculate_light( index_0, halfview, co, normal );\n"
-"\n"
-"      if( light_count >= 2u ){\n"
-"         l += scene_calculate_light( index_1, halfview, co, normal );\n"
-"\n"
-"         if( light_count >= 3u ){\n"
-"            l += scene_calculate_light( index_2, halfview, co, normal );\n"
-"         }\n"
-"      }\n"
-"   }\n"
-"\n"
-"   return l;\n"
-"}\n"
-"\n"
-"vec3 world_compute_lighting( vec3 diffuse, vec3 normal, vec3 co,\n"
-"                             float light_mask )\n"
-"{\n"
-"   if( g_light_preview == 1 )\n"
-"      diffuse = vec3(0.75);\n"
-"\n"
-"   // Lighting\n"
-"   vec3 halfview = uCamera - co;\n"
-"   float fdist = length(halfview);\n"
-"   halfview /= fdist;\n"
-"\n"
-"   float world_shadow = newlight_compute_sun_shadow( \n"
-"               co, g_sun_dir.xyz * (1.0/(max(g_sun_dir.y,0.0)+0.2)) );\n"
-"\n"
-"   vec3 total_light = clearskies_lighting( \n"
-"                           normal, min( light_mask, world_shadow ), halfview );\n"
-"\n"
-"   vec3 cube_coord = (co - g_cube_min.xyz) * g_cube_inv_range.xyz;\n"
-"        cube_coord = floor( cube_coord );\n"
-"\n"
-"   if( g_debug_indices == 1 )\n"
-"   {\n"
-"      return rand33(cube_coord);\n"
-"   }\n"
-"\n"
-"   if( g_debug_complexity == 1 )\n"
-"   {\n"
-"      ivec3 coord = ivec3( cube_coord );\n"
-"      uvec4 index_sample = texelFetch( uLightsIndex, coord, 0 );\n"
-"\n"
-"      uint light_count = (index_sample.x & 0x3u) + (index_sample.y & 0x3u);\n"
-"      return vec3( float(light_count)*(1.0/6.0), 0.0, 0.5 );\n"
-"   }\n"
-"\n"
-"   // FIXME: this coord should absolutely must be clamped!\n"
-"   \n"
-"   ivec3 coord = ivec3( cube_coord );\n"
-"   uvec4 index_sample = texelFetch( uLightsIndex, coord, 0 );\n"
-"\n"
-"   total_light += \n"
-"      scene_calculate_packed_light_patch( index_sample.x,\n"
-"                                          halfview, co, normal ) \n"
-"                                          * light_mask;\n"
-"   total_light += \n"
-"      scene_calculate_packed_light_patch( index_sample.y,\n"
-"                                          halfview, co, normal )\n"
-"                                          * light_mask;\n"
-"\n"
-"   // Take a section of the sky function to give us a matching fog colour\n"
-"\n"
-"   vec3 fog_colour  = clearskies_ambient( -halfview );\n"
-"   float sun_theta  = dot( -halfview, g_sun_dir.xyz );\n"
-"   float sun_size   = max( 0.0, sun_theta * 0.5 + 0.5 );\n"
-"   float sun_shape  = sun_size * max(g_sun_dir.y,0.0) * 0.5;\n"
-"         \n"
-"   vec3 sun_colour  = mix( vec3(1.0), g_sunset_colour.rgb, g_sunset_phase*0.5 );\n"
-"        sun_colour *= sun_shape;\n"
-"\n"
-"   fog_colour += sun_colour;\n"
-"   return scene_apply_fog( diffuse * total_light, fog_colour, fdist );\n"
-"}\n"
-"\n"
-"#line      9        0 \n"
-"\n"
-"float sdLine( vec3 p, vec3 a, vec3 b )\n"
-"{\n"
-"  vec3 pa = p - a;\n"
-"  vec3 ba = b - a;\n"
-"\n"
-"  float h = clamp( dot(pa,ba)/dot(ba,ba), 0.0, 1.0 );\n"
-"  return length( pa - ba*h );\n"
-"}\n"
-"\n"
-"float compute_board_shadow()\n"
-"{\n"
-"   // player shadow\n"
-"   float dist_to_player = max( 0.0, sdLine( aWorldCo, g_board_0.xyz,\n"
-"                                                      g_board_1.xyz )-0.1 );\n"
-"   float player_shadow = max( 1.0-dist_to_player*2.7, 0.0 );\n"
-"   player_shadow *= player_shadow*player_shadow*player_shadow;\n"
-"\n"
-"   return 1.0 - player_shadow*0.8;\n"
-"}\n"
-"\n"
-"vec3 scene_compute_lighting( vec3 diffuse, vec3 normal, vec3 co )\n"
-"{\n"
-"   return world_compute_lighting( diffuse, normal, co, compute_board_shadow() );\n"
-"}\n"
-"\n"
-"#line      6        0 \n"
-"#line       1        3 \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      7        0 \n"
-"\n"
-"void main(){\n"
-"   oMotionVec = vec2(0.0);\n"
-"\n"
-"   vec4 vsamplemain = texture( uTexMain, aUv );\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 = vec4( vsamplemain.rgb, 1.0 );\n"
-"}\n"
-""},
-};
-
-static GLuint _uniform_scene_fxglow_uMdl;
-static GLuint _uniform_scene_fxglow_uPv;
-static GLuint _uniform_scene_fxglow_uPvmPrev;
-static GLuint _uniform_scene_fxglow_uUvOffset;
-static GLuint _uniform_scene_fxglow_uTexMain;
-static GLuint _uniform_scene_fxglow_uCamera;
-static GLuint _uniform_scene_fxglow_g_world_depth;
-static GLuint _uniform_scene_fxglow_uLightsArray;
-static GLuint _uniform_scene_fxglow_uLightsIndex;
-static void shader_scene_fxglow_uMdl(m4x3f m){
-   glUniformMatrix4x3fv(_uniform_scene_fxglow_uMdl,1,GL_FALSE,(float*)m);
+   glUniformMatrix4x3fv(_uniform_scene_fxglow_uMdl,1,GL_FALSE,(f32*)m);
 }
-static void shader_scene_fxglow_uPv(m4x4f m){
-   glUniformMatrix4fv(_uniform_scene_fxglow_uPv,1,GL_FALSE,(float*)m);
+static inline void shader_scene_fxglow_uPv(m4x4f m)
+{
+   glUniformMatrix4fv(_uniform_scene_fxglow_uPv,1,GL_FALSE,(f32*)m);
 }
-static void shader_scene_fxglow_uPvmPrev(m4x4f m){
-   glUniformMatrix4fv(_uniform_scene_fxglow_uPvmPrev,1,GL_FALSE,(float*)m);
+static inline void shader_scene_fxglow_uPvmPrev(m4x4f m)
+{
+   glUniformMatrix4fv(_uniform_scene_fxglow_uPvmPrev,1,GL_FALSE,(f32*)m);
 }
-static void shader_scene_fxglow_uUvOffset(v2f v){
+static inline void shader_scene_fxglow_uUvOffset(v2f v)
+{
    glUniform2fv(_uniform_scene_fxglow_uUvOffset,1,v);
 }
-static void shader_scene_fxglow_uTexMain(int i){
+static inline void shader_scene_fxglow_uTexMain(int i)
+{
    glUniform1i(_uniform_scene_fxglow_uTexMain,i);
 }
-static void shader_scene_fxglow_uCamera(v3f v){
+static inline void shader_scene_fxglow_uCamera(v3f v)
+{
    glUniform3fv(_uniform_scene_fxglow_uCamera,1,v);
 }
-static void shader_scene_fxglow_g_world_depth(int i){
+static inline void shader_scene_fxglow_g_world_depth(int i)
+{
    glUniform1i(_uniform_scene_fxglow_g_world_depth,i);
 }
-static void shader_scene_fxglow_register(void){
-   vg_shader_register( &_shader_scene_fxglow );
-}
-static void shader_scene_fxglow_use(void){ glUseProgram(_shader_scene_fxglow.id); }
-static void shader_scene_fxglow_link(void){
-   _uniform_scene_fxglow_uMdl = glGetUniformLocation( _shader_scene_fxglow.id, "uMdl" );
-   _uniform_scene_fxglow_uPv = glGetUniformLocation( _shader_scene_fxglow.id, "uPv" );
-   _uniform_scene_fxglow_uPvmPrev = glGetUniformLocation( _shader_scene_fxglow.id, "uPvmPrev" );
-   _uniform_scene_fxglow_uUvOffset = glGetUniformLocation( _shader_scene_fxglow.id, "uUvOffset" );
-   _uniform_scene_fxglow_uTexMain = glGetUniformLocation( _shader_scene_fxglow.id, "uTexMain" );
-   _uniform_scene_fxglow_uCamera = glGetUniformLocation( _shader_scene_fxglow.id, "uCamera" );
-   _uniform_scene_fxglow_g_world_depth = glGetUniformLocation( _shader_scene_fxglow.id, "g_world_depth" );
-   _uniform_scene_fxglow_uLightsArray = glGetUniformLocation( _shader_scene_fxglow.id, "uLightsArray" );
-   _uniform_scene_fxglow_uLightsIndex = glGetUniformLocation( _shader_scene_fxglow.id, "uLightsIndex" );
+static inline void shader_scene_fxglow_use(void);
+static inline void shader_scene_fxglow_use(void)
+{
+   glUseProgram(_shader_scene_fxglow.id);
 }
-#endif /* SHADER_scene_fxglow_H */
index c84a5baaa62b0ac9f7b79501a3be8ca2aed3283a..3b29c99430528abd16082568728a23ef728a7a2f 100644 (file)
-#ifndef SHADER_scene_override_H
-#define SHADER_scene_override_H
-static void shader_scene_override_link(void);
-static void shader_scene_override_register(void);
-static struct vg_shader _shader_scene_override = {
-   .name = "scene_override",
-   .link = shader_scene_override_link,
-   .vs = 
+#pragma once
+#include "vg/vg_engine.h"
+extern struct vg_shader _shader_scene_override;
+extern GLuint _uniform_scene_override_uMdl;
+extern GLuint _uniform_scene_override_uPv;
+extern GLuint _uniform_scene_override_uPvmPrev;
+extern GLuint _uniform_scene_override_uNormalMtx;
+extern GLuint _uniform_scene_override_uTexGarbage;
+extern GLuint _uniform_scene_override_uTexMain;
+extern GLuint _uniform_scene_override_uCamera;
+extern GLuint _uniform_scene_override_uPlane;
+extern GLuint _uniform_scene_override_uPlayerPos;
+extern GLuint _uniform_scene_override_uSpawnPos;
+extern GLuint _uniform_scene_override_uAlphatest;
+extern GLuint _uniform_scene_override_uMapInfo;
+extern GLuint _uniform_scene_override_g_world_depth;
+extern GLuint _uniform_scene_override_uLightsArray;
+extern GLuint _uniform_scene_override_uLightsIndex;
+static inline void shader_scene_override_uMdl(m4x3f m)
 {
-.orig_file = "shaders/scene_override.vs",
-.static_src = 
-"layout (location=0) in vec3  a_co;\n"
-"layout (location=1) in vec4  a_norm;\n"
-"layout (location=2) in vec2  a_uv;\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      6        0 \n"
-"\n"
-"uniform mat4x3 uMdl;\n"
-"uniform mat4   uPv;\n"
-"uniform mat4   uPvmPrev;\n"
-"uniform mat3   uNormalMtx;\n"
-"\n"
-"out vec2 aUv;\n"
-"out vec4 aNorm;\n"
-"out vec3 aCo;\n"
-"out vec3 aWorldCo;\n"
-"\n"
-"void main()\n"
-"{\n"
-"   vec3 world_pos0 = uMdl     * vec4( a_co, 1.0 );\n"
-"   vec4 vproj0     = uPv      * vec4( world_pos0, 1.0 );\n"
-"   vec4 vproj1     = uPvmPrev * vec4( a_co, 1.0 );\n"
-"\n"
-"   vs_motion_out( vproj0, vproj1 );\n"
-"\n"
-"   gl_Position = vproj0;\n"
-"\n"
-"   aUv = a_uv;\n"
-"   aNorm = vec4( uNormalMtx * a_norm.xyz, a_norm.w );\n"
-"   aCo = a_co;\n"
-"   aWorldCo = world_pos0;\n"
-"}\n"
-""},
-   .fs = 
-{
-.orig_file = "shaders/scene_override.fs",
-.static_src = 
-"uniform sampler2D uTexGarbage;\n"
-"uniform sampler2D uTexMain;\n"
-"uniform vec3 uCamera;\n"
-"uniform vec4 uPlane;\n"
-"\n"
-"uniform vec4 uPlayerPos; /* w: distance to uSpawnPos */\n"
-"uniform vec4 uSpawnPos;  /* w: inverse distance to uPlayerPos */\n"
-"uniform bool uAlphatest;\n"
-"uniform vec4 uMapInfo; /* x: min, y: max, z: iso line amount */\n"
-"\n"
-"#line       1        1 \n"
-"// :D\n"
-"const float CLEARSKIES_LIGHT_DOT_MIN = 0.0;\n"
-"\n"
-"#line     12        0 \n"
-"#line       1        2 \n"
-"// :D\n"
-"\n"
-"in vec2 aUv;\n"
-"in vec4 aNorm;\n"
-"in vec3 aCo;\n"
-"in vec3 aWorldCo;\n"
-"\n"
-"#line       1        1 \n"
-"layout (location = 0) out vec4 oColour;\n"
-"\n"
-"// OpenGL wiki: Recommends do not use vec3 because of drivers. hence the v4s...\n"
-"layout (std140) uniform ub_world_lighting\n"
-"{\n"
-"   vec4 g_cube_min;\n"
-"   vec4 g_cube_inv_range;\n"
-"\n"
-"   vec4 g_water_plane;\n"
-"   vec4 g_depth_bounds;\n"
-"\n"
-"   vec4 g_daysky_colour;\n"
-"   vec4 g_nightsky_colour;\n"
-"   vec4 g_sunset_colour;\n"
-"   vec4 g_ambient_colour;\n"
-"   vec4 g_sunset_ambient;\n"
-"   vec4 g_sun_colour;\n"
-"   vec4 g_sun_dir;\n"
-"   vec4 g_board_0;\n"
-"   vec4 g_board_1;\n"
-"\n"
-"   float g_water_fog;\n"
-"   float g_time;\n"
-"   float g_realtime;\n"
-"   float g_shadow_length;\n"
-"   float g_shadow_spread;\n"
-"\n"
-"   float g_time_of_day;\n"
-"   float g_day_phase;\n"
-"   float g_sunset_phase;\n"
-"\n"
-"   int g_light_preview;\n"
-"   int g_shadow_samples;\n"
-"\n"
-"   int g_debug_indices;\n"
-"   int g_debug_complexity;\n"
-"};\n"
-"\n"
-"uniform sampler2D g_world_depth;\n"
-"uniform samplerBuffer uLightsArray;\n"
-"uniform usampler3D uLightsIndex;\n"
-"\n"
-"#line       1        1 \n"
-"//const vec3  DAYSKY_COLOUR   = vec3( 0.37, 0.54, 0.97 );\n"
-"//const vec3  NIGHTSKY_COLOUR = vec3( 0.03, 0.05, 0.20 );\n"
-"//const vec3  SUNSET_COLOUR   = vec3( 1.00, 0.32, 0.01 );\n"
-"//const vec3  AMBIENT_COLOUR  = vec3( 0.13, 0.17, 0.35 );\n"
-"//const vec3  SUNSET_AMBIENT  = vec3( 0.25, 0.17, 0.51 );\n"
-"//const vec3  SUN_COLOUR      = vec3( 1.10, 0.89, 0.35 );\n"
-"\n"
-"const float SUN_ANGLE       = 0.0001;\n"
-"const float PI              = 3.14159265358979323846264;\n"
-"\n"
-"//struct world_info\n"
-"//{\n"
-"//   float time,\n"
-"//         time_of_day,\n"
-"//         day_phase,\n"
-"//         sunset_phase;\n"
-"//   \n"
-"//   vec3 sun_dir;\n"
-"//};\n"
-"\n"
-"vec3 rand33(vec3 p3)\n"
-"{\n"
-"      p3 = fract(p3 * vec3(.1031, .1030, .0973));\n"
-"   p3 += dot(p3, p3.yxz+33.33);\n"
-"   return fract((p3.xxy + p3.yxx)*p3.zyx);\n"
-"}\n"
-"\n"
-"float stars( vec3 rd, float rr, float size ){\n"
-"   vec3 co = rd * rr;\n"
-"\n"
-"   float a = atan(co.y, length(co.xz)) + 4.0 * PI;\n"
-"\n"
-"   float spaces = 1.0 / rr;\n"
-"   size = (rr * 0.0015) * fwidth(a) * 1000.0 * size;\n"
-"   a -= mod(a, spaces) - spaces * 0.5;\n"
-"\n"
-"   float count = floor(sqrt(pow(rr, 2.0) * (1.0 - pow(sin(a), 2.0))) * 3.0);\n"
-"   \n"
-"   float plane = atan(co.z, co.x) + 4.0 * PI;\n"
-"   plane = plane - mod(plane, PI / count);\n"
-"\n"
-"   vec2 delta = rand33(vec3(plane, a, 0.0)).xy;\n"
-"\n"
-"   float level = sin(a + spaces * (delta.y - 0.5) * (1.0 - size)) * rr;\n"
-"   float ydist = sqrt(rr * rr - level * level);\n"
-"   float angle = plane + (PI * (delta.x * (1.0-size) + size * 0.5) / count);\n"
-"   vec3 center = vec3(cos(angle) * ydist, level, sin(angle) * ydist);\n"
-"   float star = smoothstep(size, 0.0, distance(center, co));\n"
-"   return star;\n"
-"}\n"
-"\n"
-"float luminance( vec3 v )\n"
-"{\n"
-"   return dot( v, vec3(0.2126, 0.7152, 0.0722) );\n"
-"}\n"
-"\n"
-"vec3 clearskies_ambient( vec3 dir )\n"
-"{\n"
-"   float sun_azimuth  = g_sunset_phase * (dot( dir.xz, g_sun_dir.xz )*0.4+0.6);\n"
-"   float sky_gradient = dir.y;\n"
-"   \n"
-"   /* Blend phase colours */\n"
-"   vec3 ambient  = g_daysky_colour.rgb   * (g_day_phase-g_sunset_phase*0.1);\n"
-"        ambient += g_sunset_colour.rgb   * (1.0-dir.y*0.5)*sun_azimuth;\n"
-"        ambient += g_nightsky_colour.rgb * (1.0-g_day_phase);\n"
-"   \n"
-"   /* Add gradient */\n"
-"        ambient -= sky_gradient * luminance(ambient);\n"
-"        \n"
-"   return ambient;\n"
-"}\n"
-"\n"
-"vec3 clearskies_sky( vec3 ray_dir )\n"
-"{\n"
-"   ray_dir.y = abs( ray_dir.y );\n"
-"   vec3 sky_colour  = clearskies_ambient( ray_dir );\n"
-"   \n"
-"   /* Sun */\n"
-"   float sun_theta  = dot( ray_dir, g_sun_dir.xyz );\n"
-"   float sun_size   = max( 0.0, sun_theta * 0.5 + 0.5 + SUN_ANGLE );\n"
-"   float sun_shape  = pow( sun_size, 2000.0 );\n"
-"         sun_shape += sun_size * max(g_sun_dir.y,0.0) * 0.5;\n"
-"         \n"
-"   vec3 sun_colour  = mix( vec3(1.0), g_sunset_colour.rgb, g_sunset_phase*0.5 );\n"
-"        sun_colour *= sun_shape;\n"
-"\n"
-"   \n"
-"   float star = 0.0;\n"
-"   float star_blend = 10.0*max(0.0,(1.0-g_day_phase*2.0));\n"
-"\n"
-"   if( star_blend > 0.001 ){\n"
-"      for( float j = 1.0; j <= 4.1; j += 1.0 ){\n"
-"         float m = mix(0.6, 0.9, smoothstep(1.0, 2.0, j));\n"
-"         star += stars( ray_dir, 1.94 * pow( 1.64, j ), m ) * (1.0/pow(4.0, j));\n"
-"      }\n"
-"   }\n"
-"   \n"
-"   vec3 composite   = sky_colour + sun_colour + star*star_blend;\n"
-"   return composite;\n"
-"}\n"
-"\n"
-"vec3 clearskies_lighting( vec3 normal, float shadow, vec3 halfview )\n"
-"{\n"
-"   float fresnel = 1.0 - abs(dot(normal,halfview));\n"
-"\n"
-"   vec3  reflect_colour = mix( g_daysky_colour.rgb, g_sunset_colour.rgb, \n"
-"                               g_sunset_phase );\n"
-"\n"
-"   vec3  sky_reflection = 0.5 * fresnel * reflect_colour;\n"
-"   vec3  light_sun      = max( CLEARSKIES_LIGHT_DOT_MIN, \n"
-"                               dot(normal,g_sun_dir.xyz)*0.75+0.25\n"
-"                           ) * g_sun_colour.rgb * g_day_phase;\n"
-"\n"
-"   float scaled_shadow = max( shadow, 1.0 - max(g_sun_dir.y,0.0) );\n"
-"   vec3 ambient = mix( g_ambient_colour.rgb, g_sunset_ambient.rgb, \n"
-"                       g_sunset_phase );\n"
-"\n"
-"   return ambient + (light_sun + sky_reflection) * shadow;\n"
-"}\n"
-"\n"
-"#line     44        0 \n"
-"\n"
-"float world_depth_sample( vec3 pos )\n"
-"{\n"
-"   vec2 depth_coord = (pos.xz - g_depth_bounds.xy) * g_depth_bounds.zw; \n"
-"   return texture( g_world_depth, depth_coord ).r;\n"
-"}\n"
-"\n"
-"float world_water_depth( vec3 pos )\n"
-"{\n"
-"   float ref_depth = g_water_plane.y*g_water_plane.w;\n"
-"   return world_depth_sample( pos ) - ref_depth;\n"
-"}\n"
-"\n"
-"float shadow_sample( vec3 co ){\n"
-"   float height_sample = world_depth_sample( co );\n"
-"\n"
-"   float fdelta = height_sample - co.y;\n"
-"   return clamp( fdelta, 0.2, 0.4 )-0.2;\n"
-"}\n"
-"\n"
-"float newlight_compute_sun_shadow( vec3 co, vec3 dir ){\n"
-"   if( g_shadow_samples == 0 ){\n"
-"      return 1.0;\n"
-"   }\n"
-"\n"
-"   float fspread = g_shadow_spread;\n"
-"   float flength = g_shadow_length;\n"
-"\n"
-"   float famt = 0.0;\n"
-"   famt += shadow_sample(co+(dir+vec3(-0.56,0.55, 0.30)*fspread)*flength*0.1);\n"
-"   famt += shadow_sample(co+(dir+vec3( 0.80,0.68, 0.34)*fspread)*flength*0.2);\n"
-"   famt += shadow_sample(co+(dir+vec3( 0.78,0.07,-0.06)*fspread)*flength*0.3);\n"
-"   famt += shadow_sample(co+(dir+vec3(-0.59,0.07,-0.42)*fspread)*flength*0.4);\n"
-"\n"
-"   //famt+=shadow_sample(co+(dir+vec3(-0.790,-0.933,-0.875)*fspread)*flength*0.5);\n"
-"   //famt+=shadow_sample(co+(dir+vec3( 0.807,-0.690, 0.472)*fspread)*flength*0.6);\n"
-"   //famt+=shadow_sample(co+(dir+vec3( 0.522,-0.379, 0.350)*fspread)*flength*0.7);\n"
-"   //famt+=shadow_sample(co+(dir+vec3( 0.483, 0.201, 0.306)*fspread)*flength*0.8);\n"
-"\n"
-"   return 1.0 - famt;\n"
-"}\n"
-"\n"
-"float newlight_specular( vec3 wnormal, vec3 dir, vec3 halfview, float exponent )\n"
-"{\n"
-"   vec3 specdir = reflect( -dir, wnormal );\n"
-"   return pow(max(dot( halfview, specdir ), 0.0), exponent);\n"
-"}\n"
-"\n"
-"vec3 scene_apply_fog( vec3 vfrag, vec3 colour, float fdist ){\n"
-"   float dist = pow(fdist*0.0010,0.78);\n"
-"   return mix( vfrag, colour, min( 1.0, dist ) );\n"
-"}\n"
-"\n"
-"vec3 scene_calculate_light( int light_index, \n"
-"                            vec3 halfview, vec3 co, vec3 normal )\n"
-"{\n"
-"   vec4 light_colour = texelFetch( uLightsArray, light_index+0 );\n"
-"   vec4 light_co     = texelFetch( uLightsArray, light_index+1 );\n"
-"   vec4 light_dir    = texelFetch( uLightsArray, light_index+2 );\n"
-"\n"
-"   vec3 light_delta = light_co.xyz-co;\n"
-"   float dist2 = dot(light_delta,light_delta);\n"
-"\n"
-"   light_delta = normalize( light_delta );\n"
-"\n"
-"   float quadratic = dist2*100.0;\n"
-"   float attenuation  = 1.0/( 1.0 + quadratic );\n"
-"         attenuation *= max( dot( light_delta, normal ), 0.0 );\n"
-"\n"
-"   float falloff = max( 0.0, 1.0-(dist2*light_co.w) );\n"
-"\n"
-"   if( light_dir.w < 0.999999 ){\n"
-"      float spot_theta = max( 0.0, dot( light_delta, -light_dir.xyz ) );\n"
-"      falloff *= max( 0.0, (spot_theta - light_dir.w) / (1.0-light_dir.w) );\n"
-"   }\n"
-"\n"
-"   return light_colour.rgb * attenuation * falloff \n"
-"            * step( g_day_phase, light_colour.w );\n"
-"}\n"
-"\n"
-"vec3 scene_calculate_packed_light_patch( uint packed_index, \n"
-"                                         vec3 halfview, vec3 co, vec3 normal )\n"
-"{\n"
-"   uint light_count = packed_index & 0x3u;\n"
-"\n"
-"   vec3 l = vec3(0.0);\n"
-"\n"
-"   if( light_count >= 1u ){\n"
-"      int index_0 = int( ((packed_index >>  2u) & 0x3ffu) * 3u );\n"
-"      int index_1 = int( ((packed_index >> 12u) & 0x3ffu) * 3u );\n"
-"      int index_2 = int( ((packed_index >> 22u) & 0x3ffu) * 3u );\n"
-"\n"
-"      l += scene_calculate_light( index_0, halfview, co, normal );\n"
-"\n"
-"      if( light_count >= 2u ){\n"
-"         l += scene_calculate_light( index_1, halfview, co, normal );\n"
-"\n"
-"         if( light_count >= 3u ){\n"
-"            l += scene_calculate_light( index_2, halfview, co, normal );\n"
-"         }\n"
-"      }\n"
-"   }\n"
-"\n"
-"   return l;\n"
-"}\n"
-"\n"
-"vec3 world_compute_lighting( vec3 diffuse, vec3 normal, vec3 co,\n"
-"                             float light_mask )\n"
-"{\n"
-"   if( g_light_preview == 1 )\n"
-"      diffuse = vec3(0.75);\n"
-"\n"
-"   // Lighting\n"
-"   vec3 halfview = uCamera - co;\n"
-"   float fdist = length(halfview);\n"
-"   halfview /= fdist;\n"
-"\n"
-"   float world_shadow = newlight_compute_sun_shadow( \n"
-"               co, g_sun_dir.xyz * (1.0/(max(g_sun_dir.y,0.0)+0.2)) );\n"
-"\n"
-"   vec3 total_light = clearskies_lighting( \n"
-"                           normal, min( light_mask, world_shadow ), halfview );\n"
-"\n"
-"   vec3 cube_coord = (co - g_cube_min.xyz) * g_cube_inv_range.xyz;\n"
-"        cube_coord = floor( cube_coord );\n"
-"\n"
-"   if( g_debug_indices == 1 )\n"
-"   {\n"
-"      return rand33(cube_coord);\n"
-"   }\n"
-"\n"
-"   if( g_debug_complexity == 1 )\n"
-"   {\n"
-"      ivec3 coord = ivec3( cube_coord );\n"
-"      uvec4 index_sample = texelFetch( uLightsIndex, coord, 0 );\n"
-"\n"
-"      uint light_count = (index_sample.x & 0x3u) + (index_sample.y & 0x3u);\n"
-"      return vec3( float(light_count)*(1.0/6.0), 0.0, 0.5 );\n"
-"   }\n"
-"\n"
-"   // FIXME: this coord should absolutely must be clamped!\n"
-"   \n"
-"   ivec3 coord = ivec3( cube_coord );\n"
-"   uvec4 index_sample = texelFetch( uLightsIndex, coord, 0 );\n"
-"\n"
-"   total_light += \n"
-"      scene_calculate_packed_light_patch( index_sample.x,\n"
-"                                          halfview, co, normal ) \n"
-"                                          * light_mask;\n"
-"   total_light += \n"
-"      scene_calculate_packed_light_patch( index_sample.y,\n"
-"                                          halfview, co, normal )\n"
-"                                          * light_mask;\n"
-"\n"
-"   // Take a section of the sky function to give us a matching fog colour\n"
-"\n"
-"   vec3 fog_colour  = clearskies_ambient( -halfview );\n"
-"   float sun_theta  = dot( -halfview, g_sun_dir.xyz );\n"
-"   float sun_size   = max( 0.0, sun_theta * 0.5 + 0.5 );\n"
-"   float sun_shape  = sun_size * max(g_sun_dir.y,0.0) * 0.5;\n"
-"         \n"
-"   vec3 sun_colour  = mix( vec3(1.0), g_sunset_colour.rgb, g_sunset_phase*0.5 );\n"
-"        sun_colour *= sun_shape;\n"
-"\n"
-"   fog_colour += sun_colour;\n"
-"   return scene_apply_fog( diffuse * total_light, fog_colour, fdist );\n"
-"}\n"
-"\n"
-"#line      9        0 \n"
-"\n"
-"float sdLine( vec3 p, vec3 a, vec3 b )\n"
-"{\n"
-"  vec3 pa = p - a;\n"
-"  vec3 ba = b - a;\n"
-"\n"
-"  float h = clamp( dot(pa,ba)/dot(ba,ba), 0.0, 1.0 );\n"
-"  return length( pa - ba*h );\n"
-"}\n"
-"\n"
-"float compute_board_shadow()\n"
-"{\n"
-"   // player shadow\n"
-"   float dist_to_player = max( 0.0, sdLine( aWorldCo, g_board_0.xyz,\n"
-"                                                      g_board_1.xyz )-0.1 );\n"
-"   float player_shadow = max( 1.0-dist_to_player*2.7, 0.0 );\n"
-"   player_shadow *= player_shadow*player_shadow*player_shadow;\n"
-"\n"
-"   return 1.0 - player_shadow*0.8;\n"
-"}\n"
-"\n"
-"vec3 scene_compute_lighting( vec3 diffuse, vec3 normal, vec3 co )\n"
-"{\n"
-"   return world_compute_lighting( diffuse, normal, co, compute_board_shadow() );\n"
-"}\n"
-"\n"
-"#line     13        0 \n"
-"#line       1        3 \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     14        0 \n"
-"\n"
-"vec2 smin( float a, float b, float k ){\n"
-"   float h = max( k-abs(a-b), 0.0 )/k;\n"
-"   float m = h*h*0.5;\n"
-"   float s = m*k*(1.0/2.0);\n"
-"\n"
-"   if( a < b )\n"
-"      return vec2(a-s,m);\n"
-"   else\n"
-"      return vec2(b-s,1.0-m);\n"
-"}\n"
-"\n"
-"void main(){\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"
-"   float dcam = (-8.0+distance( aCo, uCamera ))/4.0;\n"
-"   float dy0 = aCo.y - uMapInfo.x;\n"
-"   float dy1 = uMapInfo.y - aCo.y;\n"
-"\n"
-"   if( min(min(dy0,dy1)*0.5, dcam) + dither < 0.51 ) \n"
-"      discard;\n"
-"\n"
-"   compute_motion_vectors();\n"
-"\n"
-"   vec3 vfrag = vec3(0.898,0.811,0.716);\n"
-"   vec3 qnorm = aNorm.xyz;\n"
-"\n"
-"   qnorm = normalize(floor(aNorm.xyz*4.0)*0.25);\n"
-"   qnorm += vec3(0.001,0.0,0.0);\n"
-"\n"
-"   if( uAlphatest ){\n"
-"      vec4 vSample = texture( uTexMain, aUv );\n"
-"      if( vSample.a < 0.5 )\n"
-"         discard;\n"
-"   }\n"
-"   else{\n"
-"   }\n"
-"\n"
-"   vfrag = scene_compute_lighting( vfrag, qnorm, aWorldCo );\n"
-"   \n"
-"   // dots\n"
-"   float d0 = distance( aCo, uPlayerPos.xyz )*2.0;\n"
-"   float d1 = distance( aCo, uSpawnPos.xyz );\n"
-"\n"
-"   vec2 dm = smin( d0, d1, 10.0 );\n"
-"   float dd = fract(dm.x*0.2-g_realtime*0.5) * \n"
-"               max(0.0,1.0-dm.x*0.04) * \n"
-"               max(0.0,qnorm.y);\n"
-"   vec3 emit = mix(vec3(1.0,0.0,0.0),vec3(0.0,1.0,0.0),dm.y)*dd;\n"
-"\n"
-"   // line\n"
-"   vec3 v0 = (uSpawnPos.xyz-uPlayerPos.xyz)*uSpawnPos.w;\n"
-"   float t = clamp( dot(aCo-uPlayerPos.xyz,v0), 0.0, uPlayerPos.w );\n"
-"   vec3 p0 = uPlayerPos.xyz + v0*t;\n"
-"   float d3 = distance(p0,aCo);\n"
-"   emit += vec3(fract(t*0.2-g_realtime+d3*0.2)*max(0.0,1.0-d3*0.2));\n"
-"\n"
-"   vfrag += emit;\n"
-"\n"
-"   if( uMapInfo.z > 0.0 ){\n"
-"      float height = fract( aCo.y * 0.1 );\n"
-"      float lg = 2.0*length(vec2(dFdx(height), dFdy(height)));\n"
-"      vfrag *= 1.0f+(lg*0.2*uMapInfo.z);\n"
-"   }\n"
-"\n"
-"   oColour = vec4( vfrag, 1.0 );\n"
-"   //oColour = vec4( vfrag, 1.0 );\n"
-"}\n"
-""},
-};
-
-static GLuint _uniform_scene_override_uMdl;
-static GLuint _uniform_scene_override_uPv;
-static GLuint _uniform_scene_override_uPvmPrev;
-static GLuint _uniform_scene_override_uNormalMtx;
-static GLuint _uniform_scene_override_uTexGarbage;
-static GLuint _uniform_scene_override_uTexMain;
-static GLuint _uniform_scene_override_uCamera;
-static GLuint _uniform_scene_override_uPlane;
-static GLuint _uniform_scene_override_uPlayerPos;
-static GLuint _uniform_scene_override_uSpawnPos;
-static GLuint _uniform_scene_override_uAlphatest;
-static GLuint _uniform_scene_override_uMapInfo;
-static GLuint _uniform_scene_override_g_world_depth;
-static GLuint _uniform_scene_override_uLightsArray;
-static GLuint _uniform_scene_override_uLightsIndex;
-static void shader_scene_override_uMdl(m4x3f m){
-   glUniformMatrix4x3fv(_uniform_scene_override_uMdl,1,GL_FALSE,(float*)m);
+   glUniformMatrix4x3fv(_uniform_scene_override_uMdl,1,GL_FALSE,(f32*)m);
 }
-static void shader_scene_override_uPv(m4x4f m){
-   glUniformMatrix4fv(_uniform_scene_override_uPv,1,GL_FALSE,(float*)m);
+static inline void shader_scene_override_uPv(m4x4f m)
+{
+   glUniformMatrix4fv(_uniform_scene_override_uPv,1,GL_FALSE,(f32*)m);
 }
-static void shader_scene_override_uPvmPrev(m4x4f m){
-   glUniformMatrix4fv(_uniform_scene_override_uPvmPrev,1,GL_FALSE,(float*)m);
+static inline void shader_scene_override_uPvmPrev(m4x4f m)
+{
+   glUniformMatrix4fv(_uniform_scene_override_uPvmPrev,1,GL_FALSE,(f32*)m);
 }
-static void shader_scene_override_uNormalMtx(m3x3f m){
-   glUniformMatrix3fv(_uniform_scene_override_uNormalMtx,1,GL_FALSE,(float*)m);
+static inline void shader_scene_override_uNormalMtx(m3x3f m)
+{
+   glUniformMatrix3fv(_uniform_scene_override_uNormalMtx,1,GL_FALSE,(f32*)m);
 }
-static void shader_scene_override_uTexGarbage(int i){
+static inline void shader_scene_override_uTexGarbage(int i)
+{
    glUniform1i(_uniform_scene_override_uTexGarbage,i);
 }
-static void shader_scene_override_uTexMain(int i){
+static inline void shader_scene_override_uTexMain(int i)
+{
    glUniform1i(_uniform_scene_override_uTexMain,i);
 }
-static void shader_scene_override_uCamera(v3f v){
+static inline void shader_scene_override_uCamera(v3f v)
+{
    glUniform3fv(_uniform_scene_override_uCamera,1,v);
 }
-static void shader_scene_override_uPlane(v4f v){
+static inline void shader_scene_override_uPlane(v4f v)
+{
    glUniform4fv(_uniform_scene_override_uPlane,1,v);
 }
-static void shader_scene_override_uPlayerPos(v4f v){
+static inline void shader_scene_override_uPlayerPos(v4f v)
+{
    glUniform4fv(_uniform_scene_override_uPlayerPos,1,v);
 }
-static void shader_scene_override_uSpawnPos(v4f v){
+static inline void shader_scene_override_uSpawnPos(v4f v)
+{
    glUniform4fv(_uniform_scene_override_uSpawnPos,1,v);
 }
-static void shader_scene_override_uAlphatest(int b){
+static inline void shader_scene_override_uAlphatest(int b)
+{
    glUniform1i(_uniform_scene_override_uAlphatest,b);
 }
-static void shader_scene_override_uMapInfo(v4f v){
+static inline void shader_scene_override_uMapInfo(v4f v)
+{
    glUniform4fv(_uniform_scene_override_uMapInfo,1,v);
 }
-static void shader_scene_override_g_world_depth(int i){
+static inline void shader_scene_override_g_world_depth(int i)
+{
    glUniform1i(_uniform_scene_override_g_world_depth,i);
 }
-static void shader_scene_override_register(void){
-   vg_shader_register( &_shader_scene_override );
-}
-static void shader_scene_override_use(void){ glUseProgram(_shader_scene_override.id); }
-static void shader_scene_override_link(void){
-   _uniform_scene_override_uMdl = glGetUniformLocation( _shader_scene_override.id, "uMdl" );
-   _uniform_scene_override_uPv = glGetUniformLocation( _shader_scene_override.id, "uPv" );
-   _uniform_scene_override_uPvmPrev = glGetUniformLocation( _shader_scene_override.id, "uPvmPrev" );
-   _uniform_scene_override_uNormalMtx = glGetUniformLocation( _shader_scene_override.id, "uNormalMtx" );
-   _uniform_scene_override_uTexGarbage = glGetUniformLocation( _shader_scene_override.id, "uTexGarbage" );
-   _uniform_scene_override_uTexMain = glGetUniformLocation( _shader_scene_override.id, "uTexMain" );
-   _uniform_scene_override_uCamera = glGetUniformLocation( _shader_scene_override.id, "uCamera" );
-   _uniform_scene_override_uPlane = glGetUniformLocation( _shader_scene_override.id, "uPlane" );
-   _uniform_scene_override_uPlayerPos = glGetUniformLocation( _shader_scene_override.id, "uPlayerPos" );
-   _uniform_scene_override_uSpawnPos = glGetUniformLocation( _shader_scene_override.id, "uSpawnPos" );
-   _uniform_scene_override_uAlphatest = glGetUniformLocation( _shader_scene_override.id, "uAlphatest" );
-   _uniform_scene_override_uMapInfo = glGetUniformLocation( _shader_scene_override.id, "uMapInfo" );
-   _uniform_scene_override_g_world_depth = glGetUniformLocation( _shader_scene_override.id, "g_world_depth" );
-   _uniform_scene_override_uLightsArray = glGetUniformLocation( _shader_scene_override.id, "uLightsArray" );
-   _uniform_scene_override_uLightsIndex = glGetUniformLocation( _shader_scene_override.id, "uLightsIndex" );
+static inline void shader_scene_override_use(void);
+static inline void shader_scene_override_use(void)
+{
+   glUseProgram(_shader_scene_override.id);
 }
-#endif /* SHADER_scene_override_H */
index 9736d9441d62a8a964e95d85502034671ef4204f..2e99c02b8ba63415dadd6adb2f0df1ba85d02b2d 100644 (file)
-#ifndef SHADER_scene_position_H
-#define SHADER_scene_position_H
-static void shader_scene_position_link(void);
-static void shader_scene_position_register(void);
-static struct vg_shader _shader_scene_position = {
-   .name = "scene_position",
-   .link = shader_scene_position_link,
-   .vs = 
+#pragma once
+#include "vg/vg_engine.h"
+extern struct vg_shader _shader_scene_position;
+extern GLuint _uniform_scene_position_uMdl;
+extern GLuint _uniform_scene_position_uPv;
+extern GLuint _uniform_scene_position_uPvmPrev;
+extern GLuint _uniform_scene_position_uCamera;
+extern GLuint _uniform_scene_position_uBoard0;
+extern GLuint _uniform_scene_position_uBoard1;
+extern GLuint _uniform_scene_position_g_world_depth;
+extern GLuint _uniform_scene_position_uLightsArray;
+extern GLuint _uniform_scene_position_uLightsIndex;
+static inline void shader_scene_position_uMdl(m4x3f m)
 {
-.orig_file = "shaders/scene.vs",
-.static_src = 
-"layout (location=0) in vec3  a_co;\n"
-"layout (location=1) in vec4  a_norm;\n"
-"layout (location=2) in vec2  a_uv;\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      6        0 \n"
-"\n"
-"uniform mat4x3 uMdl;\n"
-"uniform mat4   uPv;\n"
-"uniform mat4   uPvmPrev;\n"
-"\n"
-"out vec2 aUv;\n"
-"out vec4 aNorm;\n"
-"out vec3 aCo;\n"
-"out vec3 aWorldCo;\n"
-"\n"
-"void main()\n"
-"{\n"
-"   vec3 world_pos0 = uMdl     * vec4( a_co, 1.0 );\n"
-"   vec4 vproj0     = uPv      * vec4( world_pos0, 1.0 );\n"
-"   vec4 vproj1     = uPvmPrev * vec4( a_co, 1.0 );\n"
-"\n"
-"   vs_motion_out( vproj0, vproj1 );\n"
-"\n"
-"   gl_Position = vproj0;\n"
-"\n"
-"   aUv = a_uv;\n"
-"   aNorm = vec4( mat3(uMdl) * a_norm.xyz, a_norm.w );\n"
-"   aCo = a_co;\n"
-"   aWorldCo = world_pos0;\n"
-"}\n"
-""},
-   .fs = 
-{
-.orig_file = "shaders/scene_position.fs",
-.static_src = 
-"out vec4 FragColor;\n"
-"\n"
-"uniform vec3 uCamera;\n"
-"uniform vec3 uBoard0;\n"
-"uniform vec3 uBoard1;\n"
-"\n"
-"#line       1        1 \n"
-"// :D\n"
-"const float CLEARSKIES_LIGHT_DOT_MIN = 0.0;\n"
-"\n"
-"#line      8        0 \n"
-"#line       1        2 \n"
-"// :D\n"
-"\n"
-"in vec2 aUv;\n"
-"in vec4 aNorm;\n"
-"in vec3 aCo;\n"
-"in vec3 aWorldCo;\n"
-"\n"
-"#line       1        1 \n"
-"layout (location = 0) out vec4 oColour;\n"
-"\n"
-"// OpenGL wiki: Recommends do not use vec3 because of drivers. hence the v4s...\n"
-"layout (std140) uniform ub_world_lighting\n"
-"{\n"
-"   vec4 g_cube_min;\n"
-"   vec4 g_cube_inv_range;\n"
-"\n"
-"   vec4 g_water_plane;\n"
-"   vec4 g_depth_bounds;\n"
-"\n"
-"   vec4 g_daysky_colour;\n"
-"   vec4 g_nightsky_colour;\n"
-"   vec4 g_sunset_colour;\n"
-"   vec4 g_ambient_colour;\n"
-"   vec4 g_sunset_ambient;\n"
-"   vec4 g_sun_colour;\n"
-"   vec4 g_sun_dir;\n"
-"   vec4 g_board_0;\n"
-"   vec4 g_board_1;\n"
-"\n"
-"   float g_water_fog;\n"
-"   float g_time;\n"
-"   float g_realtime;\n"
-"   float g_shadow_length;\n"
-"   float g_shadow_spread;\n"
-"\n"
-"   float g_time_of_day;\n"
-"   float g_day_phase;\n"
-"   float g_sunset_phase;\n"
-"\n"
-"   int g_light_preview;\n"
-"   int g_shadow_samples;\n"
-"\n"
-"   int g_debug_indices;\n"
-"   int g_debug_complexity;\n"
-"};\n"
-"\n"
-"uniform sampler2D g_world_depth;\n"
-"uniform samplerBuffer uLightsArray;\n"
-"uniform usampler3D uLightsIndex;\n"
-"\n"
-"#line       1        1 \n"
-"//const vec3  DAYSKY_COLOUR   = vec3( 0.37, 0.54, 0.97 );\n"
-"//const vec3  NIGHTSKY_COLOUR = vec3( 0.03, 0.05, 0.20 );\n"
-"//const vec3  SUNSET_COLOUR   = vec3( 1.00, 0.32, 0.01 );\n"
-"//const vec3  AMBIENT_COLOUR  = vec3( 0.13, 0.17, 0.35 );\n"
-"//const vec3  SUNSET_AMBIENT  = vec3( 0.25, 0.17, 0.51 );\n"
-"//const vec3  SUN_COLOUR      = vec3( 1.10, 0.89, 0.35 );\n"
-"\n"
-"const float SUN_ANGLE       = 0.0001;\n"
-"const float PI              = 3.14159265358979323846264;\n"
-"\n"
-"//struct world_info\n"
-"//{\n"
-"//   float time,\n"
-"//         time_of_day,\n"
-"//         day_phase,\n"
-"//         sunset_phase;\n"
-"//   \n"
-"//   vec3 sun_dir;\n"
-"//};\n"
-"\n"
-"vec3 rand33(vec3 p3)\n"
-"{\n"
-"      p3 = fract(p3 * vec3(.1031, .1030, .0973));\n"
-"   p3 += dot(p3, p3.yxz+33.33);\n"
-"   return fract((p3.xxy + p3.yxx)*p3.zyx);\n"
-"}\n"
-"\n"
-"float stars( vec3 rd, float rr, float size ){\n"
-"   vec3 co = rd * rr;\n"
-"\n"
-"   float a = atan(co.y, length(co.xz)) + 4.0 * PI;\n"
-"\n"
-"   float spaces = 1.0 / rr;\n"
-"   size = (rr * 0.0015) * fwidth(a) * 1000.0 * size;\n"
-"   a -= mod(a, spaces) - spaces * 0.5;\n"
-"\n"
-"   float count = floor(sqrt(pow(rr, 2.0) * (1.0 - pow(sin(a), 2.0))) * 3.0);\n"
-"   \n"
-"   float plane = atan(co.z, co.x) + 4.0 * PI;\n"
-"   plane = plane - mod(plane, PI / count);\n"
-"\n"
-"   vec2 delta = rand33(vec3(plane, a, 0.0)).xy;\n"
-"\n"
-"   float level = sin(a + spaces * (delta.y - 0.5) * (1.0 - size)) * rr;\n"
-"   float ydist = sqrt(rr * rr - level * level);\n"
-"   float angle = plane + (PI * (delta.x * (1.0-size) + size * 0.5) / count);\n"
-"   vec3 center = vec3(cos(angle) * ydist, level, sin(angle) * ydist);\n"
-"   float star = smoothstep(size, 0.0, distance(center, co));\n"
-"   return star;\n"
-"}\n"
-"\n"
-"float luminance( vec3 v )\n"
-"{\n"
-"   return dot( v, vec3(0.2126, 0.7152, 0.0722) );\n"
-"}\n"
-"\n"
-"vec3 clearskies_ambient( vec3 dir )\n"
-"{\n"
-"   float sun_azimuth  = g_sunset_phase * (dot( dir.xz, g_sun_dir.xz )*0.4+0.6);\n"
-"   float sky_gradient = dir.y;\n"
-"   \n"
-"   /* Blend phase colours */\n"
-"   vec3 ambient  = g_daysky_colour.rgb   * (g_day_phase-g_sunset_phase*0.1);\n"
-"        ambient += g_sunset_colour.rgb   * (1.0-dir.y*0.5)*sun_azimuth;\n"
-"        ambient += g_nightsky_colour.rgb * (1.0-g_day_phase);\n"
-"   \n"
-"   /* Add gradient */\n"
-"        ambient -= sky_gradient * luminance(ambient);\n"
-"        \n"
-"   return ambient;\n"
-"}\n"
-"\n"
-"vec3 clearskies_sky( vec3 ray_dir )\n"
-"{\n"
-"   ray_dir.y = abs( ray_dir.y );\n"
-"   vec3 sky_colour  = clearskies_ambient( ray_dir );\n"
-"   \n"
-"   /* Sun */\n"
-"   float sun_theta  = dot( ray_dir, g_sun_dir.xyz );\n"
-"   float sun_size   = max( 0.0, sun_theta * 0.5 + 0.5 + SUN_ANGLE );\n"
-"   float sun_shape  = pow( sun_size, 2000.0 );\n"
-"         sun_shape += sun_size * max(g_sun_dir.y,0.0) * 0.5;\n"
-"         \n"
-"   vec3 sun_colour  = mix( vec3(1.0), g_sunset_colour.rgb, g_sunset_phase*0.5 );\n"
-"        sun_colour *= sun_shape;\n"
-"\n"
-"   \n"
-"   float star = 0.0;\n"
-"   float star_blend = 10.0*max(0.0,(1.0-g_day_phase*2.0));\n"
-"\n"
-"   if( star_blend > 0.001 ){\n"
-"      for( float j = 1.0; j <= 4.1; j += 1.0 ){\n"
-"         float m = mix(0.6, 0.9, smoothstep(1.0, 2.0, j));\n"
-"         star += stars( ray_dir, 1.94 * pow( 1.64, j ), m ) * (1.0/pow(4.0, j));\n"
-"      }\n"
-"   }\n"
-"   \n"
-"   vec3 composite   = sky_colour + sun_colour + star*star_blend;\n"
-"   return composite;\n"
-"}\n"
-"\n"
-"vec3 clearskies_lighting( vec3 normal, float shadow, vec3 halfview )\n"
-"{\n"
-"   float fresnel = 1.0 - abs(dot(normal,halfview));\n"
-"\n"
-"   vec3  reflect_colour = mix( g_daysky_colour.rgb, g_sunset_colour.rgb, \n"
-"                               g_sunset_phase );\n"
-"\n"
-"   vec3  sky_reflection = 0.5 * fresnel * reflect_colour;\n"
-"   vec3  light_sun      = max( CLEARSKIES_LIGHT_DOT_MIN, \n"
-"                               dot(normal,g_sun_dir.xyz)*0.75+0.25\n"
-"                           ) * g_sun_colour.rgb * g_day_phase;\n"
-"\n"
-"   float scaled_shadow = max( shadow, 1.0 - max(g_sun_dir.y,0.0) );\n"
-"   vec3 ambient = mix( g_ambient_colour.rgb, g_sunset_ambient.rgb, \n"
-"                       g_sunset_phase );\n"
-"\n"
-"   return ambient + (light_sun + sky_reflection) * shadow;\n"
-"}\n"
-"\n"
-"#line     44        0 \n"
-"\n"
-"float world_depth_sample( vec3 pos )\n"
-"{\n"
-"   vec2 depth_coord = (pos.xz - g_depth_bounds.xy) * g_depth_bounds.zw; \n"
-"   return texture( g_world_depth, depth_coord ).r;\n"
-"}\n"
-"\n"
-"float world_water_depth( vec3 pos )\n"
-"{\n"
-"   float ref_depth = g_water_plane.y*g_water_plane.w;\n"
-"   return world_depth_sample( pos ) - ref_depth;\n"
-"}\n"
-"\n"
-"float shadow_sample( vec3 co ){\n"
-"   float height_sample = world_depth_sample( co );\n"
-"\n"
-"   float fdelta = height_sample - co.y;\n"
-"   return clamp( fdelta, 0.2, 0.4 )-0.2;\n"
-"}\n"
-"\n"
-"float newlight_compute_sun_shadow( vec3 co, vec3 dir ){\n"
-"   if( g_shadow_samples == 0 ){\n"
-"      return 1.0;\n"
-"   }\n"
-"\n"
-"   float fspread = g_shadow_spread;\n"
-"   float flength = g_shadow_length;\n"
-"\n"
-"   float famt = 0.0;\n"
-"   famt += shadow_sample(co+(dir+vec3(-0.56,0.55, 0.30)*fspread)*flength*0.1);\n"
-"   famt += shadow_sample(co+(dir+vec3( 0.80,0.68, 0.34)*fspread)*flength*0.2);\n"
-"   famt += shadow_sample(co+(dir+vec3( 0.78,0.07,-0.06)*fspread)*flength*0.3);\n"
-"   famt += shadow_sample(co+(dir+vec3(-0.59,0.07,-0.42)*fspread)*flength*0.4);\n"
-"\n"
-"   //famt+=shadow_sample(co+(dir+vec3(-0.790,-0.933,-0.875)*fspread)*flength*0.5);\n"
-"   //famt+=shadow_sample(co+(dir+vec3( 0.807,-0.690, 0.472)*fspread)*flength*0.6);\n"
-"   //famt+=shadow_sample(co+(dir+vec3( 0.522,-0.379, 0.350)*fspread)*flength*0.7);\n"
-"   //famt+=shadow_sample(co+(dir+vec3( 0.483, 0.201, 0.306)*fspread)*flength*0.8);\n"
-"\n"
-"   return 1.0 - famt;\n"
-"}\n"
-"\n"
-"float newlight_specular( vec3 wnormal, vec3 dir, vec3 halfview, float exponent )\n"
-"{\n"
-"   vec3 specdir = reflect( -dir, wnormal );\n"
-"   return pow(max(dot( halfview, specdir ), 0.0), exponent);\n"
-"}\n"
-"\n"
-"vec3 scene_apply_fog( vec3 vfrag, vec3 colour, float fdist ){\n"
-"   float dist = pow(fdist*0.0010,0.78);\n"
-"   return mix( vfrag, colour, min( 1.0, dist ) );\n"
-"}\n"
-"\n"
-"vec3 scene_calculate_light( int light_index, \n"
-"                            vec3 halfview, vec3 co, vec3 normal )\n"
-"{\n"
-"   vec4 light_colour = texelFetch( uLightsArray, light_index+0 );\n"
-"   vec4 light_co     = texelFetch( uLightsArray, light_index+1 );\n"
-"   vec4 light_dir    = texelFetch( uLightsArray, light_index+2 );\n"
-"\n"
-"   vec3 light_delta = light_co.xyz-co;\n"
-"   float dist2 = dot(light_delta,light_delta);\n"
-"\n"
-"   light_delta = normalize( light_delta );\n"
-"\n"
-"   float quadratic = dist2*100.0;\n"
-"   float attenuation  = 1.0/( 1.0 + quadratic );\n"
-"         attenuation *= max( dot( light_delta, normal ), 0.0 );\n"
-"\n"
-"   float falloff = max( 0.0, 1.0-(dist2*light_co.w) );\n"
-"\n"
-"   if( light_dir.w < 0.999999 ){\n"
-"      float spot_theta = max( 0.0, dot( light_delta, -light_dir.xyz ) );\n"
-"      falloff *= max( 0.0, (spot_theta - light_dir.w) / (1.0-light_dir.w) );\n"
-"   }\n"
-"\n"
-"   return light_colour.rgb * attenuation * falloff \n"
-"            * step( g_day_phase, light_colour.w );\n"
-"}\n"
-"\n"
-"vec3 scene_calculate_packed_light_patch( uint packed_index, \n"
-"                                         vec3 halfview, vec3 co, vec3 normal )\n"
-"{\n"
-"   uint light_count = packed_index & 0x3u;\n"
-"\n"
-"   vec3 l = vec3(0.0);\n"
-"\n"
-"   if( light_count >= 1u ){\n"
-"      int index_0 = int( ((packed_index >>  2u) & 0x3ffu) * 3u );\n"
-"      int index_1 = int( ((packed_index >> 12u) & 0x3ffu) * 3u );\n"
-"      int index_2 = int( ((packed_index >> 22u) & 0x3ffu) * 3u );\n"
-"\n"
-"      l += scene_calculate_light( index_0, halfview, co, normal );\n"
-"\n"
-"      if( light_count >= 2u ){\n"
-"         l += scene_calculate_light( index_1, halfview, co, normal );\n"
-"\n"
-"         if( light_count >= 3u ){\n"
-"            l += scene_calculate_light( index_2, halfview, co, normal );\n"
-"         }\n"
-"      }\n"
-"   }\n"
-"\n"
-"   return l;\n"
-"}\n"
-"\n"
-"vec3 world_compute_lighting( vec3 diffuse, vec3 normal, vec3 co,\n"
-"                             float light_mask )\n"
-"{\n"
-"   if( g_light_preview == 1 )\n"
-"      diffuse = vec3(0.75);\n"
-"\n"
-"   // Lighting\n"
-"   vec3 halfview = uCamera - co;\n"
-"   float fdist = length(halfview);\n"
-"   halfview /= fdist;\n"
-"\n"
-"   float world_shadow = newlight_compute_sun_shadow( \n"
-"               co, g_sun_dir.xyz * (1.0/(max(g_sun_dir.y,0.0)+0.2)) );\n"
-"\n"
-"   vec3 total_light = clearskies_lighting( \n"
-"                           normal, min( light_mask, world_shadow ), halfview );\n"
-"\n"
-"   vec3 cube_coord = (co - g_cube_min.xyz) * g_cube_inv_range.xyz;\n"
-"        cube_coord = floor( cube_coord );\n"
-"\n"
-"   if( g_debug_indices == 1 )\n"
-"   {\n"
-"      return rand33(cube_coord);\n"
-"   }\n"
-"\n"
-"   if( g_debug_complexity == 1 )\n"
-"   {\n"
-"      ivec3 coord = ivec3( cube_coord );\n"
-"      uvec4 index_sample = texelFetch( uLightsIndex, coord, 0 );\n"
-"\n"
-"      uint light_count = (index_sample.x & 0x3u) + (index_sample.y & 0x3u);\n"
-"      return vec3( float(light_count)*(1.0/6.0), 0.0, 0.5 );\n"
-"   }\n"
-"\n"
-"   // FIXME: this coord should absolutely must be clamped!\n"
-"   \n"
-"   ivec3 coord = ivec3( cube_coord );\n"
-"   uvec4 index_sample = texelFetch( uLightsIndex, coord, 0 );\n"
-"\n"
-"   total_light += \n"
-"      scene_calculate_packed_light_patch( index_sample.x,\n"
-"                                          halfview, co, normal ) \n"
-"                                          * light_mask;\n"
-"   total_light += \n"
-"      scene_calculate_packed_light_patch( index_sample.y,\n"
-"                                          halfview, co, normal )\n"
-"                                          * light_mask;\n"
-"\n"
-"   // Take a section of the sky function to give us a matching fog colour\n"
-"\n"
-"   vec3 fog_colour  = clearskies_ambient( -halfview );\n"
-"   float sun_theta  = dot( -halfview, g_sun_dir.xyz );\n"
-"   float sun_size   = max( 0.0, sun_theta * 0.5 + 0.5 );\n"
-"   float sun_shape  = sun_size * max(g_sun_dir.y,0.0) * 0.5;\n"
-"         \n"
-"   vec3 sun_colour  = mix( vec3(1.0), g_sunset_colour.rgb, g_sunset_phase*0.5 );\n"
-"        sun_colour *= sun_shape;\n"
-"\n"
-"   fog_colour += sun_colour;\n"
-"   return scene_apply_fog( diffuse * total_light, fog_colour, fdist );\n"
-"}\n"
-"\n"
-"#line      9        0 \n"
-"\n"
-"float sdLine( vec3 p, vec3 a, vec3 b )\n"
-"{\n"
-"  vec3 pa = p - a;\n"
-"  vec3 ba = b - a;\n"
-"\n"
-"  float h = clamp( dot(pa,ba)/dot(ba,ba), 0.0, 1.0 );\n"
-"  return length( pa - ba*h );\n"
-"}\n"
-"\n"
-"float compute_board_shadow()\n"
-"{\n"
-"   // player shadow\n"
-"   float dist_to_player = max( 0.0, sdLine( aWorldCo, g_board_0.xyz,\n"
-"                                                      g_board_1.xyz )-0.1 );\n"
-"   float player_shadow = max( 1.0-dist_to_player*2.7, 0.0 );\n"
-"   player_shadow *= player_shadow*player_shadow*player_shadow;\n"
-"\n"
-"   return 1.0 - player_shadow*0.8;\n"
-"}\n"
-"\n"
-"vec3 scene_compute_lighting( vec3 diffuse, vec3 normal, vec3 co )\n"
-"{\n"
-"   return world_compute_lighting( diffuse, normal, co, compute_board_shadow() );\n"
-"}\n"
-"\n"
-"#line      9        0 \n"
-"\n"
-"void main()\n"
-"{\n"
-"   float height_full = aWorldCo.y;\n"
-"   float height_water = height_full;\n"
-"\n"
-"   if( height_water > (g_water_plane.y * g_water_plane.w) + 2.0 )\n"
-"      height_water = -99999.9;\n"
-"\n"
-"   FragColor = vec4( height_full, height_water, 0.0, 0.0 );\n"
-"}\n"
-""},
-};
-
-static GLuint _uniform_scene_position_uMdl;
-static GLuint _uniform_scene_position_uPv;
-static GLuint _uniform_scene_position_uPvmPrev;
-static GLuint _uniform_scene_position_uCamera;
-static GLuint _uniform_scene_position_uBoard0;
-static GLuint _uniform_scene_position_uBoard1;
-static GLuint _uniform_scene_position_g_world_depth;
-static GLuint _uniform_scene_position_uLightsArray;
-static GLuint _uniform_scene_position_uLightsIndex;
-static void shader_scene_position_uMdl(m4x3f m){
-   glUniformMatrix4x3fv(_uniform_scene_position_uMdl,1,GL_FALSE,(float*)m);
+   glUniformMatrix4x3fv(_uniform_scene_position_uMdl,1,GL_FALSE,(f32*)m);
 }
-static void shader_scene_position_uPv(m4x4f m){
-   glUniformMatrix4fv(_uniform_scene_position_uPv,1,GL_FALSE,(float*)m);
+static inline void shader_scene_position_uPv(m4x4f m)
+{
+   glUniformMatrix4fv(_uniform_scene_position_uPv,1,GL_FALSE,(f32*)m);
 }
-static void shader_scene_position_uPvmPrev(m4x4f m){
-   glUniformMatrix4fv(_uniform_scene_position_uPvmPrev,1,GL_FALSE,(float*)m);
+static inline void shader_scene_position_uPvmPrev(m4x4f m)
+{
+   glUniformMatrix4fv(_uniform_scene_position_uPvmPrev,1,GL_FALSE,(f32*)m);
 }
-static void shader_scene_position_uCamera(v3f v){
+static inline void shader_scene_position_uCamera(v3f v)
+{
    glUniform3fv(_uniform_scene_position_uCamera,1,v);
 }
-static void shader_scene_position_uBoard0(v3f v){
+static inline void shader_scene_position_uBoard0(v3f v)
+{
    glUniform3fv(_uniform_scene_position_uBoard0,1,v);
 }
-static void shader_scene_position_uBoard1(v3f v){
+static inline void shader_scene_position_uBoard1(v3f v)
+{
    glUniform3fv(_uniform_scene_position_uBoard1,1,v);
 }
-static void shader_scene_position_g_world_depth(int i){
+static inline void shader_scene_position_g_world_depth(int i)
+{
    glUniform1i(_uniform_scene_position_g_world_depth,i);
 }
-static void shader_scene_position_register(void){
-   vg_shader_register( &_shader_scene_position );
-}
-static void shader_scene_position_use(void){ glUseProgram(_shader_scene_position.id); }
-static void shader_scene_position_link(void){
-   _uniform_scene_position_uMdl = glGetUniformLocation( _shader_scene_position.id, "uMdl" );
-   _uniform_scene_position_uPv = glGetUniformLocation( _shader_scene_position.id, "uPv" );
-   _uniform_scene_position_uPvmPrev = glGetUniformLocation( _shader_scene_position.id, "uPvmPrev" );
-   _uniform_scene_position_uCamera = glGetUniformLocation( _shader_scene_position.id, "uCamera" );
-   _uniform_scene_position_uBoard0 = glGetUniformLocation( _shader_scene_position.id, "uBoard0" );
-   _uniform_scene_position_uBoard1 = glGetUniformLocation( _shader_scene_position.id, "uBoard1" );
-   _uniform_scene_position_g_world_depth = glGetUniformLocation( _shader_scene_position.id, "g_world_depth" );
-   _uniform_scene_position_uLightsArray = glGetUniformLocation( _shader_scene_position.id, "uLightsArray" );
-   _uniform_scene_position_uLightsIndex = glGetUniformLocation( _shader_scene_position.id, "uLightsIndex" );
+static inline void shader_scene_position_use(void);
+static inline void shader_scene_position_use(void)
+{
+   glUseProgram(_shader_scene_position.id);
 }
-#endif /* SHADER_scene_position_H */
index f136afe45d12abf3410ebf40a02ed40d56d33a89..b9fc0aa267a3be89e8f083d22e3438096cf462c7 100644 (file)
-#ifndef SHADER_scene_route_H
-#define SHADER_scene_route_H
-static void shader_scene_route_link(void);
-static void shader_scene_route_register(void);
-static struct vg_shader _shader_scene_route = {
-   .name = "scene_route",
-   .link = shader_scene_route_link,
-   .vs = 
+#pragma once
+#include "vg/vg_engine.h"
+extern struct vg_shader _shader_scene_route;
+extern GLuint _uniform_scene_route_uMdl;
+extern GLuint _uniform_scene_route_uPv;
+extern GLuint _uniform_scene_route_uPvmPrev;
+extern GLuint _uniform_scene_route_uNormalMtx;
+extern GLuint _uniform_scene_route_uTexGarbage;
+extern GLuint _uniform_scene_route_uTexGradients;
+extern GLuint _uniform_scene_route_uCamera;
+extern GLuint _uniform_scene_route_uColour;
+extern GLuint _uniform_scene_route_g_world_depth;
+extern GLuint _uniform_scene_route_uLightsArray;
+extern GLuint _uniform_scene_route_uLightsIndex;
+static inline void shader_scene_route_uMdl(m4x3f m)
 {
-.orig_file = "shaders/scene_override.vs",
-.static_src = 
-"layout (location=0) in vec3  a_co;\n"
-"layout (location=1) in vec4  a_norm;\n"
-"layout (location=2) in vec2  a_uv;\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      6        0 \n"
-"\n"
-"uniform mat4x3 uMdl;\n"
-"uniform mat4   uPv;\n"
-"uniform mat4   uPvmPrev;\n"
-"uniform mat3   uNormalMtx;\n"
-"\n"
-"out vec2 aUv;\n"
-"out vec4 aNorm;\n"
-"out vec3 aCo;\n"
-"out vec3 aWorldCo;\n"
-"\n"
-"void main()\n"
-"{\n"
-"   vec3 world_pos0 = uMdl     * vec4( a_co, 1.0 );\n"
-"   vec4 vproj0     = uPv      * vec4( world_pos0, 1.0 );\n"
-"   vec4 vproj1     = uPvmPrev * vec4( a_co, 1.0 );\n"
-"\n"
-"   vs_motion_out( vproj0, vproj1 );\n"
-"\n"
-"   gl_Position = vproj0;\n"
-"\n"
-"   aUv = a_uv;\n"
-"   aNorm = vec4( uNormalMtx * a_norm.xyz, a_norm.w );\n"
-"   aCo = a_co;\n"
-"   aWorldCo = world_pos0;\n"
-"}\n"
-""},
-   .fs = 
-{
-.orig_file = "shaders/scene_route.fs",
-.static_src = 
-"uniform sampler2D uTexGarbage;\n"
-"uniform sampler2D uTexGradients;\n"
-"uniform vec3 uCamera;\n"
-"uniform vec4 uColour;\n"
-"\n"
-"#line       1        1 \n"
-"// :D\n"
-"const float CLEARSKIES_LIGHT_DOT_MIN = 0.0;\n"
-"\n"
-"#line      7        0 \n"
-"#line       1        2 \n"
-"// :D\n"
-"\n"
-"in vec2 aUv;\n"
-"in vec4 aNorm;\n"
-"in vec3 aCo;\n"
-"in vec3 aWorldCo;\n"
-"\n"
-"#line       1        1 \n"
-"layout (location = 0) out vec4 oColour;\n"
-"\n"
-"// OpenGL wiki: Recommends do not use vec3 because of drivers. hence the v4s...\n"
-"layout (std140) uniform ub_world_lighting\n"
-"{\n"
-"   vec4 g_cube_min;\n"
-"   vec4 g_cube_inv_range;\n"
-"\n"
-"   vec4 g_water_plane;\n"
-"   vec4 g_depth_bounds;\n"
-"\n"
-"   vec4 g_daysky_colour;\n"
-"   vec4 g_nightsky_colour;\n"
-"   vec4 g_sunset_colour;\n"
-"   vec4 g_ambient_colour;\n"
-"   vec4 g_sunset_ambient;\n"
-"   vec4 g_sun_colour;\n"
-"   vec4 g_sun_dir;\n"
-"   vec4 g_board_0;\n"
-"   vec4 g_board_1;\n"
-"\n"
-"   float g_water_fog;\n"
-"   float g_time;\n"
-"   float g_realtime;\n"
-"   float g_shadow_length;\n"
-"   float g_shadow_spread;\n"
-"\n"
-"   float g_time_of_day;\n"
-"   float g_day_phase;\n"
-"   float g_sunset_phase;\n"
-"\n"
-"   int g_light_preview;\n"
-"   int g_shadow_samples;\n"
-"\n"
-"   int g_debug_indices;\n"
-"   int g_debug_complexity;\n"
-"};\n"
-"\n"
-"uniform sampler2D g_world_depth;\n"
-"uniform samplerBuffer uLightsArray;\n"
-"uniform usampler3D uLightsIndex;\n"
-"\n"
-"#line       1        1 \n"
-"//const vec3  DAYSKY_COLOUR   = vec3( 0.37, 0.54, 0.97 );\n"
-"//const vec3  NIGHTSKY_COLOUR = vec3( 0.03, 0.05, 0.20 );\n"
-"//const vec3  SUNSET_COLOUR   = vec3( 1.00, 0.32, 0.01 );\n"
-"//const vec3  AMBIENT_COLOUR  = vec3( 0.13, 0.17, 0.35 );\n"
-"//const vec3  SUNSET_AMBIENT  = vec3( 0.25, 0.17, 0.51 );\n"
-"//const vec3  SUN_COLOUR      = vec3( 1.10, 0.89, 0.35 );\n"
-"\n"
-"const float SUN_ANGLE       = 0.0001;\n"
-"const float PI              = 3.14159265358979323846264;\n"
-"\n"
-"//struct world_info\n"
-"//{\n"
-"//   float time,\n"
-"//         time_of_day,\n"
-"//         day_phase,\n"
-"//         sunset_phase;\n"
-"//   \n"
-"//   vec3 sun_dir;\n"
-"//};\n"
-"\n"
-"vec3 rand33(vec3 p3)\n"
-"{\n"
-"      p3 = fract(p3 * vec3(.1031, .1030, .0973));\n"
-"   p3 += dot(p3, p3.yxz+33.33);\n"
-"   return fract((p3.xxy + p3.yxx)*p3.zyx);\n"
-"}\n"
-"\n"
-"float stars( vec3 rd, float rr, float size ){\n"
-"   vec3 co = rd * rr;\n"
-"\n"
-"   float a = atan(co.y, length(co.xz)) + 4.0 * PI;\n"
-"\n"
-"   float spaces = 1.0 / rr;\n"
-"   size = (rr * 0.0015) * fwidth(a) * 1000.0 * size;\n"
-"   a -= mod(a, spaces) - spaces * 0.5;\n"
-"\n"
-"   float count = floor(sqrt(pow(rr, 2.0) * (1.0 - pow(sin(a), 2.0))) * 3.0);\n"
-"   \n"
-"   float plane = atan(co.z, co.x) + 4.0 * PI;\n"
-"   plane = plane - mod(plane, PI / count);\n"
-"\n"
-"   vec2 delta = rand33(vec3(plane, a, 0.0)).xy;\n"
-"\n"
-"   float level = sin(a + spaces * (delta.y - 0.5) * (1.0 - size)) * rr;\n"
-"   float ydist = sqrt(rr * rr - level * level);\n"
-"   float angle = plane + (PI * (delta.x * (1.0-size) + size * 0.5) / count);\n"
-"   vec3 center = vec3(cos(angle) * ydist, level, sin(angle) * ydist);\n"
-"   float star = smoothstep(size, 0.0, distance(center, co));\n"
-"   return star;\n"
-"}\n"
-"\n"
-"float luminance( vec3 v )\n"
-"{\n"
-"   return dot( v, vec3(0.2126, 0.7152, 0.0722) );\n"
-"}\n"
-"\n"
-"vec3 clearskies_ambient( vec3 dir )\n"
-"{\n"
-"   float sun_azimuth  = g_sunset_phase * (dot( dir.xz, g_sun_dir.xz )*0.4+0.6);\n"
-"   float sky_gradient = dir.y;\n"
-"   \n"
-"   /* Blend phase colours */\n"
-"   vec3 ambient  = g_daysky_colour.rgb   * (g_day_phase-g_sunset_phase*0.1);\n"
-"        ambient += g_sunset_colour.rgb   * (1.0-dir.y*0.5)*sun_azimuth;\n"
-"        ambient += g_nightsky_colour.rgb * (1.0-g_day_phase);\n"
-"   \n"
-"   /* Add gradient */\n"
-"        ambient -= sky_gradient * luminance(ambient);\n"
-"        \n"
-"   return ambient;\n"
-"}\n"
-"\n"
-"vec3 clearskies_sky( vec3 ray_dir )\n"
-"{\n"
-"   ray_dir.y = abs( ray_dir.y );\n"
-"   vec3 sky_colour  = clearskies_ambient( ray_dir );\n"
-"   \n"
-"   /* Sun */\n"
-"   float sun_theta  = dot( ray_dir, g_sun_dir.xyz );\n"
-"   float sun_size   = max( 0.0, sun_theta * 0.5 + 0.5 + SUN_ANGLE );\n"
-"   float sun_shape  = pow( sun_size, 2000.0 );\n"
-"         sun_shape += sun_size * max(g_sun_dir.y,0.0) * 0.5;\n"
-"         \n"
-"   vec3 sun_colour  = mix( vec3(1.0), g_sunset_colour.rgb, g_sunset_phase*0.5 );\n"
-"        sun_colour *= sun_shape;\n"
-"\n"
-"   \n"
-"   float star = 0.0;\n"
-"   float star_blend = 10.0*max(0.0,(1.0-g_day_phase*2.0));\n"
-"\n"
-"   if( star_blend > 0.001 ){\n"
-"      for( float j = 1.0; j <= 4.1; j += 1.0 ){\n"
-"         float m = mix(0.6, 0.9, smoothstep(1.0, 2.0, j));\n"
-"         star += stars( ray_dir, 1.94 * pow( 1.64, j ), m ) * (1.0/pow(4.0, j));\n"
-"      }\n"
-"   }\n"
-"   \n"
-"   vec3 composite   = sky_colour + sun_colour + star*star_blend;\n"
-"   return composite;\n"
-"}\n"
-"\n"
-"vec3 clearskies_lighting( vec3 normal, float shadow, vec3 halfview )\n"
-"{\n"
-"   float fresnel = 1.0 - abs(dot(normal,halfview));\n"
-"\n"
-"   vec3  reflect_colour = mix( g_daysky_colour.rgb, g_sunset_colour.rgb, \n"
-"                               g_sunset_phase );\n"
-"\n"
-"   vec3  sky_reflection = 0.5 * fresnel * reflect_colour;\n"
-"   vec3  light_sun      = max( CLEARSKIES_LIGHT_DOT_MIN, \n"
-"                               dot(normal,g_sun_dir.xyz)*0.75+0.25\n"
-"                           ) * g_sun_colour.rgb * g_day_phase;\n"
-"\n"
-"   float scaled_shadow = max( shadow, 1.0 - max(g_sun_dir.y,0.0) );\n"
-"   vec3 ambient = mix( g_ambient_colour.rgb, g_sunset_ambient.rgb, \n"
-"                       g_sunset_phase );\n"
-"\n"
-"   return ambient + (light_sun + sky_reflection) * shadow;\n"
-"}\n"
-"\n"
-"#line     44        0 \n"
-"\n"
-"float world_depth_sample( vec3 pos )\n"
-"{\n"
-"   vec2 depth_coord = (pos.xz - g_depth_bounds.xy) * g_depth_bounds.zw; \n"
-"   return texture( g_world_depth, depth_coord ).r;\n"
-"}\n"
-"\n"
-"float world_water_depth( vec3 pos )\n"
-"{\n"
-"   float ref_depth = g_water_plane.y*g_water_plane.w;\n"
-"   return world_depth_sample( pos ) - ref_depth;\n"
-"}\n"
-"\n"
-"float shadow_sample( vec3 co ){\n"
-"   float height_sample = world_depth_sample( co );\n"
-"\n"
-"   float fdelta = height_sample - co.y;\n"
-"   return clamp( fdelta, 0.2, 0.4 )-0.2;\n"
-"}\n"
-"\n"
-"float newlight_compute_sun_shadow( vec3 co, vec3 dir ){\n"
-"   if( g_shadow_samples == 0 ){\n"
-"      return 1.0;\n"
-"   }\n"
-"\n"
-"   float fspread = g_shadow_spread;\n"
-"   float flength = g_shadow_length;\n"
-"\n"
-"   float famt = 0.0;\n"
-"   famt += shadow_sample(co+(dir+vec3(-0.56,0.55, 0.30)*fspread)*flength*0.1);\n"
-"   famt += shadow_sample(co+(dir+vec3( 0.80,0.68, 0.34)*fspread)*flength*0.2);\n"
-"   famt += shadow_sample(co+(dir+vec3( 0.78,0.07,-0.06)*fspread)*flength*0.3);\n"
-"   famt += shadow_sample(co+(dir+vec3(-0.59,0.07,-0.42)*fspread)*flength*0.4);\n"
-"\n"
-"   //famt+=shadow_sample(co+(dir+vec3(-0.790,-0.933,-0.875)*fspread)*flength*0.5);\n"
-"   //famt+=shadow_sample(co+(dir+vec3( 0.807,-0.690, 0.472)*fspread)*flength*0.6);\n"
-"   //famt+=shadow_sample(co+(dir+vec3( 0.522,-0.379, 0.350)*fspread)*flength*0.7);\n"
-"   //famt+=shadow_sample(co+(dir+vec3( 0.483, 0.201, 0.306)*fspread)*flength*0.8);\n"
-"\n"
-"   return 1.0 - famt;\n"
-"}\n"
-"\n"
-"float newlight_specular( vec3 wnormal, vec3 dir, vec3 halfview, float exponent )\n"
-"{\n"
-"   vec3 specdir = reflect( -dir, wnormal );\n"
-"   return pow(max(dot( halfview, specdir ), 0.0), exponent);\n"
-"}\n"
-"\n"
-"vec3 scene_apply_fog( vec3 vfrag, vec3 colour, float fdist ){\n"
-"   float dist = pow(fdist*0.0010,0.78);\n"
-"   return mix( vfrag, colour, min( 1.0, dist ) );\n"
-"}\n"
-"\n"
-"vec3 scene_calculate_light( int light_index, \n"
-"                            vec3 halfview, vec3 co, vec3 normal )\n"
-"{\n"
-"   vec4 light_colour = texelFetch( uLightsArray, light_index+0 );\n"
-"   vec4 light_co     = texelFetch( uLightsArray, light_index+1 );\n"
-"   vec4 light_dir    = texelFetch( uLightsArray, light_index+2 );\n"
-"\n"
-"   vec3 light_delta = light_co.xyz-co;\n"
-"   float dist2 = dot(light_delta,light_delta);\n"
-"\n"
-"   light_delta = normalize( light_delta );\n"
-"\n"
-"   float quadratic = dist2*100.0;\n"
-"   float attenuation  = 1.0/( 1.0 + quadratic );\n"
-"         attenuation *= max( dot( light_delta, normal ), 0.0 );\n"
-"\n"
-"   float falloff = max( 0.0, 1.0-(dist2*light_co.w) );\n"
-"\n"
-"   if( light_dir.w < 0.999999 ){\n"
-"      float spot_theta = max( 0.0, dot( light_delta, -light_dir.xyz ) );\n"
-"      falloff *= max( 0.0, (spot_theta - light_dir.w) / (1.0-light_dir.w) );\n"
-"   }\n"
-"\n"
-"   return light_colour.rgb * attenuation * falloff \n"
-"            * step( g_day_phase, light_colour.w );\n"
-"}\n"
-"\n"
-"vec3 scene_calculate_packed_light_patch( uint packed_index, \n"
-"                                         vec3 halfview, vec3 co, vec3 normal )\n"
-"{\n"
-"   uint light_count = packed_index & 0x3u;\n"
-"\n"
-"   vec3 l = vec3(0.0);\n"
-"\n"
-"   if( light_count >= 1u ){\n"
-"      int index_0 = int( ((packed_index >>  2u) & 0x3ffu) * 3u );\n"
-"      int index_1 = int( ((packed_index >> 12u) & 0x3ffu) * 3u );\n"
-"      int index_2 = int( ((packed_index >> 22u) & 0x3ffu) * 3u );\n"
-"\n"
-"      l += scene_calculate_light( index_0, halfview, co, normal );\n"
-"\n"
-"      if( light_count >= 2u ){\n"
-"         l += scene_calculate_light( index_1, halfview, co, normal );\n"
-"\n"
-"         if( light_count >= 3u ){\n"
-"            l += scene_calculate_light( index_2, halfview, co, normal );\n"
-"         }\n"
-"      }\n"
-"   }\n"
-"\n"
-"   return l;\n"
-"}\n"
-"\n"
-"vec3 world_compute_lighting( vec3 diffuse, vec3 normal, vec3 co,\n"
-"                             float light_mask )\n"
-"{\n"
-"   if( g_light_preview == 1 )\n"
-"      diffuse = vec3(0.75);\n"
-"\n"
-"   // Lighting\n"
-"   vec3 halfview = uCamera - co;\n"
-"   float fdist = length(halfview);\n"
-"   halfview /= fdist;\n"
-"\n"
-"   float world_shadow = newlight_compute_sun_shadow( \n"
-"               co, g_sun_dir.xyz * (1.0/(max(g_sun_dir.y,0.0)+0.2)) );\n"
-"\n"
-"   vec3 total_light = clearskies_lighting( \n"
-"                           normal, min( light_mask, world_shadow ), halfview );\n"
-"\n"
-"   vec3 cube_coord = (co - g_cube_min.xyz) * g_cube_inv_range.xyz;\n"
-"        cube_coord = floor( cube_coord );\n"
-"\n"
-"   if( g_debug_indices == 1 )\n"
-"   {\n"
-"      return rand33(cube_coord);\n"
-"   }\n"
-"\n"
-"   if( g_debug_complexity == 1 )\n"
-"   {\n"
-"      ivec3 coord = ivec3( cube_coord );\n"
-"      uvec4 index_sample = texelFetch( uLightsIndex, coord, 0 );\n"
-"\n"
-"      uint light_count = (index_sample.x & 0x3u) + (index_sample.y & 0x3u);\n"
-"      return vec3( float(light_count)*(1.0/6.0), 0.0, 0.5 );\n"
-"   }\n"
-"\n"
-"   // FIXME: this coord should absolutely must be clamped!\n"
-"   \n"
-"   ivec3 coord = ivec3( cube_coord );\n"
-"   uvec4 index_sample = texelFetch( uLightsIndex, coord, 0 );\n"
-"\n"
-"   total_light += \n"
-"      scene_calculate_packed_light_patch( index_sample.x,\n"
-"                                          halfview, co, normal ) \n"
-"                                          * light_mask;\n"
-"   total_light += \n"
-"      scene_calculate_packed_light_patch( index_sample.y,\n"
-"                                          halfview, co, normal )\n"
-"                                          * light_mask;\n"
-"\n"
-"   // Take a section of the sky function to give us a matching fog colour\n"
-"\n"
-"   vec3 fog_colour  = clearskies_ambient( -halfview );\n"
-"   float sun_theta  = dot( -halfview, g_sun_dir.xyz );\n"
-"   float sun_size   = max( 0.0, sun_theta * 0.5 + 0.5 );\n"
-"   float sun_shape  = sun_size * max(g_sun_dir.y,0.0) * 0.5;\n"
-"         \n"
-"   vec3 sun_colour  = mix( vec3(1.0), g_sunset_colour.rgb, g_sunset_phase*0.5 );\n"
-"        sun_colour *= sun_shape;\n"
-"\n"
-"   fog_colour += sun_colour;\n"
-"   return scene_apply_fog( diffuse * total_light, fog_colour, fdist );\n"
-"}\n"
-"\n"
-"#line      9        0 \n"
-"\n"
-"float sdLine( vec3 p, vec3 a, vec3 b )\n"
-"{\n"
-"  vec3 pa = p - a;\n"
-"  vec3 ba = b - a;\n"
-"\n"
-"  float h = clamp( dot(pa,ba)/dot(ba,ba), 0.0, 1.0 );\n"
-"  return length( pa - ba*h );\n"
-"}\n"
-"\n"
-"float compute_board_shadow()\n"
-"{\n"
-"   // player shadow\n"
-"   float dist_to_player = max( 0.0, sdLine( aWorldCo, g_board_0.xyz,\n"
-"                                                      g_board_1.xyz )-0.1 );\n"
-"   float player_shadow = max( 1.0-dist_to_player*2.7, 0.0 );\n"
-"   player_shadow *= player_shadow*player_shadow*player_shadow;\n"
-"\n"
-"   return 1.0 - player_shadow*0.8;\n"
-"}\n"
-"\n"
-"vec3 scene_compute_lighting( vec3 diffuse, vec3 normal, vec3 co )\n"
-"{\n"
-"   return world_compute_lighting( diffuse, normal, co, compute_board_shadow() );\n"
-"}\n"
-"\n"
-"#line      8        0 \n"
-"#line       1        3 \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      9        0 \n"
-"\n"
-"float filtered_stripe( in float p, in float ddx, in float ddy )\n"
-"{\n"
-"   float w = max(abs(ddx), abs(ddy)) + 0.02;\n"
-"   float i = (abs(fract((p-0.5*w)/2.0)-0.5)-abs(fract((p+0.5*w)/2.0)-0.5))/w;\n"
-"   return 0.5 - i;\n"
-"}\n"
-"\n"
-"void main()\n"
-"{\n"
-"   compute_motion_vectors();\n"
-"\n"
-"   vec3 vfrag = vec3(0.5,0.5,0.5);\n"
-"\n"
-"   // ws modulation\n"
-"   vec4 wgarbage = texture( uTexGarbage, aCo.xz * 0.015 );\n"
-"\n"
-"   // Creating normal patches\n"
-"   vec3 modnorm = (wgarbage.rgb-0.4) * 1.4;\n"
-"   vec3 qnorm = normalize(floor(aNorm.xyz*4.0+modnorm)*0.25);\n"
-"   qnorm += vec3(0.001,0.0,0.0);\n"
-"\n"
-"   vec3 tangent0 = normalize(cross(qnorm,vec3(0.0,1.0,0.0)));\n"
-"   vec3 tangent1 = cross(qnorm,tangent0);\n"
-"   vec2 uvdiffuse = vec2( dot(tangent0,aCo), dot(tangent1,aCo) ) * 0.035;\n"
-"   \n"
-"   // Patch local noise\n"
-"   vec4 rgarbage = texture( uTexGarbage, uvdiffuse );\n"
-"\n"
-"   vfrag = pow(uColour.rgb,vec3(1.0/2.2));\n"
-"   vfrag -= rgarbage.a*0.1;\n"
-"\n"
-"   if( wgarbage.g < 0.1 )\n"
-"      discard;\n"
-"\n"
-"   float movep = (aUv.x + abs(aUv.y-0.5)*0.4 - g_realtime)*2.0;\n"
-"   float stripe = filtered_stripe( movep, dFdx(movep), dFdy(movep) );\n"
-"   vfrag *= 0.9+stripe*uColour.a; \n"
-"\n"
-"   if( g_light_preview == 1 )\n"
-"   {\n"
-"      vfrag = vec3(0.5);\n"
-"   }\n"
-"\n"
-"   // Lighting\n"
-"   oColour = vec4( scene_compute_lighting( vfrag, qnorm, aWorldCo ), 1.0 );\n"
-"}\n"
-""},
-};
-
-static GLuint _uniform_scene_route_uMdl;
-static GLuint _uniform_scene_route_uPv;
-static GLuint _uniform_scene_route_uPvmPrev;
-static GLuint _uniform_scene_route_uNormalMtx;
-static GLuint _uniform_scene_route_uTexGarbage;
-static GLuint _uniform_scene_route_uTexGradients;
-static GLuint _uniform_scene_route_uCamera;
-static GLuint _uniform_scene_route_uColour;
-static GLuint _uniform_scene_route_g_world_depth;
-static GLuint _uniform_scene_route_uLightsArray;
-static GLuint _uniform_scene_route_uLightsIndex;
-static void shader_scene_route_uMdl(m4x3f m){
-   glUniformMatrix4x3fv(_uniform_scene_route_uMdl,1,GL_FALSE,(float*)m);
+   glUniformMatrix4x3fv(_uniform_scene_route_uMdl,1,GL_FALSE,(f32*)m);
 }
-static void shader_scene_route_uPv(m4x4f m){
-   glUniformMatrix4fv(_uniform_scene_route_uPv,1,GL_FALSE,(float*)m);
+static inline void shader_scene_route_uPv(m4x4f m)
+{
+   glUniformMatrix4fv(_uniform_scene_route_uPv,1,GL_FALSE,(f32*)m);
 }
-static void shader_scene_route_uPvmPrev(m4x4f m){
-   glUniformMatrix4fv(_uniform_scene_route_uPvmPrev,1,GL_FALSE,(float*)m);
+static inline void shader_scene_route_uPvmPrev(m4x4f m)
+{
+   glUniformMatrix4fv(_uniform_scene_route_uPvmPrev,1,GL_FALSE,(f32*)m);
 }
-static void shader_scene_route_uNormalMtx(m3x3f m){
-   glUniformMatrix3fv(_uniform_scene_route_uNormalMtx,1,GL_FALSE,(float*)m);
+static inline void shader_scene_route_uNormalMtx(m3x3f m)
+{
+   glUniformMatrix3fv(_uniform_scene_route_uNormalMtx,1,GL_FALSE,(f32*)m);
 }
-static void shader_scene_route_uTexGarbage(int i){
+static inline void shader_scene_route_uTexGarbage(int i)
+{
    glUniform1i(_uniform_scene_route_uTexGarbage,i);
 }
-static void shader_scene_route_uTexGradients(int i){
+static inline void shader_scene_route_uTexGradients(int i)
+{
    glUniform1i(_uniform_scene_route_uTexGradients,i);
 }
-static void shader_scene_route_uCamera(v3f v){
+static inline void shader_scene_route_uCamera(v3f v)
+{
    glUniform3fv(_uniform_scene_route_uCamera,1,v);
 }
-static void shader_scene_route_uColour(v4f v){
+static inline void shader_scene_route_uColour(v4f v)
+{
    glUniform4fv(_uniform_scene_route_uColour,1,v);
 }
-static void shader_scene_route_g_world_depth(int i){
+static inline void shader_scene_route_g_world_depth(int i)
+{
    glUniform1i(_uniform_scene_route_g_world_depth,i);
 }
-static void shader_scene_route_register(void){
-   vg_shader_register( &_shader_scene_route );
-}
-static void shader_scene_route_use(void){ glUseProgram(_shader_scene_route.id); }
-static void shader_scene_route_link(void){
-   _uniform_scene_route_uMdl = glGetUniformLocation( _shader_scene_route.id, "uMdl" );
-   _uniform_scene_route_uPv = glGetUniformLocation( _shader_scene_route.id, "uPv" );
-   _uniform_scene_route_uPvmPrev = glGetUniformLocation( _shader_scene_route.id, "uPvmPrev" );
-   _uniform_scene_route_uNormalMtx = glGetUniformLocation( _shader_scene_route.id, "uNormalMtx" );
-   _uniform_scene_route_uTexGarbage = glGetUniformLocation( _shader_scene_route.id, "uTexGarbage" );
-   _uniform_scene_route_uTexGradients = glGetUniformLocation( _shader_scene_route.id, "uTexGradients" );
-   _uniform_scene_route_uCamera = glGetUniformLocation( _shader_scene_route.id, "uCamera" );
-   _uniform_scene_route_uColour = glGetUniformLocation( _shader_scene_route.id, "uColour" );
-   _uniform_scene_route_g_world_depth = glGetUniformLocation( _shader_scene_route.id, "g_world_depth" );
-   _uniform_scene_route_uLightsArray = glGetUniformLocation( _shader_scene_route.id, "uLightsArray" );
-   _uniform_scene_route_uLightsIndex = glGetUniformLocation( _shader_scene_route.id, "uLightsIndex" );
+static inline void shader_scene_route_use(void);
+static inline void shader_scene_route_use(void)
+{
+   glUseProgram(_shader_scene_route.id);
 }
-#endif /* SHADER_scene_route_H */
index 3b91becdea75b7e4d04f9d37eb2c73aedbd4bde9..0be2bf2dbffcc2ca72e52148c06456f2ceb8694d 100644 (file)
-#ifndef SHADER_scene_scoretext_H
-#define SHADER_scene_scoretext_H
-static void shader_scene_scoretext_link(void);
-static void shader_scene_scoretext_register(void);
-static struct vg_shader _shader_scene_scoretext = {
-   .name = "scene_scoretext",
-   .link = shader_scene_scoretext_link,
-   .vs = 
+#pragma once
+#include "vg/vg_engine.h"
+extern struct vg_shader _shader_scene_scoretext;
+extern GLuint _uniform_scene_scoretext_uMdl;
+extern GLuint _uniform_scene_scoretext_uPv;
+extern GLuint _uniform_scene_scoretext_uPvmPrev;
+extern GLuint _uniform_scene_scoretext_uInfo;
+extern GLuint _uniform_scene_scoretext_uTexGarbage;
+extern GLuint _uniform_scene_scoretext_uTexMain;
+extern GLuint _uniform_scene_scoretext_uCamera;
+extern GLuint _uniform_scene_scoretext_uPlane;
+extern GLuint _uniform_scene_scoretext_g_world_depth;
+extern GLuint _uniform_scene_scoretext_uLightsArray;
+extern GLuint _uniform_scene_scoretext_uLightsIndex;
+static inline void shader_scene_scoretext_uMdl(m4x3f m)
 {
-.orig_file = "shaders/scene_sfd.vs",
-.static_src = 
-"layout (location=0) in vec3  a_co;\n"
-"layout (location=1) in vec4  a_norm;\n"
-"layout (location=2) in vec2  a_uv;\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      6        0 \n"
-"\n"
-"uniform mat4x3 uMdl;\n"
-"uniform mat4   uPv;\n"
-"uniform mat4   uPvmPrev;\n"
-"uniform vec3   uInfo;\n"
-"\n"
-"out vec2 aUv;\n"
-"out vec4 aNorm;\n"
-"out vec3 aCo;\n"
-"out vec3 aWorldCo;\n"
-"\n"
-"void main()\n"
-"{\n"
-"   float w = ((a_norm.w)-0.5)*2.0 + fract(uInfo.z) - 0.0;\n"
-"   float c = -cos(w*0.6);\n"
-"   float s = -sin(w*0.6);\n"
-"   float r = 0.2;\n"
-"\n"
-"   float w1 = clamp( w*4.0 - a_co.y*10.0, -1.0, 1.0 ) * (3.14159265*0.5);\n"
-"   float c1 = cos(w1);\n"
-"   float s1 = sin(w1);\n"
-"\n"
-"   float yoff = step(0.01,fract(uInfo.z))*-0.5;\n"
-"\n"
-"   mat4x3 mlocal;\n"
-"   mlocal[0] = vec3(c1, s1,0.0);\n"
-"   mlocal[1] = vec3(-s1,c1,0.0);\n"
-"   mlocal[2] = vec3(0.0,0.0,1.0);\n"
-"   mlocal[3] = vec3(c*r,uInfo.y*0.875 + s*r,uInfo.x*0.5);\n"
-"\n"
-"   vec3 local_pos0 = mlocal * vec4( a_co, 1.0 );\n"
-"   vec3 world_pos0 = uMdl * vec4( local_pos0, 1.0 );\n"
-"\n"
-"   vec4 vproj0     = uPv      * vec4( world_pos0, 1.0 );\n"
-"   vec4 vproj1     = uPvmPrev * vec4( local_pos0, 1.0 );\n"
-"\n"
-"   vs_motion_out( vproj0, vproj1 );\n"
-"\n"
-"   gl_Position = vproj0;\n"
-"\n"
-"   aUv = a_uv + vec2( floor(uInfo.z+0.5)*(1.0/64.0), yoff );\n"
-"   aNorm = vec4( mat3(uMdl) * mat3(mlocal) * a_norm.xyz, a_norm.w );\n"
-"   aCo = a_co;\n"
-"   aWorldCo = world_pos0;\n"
-"}\n"
-""},
-   .fs = 
-{
-.orig_file = "shaders/scene_standard.fs",
-.static_src = 
-"uniform sampler2D uTexGarbage;\n"
-"uniform sampler2D uTexMain;\n"
-"uniform vec3 uCamera;\n"
-"uniform vec4 uPlane;\n"
-"\n"
-"#line       1        1 \n"
-"// :D\n"
-"const float CLEARSKIES_LIGHT_DOT_MIN = 0.0;\n"
-"\n"
-"#line      7        0 \n"
-"#line       1        2 \n"
-"// :D\n"
-"\n"
-"in vec2 aUv;\n"
-"in vec4 aNorm;\n"
-"in vec3 aCo;\n"
-"in vec3 aWorldCo;\n"
-"\n"
-"#line       1        1 \n"
-"layout (location = 0) out vec4 oColour;\n"
-"\n"
-"// OpenGL wiki: Recommends do not use vec3 because of drivers. hence the v4s...\n"
-"layout (std140) uniform ub_world_lighting\n"
-"{\n"
-"   vec4 g_cube_min;\n"
-"   vec4 g_cube_inv_range;\n"
-"\n"
-"   vec4 g_water_plane;\n"
-"   vec4 g_depth_bounds;\n"
-"\n"
-"   vec4 g_daysky_colour;\n"
-"   vec4 g_nightsky_colour;\n"
-"   vec4 g_sunset_colour;\n"
-"   vec4 g_ambient_colour;\n"
-"   vec4 g_sunset_ambient;\n"
-"   vec4 g_sun_colour;\n"
-"   vec4 g_sun_dir;\n"
-"   vec4 g_board_0;\n"
-"   vec4 g_board_1;\n"
-"\n"
-"   float g_water_fog;\n"
-"   float g_time;\n"
-"   float g_realtime;\n"
-"   float g_shadow_length;\n"
-"   float g_shadow_spread;\n"
-"\n"
-"   float g_time_of_day;\n"
-"   float g_day_phase;\n"
-"   float g_sunset_phase;\n"
-"\n"
-"   int g_light_preview;\n"
-"   int g_shadow_samples;\n"
-"\n"
-"   int g_debug_indices;\n"
-"   int g_debug_complexity;\n"
-"};\n"
-"\n"
-"uniform sampler2D g_world_depth;\n"
-"uniform samplerBuffer uLightsArray;\n"
-"uniform usampler3D uLightsIndex;\n"
-"\n"
-"#line       1        1 \n"
-"//const vec3  DAYSKY_COLOUR   = vec3( 0.37, 0.54, 0.97 );\n"
-"//const vec3  NIGHTSKY_COLOUR = vec3( 0.03, 0.05, 0.20 );\n"
-"//const vec3  SUNSET_COLOUR   = vec3( 1.00, 0.32, 0.01 );\n"
-"//const vec3  AMBIENT_COLOUR  = vec3( 0.13, 0.17, 0.35 );\n"
-"//const vec3  SUNSET_AMBIENT  = vec3( 0.25, 0.17, 0.51 );\n"
-"//const vec3  SUN_COLOUR      = vec3( 1.10, 0.89, 0.35 );\n"
-"\n"
-"const float SUN_ANGLE       = 0.0001;\n"
-"const float PI              = 3.14159265358979323846264;\n"
-"\n"
-"//struct world_info\n"
-"//{\n"
-"//   float time,\n"
-"//         time_of_day,\n"
-"//         day_phase,\n"
-"//         sunset_phase;\n"
-"//   \n"
-"//   vec3 sun_dir;\n"
-"//};\n"
-"\n"
-"vec3 rand33(vec3 p3)\n"
-"{\n"
-"      p3 = fract(p3 * vec3(.1031, .1030, .0973));\n"
-"   p3 += dot(p3, p3.yxz+33.33);\n"
-"   return fract((p3.xxy + p3.yxx)*p3.zyx);\n"
-"}\n"
-"\n"
-"float stars( vec3 rd, float rr, float size ){\n"
-"   vec3 co = rd * rr;\n"
-"\n"
-"   float a = atan(co.y, length(co.xz)) + 4.0 * PI;\n"
-"\n"
-"   float spaces = 1.0 / rr;\n"
-"   size = (rr * 0.0015) * fwidth(a) * 1000.0 * size;\n"
-"   a -= mod(a, spaces) - spaces * 0.5;\n"
-"\n"
-"   float count = floor(sqrt(pow(rr, 2.0) * (1.0 - pow(sin(a), 2.0))) * 3.0);\n"
-"   \n"
-"   float plane = atan(co.z, co.x) + 4.0 * PI;\n"
-"   plane = plane - mod(plane, PI / count);\n"
-"\n"
-"   vec2 delta = rand33(vec3(plane, a, 0.0)).xy;\n"
-"\n"
-"   float level = sin(a + spaces * (delta.y - 0.5) * (1.0 - size)) * rr;\n"
-"   float ydist = sqrt(rr * rr - level * level);\n"
-"   float angle = plane + (PI * (delta.x * (1.0-size) + size * 0.5) / count);\n"
-"   vec3 center = vec3(cos(angle) * ydist, level, sin(angle) * ydist);\n"
-"   float star = smoothstep(size, 0.0, distance(center, co));\n"
-"   return star;\n"
-"}\n"
-"\n"
-"float luminance( vec3 v )\n"
-"{\n"
-"   return dot( v, vec3(0.2126, 0.7152, 0.0722) );\n"
-"}\n"
-"\n"
-"vec3 clearskies_ambient( vec3 dir )\n"
-"{\n"
-"   float sun_azimuth  = g_sunset_phase * (dot( dir.xz, g_sun_dir.xz )*0.4+0.6);\n"
-"   float sky_gradient = dir.y;\n"
-"   \n"
-"   /* Blend phase colours */\n"
-"   vec3 ambient  = g_daysky_colour.rgb   * (g_day_phase-g_sunset_phase*0.1);\n"
-"        ambient += g_sunset_colour.rgb   * (1.0-dir.y*0.5)*sun_azimuth;\n"
-"        ambient += g_nightsky_colour.rgb * (1.0-g_day_phase);\n"
-"   \n"
-"   /* Add gradient */\n"
-"        ambient -= sky_gradient * luminance(ambient);\n"
-"        \n"
-"   return ambient;\n"
-"}\n"
-"\n"
-"vec3 clearskies_sky( vec3 ray_dir )\n"
-"{\n"
-"   ray_dir.y = abs( ray_dir.y );\n"
-"   vec3 sky_colour  = clearskies_ambient( ray_dir );\n"
-"   \n"
-"   /* Sun */\n"
-"   float sun_theta  = dot( ray_dir, g_sun_dir.xyz );\n"
-"   float sun_size   = max( 0.0, sun_theta * 0.5 + 0.5 + SUN_ANGLE );\n"
-"   float sun_shape  = pow( sun_size, 2000.0 );\n"
-"         sun_shape += sun_size * max(g_sun_dir.y,0.0) * 0.5;\n"
-"         \n"
-"   vec3 sun_colour  = mix( vec3(1.0), g_sunset_colour.rgb, g_sunset_phase*0.5 );\n"
-"        sun_colour *= sun_shape;\n"
-"\n"
-"   \n"
-"   float star = 0.0;\n"
-"   float star_blend = 10.0*max(0.0,(1.0-g_day_phase*2.0));\n"
-"\n"
-"   if( star_blend > 0.001 ){\n"
-"      for( float j = 1.0; j <= 4.1; j += 1.0 ){\n"
-"         float m = mix(0.6, 0.9, smoothstep(1.0, 2.0, j));\n"
-"         star += stars( ray_dir, 1.94 * pow( 1.64, j ), m ) * (1.0/pow(4.0, j));\n"
-"      }\n"
-"   }\n"
-"   \n"
-"   vec3 composite   = sky_colour + sun_colour + star*star_blend;\n"
-"   return composite;\n"
-"}\n"
-"\n"
-"vec3 clearskies_lighting( vec3 normal, float shadow, vec3 halfview )\n"
-"{\n"
-"   float fresnel = 1.0 - abs(dot(normal,halfview));\n"
-"\n"
-"   vec3  reflect_colour = mix( g_daysky_colour.rgb, g_sunset_colour.rgb, \n"
-"                               g_sunset_phase );\n"
-"\n"
-"   vec3  sky_reflection = 0.5 * fresnel * reflect_colour;\n"
-"   vec3  light_sun      = max( CLEARSKIES_LIGHT_DOT_MIN, \n"
-"                               dot(normal,g_sun_dir.xyz)*0.75+0.25\n"
-"                           ) * g_sun_colour.rgb * g_day_phase;\n"
-"\n"
-"   float scaled_shadow = max( shadow, 1.0 - max(g_sun_dir.y,0.0) );\n"
-"   vec3 ambient = mix( g_ambient_colour.rgb, g_sunset_ambient.rgb, \n"
-"                       g_sunset_phase );\n"
-"\n"
-"   return ambient + (light_sun + sky_reflection) * shadow;\n"
-"}\n"
-"\n"
-"#line     44        0 \n"
-"\n"
-"float world_depth_sample( vec3 pos )\n"
-"{\n"
-"   vec2 depth_coord = (pos.xz - g_depth_bounds.xy) * g_depth_bounds.zw; \n"
-"   return texture( g_world_depth, depth_coord ).r;\n"
-"}\n"
-"\n"
-"float world_water_depth( vec3 pos )\n"
-"{\n"
-"   float ref_depth = g_water_plane.y*g_water_plane.w;\n"
-"   return world_depth_sample( pos ) - ref_depth;\n"
-"}\n"
-"\n"
-"float shadow_sample( vec3 co ){\n"
-"   float height_sample = world_depth_sample( co );\n"
-"\n"
-"   float fdelta = height_sample - co.y;\n"
-"   return clamp( fdelta, 0.2, 0.4 )-0.2;\n"
-"}\n"
-"\n"
-"float newlight_compute_sun_shadow( vec3 co, vec3 dir ){\n"
-"   if( g_shadow_samples == 0 ){\n"
-"      return 1.0;\n"
-"   }\n"
-"\n"
-"   float fspread = g_shadow_spread;\n"
-"   float flength = g_shadow_length;\n"
-"\n"
-"   float famt = 0.0;\n"
-"   famt += shadow_sample(co+(dir+vec3(-0.56,0.55, 0.30)*fspread)*flength*0.1);\n"
-"   famt += shadow_sample(co+(dir+vec3( 0.80,0.68, 0.34)*fspread)*flength*0.2);\n"
-"   famt += shadow_sample(co+(dir+vec3( 0.78,0.07,-0.06)*fspread)*flength*0.3);\n"
-"   famt += shadow_sample(co+(dir+vec3(-0.59,0.07,-0.42)*fspread)*flength*0.4);\n"
-"\n"
-"   //famt+=shadow_sample(co+(dir+vec3(-0.790,-0.933,-0.875)*fspread)*flength*0.5);\n"
-"   //famt+=shadow_sample(co+(dir+vec3( 0.807,-0.690, 0.472)*fspread)*flength*0.6);\n"
-"   //famt+=shadow_sample(co+(dir+vec3( 0.522,-0.379, 0.350)*fspread)*flength*0.7);\n"
-"   //famt+=shadow_sample(co+(dir+vec3( 0.483, 0.201, 0.306)*fspread)*flength*0.8);\n"
-"\n"
-"   return 1.0 - famt;\n"
-"}\n"
-"\n"
-"float newlight_specular( vec3 wnormal, vec3 dir, vec3 halfview, float exponent )\n"
-"{\n"
-"   vec3 specdir = reflect( -dir, wnormal );\n"
-"   return pow(max(dot( halfview, specdir ), 0.0), exponent);\n"
-"}\n"
-"\n"
-"vec3 scene_apply_fog( vec3 vfrag, vec3 colour, float fdist ){\n"
-"   float dist = pow(fdist*0.0010,0.78);\n"
-"   return mix( vfrag, colour, min( 1.0, dist ) );\n"
-"}\n"
-"\n"
-"vec3 scene_calculate_light( int light_index, \n"
-"                            vec3 halfview, vec3 co, vec3 normal )\n"
-"{\n"
-"   vec4 light_colour = texelFetch( uLightsArray, light_index+0 );\n"
-"   vec4 light_co     = texelFetch( uLightsArray, light_index+1 );\n"
-"   vec4 light_dir    = texelFetch( uLightsArray, light_index+2 );\n"
-"\n"
-"   vec3 light_delta = light_co.xyz-co;\n"
-"   float dist2 = dot(light_delta,light_delta);\n"
-"\n"
-"   light_delta = normalize( light_delta );\n"
-"\n"
-"   float quadratic = dist2*100.0;\n"
-"   float attenuation  = 1.0/( 1.0 + quadratic );\n"
-"         attenuation *= max( dot( light_delta, normal ), 0.0 );\n"
-"\n"
-"   float falloff = max( 0.0, 1.0-(dist2*light_co.w) );\n"
-"\n"
-"   if( light_dir.w < 0.999999 ){\n"
-"      float spot_theta = max( 0.0, dot( light_delta, -light_dir.xyz ) );\n"
-"      falloff *= max( 0.0, (spot_theta - light_dir.w) / (1.0-light_dir.w) );\n"
-"   }\n"
-"\n"
-"   return light_colour.rgb * attenuation * falloff \n"
-"            * step( g_day_phase, light_colour.w );\n"
-"}\n"
-"\n"
-"vec3 scene_calculate_packed_light_patch( uint packed_index, \n"
-"                                         vec3 halfview, vec3 co, vec3 normal )\n"
-"{\n"
-"   uint light_count = packed_index & 0x3u;\n"
-"\n"
-"   vec3 l = vec3(0.0);\n"
-"\n"
-"   if( light_count >= 1u ){\n"
-"      int index_0 = int( ((packed_index >>  2u) & 0x3ffu) * 3u );\n"
-"      int index_1 = int( ((packed_index >> 12u) & 0x3ffu) * 3u );\n"
-"      int index_2 = int( ((packed_index >> 22u) & 0x3ffu) * 3u );\n"
-"\n"
-"      l += scene_calculate_light( index_0, halfview, co, normal );\n"
-"\n"
-"      if( light_count >= 2u ){\n"
-"         l += scene_calculate_light( index_1, halfview, co, normal );\n"
-"\n"
-"         if( light_count >= 3u ){\n"
-"            l += scene_calculate_light( index_2, halfview, co, normal );\n"
-"         }\n"
-"      }\n"
-"   }\n"
-"\n"
-"   return l;\n"
-"}\n"
-"\n"
-"vec3 world_compute_lighting( vec3 diffuse, vec3 normal, vec3 co,\n"
-"                             float light_mask )\n"
-"{\n"
-"   if( g_light_preview == 1 )\n"
-"      diffuse = vec3(0.75);\n"
-"\n"
-"   // Lighting\n"
-"   vec3 halfview = uCamera - co;\n"
-"   float fdist = length(halfview);\n"
-"   halfview /= fdist;\n"
-"\n"
-"   float world_shadow = newlight_compute_sun_shadow( \n"
-"               co, g_sun_dir.xyz * (1.0/(max(g_sun_dir.y,0.0)+0.2)) );\n"
-"\n"
-"   vec3 total_light = clearskies_lighting( \n"
-"                           normal, min( light_mask, world_shadow ), halfview );\n"
-"\n"
-"   vec3 cube_coord = (co - g_cube_min.xyz) * g_cube_inv_range.xyz;\n"
-"        cube_coord = floor( cube_coord );\n"
-"\n"
-"   if( g_debug_indices == 1 )\n"
-"   {\n"
-"      return rand33(cube_coord);\n"
-"   }\n"
-"\n"
-"   if( g_debug_complexity == 1 )\n"
-"   {\n"
-"      ivec3 coord = ivec3( cube_coord );\n"
-"      uvec4 index_sample = texelFetch( uLightsIndex, coord, 0 );\n"
-"\n"
-"      uint light_count = (index_sample.x & 0x3u) + (index_sample.y & 0x3u);\n"
-"      return vec3( float(light_count)*(1.0/6.0), 0.0, 0.5 );\n"
-"   }\n"
-"\n"
-"   // FIXME: this coord should absolutely must be clamped!\n"
-"   \n"
-"   ivec3 coord = ivec3( cube_coord );\n"
-"   uvec4 index_sample = texelFetch( uLightsIndex, coord, 0 );\n"
-"\n"
-"   total_light += \n"
-"      scene_calculate_packed_light_patch( index_sample.x,\n"
-"                                          halfview, co, normal ) \n"
-"                                          * light_mask;\n"
-"   total_light += \n"
-"      scene_calculate_packed_light_patch( index_sample.y,\n"
-"                                          halfview, co, normal )\n"
-"                                          * light_mask;\n"
-"\n"
-"   // Take a section of the sky function to give us a matching fog colour\n"
-"\n"
-"   vec3 fog_colour  = clearskies_ambient( -halfview );\n"
-"   float sun_theta  = dot( -halfview, g_sun_dir.xyz );\n"
-"   float sun_size   = max( 0.0, sun_theta * 0.5 + 0.5 );\n"
-"   float sun_shape  = sun_size * max(g_sun_dir.y,0.0) * 0.5;\n"
-"         \n"
-"   vec3 sun_colour  = mix( vec3(1.0), g_sunset_colour.rgb, g_sunset_phase*0.5 );\n"
-"        sun_colour *= sun_shape;\n"
-"\n"
-"   fog_colour += sun_colour;\n"
-"   return scene_apply_fog( diffuse * total_light, fog_colour, fdist );\n"
-"}\n"
-"\n"
-"#line      9        0 \n"
-"\n"
-"float sdLine( vec3 p, vec3 a, vec3 b )\n"
-"{\n"
-"  vec3 pa = p - a;\n"
-"  vec3 ba = b - a;\n"
-"\n"
-"  float h = clamp( dot(pa,ba)/dot(ba,ba), 0.0, 1.0 );\n"
-"  return length( pa - ba*h );\n"
-"}\n"
-"\n"
-"float compute_board_shadow()\n"
-"{\n"
-"   // player shadow\n"
-"   float dist_to_player = max( 0.0, sdLine( aWorldCo, g_board_0.xyz,\n"
-"                                                      g_board_1.xyz )-0.1 );\n"
-"   float player_shadow = max( 1.0-dist_to_player*2.7, 0.0 );\n"
-"   player_shadow *= player_shadow*player_shadow*player_shadow;\n"
-"\n"
-"   return 1.0 - player_shadow*0.8;\n"
-"}\n"
-"\n"
-"vec3 scene_compute_lighting( vec3 diffuse, vec3 normal, vec3 co )\n"
-"{\n"
-"   return world_compute_lighting( diffuse, normal, co, compute_board_shadow() );\n"
-"}\n"
-"\n"
-"#line      8        0 \n"
-"#line       1        3 \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      9        0 \n"
-"\n"
-"void main()\n"
-"{\n"
-"   compute_motion_vectors();\n"
-"\n"
-"   vec3 vfrag = vec3(0.5,0.5,0.5);\n"
-"   vec4 vsamplemain = texture( uTexMain, aUv );\n"
-"   vec3 qnorm = aNorm.xyz;\n"
-"\n"
-"   vfrag = vsamplemain.rgb;\n"
-"\n"
-"   if( g_light_preview == 1 )\n"
-"   {\n"
-"      vfrag = vec3(0.5);\n"
-"   }\n"
-"\n"
-"   vfrag = scene_compute_lighting( vfrag, qnorm, aWorldCo );\n"
-"   oColour = vec4( vfrag, 1.0 );\n"
-"}\n"
-""},
-};
-
-static GLuint _uniform_scene_scoretext_uMdl;
-static GLuint _uniform_scene_scoretext_uPv;
-static GLuint _uniform_scene_scoretext_uPvmPrev;
-static GLuint _uniform_scene_scoretext_uInfo;
-static GLuint _uniform_scene_scoretext_uTexGarbage;
-static GLuint _uniform_scene_scoretext_uTexMain;
-static GLuint _uniform_scene_scoretext_uCamera;
-static GLuint _uniform_scene_scoretext_uPlane;
-static GLuint _uniform_scene_scoretext_g_world_depth;
-static GLuint _uniform_scene_scoretext_uLightsArray;
-static GLuint _uniform_scene_scoretext_uLightsIndex;
-static void shader_scene_scoretext_uMdl(m4x3f m){
-   glUniformMatrix4x3fv(_uniform_scene_scoretext_uMdl,1,GL_FALSE,(float*)m);
+   glUniformMatrix4x3fv(_uniform_scene_scoretext_uMdl,1,GL_FALSE,(f32*)m);
 }
-static void shader_scene_scoretext_uPv(m4x4f m){
-   glUniformMatrix4fv(_uniform_scene_scoretext_uPv,1,GL_FALSE,(float*)m);
+static inline void shader_scene_scoretext_uPv(m4x4f m)
+{
+   glUniformMatrix4fv(_uniform_scene_scoretext_uPv,1,GL_FALSE,(f32*)m);
 }
-static void shader_scene_scoretext_uPvmPrev(m4x4f m){
-   glUniformMatrix4fv(_uniform_scene_scoretext_uPvmPrev,1,GL_FALSE,(float*)m);
+static inline void shader_scene_scoretext_uPvmPrev(m4x4f m)
+{
+   glUniformMatrix4fv(_uniform_scene_scoretext_uPvmPrev,1,GL_FALSE,(f32*)m);
 }
-static void shader_scene_scoretext_uInfo(v3f v){
+static inline void shader_scene_scoretext_uInfo(v3f v)
+{
    glUniform3fv(_uniform_scene_scoretext_uInfo,1,v);
 }
-static void shader_scene_scoretext_uTexGarbage(int i){
+static inline void shader_scene_scoretext_uTexGarbage(int i)
+{
    glUniform1i(_uniform_scene_scoretext_uTexGarbage,i);
 }
-static void shader_scene_scoretext_uTexMain(int i){
+static inline void shader_scene_scoretext_uTexMain(int i)
+{
    glUniform1i(_uniform_scene_scoretext_uTexMain,i);
 }
-static void shader_scene_scoretext_uCamera(v3f v){
+static inline void shader_scene_scoretext_uCamera(v3f v)
+{
    glUniform3fv(_uniform_scene_scoretext_uCamera,1,v);
 }
-static void shader_scene_scoretext_uPlane(v4f v){
+static inline void shader_scene_scoretext_uPlane(v4f v)
+{
    glUniform4fv(_uniform_scene_scoretext_uPlane,1,v);
 }
-static void shader_scene_scoretext_g_world_depth(int i){
+static inline void shader_scene_scoretext_g_world_depth(int i)
+{
    glUniform1i(_uniform_scene_scoretext_g_world_depth,i);
 }
-static void shader_scene_scoretext_register(void){
-   vg_shader_register( &_shader_scene_scoretext );
-}
-static void shader_scene_scoretext_use(void){ glUseProgram(_shader_scene_scoretext.id); }
-static void shader_scene_scoretext_link(void){
-   _uniform_scene_scoretext_uMdl = glGetUniformLocation( _shader_scene_scoretext.id, "uMdl" );
-   _uniform_scene_scoretext_uPv = glGetUniformLocation( _shader_scene_scoretext.id, "uPv" );
-   _uniform_scene_scoretext_uPvmPrev = glGetUniformLocation( _shader_scene_scoretext.id, "uPvmPrev" );
-   _uniform_scene_scoretext_uInfo = glGetUniformLocation( _shader_scene_scoretext.id, "uInfo" );
-   _uniform_scene_scoretext_uTexGarbage = glGetUniformLocation( _shader_scene_scoretext.id, "uTexGarbage" );
-   _uniform_scene_scoretext_uTexMain = glGetUniformLocation( _shader_scene_scoretext.id, "uTexMain" );
-   _uniform_scene_scoretext_uCamera = glGetUniformLocation( _shader_scene_scoretext.id, "uCamera" );
-   _uniform_scene_scoretext_uPlane = glGetUniformLocation( _shader_scene_scoretext.id, "uPlane" );
-   _uniform_scene_scoretext_g_world_depth = glGetUniformLocation( _shader_scene_scoretext.id, "g_world_depth" );
-   _uniform_scene_scoretext_uLightsArray = glGetUniformLocation( _shader_scene_scoretext.id, "uLightsArray" );
-   _uniform_scene_scoretext_uLightsIndex = glGetUniformLocation( _shader_scene_scoretext.id, "uLightsIndex" );
+static inline void shader_scene_scoretext_use(void);
+static inline void shader_scene_scoretext_use(void)
+{
+   glUseProgram(_shader_scene_scoretext.id);
 }
-#endif /* SHADER_scene_scoretext_H */
index 6a337e7dcb63cb4daade27f984ae3667fda0d33e..0dca3c7189881e3e158158a61bd519fa14c847e0 100644 (file)
-#ifndef SHADER_scene_standard_H
-#define SHADER_scene_standard_H
-static void shader_scene_standard_link(void);
-static void shader_scene_standard_register(void);
-static struct vg_shader _shader_scene_standard = {
-   .name = "scene_standard",
-   .link = shader_scene_standard_link,
-   .vs = 
+#pragma once
+#include "vg/vg_engine.h"
+extern struct vg_shader _shader_scene_standard;
+extern GLuint _uniform_scene_standard_uMdl;
+extern GLuint _uniform_scene_standard_uPv;
+extern GLuint _uniform_scene_standard_uPvmPrev;
+extern GLuint _uniform_scene_standard_uTexGarbage;
+extern GLuint _uniform_scene_standard_uTexMain;
+extern GLuint _uniform_scene_standard_uCamera;
+extern GLuint _uniform_scene_standard_uPlane;
+extern GLuint _uniform_scene_standard_g_world_depth;
+extern GLuint _uniform_scene_standard_uLightsArray;
+extern GLuint _uniform_scene_standard_uLightsIndex;
+static inline void shader_scene_standard_uMdl(m4x3f m)
 {
-.orig_file = "shaders/scene.vs",
-.static_src = 
-"layout (location=0) in vec3  a_co;\n"
-"layout (location=1) in vec4  a_norm;\n"
-"layout (location=2) in vec2  a_uv;\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      6        0 \n"
-"\n"
-"uniform mat4x3 uMdl;\n"
-"uniform mat4   uPv;\n"
-"uniform mat4   uPvmPrev;\n"
-"\n"
-"out vec2 aUv;\n"
-"out vec4 aNorm;\n"
-"out vec3 aCo;\n"
-"out vec3 aWorldCo;\n"
-"\n"
-"void main()\n"
-"{\n"
-"   vec3 world_pos0 = uMdl     * vec4( a_co, 1.0 );\n"
-"   vec4 vproj0     = uPv      * vec4( world_pos0, 1.0 );\n"
-"   vec4 vproj1     = uPvmPrev * vec4( a_co, 1.0 );\n"
-"\n"
-"   vs_motion_out( vproj0, vproj1 );\n"
-"\n"
-"   gl_Position = vproj0;\n"
-"\n"
-"   aUv = a_uv;\n"
-"   aNorm = vec4( mat3(uMdl) * a_norm.xyz, a_norm.w );\n"
-"   aCo = a_co;\n"
-"   aWorldCo = world_pos0;\n"
-"}\n"
-""},
-   .fs = 
-{
-.orig_file = "shaders/scene_standard.fs",
-.static_src = 
-"uniform sampler2D uTexGarbage;\n"
-"uniform sampler2D uTexMain;\n"
-"uniform vec3 uCamera;\n"
-"uniform vec4 uPlane;\n"
-"\n"
-"#line       1        1 \n"
-"// :D\n"
-"const float CLEARSKIES_LIGHT_DOT_MIN = 0.0;\n"
-"\n"
-"#line      7        0 \n"
-"#line       1        2 \n"
-"// :D\n"
-"\n"
-"in vec2 aUv;\n"
-"in vec4 aNorm;\n"
-"in vec3 aCo;\n"
-"in vec3 aWorldCo;\n"
-"\n"
-"#line       1        1 \n"
-"layout (location = 0) out vec4 oColour;\n"
-"\n"
-"// OpenGL wiki: Recommends do not use vec3 because of drivers. hence the v4s...\n"
-"layout (std140) uniform ub_world_lighting\n"
-"{\n"
-"   vec4 g_cube_min;\n"
-"   vec4 g_cube_inv_range;\n"
-"\n"
-"   vec4 g_water_plane;\n"
-"   vec4 g_depth_bounds;\n"
-"\n"
-"   vec4 g_daysky_colour;\n"
-"   vec4 g_nightsky_colour;\n"
-"   vec4 g_sunset_colour;\n"
-"   vec4 g_ambient_colour;\n"
-"   vec4 g_sunset_ambient;\n"
-"   vec4 g_sun_colour;\n"
-"   vec4 g_sun_dir;\n"
-"   vec4 g_board_0;\n"
-"   vec4 g_board_1;\n"
-"\n"
-"   float g_water_fog;\n"
-"   float g_time;\n"
-"   float g_realtime;\n"
-"   float g_shadow_length;\n"
-"   float g_shadow_spread;\n"
-"\n"
-"   float g_time_of_day;\n"
-"   float g_day_phase;\n"
-"   float g_sunset_phase;\n"
-"\n"
-"   int g_light_preview;\n"
-"   int g_shadow_samples;\n"
-"\n"
-"   int g_debug_indices;\n"
-"   int g_debug_complexity;\n"
-"};\n"
-"\n"
-"uniform sampler2D g_world_depth;\n"
-"uniform samplerBuffer uLightsArray;\n"
-"uniform usampler3D uLightsIndex;\n"
-"\n"
-"#line       1        1 \n"
-"//const vec3  DAYSKY_COLOUR   = vec3( 0.37, 0.54, 0.97 );\n"
-"//const vec3  NIGHTSKY_COLOUR = vec3( 0.03, 0.05, 0.20 );\n"
-"//const vec3  SUNSET_COLOUR   = vec3( 1.00, 0.32, 0.01 );\n"
-"//const vec3  AMBIENT_COLOUR  = vec3( 0.13, 0.17, 0.35 );\n"
-"//const vec3  SUNSET_AMBIENT  = vec3( 0.25, 0.17, 0.51 );\n"
-"//const vec3  SUN_COLOUR      = vec3( 1.10, 0.89, 0.35 );\n"
-"\n"
-"const float SUN_ANGLE       = 0.0001;\n"
-"const float PI              = 3.14159265358979323846264;\n"
-"\n"
-"//struct world_info\n"
-"//{\n"
-"//   float time,\n"
-"//         time_of_day,\n"
-"//         day_phase,\n"
-"//         sunset_phase;\n"
-"//   \n"
-"//   vec3 sun_dir;\n"
-"//};\n"
-"\n"
-"vec3 rand33(vec3 p3)\n"
-"{\n"
-"      p3 = fract(p3 * vec3(.1031, .1030, .0973));\n"
-"   p3 += dot(p3, p3.yxz+33.33);\n"
-"   return fract((p3.xxy + p3.yxx)*p3.zyx);\n"
-"}\n"
-"\n"
-"float stars( vec3 rd, float rr, float size ){\n"
-"   vec3 co = rd * rr;\n"
-"\n"
-"   float a = atan(co.y, length(co.xz)) + 4.0 * PI;\n"
-"\n"
-"   float spaces = 1.0 / rr;\n"
-"   size = (rr * 0.0015) * fwidth(a) * 1000.0 * size;\n"
-"   a -= mod(a, spaces) - spaces * 0.5;\n"
-"\n"
-"   float count = floor(sqrt(pow(rr, 2.0) * (1.0 - pow(sin(a), 2.0))) * 3.0);\n"
-"   \n"
-"   float plane = atan(co.z, co.x) + 4.0 * PI;\n"
-"   plane = plane - mod(plane, PI / count);\n"
-"\n"
-"   vec2 delta = rand33(vec3(plane, a, 0.0)).xy;\n"
-"\n"
-"   float level = sin(a + spaces * (delta.y - 0.5) * (1.0 - size)) * rr;\n"
-"   float ydist = sqrt(rr * rr - level * level);\n"
-"   float angle = plane + (PI * (delta.x * (1.0-size) + size * 0.5) / count);\n"
-"   vec3 center = vec3(cos(angle) * ydist, level, sin(angle) * ydist);\n"
-"   float star = smoothstep(size, 0.0, distance(center, co));\n"
-"   return star;\n"
-"}\n"
-"\n"
-"float luminance( vec3 v )\n"
-"{\n"
-"   return dot( v, vec3(0.2126, 0.7152, 0.0722) );\n"
-"}\n"
-"\n"
-"vec3 clearskies_ambient( vec3 dir )\n"
-"{\n"
-"   float sun_azimuth  = g_sunset_phase * (dot( dir.xz, g_sun_dir.xz )*0.4+0.6);\n"
-"   float sky_gradient = dir.y;\n"
-"   \n"
-"   /* Blend phase colours */\n"
-"   vec3 ambient  = g_daysky_colour.rgb   * (g_day_phase-g_sunset_phase*0.1);\n"
-"        ambient += g_sunset_colour.rgb   * (1.0-dir.y*0.5)*sun_azimuth;\n"
-"        ambient += g_nightsky_colour.rgb * (1.0-g_day_phase);\n"
-"   \n"
-"   /* Add gradient */\n"
-"        ambient -= sky_gradient * luminance(ambient);\n"
-"        \n"
-"   return ambient;\n"
-"}\n"
-"\n"
-"vec3 clearskies_sky( vec3 ray_dir )\n"
-"{\n"
-"   ray_dir.y = abs( ray_dir.y );\n"
-"   vec3 sky_colour  = clearskies_ambient( ray_dir );\n"
-"   \n"
-"   /* Sun */\n"
-"   float sun_theta  = dot( ray_dir, g_sun_dir.xyz );\n"
-"   float sun_size   = max( 0.0, sun_theta * 0.5 + 0.5 + SUN_ANGLE );\n"
-"   float sun_shape  = pow( sun_size, 2000.0 );\n"
-"         sun_shape += sun_size * max(g_sun_dir.y,0.0) * 0.5;\n"
-"         \n"
-"   vec3 sun_colour  = mix( vec3(1.0), g_sunset_colour.rgb, g_sunset_phase*0.5 );\n"
-"        sun_colour *= sun_shape;\n"
-"\n"
-"   \n"
-"   float star = 0.0;\n"
-"   float star_blend = 10.0*max(0.0,(1.0-g_day_phase*2.0));\n"
-"\n"
-"   if( star_blend > 0.001 ){\n"
-"      for( float j = 1.0; j <= 4.1; j += 1.0 ){\n"
-"         float m = mix(0.6, 0.9, smoothstep(1.0, 2.0, j));\n"
-"         star += stars( ray_dir, 1.94 * pow( 1.64, j ), m ) * (1.0/pow(4.0, j));\n"
-"      }\n"
-"   }\n"
-"   \n"
-"   vec3 composite   = sky_colour + sun_colour + star*star_blend;\n"
-"   return composite;\n"
-"}\n"
-"\n"
-"vec3 clearskies_lighting( vec3 normal, float shadow, vec3 halfview )\n"
-"{\n"
-"   float fresnel = 1.0 - abs(dot(normal,halfview));\n"
-"\n"
-"   vec3  reflect_colour = mix( g_daysky_colour.rgb, g_sunset_colour.rgb, \n"
-"                               g_sunset_phase );\n"
-"\n"
-"   vec3  sky_reflection = 0.5 * fresnel * reflect_colour;\n"
-"   vec3  light_sun      = max( CLEARSKIES_LIGHT_DOT_MIN, \n"
-"                               dot(normal,g_sun_dir.xyz)*0.75+0.25\n"
-"                           ) * g_sun_colour.rgb * g_day_phase;\n"
-"\n"
-"   float scaled_shadow = max( shadow, 1.0 - max(g_sun_dir.y,0.0) );\n"
-"   vec3 ambient = mix( g_ambient_colour.rgb, g_sunset_ambient.rgb, \n"
-"                       g_sunset_phase );\n"
-"\n"
-"   return ambient + (light_sun + sky_reflection) * shadow;\n"
-"}\n"
-"\n"
-"#line     44        0 \n"
-"\n"
-"float world_depth_sample( vec3 pos )\n"
-"{\n"
-"   vec2 depth_coord = (pos.xz - g_depth_bounds.xy) * g_depth_bounds.zw; \n"
-"   return texture( g_world_depth, depth_coord ).r;\n"
-"}\n"
-"\n"
-"float world_water_depth( vec3 pos )\n"
-"{\n"
-"   float ref_depth = g_water_plane.y*g_water_plane.w;\n"
-"   return world_depth_sample( pos ) - ref_depth;\n"
-"}\n"
-"\n"
-"float shadow_sample( vec3 co ){\n"
-"   float height_sample = world_depth_sample( co );\n"
-"\n"
-"   float fdelta = height_sample - co.y;\n"
-"   return clamp( fdelta, 0.2, 0.4 )-0.2;\n"
-"}\n"
-"\n"
-"float newlight_compute_sun_shadow( vec3 co, vec3 dir ){\n"
-"   if( g_shadow_samples == 0 ){\n"
-"      return 1.0;\n"
-"   }\n"
-"\n"
-"   float fspread = g_shadow_spread;\n"
-"   float flength = g_shadow_length;\n"
-"\n"
-"   float famt = 0.0;\n"
-"   famt += shadow_sample(co+(dir+vec3(-0.56,0.55, 0.30)*fspread)*flength*0.1);\n"
-"   famt += shadow_sample(co+(dir+vec3( 0.80,0.68, 0.34)*fspread)*flength*0.2);\n"
-"   famt += shadow_sample(co+(dir+vec3( 0.78,0.07,-0.06)*fspread)*flength*0.3);\n"
-"   famt += shadow_sample(co+(dir+vec3(-0.59,0.07,-0.42)*fspread)*flength*0.4);\n"
-"\n"
-"   //famt+=shadow_sample(co+(dir+vec3(-0.790,-0.933,-0.875)*fspread)*flength*0.5);\n"
-"   //famt+=shadow_sample(co+(dir+vec3( 0.807,-0.690, 0.472)*fspread)*flength*0.6);\n"
-"   //famt+=shadow_sample(co+(dir+vec3( 0.522,-0.379, 0.350)*fspread)*flength*0.7);\n"
-"   //famt+=shadow_sample(co+(dir+vec3( 0.483, 0.201, 0.306)*fspread)*flength*0.8);\n"
-"\n"
-"   return 1.0 - famt;\n"
-"}\n"
-"\n"
-"float newlight_specular( vec3 wnormal, vec3 dir, vec3 halfview, float exponent )\n"
-"{\n"
-"   vec3 specdir = reflect( -dir, wnormal );\n"
-"   return pow(max(dot( halfview, specdir ), 0.0), exponent);\n"
-"}\n"
-"\n"
-"vec3 scene_apply_fog( vec3 vfrag, vec3 colour, float fdist ){\n"
-"   float dist = pow(fdist*0.0010,0.78);\n"
-"   return mix( vfrag, colour, min( 1.0, dist ) );\n"
-"}\n"
-"\n"
-"vec3 scene_calculate_light( int light_index, \n"
-"                            vec3 halfview, vec3 co, vec3 normal )\n"
-"{\n"
-"   vec4 light_colour = texelFetch( uLightsArray, light_index+0 );\n"
-"   vec4 light_co     = texelFetch( uLightsArray, light_index+1 );\n"
-"   vec4 light_dir    = texelFetch( uLightsArray, light_index+2 );\n"
-"\n"
-"   vec3 light_delta = light_co.xyz-co;\n"
-"   float dist2 = dot(light_delta,light_delta);\n"
-"\n"
-"   light_delta = normalize( light_delta );\n"
-"\n"
-"   float quadratic = dist2*100.0;\n"
-"   float attenuation  = 1.0/( 1.0 + quadratic );\n"
-"         attenuation *= max( dot( light_delta, normal ), 0.0 );\n"
-"\n"
-"   float falloff = max( 0.0, 1.0-(dist2*light_co.w) );\n"
-"\n"
-"   if( light_dir.w < 0.999999 ){\n"
-"      float spot_theta = max( 0.0, dot( light_delta, -light_dir.xyz ) );\n"
-"      falloff *= max( 0.0, (spot_theta - light_dir.w) / (1.0-light_dir.w) );\n"
-"   }\n"
-"\n"
-"   return light_colour.rgb * attenuation * falloff \n"
-"            * step( g_day_phase, light_colour.w );\n"
-"}\n"
-"\n"
-"vec3 scene_calculate_packed_light_patch( uint packed_index, \n"
-"                                         vec3 halfview, vec3 co, vec3 normal )\n"
-"{\n"
-"   uint light_count = packed_index & 0x3u;\n"
-"\n"
-"   vec3 l = vec3(0.0);\n"
-"\n"
-"   if( light_count >= 1u ){\n"
-"      int index_0 = int( ((packed_index >>  2u) & 0x3ffu) * 3u );\n"
-"      int index_1 = int( ((packed_index >> 12u) & 0x3ffu) * 3u );\n"
-"      int index_2 = int( ((packed_index >> 22u) & 0x3ffu) * 3u );\n"
-"\n"
-"      l += scene_calculate_light( index_0, halfview, co, normal );\n"
-"\n"
-"      if( light_count >= 2u ){\n"
-"         l += scene_calculate_light( index_1, halfview, co, normal );\n"
-"\n"
-"         if( light_count >= 3u ){\n"
-"            l += scene_calculate_light( index_2, halfview, co, normal );\n"
-"         }\n"
-"      }\n"
-"   }\n"
-"\n"
-"   return l;\n"
-"}\n"
-"\n"
-"vec3 world_compute_lighting( vec3 diffuse, vec3 normal, vec3 co,\n"
-"                             float light_mask )\n"
-"{\n"
-"   if( g_light_preview == 1 )\n"
-"      diffuse = vec3(0.75);\n"
-"\n"
-"   // Lighting\n"
-"   vec3 halfview = uCamera - co;\n"
-"   float fdist = length(halfview);\n"
-"   halfview /= fdist;\n"
-"\n"
-"   float world_shadow = newlight_compute_sun_shadow( \n"
-"               co, g_sun_dir.xyz * (1.0/(max(g_sun_dir.y,0.0)+0.2)) );\n"
-"\n"
-"   vec3 total_light = clearskies_lighting( \n"
-"                           normal, min( light_mask, world_shadow ), halfview );\n"
-"\n"
-"   vec3 cube_coord = (co - g_cube_min.xyz) * g_cube_inv_range.xyz;\n"
-"        cube_coord = floor( cube_coord );\n"
-"\n"
-"   if( g_debug_indices == 1 )\n"
-"   {\n"
-"      return rand33(cube_coord);\n"
-"   }\n"
-"\n"
-"   if( g_debug_complexity == 1 )\n"
-"   {\n"
-"      ivec3 coord = ivec3( cube_coord );\n"
-"      uvec4 index_sample = texelFetch( uLightsIndex, coord, 0 );\n"
-"\n"
-"      uint light_count = (index_sample.x & 0x3u) + (index_sample.y & 0x3u);\n"
-"      return vec3( float(light_count)*(1.0/6.0), 0.0, 0.5 );\n"
-"   }\n"
-"\n"
-"   // FIXME: this coord should absolutely must be clamped!\n"
-"   \n"
-"   ivec3 coord = ivec3( cube_coord );\n"
-"   uvec4 index_sample = texelFetch( uLightsIndex, coord, 0 );\n"
-"\n"
-"   total_light += \n"
-"      scene_calculate_packed_light_patch( index_sample.x,\n"
-"                                          halfview, co, normal ) \n"
-"                                          * light_mask;\n"
-"   total_light += \n"
-"      scene_calculate_packed_light_patch( index_sample.y,\n"
-"                                          halfview, co, normal )\n"
-"                                          * light_mask;\n"
-"\n"
-"   // Take a section of the sky function to give us a matching fog colour\n"
-"\n"
-"   vec3 fog_colour  = clearskies_ambient( -halfview );\n"
-"   float sun_theta  = dot( -halfview, g_sun_dir.xyz );\n"
-"   float sun_size   = max( 0.0, sun_theta * 0.5 + 0.5 );\n"
-"   float sun_shape  = sun_size * max(g_sun_dir.y,0.0) * 0.5;\n"
-"         \n"
-"   vec3 sun_colour  = mix( vec3(1.0), g_sunset_colour.rgb, g_sunset_phase*0.5 );\n"
-"        sun_colour *= sun_shape;\n"
-"\n"
-"   fog_colour += sun_colour;\n"
-"   return scene_apply_fog( diffuse * total_light, fog_colour, fdist );\n"
-"}\n"
-"\n"
-"#line      9        0 \n"
-"\n"
-"float sdLine( vec3 p, vec3 a, vec3 b )\n"
-"{\n"
-"  vec3 pa = p - a;\n"
-"  vec3 ba = b - a;\n"
-"\n"
-"  float h = clamp( dot(pa,ba)/dot(ba,ba), 0.0, 1.0 );\n"
-"  return length( pa - ba*h );\n"
-"}\n"
-"\n"
-"float compute_board_shadow()\n"
-"{\n"
-"   // player shadow\n"
-"   float dist_to_player = max( 0.0, sdLine( aWorldCo, g_board_0.xyz,\n"
-"                                                      g_board_1.xyz )-0.1 );\n"
-"   float player_shadow = max( 1.0-dist_to_player*2.7, 0.0 );\n"
-"   player_shadow *= player_shadow*player_shadow*player_shadow;\n"
-"\n"
-"   return 1.0 - player_shadow*0.8;\n"
-"}\n"
-"\n"
-"vec3 scene_compute_lighting( vec3 diffuse, vec3 normal, vec3 co )\n"
-"{\n"
-"   return world_compute_lighting( diffuse, normal, co, compute_board_shadow() );\n"
-"}\n"
-"\n"
-"#line      8        0 \n"
-"#line       1        3 \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      9        0 \n"
-"\n"
-"void main()\n"
-"{\n"
-"   compute_motion_vectors();\n"
-"\n"
-"   vec3 vfrag = vec3(0.5,0.5,0.5);\n"
-"   vec4 vsamplemain = texture( uTexMain, aUv );\n"
-"   vec3 qnorm = aNorm.xyz;\n"
-"\n"
-"   vfrag = vsamplemain.rgb;\n"
-"\n"
-"   if( g_light_preview == 1 )\n"
-"   {\n"
-"      vfrag = vec3(0.5);\n"
-"   }\n"
-"\n"
-"   vfrag = scene_compute_lighting( vfrag, qnorm, aWorldCo );\n"
-"   oColour = vec4( vfrag, 1.0 );\n"
-"}\n"
-""},
-};
-
-static GLuint _uniform_scene_standard_uMdl;
-static GLuint _uniform_scene_standard_uPv;
-static GLuint _uniform_scene_standard_uPvmPrev;
-static GLuint _uniform_scene_standard_uTexGarbage;
-static GLuint _uniform_scene_standard_uTexMain;
-static GLuint _uniform_scene_standard_uCamera;
-static GLuint _uniform_scene_standard_uPlane;
-static GLuint _uniform_scene_standard_g_world_depth;
-static GLuint _uniform_scene_standard_uLightsArray;
-static GLuint _uniform_scene_standard_uLightsIndex;
-static void shader_scene_standard_uMdl(m4x3f m){
-   glUniformMatrix4x3fv(_uniform_scene_standard_uMdl,1,GL_FALSE,(float*)m);
+   glUniformMatrix4x3fv(_uniform_scene_standard_uMdl,1,GL_FALSE,(f32*)m);
 }
-static void shader_scene_standard_uPv(m4x4f m){
-   glUniformMatrix4fv(_uniform_scene_standard_uPv,1,GL_FALSE,(float*)m);
+static inline void shader_scene_standard_uPv(m4x4f m)
+{
+   glUniformMatrix4fv(_uniform_scene_standard_uPv,1,GL_FALSE,(f32*)m);
 }
-static void shader_scene_standard_uPvmPrev(m4x4f m){
-   glUniformMatrix4fv(_uniform_scene_standard_uPvmPrev,1,GL_FALSE,(float*)m);
+static inline void shader_scene_standard_uPvmPrev(m4x4f m)
+{
+   glUniformMatrix4fv(_uniform_scene_standard_uPvmPrev,1,GL_FALSE,(f32*)m);
 }
-static void shader_scene_standard_uTexGarbage(int i){
+static inline void shader_scene_standard_uTexGarbage(int i)
+{
    glUniform1i(_uniform_scene_standard_uTexGarbage,i);
 }
-static void shader_scene_standard_uTexMain(int i){
+static inline void shader_scene_standard_uTexMain(int i)
+{
    glUniform1i(_uniform_scene_standard_uTexMain,i);
 }
-static void shader_scene_standard_uCamera(v3f v){
+static inline void shader_scene_standard_uCamera(v3f v)
+{
    glUniform3fv(_uniform_scene_standard_uCamera,1,v);
 }
-static void shader_scene_standard_uPlane(v4f v){
+static inline void shader_scene_standard_uPlane(v4f v)
+{
    glUniform4fv(_uniform_scene_standard_uPlane,1,v);
 }
-static void shader_scene_standard_g_world_depth(int i){
+static inline void shader_scene_standard_g_world_depth(int i)
+{
    glUniform1i(_uniform_scene_standard_g_world_depth,i);
 }
-static void shader_scene_standard_register(void){
-   vg_shader_register( &_shader_scene_standard );
-}
-static void shader_scene_standard_use(void){ glUseProgram(_shader_scene_standard.id); }
-static void shader_scene_standard_link(void){
-   _uniform_scene_standard_uMdl = glGetUniformLocation( _shader_scene_standard.id, "uMdl" );
-   _uniform_scene_standard_uPv = glGetUniformLocation( _shader_scene_standard.id, "uPv" );
-   _uniform_scene_standard_uPvmPrev = glGetUniformLocation( _shader_scene_standard.id, "uPvmPrev" );
-   _uniform_scene_standard_uTexGarbage = glGetUniformLocation( _shader_scene_standard.id, "uTexGarbage" );
-   _uniform_scene_standard_uTexMain = glGetUniformLocation( _shader_scene_standard.id, "uTexMain" );
-   _uniform_scene_standard_uCamera = glGetUniformLocation( _shader_scene_standard.id, "uCamera" );
-   _uniform_scene_standard_uPlane = glGetUniformLocation( _shader_scene_standard.id, "uPlane" );
-   _uniform_scene_standard_g_world_depth = glGetUniformLocation( _shader_scene_standard.id, "g_world_depth" );
-   _uniform_scene_standard_uLightsArray = glGetUniformLocation( _shader_scene_standard.id, "uLightsArray" );
-   _uniform_scene_standard_uLightsIndex = glGetUniformLocation( _shader_scene_standard.id, "uLightsIndex" );
+static inline void shader_scene_standard_use(void);
+static inline void shader_scene_standard_use(void)
+{
+   glUseProgram(_shader_scene_standard.id);
 }
-#endif /* SHADER_scene_standard_H */
index 0d6911c27eee702148a9bb9828cec7c4dbbb8b97..73fc7a6396b1df61a03766dc4095c6a06ffffd95 100644 (file)
-#ifndef SHADER_scene_standard_alphatest_H
-#define SHADER_scene_standard_alphatest_H
-static void shader_scene_standard_alphatest_link(void);
-static void shader_scene_standard_alphatest_register(void);
-static struct vg_shader _shader_scene_standard_alphatest = {
-   .name = "scene_standard_alphatest",
-   .link = shader_scene_standard_alphatest_link,
-   .vs = 
+#pragma once
+#include "vg/vg_engine.h"
+extern struct vg_shader _shader_scene_standard_alphatest;
+extern GLuint _uniform_scene_standard_alphatest_uMdl;
+extern GLuint _uniform_scene_standard_alphatest_uPv;
+extern GLuint _uniform_scene_standard_alphatest_uPvmPrev;
+extern GLuint _uniform_scene_standard_alphatest_uTexGarbage;
+extern GLuint _uniform_scene_standard_alphatest_uTexMain;
+extern GLuint _uniform_scene_standard_alphatest_uCamera;
+extern GLuint _uniform_scene_standard_alphatest_uPlane;
+extern GLuint _uniform_scene_standard_alphatest_g_world_depth;
+extern GLuint _uniform_scene_standard_alphatest_uLightsArray;
+extern GLuint _uniform_scene_standard_alphatest_uLightsIndex;
+static inline void shader_scene_standard_alphatest_uMdl(m4x3f m)
 {
-.orig_file = "shaders/scene.vs",
-.static_src = 
-"layout (location=0) in vec3  a_co;\n"
-"layout (location=1) in vec4  a_norm;\n"
-"layout (location=2) in vec2  a_uv;\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      6        0 \n"
-"\n"
-"uniform mat4x3 uMdl;\n"
-"uniform mat4   uPv;\n"
-"uniform mat4   uPvmPrev;\n"
-"\n"
-"out vec2 aUv;\n"
-"out vec4 aNorm;\n"
-"out vec3 aCo;\n"
-"out vec3 aWorldCo;\n"
-"\n"
-"void main()\n"
-"{\n"
-"   vec3 world_pos0 = uMdl     * vec4( a_co, 1.0 );\n"
-"   vec4 vproj0     = uPv      * vec4( world_pos0, 1.0 );\n"
-"   vec4 vproj1     = uPvmPrev * vec4( a_co, 1.0 );\n"
-"\n"
-"   vs_motion_out( vproj0, vproj1 );\n"
-"\n"
-"   gl_Position = vproj0;\n"
-"\n"
-"   aUv = a_uv;\n"
-"   aNorm = vec4( mat3(uMdl) * a_norm.xyz, a_norm.w );\n"
-"   aCo = a_co;\n"
-"   aWorldCo = world_pos0;\n"
-"}\n"
-""},
-   .fs = 
-{
-.orig_file = "shaders/scene_standard_alphatest.fs",
-.static_src = 
-"uniform sampler2D uTexGarbage;\n"
-"uniform sampler2D uTexMain;\n"
-"uniform vec3 uCamera;\n"
-"uniform vec4 uPlane;\n"
-"\n"
-"#line       1        1 \n"
-"// :D\n"
-"const float CLEARSKIES_LIGHT_DOT_MIN = 0.0;\n"
-"\n"
-"#line      7        0 \n"
-"#line       1        2 \n"
-"// :D\n"
-"\n"
-"in vec2 aUv;\n"
-"in vec4 aNorm;\n"
-"in vec3 aCo;\n"
-"in vec3 aWorldCo;\n"
-"\n"
-"#line       1        1 \n"
-"layout (location = 0) out vec4 oColour;\n"
-"\n"
-"// OpenGL wiki: Recommends do not use vec3 because of drivers. hence the v4s...\n"
-"layout (std140) uniform ub_world_lighting\n"
-"{\n"
-"   vec4 g_cube_min;\n"
-"   vec4 g_cube_inv_range;\n"
-"\n"
-"   vec4 g_water_plane;\n"
-"   vec4 g_depth_bounds;\n"
-"\n"
-"   vec4 g_daysky_colour;\n"
-"   vec4 g_nightsky_colour;\n"
-"   vec4 g_sunset_colour;\n"
-"   vec4 g_ambient_colour;\n"
-"   vec4 g_sunset_ambient;\n"
-"   vec4 g_sun_colour;\n"
-"   vec4 g_sun_dir;\n"
-"   vec4 g_board_0;\n"
-"   vec4 g_board_1;\n"
-"\n"
-"   float g_water_fog;\n"
-"   float g_time;\n"
-"   float g_realtime;\n"
-"   float g_shadow_length;\n"
-"   float g_shadow_spread;\n"
-"\n"
-"   float g_time_of_day;\n"
-"   float g_day_phase;\n"
-"   float g_sunset_phase;\n"
-"\n"
-"   int g_light_preview;\n"
-"   int g_shadow_samples;\n"
-"\n"
-"   int g_debug_indices;\n"
-"   int g_debug_complexity;\n"
-"};\n"
-"\n"
-"uniform sampler2D g_world_depth;\n"
-"uniform samplerBuffer uLightsArray;\n"
-"uniform usampler3D uLightsIndex;\n"
-"\n"
-"#line       1        1 \n"
-"//const vec3  DAYSKY_COLOUR   = vec3( 0.37, 0.54, 0.97 );\n"
-"//const vec3  NIGHTSKY_COLOUR = vec3( 0.03, 0.05, 0.20 );\n"
-"//const vec3  SUNSET_COLOUR   = vec3( 1.00, 0.32, 0.01 );\n"
-"//const vec3  AMBIENT_COLOUR  = vec3( 0.13, 0.17, 0.35 );\n"
-"//const vec3  SUNSET_AMBIENT  = vec3( 0.25, 0.17, 0.51 );\n"
-"//const vec3  SUN_COLOUR      = vec3( 1.10, 0.89, 0.35 );\n"
-"\n"
-"const float SUN_ANGLE       = 0.0001;\n"
-"const float PI              = 3.14159265358979323846264;\n"
-"\n"
-"//struct world_info\n"
-"//{\n"
-"//   float time,\n"
-"//         time_of_day,\n"
-"//         day_phase,\n"
-"//         sunset_phase;\n"
-"//   \n"
-"//   vec3 sun_dir;\n"
-"//};\n"
-"\n"
-"vec3 rand33(vec3 p3)\n"
-"{\n"
-"      p3 = fract(p3 * vec3(.1031, .1030, .0973));\n"
-"   p3 += dot(p3, p3.yxz+33.33);\n"
-"   return fract((p3.xxy + p3.yxx)*p3.zyx);\n"
-"}\n"
-"\n"
-"float stars( vec3 rd, float rr, float size ){\n"
-"   vec3 co = rd * rr;\n"
-"\n"
-"   float a = atan(co.y, length(co.xz)) + 4.0 * PI;\n"
-"\n"
-"   float spaces = 1.0 / rr;\n"
-"   size = (rr * 0.0015) * fwidth(a) * 1000.0 * size;\n"
-"   a -= mod(a, spaces) - spaces * 0.5;\n"
-"\n"
-"   float count = floor(sqrt(pow(rr, 2.0) * (1.0 - pow(sin(a), 2.0))) * 3.0);\n"
-"   \n"
-"   float plane = atan(co.z, co.x) + 4.0 * PI;\n"
-"   plane = plane - mod(plane, PI / count);\n"
-"\n"
-"   vec2 delta = rand33(vec3(plane, a, 0.0)).xy;\n"
-"\n"
-"   float level = sin(a + spaces * (delta.y - 0.5) * (1.0 - size)) * rr;\n"
-"   float ydist = sqrt(rr * rr - level * level);\n"
-"   float angle = plane + (PI * (delta.x * (1.0-size) + size * 0.5) / count);\n"
-"   vec3 center = vec3(cos(angle) * ydist, level, sin(angle) * ydist);\n"
-"   float star = smoothstep(size, 0.0, distance(center, co));\n"
-"   return star;\n"
-"}\n"
-"\n"
-"float luminance( vec3 v )\n"
-"{\n"
-"   return dot( v, vec3(0.2126, 0.7152, 0.0722) );\n"
-"}\n"
-"\n"
-"vec3 clearskies_ambient( vec3 dir )\n"
-"{\n"
-"   float sun_azimuth  = g_sunset_phase * (dot( dir.xz, g_sun_dir.xz )*0.4+0.6);\n"
-"   float sky_gradient = dir.y;\n"
-"   \n"
-"   /* Blend phase colours */\n"
-"   vec3 ambient  = g_daysky_colour.rgb   * (g_day_phase-g_sunset_phase*0.1);\n"
-"        ambient += g_sunset_colour.rgb   * (1.0-dir.y*0.5)*sun_azimuth;\n"
-"        ambient += g_nightsky_colour.rgb * (1.0-g_day_phase);\n"
-"   \n"
-"   /* Add gradient */\n"
-"        ambient -= sky_gradient * luminance(ambient);\n"
-"        \n"
-"   return ambient;\n"
-"}\n"
-"\n"
-"vec3 clearskies_sky( vec3 ray_dir )\n"
-"{\n"
-"   ray_dir.y = abs( ray_dir.y );\n"
-"   vec3 sky_colour  = clearskies_ambient( ray_dir );\n"
-"   \n"
-"   /* Sun */\n"
-"   float sun_theta  = dot( ray_dir, g_sun_dir.xyz );\n"
-"   float sun_size   = max( 0.0, sun_theta * 0.5 + 0.5 + SUN_ANGLE );\n"
-"   float sun_shape  = pow( sun_size, 2000.0 );\n"
-"         sun_shape += sun_size * max(g_sun_dir.y,0.0) * 0.5;\n"
-"         \n"
-"   vec3 sun_colour  = mix( vec3(1.0), g_sunset_colour.rgb, g_sunset_phase*0.5 );\n"
-"        sun_colour *= sun_shape;\n"
-"\n"
-"   \n"
-"   float star = 0.0;\n"
-"   float star_blend = 10.0*max(0.0,(1.0-g_day_phase*2.0));\n"
-"\n"
-"   if( star_blend > 0.001 ){\n"
-"      for( float j = 1.0; j <= 4.1; j += 1.0 ){\n"
-"         float m = mix(0.6, 0.9, smoothstep(1.0, 2.0, j));\n"
-"         star += stars( ray_dir, 1.94 * pow( 1.64, j ), m ) * (1.0/pow(4.0, j));\n"
-"      }\n"
-"   }\n"
-"   \n"
-"   vec3 composite   = sky_colour + sun_colour + star*star_blend;\n"
-"   return composite;\n"
-"}\n"
-"\n"
-"vec3 clearskies_lighting( vec3 normal, float shadow, vec3 halfview )\n"
-"{\n"
-"   float fresnel = 1.0 - abs(dot(normal,halfview));\n"
-"\n"
-"   vec3  reflect_colour = mix( g_daysky_colour.rgb, g_sunset_colour.rgb, \n"
-"                               g_sunset_phase );\n"
-"\n"
-"   vec3  sky_reflection = 0.5 * fresnel * reflect_colour;\n"
-"   vec3  light_sun      = max( CLEARSKIES_LIGHT_DOT_MIN, \n"
-"                               dot(normal,g_sun_dir.xyz)*0.75+0.25\n"
-"                           ) * g_sun_colour.rgb * g_day_phase;\n"
-"\n"
-"   float scaled_shadow = max( shadow, 1.0 - max(g_sun_dir.y,0.0) );\n"
-"   vec3 ambient = mix( g_ambient_colour.rgb, g_sunset_ambient.rgb, \n"
-"                       g_sunset_phase );\n"
-"\n"
-"   return ambient + (light_sun + sky_reflection) * shadow;\n"
-"}\n"
-"\n"
-"#line     44        0 \n"
-"\n"
-"float world_depth_sample( vec3 pos )\n"
-"{\n"
-"   vec2 depth_coord = (pos.xz - g_depth_bounds.xy) * g_depth_bounds.zw; \n"
-"   return texture( g_world_depth, depth_coord ).r;\n"
-"}\n"
-"\n"
-"float world_water_depth( vec3 pos )\n"
-"{\n"
-"   float ref_depth = g_water_plane.y*g_water_plane.w;\n"
-"   return world_depth_sample( pos ) - ref_depth;\n"
-"}\n"
-"\n"
-"float shadow_sample( vec3 co ){\n"
-"   float height_sample = world_depth_sample( co );\n"
-"\n"
-"   float fdelta = height_sample - co.y;\n"
-"   return clamp( fdelta, 0.2, 0.4 )-0.2;\n"
-"}\n"
-"\n"
-"float newlight_compute_sun_shadow( vec3 co, vec3 dir ){\n"
-"   if( g_shadow_samples == 0 ){\n"
-"      return 1.0;\n"
-"   }\n"
-"\n"
-"   float fspread = g_shadow_spread;\n"
-"   float flength = g_shadow_length;\n"
-"\n"
-"   float famt = 0.0;\n"
-"   famt += shadow_sample(co+(dir+vec3(-0.56,0.55, 0.30)*fspread)*flength*0.1);\n"
-"   famt += shadow_sample(co+(dir+vec3( 0.80,0.68, 0.34)*fspread)*flength*0.2);\n"
-"   famt += shadow_sample(co+(dir+vec3( 0.78,0.07,-0.06)*fspread)*flength*0.3);\n"
-"   famt += shadow_sample(co+(dir+vec3(-0.59,0.07,-0.42)*fspread)*flength*0.4);\n"
-"\n"
-"   //famt+=shadow_sample(co+(dir+vec3(-0.790,-0.933,-0.875)*fspread)*flength*0.5);\n"
-"   //famt+=shadow_sample(co+(dir+vec3( 0.807,-0.690, 0.472)*fspread)*flength*0.6);\n"
-"   //famt+=shadow_sample(co+(dir+vec3( 0.522,-0.379, 0.350)*fspread)*flength*0.7);\n"
-"   //famt+=shadow_sample(co+(dir+vec3( 0.483, 0.201, 0.306)*fspread)*flength*0.8);\n"
-"\n"
-"   return 1.0 - famt;\n"
-"}\n"
-"\n"
-"float newlight_specular( vec3 wnormal, vec3 dir, vec3 halfview, float exponent )\n"
-"{\n"
-"   vec3 specdir = reflect( -dir, wnormal );\n"
-"   return pow(max(dot( halfview, specdir ), 0.0), exponent);\n"
-"}\n"
-"\n"
-"vec3 scene_apply_fog( vec3 vfrag, vec3 colour, float fdist ){\n"
-"   float dist = pow(fdist*0.0010,0.78);\n"
-"   return mix( vfrag, colour, min( 1.0, dist ) );\n"
-"}\n"
-"\n"
-"vec3 scene_calculate_light( int light_index, \n"
-"                            vec3 halfview, vec3 co, vec3 normal )\n"
-"{\n"
-"   vec4 light_colour = texelFetch( uLightsArray, light_index+0 );\n"
-"   vec4 light_co     = texelFetch( uLightsArray, light_index+1 );\n"
-"   vec4 light_dir    = texelFetch( uLightsArray, light_index+2 );\n"
-"\n"
-"   vec3 light_delta = light_co.xyz-co;\n"
-"   float dist2 = dot(light_delta,light_delta);\n"
-"\n"
-"   light_delta = normalize( light_delta );\n"
-"\n"
-"   float quadratic = dist2*100.0;\n"
-"   float attenuation  = 1.0/( 1.0 + quadratic );\n"
-"         attenuation *= max( dot( light_delta, normal ), 0.0 );\n"
-"\n"
-"   float falloff = max( 0.0, 1.0-(dist2*light_co.w) );\n"
-"\n"
-"   if( light_dir.w < 0.999999 ){\n"
-"      float spot_theta = max( 0.0, dot( light_delta, -light_dir.xyz ) );\n"
-"      falloff *= max( 0.0, (spot_theta - light_dir.w) / (1.0-light_dir.w) );\n"
-"   }\n"
-"\n"
-"   return light_colour.rgb * attenuation * falloff \n"
-"            * step( g_day_phase, light_colour.w );\n"
-"}\n"
-"\n"
-"vec3 scene_calculate_packed_light_patch( uint packed_index, \n"
-"                                         vec3 halfview, vec3 co, vec3 normal )\n"
-"{\n"
-"   uint light_count = packed_index & 0x3u;\n"
-"\n"
-"   vec3 l = vec3(0.0);\n"
-"\n"
-"   if( light_count >= 1u ){\n"
-"      int index_0 = int( ((packed_index >>  2u) & 0x3ffu) * 3u );\n"
-"      int index_1 = int( ((packed_index >> 12u) & 0x3ffu) * 3u );\n"
-"      int index_2 = int( ((packed_index >> 22u) & 0x3ffu) * 3u );\n"
-"\n"
-"      l += scene_calculate_light( index_0, halfview, co, normal );\n"
-"\n"
-"      if( light_count >= 2u ){\n"
-"         l += scene_calculate_light( index_1, halfview, co, normal );\n"
-"\n"
-"         if( light_count >= 3u ){\n"
-"            l += scene_calculate_light( index_2, halfview, co, normal );\n"
-"         }\n"
-"      }\n"
-"   }\n"
-"\n"
-"   return l;\n"
-"}\n"
-"\n"
-"vec3 world_compute_lighting( vec3 diffuse, vec3 normal, vec3 co,\n"
-"                             float light_mask )\n"
-"{\n"
-"   if( g_light_preview == 1 )\n"
-"      diffuse = vec3(0.75);\n"
-"\n"
-"   // Lighting\n"
-"   vec3 halfview = uCamera - co;\n"
-"   float fdist = length(halfview);\n"
-"   halfview /= fdist;\n"
-"\n"
-"   float world_shadow = newlight_compute_sun_shadow( \n"
-"               co, g_sun_dir.xyz * (1.0/(max(g_sun_dir.y,0.0)+0.2)) );\n"
-"\n"
-"   vec3 total_light = clearskies_lighting( \n"
-"                           normal, min( light_mask, world_shadow ), halfview );\n"
-"\n"
-"   vec3 cube_coord = (co - g_cube_min.xyz) * g_cube_inv_range.xyz;\n"
-"        cube_coord = floor( cube_coord );\n"
-"\n"
-"   if( g_debug_indices == 1 )\n"
-"   {\n"
-"      return rand33(cube_coord);\n"
-"   }\n"
-"\n"
-"   if( g_debug_complexity == 1 )\n"
-"   {\n"
-"      ivec3 coord = ivec3( cube_coord );\n"
-"      uvec4 index_sample = texelFetch( uLightsIndex, coord, 0 );\n"
-"\n"
-"      uint light_count = (index_sample.x & 0x3u) + (index_sample.y & 0x3u);\n"
-"      return vec3( float(light_count)*(1.0/6.0), 0.0, 0.5 );\n"
-"   }\n"
-"\n"
-"   // FIXME: this coord should absolutely must be clamped!\n"
-"   \n"
-"   ivec3 coord = ivec3( cube_coord );\n"
-"   uvec4 index_sample = texelFetch( uLightsIndex, coord, 0 );\n"
-"\n"
-"   total_light += \n"
-"      scene_calculate_packed_light_patch( index_sample.x,\n"
-"                                          halfview, co, normal ) \n"
-"                                          * light_mask;\n"
-"   total_light += \n"
-"      scene_calculate_packed_light_patch( index_sample.y,\n"
-"                                          halfview, co, normal )\n"
-"                                          * light_mask;\n"
-"\n"
-"   // Take a section of the sky function to give us a matching fog colour\n"
-"\n"
-"   vec3 fog_colour  = clearskies_ambient( -halfview );\n"
-"   float sun_theta  = dot( -halfview, g_sun_dir.xyz );\n"
-"   float sun_size   = max( 0.0, sun_theta * 0.5 + 0.5 );\n"
-"   float sun_shape  = sun_size * max(g_sun_dir.y,0.0) * 0.5;\n"
-"         \n"
-"   vec3 sun_colour  = mix( vec3(1.0), g_sunset_colour.rgb, g_sunset_phase*0.5 );\n"
-"        sun_colour *= sun_shape;\n"
-"\n"
-"   fog_colour += sun_colour;\n"
-"   return scene_apply_fog( diffuse * total_light, fog_colour, fdist );\n"
-"}\n"
-"\n"
-"#line      9        0 \n"
-"\n"
-"float sdLine( vec3 p, vec3 a, vec3 b )\n"
-"{\n"
-"  vec3 pa = p - a;\n"
-"  vec3 ba = b - a;\n"
-"\n"
-"  float h = clamp( dot(pa,ba)/dot(ba,ba), 0.0, 1.0 );\n"
-"  return length( pa - ba*h );\n"
-"}\n"
-"\n"
-"float compute_board_shadow()\n"
-"{\n"
-"   // player shadow\n"
-"   float dist_to_player = max( 0.0, sdLine( aWorldCo, g_board_0.xyz,\n"
-"                                                      g_board_1.xyz )-0.1 );\n"
-"   float player_shadow = max( 1.0-dist_to_player*2.7, 0.0 );\n"
-"   player_shadow *= player_shadow*player_shadow*player_shadow;\n"
-"\n"
-"   return 1.0 - player_shadow*0.8;\n"
-"}\n"
-"\n"
-"vec3 scene_compute_lighting( vec3 diffuse, vec3 normal, vec3 co )\n"
-"{\n"
-"   return world_compute_lighting( diffuse, normal, co, compute_board_shadow() );\n"
-"}\n"
-"\n"
-"#line      8        0 \n"
-"#line       1        3 \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      9        0 \n"
-"\n"
-"void main()\n"
-"{\n"
-"   compute_motion_vectors();\n"
-"\n"
-"   vec3 vfrag = vec3(0.5,0.5,0.5);\n"
-"   vec4 vsamplemain = texture( uTexMain, aUv );\n"
-"   vec3 qnorm = aNorm.xyz;\n"
-"\n"
-"   if( vsamplemain.a < 0.15 )\n"
-"     discard;\n"
-"\n"
-"   vfrag = vsamplemain.rgb;\n"
-"\n"
-"   if( g_light_preview == 1 )\n"
-"   {\n"
-"      vfrag = vec3(0.5);\n"
-"   }\n"
-"\n"
-"   vfrag = scene_compute_lighting( vfrag, qnorm, aWorldCo );\n"
-"   oColour = vec4(vfrag, 1.0);\n"
-"}\n"
-""},
-};
-
-static GLuint _uniform_scene_standard_alphatest_uMdl;
-static GLuint _uniform_scene_standard_alphatest_uPv;
-static GLuint _uniform_scene_standard_alphatest_uPvmPrev;
-static GLuint _uniform_scene_standard_alphatest_uTexGarbage;
-static GLuint _uniform_scene_standard_alphatest_uTexMain;
-static GLuint _uniform_scene_standard_alphatest_uCamera;
-static GLuint _uniform_scene_standard_alphatest_uPlane;
-static GLuint _uniform_scene_standard_alphatest_g_world_depth;
-static GLuint _uniform_scene_standard_alphatest_uLightsArray;
-static GLuint _uniform_scene_standard_alphatest_uLightsIndex;
-static void shader_scene_standard_alphatest_uMdl(m4x3f m){
-   glUniformMatrix4x3fv(_uniform_scene_standard_alphatest_uMdl,1,GL_FALSE,(float*)m);
+   glUniformMatrix4x3fv(_uniform_scene_standard_alphatest_uMdl,1,GL_FALSE,(f32*)m);
 }
-static void shader_scene_standard_alphatest_uPv(m4x4f m){
-   glUniformMatrix4fv(_uniform_scene_standard_alphatest_uPv,1,GL_FALSE,(float*)m);
+static inline void shader_scene_standard_alphatest_uPv(m4x4f m)
+{
+   glUniformMatrix4fv(_uniform_scene_standard_alphatest_uPv,1,GL_FALSE,(f32*)m);
 }
-static void shader_scene_standard_alphatest_uPvmPrev(m4x4f m){
-   glUniformMatrix4fv(_uniform_scene_standard_alphatest_uPvmPrev,1,GL_FALSE,(float*)m);
+static inline void shader_scene_standard_alphatest_uPvmPrev(m4x4f m)
+{
+   glUniformMatrix4fv(_uniform_scene_standard_alphatest_uPvmPrev,1,GL_FALSE,(f32*)m);
 }
-static void shader_scene_standard_alphatest_uTexGarbage(int i){
+static inline void shader_scene_standard_alphatest_uTexGarbage(int i)
+{
    glUniform1i(_uniform_scene_standard_alphatest_uTexGarbage,i);
 }
-static void shader_scene_standard_alphatest_uTexMain(int i){
+static inline void shader_scene_standard_alphatest_uTexMain(int i)
+{
    glUniform1i(_uniform_scene_standard_alphatest_uTexMain,i);
 }
-static void shader_scene_standard_alphatest_uCamera(v3f v){
+static inline void shader_scene_standard_alphatest_uCamera(v3f v)
+{
    glUniform3fv(_uniform_scene_standard_alphatest_uCamera,1,v);
 }
-static void shader_scene_standard_alphatest_uPlane(v4f v){
+static inline void shader_scene_standard_alphatest_uPlane(v4f v)
+{
    glUniform4fv(_uniform_scene_standard_alphatest_uPlane,1,v);
 }
-static void shader_scene_standard_alphatest_g_world_depth(int i){
+static inline void shader_scene_standard_alphatest_g_world_depth(int i)
+{
    glUniform1i(_uniform_scene_standard_alphatest_g_world_depth,i);
 }
-static void shader_scene_standard_alphatest_register(void){
-   vg_shader_register( &_shader_scene_standard_alphatest );
-}
-static void shader_scene_standard_alphatest_use(void){ glUseProgram(_shader_scene_standard_alphatest.id); }
-static void shader_scene_standard_alphatest_link(void){
-   _uniform_scene_standard_alphatest_uMdl = glGetUniformLocation( _shader_scene_standard_alphatest.id, "uMdl" );
-   _uniform_scene_standard_alphatest_uPv = glGetUniformLocation( _shader_scene_standard_alphatest.id, "uPv" );
-   _uniform_scene_standard_alphatest_uPvmPrev = glGetUniformLocation( _shader_scene_standard_alphatest.id, "uPvmPrev" );
-   _uniform_scene_standard_alphatest_uTexGarbage = glGetUniformLocation( _shader_scene_standard_alphatest.id, "uTexGarbage" );
-   _uniform_scene_standard_alphatest_uTexMain = glGetUniformLocation( _shader_scene_standard_alphatest.id, "uTexMain" );
-   _uniform_scene_standard_alphatest_uCamera = glGetUniformLocation( _shader_scene_standard_alphatest.id, "uCamera" );
-   _uniform_scene_standard_alphatest_uPlane = glGetUniformLocation( _shader_scene_standard_alphatest.id, "uPlane" );
-   _uniform_scene_standard_alphatest_g_world_depth = glGetUniformLocation( _shader_scene_standard_alphatest.id, "g_world_depth" );
-   _uniform_scene_standard_alphatest_uLightsArray = glGetUniformLocation( _shader_scene_standard_alphatest.id, "uLightsArray" );
-   _uniform_scene_standard_alphatest_uLightsIndex = glGetUniformLocation( _shader_scene_standard_alphatest.id, "uLightsIndex" );
+static inline void shader_scene_standard_alphatest_use(void);
+static inline void shader_scene_standard_alphatest_use(void)
+{
+   glUseProgram(_shader_scene_standard_alphatest.id);
 }
-#endif /* SHADER_scene_standard_alphatest_H */
index d7c58efb03593282ef60e70e016d3315c395786f..37b6a3c2b9f77ebdc890946e33c5f6657780daba 100644 (file)
-#ifndef SHADER_scene_terrain_H
-#define SHADER_scene_terrain_H
-static void shader_scene_terrain_link(void);
-static void shader_scene_terrain_register(void);
-static struct vg_shader _shader_scene_terrain = {
-   .name = "scene_terrain",
-   .link = shader_scene_terrain_link,
-   .vs = 
+#pragma once
+#include "vg/vg_engine.h"
+extern struct vg_shader _shader_scene_terrain;
+extern GLuint _uniform_scene_terrain_uMdl;
+extern GLuint _uniform_scene_terrain_uPv;
+extern GLuint _uniform_scene_terrain_uPvmPrev;
+extern GLuint _uniform_scene_terrain_uTexGarbage;
+extern GLuint _uniform_scene_terrain_uTexGradients;
+extern GLuint _uniform_scene_terrain_uCamera;
+extern GLuint _uniform_scene_terrain_uSandColour;
+extern GLuint _uniform_scene_terrain_uBlendOffset;
+extern GLuint _uniform_scene_terrain_g_world_depth;
+extern GLuint _uniform_scene_terrain_uLightsArray;
+extern GLuint _uniform_scene_terrain_uLightsIndex;
+static inline void shader_scene_terrain_uMdl(m4x3f m)
 {
-.orig_file = "shaders/scene.vs",
-.static_src = 
-"layout (location=0) in vec3  a_co;\n"
-"layout (location=1) in vec4  a_norm;\n"
-"layout (location=2) in vec2  a_uv;\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      6        0 \n"
-"\n"
-"uniform mat4x3 uMdl;\n"
-"uniform mat4   uPv;\n"
-"uniform mat4   uPvmPrev;\n"
-"\n"
-"out vec2 aUv;\n"
-"out vec4 aNorm;\n"
-"out vec3 aCo;\n"
-"out vec3 aWorldCo;\n"
-"\n"
-"void main()\n"
-"{\n"
-"   vec3 world_pos0 = uMdl     * vec4( a_co, 1.0 );\n"
-"   vec4 vproj0     = uPv      * vec4( world_pos0, 1.0 );\n"
-"   vec4 vproj1     = uPvmPrev * vec4( a_co, 1.0 );\n"
-"\n"
-"   vs_motion_out( vproj0, vproj1 );\n"
-"\n"
-"   gl_Position = vproj0;\n"
-"\n"
-"   aUv = a_uv;\n"
-"   aNorm = vec4( mat3(uMdl) * a_norm.xyz, a_norm.w );\n"
-"   aCo = a_co;\n"
-"   aWorldCo = world_pos0;\n"
-"}\n"
-""},
-   .fs = 
-{
-.orig_file = "shaders/scene_terrain.fs",
-.static_src = 
-"uniform sampler2D uTexGarbage;\n"
-"uniform sampler2D uTexGradients;\n"
-"uniform vec3 uCamera;\n"
-"uniform vec3 uSandColour;\n"
-"uniform vec2 uBlendOffset;\n"
-"\n"
-"#line       1        1 \n"
-"// :D\n"
-"const float CLEARSKIES_LIGHT_DOT_MIN = 0.0;\n"
-"\n"
-"#line      8        0 \n"
-"#line       1        2 \n"
-"// :D\n"
-"\n"
-"in vec2 aUv;\n"
-"in vec4 aNorm;\n"
-"in vec3 aCo;\n"
-"in vec3 aWorldCo;\n"
-"\n"
-"#line       1        1 \n"
-"layout (location = 0) out vec4 oColour;\n"
-"\n"
-"// OpenGL wiki: Recommends do not use vec3 because of drivers. hence the v4s...\n"
-"layout (std140) uniform ub_world_lighting\n"
-"{\n"
-"   vec4 g_cube_min;\n"
-"   vec4 g_cube_inv_range;\n"
-"\n"
-"   vec4 g_water_plane;\n"
-"   vec4 g_depth_bounds;\n"
-"\n"
-"   vec4 g_daysky_colour;\n"
-"   vec4 g_nightsky_colour;\n"
-"   vec4 g_sunset_colour;\n"
-"   vec4 g_ambient_colour;\n"
-"   vec4 g_sunset_ambient;\n"
-"   vec4 g_sun_colour;\n"
-"   vec4 g_sun_dir;\n"
-"   vec4 g_board_0;\n"
-"   vec4 g_board_1;\n"
-"\n"
-"   float g_water_fog;\n"
-"   float g_time;\n"
-"   float g_realtime;\n"
-"   float g_shadow_length;\n"
-"   float g_shadow_spread;\n"
-"\n"
-"   float g_time_of_day;\n"
-"   float g_day_phase;\n"
-"   float g_sunset_phase;\n"
-"\n"
-"   int g_light_preview;\n"
-"   int g_shadow_samples;\n"
-"\n"
-"   int g_debug_indices;\n"
-"   int g_debug_complexity;\n"
-"};\n"
-"\n"
-"uniform sampler2D g_world_depth;\n"
-"uniform samplerBuffer uLightsArray;\n"
-"uniform usampler3D uLightsIndex;\n"
-"\n"
-"#line       1        1 \n"
-"//const vec3  DAYSKY_COLOUR   = vec3( 0.37, 0.54, 0.97 );\n"
-"//const vec3  NIGHTSKY_COLOUR = vec3( 0.03, 0.05, 0.20 );\n"
-"//const vec3  SUNSET_COLOUR   = vec3( 1.00, 0.32, 0.01 );\n"
-"//const vec3  AMBIENT_COLOUR  = vec3( 0.13, 0.17, 0.35 );\n"
-"//const vec3  SUNSET_AMBIENT  = vec3( 0.25, 0.17, 0.51 );\n"
-"//const vec3  SUN_COLOUR      = vec3( 1.10, 0.89, 0.35 );\n"
-"\n"
-"const float SUN_ANGLE       = 0.0001;\n"
-"const float PI              = 3.14159265358979323846264;\n"
-"\n"
-"//struct world_info\n"
-"//{\n"
-"//   float time,\n"
-"//         time_of_day,\n"
-"//         day_phase,\n"
-"//         sunset_phase;\n"
-"//   \n"
-"//   vec3 sun_dir;\n"
-"//};\n"
-"\n"
-"vec3 rand33(vec3 p3)\n"
-"{\n"
-"      p3 = fract(p3 * vec3(.1031, .1030, .0973));\n"
-"   p3 += dot(p3, p3.yxz+33.33);\n"
-"   return fract((p3.xxy + p3.yxx)*p3.zyx);\n"
-"}\n"
-"\n"
-"float stars( vec3 rd, float rr, float size ){\n"
-"   vec3 co = rd * rr;\n"
-"\n"
-"   float a = atan(co.y, length(co.xz)) + 4.0 * PI;\n"
-"\n"
-"   float spaces = 1.0 / rr;\n"
-"   size = (rr * 0.0015) * fwidth(a) * 1000.0 * size;\n"
-"   a -= mod(a, spaces) - spaces * 0.5;\n"
-"\n"
-"   float count = floor(sqrt(pow(rr, 2.0) * (1.0 - pow(sin(a), 2.0))) * 3.0);\n"
-"   \n"
-"   float plane = atan(co.z, co.x) + 4.0 * PI;\n"
-"   plane = plane - mod(plane, PI / count);\n"
-"\n"
-"   vec2 delta = rand33(vec3(plane, a, 0.0)).xy;\n"
-"\n"
-"   float level = sin(a + spaces * (delta.y - 0.5) * (1.0 - size)) * rr;\n"
-"   float ydist = sqrt(rr * rr - level * level);\n"
-"   float angle = plane + (PI * (delta.x * (1.0-size) + size * 0.5) / count);\n"
-"   vec3 center = vec3(cos(angle) * ydist, level, sin(angle) * ydist);\n"
-"   float star = smoothstep(size, 0.0, distance(center, co));\n"
-"   return star;\n"
-"}\n"
-"\n"
-"float luminance( vec3 v )\n"
-"{\n"
-"   return dot( v, vec3(0.2126, 0.7152, 0.0722) );\n"
-"}\n"
-"\n"
-"vec3 clearskies_ambient( vec3 dir )\n"
-"{\n"
-"   float sun_azimuth  = g_sunset_phase * (dot( dir.xz, g_sun_dir.xz )*0.4+0.6);\n"
-"   float sky_gradient = dir.y;\n"
-"   \n"
-"   /* Blend phase colours */\n"
-"   vec3 ambient  = g_daysky_colour.rgb   * (g_day_phase-g_sunset_phase*0.1);\n"
-"        ambient += g_sunset_colour.rgb   * (1.0-dir.y*0.5)*sun_azimuth;\n"
-"        ambient += g_nightsky_colour.rgb * (1.0-g_day_phase);\n"
-"   \n"
-"   /* Add gradient */\n"
-"        ambient -= sky_gradient * luminance(ambient);\n"
-"        \n"
-"   return ambient;\n"
-"}\n"
-"\n"
-"vec3 clearskies_sky( vec3 ray_dir )\n"
-"{\n"
-"   ray_dir.y = abs( ray_dir.y );\n"
-"   vec3 sky_colour  = clearskies_ambient( ray_dir );\n"
-"   \n"
-"   /* Sun */\n"
-"   float sun_theta  = dot( ray_dir, g_sun_dir.xyz );\n"
-"   float sun_size   = max( 0.0, sun_theta * 0.5 + 0.5 + SUN_ANGLE );\n"
-"   float sun_shape  = pow( sun_size, 2000.0 );\n"
-"         sun_shape += sun_size * max(g_sun_dir.y,0.0) * 0.5;\n"
-"         \n"
-"   vec3 sun_colour  = mix( vec3(1.0), g_sunset_colour.rgb, g_sunset_phase*0.5 );\n"
-"        sun_colour *= sun_shape;\n"
-"\n"
-"   \n"
-"   float star = 0.0;\n"
-"   float star_blend = 10.0*max(0.0,(1.0-g_day_phase*2.0));\n"
-"\n"
-"   if( star_blend > 0.001 ){\n"
-"      for( float j = 1.0; j <= 4.1; j += 1.0 ){\n"
-"         float m = mix(0.6, 0.9, smoothstep(1.0, 2.0, j));\n"
-"         star += stars( ray_dir, 1.94 * pow( 1.64, j ), m ) * (1.0/pow(4.0, j));\n"
-"      }\n"
-"   }\n"
-"   \n"
-"   vec3 composite   = sky_colour + sun_colour + star*star_blend;\n"
-"   return composite;\n"
-"}\n"
-"\n"
-"vec3 clearskies_lighting( vec3 normal, float shadow, vec3 halfview )\n"
-"{\n"
-"   float fresnel = 1.0 - abs(dot(normal,halfview));\n"
-"\n"
-"   vec3  reflect_colour = mix( g_daysky_colour.rgb, g_sunset_colour.rgb, \n"
-"                               g_sunset_phase );\n"
-"\n"
-"   vec3  sky_reflection = 0.5 * fresnel * reflect_colour;\n"
-"   vec3  light_sun      = max( CLEARSKIES_LIGHT_DOT_MIN, \n"
-"                               dot(normal,g_sun_dir.xyz)*0.75+0.25\n"
-"                           ) * g_sun_colour.rgb * g_day_phase;\n"
-"\n"
-"   float scaled_shadow = max( shadow, 1.0 - max(g_sun_dir.y,0.0) );\n"
-"   vec3 ambient = mix( g_ambient_colour.rgb, g_sunset_ambient.rgb, \n"
-"                       g_sunset_phase );\n"
-"\n"
-"   return ambient + (light_sun + sky_reflection) * shadow;\n"
-"}\n"
-"\n"
-"#line     44        0 \n"
-"\n"
-"float world_depth_sample( vec3 pos )\n"
-"{\n"
-"   vec2 depth_coord = (pos.xz - g_depth_bounds.xy) * g_depth_bounds.zw; \n"
-"   return texture( g_world_depth, depth_coord ).r;\n"
-"}\n"
-"\n"
-"float world_water_depth( vec3 pos )\n"
-"{\n"
-"   float ref_depth = g_water_plane.y*g_water_plane.w;\n"
-"   return world_depth_sample( pos ) - ref_depth;\n"
-"}\n"
-"\n"
-"float shadow_sample( vec3 co ){\n"
-"   float height_sample = world_depth_sample( co );\n"
-"\n"
-"   float fdelta = height_sample - co.y;\n"
-"   return clamp( fdelta, 0.2, 0.4 )-0.2;\n"
-"}\n"
-"\n"
-"float newlight_compute_sun_shadow( vec3 co, vec3 dir ){\n"
-"   if( g_shadow_samples == 0 ){\n"
-"      return 1.0;\n"
-"   }\n"
-"\n"
-"   float fspread = g_shadow_spread;\n"
-"   float flength = g_shadow_length;\n"
-"\n"
-"   float famt = 0.0;\n"
-"   famt += shadow_sample(co+(dir+vec3(-0.56,0.55, 0.30)*fspread)*flength*0.1);\n"
-"   famt += shadow_sample(co+(dir+vec3( 0.80,0.68, 0.34)*fspread)*flength*0.2);\n"
-"   famt += shadow_sample(co+(dir+vec3( 0.78,0.07,-0.06)*fspread)*flength*0.3);\n"
-"   famt += shadow_sample(co+(dir+vec3(-0.59,0.07,-0.42)*fspread)*flength*0.4);\n"
-"\n"
-"   //famt+=shadow_sample(co+(dir+vec3(-0.790,-0.933,-0.875)*fspread)*flength*0.5);\n"
-"   //famt+=shadow_sample(co+(dir+vec3( 0.807,-0.690, 0.472)*fspread)*flength*0.6);\n"
-"   //famt+=shadow_sample(co+(dir+vec3( 0.522,-0.379, 0.350)*fspread)*flength*0.7);\n"
-"   //famt+=shadow_sample(co+(dir+vec3( 0.483, 0.201, 0.306)*fspread)*flength*0.8);\n"
-"\n"
-"   return 1.0 - famt;\n"
-"}\n"
-"\n"
-"float newlight_specular( vec3 wnormal, vec3 dir, vec3 halfview, float exponent )\n"
-"{\n"
-"   vec3 specdir = reflect( -dir, wnormal );\n"
-"   return pow(max(dot( halfview, specdir ), 0.0), exponent);\n"
-"}\n"
-"\n"
-"vec3 scene_apply_fog( vec3 vfrag, vec3 colour, float fdist ){\n"
-"   float dist = pow(fdist*0.0010,0.78);\n"
-"   return mix( vfrag, colour, min( 1.0, dist ) );\n"
-"}\n"
-"\n"
-"vec3 scene_calculate_light( int light_index, \n"
-"                            vec3 halfview, vec3 co, vec3 normal )\n"
-"{\n"
-"   vec4 light_colour = texelFetch( uLightsArray, light_index+0 );\n"
-"   vec4 light_co     = texelFetch( uLightsArray, light_index+1 );\n"
-"   vec4 light_dir    = texelFetch( uLightsArray, light_index+2 );\n"
-"\n"
-"   vec3 light_delta = light_co.xyz-co;\n"
-"   float dist2 = dot(light_delta,light_delta);\n"
-"\n"
-"   light_delta = normalize( light_delta );\n"
-"\n"
-"   float quadratic = dist2*100.0;\n"
-"   float attenuation  = 1.0/( 1.0 + quadratic );\n"
-"         attenuation *= max( dot( light_delta, normal ), 0.0 );\n"
-"\n"
-"   float falloff = max( 0.0, 1.0-(dist2*light_co.w) );\n"
-"\n"
-"   if( light_dir.w < 0.999999 ){\n"
-"      float spot_theta = max( 0.0, dot( light_delta, -light_dir.xyz ) );\n"
-"      falloff *= max( 0.0, (spot_theta - light_dir.w) / (1.0-light_dir.w) );\n"
-"   }\n"
-"\n"
-"   return light_colour.rgb * attenuation * falloff \n"
-"            * step( g_day_phase, light_colour.w );\n"
-"}\n"
-"\n"
-"vec3 scene_calculate_packed_light_patch( uint packed_index, \n"
-"                                         vec3 halfview, vec3 co, vec3 normal )\n"
-"{\n"
-"   uint light_count = packed_index & 0x3u;\n"
-"\n"
-"   vec3 l = vec3(0.0);\n"
-"\n"
-"   if( light_count >= 1u ){\n"
-"      int index_0 = int( ((packed_index >>  2u) & 0x3ffu) * 3u );\n"
-"      int index_1 = int( ((packed_index >> 12u) & 0x3ffu) * 3u );\n"
-"      int index_2 = int( ((packed_index >> 22u) & 0x3ffu) * 3u );\n"
-"\n"
-"      l += scene_calculate_light( index_0, halfview, co, normal );\n"
-"\n"
-"      if( light_count >= 2u ){\n"
-"         l += scene_calculate_light( index_1, halfview, co, normal );\n"
-"\n"
-"         if( light_count >= 3u ){\n"
-"            l += scene_calculate_light( index_2, halfview, co, normal );\n"
-"         }\n"
-"      }\n"
-"   }\n"
-"\n"
-"   return l;\n"
-"}\n"
-"\n"
-"vec3 world_compute_lighting( vec3 diffuse, vec3 normal, vec3 co,\n"
-"                             float light_mask )\n"
-"{\n"
-"   if( g_light_preview == 1 )\n"
-"      diffuse = vec3(0.75);\n"
-"\n"
-"   // Lighting\n"
-"   vec3 halfview = uCamera - co;\n"
-"   float fdist = length(halfview);\n"
-"   halfview /= fdist;\n"
-"\n"
-"   float world_shadow = newlight_compute_sun_shadow( \n"
-"               co, g_sun_dir.xyz * (1.0/(max(g_sun_dir.y,0.0)+0.2)) );\n"
-"\n"
-"   vec3 total_light = clearskies_lighting( \n"
-"                           normal, min( light_mask, world_shadow ), halfview );\n"
-"\n"
-"   vec3 cube_coord = (co - g_cube_min.xyz) * g_cube_inv_range.xyz;\n"
-"        cube_coord = floor( cube_coord );\n"
-"\n"
-"   if( g_debug_indices == 1 )\n"
-"   {\n"
-"      return rand33(cube_coord);\n"
-"   }\n"
-"\n"
-"   if( g_debug_complexity == 1 )\n"
-"   {\n"
-"      ivec3 coord = ivec3( cube_coord );\n"
-"      uvec4 index_sample = texelFetch( uLightsIndex, coord, 0 );\n"
-"\n"
-"      uint light_count = (index_sample.x & 0x3u) + (index_sample.y & 0x3u);\n"
-"      return vec3( float(light_count)*(1.0/6.0), 0.0, 0.5 );\n"
-"   }\n"
-"\n"
-"   // FIXME: this coord should absolutely must be clamped!\n"
-"   \n"
-"   ivec3 coord = ivec3( cube_coord );\n"
-"   uvec4 index_sample = texelFetch( uLightsIndex, coord, 0 );\n"
-"\n"
-"   total_light += \n"
-"      scene_calculate_packed_light_patch( index_sample.x,\n"
-"                                          halfview, co, normal ) \n"
-"                                          * light_mask;\n"
-"   total_light += \n"
-"      scene_calculate_packed_light_patch( index_sample.y,\n"
-"                                          halfview, co, normal )\n"
-"                                          * light_mask;\n"
-"\n"
-"   // Take a section of the sky function to give us a matching fog colour\n"
-"\n"
-"   vec3 fog_colour  = clearskies_ambient( -halfview );\n"
-"   float sun_theta  = dot( -halfview, g_sun_dir.xyz );\n"
-"   float sun_size   = max( 0.0, sun_theta * 0.5 + 0.5 );\n"
-"   float sun_shape  = sun_size * max(g_sun_dir.y,0.0) * 0.5;\n"
-"         \n"
-"   vec3 sun_colour  = mix( vec3(1.0), g_sunset_colour.rgb, g_sunset_phase*0.5 );\n"
-"        sun_colour *= sun_shape;\n"
-"\n"
-"   fog_colour += sun_colour;\n"
-"   return scene_apply_fog( diffuse * total_light, fog_colour, fdist );\n"
-"}\n"
-"\n"
-"#line      9        0 \n"
-"\n"
-"float sdLine( vec3 p, vec3 a, vec3 b )\n"
-"{\n"
-"  vec3 pa = p - a;\n"
-"  vec3 ba = b - a;\n"
-"\n"
-"  float h = clamp( dot(pa,ba)/dot(ba,ba), 0.0, 1.0 );\n"
-"  return length( pa - ba*h );\n"
-"}\n"
-"\n"
-"float compute_board_shadow()\n"
-"{\n"
-"   // player shadow\n"
-"   float dist_to_player = max( 0.0, sdLine( aWorldCo, g_board_0.xyz,\n"
-"                                                      g_board_1.xyz )-0.1 );\n"
-"   float player_shadow = max( 1.0-dist_to_player*2.7, 0.0 );\n"
-"   player_shadow *= player_shadow*player_shadow*player_shadow;\n"
-"\n"
-"   return 1.0 - player_shadow*0.8;\n"
-"}\n"
-"\n"
-"vec3 scene_compute_lighting( vec3 diffuse, vec3 normal, vec3 co )\n"
-"{\n"
-"   return world_compute_lighting( diffuse, normal, co, compute_board_shadow() );\n"
-"}\n"
-"\n"
-"#line      9        0 \n"
-"#line       1        3 \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     10        0 \n"
-"\n"
-"void main()\n"
-"{\n"
-"   compute_motion_vectors();\n"
-"\n"
-"   // Colour\n"
-"   // ------\n"
-"   vec3 vfrag = vec3(0.5,0.5,0.5);\n"
-"\n"
-"   // ws modulation\n"
-"   vec4 wgarbage = texture( uTexGarbage, aCo.xz * 0.015 );\n"
-"   \n"
-"   // Creating normal patches\n"
-"   vec3 modnorm = (wgarbage.rgb-0.4) * 1.4;\n"
-"   vec3 qnorm = normalize(floor(aNorm.xyz*4.0+modnorm)*0.25);\n"
-"   qnorm += vec3(0.001,0.0,0.0);\n"
-"\n"
-"   vec2 dir = normalize(qnorm.xz);\n"
-"   vec2 uvdiffuse = aCo.xz * 0.02;\n"
-"   uvdiffuse = mat2(dir.y, dir.x, -dir.x, dir.y) * uvdiffuse;\n"
-"   \n"
-"   // Patch local noise\n"
-"   vec4 rgarbage = texture( uTexGarbage, uvdiffuse );\n"
-"\n"
-"   // Colour blending\n"
-"   float amtgrass = step(qnorm.y,0.6);\n"
-"   float amtsand = min(max((aCo.y - 10.0) * -0.1,0.0)*qnorm.y,1.0);\n"
-"   vec2 uvgradients = aUv + vec2( amtgrass + rgarbage.a*0.8 )*uBlendOffset;\n"
-"   vfrag = texture( uTexGradients, uvgradients ).rgb;\n"
-"   vfrag = mix( vfrag, uSandColour, amtsand );\n"
-"\n"
-"   qnorm = mix( qnorm, aNorm.xyz, amtsand );\n"
-"   \n"
-"   if( g_light_preview == 1 )\n"
-"   {\n"
-"      vfrag = vec3(0.5);\n"
-"   }\n"
-"\n"
-"   vfrag = scene_compute_lighting( vfrag, qnorm, aWorldCo );\n"
-"   oColour = vec4(vfrag, 1.0);\n"
-"}\n"
-""},
-};
-
-static GLuint _uniform_scene_terrain_uMdl;
-static GLuint _uniform_scene_terrain_uPv;
-static GLuint _uniform_scene_terrain_uPvmPrev;
-static GLuint _uniform_scene_terrain_uTexGarbage;
-static GLuint _uniform_scene_terrain_uTexGradients;
-static GLuint _uniform_scene_terrain_uCamera;
-static GLuint _uniform_scene_terrain_uSandColour;
-static GLuint _uniform_scene_terrain_uBlendOffset;
-static GLuint _uniform_scene_terrain_g_world_depth;
-static GLuint _uniform_scene_terrain_uLightsArray;
-static GLuint _uniform_scene_terrain_uLightsIndex;
-static void shader_scene_terrain_uMdl(m4x3f m){
-   glUniformMatrix4x3fv(_uniform_scene_terrain_uMdl,1,GL_FALSE,(float*)m);
+   glUniformMatrix4x3fv(_uniform_scene_terrain_uMdl,1,GL_FALSE,(f32*)m);
 }
-static void shader_scene_terrain_uPv(m4x4f m){
-   glUniformMatrix4fv(_uniform_scene_terrain_uPv,1,GL_FALSE,(float*)m);
+static inline void shader_scene_terrain_uPv(m4x4f m)
+{
+   glUniformMatrix4fv(_uniform_scene_terrain_uPv,1,GL_FALSE,(f32*)m);
 }
-static void shader_scene_terrain_uPvmPrev(m4x4f m){
-   glUniformMatrix4fv(_uniform_scene_terrain_uPvmPrev,1,GL_FALSE,(float*)m);
+static inline void shader_scene_terrain_uPvmPrev(m4x4f m)
+{
+   glUniformMatrix4fv(_uniform_scene_terrain_uPvmPrev,1,GL_FALSE,(f32*)m);
 }
-static void shader_scene_terrain_uTexGarbage(int i){
+static inline void shader_scene_terrain_uTexGarbage(int i)
+{
    glUniform1i(_uniform_scene_terrain_uTexGarbage,i);
 }
-static void shader_scene_terrain_uTexGradients(int i){
+static inline void shader_scene_terrain_uTexGradients(int i)
+{
    glUniform1i(_uniform_scene_terrain_uTexGradients,i);
 }
-static void shader_scene_terrain_uCamera(v3f v){
+static inline void shader_scene_terrain_uCamera(v3f v)
+{
    glUniform3fv(_uniform_scene_terrain_uCamera,1,v);
 }
-static void shader_scene_terrain_uSandColour(v3f v){
+static inline void shader_scene_terrain_uSandColour(v3f v)
+{
    glUniform3fv(_uniform_scene_terrain_uSandColour,1,v);
 }
-static void shader_scene_terrain_uBlendOffset(v2f v){
+static inline void shader_scene_terrain_uBlendOffset(v2f v)
+{
    glUniform2fv(_uniform_scene_terrain_uBlendOffset,1,v);
 }
-static void shader_scene_terrain_g_world_depth(int i){
+static inline void shader_scene_terrain_g_world_depth(int i)
+{
    glUniform1i(_uniform_scene_terrain_g_world_depth,i);
 }
-static void shader_scene_terrain_register(void){
-   vg_shader_register( &_shader_scene_terrain );
-}
-static void shader_scene_terrain_use(void){ glUseProgram(_shader_scene_terrain.id); }
-static void shader_scene_terrain_link(void){
-   _uniform_scene_terrain_uMdl = glGetUniformLocation( _shader_scene_terrain.id, "uMdl" );
-   _uniform_scene_terrain_uPv = glGetUniformLocation( _shader_scene_terrain.id, "uPv" );
-   _uniform_scene_terrain_uPvmPrev = glGetUniformLocation( _shader_scene_terrain.id, "uPvmPrev" );
-   _uniform_scene_terrain_uTexGarbage = glGetUniformLocation( _shader_scene_terrain.id, "uTexGarbage" );
-   _uniform_scene_terrain_uTexGradients = glGetUniformLocation( _shader_scene_terrain.id, "uTexGradients" );
-   _uniform_scene_terrain_uCamera = glGetUniformLocation( _shader_scene_terrain.id, "uCamera" );
-   _uniform_scene_terrain_uSandColour = glGetUniformLocation( _shader_scene_terrain.id, "uSandColour" );
-   _uniform_scene_terrain_uBlendOffset = glGetUniformLocation( _shader_scene_terrain.id, "uBlendOffset" );
-   _uniform_scene_terrain_g_world_depth = glGetUniformLocation( _shader_scene_terrain.id, "g_world_depth" );
-   _uniform_scene_terrain_uLightsArray = glGetUniformLocation( _shader_scene_terrain.id, "uLightsArray" );
-   _uniform_scene_terrain_uLightsIndex = glGetUniformLocation( _shader_scene_terrain.id, "uLightsIndex" );
+static inline void shader_scene_terrain_use(void);
+static inline void shader_scene_terrain_use(void)
+{
+   glUseProgram(_shader_scene_terrain.id);
 }
-#endif /* SHADER_scene_terrain_H */
index 7cc9102706ad5219e5dcf1ddfd378e8218d829cb..376c81be8b8574262e420a40a485628690d758e5 100644 (file)
-#ifndef SHADER_scene_vertex_blend_H
-#define SHADER_scene_vertex_blend_H
-static void shader_scene_vertex_blend_link(void);
-static void shader_scene_vertex_blend_register(void);
-static struct vg_shader _shader_scene_vertex_blend = {
-   .name = "scene_vertex_blend",
-   .link = shader_scene_vertex_blend_link,
-   .vs = 
+#pragma once
+#include "vg/vg_engine.h"
+extern struct vg_shader _shader_scene_vertex_blend;
+extern GLuint _uniform_scene_vertex_blend_uMdl;
+extern GLuint _uniform_scene_vertex_blend_uPv;
+extern GLuint _uniform_scene_vertex_blend_uPvmPrev;
+extern GLuint _uniform_scene_vertex_blend_uTexGarbage;
+extern GLuint _uniform_scene_vertex_blend_uTexGradients;
+extern GLuint _uniform_scene_vertex_blend_uCamera;
+extern GLuint _uniform_scene_vertex_blend_g_world_depth;
+extern GLuint _uniform_scene_vertex_blend_uLightsArray;
+extern GLuint _uniform_scene_vertex_blend_uLightsIndex;
+static inline void shader_scene_vertex_blend_uMdl(m4x3f m)
 {
-.orig_file = "shaders/scene.vs",
-.static_src = 
-"layout (location=0) in vec3  a_co;\n"
-"layout (location=1) in vec4  a_norm;\n"
-"layout (location=2) in vec2  a_uv;\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      6        0 \n"
-"\n"
-"uniform mat4x3 uMdl;\n"
-"uniform mat4   uPv;\n"
-"uniform mat4   uPvmPrev;\n"
-"\n"
-"out vec2 aUv;\n"
-"out vec4 aNorm;\n"
-"out vec3 aCo;\n"
-"out vec3 aWorldCo;\n"
-"\n"
-"void main()\n"
-"{\n"
-"   vec3 world_pos0 = uMdl     * vec4( a_co, 1.0 );\n"
-"   vec4 vproj0     = uPv      * vec4( world_pos0, 1.0 );\n"
-"   vec4 vproj1     = uPvmPrev * vec4( a_co, 1.0 );\n"
-"\n"
-"   vs_motion_out( vproj0, vproj1 );\n"
-"\n"
-"   gl_Position = vproj0;\n"
-"\n"
-"   aUv = a_uv;\n"
-"   aNorm = vec4( mat3(uMdl) * a_norm.xyz, a_norm.w );\n"
-"   aCo = a_co;\n"
-"   aWorldCo = world_pos0;\n"
-"}\n"
-""},
-   .fs = 
-{
-.orig_file = "shaders/scene_vertex_blend.fs",
-.static_src = 
-"uniform sampler2D uTexGarbage;\n"
-"uniform sampler2D uTexGradients;\n"
-"uniform vec3 uCamera;\n"
-"\n"
-"#line       1        1 \n"
-"// :D\n"
-"const float CLEARSKIES_LIGHT_DOT_MIN = 0.0;\n"
-"\n"
-"#line      6        0 \n"
-"#line       1        2 \n"
-"// :D\n"
-"\n"
-"in vec2 aUv;\n"
-"in vec4 aNorm;\n"
-"in vec3 aCo;\n"
-"in vec3 aWorldCo;\n"
-"\n"
-"#line       1        1 \n"
-"layout (location = 0) out vec4 oColour;\n"
-"\n"
-"// OpenGL wiki: Recommends do not use vec3 because of drivers. hence the v4s...\n"
-"layout (std140) uniform ub_world_lighting\n"
-"{\n"
-"   vec4 g_cube_min;\n"
-"   vec4 g_cube_inv_range;\n"
-"\n"
-"   vec4 g_water_plane;\n"
-"   vec4 g_depth_bounds;\n"
-"\n"
-"   vec4 g_daysky_colour;\n"
-"   vec4 g_nightsky_colour;\n"
-"   vec4 g_sunset_colour;\n"
-"   vec4 g_ambient_colour;\n"
-"   vec4 g_sunset_ambient;\n"
-"   vec4 g_sun_colour;\n"
-"   vec4 g_sun_dir;\n"
-"   vec4 g_board_0;\n"
-"   vec4 g_board_1;\n"
-"\n"
-"   float g_water_fog;\n"
-"   float g_time;\n"
-"   float g_realtime;\n"
-"   float g_shadow_length;\n"
-"   float g_shadow_spread;\n"
-"\n"
-"   float g_time_of_day;\n"
-"   float g_day_phase;\n"
-"   float g_sunset_phase;\n"
-"\n"
-"   int g_light_preview;\n"
-"   int g_shadow_samples;\n"
-"\n"
-"   int g_debug_indices;\n"
-"   int g_debug_complexity;\n"
-"};\n"
-"\n"
-"uniform sampler2D g_world_depth;\n"
-"uniform samplerBuffer uLightsArray;\n"
-"uniform usampler3D uLightsIndex;\n"
-"\n"
-"#line       1        1 \n"
-"//const vec3  DAYSKY_COLOUR   = vec3( 0.37, 0.54, 0.97 );\n"
-"//const vec3  NIGHTSKY_COLOUR = vec3( 0.03, 0.05, 0.20 );\n"
-"//const vec3  SUNSET_COLOUR   = vec3( 1.00, 0.32, 0.01 );\n"
-"//const vec3  AMBIENT_COLOUR  = vec3( 0.13, 0.17, 0.35 );\n"
-"//const vec3  SUNSET_AMBIENT  = vec3( 0.25, 0.17, 0.51 );\n"
-"//const vec3  SUN_COLOUR      = vec3( 1.10, 0.89, 0.35 );\n"
-"\n"
-"const float SUN_ANGLE       = 0.0001;\n"
-"const float PI              = 3.14159265358979323846264;\n"
-"\n"
-"//struct world_info\n"
-"//{\n"
-"//   float time,\n"
-"//         time_of_day,\n"
-"//         day_phase,\n"
-"//         sunset_phase;\n"
-"//   \n"
-"//   vec3 sun_dir;\n"
-"//};\n"
-"\n"
-"vec3 rand33(vec3 p3)\n"
-"{\n"
-"      p3 = fract(p3 * vec3(.1031, .1030, .0973));\n"
-"   p3 += dot(p3, p3.yxz+33.33);\n"
-"   return fract((p3.xxy + p3.yxx)*p3.zyx);\n"
-"}\n"
-"\n"
-"float stars( vec3 rd, float rr, float size ){\n"
-"   vec3 co = rd * rr;\n"
-"\n"
-"   float a = atan(co.y, length(co.xz)) + 4.0 * PI;\n"
-"\n"
-"   float spaces = 1.0 / rr;\n"
-"   size = (rr * 0.0015) * fwidth(a) * 1000.0 * size;\n"
-"   a -= mod(a, spaces) - spaces * 0.5;\n"
-"\n"
-"   float count = floor(sqrt(pow(rr, 2.0) * (1.0 - pow(sin(a), 2.0))) * 3.0);\n"
-"   \n"
-"   float plane = atan(co.z, co.x) + 4.0 * PI;\n"
-"   plane = plane - mod(plane, PI / count);\n"
-"\n"
-"   vec2 delta = rand33(vec3(plane, a, 0.0)).xy;\n"
-"\n"
-"   float level = sin(a + spaces * (delta.y - 0.5) * (1.0 - size)) * rr;\n"
-"   float ydist = sqrt(rr * rr - level * level);\n"
-"   float angle = plane + (PI * (delta.x * (1.0-size) + size * 0.5) / count);\n"
-"   vec3 center = vec3(cos(angle) * ydist, level, sin(angle) * ydist);\n"
-"   float star = smoothstep(size, 0.0, distance(center, co));\n"
-"   return star;\n"
-"}\n"
-"\n"
-"float luminance( vec3 v )\n"
-"{\n"
-"   return dot( v, vec3(0.2126, 0.7152, 0.0722) );\n"
-"}\n"
-"\n"
-"vec3 clearskies_ambient( vec3 dir )\n"
-"{\n"
-"   float sun_azimuth  = g_sunset_phase * (dot( dir.xz, g_sun_dir.xz )*0.4+0.6);\n"
-"   float sky_gradient = dir.y;\n"
-"   \n"
-"   /* Blend phase colours */\n"
-"   vec3 ambient  = g_daysky_colour.rgb   * (g_day_phase-g_sunset_phase*0.1);\n"
-"        ambient += g_sunset_colour.rgb   * (1.0-dir.y*0.5)*sun_azimuth;\n"
-"        ambient += g_nightsky_colour.rgb * (1.0-g_day_phase);\n"
-"   \n"
-"   /* Add gradient */\n"
-"        ambient -= sky_gradient * luminance(ambient);\n"
-"        \n"
-"   return ambient;\n"
-"}\n"
-"\n"
-"vec3 clearskies_sky( vec3 ray_dir )\n"
-"{\n"
-"   ray_dir.y = abs( ray_dir.y );\n"
-"   vec3 sky_colour  = clearskies_ambient( ray_dir );\n"
-"   \n"
-"   /* Sun */\n"
-"   float sun_theta  = dot( ray_dir, g_sun_dir.xyz );\n"
-"   float sun_size   = max( 0.0, sun_theta * 0.5 + 0.5 + SUN_ANGLE );\n"
-"   float sun_shape  = pow( sun_size, 2000.0 );\n"
-"         sun_shape += sun_size * max(g_sun_dir.y,0.0) * 0.5;\n"
-"         \n"
-"   vec3 sun_colour  = mix( vec3(1.0), g_sunset_colour.rgb, g_sunset_phase*0.5 );\n"
-"        sun_colour *= sun_shape;\n"
-"\n"
-"   \n"
-"   float star = 0.0;\n"
-"   float star_blend = 10.0*max(0.0,(1.0-g_day_phase*2.0));\n"
-"\n"
-"   if( star_blend > 0.001 ){\n"
-"      for( float j = 1.0; j <= 4.1; j += 1.0 ){\n"
-"         float m = mix(0.6, 0.9, smoothstep(1.0, 2.0, j));\n"
-"         star += stars( ray_dir, 1.94 * pow( 1.64, j ), m ) * (1.0/pow(4.0, j));\n"
-"      }\n"
-"   }\n"
-"   \n"
-"   vec3 composite   = sky_colour + sun_colour + star*star_blend;\n"
-"   return composite;\n"
-"}\n"
-"\n"
-"vec3 clearskies_lighting( vec3 normal, float shadow, vec3 halfview )\n"
-"{\n"
-"   float fresnel = 1.0 - abs(dot(normal,halfview));\n"
-"\n"
-"   vec3  reflect_colour = mix( g_daysky_colour.rgb, g_sunset_colour.rgb, \n"
-"                               g_sunset_phase );\n"
-"\n"
-"   vec3  sky_reflection = 0.5 * fresnel * reflect_colour;\n"
-"   vec3  light_sun      = max( CLEARSKIES_LIGHT_DOT_MIN, \n"
-"                               dot(normal,g_sun_dir.xyz)*0.75+0.25\n"
-"                           ) * g_sun_colour.rgb * g_day_phase;\n"
-"\n"
-"   float scaled_shadow = max( shadow, 1.0 - max(g_sun_dir.y,0.0) );\n"
-"   vec3 ambient = mix( g_ambient_colour.rgb, g_sunset_ambient.rgb, \n"
-"                       g_sunset_phase );\n"
-"\n"
-"   return ambient + (light_sun + sky_reflection) * shadow;\n"
-"}\n"
-"\n"
-"#line     44        0 \n"
-"\n"
-"float world_depth_sample( vec3 pos )\n"
-"{\n"
-"   vec2 depth_coord = (pos.xz - g_depth_bounds.xy) * g_depth_bounds.zw; \n"
-"   return texture( g_world_depth, depth_coord ).r;\n"
-"}\n"
-"\n"
-"float world_water_depth( vec3 pos )\n"
-"{\n"
-"   float ref_depth = g_water_plane.y*g_water_plane.w;\n"
-"   return world_depth_sample( pos ) - ref_depth;\n"
-"}\n"
-"\n"
-"float shadow_sample( vec3 co ){\n"
-"   float height_sample = world_depth_sample( co );\n"
-"\n"
-"   float fdelta = height_sample - co.y;\n"
-"   return clamp( fdelta, 0.2, 0.4 )-0.2;\n"
-"}\n"
-"\n"
-"float newlight_compute_sun_shadow( vec3 co, vec3 dir ){\n"
-"   if( g_shadow_samples == 0 ){\n"
-"      return 1.0;\n"
-"   }\n"
-"\n"
-"   float fspread = g_shadow_spread;\n"
-"   float flength = g_shadow_length;\n"
-"\n"
-"   float famt = 0.0;\n"
-"   famt += shadow_sample(co+(dir+vec3(-0.56,0.55, 0.30)*fspread)*flength*0.1);\n"
-"   famt += shadow_sample(co+(dir+vec3( 0.80,0.68, 0.34)*fspread)*flength*0.2);\n"
-"   famt += shadow_sample(co+(dir+vec3( 0.78,0.07,-0.06)*fspread)*flength*0.3);\n"
-"   famt += shadow_sample(co+(dir+vec3(-0.59,0.07,-0.42)*fspread)*flength*0.4);\n"
-"\n"
-"   //famt+=shadow_sample(co+(dir+vec3(-0.790,-0.933,-0.875)*fspread)*flength*0.5);\n"
-"   //famt+=shadow_sample(co+(dir+vec3( 0.807,-0.690, 0.472)*fspread)*flength*0.6);\n"
-"   //famt+=shadow_sample(co+(dir+vec3( 0.522,-0.379, 0.350)*fspread)*flength*0.7);\n"
-"   //famt+=shadow_sample(co+(dir+vec3( 0.483, 0.201, 0.306)*fspread)*flength*0.8);\n"
-"\n"
-"   return 1.0 - famt;\n"
-"}\n"
-"\n"
-"float newlight_specular( vec3 wnormal, vec3 dir, vec3 halfview, float exponent )\n"
-"{\n"
-"   vec3 specdir = reflect( -dir, wnormal );\n"
-"   return pow(max(dot( halfview, specdir ), 0.0), exponent);\n"
-"}\n"
-"\n"
-"vec3 scene_apply_fog( vec3 vfrag, vec3 colour, float fdist ){\n"
-"   float dist = pow(fdist*0.0010,0.78);\n"
-"   return mix( vfrag, colour, min( 1.0, dist ) );\n"
-"}\n"
-"\n"
-"vec3 scene_calculate_light( int light_index, \n"
-"                            vec3 halfview, vec3 co, vec3 normal )\n"
-"{\n"
-"   vec4 light_colour = texelFetch( uLightsArray, light_index+0 );\n"
-"   vec4 light_co     = texelFetch( uLightsArray, light_index+1 );\n"
-"   vec4 light_dir    = texelFetch( uLightsArray, light_index+2 );\n"
-"\n"
-"   vec3 light_delta = light_co.xyz-co;\n"
-"   float dist2 = dot(light_delta,light_delta);\n"
-"\n"
-"   light_delta = normalize( light_delta );\n"
-"\n"
-"   float quadratic = dist2*100.0;\n"
-"   float attenuation  = 1.0/( 1.0 + quadratic );\n"
-"         attenuation *= max( dot( light_delta, normal ), 0.0 );\n"
-"\n"
-"   float falloff = max( 0.0, 1.0-(dist2*light_co.w) );\n"
-"\n"
-"   if( light_dir.w < 0.999999 ){\n"
-"      float spot_theta = max( 0.0, dot( light_delta, -light_dir.xyz ) );\n"
-"      falloff *= max( 0.0, (spot_theta - light_dir.w) / (1.0-light_dir.w) );\n"
-"   }\n"
-"\n"
-"   return light_colour.rgb * attenuation * falloff \n"
-"            * step( g_day_phase, light_colour.w );\n"
-"}\n"
-"\n"
-"vec3 scene_calculate_packed_light_patch( uint packed_index, \n"
-"                                         vec3 halfview, vec3 co, vec3 normal )\n"
-"{\n"
-"   uint light_count = packed_index & 0x3u;\n"
-"\n"
-"   vec3 l = vec3(0.0);\n"
-"\n"
-"   if( light_count >= 1u ){\n"
-"      int index_0 = int( ((packed_index >>  2u) & 0x3ffu) * 3u );\n"
-"      int index_1 = int( ((packed_index >> 12u) & 0x3ffu) * 3u );\n"
-"      int index_2 = int( ((packed_index >> 22u) & 0x3ffu) * 3u );\n"
-"\n"
-"      l += scene_calculate_light( index_0, halfview, co, normal );\n"
-"\n"
-"      if( light_count >= 2u ){\n"
-"         l += scene_calculate_light( index_1, halfview, co, normal );\n"
-"\n"
-"         if( light_count >= 3u ){\n"
-"            l += scene_calculate_light( index_2, halfview, co, normal );\n"
-"         }\n"
-"      }\n"
-"   }\n"
-"\n"
-"   return l;\n"
-"}\n"
-"\n"
-"vec3 world_compute_lighting( vec3 diffuse, vec3 normal, vec3 co,\n"
-"                             float light_mask )\n"
-"{\n"
-"   if( g_light_preview == 1 )\n"
-"      diffuse = vec3(0.75);\n"
-"\n"
-"   // Lighting\n"
-"   vec3 halfview = uCamera - co;\n"
-"   float fdist = length(halfview);\n"
-"   halfview /= fdist;\n"
-"\n"
-"   float world_shadow = newlight_compute_sun_shadow( \n"
-"               co, g_sun_dir.xyz * (1.0/(max(g_sun_dir.y,0.0)+0.2)) );\n"
-"\n"
-"   vec3 total_light = clearskies_lighting( \n"
-"                           normal, min( light_mask, world_shadow ), halfview );\n"
-"\n"
-"   vec3 cube_coord = (co - g_cube_min.xyz) * g_cube_inv_range.xyz;\n"
-"        cube_coord = floor( cube_coord );\n"
-"\n"
-"   if( g_debug_indices == 1 )\n"
-"   {\n"
-"      return rand33(cube_coord);\n"
-"   }\n"
-"\n"
-"   if( g_debug_complexity == 1 )\n"
-"   {\n"
-"      ivec3 coord = ivec3( cube_coord );\n"
-"      uvec4 index_sample = texelFetch( uLightsIndex, coord, 0 );\n"
-"\n"
-"      uint light_count = (index_sample.x & 0x3u) + (index_sample.y & 0x3u);\n"
-"      return vec3( float(light_count)*(1.0/6.0), 0.0, 0.5 );\n"
-"   }\n"
-"\n"
-"   // FIXME: this coord should absolutely must be clamped!\n"
-"   \n"
-"   ivec3 coord = ivec3( cube_coord );\n"
-"   uvec4 index_sample = texelFetch( uLightsIndex, coord, 0 );\n"
-"\n"
-"   total_light += \n"
-"      scene_calculate_packed_light_patch( index_sample.x,\n"
-"                                          halfview, co, normal ) \n"
-"                                          * light_mask;\n"
-"   total_light += \n"
-"      scene_calculate_packed_light_patch( index_sample.y,\n"
-"                                          halfview, co, normal )\n"
-"                                          * light_mask;\n"
-"\n"
-"   // Take a section of the sky function to give us a matching fog colour\n"
-"\n"
-"   vec3 fog_colour  = clearskies_ambient( -halfview );\n"
-"   float sun_theta  = dot( -halfview, g_sun_dir.xyz );\n"
-"   float sun_size   = max( 0.0, sun_theta * 0.5 + 0.5 );\n"
-"   float sun_shape  = sun_size * max(g_sun_dir.y,0.0) * 0.5;\n"
-"         \n"
-"   vec3 sun_colour  = mix( vec3(1.0), g_sunset_colour.rgb, g_sunset_phase*0.5 );\n"
-"        sun_colour *= sun_shape;\n"
-"\n"
-"   fog_colour += sun_colour;\n"
-"   return scene_apply_fog( diffuse * total_light, fog_colour, fdist );\n"
-"}\n"
-"\n"
-"#line      9        0 \n"
-"\n"
-"float sdLine( vec3 p, vec3 a, vec3 b )\n"
-"{\n"
-"  vec3 pa = p - a;\n"
-"  vec3 ba = b - a;\n"
-"\n"
-"  float h = clamp( dot(pa,ba)/dot(ba,ba), 0.0, 1.0 );\n"
-"  return length( pa - ba*h );\n"
-"}\n"
-"\n"
-"float compute_board_shadow()\n"
-"{\n"
-"   // player shadow\n"
-"   float dist_to_player = max( 0.0, sdLine( aWorldCo, g_board_0.xyz,\n"
-"                                                      g_board_1.xyz )-0.1 );\n"
-"   float player_shadow = max( 1.0-dist_to_player*2.7, 0.0 );\n"
-"   player_shadow *= player_shadow*player_shadow*player_shadow;\n"
-"\n"
-"   return 1.0 - player_shadow*0.8;\n"
-"}\n"
-"\n"
-"vec3 scene_compute_lighting( vec3 diffuse, vec3 normal, vec3 co )\n"
-"{\n"
-"   return world_compute_lighting( diffuse, normal, co, compute_board_shadow() );\n"
-"}\n"
-"\n"
-"#line      7        0 \n"
-"#line       1        3 \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      8        0 \n"
-"\n"
-"void main()\n"
-"{\n"
-"   compute_motion_vectors();\n"
-"\n"
-"   vec3 vfrag = vec3(0.5,0.5,0.5);\n"
-"\n"
-"   // ws modulation\n"
-"   vec4 wgarbage = vec4(0.5,0.5,0.5,1.0);\n"
-"   \n"
-"   // Creating normal patches\n"
-"   vec3 modnorm = (wgarbage.rgb-0.4) * 1.4;\n"
-"   vec3 qnorm = normalize(floor(aNorm.xyz*4.0+modnorm)*0.25);\n"
-"   qnorm += vec3(0.001,0.0,0.0);\n"
-"\n"
-"   vec3 tangent0 = normalize(cross(qnorm,vec3(0.0,1.0,0.0)));\n"
-"   vec3 tangent1 = cross(qnorm,tangent0);\n"
-"   vec2 uvdiffuse = vec2( dot(tangent0,aCo), dot(tangent1,aCo) ) * 0.160;\n"
-"   \n"
-"   // Patch local noise\n"
-"   vec4 rgarbage = texture( uTexGarbage, uvdiffuse );\n"
-"\n"
-"   // Colour blending\n"
-"   float fblendclip = step(0.380,aNorm.w + (rgarbage.r-0.5)*-1.740)*0.320;\n"
-"   vec2 uvgradients = aUv + vec2( fblendclip, 0.0 );\n"
-"\n"
-"   vfrag = texture( uTexGradients, uvgradients ).rgb;\n"
-"   vfrag -= rgarbage.a*0.04;\n"
-"\n"
-"   if( g_light_preview == 1 )\n"
-"   {\n"
-"      vfrag = vec3(0.5);\n"
-"   }\n"
-"\n"
-"   vfrag = scene_compute_lighting( vfrag, qnorm, aWorldCo );\n"
-"   oColour = vec4(vfrag, 1.0);\n"
-"}\n"
-""},
-};
-
-static GLuint _uniform_scene_vertex_blend_uMdl;
-static GLuint _uniform_scene_vertex_blend_uPv;
-static GLuint _uniform_scene_vertex_blend_uPvmPrev;
-static GLuint _uniform_scene_vertex_blend_uTexGarbage;
-static GLuint _uniform_scene_vertex_blend_uTexGradients;
-static GLuint _uniform_scene_vertex_blend_uCamera;
-static GLuint _uniform_scene_vertex_blend_g_world_depth;
-static GLuint _uniform_scene_vertex_blend_uLightsArray;
-static GLuint _uniform_scene_vertex_blend_uLightsIndex;
-static void shader_scene_vertex_blend_uMdl(m4x3f m){
-   glUniformMatrix4x3fv(_uniform_scene_vertex_blend_uMdl,1,GL_FALSE,(float*)m);
+   glUniformMatrix4x3fv(_uniform_scene_vertex_blend_uMdl,1,GL_FALSE,(f32*)m);
 }
-static void shader_scene_vertex_blend_uPv(m4x4f m){
-   glUniformMatrix4fv(_uniform_scene_vertex_blend_uPv,1,GL_FALSE,(float*)m);
+static inline void shader_scene_vertex_blend_uPv(m4x4f m)
+{
+   glUniformMatrix4fv(_uniform_scene_vertex_blend_uPv,1,GL_FALSE,(f32*)m);
 }
-static void shader_scene_vertex_blend_uPvmPrev(m4x4f m){
-   glUniformMatrix4fv(_uniform_scene_vertex_blend_uPvmPrev,1,GL_FALSE,(float*)m);
+static inline void shader_scene_vertex_blend_uPvmPrev(m4x4f m)
+{
+   glUniformMatrix4fv(_uniform_scene_vertex_blend_uPvmPrev,1,GL_FALSE,(f32*)m);
 }
-static void shader_scene_vertex_blend_uTexGarbage(int i){
+static inline void shader_scene_vertex_blend_uTexGarbage(int i)
+{
    glUniform1i(_uniform_scene_vertex_blend_uTexGarbage,i);
 }
-static void shader_scene_vertex_blend_uTexGradients(int i){
+static inline void shader_scene_vertex_blend_uTexGradients(int i)
+{
    glUniform1i(_uniform_scene_vertex_blend_uTexGradients,i);
 }
-static void shader_scene_vertex_blend_uCamera(v3f v){
+static inline void shader_scene_vertex_blend_uCamera(v3f v)
+{
    glUniform3fv(_uniform_scene_vertex_blend_uCamera,1,v);
 }
-static void shader_scene_vertex_blend_g_world_depth(int i){
+static inline void shader_scene_vertex_blend_g_world_depth(int i)
+{
    glUniform1i(_uniform_scene_vertex_blend_g_world_depth,i);
 }
-static void shader_scene_vertex_blend_register(void){
-   vg_shader_register( &_shader_scene_vertex_blend );
-}
-static void shader_scene_vertex_blend_use(void){ glUseProgram(_shader_scene_vertex_blend.id); }
-static void shader_scene_vertex_blend_link(void){
-   _uniform_scene_vertex_blend_uMdl = glGetUniformLocation( _shader_scene_vertex_blend.id, "uMdl" );
-   _uniform_scene_vertex_blend_uPv = glGetUniformLocation( _shader_scene_vertex_blend.id, "uPv" );
-   _uniform_scene_vertex_blend_uPvmPrev = glGetUniformLocation( _shader_scene_vertex_blend.id, "uPvmPrev" );
-   _uniform_scene_vertex_blend_uTexGarbage = glGetUniformLocation( _shader_scene_vertex_blend.id, "uTexGarbage" );
-   _uniform_scene_vertex_blend_uTexGradients = glGetUniformLocation( _shader_scene_vertex_blend.id, "uTexGradients" );
-   _uniform_scene_vertex_blend_uCamera = glGetUniformLocation( _shader_scene_vertex_blend.id, "uCamera" );
-   _uniform_scene_vertex_blend_g_world_depth = glGetUniformLocation( _shader_scene_vertex_blend.id, "g_world_depth" );
-   _uniform_scene_vertex_blend_uLightsArray = glGetUniformLocation( _shader_scene_vertex_blend.id, "uLightsArray" );
-   _uniform_scene_vertex_blend_uLightsIndex = glGetUniformLocation( _shader_scene_vertex_blend.id, "uLightsIndex" );
+static inline void shader_scene_vertex_blend_use(void);
+static inline void shader_scene_vertex_blend_use(void)
+{
+   glUseProgram(_shader_scene_vertex_blend.id);
 }
-#endif /* SHADER_scene_vertex_blend_H */
index 3ac3b9d89eadee1326335ec34852edfb8eabff62..d19c02d050527c5e26007a44a78fe032626507a9 100644 (file)
-#ifndef SHADER_scene_water_H
-#define SHADER_scene_water_H
-static void shader_scene_water_link(void);
-static void shader_scene_water_register(void);
-static struct vg_shader _shader_scene_water = {
-   .name = "scene_water",
-   .link = shader_scene_water_link,
-   .vs = 
+#pragma once
+#include "vg/vg_engine.h"
+extern struct vg_shader _shader_scene_water;
+extern GLuint _uniform_scene_water_uMdl;
+extern GLuint _uniform_scene_water_uPv;
+extern GLuint _uniform_scene_water_uPvmPrev;
+extern GLuint _uniform_scene_water_uTexMain;
+extern GLuint _uniform_scene_water_uTexDudv;
+extern GLuint _uniform_scene_water_uTexBack;
+extern GLuint _uniform_scene_water_uInvRes;
+extern GLuint _uniform_scene_water_uTime;
+extern GLuint _uniform_scene_water_uCamera;
+extern GLuint _uniform_scene_water_uSurfaceY;
+extern GLuint _uniform_scene_water_uBoard0;
+extern GLuint _uniform_scene_water_uBoard1;
+extern GLuint _uniform_scene_water_uShoreColour;
+extern GLuint _uniform_scene_water_uOceanColour;
+extern GLuint _uniform_scene_water_g_world_depth;
+extern GLuint _uniform_scene_water_uLightsArray;
+extern GLuint _uniform_scene_water_uLightsIndex;
+static inline void shader_scene_water_uMdl(m4x3f m)
 {
-.orig_file = "shaders/scene.vs",
-.static_src = 
-"layout (location=0) in vec3  a_co;\n"
-"layout (location=1) in vec4  a_norm;\n"
-"layout (location=2) in vec2  a_uv;\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      6        0 \n"
-"\n"
-"uniform mat4x3 uMdl;\n"
-"uniform mat4   uPv;\n"
-"uniform mat4   uPvmPrev;\n"
-"\n"
-"out vec2 aUv;\n"
-"out vec4 aNorm;\n"
-"out vec3 aCo;\n"
-"out vec3 aWorldCo;\n"
-"\n"
-"void main()\n"
-"{\n"
-"   vec3 world_pos0 = uMdl     * vec4( a_co, 1.0 );\n"
-"   vec4 vproj0     = uPv      * vec4( world_pos0, 1.0 );\n"
-"   vec4 vproj1     = uPvmPrev * vec4( a_co, 1.0 );\n"
-"\n"
-"   vs_motion_out( vproj0, vproj1 );\n"
-"\n"
-"   gl_Position = vproj0;\n"
-"\n"
-"   aUv = a_uv;\n"
-"   aNorm = vec4( mat3(uMdl) * a_norm.xyz, a_norm.w );\n"
-"   aCo = a_co;\n"
-"   aWorldCo = world_pos0;\n"
-"}\n"
-""},
-   .fs = 
-{
-.orig_file = "shaders/scene_water.fs",
-.static_src = 
-"uniform sampler2D uTexMain;\n"
-"uniform sampler2D uTexDudv;\n"
-"uniform sampler2D uTexBack;\n"
-"\n"
-"uniform vec2 uInvRes;\n"
-"uniform float uTime;\n"
-"uniform vec3 uCamera;\n"
-"uniform float uSurfaceY;\n"
-"uniform vec3 uBoard0;\n"
-"uniform vec3 uBoard1;\n"
-"\n"
-"uniform vec3 uShoreColour;\n"
-"uniform vec3 uOceanColour;\n"
-"\n"
-"#line       1        1 \n"
-"// :D\n"
-"const float CLEARSKIES_LIGHT_DOT_MIN = 0.0;\n"
-"\n"
-"#line     16        0 \n"
-"#line       1        2 \n"
-"// :D\n"
-"\n"
-"in vec2 aUv;\n"
-"in vec4 aNorm;\n"
-"in vec3 aCo;\n"
-"in vec3 aWorldCo;\n"
-"\n"
-"#line       1        1 \n"
-"layout (location = 0) out vec4 oColour;\n"
-"\n"
-"// OpenGL wiki: Recommends do not use vec3 because of drivers. hence the v4s...\n"
-"layout (std140) uniform ub_world_lighting\n"
-"{\n"
-"   vec4 g_cube_min;\n"
-"   vec4 g_cube_inv_range;\n"
-"\n"
-"   vec4 g_water_plane;\n"
-"   vec4 g_depth_bounds;\n"
-"\n"
-"   vec4 g_daysky_colour;\n"
-"   vec4 g_nightsky_colour;\n"
-"   vec4 g_sunset_colour;\n"
-"   vec4 g_ambient_colour;\n"
-"   vec4 g_sunset_ambient;\n"
-"   vec4 g_sun_colour;\n"
-"   vec4 g_sun_dir;\n"
-"   vec4 g_board_0;\n"
-"   vec4 g_board_1;\n"
-"\n"
-"   float g_water_fog;\n"
-"   float g_time;\n"
-"   float g_realtime;\n"
-"   float g_shadow_length;\n"
-"   float g_shadow_spread;\n"
-"\n"
-"   float g_time_of_day;\n"
-"   float g_day_phase;\n"
-"   float g_sunset_phase;\n"
-"\n"
-"   int g_light_preview;\n"
-"   int g_shadow_samples;\n"
-"\n"
-"   int g_debug_indices;\n"
-"   int g_debug_complexity;\n"
-"};\n"
-"\n"
-"uniform sampler2D g_world_depth;\n"
-"uniform samplerBuffer uLightsArray;\n"
-"uniform usampler3D uLightsIndex;\n"
-"\n"
-"#line       1        1 \n"
-"//const vec3  DAYSKY_COLOUR   = vec3( 0.37, 0.54, 0.97 );\n"
-"//const vec3  NIGHTSKY_COLOUR = vec3( 0.03, 0.05, 0.20 );\n"
-"//const vec3  SUNSET_COLOUR   = vec3( 1.00, 0.32, 0.01 );\n"
-"//const vec3  AMBIENT_COLOUR  = vec3( 0.13, 0.17, 0.35 );\n"
-"//const vec3  SUNSET_AMBIENT  = vec3( 0.25, 0.17, 0.51 );\n"
-"//const vec3  SUN_COLOUR      = vec3( 1.10, 0.89, 0.35 );\n"
-"\n"
-"const float SUN_ANGLE       = 0.0001;\n"
-"const float PI              = 3.14159265358979323846264;\n"
-"\n"
-"//struct world_info\n"
-"//{\n"
-"//   float time,\n"
-"//         time_of_day,\n"
-"//         day_phase,\n"
-"//         sunset_phase;\n"
-"//   \n"
-"//   vec3 sun_dir;\n"
-"//};\n"
-"\n"
-"vec3 rand33(vec3 p3)\n"
-"{\n"
-"      p3 = fract(p3 * vec3(.1031, .1030, .0973));\n"
-"   p3 += dot(p3, p3.yxz+33.33);\n"
-"   return fract((p3.xxy + p3.yxx)*p3.zyx);\n"
-"}\n"
-"\n"
-"float stars( vec3 rd, float rr, float size ){\n"
-"   vec3 co = rd * rr;\n"
-"\n"
-"   float a = atan(co.y, length(co.xz)) + 4.0 * PI;\n"
-"\n"
-"   float spaces = 1.0 / rr;\n"
-"   size = (rr * 0.0015) * fwidth(a) * 1000.0 * size;\n"
-"   a -= mod(a, spaces) - spaces * 0.5;\n"
-"\n"
-"   float count = floor(sqrt(pow(rr, 2.0) * (1.0 - pow(sin(a), 2.0))) * 3.0);\n"
-"   \n"
-"   float plane = atan(co.z, co.x) + 4.0 * PI;\n"
-"   plane = plane - mod(plane, PI / count);\n"
-"\n"
-"   vec2 delta = rand33(vec3(plane, a, 0.0)).xy;\n"
-"\n"
-"   float level = sin(a + spaces * (delta.y - 0.5) * (1.0 - size)) * rr;\n"
-"   float ydist = sqrt(rr * rr - level * level);\n"
-"   float angle = plane + (PI * (delta.x * (1.0-size) + size * 0.5) / count);\n"
-"   vec3 center = vec3(cos(angle) * ydist, level, sin(angle) * ydist);\n"
-"   float star = smoothstep(size, 0.0, distance(center, co));\n"
-"   return star;\n"
-"}\n"
-"\n"
-"float luminance( vec3 v )\n"
-"{\n"
-"   return dot( v, vec3(0.2126, 0.7152, 0.0722) );\n"
-"}\n"
-"\n"
-"vec3 clearskies_ambient( vec3 dir )\n"
-"{\n"
-"   float sun_azimuth  = g_sunset_phase * (dot( dir.xz, g_sun_dir.xz )*0.4+0.6);\n"
-"   float sky_gradient = dir.y;\n"
-"   \n"
-"   /* Blend phase colours */\n"
-"   vec3 ambient  = g_daysky_colour.rgb   * (g_day_phase-g_sunset_phase*0.1);\n"
-"        ambient += g_sunset_colour.rgb   * (1.0-dir.y*0.5)*sun_azimuth;\n"
-"        ambient += g_nightsky_colour.rgb * (1.0-g_day_phase);\n"
-"   \n"
-"   /* Add gradient */\n"
-"        ambient -= sky_gradient * luminance(ambient);\n"
-"        \n"
-"   return ambient;\n"
-"}\n"
-"\n"
-"vec3 clearskies_sky( vec3 ray_dir )\n"
-"{\n"
-"   ray_dir.y = abs( ray_dir.y );\n"
-"   vec3 sky_colour  = clearskies_ambient( ray_dir );\n"
-"   \n"
-"   /* Sun */\n"
-"   float sun_theta  = dot( ray_dir, g_sun_dir.xyz );\n"
-"   float sun_size   = max( 0.0, sun_theta * 0.5 + 0.5 + SUN_ANGLE );\n"
-"   float sun_shape  = pow( sun_size, 2000.0 );\n"
-"         sun_shape += sun_size * max(g_sun_dir.y,0.0) * 0.5;\n"
-"         \n"
-"   vec3 sun_colour  = mix( vec3(1.0), g_sunset_colour.rgb, g_sunset_phase*0.5 );\n"
-"        sun_colour *= sun_shape;\n"
-"\n"
-"   \n"
-"   float star = 0.0;\n"
-"   float star_blend = 10.0*max(0.0,(1.0-g_day_phase*2.0));\n"
-"\n"
-"   if( star_blend > 0.001 ){\n"
-"      for( float j = 1.0; j <= 4.1; j += 1.0 ){\n"
-"         float m = mix(0.6, 0.9, smoothstep(1.0, 2.0, j));\n"
-"         star += stars( ray_dir, 1.94 * pow( 1.64, j ), m ) * (1.0/pow(4.0, j));\n"
-"      }\n"
-"   }\n"
-"   \n"
-"   vec3 composite   = sky_colour + sun_colour + star*star_blend;\n"
-"   return composite;\n"
-"}\n"
-"\n"
-"vec3 clearskies_lighting( vec3 normal, float shadow, vec3 halfview )\n"
-"{\n"
-"   float fresnel = 1.0 - abs(dot(normal,halfview));\n"
-"\n"
-"   vec3  reflect_colour = mix( g_daysky_colour.rgb, g_sunset_colour.rgb, \n"
-"                               g_sunset_phase );\n"
-"\n"
-"   vec3  sky_reflection = 0.5 * fresnel * reflect_colour;\n"
-"   vec3  light_sun      = max( CLEARSKIES_LIGHT_DOT_MIN, \n"
-"                               dot(normal,g_sun_dir.xyz)*0.75+0.25\n"
-"                           ) * g_sun_colour.rgb * g_day_phase;\n"
-"\n"
-"   float scaled_shadow = max( shadow, 1.0 - max(g_sun_dir.y,0.0) );\n"
-"   vec3 ambient = mix( g_ambient_colour.rgb, g_sunset_ambient.rgb, \n"
-"                       g_sunset_phase );\n"
-"\n"
-"   return ambient + (light_sun + sky_reflection) * shadow;\n"
-"}\n"
-"\n"
-"#line     44        0 \n"
-"\n"
-"float world_depth_sample( vec3 pos )\n"
-"{\n"
-"   vec2 depth_coord = (pos.xz - g_depth_bounds.xy) * g_depth_bounds.zw; \n"
-"   return texture( g_world_depth, depth_coord ).r;\n"
-"}\n"
-"\n"
-"float world_water_depth( vec3 pos )\n"
-"{\n"
-"   float ref_depth = g_water_plane.y*g_water_plane.w;\n"
-"   return world_depth_sample( pos ) - ref_depth;\n"
-"}\n"
-"\n"
-"float shadow_sample( vec3 co ){\n"
-"   float height_sample = world_depth_sample( co );\n"
-"\n"
-"   float fdelta = height_sample - co.y;\n"
-"   return clamp( fdelta, 0.2, 0.4 )-0.2;\n"
-"}\n"
-"\n"
-"float newlight_compute_sun_shadow( vec3 co, vec3 dir ){\n"
-"   if( g_shadow_samples == 0 ){\n"
-"      return 1.0;\n"
-"   }\n"
-"\n"
-"   float fspread = g_shadow_spread;\n"
-"   float flength = g_shadow_length;\n"
-"\n"
-"   float famt = 0.0;\n"
-"   famt += shadow_sample(co+(dir+vec3(-0.56,0.55, 0.30)*fspread)*flength*0.1);\n"
-"   famt += shadow_sample(co+(dir+vec3( 0.80,0.68, 0.34)*fspread)*flength*0.2);\n"
-"   famt += shadow_sample(co+(dir+vec3( 0.78,0.07,-0.06)*fspread)*flength*0.3);\n"
-"   famt += shadow_sample(co+(dir+vec3(-0.59,0.07,-0.42)*fspread)*flength*0.4);\n"
-"\n"
-"   //famt+=shadow_sample(co+(dir+vec3(-0.790,-0.933,-0.875)*fspread)*flength*0.5);\n"
-"   //famt+=shadow_sample(co+(dir+vec3( 0.807,-0.690, 0.472)*fspread)*flength*0.6);\n"
-"   //famt+=shadow_sample(co+(dir+vec3( 0.522,-0.379, 0.350)*fspread)*flength*0.7);\n"
-"   //famt+=shadow_sample(co+(dir+vec3( 0.483, 0.201, 0.306)*fspread)*flength*0.8);\n"
-"\n"
-"   return 1.0 - famt;\n"
-"}\n"
-"\n"
-"float newlight_specular( vec3 wnormal, vec3 dir, vec3 halfview, float exponent )\n"
-"{\n"
-"   vec3 specdir = reflect( -dir, wnormal );\n"
-"   return pow(max(dot( halfview, specdir ), 0.0), exponent);\n"
-"}\n"
-"\n"
-"vec3 scene_apply_fog( vec3 vfrag, vec3 colour, float fdist ){\n"
-"   float dist = pow(fdist*0.0010,0.78);\n"
-"   return mix( vfrag, colour, min( 1.0, dist ) );\n"
-"}\n"
-"\n"
-"vec3 scene_calculate_light( int light_index, \n"
-"                            vec3 halfview, vec3 co, vec3 normal )\n"
-"{\n"
-"   vec4 light_colour = texelFetch( uLightsArray, light_index+0 );\n"
-"   vec4 light_co     = texelFetch( uLightsArray, light_index+1 );\n"
-"   vec4 light_dir    = texelFetch( uLightsArray, light_index+2 );\n"
-"\n"
-"   vec3 light_delta = light_co.xyz-co;\n"
-"   float dist2 = dot(light_delta,light_delta);\n"
-"\n"
-"   light_delta = normalize( light_delta );\n"
-"\n"
-"   float quadratic = dist2*100.0;\n"
-"   float attenuation  = 1.0/( 1.0 + quadratic );\n"
-"         attenuation *= max( dot( light_delta, normal ), 0.0 );\n"
-"\n"
-"   float falloff = max( 0.0, 1.0-(dist2*light_co.w) );\n"
-"\n"
-"   if( light_dir.w < 0.999999 ){\n"
-"      float spot_theta = max( 0.0, dot( light_delta, -light_dir.xyz ) );\n"
-"      falloff *= max( 0.0, (spot_theta - light_dir.w) / (1.0-light_dir.w) );\n"
-"   }\n"
-"\n"
-"   return light_colour.rgb * attenuation * falloff \n"
-"            * step( g_day_phase, light_colour.w );\n"
-"}\n"
-"\n"
-"vec3 scene_calculate_packed_light_patch( uint packed_index, \n"
-"                                         vec3 halfview, vec3 co, vec3 normal )\n"
-"{\n"
-"   uint light_count = packed_index & 0x3u;\n"
-"\n"
-"   vec3 l = vec3(0.0);\n"
-"\n"
-"   if( light_count >= 1u ){\n"
-"      int index_0 = int( ((packed_index >>  2u) & 0x3ffu) * 3u );\n"
-"      int index_1 = int( ((packed_index >> 12u) & 0x3ffu) * 3u );\n"
-"      int index_2 = int( ((packed_index >> 22u) & 0x3ffu) * 3u );\n"
-"\n"
-"      l += scene_calculate_light( index_0, halfview, co, normal );\n"
-"\n"
-"      if( light_count >= 2u ){\n"
-"         l += scene_calculate_light( index_1, halfview, co, normal );\n"
-"\n"
-"         if( light_count >= 3u ){\n"
-"            l += scene_calculate_light( index_2, halfview, co, normal );\n"
-"         }\n"
-"      }\n"
-"   }\n"
-"\n"
-"   return l;\n"
-"}\n"
-"\n"
-"vec3 world_compute_lighting( vec3 diffuse, vec3 normal, vec3 co,\n"
-"                             float light_mask )\n"
-"{\n"
-"   if( g_light_preview == 1 )\n"
-"      diffuse = vec3(0.75);\n"
-"\n"
-"   // Lighting\n"
-"   vec3 halfview = uCamera - co;\n"
-"   float fdist = length(halfview);\n"
-"   halfview /= fdist;\n"
-"\n"
-"   float world_shadow = newlight_compute_sun_shadow( \n"
-"               co, g_sun_dir.xyz * (1.0/(max(g_sun_dir.y,0.0)+0.2)) );\n"
-"\n"
-"   vec3 total_light = clearskies_lighting( \n"
-"                           normal, min( light_mask, world_shadow ), halfview );\n"
-"\n"
-"   vec3 cube_coord = (co - g_cube_min.xyz) * g_cube_inv_range.xyz;\n"
-"        cube_coord = floor( cube_coord );\n"
-"\n"
-"   if( g_debug_indices == 1 )\n"
-"   {\n"
-"      return rand33(cube_coord);\n"
-"   }\n"
-"\n"
-"   if( g_debug_complexity == 1 )\n"
-"   {\n"
-"      ivec3 coord = ivec3( cube_coord );\n"
-"      uvec4 index_sample = texelFetch( uLightsIndex, coord, 0 );\n"
-"\n"
-"      uint light_count = (index_sample.x & 0x3u) + (index_sample.y & 0x3u);\n"
-"      return vec3( float(light_count)*(1.0/6.0), 0.0, 0.5 );\n"
-"   }\n"
-"\n"
-"   // FIXME: this coord should absolutely must be clamped!\n"
-"   \n"
-"   ivec3 coord = ivec3( cube_coord );\n"
-"   uvec4 index_sample = texelFetch( uLightsIndex, coord, 0 );\n"
-"\n"
-"   total_light += \n"
-"      scene_calculate_packed_light_patch( index_sample.x,\n"
-"                                          halfview, co, normal ) \n"
-"                                          * light_mask;\n"
-"   total_light += \n"
-"      scene_calculate_packed_light_patch( index_sample.y,\n"
-"                                          halfview, co, normal )\n"
-"                                          * light_mask;\n"
-"\n"
-"   // Take a section of the sky function to give us a matching fog colour\n"
-"\n"
-"   vec3 fog_colour  = clearskies_ambient( -halfview );\n"
-"   float sun_theta  = dot( -halfview, g_sun_dir.xyz );\n"
-"   float sun_size   = max( 0.0, sun_theta * 0.5 + 0.5 );\n"
-"   float sun_shape  = sun_size * max(g_sun_dir.y,0.0) * 0.5;\n"
-"         \n"
-"   vec3 sun_colour  = mix( vec3(1.0), g_sunset_colour.rgb, g_sunset_phase*0.5 );\n"
-"        sun_colour *= sun_shape;\n"
-"\n"
-"   fog_colour += sun_colour;\n"
-"   return scene_apply_fog( diffuse * total_light, fog_colour, fdist );\n"
-"}\n"
-"\n"
-"#line      9        0 \n"
-"\n"
-"float sdLine( vec3 p, vec3 a, vec3 b )\n"
-"{\n"
-"  vec3 pa = p - a;\n"
-"  vec3 ba = b - a;\n"
-"\n"
-"  float h = clamp( dot(pa,ba)/dot(ba,ba), 0.0, 1.0 );\n"
-"  return length( pa - ba*h );\n"
-"}\n"
-"\n"
-"float compute_board_shadow()\n"
-"{\n"
-"   // player shadow\n"
-"   float dist_to_player = max( 0.0, sdLine( aWorldCo, g_board_0.xyz,\n"
-"                                                      g_board_1.xyz )-0.1 );\n"
-"   float player_shadow = max( 1.0-dist_to_player*2.7, 0.0 );\n"
-"   player_shadow *= player_shadow*player_shadow*player_shadow;\n"
-"\n"
-"   return 1.0 - player_shadow*0.8;\n"
-"}\n"
-"\n"
-"vec3 scene_compute_lighting( vec3 diffuse, vec3 normal, vec3 co )\n"
-"{\n"
-"   return world_compute_lighting( diffuse, normal, co, compute_board_shadow() );\n"
-"}\n"
-"\n"
-"#line     17        0 \n"
-"#line       1        3 \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     18        0 \n"
-"\n"
-"vec4 water_surf( vec3 halfview, vec3 vnorm, float depthvalue, \n"
-"                 vec4 beneath, vec4 above )\n"
-"{\n"
-"   vec3 surface_tint = mix(uShoreColour, uOceanColour, depthvalue);\n"
-"\n"
-"   float ffresnel = pow(1.0-dot( vnorm, halfview ),5.0);\n"
-"\n"
-"   vec3 lightdir = vec3(0.95,0.0,-0.3);\n"
-"   vec3 specdir = reflect( -lightdir, vnorm );\n"
-"   float spec = pow(max(dot(halfview,specdir),0.0),20.0)*0.3;\n"
-"   \n"
-"   // Depth \n"
-"   float depthblend = pow( beneath.r, 0.8 );\n"
-"\n"
-"   // Composite\n"
-"   vec3 vsurface = mix(surface_tint, above.rgb, ffresnel );\n"
-"   //vsurface += spec;\n"
-"\n"
-"   return vec4( vsurface,depthblend );\n"
-"}\n"
-"\n"
-"void main()\n"
-"{\n"
-"   compute_motion_vectors();\n"
-"\n"
-"   // Create texture coords\n"
-"   vec2 ssuv = gl_FragCoord.xy*uInvRes;\n"
-"   \n"
-"   // Surface colour composite\n"
-"   float depthvalue = clamp( -world_water_depth(aCo)*(1.0/25.0), 0.0,1.0 );\n"
-"\n"
-"   vec2 world_coord = aCo.xz * 0.008;\n"
-"   vec4 time_offsets = vec4( uTime ) * vec4( 0.008, 0.006, 0.003, 0.03 );\n"
-"   vec4 dudva = texture( uTexDudv, world_coord + time_offsets.xy )-0.5;\n"
-"   vec4 dudvb = texture( uTexDudv, world_coord *7.0 - time_offsets.zw )-0.5;\n"
-"\n"
-"   vec3 surfnorm = dudva.rgb + dudvb.rgb;\n"
-"   surfnorm = normalize(vec3(0.0,1.0,0.0) + dudva.xyz*0.4 + dudvb.xyz*0.1);\n"
-"   \n"
-"   // Foam\n"
-"   float fband = fract( aCo.z*0.02+uTime*0.1+depthvalue*10.0 );\n"
-"   fband = step( fband+dudva.a*0.8, 0.3 ) * max((1.0-depthvalue*4.0),0.0);\n"
-"\n"
-"   // Lighting\n"
-"   vec3 halfview = -normalize( aCo-uCamera );\n"
-"\n"
-"   // Sample textures\n"
-"   vec4 above = texture( uTexMain, ssuv+ surfnorm.xz*0.2 );\n"
-"   vec4 beneath = texture( uTexBack, ssuv );\n"
-"\n"
-"   // Fog\n"
-"   float fdist = pow(length( aCo.xz-uCamera.xz ) * 0.00047, 2.6);\n"
-"\n"
-"   // Composite\n"
-"   vec4 vsurface = water_surf( halfview, surfnorm, depthvalue, beneath, above );\n"
-"   vsurface.a -= fdist;\n"
-"   oColour = mix( vsurface, vec4(1.0,1.0,1.0,0.5), fband );\n"
-"   oColour.rgb = scene_compute_lighting( oColour.rgb, aNorm.xyz, aWorldCo );\n"
-"}\n"
-""},
-};
-
-static GLuint _uniform_scene_water_uMdl;
-static GLuint _uniform_scene_water_uPv;
-static GLuint _uniform_scene_water_uPvmPrev;
-static GLuint _uniform_scene_water_uTexMain;
-static GLuint _uniform_scene_water_uTexDudv;
-static GLuint _uniform_scene_water_uTexBack;
-static GLuint _uniform_scene_water_uInvRes;
-static GLuint _uniform_scene_water_uTime;
-static GLuint _uniform_scene_water_uCamera;
-static GLuint _uniform_scene_water_uSurfaceY;
-static GLuint _uniform_scene_water_uBoard0;
-static GLuint _uniform_scene_water_uBoard1;
-static GLuint _uniform_scene_water_uShoreColour;
-static GLuint _uniform_scene_water_uOceanColour;
-static GLuint _uniform_scene_water_g_world_depth;
-static GLuint _uniform_scene_water_uLightsArray;
-static GLuint _uniform_scene_water_uLightsIndex;
-static void shader_scene_water_uMdl(m4x3f m){
-   glUniformMatrix4x3fv(_uniform_scene_water_uMdl,1,GL_FALSE,(float*)m);
+   glUniformMatrix4x3fv(_uniform_scene_water_uMdl,1,GL_FALSE,(f32*)m);
 }
-static void shader_scene_water_uPv(m4x4f m){
-   glUniformMatrix4fv(_uniform_scene_water_uPv,1,GL_FALSE,(float*)m);
+static inline void shader_scene_water_uPv(m4x4f m)
+{
+   glUniformMatrix4fv(_uniform_scene_water_uPv,1,GL_FALSE,(f32*)m);
 }
-static void shader_scene_water_uPvmPrev(m4x4f m){
-   glUniformMatrix4fv(_uniform_scene_water_uPvmPrev,1,GL_FALSE,(float*)m);
+static inline void shader_scene_water_uPvmPrev(m4x4f m)
+{
+   glUniformMatrix4fv(_uniform_scene_water_uPvmPrev,1,GL_FALSE,(f32*)m);
 }
-static void shader_scene_water_uTexMain(int i){
+static inline void shader_scene_water_uTexMain(int i)
+{
    glUniform1i(_uniform_scene_water_uTexMain,i);
 }
-static void shader_scene_water_uTexDudv(int i){
+static inline void shader_scene_water_uTexDudv(int i)
+{
    glUniform1i(_uniform_scene_water_uTexDudv,i);
 }
-static void shader_scene_water_uTexBack(int i){
+static inline void shader_scene_water_uTexBack(int i)
+{
    glUniform1i(_uniform_scene_water_uTexBack,i);
 }
-static void shader_scene_water_uInvRes(v2f v){
+static inline void shader_scene_water_uInvRes(v2f v)
+{
    glUniform2fv(_uniform_scene_water_uInvRes,1,v);
 }
-static void shader_scene_water_uTime(float f){
+static inline void shader_scene_water_uTime(f32 f)
+{
    glUniform1f(_uniform_scene_water_uTime,f);
 }
-static void shader_scene_water_uCamera(v3f v){
+static inline void shader_scene_water_uCamera(v3f v)
+{
    glUniform3fv(_uniform_scene_water_uCamera,1,v);
 }
-static void shader_scene_water_uSurfaceY(float f){
+static inline void shader_scene_water_uSurfaceY(f32 f)
+{
    glUniform1f(_uniform_scene_water_uSurfaceY,f);
 }
-static void shader_scene_water_uBoard0(v3f v){
+static inline void shader_scene_water_uBoard0(v3f v)
+{
    glUniform3fv(_uniform_scene_water_uBoard0,1,v);
 }
-static void shader_scene_water_uBoard1(v3f v){
+static inline void shader_scene_water_uBoard1(v3f v)
+{
    glUniform3fv(_uniform_scene_water_uBoard1,1,v);
 }
-static void shader_scene_water_uShoreColour(v3f v){
+static inline void shader_scene_water_uShoreColour(v3f v)
+{
    glUniform3fv(_uniform_scene_water_uShoreColour,1,v);
 }
-static void shader_scene_water_uOceanColour(v3f v){
+static inline void shader_scene_water_uOceanColour(v3f v)
+{
    glUniform3fv(_uniform_scene_water_uOceanColour,1,v);
 }
-static void shader_scene_water_g_world_depth(int i){
+static inline void shader_scene_water_g_world_depth(int i)
+{
    glUniform1i(_uniform_scene_water_g_world_depth,i);
 }
-static void shader_scene_water_register(void){
-   vg_shader_register( &_shader_scene_water );
-}
-static void shader_scene_water_use(void){ glUseProgram(_shader_scene_water.id); }
-static void shader_scene_water_link(void){
-   _uniform_scene_water_uMdl = glGetUniformLocation( _shader_scene_water.id, "uMdl" );
-   _uniform_scene_water_uPv = glGetUniformLocation( _shader_scene_water.id, "uPv" );
-   _uniform_scene_water_uPvmPrev = glGetUniformLocation( _shader_scene_water.id, "uPvmPrev" );
-   _uniform_scene_water_uTexMain = glGetUniformLocation( _shader_scene_water.id, "uTexMain" );
-   _uniform_scene_water_uTexDudv = glGetUniformLocation( _shader_scene_water.id, "uTexDudv" );
-   _uniform_scene_water_uTexBack = glGetUniformLocation( _shader_scene_water.id, "uTexBack" );
-   _uniform_scene_water_uInvRes = glGetUniformLocation( _shader_scene_water.id, "uInvRes" );
-   _uniform_scene_water_uTime = glGetUniformLocation( _shader_scene_water.id, "uTime" );
-   _uniform_scene_water_uCamera = glGetUniformLocation( _shader_scene_water.id, "uCamera" );
-   _uniform_scene_water_uSurfaceY = glGetUniformLocation( _shader_scene_water.id, "uSurfaceY" );
-   _uniform_scene_water_uBoard0 = glGetUniformLocation( _shader_scene_water.id, "uBoard0" );
-   _uniform_scene_water_uBoard1 = glGetUniformLocation( _shader_scene_water.id, "uBoard1" );
-   _uniform_scene_water_uShoreColour = glGetUniformLocation( _shader_scene_water.id, "uShoreColour" );
-   _uniform_scene_water_uOceanColour = glGetUniformLocation( _shader_scene_water.id, "uOceanColour" );
-   _uniform_scene_water_g_world_depth = glGetUniformLocation( _shader_scene_water.id, "g_world_depth" );
-   _uniform_scene_water_uLightsArray = glGetUniformLocation( _shader_scene_water.id, "uLightsArray" );
-   _uniform_scene_water_uLightsIndex = glGetUniformLocation( _shader_scene_water.id, "uLightsIndex" );
+static inline void shader_scene_water_use(void);
+static inline void shader_scene_water_use(void)
+{
+   glUseProgram(_shader_scene_water.id);
 }
-#endif /* SHADER_scene_water_H */
index ac987dd5204c6f15feb79c77bc4d6fff46469757..e0f1b4c1c2641ca0483051e7f36dee4bae2fa829 100644 (file)
-#ifndef SHADER_scene_water_fast_H
-#define SHADER_scene_water_fast_H
-static void shader_scene_water_fast_link(void);
-static void shader_scene_water_fast_register(void);
-static struct vg_shader _shader_scene_water_fast = {
-   .name = "scene_water_fast",
-   .link = shader_scene_water_fast_link,
-   .vs = 
+#pragma once
+#include "vg/vg_engine.h"
+extern struct vg_shader _shader_scene_water_fast;
+extern GLuint _uniform_scene_water_fast_uMdl;
+extern GLuint _uniform_scene_water_fast_uPv;
+extern GLuint _uniform_scene_water_fast_uPvmPrev;
+extern GLuint _uniform_scene_water_fast_uTexDudv;
+extern GLuint _uniform_scene_water_fast_uTime;
+extern GLuint _uniform_scene_water_fast_uCamera;
+extern GLuint _uniform_scene_water_fast_uSurfaceY;
+extern GLuint _uniform_scene_water_fast_uBoard0;
+extern GLuint _uniform_scene_water_fast_uBoard1;
+extern GLuint _uniform_scene_water_fast_uShoreColour;
+extern GLuint _uniform_scene_water_fast_uOceanColour;
+extern GLuint _uniform_scene_water_fast_g_world_depth;
+extern GLuint _uniform_scene_water_fast_uLightsArray;
+extern GLuint _uniform_scene_water_fast_uLightsIndex;
+static inline void shader_scene_water_fast_uMdl(m4x3f m)
 {
-.orig_file = "shaders/scene.vs",
-.static_src = 
-"layout (location=0) in vec3  a_co;\n"
-"layout (location=1) in vec4  a_norm;\n"
-"layout (location=2) in vec2  a_uv;\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      6        0 \n"
-"\n"
-"uniform mat4x3 uMdl;\n"
-"uniform mat4   uPv;\n"
-"uniform mat4   uPvmPrev;\n"
-"\n"
-"out vec2 aUv;\n"
-"out vec4 aNorm;\n"
-"out vec3 aCo;\n"
-"out vec3 aWorldCo;\n"
-"\n"
-"void main()\n"
-"{\n"
-"   vec3 world_pos0 = uMdl     * vec4( a_co, 1.0 );\n"
-"   vec4 vproj0     = uPv      * vec4( world_pos0, 1.0 );\n"
-"   vec4 vproj1     = uPvmPrev * vec4( a_co, 1.0 );\n"
-"\n"
-"   vs_motion_out( vproj0, vproj1 );\n"
-"\n"
-"   gl_Position = vproj0;\n"
-"\n"
-"   aUv = a_uv;\n"
-"   aNorm = vec4( mat3(uMdl) * a_norm.xyz, a_norm.w );\n"
-"   aCo = a_co;\n"
-"   aWorldCo = world_pos0;\n"
-"}\n"
-""},
-   .fs = 
-{
-.orig_file = "shaders/scene_water_fast.fs",
-.static_src = 
-"uniform sampler2D uTexDudv;\n"
-"\n"
-"uniform float uTime;\n"
-"uniform vec3 uCamera;\n"
-"uniform float uSurfaceY;\n"
-"uniform vec3 uBoard0;\n"
-"uniform vec3 uBoard1;\n"
-"\n"
-"uniform vec3 uShoreColour;\n"
-"uniform vec3 uOceanColour;\n"
-"\n"
-"#line       1        1 \n"
-"// :D\n"
-"const float CLEARSKIES_LIGHT_DOT_MIN = 0.0;\n"
-"\n"
-"#line     13        0 \n"
-"#line       1        2 \n"
-"// :D\n"
-"\n"
-"in vec2 aUv;\n"
-"in vec4 aNorm;\n"
-"in vec3 aCo;\n"
-"in vec3 aWorldCo;\n"
-"\n"
-"#line       1        1 \n"
-"layout (location = 0) out vec4 oColour;\n"
-"\n"
-"// OpenGL wiki: Recommends do not use vec3 because of drivers. hence the v4s...\n"
-"layout (std140) uniform ub_world_lighting\n"
-"{\n"
-"   vec4 g_cube_min;\n"
-"   vec4 g_cube_inv_range;\n"
-"\n"
-"   vec4 g_water_plane;\n"
-"   vec4 g_depth_bounds;\n"
-"\n"
-"   vec4 g_daysky_colour;\n"
-"   vec4 g_nightsky_colour;\n"
-"   vec4 g_sunset_colour;\n"
-"   vec4 g_ambient_colour;\n"
-"   vec4 g_sunset_ambient;\n"
-"   vec4 g_sun_colour;\n"
-"   vec4 g_sun_dir;\n"
-"   vec4 g_board_0;\n"
-"   vec4 g_board_1;\n"
-"\n"
-"   float g_water_fog;\n"
-"   float g_time;\n"
-"   float g_realtime;\n"
-"   float g_shadow_length;\n"
-"   float g_shadow_spread;\n"
-"\n"
-"   float g_time_of_day;\n"
-"   float g_day_phase;\n"
-"   float g_sunset_phase;\n"
-"\n"
-"   int g_light_preview;\n"
-"   int g_shadow_samples;\n"
-"\n"
-"   int g_debug_indices;\n"
-"   int g_debug_complexity;\n"
-"};\n"
-"\n"
-"uniform sampler2D g_world_depth;\n"
-"uniform samplerBuffer uLightsArray;\n"
-"uniform usampler3D uLightsIndex;\n"
-"\n"
-"#line       1        1 \n"
-"//const vec3  DAYSKY_COLOUR   = vec3( 0.37, 0.54, 0.97 );\n"
-"//const vec3  NIGHTSKY_COLOUR = vec3( 0.03, 0.05, 0.20 );\n"
-"//const vec3  SUNSET_COLOUR   = vec3( 1.00, 0.32, 0.01 );\n"
-"//const vec3  AMBIENT_COLOUR  = vec3( 0.13, 0.17, 0.35 );\n"
-"//const vec3  SUNSET_AMBIENT  = vec3( 0.25, 0.17, 0.51 );\n"
-"//const vec3  SUN_COLOUR      = vec3( 1.10, 0.89, 0.35 );\n"
-"\n"
-"const float SUN_ANGLE       = 0.0001;\n"
-"const float PI              = 3.14159265358979323846264;\n"
-"\n"
-"//struct world_info\n"
-"//{\n"
-"//   float time,\n"
-"//         time_of_day,\n"
-"//         day_phase,\n"
-"//         sunset_phase;\n"
-"//   \n"
-"//   vec3 sun_dir;\n"
-"//};\n"
-"\n"
-"vec3 rand33(vec3 p3)\n"
-"{\n"
-"      p3 = fract(p3 * vec3(.1031, .1030, .0973));\n"
-"   p3 += dot(p3, p3.yxz+33.33);\n"
-"   return fract((p3.xxy + p3.yxx)*p3.zyx);\n"
-"}\n"
-"\n"
-"float stars( vec3 rd, float rr, float size ){\n"
-"   vec3 co = rd * rr;\n"
-"\n"
-"   float a = atan(co.y, length(co.xz)) + 4.0 * PI;\n"
-"\n"
-"   float spaces = 1.0 / rr;\n"
-"   size = (rr * 0.0015) * fwidth(a) * 1000.0 * size;\n"
-"   a -= mod(a, spaces) - spaces * 0.5;\n"
-"\n"
-"   float count = floor(sqrt(pow(rr, 2.0) * (1.0 - pow(sin(a), 2.0))) * 3.0);\n"
-"   \n"
-"   float plane = atan(co.z, co.x) + 4.0 * PI;\n"
-"   plane = plane - mod(plane, PI / count);\n"
-"\n"
-"   vec2 delta = rand33(vec3(plane, a, 0.0)).xy;\n"
-"\n"
-"   float level = sin(a + spaces * (delta.y - 0.5) * (1.0 - size)) * rr;\n"
-"   float ydist = sqrt(rr * rr - level * level);\n"
-"   float angle = plane + (PI * (delta.x * (1.0-size) + size * 0.5) / count);\n"
-"   vec3 center = vec3(cos(angle) * ydist, level, sin(angle) * ydist);\n"
-"   float star = smoothstep(size, 0.0, distance(center, co));\n"
-"   return star;\n"
-"}\n"
-"\n"
-"float luminance( vec3 v )\n"
-"{\n"
-"   return dot( v, vec3(0.2126, 0.7152, 0.0722) );\n"
-"}\n"
-"\n"
-"vec3 clearskies_ambient( vec3 dir )\n"
-"{\n"
-"   float sun_azimuth  = g_sunset_phase * (dot( dir.xz, g_sun_dir.xz )*0.4+0.6);\n"
-"   float sky_gradient = dir.y;\n"
-"   \n"
-"   /* Blend phase colours */\n"
-"   vec3 ambient  = g_daysky_colour.rgb   * (g_day_phase-g_sunset_phase*0.1);\n"
-"        ambient += g_sunset_colour.rgb   * (1.0-dir.y*0.5)*sun_azimuth;\n"
-"        ambient += g_nightsky_colour.rgb * (1.0-g_day_phase);\n"
-"   \n"
-"   /* Add gradient */\n"
-"        ambient -= sky_gradient * luminance(ambient);\n"
-"        \n"
-"   return ambient;\n"
-"}\n"
-"\n"
-"vec3 clearskies_sky( vec3 ray_dir )\n"
-"{\n"
-"   ray_dir.y = abs( ray_dir.y );\n"
-"   vec3 sky_colour  = clearskies_ambient( ray_dir );\n"
-"   \n"
-"   /* Sun */\n"
-"   float sun_theta  = dot( ray_dir, g_sun_dir.xyz );\n"
-"   float sun_size   = max( 0.0, sun_theta * 0.5 + 0.5 + SUN_ANGLE );\n"
-"   float sun_shape  = pow( sun_size, 2000.0 );\n"
-"         sun_shape += sun_size * max(g_sun_dir.y,0.0) * 0.5;\n"
-"         \n"
-"   vec3 sun_colour  = mix( vec3(1.0), g_sunset_colour.rgb, g_sunset_phase*0.5 );\n"
-"        sun_colour *= sun_shape;\n"
-"\n"
-"   \n"
-"   float star = 0.0;\n"
-"   float star_blend = 10.0*max(0.0,(1.0-g_day_phase*2.0));\n"
-"\n"
-"   if( star_blend > 0.001 ){\n"
-"      for( float j = 1.0; j <= 4.1; j += 1.0 ){\n"
-"         float m = mix(0.6, 0.9, smoothstep(1.0, 2.0, j));\n"
-"         star += stars( ray_dir, 1.94 * pow( 1.64, j ), m ) * (1.0/pow(4.0, j));\n"
-"      }\n"
-"   }\n"
-"   \n"
-"   vec3 composite   = sky_colour + sun_colour + star*star_blend;\n"
-"   return composite;\n"
-"}\n"
-"\n"
-"vec3 clearskies_lighting( vec3 normal, float shadow, vec3 halfview )\n"
-"{\n"
-"   float fresnel = 1.0 - abs(dot(normal,halfview));\n"
-"\n"
-"   vec3  reflect_colour = mix( g_daysky_colour.rgb, g_sunset_colour.rgb, \n"
-"                               g_sunset_phase );\n"
-"\n"
-"   vec3  sky_reflection = 0.5 * fresnel * reflect_colour;\n"
-"   vec3  light_sun      = max( CLEARSKIES_LIGHT_DOT_MIN, \n"
-"                               dot(normal,g_sun_dir.xyz)*0.75+0.25\n"
-"                           ) * g_sun_colour.rgb * g_day_phase;\n"
-"\n"
-"   float scaled_shadow = max( shadow, 1.0 - max(g_sun_dir.y,0.0) );\n"
-"   vec3 ambient = mix( g_ambient_colour.rgb, g_sunset_ambient.rgb, \n"
-"                       g_sunset_phase );\n"
-"\n"
-"   return ambient + (light_sun + sky_reflection) * shadow;\n"
-"}\n"
-"\n"
-"#line     44        0 \n"
-"\n"
-"float world_depth_sample( vec3 pos )\n"
-"{\n"
-"   vec2 depth_coord = (pos.xz - g_depth_bounds.xy) * g_depth_bounds.zw; \n"
-"   return texture( g_world_depth, depth_coord ).r;\n"
-"}\n"
-"\n"
-"float world_water_depth( vec3 pos )\n"
-"{\n"
-"   float ref_depth = g_water_plane.y*g_water_plane.w;\n"
-"   return world_depth_sample( pos ) - ref_depth;\n"
-"}\n"
-"\n"
-"float shadow_sample( vec3 co ){\n"
-"   float height_sample = world_depth_sample( co );\n"
-"\n"
-"   float fdelta = height_sample - co.y;\n"
-"   return clamp( fdelta, 0.2, 0.4 )-0.2;\n"
-"}\n"
-"\n"
-"float newlight_compute_sun_shadow( vec3 co, vec3 dir ){\n"
-"   if( g_shadow_samples == 0 ){\n"
-"      return 1.0;\n"
-"   }\n"
-"\n"
-"   float fspread = g_shadow_spread;\n"
-"   float flength = g_shadow_length;\n"
-"\n"
-"   float famt = 0.0;\n"
-"   famt += shadow_sample(co+(dir+vec3(-0.56,0.55, 0.30)*fspread)*flength*0.1);\n"
-"   famt += shadow_sample(co+(dir+vec3( 0.80,0.68, 0.34)*fspread)*flength*0.2);\n"
-"   famt += shadow_sample(co+(dir+vec3( 0.78,0.07,-0.06)*fspread)*flength*0.3);\n"
-"   famt += shadow_sample(co+(dir+vec3(-0.59,0.07,-0.42)*fspread)*flength*0.4);\n"
-"\n"
-"   //famt+=shadow_sample(co+(dir+vec3(-0.790,-0.933,-0.875)*fspread)*flength*0.5);\n"
-"   //famt+=shadow_sample(co+(dir+vec3( 0.807,-0.690, 0.472)*fspread)*flength*0.6);\n"
-"   //famt+=shadow_sample(co+(dir+vec3( 0.522,-0.379, 0.350)*fspread)*flength*0.7);\n"
-"   //famt+=shadow_sample(co+(dir+vec3( 0.483, 0.201, 0.306)*fspread)*flength*0.8);\n"
-"\n"
-"   return 1.0 - famt;\n"
-"}\n"
-"\n"
-"float newlight_specular( vec3 wnormal, vec3 dir, vec3 halfview, float exponent )\n"
-"{\n"
-"   vec3 specdir = reflect( -dir, wnormal );\n"
-"   return pow(max(dot( halfview, specdir ), 0.0), exponent);\n"
-"}\n"
-"\n"
-"vec3 scene_apply_fog( vec3 vfrag, vec3 colour, float fdist ){\n"
-"   float dist = pow(fdist*0.0010,0.78);\n"
-"   return mix( vfrag, colour, min( 1.0, dist ) );\n"
-"}\n"
-"\n"
-"vec3 scene_calculate_light( int light_index, \n"
-"                            vec3 halfview, vec3 co, vec3 normal )\n"
-"{\n"
-"   vec4 light_colour = texelFetch( uLightsArray, light_index+0 );\n"
-"   vec4 light_co     = texelFetch( uLightsArray, light_index+1 );\n"
-"   vec4 light_dir    = texelFetch( uLightsArray, light_index+2 );\n"
-"\n"
-"   vec3 light_delta = light_co.xyz-co;\n"
-"   float dist2 = dot(light_delta,light_delta);\n"
-"\n"
-"   light_delta = normalize( light_delta );\n"
-"\n"
-"   float quadratic = dist2*100.0;\n"
-"   float attenuation  = 1.0/( 1.0 + quadratic );\n"
-"         attenuation *= max( dot( light_delta, normal ), 0.0 );\n"
-"\n"
-"   float falloff = max( 0.0, 1.0-(dist2*light_co.w) );\n"
-"\n"
-"   if( light_dir.w < 0.999999 ){\n"
-"      float spot_theta = max( 0.0, dot( light_delta, -light_dir.xyz ) );\n"
-"      falloff *= max( 0.0, (spot_theta - light_dir.w) / (1.0-light_dir.w) );\n"
-"   }\n"
-"\n"
-"   return light_colour.rgb * attenuation * falloff \n"
-"            * step( g_day_phase, light_colour.w );\n"
-"}\n"
-"\n"
-"vec3 scene_calculate_packed_light_patch( uint packed_index, \n"
-"                                         vec3 halfview, vec3 co, vec3 normal )\n"
-"{\n"
-"   uint light_count = packed_index & 0x3u;\n"
-"\n"
-"   vec3 l = vec3(0.0);\n"
-"\n"
-"   if( light_count >= 1u ){\n"
-"      int index_0 = int( ((packed_index >>  2u) & 0x3ffu) * 3u );\n"
-"      int index_1 = int( ((packed_index >> 12u) & 0x3ffu) * 3u );\n"
-"      int index_2 = int( ((packed_index >> 22u) & 0x3ffu) * 3u );\n"
-"\n"
-"      l += scene_calculate_light( index_0, halfview, co, normal );\n"
-"\n"
-"      if( light_count >= 2u ){\n"
-"         l += scene_calculate_light( index_1, halfview, co, normal );\n"
-"\n"
-"         if( light_count >= 3u ){\n"
-"            l += scene_calculate_light( index_2, halfview, co, normal );\n"
-"         }\n"
-"      }\n"
-"   }\n"
-"\n"
-"   return l;\n"
-"}\n"
-"\n"
-"vec3 world_compute_lighting( vec3 diffuse, vec3 normal, vec3 co,\n"
-"                             float light_mask )\n"
-"{\n"
-"   if( g_light_preview == 1 )\n"
-"      diffuse = vec3(0.75);\n"
-"\n"
-"   // Lighting\n"
-"   vec3 halfview = uCamera - co;\n"
-"   float fdist = length(halfview);\n"
-"   halfview /= fdist;\n"
-"\n"
-"   float world_shadow = newlight_compute_sun_shadow( \n"
-"               co, g_sun_dir.xyz * (1.0/(max(g_sun_dir.y,0.0)+0.2)) );\n"
-"\n"
-"   vec3 total_light = clearskies_lighting( \n"
-"                           normal, min( light_mask, world_shadow ), halfview );\n"
-"\n"
-"   vec3 cube_coord = (co - g_cube_min.xyz) * g_cube_inv_range.xyz;\n"
-"        cube_coord = floor( cube_coord );\n"
-"\n"
-"   if( g_debug_indices == 1 )\n"
-"   {\n"
-"      return rand33(cube_coord);\n"
-"   }\n"
-"\n"
-"   if( g_debug_complexity == 1 )\n"
-"   {\n"
-"      ivec3 coord = ivec3( cube_coord );\n"
-"      uvec4 index_sample = texelFetch( uLightsIndex, coord, 0 );\n"
-"\n"
-"      uint light_count = (index_sample.x & 0x3u) + (index_sample.y & 0x3u);\n"
-"      return vec3( float(light_count)*(1.0/6.0), 0.0, 0.5 );\n"
-"   }\n"
-"\n"
-"   // FIXME: this coord should absolutely must be clamped!\n"
-"   \n"
-"   ivec3 coord = ivec3( cube_coord );\n"
-"   uvec4 index_sample = texelFetch( uLightsIndex, coord, 0 );\n"
-"\n"
-"   total_light += \n"
-"      scene_calculate_packed_light_patch( index_sample.x,\n"
-"                                          halfview, co, normal ) \n"
-"                                          * light_mask;\n"
-"   total_light += \n"
-"      scene_calculate_packed_light_patch( index_sample.y,\n"
-"                                          halfview, co, normal )\n"
-"                                          * light_mask;\n"
-"\n"
-"   // Take a section of the sky function to give us a matching fog colour\n"
-"\n"
-"   vec3 fog_colour  = clearskies_ambient( -halfview );\n"
-"   float sun_theta  = dot( -halfview, g_sun_dir.xyz );\n"
-"   float sun_size   = max( 0.0, sun_theta * 0.5 + 0.5 );\n"
-"   float sun_shape  = sun_size * max(g_sun_dir.y,0.0) * 0.5;\n"
-"         \n"
-"   vec3 sun_colour  = mix( vec3(1.0), g_sunset_colour.rgb, g_sunset_phase*0.5 );\n"
-"        sun_colour *= sun_shape;\n"
-"\n"
-"   fog_colour += sun_colour;\n"
-"   return scene_apply_fog( diffuse * total_light, fog_colour, fdist );\n"
-"}\n"
-"\n"
-"#line      9        0 \n"
-"\n"
-"float sdLine( vec3 p, vec3 a, vec3 b )\n"
-"{\n"
-"  vec3 pa = p - a;\n"
-"  vec3 ba = b - a;\n"
-"\n"
-"  float h = clamp( dot(pa,ba)/dot(ba,ba), 0.0, 1.0 );\n"
-"  return length( pa - ba*h );\n"
-"}\n"
-"\n"
-"float compute_board_shadow()\n"
-"{\n"
-"   // player shadow\n"
-"   float dist_to_player = max( 0.0, sdLine( aWorldCo, g_board_0.xyz,\n"
-"                                                      g_board_1.xyz )-0.1 );\n"
-"   float player_shadow = max( 1.0-dist_to_player*2.7, 0.0 );\n"
-"   player_shadow *= player_shadow*player_shadow*player_shadow;\n"
-"\n"
-"   return 1.0 - player_shadow*0.8;\n"
-"}\n"
-"\n"
-"vec3 scene_compute_lighting( vec3 diffuse, vec3 normal, vec3 co )\n"
-"{\n"
-"   return world_compute_lighting( diffuse, normal, co, compute_board_shadow() );\n"
-"}\n"
-"\n"
-"#line     14        0 \n"
-"#line       1        3 \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     15        0 \n"
-"\n"
-"vec4 water_surf( vec3 halfview, vec3 vnorm, float depthvalue )\n"
-"{\n"
-"   vec3 surface_tint = mix(uShoreColour, uOceanColour, depthvalue);\n"
-"\n"
-"   float ffresnel = pow(1.0-dot( vnorm, halfview ),5.0);\n"
-"\n"
-"   vec3 lightdir = vec3(0.95,0.0,-0.3);\n"
-"   vec3 specdir = reflect( -lightdir, vnorm );\n"
-"   float spec = pow(max(dot(halfview,specdir),0.0),20.0)*0.3;\n"
-"   \n"
-"   return vec4( surface_tint + spec, max(min(depthvalue*4.0, 1.0),0.0) );\n"
-"}\n"
-"\n"
-"void main()\n"
-"{\n"
-"   compute_motion_vectors();\n"
-"\n"
-"   // Surface colour composite\n"
-"   float depthvalue = clamp( -world_water_depth( aCo )*(1.0/25.0), 0.0, 1.0 );\n"
-"\n"
-"   vec2 world_coord = aCo.xz * 0.008;\n"
-"   vec4 time_offsets = vec4( uTime ) * vec4( 0.008, 0.006, 0.003, 0.03 );\n"
-"   vec4 dudva = texture( uTexDudv, world_coord + time_offsets.xy )-0.5;\n"
-"   vec4 dudvb = texture( uTexDudv, world_coord *7.0 - time_offsets.zw )-0.5;\n"
-"\n"
-"   vec3 surfnorm = dudva.rgb + dudvb.rgb;\n"
-"   surfnorm = normalize(vec3(0.0,1.0,0.0) + dudva.xyz*0.4 + dudvb.xyz*0.1);\n"
-"   \n"
-"   // Foam\n"
-"   float fband = fract( aCo.z*0.02+uTime*0.1+depthvalue*10.0 );\n"
-"   fband = step( fband+dudva.a*0.8, 0.3 ) * max((1.0-depthvalue*4.0),0.0);\n"
-"\n"
-"   // Lighting\n"
-"   vec3 halfview = -normalize( aCo-uCamera );\n"
-"\n"
-"   // Fog\n"
-"   float fdist = pow(length( aCo.xz-uCamera.xz ) * 0.00047, 2.6);\n"
-"\n"
-"   // Composite\n"
-"   vec4 vsurface = water_surf( halfview, surfnorm, depthvalue );\n"
-"   vsurface.a -= fdist;\n"
-"   oColour = mix( vsurface, vec4(1.0,1.0,1.0,0.5), fband );\n"
-"   oColour.rgb = scene_compute_lighting( oColour.rgb, aNorm.xyz, aWorldCo );\n"
-"}\n"
-""},
-};
-
-static GLuint _uniform_scene_water_fast_uMdl;
-static GLuint _uniform_scene_water_fast_uPv;
-static GLuint _uniform_scene_water_fast_uPvmPrev;
-static GLuint _uniform_scene_water_fast_uTexDudv;
-static GLuint _uniform_scene_water_fast_uTime;
-static GLuint _uniform_scene_water_fast_uCamera;
-static GLuint _uniform_scene_water_fast_uSurfaceY;
-static GLuint _uniform_scene_water_fast_uBoard0;
-static GLuint _uniform_scene_water_fast_uBoard1;
-static GLuint _uniform_scene_water_fast_uShoreColour;
-static GLuint _uniform_scene_water_fast_uOceanColour;
-static GLuint _uniform_scene_water_fast_g_world_depth;
-static GLuint _uniform_scene_water_fast_uLightsArray;
-static GLuint _uniform_scene_water_fast_uLightsIndex;
-static void shader_scene_water_fast_uMdl(m4x3f m){
-   glUniformMatrix4x3fv(_uniform_scene_water_fast_uMdl,1,GL_FALSE,(float*)m);
+   glUniformMatrix4x3fv(_uniform_scene_water_fast_uMdl,1,GL_FALSE,(f32*)m);
 }
-static void shader_scene_water_fast_uPv(m4x4f m){
-   glUniformMatrix4fv(_uniform_scene_water_fast_uPv,1,GL_FALSE,(float*)m);
+static inline void shader_scene_water_fast_uPv(m4x4f m)
+{
+   glUniformMatrix4fv(_uniform_scene_water_fast_uPv,1,GL_FALSE,(f32*)m);
 }
-static void shader_scene_water_fast_uPvmPrev(m4x4f m){
-   glUniformMatrix4fv(_uniform_scene_water_fast_uPvmPrev,1,GL_FALSE,(float*)m);
+static inline void shader_scene_water_fast_uPvmPrev(m4x4f m)
+{
+   glUniformMatrix4fv(_uniform_scene_water_fast_uPvmPrev,1,GL_FALSE,(f32*)m);
 }
-static void shader_scene_water_fast_uTexDudv(int i){
+static inline void shader_scene_water_fast_uTexDudv(int i)
+{
    glUniform1i(_uniform_scene_water_fast_uTexDudv,i);
 }
-static void shader_scene_water_fast_uTime(float f){
+static inline void shader_scene_water_fast_uTime(f32 f)
+{
    glUniform1f(_uniform_scene_water_fast_uTime,f);
 }
-static void shader_scene_water_fast_uCamera(v3f v){
+static inline void shader_scene_water_fast_uCamera(v3f v)
+{
    glUniform3fv(_uniform_scene_water_fast_uCamera,1,v);
 }
-static void shader_scene_water_fast_uSurfaceY(float f){
+static inline void shader_scene_water_fast_uSurfaceY(f32 f)
+{
    glUniform1f(_uniform_scene_water_fast_uSurfaceY,f);
 }
-static void shader_scene_water_fast_uBoard0(v3f v){
+static inline void shader_scene_water_fast_uBoard0(v3f v)
+{
    glUniform3fv(_uniform_scene_water_fast_uBoard0,1,v);
 }
-static void shader_scene_water_fast_uBoard1(v3f v){
+static inline void shader_scene_water_fast_uBoard1(v3f v)
+{
    glUniform3fv(_uniform_scene_water_fast_uBoard1,1,v);
 }
-static void shader_scene_water_fast_uShoreColour(v3f v){
+static inline void shader_scene_water_fast_uShoreColour(v3f v)
+{
    glUniform3fv(_uniform_scene_water_fast_uShoreColour,1,v);
 }
-static void shader_scene_water_fast_uOceanColour(v3f v){
+static inline void shader_scene_water_fast_uOceanColour(v3f v)
+{
    glUniform3fv(_uniform_scene_water_fast_uOceanColour,1,v);
 }
-static void shader_scene_water_fast_g_world_depth(int i){
+static inline void shader_scene_water_fast_g_world_depth(int i)
+{
    glUniform1i(_uniform_scene_water_fast_g_world_depth,i);
 }
-static void shader_scene_water_fast_register(void){
-   vg_shader_register( &_shader_scene_water_fast );
-}
-static void shader_scene_water_fast_use(void){ glUseProgram(_shader_scene_water_fast.id); }
-static void shader_scene_water_fast_link(void){
-   _uniform_scene_water_fast_uMdl = glGetUniformLocation( _shader_scene_water_fast.id, "uMdl" );
-   _uniform_scene_water_fast_uPv = glGetUniformLocation( _shader_scene_water_fast.id, "uPv" );
-   _uniform_scene_water_fast_uPvmPrev = glGetUniformLocation( _shader_scene_water_fast.id, "uPvmPrev" );
-   _uniform_scene_water_fast_uTexDudv = glGetUniformLocation( _shader_scene_water_fast.id, "uTexDudv" );
-   _uniform_scene_water_fast_uTime = glGetUniformLocation( _shader_scene_water_fast.id, "uTime" );
-   _uniform_scene_water_fast_uCamera = glGetUniformLocation( _shader_scene_water_fast.id, "uCamera" );
-   _uniform_scene_water_fast_uSurfaceY = glGetUniformLocation( _shader_scene_water_fast.id, "uSurfaceY" );
-   _uniform_scene_water_fast_uBoard0 = glGetUniformLocation( _shader_scene_water_fast.id, "uBoard0" );
-   _uniform_scene_water_fast_uBoard1 = glGetUniformLocation( _shader_scene_water_fast.id, "uBoard1" );
-   _uniform_scene_water_fast_uShoreColour = glGetUniformLocation( _shader_scene_water_fast.id, "uShoreColour" );
-   _uniform_scene_water_fast_uOceanColour = glGetUniformLocation( _shader_scene_water_fast.id, "uOceanColour" );
-   _uniform_scene_water_fast_g_world_depth = glGetUniformLocation( _shader_scene_water_fast.id, "g_world_depth" );
-   _uniform_scene_water_fast_uLightsArray = glGetUniformLocation( _shader_scene_water_fast.id, "uLightsArray" );
-   _uniform_scene_water_fast_uLightsIndex = glGetUniformLocation( _shader_scene_water_fast.id, "uLightsIndex" );
+static inline void shader_scene_water_fast_use(void);
+static inline void shader_scene_water_fast_use(void)
+{
+   glUseProgram(_shader_scene_water_fast.id);
 }
-#endif /* SHADER_scene_water_fast_H */
index ee6090cd22847502989200d2608d7ecac984a2da..b9ab766b179cbef9b9a78dd511a21b52948b5bf5 100644 (file)
-#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 = 
+#pragma once
+#include "vg/vg_engine.h"
+extern struct vg_shader _shader_trail;
+extern GLuint _uniform_trail_uPv;
+extern GLuint _uniform_trail_uPvPrev;
+extern GLuint _uniform_trail_uColour;
+static inline void shader_trail_uPv(m4x4f m)
 {
-.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);
+   glUniformMatrix4fv(_uniform_trail_uPv,1,GL_FALSE,(f32*)m);
 }
-static void shader_trail_uPvPrev(m4x4f m){
-   glUniformMatrix4fv(_uniform_trail_uPvPrev,1,GL_FALSE,(float*)m);
+static inline void shader_trail_uPvPrev(m4x4f m)
+{
+   glUniformMatrix4fv(_uniform_trail_uPvPrev,1,GL_FALSE,(f32*)m);
 }
-static void shader_trail_uColour(v4f v){
+static inline 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" );
+static inline void shader_trail_use(void);
+static inline void shader_trail_use(void)
+{
+   glUseProgram(_shader_trail.id);
 }
-#endif /* SHADER_trail_H */
index fee0039dc2c05dcea491e3c64f261f87521f058c..8d79e9ebdabad3cbf85c0f20b8c47a3b33889933 100644 (file)
@@ -20,8 +20,8 @@
 #include "skaterift.h"
 #include "steam.h"
 #include "render.h"
-#include "audio.h"
 #include "vg/vg_opt.h"
+#include "vg/vg_loader.h"
 
 #include "world.h"
 
 #include "vehicle.h"
 #include "save.h"
 #include "player_remote.h"
-
-/*    unity build
- * ----------------- */
-
-#include "world.c"
-#include "player.c"
-#include "vehicle.c"
-#include "entity.c"
-#include "workshop.c"
-#include "addon.c"
-#include "save.c"
-#include "world_map.c"
-#include "network.c"
-#include "player_remote.c"
-#include "vg/vg_audio_dsp.h"
-#include "world_routes_ui.c"
-#include "particle.c"
-#include "player_effects.c"
-#include "freecam.c"
-#include "testing.c"
+#include "particle.h"
 #include "trail.h"
-#include "trail.c"
+#include "freecam.h"
+#include "ent_tornado.h"
+#include "ent_miniworld.h"
+#include "ent_skateshop.h"
+#include "world_map.h"
+#include "gui.h"
+#include "workshop.h"
+#include "audio.h"
+#include "player_render.h"
+
+struct skaterift_globals skaterift = 
+{ 
+   .op = k_async_op_clientloading, .time_rate = 1.0f, .demo_mode = 1,
+   .hub_world = "maps/dev_hub",
+};
 
 static int k_tools_mode = 0;
 
@@ -124,10 +119,10 @@ static void async_call_ready( void *payload, u32 size ){
    skaterift.op = k_async_op_none;
 }
 
-static void skaterift_restore_state(void){
+static void skaterift_restore_state(void)
+{
    savedata_file sav;
-   strcpy( sav.path, str_skaterift_main_save );
-   savedata_file_read( &sav );
+   skaterift_read_main_savedata( &sav );
 
    vg_msg kvsav;
    vg_msg_init( &kvsav, sav.buf, sizeof(sav.buf) );
@@ -193,9 +188,9 @@ static void skaterift_load_world_content(void){
 
 static void skaterift_load_player_content(void){
    u32 bytes = 1024*1024*10;
-   skaterift.replay.data = vg_linear_alloc( vg_mem.rtmemory, bytes );
-   skaterift.replay.size = bytes;
-   replay_clear( &skaterift.replay );
+   player_replay.local.data = vg_linear_alloc( vg_mem.rtmemory, bytes );
+   player_replay.local.size = bytes;
+   replay_clear( &player_replay.local );
 
    particle_alloc( &particles_grind, 300 );
    particle_alloc( &particles_env, 200 );
@@ -216,8 +211,6 @@ void vg_load(void)
    vg_audio.always_keep_compressed = 1;
 
    vg_console_reg_cmd( "load_world", skaterift_load_world_command, NULL );
-   vg_console_reg_cmd( "switch_active_instance", 
-                        skaterift_switch_instance_cmd, NULL );
    vg_console_reg_cmd( "fc", freecam_cmd, NULL );
    vg_console_reg_var( "immobile", &localplayer.immobile, k_var_dtype_i32, 0 );
 
@@ -225,7 +218,6 @@ void vg_load(void)
    vg_loader_step( menu_init, NULL );
    vg_loader_step( world_init, NULL );
    vg_loader_step( vehicle_init, NULL );
-   vg_loader_step( font3d_init, NULL );
    vg_loader_step( gui_init, NULL );
 
    vg_loader_step( player_init, NULL );
@@ -236,10 +228,6 @@ void vg_load(void)
    vg_loader_step( workshop_init, NULL );
    vg_loader_step( skateshop_init, NULL );
    vg_loader_step( ent_tornado_init, NULL );
-   vg_loader_step( testing_init, NULL );
-   vg_loader_step( trail_init, NULL );
-   vg_loader_step( particle_init, NULL );
-  
    vg_loader_step( skaterift_load_player_content, NULL );
 
    /* --------------------- */
@@ -284,7 +272,7 @@ static void draw_origin_axis(void){
    vg_line( (v3f){ 0.0f, 0.0f, 0.0f }, (v3f){ 0.0f, 1.0f, 0.0f }, 0xff00ff00 );
    vg_line( (v3f){ 0.0f, 0.0f, 0.0f }, (v3f){ 0.0f, 0.0f, 1.0f }, 0xff0000ff );
 }
-static void skaterift_change_client_world_preupdate(void);
+void skaterift_change_client_world_preupdate(void);
 
 /* 
  * UPDATE LOOP
@@ -336,7 +324,6 @@ void vg_fixed_update(void)
    world_routes_fixedupdate( world_current_instance() );
    player__update();
    vehicle_update_fixed();
-   testing_update();
 }
 
 void vg_post_update(void)
@@ -368,12 +355,7 @@ void vg_post_update(void)
    audio_unlock();
 
    vehicle_update_post();
-
-   if( vg.time - skaterift.last_autosave > 20.0 ){
-      if( skaterift_autosave(1) ){
-         skaterift.last_autosave = vg.time;
-      }
-   }
+   skaterift_autosave_update();
 }
 
 /*
@@ -415,10 +397,10 @@ static void present_view_with_post_processing(void){
       f32 glitch_strength = 0.0f;
       if( skaterift.activity == k_skaterift_replay ){
          glitch_strength = 0.005f;
-         if( skaterift.replay_control == k_replay_control_play )
+         if( player_replay.replay_control == k_replay_control_play )
             glitch_strength = 0.005f;
          else 
-            glitch_strength += 0.005f*skaterift.track_velocity;
+            glitch_strength += 0.005f*player_replay.track_velocity;
       }
       shader_blitblur_uGlitchStrength( glitch_strength );
 
@@ -443,7 +425,7 @@ static void present_view_with_post_processing(void){
 }
 
 static void render_player_transparent(void){
-   static camera small_cam;      /* DOES NOT NEED TO BE STATIC BUT MINGW 
+   static vg_camera small_cam;      /* DOES NOT NEED TO BE STATIC BUT MINGW 
                                     SAIS OTHERWISE */
 
    m4x3_copy( skaterift.cam.transform, small_cam.transform );
@@ -452,9 +434,9 @@ static void render_player_transparent(void){
    small_cam.nearz = 0.05f;
    small_cam.farz  = 60.0f;
 
-   camera_update_view( &small_cam );
-   camera_update_projection( &small_cam );
-   camera_finalize( &small_cam );
+   vg_camera_update_view( &small_cam );
+   vg_camera_update_projection( &small_cam );
+   vg_camera_finalize( &small_cam );
 
    /* Draw player to window buffer and blend background ontop */
    player__render( &small_cam );
@@ -562,18 +544,18 @@ static void render_scene(void){
 }
 
 static void skaterift_composite_maincamera(void){
-   camera_lerp( &localplayer.cam, &world_static.focus_cam,
+   vg_camera_lerp( &localplayer.cam, &world_static.focus_cam,
                 vg_smoothstepf(world_static.focus_strength), &skaterift.cam );
 
-   if( skaterift.freecam ){
+   if( player_replay.freecam ){
       freecam_preupdate();
-      v3_copy( skaterift.replay_freecam.pos, skaterift.cam.pos );
-      v3_copy( skaterift.replay_freecam.angles, skaterift.cam.angles );
-      skaterift.cam.fov = skaterift.replay_freecam.fov;
+      v3_copy( player_replay.replay_freecam.pos, skaterift.cam.pos );
+      v3_copy( player_replay.replay_freecam.angles, skaterift.cam.angles );
+      skaterift.cam.fov = player_replay.replay_freecam.fov;
    }
    else {
       if( skaterift.activity == k_skaterift_replay ){
-         replay_get_camera( &skaterift.replay, &skaterift.cam );
+         replay_get_camera( &player_replay.local, &skaterift.cam );
       }
    }
 
@@ -581,7 +563,7 @@ static void skaterift_composite_maincamera(void){
    skaterift.cam.farz  = 2100.0f;
 
    if( skaterift.activity == k_skaterift_world_map ){
-      camera_copy( &world_map.cam, &skaterift.cam );
+      vg_camera_copy( &world_map.cam, &skaterift.cam );
       skaterift.cam.nearz = 4.0f;
       skaterift.cam.farz = 3100.0f;
    }
@@ -597,19 +579,19 @@ static void skaterift_composite_maincamera(void){
       }
    }
 
-   camera_update_transform( &skaterift.cam );
-   camera_update_view( &skaterift.cam );
-   camera_update_projection( &skaterift.cam );
-   camera_finalize( &skaterift.cam );
+   vg_camera_update_transform( &skaterift.cam );
+   vg_camera_update_view( &skaterift.cam );
+   vg_camera_update_projection( &skaterift.cam );
+   vg_camera_finalize( &skaterift.cam );
 }
 
 static void render_main_game(void){
    if( skaterift.activity == k_skaterift_replay ){
-      player__animate_from_replay( &skaterift.replay );
+      player__animate_from_replay( &player_replay.local );
    }
    else{
       player__animate();
-      skaterift_record_frame( &skaterift.replay, 
+      skaterift_record_frame( &player_replay.local,
                               localplayer.deferred_frame_record );
       localplayer.deferred_frame_record = 0;
    }
@@ -653,7 +635,6 @@ static void render_main_game(void){
 
    /* composite */
    present_view_with_post_processing();
-
    skaterift_replay_post_render();
 }
 
@@ -741,3 +722,56 @@ void vg_gui(void)
       remote_players_imgui_world( world_current_instance(), vg.pv, 100.0f, 1 );
    }
 }
+
+#include "addon.c"
+#include "addon_types.c"
+#include "audio.c"
+#include "ent_challenge.c"
+#include "ent_glider.c"
+#include "entity.c"
+#include "ent_miniworld.c"
+#include "ent_objective.c"
+#include "ent_region.c"
+#include "ent_relay.c"
+#include "ent_route.c"
+#include "ent_skateshop.c"
+#include "ent_tornado.c"
+#include "ent_traffic.c"
+#include "freecam.c"
+#include "menu.c"
+#include "network.c"
+#include "particle.c"
+#include "player_basic_info.c"
+#include "player.c"
+#include "player_common.c"
+#include "player_dead.c"
+#include "player_drive.c"
+#include "player_effects.c"
+#include "player_glide.c"
+#include "player_ragdoll.c"
+#include "player_remote.c"
+#include "player_render.c"
+#include "player_replay.c"
+#include "player_skate.c"
+#include "player_walk.c"
+#include "render.c"
+#include "save.c"
+#include "scene.c"
+#include "steam.c"
+#include "trail.c"
+#include "vehicle.c"
+#include "workshop.c"
+#include "world_audio.c"
+#include "world.c"
+#include "world_entity.c"
+#include "world_gate.c"
+#include "world_gen.c"
+#include "world_load.c"
+#include "world_map.c"
+#include "world_physics.c"
+#include "world_render.c"
+#include "world_routes.c"
+#include "world_routes_ui.c"
+#include "world_sfd.c"
+#include "world_volumes.c"
+#include "world_water.c"
index 92a59637dee3f987cc33bc4649b366fd8915a07a..f3e025885e3d9722b77da23af45fdee181a8c054 100644 (file)
@@ -1,21 +1,19 @@
-#ifndef SKATERIFT_H
-#define SKATERIFT_H
-
+#pragma once
 #define SKATERIFT_APPID 2103940
-
 #include "vg/vg_engine.h"
-#include "world.h"
-#include "addon.h"
-#include "trail.h"
+#include "vg/vg_camera.h"
 
-enum skaterift_rt {
+enum skaterift_rt 
+{
    k_skaterift_rt_workshop_preview,
    k_skaterift_rt_server_status,
    k_skaterift_rt_max
 };
 
-struct{
-   enum async_operation{
+struct skaterift_globals
+{
+   enum async_operation
+   {
       k_async_op_none,
       k_async_op_clientloading,
       k_async_op_world_scan,
@@ -28,26 +26,8 @@ struct{
    op;
 
    f32 time_rate;
-   camera cam;
+   vg_camera cam;
    
-   replay_buffer replay;
-   replay_frame *resume_target;
-   f64 resume_begin;
-   f32 resume_transition;
-
-   enum replay_control {
-      k_replay_control_scrub,
-      k_replay_control_play,
-      k_replay_control_resume
-   }
-   replay_control;
-   f32 track_velocity;
-   struct gui_helper *helper_resume, *helper_freecam;
-
-   camera replay_freecam;
-   i32 freecam;
-   v3f freecam_v, freecam_w;
-
    enum skaterift_activity {
       k_skaterift_default    = 0x00,
       k_skaterift_replay     = 0x01,
@@ -56,28 +36,11 @@ struct{
       k_skaterift_world_map  = 0x08,
    }
    activity;
-
-   f64 last_autosave;
    GLuint rt_textures[k_skaterift_rt_max];
 
    u32 achievements;
    int demo_mode;
 
-   audio_channel *aud_air;
    const char *hub_world;
-
-   struct trail_system test_trail;
 }
-static skaterift = { 
-   .op = k_async_op_clientloading, .time_rate = 1.0f, .demo_mode = 1,
-   .hub_world = "maps/dev_hub",
-   .test_trail = {
-      .max = 80
-   }
-};
-
-/* Skaterift api */
-static void skaterift_change_world_start( addon_reg *reg );
-static int  skaterift_change_world_command( int argc, const char *argv[] );
-
-#endif /* SKATERIFT_H */
+extern skaterift;
index daa8fdcdab6418147062264d918c9fc94fee8cfe..9729b64c04a95b7b052ba1daa3f280f444670a44 100644 (file)
@@ -2,9 +2,8 @@
  * Copyright (C) 2021-2022 Mt.ZERO Software, Harry Godden - All Rights Reserved
  */
 
-#ifndef SKELETON_H
-#define SKELETON_H
-
+#pragma once
+#include "vg/vg_lines.h"
 #include "model.h"
 
 struct skeleton
@@ -584,5 +583,3 @@ static void skeleton_debug( struct skeleton *skele, m4x3f *final_mtx ){
          vg_line( p0, p1, 0xff00ffff );
    }
 }
-
-#endif /* SKELETON_H */
diff --git a/steam.c b/steam.c
new file mode 100644 (file)
index 0000000..a9484dd
--- /dev/null
+++ b/steam.c
@@ -0,0 +1,303 @@
+#include "vg/vg_steam.h"
+#include "vg/vg_steam_utils.h"
+#include "vg/vg_steam_networking.h"
+#include "vg/vg_steam_auth.h"
+#include "vg/vg_steam_http.h"
+#include "vg/vg_steam_friends.h"
+#include "vg/vg_steam_user_stats.h"
+#include "submodules/anyascii/impl/c/anyascii.c"
+#include "skaterift.h"
+#include <string.h>
+
+/*
+ * We only want to use steamworks if building for the networked version,
+ * theres not much point otherwise. We mainly want steamworks for setting
+ * achievements etc.. so that includes our own server too.
+ *
+ * This file also wraps the functions and interfaces that we want to use to 
+ * make them a bit easier to read, since they are the flat API they have very 
+ * long names. in non-networked builds they will return default errors or do
+ * nothing.
+ */
+
+char steam_username_at_startup[128] = "Unassigned";
+
+static void recv_steam_warning( int severity, const char *msg )
+{
+   if( severity == 0 )
+      vg_low( "%s\n", msg );
+   else
+      vg_info( "%s\n", msg );
+}
+
+int steam_ready = 0,
+    steam_stats_ready = 0;
+
+void *hSteamNetworkingSockets, *hSteamUser, *hSteamUserStats;
+static HSteamPipe hSteamClientPipe;
+
+static const char *steam_achievement_names[] = 
+{
+   "ALBERT", "MARC", "JANET", "BERNADETTA",
+   "ROUTE_MPY", "ROUTE_MPG", "ROUTE_MPB", "ROUTE_MPR",
+   "ROUTE_TO", "ROUTE_TC", "CITY_COMPLETE", "MTZERO_SILVER", "MTZERO_GOLD",
+   "80FT"
+};
+
+void steam_store_achievements(void)
+{
+   if( steam_ready && steam_stats_ready ){
+      SteamAPI_ISteamUserStats_StoreStats( hSteamUserStats );
+   }
+}
+
+void update_ach_models(void);
+void steam_set_achievement( const char *name )
+{
+   if( skaterift.demo_mode )
+      return;
+
+   /* hack lol */
+   if( !strcmp(name,"MARC") ) skaterift.achievements |= 0x1;
+   if( !strcmp(name,"ALBERT") ) skaterift.achievements |= 0x2;
+   if( !strcmp(name,"JANET") ) skaterift.achievements |= 0x4;
+   if( !strcmp(name,"BERNADETTA") ) skaterift.achievements |= 0x8;
+   update_ach_models();
+
+   if( steam_ready && steam_stats_ready ){
+      if( SteamAPI_ISteamUserStats_SetAchievement( hSteamUserStats, name ) ){
+         vg_success( "Achievement set! '%s'\n", name );
+
+      }
+      else{
+         vg_warn( "Failed to set achievement: %s\n", name );
+      }
+   }
+   else{
+      vg_warn( "Failed to set achievement (steam not ready): %s\n", name );
+   }
+}
+
+void steam_clear_achievement( const char *name )
+{
+   if( steam_ready && steam_stats_ready ){
+      if( SteamAPI_ISteamUserStats_ClearAchievement( hSteamUserStats, name ) ){
+         vg_info( "Achievement cleared: '%s'\n", name );
+      }
+      else{
+         vg_warn( "Failed to clear achievement: %s\n", name );
+      }
+   }
+   else{
+      vg_warn( "Failed to clear achievement (steam not ready): %s\n", name );
+   }
+}
+
+
+void steam_print_all_achievements(void)
+{
+   vg_info( "Achievements: \n" );
+
+   if( steam_ready && steam_stats_ready ){
+      for( int i=0; i<vg_list_size(steam_achievement_names); i++ ){
+         steamapi_bool set = 0;
+         const char *name = steam_achievement_names[i];
+
+         if( SteamAPI_ISteamUserStats_GetAchievement( 
+                  hSteamUserStats, name, &set ) )
+         {
+            vg_info( "  %s %s\n", (set? "[YES]": "[   ]"), name );
+         }
+         else{
+            vg_warn( "  Error while fetching achievement status '%s'\n", name );
+         }
+      }
+   }
+   else{
+      vg_warn( "  Steam is not initialized, no results\n" );
+   }
+}
+
+int steam_achievement_ccmd( int argc, char const *argv[] )
+{
+   if( !(steam_ready && steam_stats_ready) ) return 1;
+
+   if( argc == 1 ){
+      if( !strcmp( argv[0], "list" ) ){
+         steam_print_all_achievements();
+         return 0;
+      }
+      else if( !strcmp( argv[0], "clearall" )){
+         for( int i=0; i<vg_list_size(steam_achievement_names); i++ )
+            steam_clear_achievement( steam_achievement_names[i] );
+         
+         steam_store_achievements();
+      }
+   }
+
+   if( argc == 2 ){
+      if( !strcmp( argv[0], "set" ) ){
+         steam_set_achievement( argv[1] );
+         steam_store_achievements();
+         return 0;
+      }
+      else if( strcmp( argv[0], "clear" ) ){
+         steam_clear_achievement( argv[1] );
+         steam_store_achievements();
+         return 0;
+      }
+   }
+
+   return 1;
+}
+
+static void steam_on_recieve_current_stats( CallbackMsg_t *msg )
+{
+   UserStatsReceived_t *rec = (UserStatsReceived_t *)msg->m_pubParam;
+
+   if( rec->m_eResult == k_EResultOK ){
+      vg_info( "Recieved stats for: %lu (user: %lu)\n", rec->m_nGameID,
+                                                        rec->m_steamIDUser );
+      steam_stats_ready = 1;
+
+      steamapi_bool set = 0;
+      if( SteamAPI_ISteamUserStats_GetAchievement( 
+               hSteamUserStats, "MARC", &set ) ){
+         if( set ) skaterift.achievements |= 0x1;
+      }
+      if( SteamAPI_ISteamUserStats_GetAchievement( 
+               hSteamUserStats, "ALBERT", &set ) ){
+         if( set ) skaterift.achievements |= 0x2;
+      }
+      if( SteamAPI_ISteamUserStats_GetAchievement( 
+               hSteamUserStats, "JANET", &set ) ){
+         if( set ) skaterift.achievements |= 0x4;
+      }
+      if( SteamAPI_ISteamUserStats_GetAchievement( 
+               hSteamUserStats, "BERNADETTA", &set ) ){
+         if( set ) skaterift.achievements |= 0x8;
+      }
+      update_ach_models();
+   }
+   else{
+      vg_error( "Error recieveing stats for user (%u)\n", rec->m_eResult );
+   }
+}
+
+static u32 utf8_byte0_byte_count( u8 char0 )
+{
+   for( u32 k=2; k<4; k++ ){
+      if( !(char0 & (0x80 >> k)) )
+         return k;
+   }
+
+   return 0;
+}
+
+u32 str_utf8_collapse( const char *str, char *buf, u32 length )
+{
+   u8 *ustr = (u8 *)str;
+   u32 utf32_code = 0x00000000;
+   u32 i=0, j=0, utf32_byte_ct=0;
+
+   for(;j < length-1;){
+      if( ustr[i] == 0x00 )
+         break;
+      
+      if( ustr[i] & 0x80 ){
+         if( utf32_byte_ct ){
+            utf32_byte_ct --;
+            utf32_code |= (ustr[i] & 0x3F) << (utf32_byte_ct*6);
+
+            if( !utf32_byte_ct ){
+               const char *match;
+               size_t chars = anyascii( utf32_code, &match );
+
+               for( u32 k=0; k<VG_MIN(chars, length-1-j); k++ ){
+                  buf[ j++ ] = (u8)match[k];
+               }
+            }
+         }
+         else{
+            utf32_byte_ct = utf8_byte0_byte_count( ustr[i] )-1;
+            utf32_code = ustr[i] & (0x3F >> utf32_byte_ct);
+            utf32_code <<= utf32_byte_ct*6;
+         }
+      }
+      else{
+         utf32_byte_ct = 0x00;
+         buf[j ++] = str[i];
+      }
+
+      i++;
+   }
+
+   buf[j] = 0x00;
+   return j;
+}
+
+int steam_init(void)
+{
+   const char *username = "offline player";
+
+   vg_info( "Initializing steamworks\n" );
+
+   if( !SteamAPI_Init() ){
+      printf("\n");
+      vg_error( "Steamworks failed to initialize\n" );
+      return 1;
+   }
+
+   steam_ready = 1;
+
+   SteamAPI_ManualDispatch_Init();
+
+   /* Connect interfaces */
+   hSteamClientPipe = SteamAPI_GetHSteamPipe();
+   hSteamNetworkingSockets = SteamAPI_SteamNetworkingSockets_SteamAPI();
+   hSteamUser = SteamAPI_SteamUser();
+
+   ISteamUtils *utils = SteamAPI_SteamUtils();
+   SteamAPI_ISteamUtils_SetWarningMessageHook( utils, recv_steam_warning );
+
+   printf("\n");
+   vg_success( "\nSteamworks API running\n" );
+
+   ISteamFriends *hSteamFriends = SteamAPI_SteamFriends();
+   username = SteamAPI_ISteamFriends_GetPersonaName( hSteamFriends );
+
+   /*
+    * Request stats
+    * --------------------------------------------------------
+    */
+   hSteamUserStats = SteamAPI_SteamUserStats();
+   steam_register_callback( k_iUserStatsReceived,
+                            steam_on_recieve_current_stats );
+
+   if( !SteamAPI_ISteamUserStats_RequestCurrentStats( hSteamUserStats ) )
+      vg_warn( "No Steam Logon: Cannot request stats\n" );
+
+
+   vg_console_reg_cmd( "ach", steam_achievement_ccmd, NULL );
+
+   /* TODO: On username update callback */
+   str_utf8_collapse( username, steam_username_at_startup, 
+                        vg_list_size(steam_username_at_startup) );
+
+   return 1;
+}
+
+void steam_update(void)
+{
+   if( steam_ready ){
+      steamworks_event_loop( hSteamClientPipe );
+   }
+}
+
+void steam_end(void)
+{
+   if( steam_ready ){
+      vg_info( "Shutting down\n..." );
+      SteamAPI_Shutdown();
+   }
+}
diff --git a/steam.h b/steam.h
index 977f77d47844fa9b2294158cc3e178f6334cfb86..e2ed9822ceed634aa84106aa87ab91cdb2e8925a 100644 (file)
--- a/steam.h
+++ b/steam.h
  * All trademarks are property of their respective owners
  */
 #pragma once
-#include "vg/vg_steam.h"
-#include "vg/vg_steam_utils.h"
-#include "vg/vg_steam_networking.h"
-#include "vg/vg_steam_auth.h"
-#include "vg/vg_steam_http.h"
-#include "vg/vg_steam_friends.h"
-#include "vg/vg_steam_user_stats.h"
-#include "submodules/anyascii/impl/c/anyascii.c"
 
-/*
- * We only want to use steamworks if building for the networked version,
- * theres not much point otherwise. We mainly want steamworks for setting
- * achievements etc.. so that includes our own server too.
- *
- * This file also wraps the functions and interfaces that we want to use to 
- * make them a bit easier to read, since they are the flat API they have very 
- * long names. in non-networked builds they will return default errors or do
- * nothing.
- */
-
-static char steam_username_at_startup[128] = "Unassigned";
-
-static void recv_steam_warning( int severity, const char *msg )
-{
-   if( severity == 0 )
-      vg_low( "%s\n", msg );
-   else
-      vg_info( "%s\n", msg );
-}
-
-static int steam_ready = 0,
-              steam_stats_ready = 0;
-
-static void *hSteamNetworkingSockets,
-            *hSteamUser;
-
-static ISteamUserStats *hSteamUserStats;
-static HSteamPipe hSteamClientPipe;
-
-static const char *steam_achievement_names[] = 
-{
-   "ALBERT", "MARC", "JANET", "BERNADETTA",
-   "ROUTE_MPY", "ROUTE_MPG", "ROUTE_MPB", "ROUTE_MPR",
-   "ROUTE_TO", "ROUTE_TC", "CITY_COMPLETE", "MTZERO_SILVER", "MTZERO_GOLD",
-   "80FT"
-};
-
-static void steam_store_achievements(void)
-{
-   if( steam_ready && steam_stats_ready ){
-      SteamAPI_ISteamUserStats_StoreStats( hSteamUserStats );
-   }
-}
-
-static void update_ach_models(void);
-static void steam_set_achievement( const char *name ){
-   if( skaterift.demo_mode )
-      return;
-
-   /* hack lol */
-   if( !strcmp(name,"MARC") ) skaterift.achievements |= 0x1;
-   if( !strcmp(name,"ALBERT") ) skaterift.achievements |= 0x2;
-   if( !strcmp(name,"JANET") ) skaterift.achievements |= 0x4;
-   if( !strcmp(name,"BERNADETTA") ) skaterift.achievements |= 0x8;
-   update_ach_models();
-
-   if( steam_ready && steam_stats_ready ){
-      if( SteamAPI_ISteamUserStats_SetAchievement( hSteamUserStats, name ) ){
-         vg_success( "Achievement set! '%s'\n", name );
-
-      }
-      else{
-         vg_warn( "Failed to set achievement: %s\n", name );
-      }
-   }
-   else{
-      vg_warn( "Failed to set achievement (steam not ready): %s\n", name );
-   }
-}
-
-static void steam_clear_achievement( const char *name )
-{
-   if( steam_ready && steam_stats_ready ){
-      if( SteamAPI_ISteamUserStats_ClearAchievement( hSteamUserStats, name ) ){
-         vg_info( "Achievement cleared: '%s'\n", name );
-      }
-      else{
-         vg_warn( "Failed to clear achievement: %s\n", name );
-      }
-   }
-   else{
-      vg_warn( "Failed to clear achievement (steam not ready): %s\n", name );
-   }
-}
-
-
-static void steam_print_all_achievements(void){
-   vg_info( "Achievements: \n" );
-
-   if( steam_ready && steam_stats_ready ){
-      for( int i=0; i<vg_list_size(steam_achievement_names); i++ ){
-         steamapi_bool set = 0;
-         const char *name = steam_achievement_names[i];
-
-         if( SteamAPI_ISteamUserStats_GetAchievement( 
-                  hSteamUserStats, name, &set ) )
-         {
-            vg_info( "  %s %s\n", (set? "[YES]": "[   ]"), name );
-         }
-         else{
-            vg_warn( "  Error while fetching achievement status '%s'\n", name );
-         }
-      }
-   }
-   else{
-      vg_warn( "  Steam is not initialized, no results\n" );
-   }
-}
-
-static int steam_achievement_ccmd( int argc, char const *argv[] )
-{
-   if( !(steam_ready && steam_stats_ready) ) return 1;
-
-   if( argc == 1 ){
-      if( !strcmp( argv[0], "list" ) ){
-         steam_print_all_achievements();
-         return 0;
-      }
-      else if( !strcmp( argv[0], "clearall" )){
-         for( int i=0; i<vg_list_size(steam_achievement_names); i++ )
-            steam_clear_achievement( steam_achievement_names[i] );
-         
-         steam_store_achievements();
-      }
-   }
-
-   if( argc == 2 ){
-      if( !strcmp( argv[0], "set" ) ){
-         steam_set_achievement( argv[1] );
-         steam_store_achievements();
-         return 0;
-      }
-      else if( strcmp( argv[0], "clear" ) ){
-         steam_clear_achievement( argv[1] );
-         steam_store_achievements();
-         return 0;
-      }
-   }
-
-   return 1;
-}
-
-static void steam_on_recieve_current_stats( CallbackMsg_t *msg )
-{
-   UserStatsReceived_t *rec = (UserStatsReceived_t *)msg->m_pubParam;
-
-   if( rec->m_eResult == k_EResultOK ){
-      vg_info( "Recieved stats for: %lu (user: %lu)\n", rec->m_nGameID,
-                                                        rec->m_steamIDUser );
-      steam_stats_ready = 1;
-
-      steamapi_bool set = 0;
-      if( SteamAPI_ISteamUserStats_GetAchievement( 
-               hSteamUserStats, "MARC", &set ) ){
-         if( set ) skaterift.achievements |= 0x1;
-      }
-      if( SteamAPI_ISteamUserStats_GetAchievement( 
-               hSteamUserStats, "ALBERT", &set ) ){
-         if( set ) skaterift.achievements |= 0x2;
-      }
-      if( SteamAPI_ISteamUserStats_GetAchievement( 
-               hSteamUserStats, "JANET", &set ) ){
-         if( set ) skaterift.achievements |= 0x4;
-      }
-      if( SteamAPI_ISteamUserStats_GetAchievement( 
-               hSteamUserStats, "BERNADETTA", &set ) ){
-         if( set ) skaterift.achievements |= 0x8;
-      }
-      update_ach_models();
-   }
-   else{
-      vg_error( "Error recieveing stats for user (%u)\n", rec->m_eResult );
-   }
-}
-
-static u32 utf8_byte0_byte_count( u8 char0 )
-{
-   for( u32 k=2; k<4; k++ ){
-      if( !(char0 & (0x80 >> k)) )
-         return k;
-   }
-
-   return 0;
-}
-
-static u32 str_utf8_collapse( const char *str, char *buf, u32 length ){
-   u8 *ustr = (u8 *)str;
-   u32 utf32_code = 0x00000000;
-   u32 i=0, j=0, utf32_byte_ct=0;
-
-   for(;j < length-1;){
-      if( ustr[i] == 0x00 )
-         break;
-      
-      if( ustr[i] & 0x80 ){
-         if( utf32_byte_ct ){
-            utf32_byte_ct --;
-            utf32_code |= (ustr[i] & 0x3F) << (utf32_byte_ct*6);
-
-            if( !utf32_byte_ct ){
-               const char *match;
-               size_t chars = anyascii( utf32_code, &match );
-
-               for( u32 k=0; k<VG_MIN(chars, length-1-j); k++ ){
-                  buf[ j++ ] = (u8)match[k];
-               }
-            }
-         }
-         else{
-            utf32_byte_ct = utf8_byte0_byte_count( ustr[i] )-1;
-            utf32_code = ustr[i] & (0x3F >> utf32_byte_ct);
-            utf32_code <<= utf32_byte_ct*6;
-         }
-      }
-      else{
-         utf32_byte_ct = 0x00;
-         buf[j ++] = str[i];
-      }
-
-      i++;
-   }
-
-   buf[j] = 0x00;
-   return j;
-}
-
-static int steam_init(void){
-   const char *username = "offline player";
-
-   vg_info( "Initializing steamworks\n" );
-
-   if( !SteamAPI_Init() ){
-      printf("\n");
-      vg_error( "Steamworks failed to initialize\n" );
-      return 1;
-   }
-
-   steam_ready = 1;
-
-   SteamAPI_ManualDispatch_Init();
-
-   /* Connect interfaces */
-   hSteamClientPipe = SteamAPI_GetHSteamPipe();
-   hSteamNetworkingSockets = SteamAPI_SteamNetworkingSockets_SteamAPI();
-   hSteamUser = SteamAPI_SteamUser();
-
-   ISteamUtils *utils = SteamAPI_SteamUtils();
-   SteamAPI_ISteamUtils_SetWarningMessageHook( utils, recv_steam_warning );
-
-   printf("\n");
-   vg_success( "\nSteamworks API running\n" );
-
-   ISteamFriends *hSteamFriends = SteamAPI_SteamFriends();
-   username = SteamAPI_ISteamFriends_GetPersonaName( hSteamFriends );
-
-   /*
-    * Request stats
-    * --------------------------------------------------------
-    */
-   hSteamUserStats = SteamAPI_SteamUserStats();
-   steam_register_callback( k_iUserStatsReceived,
-                            steam_on_recieve_current_stats );
-
-   if( !SteamAPI_ISteamUserStats_RequestCurrentStats( hSteamUserStats ) )
-      vg_warn( "No Steam Logon: Cannot request stats\n" );
-
-
-   vg_console_reg_cmd( "ach", steam_achievement_ccmd, NULL );
-
-   /* TODO: On username update callback */
-   str_utf8_collapse( username, steam_username_at_startup, 
-                        vg_list_size(steam_username_at_startup) );
-
-   return 1;
-}
-
-static void steam_update(void)
-{
-   if( steam_ready ){
-      steamworks_event_loop( hSteamClientPipe );
-   }
-}
-
-static void steam_end(void)
-{
-   if( steam_ready ){
-      vg_info( "Shutting down\n..." );
-      SteamAPI_Shutdown();
-   }
-}
+extern int steam_ready, steam_stats_ready;
+extern void *hSteamNetworkingSockets, *hSteamUser, *hSteamUserStats;
+extern char steam_username_at_startup[128];
+
+int steam_init(void);
+void steam_update(void);
+void steam_end(void);
+u32 str_utf8_collapse( const char *str, char *buf, u32 length );
+int steam_achievement_ccmd( int argc, char const *argv[] );
+void steam_print_all_achievements(void);
+void steam_clear_achievement( const char *name );
+void steam_set_achievement( const char *name );
+void steam_store_achievements(void);
diff --git a/testing.c b/testing.c
deleted file mode 100644 (file)
index a71806c..0000000
--- a/testing.c
+++ /dev/null
@@ -1,65 +0,0 @@
-#pragma once
-#include "vg/vg_m.h"
-#include "vg/vg_rigidbody.h"
-#include "vg/vg_input.h"
-#include "scene_rigidbody.h"
-
-struct {
-   rigidbody rb;
-   boxf box;
-}
-static baller = { 
-   .rb.q = { 0,0,0,1 },
-   .box = {{ -0.1f, -0.2f, -0.1f },
-           {  0.1f,  1.0f,  0.1f }},
-};
-
-static void testing_update(void){
-   if( !vg_console.cheats )
-      return;
-
-   if( vg_getkey( SDLK_9 ) ){
-      v3_add( localplayer.rb.co, (v3f){0,1,0}, baller.rb.co );
-      v3_zero( baller.rb.w );
-      v3_zero( baller.rb.v );
-      q_identity( baller.rb.q );
-      rb_update_matrices( &baller.rb );
-   }
-
-   if( vg_getkey( SDLK_8 ) ){
-      localplayer.have_glider = 1;
-      localplayer.glider_orphan = 0;
-      player_glide.t = -1.0f;
-   }
-
-   vg_line_boxf_transformed( baller.rb.to_world, baller.box, VG__RED );
-
-   world_instance *world = world_current_instance();
-
-   rigidbody _null = {0};
-   _null.inv_mass = 0.0f;
-   m3x3_zero( _null.iI );
-
-   rb_solver_reset();
-   rb_ct *buf = rb_global_buffer();
-   rb_contact_count += rb_box__scene( baller.rb.to_world, baller.box,
-                          NULL, world->geo_bh, buf,
-                          k_material_flag_ghosts );
-   for( u32 j=0; j<rb_contact_count; j++ ){
-      buf[j].rba = &baller.rb;
-      buf[j].rbb = &_null;
-   }
-
-   rb_presolve_contacts( rb_contact_buffer, 
-                         vg.time_fixed_delta, rb_contact_count );
-
-   for( u32 i=0; i<8; i ++ )
-      rb_solve_contacts( rb_contact_buffer, rb_contact_count );
-
-   rb_iter( &baller.rb );
-   rb_update_matrices( &baller.rb );
-}
-
-static void testing_init(void){
-   rb_setbody_box( &baller.rb, baller.box, 8.0f, 1.0f );
-}
diff --git a/trail.c b/trail.c
index 3399694923e2fed841efd3069992e084aa4c0b14..6bdee69262a8d0eab261862fca9b9914263c48f7 100644 (file)
--- a/trail.c
+++ b/trail.c
@@ -1,4 +1,10 @@
 #pragma once
+#include "vg/vg_engine.h"
+#include "vg/vg_platform.h"
+#include "vg/vg_m.h"
+#include "vg/vg_lines.h"
+#include "vg/vg_async.h"
+#include "vg/vg_camera.h"
 #include "trail.h"
 #include "shaders/particle.h"
 #include "shaders/trail.h"
@@ -14,8 +20,9 @@ static void trail_increment( trail_system *sys ){
       sys->count ++;
 }
 
-static void trail_system_update( trail_system *sys, f32 dt,
-                                 v3f co, v3f normal, f32 alpha ){
+void trail_system_update( trail_system *sys, f32 dt,
+                          v3f co, v3f normal, f32 alpha )
+{
    /* update existing points and clip dead ones */
    bool clip_allowed = 1;
    for( i32 i=0; i<sys->count; i ++ ){
@@ -82,7 +89,8 @@ static void trail_system_update( trail_system *sys, f32 dt,
    pdest->alpha = alpha;
 }
 
-static void trail_system_debug( trail_system *sys ){
+void trail_system_debug( trail_system *sys )
+{
    for( i32 i=0; i<sys->count; i ++ ){
       i32 i0 = sys->head - sys->count + i;
       if( i0 < 0 ) i0 += sys->max;
@@ -105,7 +113,8 @@ struct trail_init_args {
    trail_system *sys;
 };
 
-static void async_trail_init( void *payload, u32 size ){
+void async_trail_init( void *payload, u32 size )
+{
    struct trail_init_args *args = payload;
    trail_system *sys = args->sys;
 
@@ -125,7 +134,8 @@ static void async_trail_init( void *payload, u32 size ){
    VG_CHECK_GL_ERR();
 }
 
-static void trail_alloc( trail_system *sys, u32 max ){
+void trail_alloc( trail_system *sys, u32 max )
+{
    size_t stride = sizeof(trail_vert);
    sys->max = max;
    sys->array = vg_linear_alloc( vg_mem.rtmemory, max*sizeof(trail_point) );
@@ -138,7 +148,8 @@ static void trail_alloc( trail_system *sys, u32 max ){
    vg_async_dispatch( call, async_trail_init );
 }
 
-static void trail_system_prerender( trail_system *sys ){
+void trail_system_prerender( trail_system *sys )
+{
    if( sys->count < 2 ) return;
 
    for( i32 i=0; i<sys->count; i ++ ){
@@ -162,7 +173,8 @@ static void trail_system_prerender( trail_system *sys ){
    glBufferSubData( GL_ARRAY_BUFFER, 0, sys->count*stride*2, sys->vertices );
 }
 
-static void trail_system_render( trail_system *sys, camera *cam ){
+void trail_system_render( trail_system *sys, vg_camera *cam )
+{
    if( sys->count < 2 ) return;
    glDisable( GL_CULL_FACE );
    glEnable( GL_DEPTH_TEST );
@@ -175,7 +187,3 @@ static void trail_system_render( trail_system *sys, camera *cam ){
        glBindVertexArray( sys->vao );
    glDrawArrays( GL_TRIANGLE_STRIP, 0, sys->count*2 );
 }
-
-static void trail_init( void ){
-   shader_trail_register();
-}
diff --git a/trail.h b/trail.h
index 58bcb933427a229461f480693330e5c60d3a00aa..82c7d608564aeea545133224f10c35fc1295a305 100644 (file)
--- a/trail.h
+++ b/trail.h
@@ -1,7 +1,4 @@
-#ifndef TRAIL_H
-#define TRAIL_H
-
-#include "skaterift.h"
+#pragma once
 
 typedef struct trail_system trail_system;
 typedef struct trail_point trail_point;
@@ -28,11 +25,9 @@ struct trail_system {
    f32 width, lifetime, min_dist;
 };
 
-static void trail_alloc( trail_system *sys, u32 max );
-static void trail_system_update( trail_system *sys, f32 dt, 
-                                 v3f co, v3f normal, f32 alpha );
-static void trail_system_debug( trail_system *sys );
-static void trail_system_prerender( trail_system *sys );
-static void trail_system_render( trail_system *sys, camera *cam );
-
-#endif /* TRAIL_H */
+void trail_alloc( trail_system *sys, u32 max );
+void trail_system_update( trail_system *sys, f32 dt, v3f co, 
+                          v3f normal, f32 alpha );
+void trail_system_debug( trail_system *sys );
+void trail_system_prerender( trail_system *sys );
+void trail_system_render( trail_system *sys, vg_camera *cam );
index 0576963e1f59ff8f4bfd0c541c9a7e9f8813a2a6..35004d6a81c08cbd323622a5bcce7c9ccf32e442 100644 (file)
--- a/vehicle.c
+++ b/vehicle.c
@@ -1,10 +1,14 @@
-#ifndef VEHICLE_C
-#define VEHICLE_C
-
+#include "skaterift.h"
 #include "vehicle.h"
 #include "scene_rigidbody.h"
 
-static int spawn_car( int argc, const char *argv[] ){
+struct drivable_vehicle gzoomer =
+{
+   .rb.co = {-2000,-2000,-2000}
+};
+
+int spawn_car( int argc, const char *argv[] )
+{
    v3f ra, rb, rx;
    v3_copy( skaterift.cam.pos, ra );
    v3_muladds( ra, skaterift.cam.transform[2], -10.0f, rb );
@@ -31,7 +35,8 @@ static int spawn_car( int argc, const char *argv[] ){
    return 0;
 }
 
-static void vehicle_init(void){
+void vehicle_init(void)
+{
    q_identity( gzoomer.rb.q );
    v3_zero( gzoomer.rb.w );
    v3_zero( gzoomer.rb.v );
@@ -58,7 +63,8 @@ static void vehicle_init(void){
    v3_copy((v3f){  1.0f, -0.25f,  1.5f }, gzoomer.wheels_local[3] );
 }
 
-static void vehicle_wheel_force( int index ){
+void vehicle_wheel_force( int index )
+{
    v3f pa, pb, n;
    m4x3_mulv( gzoomer.rb.to_world, gzoomer.wheels_local[index], pa );
    v3_muladds( pa, gzoomer.rb.to_world[1], -k_car_spring_length, pb );
@@ -164,7 +170,8 @@ static void vehicle_wheel_force( int index ){
    }
 }
 
-static void vehicle_solve_friction(void){
+void vehicle_solve_friction(void)
+{
    rigidbody *rb = &gzoomer.rb;
    for( int i=0; i<4; i++ ){
       v3f raW;
@@ -196,7 +203,7 @@ static void vehicle_solve_friction(void){
    }
 }
 
-static void vehicle_update_fixed(void)
+void vehicle_update_fixed(void)
 {
    if( !gzoomer.alive )
       return;
@@ -251,7 +258,8 @@ static void vehicle_update_fixed(void)
    rb_update_matrices( rb );
 }
 
-static void vehicle_update_post(void){
+void vehicle_update_post(void)
+{
    if( !gzoomer.alive )
       return;
 
@@ -269,5 +277,3 @@ static void vehicle_update_post(void){
       vg_line( p0, py, VG__GREEN );
    }
 }
-
-#endif /* VEHICLE_H */
index d61d1e3adf25117eed0938c69cb99aae94307ab1..3e60bb76d6d2b9e7b3cd9a6212da38b39b4982b6 100644 (file)
--- a/vehicle.h
+++ b/vehicle.h
@@ -1,7 +1,4 @@
-#ifndef VEHICLE_H
-#define VEHICLE_H
-
-#include "skaterift.h"
+#pragma once
 #include "vg/vg_rigidbody.h"
 #include "player.h"
 #include "world.h"
@@ -35,16 +32,11 @@ struct drivable_vehicle
    v3f   tangent_vectors[4][2];
    v3f   wheels_local[4];
 }
-static gzoomer =
-{
-   .rb.co = {-2000,-2000,-2000}
-};
-
-static int spawn_car( int argc, const char *argv[] );
-static void vehicle_init(void);
-static void vehicle_wheel_force( int index );
-static void vehicle_solve_friction(void);
-static void vehicle_update_fixed(void);
-static void vehicle_update_post(void);
-
-#endif /* VEHICLE_H */
+extern gzoomer;
+
+int spawn_car( int argc, const char *argv[] );
+void vehicle_init(void);
+void vehicle_wheel_force( int index );
+void vehicle_solve_friction(void);
+void vehicle_update_fixed(void);
+void vehicle_update_post(void);
index 469eeea2260d40bca903f93cb0e1990187c6fc28..0b03894ed0223f4e44715392444a236558e6c5b1 100644 (file)
@@ -1,6 +1,7 @@
-#include "workshop.h"
 
+#include "vg/vg_engine.h"
 #include "vg/vg_tex.h"
+#include "vg/vg_image.h"
 #include "vg/vg_msg.h"
 #include "vg/vg_binstr.h"
 #include "vg/vg_loader.h"
@@ -10,6 +11,9 @@
 #include "vg/vg_steam_ugc.h"
 #include "vg/vg_steam_friends.h"
 #include "steam.h"
+#include "workshop.h"
+
+struct workshop_form workshop_form;
 
 static struct ui_enum_opt workshop_form_visibility_opts[] = {
  { k_ERemoteStoragePublishedFileVisibilityPublic,       "Public"       },
@@ -805,7 +809,7 @@ static void on_workshop_UGCQueryComplete( void *data, void *userdata )
 /*
  * Console command to open the workshop publisher
  */
-static int workshop_submit_command( int argc, const char *argv[] )
+int workshop_submit_command( int argc, const char *argv[] )
 {
    if( !steam_ready ){
       ui_start_modal( "Steam API is not initialized\n", UI_MODAL_BAD );
@@ -841,7 +845,7 @@ static int workshop_submit_command( int argc, const char *argv[] )
    return 0;
 }
 
-static void workshop_init(void)
+void workshop_init(void)
 {
    vg_console_reg_cmd( "workshop_submit", workshop_submit_command, NULL );
 }
@@ -894,7 +898,7 @@ static void workshop_render_player_preview(void){
    skeleton_apply_inverses( sk, localplayer.final_mtx );
    skeleton_apply_transform( sk, transform, localplayer.final_mtx );
 
-   camera cam;
+   vg_camera cam;
    v3_copy( (v3f){ 0.0f, 201.7f, 1.2f }, cam.pos );
    
    cam.nearz = 0.01f;
@@ -902,10 +906,10 @@ static void workshop_render_player_preview(void){
    cam.fov = 57.0f;
    v3_zero( cam.angles );
    
-   camera_update_transform( &cam );
-   camera_update_view( &cam );
-   camera_update_projection( &cam );
-   camera_finalize( &cam );
+   vg_camera_update_transform( &cam );
+   vg_camera_update_view( &cam );
+   vg_camera_update_projection( &cam );
+   vg_camera_finalize( &cam );
 
    render_playermodel( &cam, world_current_instance(), 0, 
                        &workshop_form.player_model, sk, localplayer.final_mtx );
@@ -943,7 +947,7 @@ static void workshop_render_board_preview(void){
    v3_add( display->transform.co, display1->transform.co, baseco );
    v3_muls( baseco, 0.5f, baseco );
 
-   camera cam;
+   vg_camera cam;
    v3f basevector;
    v3_sub( display->transform.co, ref->transform.co, basevector );
    float dist = v3_length( basevector );
@@ -974,10 +978,10 @@ static void workshop_render_board_preview(void){
    cam.farz  = 100.0f;
    cam.fov   = ref->fov;
    
-   camera_update_transform( &cam );
-   camera_update_view( &cam );
-   camera_update_projection( &cam );
-   camera_finalize( &cam );
+   vg_camera_update_transform( &cam );
+   vg_camera_update_view( &cam );
+   vg_camera_update_projection( &cam );
+   vg_camera_finalize( &cam );
 
    m4x3f mmdl, mmdl1;
    mdl_transform_m4x3( &display->transform, mmdl );
@@ -1373,7 +1377,7 @@ static void workshop_form_gui_sidebar( ui_rect sidebar )
    }
 }
 
-static void workshop_form_gui(void)
+void workshop_form_gui(void)
 {
    enum workshop_form_page stable_page = workshop_form.page;
    if( stable_page == k_workshop_form_hidden ) return;
@@ -1501,7 +1505,7 @@ static void workshop_form_gui(void)
  * -----------------------------------------------------------------------------
  */
 
-static void async_workshop_get_filepath( void *data, u32 len )
+void async_workshop_get_filepath( void *data, u32 len )
 {
    struct async_workshop_filepath_info *info = data;
 
@@ -1517,7 +1521,7 @@ static void async_workshop_get_filepath( void *data, u32 len )
    }
 }
 
-static void async_workshop_get_installed_files( void *data, u32 len )
+void async_workshop_get_installed_files( void *data, u32 len )
 {
    struct async_workshop_installed_files_info *info = data;
 
index 42610d4e2322b9350906f15e17b40ac432371917..be9e3a5207728c7a7490d8fda4a0e96aa00e2e9c 100644 (file)
@@ -124,12 +124,11 @@ struct workshop_form{
    published_files_list[WORKSHOP_VIEW_PER_PAGE];
    int published_files_list_length;
 }
-static workshop_form;
-
-
-
-static int workshop_submit_command( int argc, const char *argv[] );
-static void async_workshop_get_filepath( void *data, u32 len );
-static void async_workshop_get_installed_files( void *data, u32 len );
-static void workshop_load_metadata( const char *path,
-                                       struct workshop_file_info *info );
+extern workshop_form;
+
+void workshop_init(void);
+int workshop_submit_command( int argc, const char *argv[] );
+void async_workshop_get_filepath( void *data, u32 len );
+void async_workshop_get_installed_files( void *data, u32 len );
+void workshop_load_metadata( const char *path,struct workshop_file_info *info );
+void workshop_form_gui(void);
diff --git a/world.c b/world.c
index 9ff62bcb3df1b3471462542c21cda5ea53b82d51..9b19387208ad9a47a5c96805b6923a83185af09b 100644 (file)
--- a/world.c
+++ b/world.c
@@ -2,19 +2,25 @@
  * Copyright (C) 2021-2023 Mt.ZERO Software, Harry Godden - All Rights Reserved
  */
 
-#ifndef WORLD_C
-#define WORLD_C
-
+#include "skaterift.h"
 #include "world.h"
 #include "network.h"
 #include "vg/vg_loader.h"
 #include "vg/vg_mem.h"
+#include "save.h"
+#include "player.h"
+#include "ent_traffic.h"
+
+struct world_static world_static;
 
-static world_instance *world_current_instance(void){
+world_instance *world_current_instance(void)
+{
    return &world_static.instances[ world_static.active_instance ];
 }
 
-static void world_init(void)
+static int skaterift_switch_instance_cmd( int argc, const char *argv[] );
+
+void world_init(void)
 {
    vg_loader_step( world_render_init, NULL );
    vg_loader_step( world_sfd_init, NULL );
@@ -26,9 +32,13 @@ static void world_init(void)
    u32 max_size = 76*1024*1024;
    world_static.heap = vg_create_linear_allocator( vg_mem.rtmemory, max_size,
                                                    VG_MEMORY_SYSTEM );
+
+   vg_console_reg_cmd( "switch_active_instance", 
+                        skaterift_switch_instance_cmd, NULL );
 }
 
-static void world_switch_instance( u32 index ){
+void world_switch_instance( u32 index )
+{
    localplayer.subsystem = k_player_subsystem_walk;
 
    if( index >= vg_list_size(world_static.instances) ){
@@ -64,7 +74,8 @@ static void world_switch_instance( u32 index ){
    player__reset();
 }
 
-static int skaterift_switch_instance_cmd( int argc, const char *argv[] ){
+static int skaterift_switch_instance_cmd( int argc, const char *argv[] )
+{
    if( argc )
       world_switch_instance( atoi(argv[0]) );
    else 
@@ -72,8 +83,8 @@ static int skaterift_switch_instance_cmd( int argc, const char *argv[] ){
    return 0;
 }
 
-static void skaterift_world_get_save_path( enum world_purpose which, 
-                                           char buf[128] ){
+void skaterift_world_get_save_path( enum world_purpose which, char buf[128] )
+{
    addon_reg *reg = world_static.instance_addons[ which ];
 
    if( !reg )
@@ -84,19 +95,8 @@ static void skaterift_world_get_save_path( enum world_purpose which,
    snprintf( buf, 128, "savedata/%s.bkv", id );
 }
 
-#include "world_entity.c"
-#include "world_gate.c"
-#include "world_gen.c"
-#include "world_load.c"
-#include "world_physics.c"
-#include "world_render.c"
-#include "world_sfd.c"
-#include "world_volumes.c"
-#include "world_water.c"
-#include "world_audio.c"
-#include "world_routes.c"
-
-static void world_update( world_instance *world, v3f pos ){
+void world_update( world_instance *world, v3f pos )
+{
    world_render.sky_time += world_render.sky_rate * vg.time_delta;
    world_render.sky_rate = vg_lerp( world_render.sky_rate, 
                                     world_render.sky_target_rate, 
@@ -108,5 +108,3 @@ static void world_update( world_instance *world, v3f pos ){
    world_sfd_update( world, pos );
    world_volumes_update( world, pos );
 }
-
-#endif /* WORLD_C */
diff --git a/world.h b/world.h
index 6ff3afbc00f295d7a459eec32d0eff75bcc7e719..823b38c70e7992ae838f91b6dd0f55a330feec1e 100644 (file)
--- a/world.h
+++ b/world.h
@@ -1,12 +1,11 @@
 /*
- * Copyright (C) 2021-2023 Mt.ZERO Software, Harry Godden - All Rights Reserved
+ * Copyright (C) 2021-2024 Mt.ZERO Software, Harry Godden - All Rights Reserved
  */
 
-#ifndef WORLD_H
-#define WORLD_H
-
+#pragma once
 #include "render.h"
 #include "network_msg.h"
+#include "addon.h"
 
 /* types
  */
@@ -33,15 +32,13 @@ struct leaderboard_cache {
 
 typedef struct world_instance world_instance;
 
-static void skaterift_world_get_save_path( enum world_purpose which, 
-                                           char buf[128] );
+void skaterift_world_get_save_path( enum world_purpose which, char buf[128] );
 
 /* submodule headers */
 #include "world_entity.h"
 #include "world_gate.h"
 #include "world_gen.h"
 #include "world_info.h"
-#include "world_load.h"
 #include "world_physics.h"
 #include "world_render.h"
 #include "world_sfd.h"
@@ -245,7 +242,7 @@ struct world_static {
    enum world_purpose active_instance;
    u32            focused_entity; /* like skateshop, challenge.. */
    f32            focus_strength;
-   camera         focus_cam;
+   vg_camera      focus_cam;
 
    /* challenges */
    ent_objective *challenge_target;
@@ -258,10 +255,16 @@ struct world_static {
    }
    load_state;
 }
-static world_static;
+extern world_static;
 
-static void world_init(void);
-static world_instance *world_current_instance(void);
-static void world_switch_instance( u32 index );
+struct world_load_args 
+{
+   enum world_purpose purpose;
+   addon_reg *reg;
+};
 
-#endif /* WORLD_H */
+void world_init(void);
+world_instance *world_current_instance(void);
+void world_switch_instance( u32 index );
+void skaterift_world_load_thread( void *_args );
+void world_update( world_instance *world, v3f pos );
index 826e20a4ce708a80fc33a15050b21d79ec268e4f..df3af70edc665a396d405488c6de5061b1ecd318 100644 (file)
@@ -1,12 +1,9 @@
-#ifndef WORLD_AUDIO_C
-#define WORLD_AUDIO_C
-
 #include "audio.h"
 #include "world_audio.h"
 
 /* finds any active playing in world and fades them out, we can only do this 
  * while unloading */
-static void world_fadeout_audio( world_instance *world )
+void world_fadeout_audio( world_instance *world )
 {
    if( world->status != k_world_status_unloading ){
       vg_fatal_error( "World status must be set to 'unloading', to fadeout"
@@ -29,8 +26,8 @@ static void world_fadeout_audio( world_instance *world )
 /*
  * Trace out a random point, near the player to try and determine water areas
  */
-static 
-enum audio_sprite_type world_audio_sample_sprite_random(v3f origin, v3f output){
+enum audio_sprite_type world_audio_sample_sprite_random(v3f origin, v3f output)
+{
    v3f chance = { (vg_randf64(&vg.rand)-0.5f) * 30.0f, 
                   8,
                   (vg_randf64(&vg.rand)-0.5f) * 30.0f };
@@ -68,7 +65,7 @@ enum audio_sprite_type world_audio_sample_sprite_random(v3f origin, v3f output){
       return k_audio_sprite_type_none;
 }
 
-static void world_audio_sample_distances( v3f co, int *index, float *value )
+void world_audio_sample_distances( v3f co, int *index, float *value )
 {
    float inr3 = 0.57735027,
          inr2 = 0.70710678118;
@@ -140,5 +137,3 @@ static void world_audio_sample_distances( v3f co, int *index, float *value )
    if( si >= 14 )
       si = 0;
 }
-
-#endif /* WORLD_AUDIO_C */
index b1b14da88eaf620ca41fbb7728d68bb665e074db..07d66d1cc300a2daca4a6df3d3962c62a35f3355 100644 (file)
@@ -1,11 +1,7 @@
-#ifndef WORLD_AUDIO_H
-#define WORLD_AUDIO_H
-
+#pragma once
 #include "world.h"
 
-static void world_fadeout_audio( world_instance *world );
-static void world_audio_sample_distances( v3f co, int *index, float *value );
-static enum audio_sprite_type world_audio_sample_sprite_random( v3f origin, 
-                                                                   v3f output );
-
-#endif /* WORLD_AUDIO_H */
+void world_fadeout_audio( world_instance *world );
+void world_audio_sample_distances( v3f co, int *index, float *value );
+enum audio_sprite_type 
+world_audio_sample_sprite_random( v3f origin, v3f output );
index 957891d4f21e059acfdfbcd98e5a3722ae9ec630..3602530ff99a70d8eac814e32a616afde6fd6363 100644 (file)
@@ -1,6 +1,5 @@
-#ifndef WORLD_ENTITY_C
-#define WORLD_ENTITY_C
-
+#include "vg/vg_steam.h"
+#include "vg/vg_steam_user_stats.h"
 #include "model.h"
 #include "entity.h"
 #include "world.h"
 #include "ent_route.h"
 #include "ent_traffic.h"
 #include "ent_glider.h"
+#include "ent_region.h"
+#include "input.h"
+#include "player_walk.h"
 
-static void world_entity_focus( u32 entity_id ){
+bh_system bh_system_entity_list = 
+{
+   .expand_bound = entity_bh_expand_bound,
+   .item_centroid = entity_bh_centroid,
+   .item_closest = entity_bh_closest,
+   .item_swap = entity_bh_swap,
+   .item_debug = entity_bh_debug,
+   .cast_ray = NULL
+};
+
+void world_entity_focus( u32 entity_id )
+{
    localplayer.immobile = 1;
    menu.disable_open = 1;
 
@@ -25,14 +38,16 @@ static void world_entity_focus( u32 entity_id ){
    skaterift.activity = k_skaterift_ent_focus;
 }
 
-static void world_entity_unfocus(void){
+void world_entity_unfocus(void)
+{
    localplayer.immobile = 0;
    skaterift.activity = k_skaterift_default;
    menu.disable_open = 0;
    srinput.state = k_input_state_resume;
 }
 
-static void world_entity_focus_camera( world_instance *world, u32 uid ){
+void world_entity_focus_camera( world_instance *world, u32 uid )
+{
    if( mdl_entity_id_type( uid ) == k_ent_camera ){
       u32 index = mdl_entity_id_id( uid );
       ent_camera *cam = mdl_arritm( &world->ent_camera, index );
@@ -44,7 +59,7 @@ static void world_entity_focus_camera( world_instance *world, u32 uid ){
       world_static.focus_cam.fov = cam->fov;
    }
    else {
-      camera_copy( &localplayer.cam, &world_static.focus_cam );
+      vg_camera_copy( &localplayer.cam, &world_static.focus_cam );
 
       /* TODO ? */
       world_static.focus_cam.nearz = localplayer.cam.nearz;
@@ -53,7 +68,8 @@ static void world_entity_focus_camera( world_instance *world, u32 uid ){
 }
 
 /* logic preupdate */
-static void world_entity_focus_preupdate(void){
+void world_entity_focus_preupdate(void)
+{
    f32 rate = vg_minf( 1.0f, vg.time_frame_delta * 2.0f );
    int active = 0;
    if( skaterift.activity == k_skaterift_ent_focus )
@@ -82,7 +98,8 @@ static void world_entity_focus_preupdate(void){
 }
 
 /* additional renderings like text etc.. */
-static void world_entity_focus_render(void){
+void world_entity_focus_render(void)
+{
    world_instance *world = world_current_instance();
    if( skaterift.activity != k_skaterift_ent_focus ){
       skateshop_render_nonfocused( world, &skaterift.cam );
@@ -104,7 +121,8 @@ static void world_entity_focus_render(void){
    }
 }
 
-static void world_gen_entities_init( world_instance *world ){
+void world_gen_entities_init( world_instance *world )
+{
    /* lights */
    for( u32 j=0; j<mdl_arrcount(&world->ent_light); j ++ ){
       ent_light *light = mdl_arritm( &world->ent_light, j );
@@ -232,7 +250,6 @@ static void world_gen_entities_init( world_instance *world ){
    }
 }
 
-static
 ent_spawn *world_find_closest_spawn( world_instance *world, v3f position )
 {
    ent_spawn *rp = NULL, *r;
@@ -261,7 +278,6 @@ ent_spawn *world_find_closest_spawn( world_instance *world, v3f position )
    return rp;
 }
 
-static
 ent_spawn *world_find_spawn_by_name( world_instance *world, const char *name )
 {
    ent_spawn *rp = NULL, *r;
@@ -279,7 +295,7 @@ ent_spawn *world_find_spawn_by_name( world_instance *world, const char *name )
    return rp;
 }
 
-static void world_default_spawn_pos( world_instance *world, v3f pos )
+void world_default_spawn_pos( world_instance *world, v3f pos )
 {
    ent_spawn *rp = world_find_spawn_by_name( world, "start" );
    if( !rp ) rp = world_find_closest_spawn( world, (v3f){0,0,0} );
@@ -292,7 +308,8 @@ static void world_default_spawn_pos( world_instance *world, v3f pos )
    }
 }
 
-static void ent_volume_call( world_instance *world, ent_call *call ){
+void ent_volume_call( world_instance *world, ent_call *call )
+{
    u32 index = mdl_entity_id_id( call->id );
    ent_volume *volume = mdl_arritm( &world->ent_volume, index );
    if( !volume->target ) return;
@@ -329,7 +346,8 @@ static void ent_volume_call( world_instance *world, ent_call *call ){
    }
 }
 
-static void ent_audio_call( world_instance *world, ent_call *call ){
+void ent_audio_call( world_instance *world, ent_call *call )
+{
    if( world->status == k_world_status_unloading ){
       vg_warn( "cannot modify audio while unloading world\n" );
       return;
@@ -422,7 +440,8 @@ static void ent_audio_call( world_instance *world, ent_call *call ){
 }
 
 
-static void ent_ccmd_call( world_instance *world, ent_call *call ){
+void ent_ccmd_call( world_instance *world, ent_call *call )
+{
    if( call->function == k_ent_function_trigger ){
       u32 index = mdl_entity_id_id( call->id );
       ent_ccmd *ccmd = mdl_arritm( &world->ent_ccmd, index );
@@ -436,8 +455,8 @@ static void ent_ccmd_call( world_instance *world, ent_call *call ){
  * ----------------------------------------------------------------------------
  */
 
-static void 
-entity_bh_expand_bound( void *user, boxf bound, u32 item_index ){
+void entity_bh_expand_bound( void *user, boxf bound, u32 item_index )
+{
    world_instance *world = user;
 
    u32 id    = world->entity_list[ item_index ],
@@ -496,7 +515,8 @@ entity_bh_expand_bound( void *user, boxf bound, u32 item_index ){
    }
 }
 
-static float entity_bh_centroid( void *user, u32 item_index, int axis ){
+float entity_bh_centroid( void *user, u32 item_index, int axis )
+{
    world_instance *world = user;
 
    u32 id    = world->entity_list[ item_index ],
@@ -529,7 +549,8 @@ static float entity_bh_centroid( void *user, u32 item_index, int axis ){
    }
 }
 
-static void entity_bh_swap( void *user, u32 ia, u32 ib ){
+void entity_bh_swap( void *user, u32 ia, u32 ib )
+{
    world_instance *world = user;
 
    u32 a = world->entity_list[ ia ],
@@ -539,7 +560,7 @@ static void entity_bh_swap( void *user, u32 ia, u32 ib ){
    world->entity_list[ ib ] = a;
 }
 
-static void entity_bh_debug( void *user, u32 item_index ){
+void entity_bh_debug( void *user, u32 item_index ){
    world_instance *world = user;
 
    u32 id    = world->entity_list[ item_index ],
@@ -587,7 +608,8 @@ static void entity_bh_debug( void *user, u32 item_index ){
    }
 }
 
-static void update_ach_models(void){
+void update_ach_models(void)
+{
    world_instance *hub = &world_static.instances[k_world_purpose_hub];
    if( hub->status != k_world_status_loaded ) return;
 
@@ -610,8 +632,8 @@ static void update_ach_models(void){
    }
 }
 
-static void entity_bh_closest( void *user, u32 item_index, v3f point,
-                                  v3f closest ){
+void entity_bh_closest( void *user, u32 item_index, v3f point, v3f closest )
+{
    world_instance *world = user;
 
    u32 id    = world->entity_list[ item_index ],
@@ -639,7 +661,8 @@ static void entity_bh_closest( void *user, u32 item_index, v3f point,
    }
 }
 
-static void world_entity_start( world_instance *world, vg_msg *sav ){
+void world_entity_start( world_instance *world, vg_msg *sav )
+{
    vg_info( "Start instance %p\n", world );
 
    world->probabilities[ k_probability_curve_constant ] = 1.0f;
@@ -733,7 +756,8 @@ static void world_entity_start( world_instance *world, vg_msg *sav ){
    ent_region_re_eval( world );
 }
 
-static void world_entity_serialize( world_instance *world, vg_msg *sav ){
+void world_entity_serialize( world_instance *world, vg_msg *sav )
+{
    for( u32 i=0; i<mdl_arrcount(&world->ent_challenge); i++ ){
       ent_challenge *challenge = mdl_arritm(&world->ent_challenge,i);
 
@@ -769,5 +793,3 @@ static void world_entity_serialize( world_instance *world, vg_msg *sav ){
       vg_msg_end_frame( sav );
    }
 }
-
-#endif /* WORLD_ENTITY_C */
index a3c5f331c5e97c8cea455ca908418c1930eb6f07..df5cbfadac5c3dc1cb25490652d56352720ec32e 100644 (file)
@@ -1,45 +1,34 @@
-#ifndef WORLD_ENTITY_H
-#define WORLD_ENTITY_H
-
+#pragma once
 #include "world.h"
 #include "entity.h"
-#include "bvh.h"
-#include "save.h"
+#include "vg/vg_bvh.h"
 #include "vg/vg_msg.h"
 
-static void world_gen_entities_init( world_instance *world );
-static ent_spawn *world_find_spawn_by_name( world_instance *world, 
-                                               const char *name );
-static ent_spawn *world_find_closest_spawn( world_instance *world, 
-                                               v3f position );
-static void world_default_spawn_pos( world_instance *world, v3f pos );
-static void world_entity_start( world_instance *world, vg_msg *sav );
-static void world_entity_serialize( world_instance *world, vg_msg *sav );
-
-static void ent_volume_call( world_instance *world, ent_call *call );
-static void ent_audio_call( world_instance *world, ent_call *call );
-static void ent_ccmd_call( world_instance *world, ent_call *call );
+void world_gen_entities_init( world_instance *world );
+ent_spawn *world_find_spawn_by_name( world_instance *world, 
+                                        const char *name );
+ent_spawn *world_find_closest_spawn( world_instance *world, 
+                                        v3f position );
+void world_default_spawn_pos( world_instance *world, v3f pos );
+void world_entity_start( world_instance *world, vg_msg *sav );
+void world_entity_serialize( world_instance *world, vg_msg *sav );
 
-static void entity_bh_expand_bound( void *user, boxf bound, u32 item_index );
-static float entity_bh_centroid( void *user, u32 item_index, int axis );
-static void entity_bh_swap( void *user, u32 ia, u32 ib );
-static void entity_bh_debug( void *user, u32 item_index );
-static void entity_bh_closest( void *user, u32 item_index, v3f point,
-                                  v3f closest );
+void ent_volume_call( world_instance *world, ent_call *call );
+void ent_audio_call( world_instance *world, ent_call *call );
+void ent_ccmd_call( world_instance *world, ent_call *call );
 
-static void world_entity_focus( u32 entity_id );
-static void world_entity_focus_preupdate(void);
-static void world_entity_focus_render(void);
-static void world_entity_unfocus();
-static void world_entity_focus_camera( world_instance *world, u32 uid );
+void entity_bh_expand_bound( void *user, boxf bound, u32 item_index );
+float entity_bh_centroid( void *user, u32 item_index, int axis );
+void entity_bh_swap( void *user, u32 ia, u32 ib );
+void entity_bh_debug( void *user, u32 item_index );
+void entity_bh_closest( void *user, u32 item_index, v3f point,
+                           v3f closest );
 
-static bh_system bh_system_entity_list = {
-   .expand_bound = entity_bh_expand_bound,
-   .item_centroid = entity_bh_centroid,
-   .item_closest = entity_bh_closest,
-   .item_swap = entity_bh_swap,
-   .item_debug = entity_bh_debug,
-   .cast_ray = NULL
-};
+void world_entity_focus( u32 entity_id );
+void world_entity_focus_preupdate(void);
+void world_entity_focus_render(void);
+void world_entity_unfocus();
+void world_entity_focus_camera( world_instance *world, u32 uid );
+void update_ach_models(void);
 
-#endif /* WORLD_ENTITY_H */
+extern bh_system bh_system_entity_list;
index 1631e05dc535b65ea19b925e65962e03271c7743..7212714090f6f82a61beec225fbed109e0994e94 100644 (file)
 #include "model.h"
 #include "entity.h"
 #include "render.h"
-#include "camera.h"
 
 #include "world_water.h"
 #include "player_remote.h"
 #include "shaders/model_gate_unlinked.h"
 
+struct world_gates world_gates;
+
 /*
  * Update the transform matrices for gate
  */
-static void gate_transform_update( ent_gate *gate ){
+void gate_transform_update( ent_gate *gate )
+{
    if( gate->flags & k_ent_gate_flip ){
       v4f qflip;
       q_axis_angle( qflip, (v3f){0.0f,1.0f,0.0f}, VG_PIf );
@@ -41,13 +43,9 @@ static void gate_transform_update( ent_gate *gate ){
    m4x3_mul( recv_to_world, to_local, gate->transport );
 }
 
-static void world_gates_init(void)
+void world_gates_init(void)
 {
    vg_info( "world_gates_init\n" );
-
-   shader_model_gate_register();
-   shader_model_gate_unlinked_register();
-
    vg_linear_clear( vg_mem.scratch );
 
    mdl_context mgate;
@@ -71,7 +69,8 @@ static void world_gates_init(void)
    mdl_close( &mgate );
 }
 
-static void ent_gate_get_mdl_mtx( ent_gate *gate, m4x3f mmdl ){
+void ent_gate_get_mdl_mtx( ent_gate *gate, m4x3f mmdl )
+{
    m4x3_copy( gate->to_world, mmdl );
    
    if( !(gate->flags & k_ent_gate_custom_mesh) ){
@@ -80,7 +79,8 @@ static void ent_gate_get_mdl_mtx( ent_gate *gate, m4x3f mmdl ){
    }
 }
 
-static void render_gate_mesh( world_instance *world, ent_gate *gate ){
+static void render_gate_mesh( world_instance *world, ent_gate *gate )
+{
    if( gate->flags & k_ent_gate_custom_mesh ){
       mesh_bind( &world->mesh_no_collide );
       for( u32 i=0; i<gate->submesh_count; i++ ){
@@ -98,8 +98,9 @@ static void render_gate_mesh( world_instance *world, ent_gate *gate ){
 /*
  * Render the view through a gate
  */
-static int render_gate( world_instance *world, world_instance *world_inside,
-                           ent_gate *gate, camera *cam ){
+int render_gate( world_instance *world, world_instance *world_inside,
+                 ent_gate *gate, vg_camera *cam )
+{
    v3f viewdir, gatedir;
    m3x3_mulv( cam->transform, (v3f){0.0f,0.0f,-1.0f}, viewdir );
    q_mulv( gate->q[0], (v3f){0.0f,0.0f,-1.0f}, gatedir );
@@ -139,8 +140,8 @@ static int render_gate( world_instance *world, world_instance *world_inside,
    world_gates.cam.farz  = 2000.0f;
 
    m4x3_mul( gate->transport, cam->transform, world_gates.cam.transform );
-   camera_update_view( &world_gates.cam );
-   camera_update_projection( &world_gates.cam );
+   vg_camera_update_view( &world_gates.cam );
+   vg_camera_update_projection( &world_gates.cam );
 
    /* Add special clipping plane to projection */
    v4f surface;
@@ -154,7 +155,7 @@ static int render_gate( world_instance *world, world_instance *world_inside,
       m4x4_clip_projection( world_gates.cam.mtx.p, surface );
 
    /* Ready to draw with new camrea */
-   camera_finalize( &world_gates.cam );
+   vg_camera_finalize( &world_gates.cam );
 
    vg_line_point( world_gates.cam.transform[3], 0.3f, 0xff00ff00 );
 
@@ -184,8 +185,9 @@ static int render_gate( world_instance *world, world_instance *world_inside,
    return 1;
 }
 
-static void render_gate_unlinked( world_instance *world,
-                                  ent_gate *gate, camera *cam ){
+void render_gate_unlinked( world_instance *world, 
+                           ent_gate *gate, vg_camera *cam )
+{
    m4x3f mmdl; m4x4f m4mdl;
    ent_gate_get_mdl_mtx( gate, mmdl );
    m4x3_expand( mmdl, m4mdl );
@@ -252,7 +254,8 @@ static int gate_intersect_plane( ent_gate *gate,
 /*
  * Intersect specific gate
  */
-static int gate_intersect( ent_gate *gate, v3f pos, v3f last ){
+int gate_intersect( ent_gate *gate, v3f pos, v3f last )
+{
    v2f xy;
 
    if( gate_intersect_plane( gate, pos, last, xy ) ){
@@ -268,7 +271,8 @@ static int gate_intersect( ent_gate *gate, v3f pos, v3f last ){
 /* 
  * Intersect all gates in the world
  */
-static u32 world_intersect_gates( world_instance *world, v3f pos, v3f last ){
+u32 world_intersect_gates( world_instance *world, v3f pos, v3f last )
+{
    for( u32 i=0; i<mdl_arrcount(&world->ent_gate); i++ ){
       ent_gate *gate = mdl_arritm( &world->ent_gate, i );
 
@@ -288,7 +292,8 @@ static u32 world_intersect_gates( world_instance *world, v3f pos, v3f last ){
    return 0;
 }
 
-static void ent_gate_call( world_instance *world, ent_call *call ){
+void ent_gate_call( world_instance *world, ent_call *call )
+{
    u32 index = mdl_entity_id_id( call->id );
    ent_gate *gate = mdl_arritm( &world->ent_gate, index );
 
@@ -305,7 +310,8 @@ static void ent_gate_call( world_instance *world, ent_call *call ){
 /* 
  * detatches any nonlocal gates 
  */
-static void world_unlink_nonlocal( world_instance *world ){
+void world_unlink_nonlocal( world_instance *world )
+{
    for( u32 j=0; j<mdl_arrcount(&world->ent_gate); j ++ ){
       ent_gate *gate = mdl_arritm( &world->ent_gate, j );
 
@@ -318,7 +324,8 @@ static void world_unlink_nonlocal( world_instance *world ){
 /* 
  * attatches nonlocal gates, to be called from main thread ONLY! 
  */
-static void world_link_nonlocal_async( void *payload, u32 size ){
+void world_link_nonlocal_async( void *payload, u32 size )
+{
    world_instance *world = payload;
    u32 world_id = world - world_static.instances;
 
index 151e428ff7be1172dd9d761572ac2cc097a91f33..03e45685b16b2c1b3908a2039cce8508c0203939 100644 (file)
@@ -1,37 +1,35 @@
 /*
- * Copyright (C) 2021-2023 Mt.ZERO Software, Harry Godden - All Rights Reserved
+ * Copyright (C) 2021-2024 Mt.ZERO Software, Harry Godden - All Rights Reserved
  */
 
-#ifndef WORLD_GATE_H
-#define WORLD_GATE_H
+#pragma once
 
-#include "camera.h"
+#include "vg/vg_camera.h"
 #include "world.h"
 #include "shaders/model_gate.h"
 
-struct world_gates{
+struct world_gates
+{
    glmesh mesh;
    mdl_submesh sm_surface, sm_marker[4];
-   camera cam;
+   vg_camera cam;
 
    v3f userportal_co;
 }
-static world_gates;
+extern world_gates;
 
-static void world_gates_init(void);
-static void gate_transform_update( ent_gate *gate );
-static int render_gate( world_instance *world, world_instance *world_inside,
-                           ent_gate *gate, camera *cam );
+void world_gates_init(void);
+void gate_transform_update( ent_gate *gate );
+int render_gate( world_instance *world, world_instance *world_inside,
+                    ent_gate *gate, vg_camera *cam );
 
-static int gate_intersect( ent_gate *gate, v3f pos, v3f last );
-static u32 world_intersect_gates( world_instance *world, v3f pos, v3f last );
+int gate_intersect( ent_gate *gate, v3f pos, v3f last );
+u32 world_intersect_gates( world_instance *world, v3f pos, v3f last );
 
-static void ent_gate_call( world_instance *world, ent_call *call );
-static void ent_gate_get_mdl_mtx( ent_gate *gate, m4x3f mmdl );
+void ent_gate_call( world_instance *world, ent_call *call );
+void ent_gate_get_mdl_mtx( ent_gate *gate, m4x3f mmdl );
 
-static void world_link_nonlocal_async( void *payload, u32 size );
-static void world_unlink_nonlocal( world_instance *world );
-static void render_gate_unlinked( world_instance *world,
-                                  ent_gate *gate, camera *cam );
-
-#endif /* WORLD_GATE_H */
+void world_link_nonlocal_async( void *payload, u32 size );
+void world_unlink_nonlocal( world_instance *world );
+void render_gate_unlinked( world_instance *world,
+                           ent_gate *gate, vg_camera *cam );
index 1bbc2ca21a7f52a6219e1cef80fdd36bad20480a..047155e6e0cf8d77483c75fff27e6b1a53ba5f50 100644 (file)
@@ -4,10 +4,6 @@
  * World generation/population. Different to regular loading, since it needs to
  * create geometry, apply procedural stuff and save that image to files etc.
  */
-
-#ifndef WORLD_GEN_C
-#define WORLD_GEN_C
-
 #include "world.h"
 #include "world_gen.h"
 #include "world_load.h"
@@ -625,7 +621,7 @@ static void async_world_postprocess( void *payload, u32 _size ){
    /* 
     * Rendering the depth map
     */
-   camera ortho;
+   vg_camera ortho;
 
    v3f extent;
    v3_sub( world->scene_geo.bbx[1], world->scene_geo.bbx[0], extent );
@@ -644,8 +640,8 @@ static void async_world_postprocess( void *payload, u32 _size ){
    ortho.mtx.p[3][1] = (ft + fb) * -tb;
    ortho.mtx.p[3][3] = 1.0f;
    m4x3_identity( ortho.transform );
-   camera_update_view( &ortho );
-   camera_finalize( &ortho );
+   vg_camera_update_view( &ortho );
+   vg_camera_finalize( &ortho );
 
    glDisable(GL_DEPTH_TEST);
    glDisable(GL_BLEND);
@@ -755,5 +751,3 @@ static void world_gen_load_surfaces( world_instance *world ){
       surf->flags = 0;
    }
 }
-
-#endif /* WORLD_GEN_C */
index aaf689fa5e1a533dddfac8af5d9a789a027840a2..f124e244a83d6553e85f262482aecf1e4bb8c262 100644 (file)
@@ -184,15 +184,11 @@ static void skaterift_world_load_done( void *payload, u32 size ){
    world_static.load_state = k_world_loader_none;
 }
 
-struct world_load_args {
-   enum world_purpose purpose;
-   addon_reg *reg;
-};
-
 /*
  * Does a complete world switch using the remaining free slots
  */
-static void skaterift_world_load_thread( void *_args ){
+void skaterift_world_load_thread( void *_args )
+{
    struct world_load_args args = *((struct world_load_args *)_args);
 
    addon_reg *reg = args.reg;
@@ -280,7 +276,8 @@ static void skaterift_world_load_thread( void *_args ){
 
 /* holding pattern before we can start loading the new world, since we might be
  * waiting for audio to stop */
-static void skaterift_change_client_world_preupdate(void){
+void skaterift_change_client_world_preupdate(void)
+{
    for( u32 i=1; i<k_world_max; i++ ){
       world_instance *inst = &world_static.instances[i];
       
@@ -311,7 +308,8 @@ static void skaterift_change_client_world_preupdate(void){
 }
 
 /* places all loaded worlds into unloading state */
-static void skaterift_change_world_start( addon_reg *reg ){
+void skaterift_change_world_start( addon_reg *reg )
+{
    if( world_static.active_instance != 0 )
       vg_error( "Cannot change worlds while in non-root world\n" );
    else{
@@ -346,7 +344,7 @@ static void skaterift_change_world_start( addon_reg *reg ){
 }
 
 /* console command for the above function */
-static int skaterift_load_world_command( int argc, const char *argv[] )
+int skaterift_load_world_command( int argc, const char *argv[] )
 {
    if( !vg_loader_availible() ) 
    {
@@ -391,7 +389,8 @@ static int skaterift_load_world_command( int argc, const char *argv[] )
  *  1. to see if all audios owned by the world have been stopped
  *  2. that this is the least significant world
  */
-static int world_freeable( world_instance *world ){
+int world_freeable( world_instance *world )
+{
    if( world->status != k_world_status_unloading ) return 0;
    u8 world_id = (world - world_static.instances) + 1;
 
@@ -420,7 +419,8 @@ static int world_freeable( world_instance *world ){
 /*
  * Free all resources for world instance
  */
-static void world_free( world_instance *world ){
+void world_free( world_instance *world )
+{
    vg_info( "Free world @%p\n", world );
 
    /* free meshes */
index 3e4722aac36ac33294b2c3e7d6f243e8fcf4aa06..038233ddd86864f5f03678d7a37e6ef5420df45b 100644 (file)
@@ -1,17 +1,11 @@
-#ifndef WORLD_LOAD_H
-#define WORLD_LOAD_H
-
+#pragma once
 #include <time.h>
 
 #include "world.h"
-#include "world_gen.h"
-#include "world_routes.h"
-#include "world_entity.h"
-#include "world_volumes.h"
 #include "addon.h"
 
-static void world_free( world_instance *world );
-static int world_freeable( world_instance *world );
-static int skaterift_load_world_command( int argc, const char *argv[] );
-
-#endif /* WORLD_LOAD_H */
+void world_free( world_instance *world );
+int world_freeable( world_instance *world );
+int skaterift_load_world_command( int argc, const char *argv[] );
+void skaterift_change_world_start( addon_reg *reg );
+void skaterift_change_client_world_preupdate(void);
index c7f6ec82ce4dbb249abf9937c06b75f57f4ec2e4..bc2ab5c9bd9092d82b59d036bd0741c7e82c7a8a 100644 (file)
@@ -1,14 +1,13 @@
-#ifndef RESPAWN_C
-#define RESPAWN_C
-
-#include "world_map.h"
 #include "skaterift.h"
+#include "world_map.h"
 #include "world.h"
 #include "input.h"
 #include "gui.h"
 #include "menu.h"
 #include "scene.h"
 
+struct world_map world_map;
+
 static void world_map_get_dir( v3f dir ){
    /* idk */
    dir[0] = -sqrtf(0.5f);
@@ -40,8 +39,8 @@ static void respawn_world_to_plane_pos( v3f pos, v2f plane_pos ){
    plane_pos[1] = co[2];
 }
 
-static void respawn_map_draw_icon( camera *cam, 
-                                      enum gui_icon icon, v3f pos ){
+static void respawn_map_draw_icon( vg_camera *cam, 
+                                   enum gui_icon icon, v3f pos ){
    v4f v;
    v3_copy( pos, v );
    v[3] = 1.0f;
@@ -51,7 +50,8 @@ static void respawn_map_draw_icon( camera *cam,
    gui_draw_icon( icon, (v2f){ v[0]*0.5f+0.5f,v[1]*0.5f+0.5f }, 1.0f );
 }
 
-static void world_map_pre_update(void){
+void world_map_pre_update(void)
+{
    if( skaterift.activity != k_skaterift_world_map ) return;
 
    if( button_down( k_srbind_mback ) ){
@@ -91,7 +91,7 @@ static void world_map_pre_update(void){
    v2_maxv( (v2f){ bbx[0][0], bbx[0][2] }, pos, pos );
 
    /* update camera */
-   camera *cam = &world_map.cam;
+   vg_camera *cam = &world_map.cam;
    v3f dir;
    world_map_get_dir(dir);
 
@@ -109,10 +109,10 @@ static void world_map_pre_update(void){
    cam->nearz = 10.0f;
    cam->fov = 40.0f;
 
-   camera_update_transform( cam );
-   camera_update_view( cam );
-   camera_update_projection( cam );
-   camera_finalize( cam );
+   vg_camera_update_transform( cam );
+   vg_camera_update_view( cam );
+   vg_camera_update_projection( cam );
+   vg_camera_finalize( cam );
 
    /* pick spawn */
    world_map.spawn = NULL;
@@ -187,7 +187,8 @@ static void world_map_pre_update(void){
    }
 }
 
-static void world_map_enter(void){
+void world_map_enter(void)
+{
    skaterift.activity = k_skaterift_world_map;
    world_map.world_id = world_static.active_instance;
 
@@ -210,5 +211,3 @@ static void world_map_enter(void){
    if( gui_new_helper( input_button_list[k_srbind_mback], &text ) )
       vg_strcat( &text, "exit" );
 }
-
-#endif /* RESPAWN_C */
index 4fbd6fc6af5d6ad36ab219644b2372a7e77a44a7..d4be3b55cb1c2f1ae6741e48156a8dd60b4b491a 100644 (file)
@@ -1,18 +1,18 @@
-#ifndef RESPAWN_H
-#define RESPAWN_H
+#pragma once
+#include "vg/vg_platform.h"
+#include "vg/vg_camera.h"
+#include "world_entity.h"
 
-#include "skaterift.h"
-
-struct {
+struct world_map
+{
    v2f plane_pos;
    f32 boom_dist;
    u32 world_id;
    u32 home_select;
 
    ent_spawn *spawn;
-   camera cam;
+   vg_camera cam;
 }
-static world_map;
-static void world_map_enter(void);
-
-#endif /* RESPAWN_H */
+extern world_map;
+void world_map_enter(void);
+void world_map_pre_update(void);
index ebe8f89110b8b4d2a0793d48809ca502c6e91d45..03be1fc27fd7c7744bd526e6d03b5391eaa4a5d1 100644 (file)
@@ -4,15 +4,14 @@
 #include "world.h"
 #include "world_physics.h"
 
-static void ray_world_get_tri( world_instance *world,
-                                  ray_hit *hit, v3f tri[3] )
+void ray_world_get_tri( world_instance *world, ray_hit *hit, v3f tri[3] )
 {
    for( int i=0; i<3; i++ )
       v3_copy( world->scene_geo.arrvertices[ hit->tri[i] ].co, tri[i] );
 }
 
-static int ray_world( world_instance *world,
-                         v3f pos, v3f dir, ray_hit *hit, u16 ignore )
+int ray_world( world_instance *world,
+               v3f pos, v3f dir, ray_hit *hit, u16 ignore )
 {
    return scene_raycast( &world->scene_geo, world->geo_bh, pos, dir, hit, 
                          ignore );
@@ -21,9 +20,8 @@ static int ray_world( world_instance *world,
 /*
  * Cast a sphere from a to b and see what time it hits
  */
-static int spherecast_world( world_instance *world,
-                                v3f pa, v3f pb, float r, float *t, v3f n,
-                                u16 ignore )
+int spherecast_world( world_instance *world,
+                      v3f pa, v3f pb, float r, float *t, v3f n, u16 ignore )
 {
    boxf region;
    box_init_inf( region );
@@ -80,9 +78,8 @@ static int spherecast_world( world_instance *world,
    return hit;
 }
 
-static 
 struct world_surface *world_tri_index_surface( world_instance *world, 
-                                                 u32 index )
+                                               u32 index )
 {
    for( int i=1; i<world->surface_count; i++ ){
       struct world_surface *surf = &world->surfaces[i];
@@ -97,14 +94,12 @@ struct world_surface *world_tri_index_surface( world_instance *world,
    return &world->surfaces[0];
 }
 
-static struct world_surface *world_contact_surface( world_instance *world,
-                                                         rb_ct *ct )
+struct world_surface *world_contact_surface( world_instance *world, rb_ct *ct )
 {
    return world_tri_index_surface( world, ct->element_id );
 }
 
-static struct world_surface *ray_hit_surface( world_instance *world,
-                                                 ray_hit *hit )
+struct world_surface *ray_hit_surface( world_instance *world, ray_hit *hit )
 {
    return world_tri_index_surface( world, hit->tri[0] );
 }
index 8531b8f1b14f0cc4ff1df6fca94b79c6caf8f575..ce65e5b29d442794ee603abc7ec40842bb0dce83 100644 (file)
@@ -1,27 +1,23 @@
-#ifndef WORLD_PHYSICS_H
-#define WORLD_PHYSICS_H
-
+#pragma once
 #include "world.h"
 #include "vg/vg_rigidbody.h"
 #include "vg/vg_rigidbody_collision.h"
 
-static void ray_world_get_tri( world_instance *world,
-                                  ray_hit *hit, v3f tri[3] );
+void ray_world_get_tri( world_instance *world,
+                           ray_hit *hit, v3f tri[3] );
 
-static int ray_world( world_instance *world,
-                         v3f pos, v3f dir, ray_hit *hit, u16 ignore );
+int ray_world( world_instance *world,
+                  v3f pos, v3f dir, ray_hit *hit, u16 ignore );
 
-static int spherecast_world( world_instance *world,
-                                v3f pa, v3f pb, float r, float *t, v3f n,
-                                u16 ignore );
+int spherecast_world( world_instance *world,
+                         v3f pa, v3f pb, float r, float *t, v3f n,
+                         u16 ignore );
 
-static struct world_surface *world_tri_index_surface( world_instance *world, 
-                                                         u32 index );
+struct world_surface *world_tri_index_surface( world_instance *world, 
+                                                  u32 index );
 
-static struct world_surface *world_contact_surface( world_instance *world,
-                                                         rb_ct *ct );
+struct world_surface *world_contact_surface( world_instance *world,
+                                                  rb_ct *ct );
 
-static struct world_surface *ray_hit_surface( world_instance *world,
+struct world_surface *ray_hit_surface( world_instance *world,
                                                  ray_hit *hit );
-
-#endif /* WORLD_PHYSICS_H */
index c82bc47c90d8f98fc00d1313f66da3d19bcc8169..029a95f62e5f0279ba88004482a023acee683b20 100644 (file)
@@ -2,9 +2,6 @@
  * Copyright (C) 2021-2023 Mt.ZERO Software, Harry Godden - All Rights Reserved
  */
 
-#ifndef WORLD_RENDER_C
-#define WORLD_RENDER_C
-
 #include "world.h"
 #include "world_render.h"
 #include "font.h"
@@ -15,6 +12,8 @@
 #include "ent_skateshop.h"
 #include "shaders/model_entity.h"
 
+struct world_render world_render;
+
 static int ccmd_set_time( int argc, const char *argv[] ){
    world_instance *world = world_current_instance();
    if( argc == 1 )
@@ -66,7 +65,8 @@ static void async_world_render_init( void *payload, u32 size ){
    }
 }
 
-static void world_render_init(void){
+void world_render_init(void)
+{
    VG_VAR_F32( k_day_length );
    VG_VAR_I32( k_debug_light_indices );
    VG_VAR_I32( k_debug_light_complexity );
@@ -77,19 +77,6 @@ static void world_render_init(void){
    world_render.sky_rate = 1.0;
    world_render.sky_target_rate = 1.0;
 
-   shader_scene_standard_register();
-   shader_scene_standard_alphatest_register();
-   shader_scene_foliage_register();
-   shader_scene_override_register();
-   shader_scene_cubemapped_register();
-   shader_scene_fxglow_register();
-   shader_scene_vertex_blend_register();
-   shader_scene_terrain_register();
-   shader_scene_depth_register();
-   shader_scene_position_register();
-   shader_model_sky_register();
-   shader_model_sky_space_register();
-
    vg_info( "Loading world resources\n" );
    vg_linear_clear( vg_mem.scratch );
 
@@ -111,35 +98,40 @@ static void world_render_init(void){
  * standard uniform bindings
  * ----------------------------------------------------------------------------
  */
-static void world_link_lighting_ub( world_instance *world, GLuint shader ){
+void world_link_lighting_ub( world_instance *world, GLuint shader )
+{
    GLuint idx = glGetUniformBlockIndex( shader, "ub_world_lighting" );   
    glUniformBlockBinding( shader, idx, world->ubo_bind_point );
 }
 
-static void world_bind_position_texture( world_instance *world, 
-                                            GLuint shader, GLuint location,
-                                            int slot ){
+void world_bind_position_texture( world_instance *world, 
+                                  GLuint shader, GLuint location,
+                                  int slot )
+{
    render_fb_bind_texture( &world->heightmap, 0, slot );
    glUniform1i( location, slot );
 }
 
-static void world_bind_light_array( world_instance *world,
-                                       GLuint shader, GLuint location, 
-                                       int slot ){
+void world_bind_light_array( world_instance *world,
+                             GLuint shader, GLuint location, 
+                             int slot )
+{
    glActiveTexture( GL_TEXTURE0 + slot );
    glBindTexture( GL_TEXTURE_BUFFER, world->tex_light_entities );
    glUniform1i( location, slot );
 }
 
-static void world_bind_light_index( world_instance *world,
-                                       GLuint shader, GLuint location,
-                                       int slot ){
+void world_bind_light_index( world_instance *world,
+                             GLuint shader, GLuint location,
+                             int slot )
+{
    glActiveTexture( GL_TEXTURE0 + slot );
    glBindTexture( GL_TEXTURE_3D, world->tex_light_cubes );
    glUniform1i( location, slot );
 }
 
-static void bind_terrain_noise(void){
+void bind_terrain_noise(void)
+{
    glActiveTexture( GL_TEXTURE0 );
    glBindTexture( GL_TEXTURE_2D, world_render.tex_terrain_noise );
 }
@@ -165,7 +157,7 @@ static void bindpoint_diffuse_texture1( world_instance *world,
  */
 
 struct world_pass{
-   camera *cam;
+   vg_camera *cam;
    enum mdl_shader shader;
    enum world_geo_type geo_type;
 
@@ -176,7 +168,7 @@ struct world_pass{
    void (*fn_set_uNormalMtx)( m3x3f mnorm );
 };
 
-static void render_world_depth( world_instance *world, camera *cam );
+void render_world_depth( world_instance *world, vg_camera *cam );
 
 /*
  * Render a run of submeshes, only of those which match material_id
@@ -293,7 +285,7 @@ static void world_render_both_stages( world_instance *world,
    glEnable( GL_CULL_FACE );
 }
 
-static void render_world_vb( world_instance *world, camera *cam ){
+static void render_world_vb( world_instance *world, vg_camera *cam ){
    shader_scene_vertex_blend_use();
    shader_scene_vertex_blend_uTexGarbage(0);
    shader_scene_vertex_blend_uTexGradients(1);
@@ -316,7 +308,7 @@ static void render_world_vb( world_instance *world, camera *cam ){
    world_render_both_stages( world, &pass );
 }
 
-static void world_shader_standard_bind( world_instance *world, camera *cam ){
+static void world_shader_standard_bind( world_instance *world, vg_camera *cam ){
    shader_scene_standard_use();
    shader_scene_standard_uTexGarbage(0);
    shader_scene_standard_uTexMain(1);
@@ -327,7 +319,7 @@ static void world_shader_standard_bind( world_instance *world, camera *cam ){
    shader_scene_standard_uCamera( cam->transform[3] );
 }
 
-static void render_world_standard( world_instance *world, camera *cam ){
+static void render_world_standard( world_instance *world, vg_camera *cam ){
    world_shader_standard_bind( world, cam );
    struct world_pass pass = {
       .shader = k_shader_standard,
@@ -360,7 +352,7 @@ static void bindpoint_diffuse1_and_cubemap10( world_instance *world,
    shader_scene_cubemapped_uColour( mat->info.colour );
 }
 
-static void render_world_cubemapped( world_instance *world, camera *cam,
+static void render_world_cubemapped( world_instance *world, vg_camera *cam,
                                      int enabled ){
    if( !mdl_arrcount( &world->ent_cubemap ) )
       return;
@@ -402,7 +394,7 @@ static void render_world_cubemapped( world_instance *world, camera *cam,
    }
 }
 
-static void render_world_alphatest( world_instance *world, camera *cam ){
+static void render_world_alphatest( world_instance *world, vg_camera *cam ){
    shader_scene_standard_alphatest_use();
    shader_scene_standard_alphatest_uTexGarbage(0);
    shader_scene_standard_alphatest_uTexMain(1);
@@ -426,7 +418,7 @@ static void render_world_alphatest( world_instance *world, camera *cam ){
    glEnable(GL_CULL_FACE);
 }
 
-static void render_world_foliage( world_instance *world, camera *cam ){
+static void render_world_foliage( world_instance *world, vg_camera *cam ){
    shader_scene_foliage_use();
    shader_scene_foliage_uTexGarbage(0);
    shader_scene_foliage_uTexMain(1);
@@ -613,7 +605,7 @@ static void world_render_challenges( world_instance *world,
 }
 
 static void render_world_fxglow( world_instance *host_world, 
-                                 world_instance *world, camera *cam,
+                                 world_instance *world, vg_camera *cam,
                                  m4x3f world_mmdl,
                                  int generic, int challenges, int regions ){
    shader_scene_fxglow_use();
@@ -700,7 +692,7 @@ static void bindpoint_override( world_instance *world,
    }
 }
 
-static void render_terrain( world_instance *world, camera *cam ){
+static void render_terrain( world_instance *world, vg_camera *cam ){
    shader_scene_terrain_use();
    shader_scene_terrain_uTexGarbage(0);
    shader_scene_terrain_uTexGradients(1);
@@ -723,7 +715,7 @@ static void render_terrain( world_instance *world, camera *cam ){
    world_render_both_stages( world, &pass );
 }
 
-static void render_sky( world_instance *world, camera *cam ){
+static void render_sky( world_instance *world, vg_camera *cam ){
    /* 
     * Modify matrix to remove clipping and view translation
     */
@@ -793,7 +785,8 @@ static void render_sky( world_instance *world, camera *cam ){
    glDepthMask( GL_TRUE );
 }
 
-static void render_world_gates( world_instance *world, camera *cam ){
+void render_world_gates( world_instance *world, vg_camera *cam )
+{
    float closest = INFINITY;
    struct ent_gate *gate = NULL;
 
@@ -838,7 +831,8 @@ static void render_world_gates( world_instance *world, camera *cam ){
    }
 }
 
-static void world_prerender( world_instance *world ){
+void world_prerender( world_instance *world )
+{
    if( mdl_arrcount( &world->ent_light ) ){
       f32 rate = vg_maxf(0.1f, fabsf(k_day_length)) * vg_signf(k_day_length);
       world->time += vg.time_frame_delta * (1.0/(rate*60.0));
@@ -892,7 +886,7 @@ static void world_prerender( world_instance *world ){
                     sizeof(struct ub_world_lighting), &world->ub_lighting );
 }
 
-static void render_other_entities( world_instance *world, camera *cam ){
+static void render_other_entities( world_instance *world, vg_camera *cam ){
    f32 radius = 40.0f;
    bh_iter it;
    bh_iter_init_range( 0, &it, cam->pos, radius+10.0f );
@@ -936,9 +930,10 @@ static void render_other_entities( world_instance *world, camera *cam ){
    }
 }
 
-static void render_world( world_instance *world, camera *cam,
-                          int stenciled, int viewing_from_gate, 
-                          int with_water, int with_cubemaps ){
+void render_world( world_instance *world, vg_camera *cam,
+                   int stenciled, int viewing_from_gate, 
+                   int with_water, int with_cubemaps )
+{
    if( stenciled ){
       glClear( GL_DEPTH_BUFFER_BIT );
       glStencilFunc( GL_EQUAL, 1, 0xFF );
@@ -1068,11 +1063,12 @@ static void render_world_override_pass( world_instance *world,
    }
 }
 
-static void render_world_override( world_instance *world,
-                                   world_instance *lighting_source,
-                                   m4x3f mmdl,
-                                   camera *cam,
-                                   ent_spawn *dest_spawn, v4f map_info ){
+void render_world_override( world_instance *world,
+                            world_instance *lighting_source,
+                            m4x3f mmdl,
+                            vg_camera *cam,
+                            ent_spawn *dest_spawn, v4f map_info )
+{
    struct world_pass pass = {
       .cam = cam,
       .fn_bind_textures = bindpoint_override,
@@ -1136,7 +1132,7 @@ static void render_world_override( world_instance *world,
 
 static void render_cubemap_side( world_instance *world, ent_cubemap *cm, 
                                     u32 side ){
-   camera cam;
+   vg_camera cam;
    glFramebufferTexture2D( GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
          GL_TEXTURE_CUBE_MAP_POSITIVE_X + side, cm->texture_id, 0 );
    glClear( GL_DEPTH_BUFFER_BIT );
@@ -1167,20 +1163,21 @@ static void render_cubemap_side( world_instance *world, ent_cubemap *cm,
    v3_copy( cm->co, cam.transform[3] );
    m4x3_invert_affine( cam.transform, cam.transform_inverse );
 
-   camera_update_view( &cam );
+   vg_camera_update_view( &cam );
 
    cam.nearz = 0.1f;
    cam.farz = 1000.0f;
    cam.fov = 90.0f;
    m4x4_copy( cam.mtx.p,  cam.mtx_prev.p );
    m4x4_projection( cam.mtx.p, cam.fov, 1.0f, cam.nearz, cam.farz );
-   camera_finalize( &cam );
-   camera_finalize( &cam );
+   vg_camera_finalize( &cam );
+   vg_camera_finalize( &cam );
 
    render_world( world, &cam, 0, 1, 1, 0 );
 }
 
-static void render_world_cubemaps( world_instance *world ){
+void render_world_cubemaps( world_instance *world )
+{
    if( world->cubemap_cooldown )
       world->cubemap_cooldown --;
    else{
@@ -1205,7 +1202,8 @@ static void render_world_cubemaps( world_instance *world ){
  * ---------------------------------------------
  */
 
-static void render_world_depth( world_instance *world, camera *cam ){
+void render_world_depth( world_instance *world, vg_camera *cam )
+{
    m4x3f identity_matrix;
    m4x3_identity( identity_matrix );
 
@@ -1220,7 +1218,8 @@ static void render_world_depth( world_instance *world, camera *cam ){
    mesh_draw( &world->mesh_geo );
 }
 
-static void render_world_position( world_instance *world, camera *cam ){
+void render_world_position( world_instance *world, vg_camera *cam )
+{
    m4x3f identity_matrix;
    m4x3_identity( identity_matrix );
 
@@ -1254,7 +1253,8 @@ static f32 *skybox_prop_location( world_instance *world, i32 index ){
    }
 }
 
-static void imgui_world_light_edit( world_instance *world ){
+void imgui_world_light_edit( world_instance *world )
+{
    ui_rect panel = { vg.window_x-400, 0, 400, vg.window_y };
    ui_fill( panel, ui_colour( k_ui_bg+1 ) );
    ui_outline( panel, 1, ui_colour( k_ui_bg+7 ), 0 );
@@ -1278,5 +1278,3 @@ static void imgui_world_light_edit( world_instance *world ){
       fclose( fp );
    }
 }
-
-#endif
index ecbd3d22ec093a78cb68dfb128df537b2a3f3340..846e2d83f7f53694147231ca09a02b2246a3caaf 100644 (file)
@@ -1,15 +1,13 @@
 /*
- * Copyright (C) 2021-2023 Mt.ZERO Software, Harry Godden - All Rights Reserved
+ * Copyright (C) 2021-2024 Mt.ZERO Software, Harry Godden - All Rights Reserved
  */
 
-#ifndef WORLD_RENDER_H
-#define WORLD_RENDER_H
+#pragma once
 
 #define WORLD_CUBEMAP_RES 32
 
-#include "camera.h"
+#include "vg/vg_camera.h"
 #include "world.h"
-
 #include "shaders/scene_standard.h"
 #include "shaders/scene_standard_alphatest.h"
 #include "shaders/scene_foliage.h"
@@ -26,7 +24,8 @@
 
 static const float k_world_light_cube_size = 8.0f;
 
-struct world_render{
+struct world_render
+{
    GLuint tex_terrain_noise;
 
    /* rendering */
@@ -61,31 +60,35 @@ struct world_render{
    text_particles[6*4];
    u32 text_particle_count;
 }
-static world_render;
-static void world_render_init(void);
+extern world_render;
+
+void world_render_init(void);
 
-static void world_link_lighting_ub( world_instance *world, GLuint shader );
-static void world_bind_position_texture( world_instance *world, 
-                                            GLuint shader, GLuint location,
-                                            int slot );
-static void world_bind_light_array( world_instance *world,
-                                       GLuint shader, GLuint location, 
-                                       int slot );
-static void world_bind_light_index( world_instance *world,
-                                       GLuint shader, GLuint location,
-                                       int slot );
-static void render_world_position( world_instance *world, camera *cam );
-static void render_world_depth( world_instance *world, camera *cam );
-static void render_world( world_instance *world, camera *cam,
-                          int stenciled, int viewing_from_gate, 
-                          int with_water, int with_cubemaps );
-static void render_world_cubemaps( world_instance *world );
-static void bind_terrain_noise(void);
-static void render_world_override( world_instance *world,
-                                   world_instance *lighting_source,
-                                   m4x3f mmdl,
-                                   camera *cam,
-                                   ent_spawn *dest_spawn, v4f map_info );
+void world_prerender( world_instance *world );
+void world_link_lighting_ub( world_instance *world, GLuint shader );
+void world_bind_position_texture( world_instance *world, 
+                                  GLuint shader, GLuint location,
+                                  int slot );
+void world_bind_light_array( world_instance *world,
+                             GLuint shader, GLuint location, 
+                             int slot );
+void world_bind_light_index( world_instance *world,
+                             GLuint shader, GLuint location,
+                             int slot );
+void render_world_position( world_instance *world, vg_camera *cam );
+void render_world_depth( world_instance *world, vg_camera *cam );
+void render_world( world_instance *world, vg_camera *cam,
+                   int stenciled, int viewing_from_gate, 
+                   int with_water, int with_cubemaps );
+void render_world_cubemaps( world_instance *world );
+void bind_terrain_noise(void);
+void render_world_override( world_instance *world,
+                            world_instance *lighting_source,
+                            m4x3f mmdl,
+                            vg_camera *cam,
+                            ent_spawn *dest_spawn, v4f map_info );
+void render_world_gates( world_instance *world, vg_camera *cam );
+void imgui_world_light_edit( world_instance *world );
 
 #define WORLD_BIND_LIGHT_BUFFERS_UB0_TEX234( WORLD, SHADER )            \
    world_link_lighting_ub( WORLD, _shader_##SHADER.id );                \
@@ -96,4 +99,3 @@ static void render_world_override( world_instance *world,
    world_bind_light_index( WORLD, _shader_##SHADER.id,                  \
                            _uniform_##SHADER##_uLightsIndex, 4 );
 
-#endif /* WORLD_RENDER_H */
index 4ee50d8cb42539e32c4792818ff31065cd0685fb..c4b339385bc9794df093d1789f76d93b321c9382 100644 (file)
@@ -24,7 +24,7 @@
 #include "ent_region.h"
 #include "scene_rigidbody.h"
 
-static void world_routes_clear( world_instance *world )
+void world_routes_clear( world_instance *world )
 {
    for( u32 i=0; i<mdl_arrcount( &world->ent_route ); i++ ){
       ent_route *route = mdl_arritm( &world->ent_route, i );
@@ -144,8 +144,7 @@ static void world_routes_time_lap( world_instance *world, ent_route *route ){
 /*
  * When going through a gate this is called for bookkeeping purposes
  */
-static void world_routes_activate_entry_gate( world_instance *world, 
-                                                 ent_gate *rg )
+void world_routes_activate_entry_gate( world_instance *world, ent_gate *rg )
 {
    world_static.last_use = world_static.time;
    ent_gate *dest = mdl_arritm( &world->ent_gate, rg->target );
@@ -477,14 +476,14 @@ static void world_routes_gen_meshes( world_instance *world, u32 route_id,
    scene_copy_slice( sc, &route->sm );
 }
 
-static 
 struct world_surface *world_tri_index_surface( world_instance *world, 
                                                  u32 index );
 
 /* 
  * Create the strips of colour that run through the world along course paths
  */
-static void world_gen_routes_generate( u32 instance_id ){
+void world_gen_routes_generate( u32 instance_id )
+{
    world_instance *world = &world_static.instances[ instance_id ];
    vg_info( "Generating route meshes\n" );
    vg_async_stall();
@@ -541,7 +540,8 @@ static void world_gen_routes_generate( u32 instance_id ){
 }
 
 /* load all routes from model header */
-static void world_gen_routes_ent_init( world_instance *world ){
+void world_gen_routes_ent_init( world_instance *world )
+{
    vg_info( "Initializing routes\n" );
 
    for( u32 i=0; i<mdl_arrcount(&world->ent_gate); i++ ){
@@ -614,9 +614,10 @@ static void world_gen_routes_ent_init( world_instance *world ){
    world_routes_clear( world );
 }
 
-static void world_routes_recv_scoreboard( world_instance *world, 
-                                          vg_msg *body, u32 route_id,
-                                          enum request_status status ){
+void world_routes_recv_scoreboard( world_instance *world, 
+                                   vg_msg *body, u32 route_id,
+                                   enum request_status status )
+{
    if( route_id >= mdl_arrcount( &world->ent_route ) ){
       vg_error( "Scoreboard route_id out of range (%u)\n", route_id );
       return;
@@ -646,16 +647,15 @@ static void world_routes_recv_scoreboard( world_instance *world,
  * -----------------------------------------------------------------------------
  */
 
-static void world_routes_init(void){
+void world_routes_init(void)
+{
    world_static.current_run_version = 200;
    world_static.time = 300.0;
    world_static.last_use = 0.0;
-
-   shader_scene_route_register();
-   shader_routeui_register();
 }
 
-static void world_routes_update( world_instance *world ){
+void world_routes_update( world_instance *world )
+{
    world_static.time += vg.time_delta;
 
    for( u32 i=0; i<mdl_arrcount(&world->ent_route); i++ ){
@@ -672,7 +672,8 @@ static void world_routes_update( world_instance *world ){
    }
 }
 
-static void world_routes_fixedupdate( world_instance *world ){
+void world_routes_fixedupdate( world_instance *world )
+{
    rb_solver_reset();
 
    rigidbody _null = {0};
@@ -721,15 +722,16 @@ static void world_routes_fixedupdate( world_instance *world ){
    }
 }
 
-static void bind_terrain_noise(void);
-static void world_bind_light_array( world_instance *world,
-                                       GLuint shader, GLuint location, 
-                                       int slot );
-static void world_bind_light_index( world_instance *world,
-                                       GLuint shader, GLuint location, 
-                                       int slot );
+void bind_terrain_noise(void);
+void world_bind_light_array( world_instance *world,
+                             GLuint shader, GLuint location, 
+                             int slot );
+void world_bind_light_index( world_instance *world,
+                             GLuint shader, GLuint location, 
+                             int slot );
 
-static void world_routes_update_timer_texts( world_instance *world ){
+void world_routes_update_timer_texts( world_instance *world )
+{
    world_render.timer_text_count = 0;
 
    for( u32 i=0; i<mdl_arrcount(&world->ent_route); i++ ){
@@ -837,8 +839,8 @@ static void world_routes_update_timer_texts( world_instance *world ){
    }
 }
 
-static void world_routes_fracture( world_instance *world, ent_gate *gate,
-                                      v3f imp_co, v3f imp_v )
+void world_routes_fracture( world_instance *world, ent_gate *gate,
+                            v3f imp_co, v3f imp_v )
 {
    world_render.text_particle_count = 0;
    
@@ -925,11 +927,11 @@ static void render_gate_markers( m4x3f world_mmdl, int run_id, ent_gate *gate ){
    }
 }
 
-static void render_world_routes( world_instance *world, 
-                                 world_instance *host_world,
-                                 m4x3f mmdl, camera *cam, 
-                                 int viewing_from_gate, int viewing_from_hub ){
-
+void render_world_routes( world_instance *world, 
+                          world_instance *host_world,
+                          m4x3f mmdl, vg_camera *cam, 
+                          int viewing_from_gate, int viewing_from_hub )
+{
    shader_scene_route_use();
    shader_scene_route_uTexGarbage(0);
    world_link_lighting_ub( host_world, _shader_scene_route.id );
index 5fccc9e0f2a60d09a77ac1ca59540fd5b38b4a34..6467977f53e285d226a4410fd9f4fb7673401fe4 100644 (file)
@@ -2,30 +2,27 @@
  * Copyright (C) 2021-2023 Mt.ZERO Software, Harry Godden - All Rights Reserved
  */
 
-#ifndef ROUTES_H
-#define ROUTES_H
-
+#pragma once
+#include "vg/vg_camera.h"
 #include "world.h"
 #include "network_msg.h"
 
-static void world_routes_init(void);
-static void world_routes_fracture( world_instance *world, ent_gate *gate,
-                                      v3f imp_co, v3f imp_v );
-static void world_routes_activate_entry_gate( world_instance *world, 
-                                                 ent_gate *rg );
-static void render_world_routes( world_instance *world, 
-                                 world_instance *host_world,
-                                 m4x3f mmdl, camera *cam, 
-                                 int viewing_from_gate, int viewing_from_hub );
-
-static void world_gen_routes_ent_init( world_instance *world );
-static void world_gen_routes_generate( u32 instance_id );
-static void world_routes_update_timer_texts( world_instance *world );
-static void world_routes_update( world_instance *world );
-static void world_routes_fixedupdate( world_instance *world );
-static void world_routes_clear( world_instance *world );
-static void world_routes_recv_scoreboard( world_instance *world, 
-                                          vg_msg *body, u32 route_id,
-                                          enum request_status status );
+void world_routes_init(void);
+void world_routes_fracture( world_instance *world, ent_gate *gate,
+                               v3f imp_co, v3f imp_v );
+void world_routes_activate_entry_gate( world_instance *world, 
+                                          ent_gate *rg );
+void render_world_routes( world_instance *world, 
+                          world_instance *host_world,
+                          m4x3f mmdl, vg_camera *cam, 
+                          int viewing_from_gate, int viewing_from_hub );
 
-#endif /* ROUTES_H */
+void world_gen_routes_ent_init( world_instance *world );
+void world_gen_routes_generate( u32 instance_id );
+void world_routes_update_timer_texts( world_instance *world );
+void world_routes_update( world_instance *world );
+void world_routes_fixedupdate( world_instance *world );
+void world_routes_clear( world_instance *world );
+void world_routes_recv_scoreboard( world_instance *world, 
+                                   vg_msg *body, u32 route_id,
+                                   enum request_status status );
index 4d39e9cce004542603187eaf9438adfe465bcee7..ace8a3d5bad0716eb02b9f6d66326e734b865e0d 100644 (file)
@@ -148,7 +148,8 @@ static void ent_route_imgui( world_instance *world, ent_route *route,
                                  vg.time_frame_delta );
 }
 
-static void world_routes_imgui( world_instance *world ){
+void world_routes_imgui( world_instance *world )
+{
    ui_point cursor = { 4, 4 };
    for( u32 i=0; i<mdl_arrcount(&world->ent_route); i++ ){
       ent_route_imgui( world, mdl_arritm( &world->ent_route, i ), cursor );
index 00bfe421c209ee5afa477f77acde740930119ae8..a821f7f23cccedee376ba20f9bb5a2de4545e3f8 100644 (file)
@@ -1,10 +1,5 @@
-#ifndef WORLD_ROUTES_UI_H
-#define WORLD_ROUTES_UI_H
-
+#pragma once
 #include "world_routes.h"
 
-struct route_ui{
-};
-
-static void ent_region_re_eval( world_instance *world );
-#endif /* WORLD_ROUTES_UI_H */
+struct route_ui{};
+void world_routes_imgui( world_instance *world );
index fbe07d36d1230319c3e0671d6c2df9a6d4619b53..ef4fc3bc7726fe4f29a21efb17601856912c05ad 100644 (file)
@@ -9,6 +9,8 @@
 #include "network_common.h"
 #include "world_routes.h"
 
+struct world_sfd world_sfd;
+
 static f32 sfd_encode_glyph( char c ){
    int value = 0;
    if( c >= 'a' && c <= 'z' )
@@ -50,7 +52,8 @@ static void sfd_clear( u32 row ){
    }
 }
 
-static void sfd_encode( v2i co, const char *str, enum world_sfd_align align ){
+void sfd_encode( v2i co, const char *str, enum world_sfd_align align )
+{
    i32 row_h = world_sfd.h -1 -co[1];
    i32 offset_x = 0;
 
@@ -76,8 +79,9 @@ static void sfd_encode( v2i co, const char *str, enum world_sfd_align align ){
    }
 }
 
-static void world_sfd_compile_scores( struct leaderboard_cache *board,
-                                      const char *title ){
+void world_sfd_compile_scores( struct leaderboard_cache *board,
+                               const char *title )
+{
    for( u32 i=0; i<13; i++ )
       sfd_clear(i);
 
@@ -169,7 +173,8 @@ static void world_sfd_compile_scores( struct leaderboard_cache *board,
    }
 }
 
-static void world_sfd_compile_active_scores(void){
+void world_sfd_compile_active_scores(void)
+{
    world_instance *world = world_current_instance();
    
    struct leaderboard_cache *board = NULL;
@@ -185,7 +190,8 @@ static void world_sfd_compile_active_scores(void){
    world_sfd_compile_scores( board, name );
 }
 
-static void world_sfd_update( world_instance *world, v3f pos ){
+void world_sfd_update( world_instance *world, v3f pos )
+{
    if( mdl_arrcount( &world->ent_route ) ){
       u32 closest = 0;
       float min_dist = INFINITY;
@@ -246,8 +252,9 @@ static void world_sfd_update( world_instance *world, v3f pos ){
    }
 }
 
-static void bind_terrain_noise(void);
-static void sfd_render( world_instance *world, camera *cam, m4x3f transform ){
+void bind_terrain_noise(void);
+void sfd_render( world_instance *world, vg_camera *cam, m4x3f transform )
+{
    mesh_bind( &world_sfd.mesh_display );
    shader_scene_scoretext_use();
    shader_scene_scoretext_uTexMain(1);
@@ -293,9 +300,9 @@ static void sfd_render( world_instance *world, camera *cam, m4x3f transform ){
    mdl_draw_submesh( &world_sfd.sm_base );
 }
 
-static void world_sfd_init(void){
+void world_sfd_init(void)
+{
    vg_info( "world_sfd_init\n" );
-   shader_scene_scoretext_register();
    vg_linear_clear( vg_mem.scratch );
 
    mdl_context mscoreboard;
index 176425dfea664ba49112f004dc90c993602e64b0..e79fbbca30430fd5c190f5397b15546da1f12a48 100644 (file)
@@ -1,10 +1,7 @@
 /*
- * Copyright (C) 2021-2023 Mt.ZERO Software, Harry Godden - All Rights Reserved
+ * Copyright (C) 2021-2024 Mt.ZERO Software, Harry Godden - All Rights Reserved
  */
-
-#ifndef SFD_H
-#define SFD_H
-
+#pragma once
 #include "world.h"
 #include "world_routes.h"
 #include "scene.h"
@@ -23,8 +20,8 @@ struct world_sfd{
    u32 w, h;
    float *buffer;
 }
-static world_sfd;
-static void world_sfd_init(void);
+extern world_sfd;
+void world_sfd_init(void);
 
 enum world_sfd_align {
    k_world_sfd_left,
@@ -32,11 +29,9 @@ enum world_sfd_align {
    k_world_sfd_center
 };
 
-static void sfd_encode( v2i co, const char *str, enum world_sfd_align align );
-static void sfd_render( world_instance *world, camera *cam, 
-                           m4x3f transform );
-static void world_sfd_compile_scores( struct leaderboard_cache *leaderboard,
-                                      const char *title );
-static void world_sfd_compile_active_scores(void);
-
-#endif /* SFD_H */
+void sfd_encode( v2i co, const char *str, enum world_sfd_align align );
+void world_sfd_update( world_instance *world, v3f pos );
+void sfd_render( world_instance *world, vg_camera *cam, m4x3f transform );
+void world_sfd_compile_scores( struct leaderboard_cache *leaderboard,
+                               const char *title );
+void world_sfd_compile_active_scores(void);
index 7f2b685170e6f1ce784ef60529e4927dd32516a1..ae507d0cffec927296435ae7f3bd0c25677de15e 100644 (file)
@@ -1,9 +1,7 @@
-#ifndef WORLD_VOLUMES_C
-#define WORLD_VOLUMES_C
-
 #include "world_volumes.h"
 
-static void world_volumes_update( world_instance *world, v3f pos ){
+void world_volumes_update( world_instance *world, v3f pos )
+{
    /* filter and check the existing ones */
    u32 j=0;
    for( u32 i=0; i<world_static.active_trigger_volume_count; i++ ){
@@ -103,5 +101,3 @@ static void world_volumes_update( world_instance *world, v3f pos ){
 next_volume:;
    }
 }
-
-#endif /* WORLD_VOLUMES_H */
index 199a09679558fe0da1aa3d25ff0e656aea0c0cf3..2d84e9e00ac8f2f2454a095f97f52a7e203ce7d1 100644 (file)
@@ -1,7 +1,5 @@
-#ifndef WORLD_VOLUMES_H
-#define WORLD_VOLUMES_H
-
+#pragma once
 #include "world.h"
-#include "bvh.h"
+#include "vg/vg_bvh.h"
 
-#endif /* WORLD_VOLUMES_H */
+void world_volumes_update( world_instance *world, v3f pos );
index 62e133d72d7cd31181621dae41668e32378a0645..0c6ac541064b2b353623dcd8a639490f89824d59 100644 (file)
 #include "shaders/scene_water_fast.h"
 #include "scene.h"
 
-static void world_water_init(void){
+struct world_water world_water;
+
+void world_water_init(void)
+{
    vg_info( "world_water_init\n" );
-   shader_scene_water_register();
-   shader_scene_water_fast_register();
 
    vg_tex2d_load_qoi_async_file( "textures/water_surf.qoi",
                                  VG_TEX2D_LINEAR|VG_TEX2D_REPEAT,
@@ -24,26 +25,28 @@ static void world_water_init(void){
    vg_success( "done\n" );
 }
 
-static void water_set_surface( world_instance *world, float height ){
+void water_set_surface( world_instance *world, float height )
+{
    world->water.height = height;
    v4_copy( (v4f){ 0.0f, 1.0f, 0.0f, height }, world->water.plane );
 }
 
-static void world_link_lighting_ub( world_instance *world, GLuint shader );
-static void world_bind_position_texture( world_instance *world, 
-                                            GLuint shader, GLuint location,
-                                            int slot );
-static void world_bind_light_array( world_instance *world,
-                                       GLuint shader, GLuint location, 
-                                       int slot );
-static void world_bind_light_index( world_instance *world,
+void world_link_lighting_ub( world_instance *world, GLuint shader );
+void world_bind_position_texture( world_instance *world, 
+                                     GLuint shader, GLuint location,
+                                     int slot );
+void world_bind_light_array( world_instance *world,
+                                GLuint shader, GLuint location, 
+                                int slot );
+void world_bind_light_index( world_instance *world,
                                        GLuint shader, GLuint location, 
                                        int slot );
 
 /*
  * Does not write motion vectors
  */
-static void render_water_texture( world_instance *world, camera *cam ){
+void render_water_texture( world_instance *world, vg_camera *cam )
+{
    if( !world->water.enabled || (vg.quality_profile == k_quality_profile_low) )
       return;
 
@@ -56,7 +59,7 @@ static void render_water_texture( world_instance *world, camera *cam ){
     */
    float cam_height = cam->transform[3][1] - world->water.height;
 
-   camera water_cam;
+   vg_camera water_cam;
    water_cam.farz = cam->farz;
    water_cam.nearz = cam->nearz;
    v3_copy( cam->transform[3], water_cam.transform[3] );
@@ -67,7 +70,7 @@ static void render_water_texture( world_instance *world, camera *cam ){
    flip[1][1] = -1.0f;
    m3x3_mul( flip, cam->transform, water_cam.transform );
 
-   camera_update_view( &water_cam );
+   vg_camera_update_view( &water_cam );
 
    /* 
     * Create clipped projection 
@@ -79,7 +82,7 @@ static void render_water_texture( world_instance *world, camera *cam ){
    m4x4_copy( cam->mtx.p, water_cam.mtx.p );
    m4x4_clip_projection( water_cam.mtx.p, clippa );
 
-   camera_finalize( &water_cam );
+   vg_camera_finalize( &water_cam );
 
    /*
     * Draw world
@@ -93,13 +96,13 @@ static void render_water_texture( world_instance *world, camera *cam ){
    /*
     * Create beneath view matrix
     */
-   camera beneath_cam;
+   vg_camera beneath_cam;
    render_fb_bind( gpipeline.fb_water_beneath, 1 );
    glClearColor( 1.0f, 0.0f, 0.0f, 0.0f );
    glClear( GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT );
 
    m4x3_copy( cam->transform, beneath_cam.transform );
-   camera_update_view( &beneath_cam );
+   vg_camera_update_view( &beneath_cam );
 
    float bias = -(cam->transform[3][1]-world->water.height)*0.1f;
 
@@ -109,7 +112,7 @@ static void render_water_texture( world_instance *world, camera *cam ){
 
    m4x4_copy( cam->mtx.p, beneath_cam.mtx.p );
    m4x4_clip_projection( beneath_cam.mtx.p, clippb );
-   camera_finalize( &beneath_cam );
+   vg_camera_finalize( &beneath_cam );
 
    glEnable( GL_DEPTH_TEST );
    glDisable( GL_BLEND );
@@ -117,7 +120,8 @@ static void render_water_texture( world_instance *world, camera *cam ){
    //glViewport( 0,0, g_render_x, g_render_y );
 }
 
-static void render_water_surface( world_instance *world, camera *cam ){
+void render_water_surface( world_instance *world, vg_camera *cam )
+{
    if( !world->water.enabled )
       return;
 
index b45ee3a260ab351b783544234a386026e7ccc899..47855b22fe8a6d8b717f441e84c6c210eef78f30 100644 (file)
@@ -2,19 +2,15 @@
  * Copyright (C) 2021-2023 Mt.ZERO Software, Harry Godden - All Rights Reserved
  */
 
-#ifndef WATER_H
-#define WATER_H
-
+#pragma once
 #include "world.h"
 
 struct world_water{
    GLuint tex_water_surf;
 }
-static world_water;
-static void world_water_init(void);
-
-static void water_set_surface( world_instance *world, float height );
-static void render_water_texture( world_instance *world, camera *cam );
-static void render_water_surface( world_instance *world, camera *cam );
+extern world_water;
+void world_water_init(void);
 
-#endif /* WATER_H */
+void water_set_surface( world_instance *world, f32 height );
+void render_water_texture( world_instance *world, vg_camera *cam );
+void render_water_surface( world_instance *world, vg_camera *cam );