From 5f6a4f9df6c8accc89f1920bfe9ace3cbac4c4b6 Mon Sep 17 00:00:00 2001 From: hgn Date: Fri, 23 Feb 2024 03:33:09 +0000 Subject: [PATCH] revision 2 --- addon.c | 89 +- addon.h | 92 +- addon_types.c | 20 + addon_types.h | 28 +- audio.c | 264 + audio.h | 300 +- build.c | 5 +- bvh.h | 416 - camera.h | 9 +- depth_compare.h | 12 +- ent_challenge.c | 11 +- ent_challenge.h | 10 +- ent_miniworld.c | 20 +- ent_miniworld.h | 20 +- ent_objective.c | 11 +- ent_objective.h | 4 + ent_region.c | 11 +- ent_region.h | 15 +- ent_relay.c | 10 +- ent_relay.h | 3 + ent_route.c | 13 +- ent_route.h | 15 +- ent_skateshop.c | 29 +- ent_skateshop.h | 25 +- ent_tornado.c | 12 +- ent_tornado.h | 6 + ent_traffic.c | 5 - ent_traffic.h | 8 +- entity.c | 38 +- entity.h | 29 +- font.h | 19 +- freecam.c | 35 +- freecam.h | 4 +- gui.h | 12 +- menu.c | 792 ++ menu.h | 801 +- model.h | 2 - network.c | 49 +- network.h | 54 +- particle.c | 46 +- particle.h | 43 +- player.c | 135 +- player.h | 129 +- player_api.h | 17 +- player_basic_info.c | 16 +- player_basic_info.h | 25 +- player_common.c | 43 +- player_dead.c | 48 +- player_dead.h | 46 +- player_drive.c | 46 +- player_drive.h | 43 +- player_effects.c | 7 +- player_effects.h | 21 +- player_glide.c | 128 +- player_glide.h | 124 +- player_ragdoll.c | 41 +- player_ragdoll.h | 39 +- player_remote.c | 52 +- player_remote.h | 43 +- player_render.c | 79 +- player_render.h | 64 +- player_replay.c | 174 +- player_replay.h | 54 +- player_skate.c | 69 +- player_skate.h | 69 +- player_walk.c | 60 +- player_walk.h | 53 +- render.c | 718 ++ render.h | 744 +- save.c | 47 +- save.h | 26 +- scene.c | 404 + scene.h | 428 +- shaders/blit.h | 93 +- shaders/blit_transition.h | 67 +- shaders/blitblur.h | 134 +- shaders/blitcolour.h | 61 +- shaders/impl.c | 11365 +++++++++++++++++++++++++++ shaders/model_board_view.h | 648 +- shaders/model_character_view.h | 643 +- shaders/model_entity.h | 509 +- shaders/model_font.h | 212 +- shaders/model_gate.h | 154 +- shaders/model_gate_unlinked.h | 184 +- shaders/model_menu.h | 137 +- shaders/model_sky.h | 516 +- shaders/model_sky_space.h | 532 +- shaders/particle.h | 118 +- shaders/routeui.h | 59 +- shaders/scene_cubemapped.h | 575 +- shaders/scene_depth.h | 532 +- shaders/scene_foliage.h | 562 +- shaders/scene_font.h | 603 +- shaders/scene_fxglow.h | 545 +- shaders/scene_override.h | 645 +- shaders/scene_position.h | 523 +- shaders/scene_route.h | 593 +- shaders/scene_scoretext.h | 582 +- shaders/scene_standard.h | 556 +- shaders/scene_standard_alphatest.h | 559 +- shaders/scene_terrain.h | 585 +- shaders/scene_vertex_blend.h | 567 +- shaders/scene_water.h | 648 +- shaders/scene_water_fast.h | 612 +- shaders/trail.h | 124 +- skaterift.c | 160 +- skaterift.h | 57 +- skeleton.h | 7 +- steam.c | 303 + steam.h | 312 +- testing.c | 65 - trail.c | 30 +- trail.h | 19 +- vehicle.c | 28 +- vehicle.h | 26 +- workshop.c | 36 +- workshop.h | 17 +- world.c | 46 +- world.h | 29 +- world_audio.c | 13 +- world_audio.h | 14 +- world_entity.c | 78 +- world_entity.h | 63 +- world_gate.c | 49 +- world_gate.h | 40 +- world_gen.c | 12 +- world_load.c | 22 +- world_load.h | 18 +- world_map.c | 29 +- world_map.h | 20 +- world_physics.c | 21 +- world_physics.h | 30 +- world_render.c | 118 +- world_render.h | 64 +- world_routes.c | 62 +- world_routes.h | 43 +- world_routes_ui.c | 3 +- world_routes_ui.h | 11 +- world_sfd.c | 25 +- world_sfd.h | 25 +- world_volumes.c | 8 +- world_volumes.h | 8 +- world_water.c | 44 +- world_water.h | 16 +- 144 files changed, 16868 insertions(+), 16725 deletions(-) create mode 100644 addon_types.c create mode 100644 audio.c delete mode 100644 bvh.h create mode 100644 ent_objective.h create mode 100644 ent_relay.h create mode 100644 ent_tornado.h create mode 100644 menu.c create mode 100644 render.c create mode 100644 scene.c create mode 100644 shaders/impl.c create mode 100644 steam.c delete mode 100644 testing.c diff --git a/addon.c b/addon.c index 984bb9c..b67db74 100644 --- 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; typecounttype == 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 bb96f2e..bb5747d 100644 --- 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 index 0000000..b10a23c --- /dev/null +++ b/addon_types.c @@ -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/" + } +}; diff --git a/addon_types.h b/addon_types.h index 5c6730f..a244fc0 100644 --- a/addon_types.h +++ b/addon_types.h @@ -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 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; ilpf, 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 984303a..4b57a79 100644 --- a/audio.h +++ b/audio.h @@ -2,151 +2,12 @@ * 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; ilpf, 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 9367e81..3190da1 100644 --- 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 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; icount; 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; tcount; 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; icount; 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; icount; 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 */ diff --git a/camera.h b/camera.h index fdbc00c..7aa1b14 100644 --- 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 diff --git a/depth_compare.h b/depth_compare.h index 8b64586..592381b 100644 --- a/depth_compare.h +++ b/depth_compare.h @@ -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 */ diff --git a/ent_challenge.c b/ent_challenge.c index 72149b1..ce87366 100644 --- a/ent_challenge.c +++ b/ent_challenge.c @@ -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 */ diff --git a/ent_challenge.h b/ent_challenge.h index a3cd92a..9b9ea10 100644 --- a/ent_challenge.h +++ b/ent_challenge.h @@ -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 ); diff --git a/ent_miniworld.c b/ent_miniworld.c index 46def88..4f22df8 100644 --- a/ent_miniworld.c +++ b/ent_miniworld.c @@ -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); } diff --git a/ent_miniworld.h b/ent_miniworld.h index e963a09..b1aed55 100644 --- a/ent_miniworld.h +++ b/ent_miniworld.h @@ -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); diff --git a/ent_objective.c b/ent_objective.c index ce5ad0f..66b822d 100644 --- a/ent_objective.c +++ b/ent_objective.c @@ -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 index 0000000..0f3e4e5 --- /dev/null +++ b/ent_objective.h @@ -0,0 +1,4 @@ +#pragma once +#include "entity.h" +#include "world.h" +void ent_objective_call( world_instance *world, ent_call *call ); diff --git a/ent_region.c b/ent_region.c index 44d49a0..e58d594 100644 --- a/ent_region.c +++ b/ent_region.c @@ -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; diff --git a/ent_region.h b/ent_region.h index 85acb45..4b27825 100644 --- a/ent_region.h +++ b/ent_region.h @@ -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 ); diff --git a/ent_relay.c b/ent_relay.c index 357031b..50bbeab 100644 --- a/ent_relay.c +++ b/ent_relay.c @@ -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 index 0000000..acbe943 --- /dev/null +++ b/ent_relay.h @@ -0,0 +1,3 @@ +#pragma once +#include "entity.h" +void ent_relay_call( world_instance *world, ent_call *call ); diff --git a/ent_route.c b/ent_route.c index fa1d669..8f95a26 100644 --- a/ent_route.c +++ b/ent_route.c @@ -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 */ diff --git a/ent_route.h b/ent_route.h index 65c074f..ecc3278 100644 --- a/ent_route.h +++ b/ent_route.h @@ -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 ); diff --git a/ent_skateshop.c b/ent_skateshop.c index 86fc971..ed22216 100644 --- a/ent_skateshop.c +++ b/ent_skateshop.c @@ -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" @@ -10,6 +13,11 @@ #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; ient_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; jent_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" ); diff --git a/ent_skateshop.h b/ent_skateshop.h index 68a34f4..0bbeb8d 100644 --- a/ent_skateshop.h +++ b/ent_skateshop.h @@ -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 ); diff --git a/ent_tornado.c b/ent_tornado.c index d59c6b7..f9fca03 100644 --- a/ent_tornado.c +++ b/ent_tornado.c @@ -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; ient_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; ient_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 index 0000000..f89c070 --- /dev/null +++ b/ent_tornado.h @@ -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); diff --git a/ent_traffic.c b/ent_traffic.c index f7167f2..5735d5b 100644 --- a/ent_traffic.c +++ b/ent_traffic.c @@ -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 */ diff --git a/ent_traffic.h b/ent_traffic.h index bebee23..18d8d1e 100644 --- a/ent_traffic.h +++ b/ent_traffic.h @@ -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 ); diff --git a/entity.c b/entity.c index ce6d98e..261dbbc 100644 --- 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; ipstr_alias ), alias ) ){ + return marker; + } + } + + return NULL; +} + diff --git a/entity.h b/entity.h index 2874441..a925318 100644 --- 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; ipstr_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 a83b73c..a783613 100644 --- 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; ifont_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 */ diff --git a/freecam.c b/freecam.c index 2e79ff1..246af3c 100644 --- 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; diff --git a/freecam.h b/freecam.h index e0d5ade..1f9f5e2 100644 --- 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 67f78b5..c6ebe71 100644 --- 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 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; itype == 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; ivisual.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; ifile.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; itype == 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; itype == 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<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; jsubmesh_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; itype != k_ent_menuitem_type_page) && + (item->type != k_ent_menuitem_type_visual) && + (item->type != k_ent_menuitem_type_visual_nocol) && + (item->groups & (0x1<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; itype == 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; jsubmesh_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; itransform, 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 e8d9474..65fba46 100644 --- 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; itype == 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; ivisual.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; ifile.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; itype == 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; itype == 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<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; jsubmesh_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; itype != k_ent_menuitem_type_page) && - (item->type != k_ent_menuitem_type_visual) && - (item->type != k_ent_menuitem_type_visual_nocol) && - (item->groups & (0x1<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; itype == 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; jsubmesh_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; itransform, 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 63e6e7f..bc0ab66 100644 --- 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" diff --git a/network.c b/network.c index 4d55707..74e03bf 100644 --- 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" @@ -10,9 +15,17 @@ #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) ) diff --git a/network.h b/network.h index 08a989b..7500c88 100644 --- 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" @@ -19,26 +18,27 @@ */ /* 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 */ diff --git a/particle.c b/particle.c index 9c1f87e..2e05a19 100644 --- a/particle.c +++ b/particle.c @@ -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; ialive; 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; ialive; 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 ); diff --git a/particle.h b/particle.h index fb4d27f..6858890 100644 --- a/particle.h +++ b/particle.h @@ -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 ); diff --git a/player.c b/player.c index 1d690a0..b11eacb 100644 --- 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" @@ -18,7 +16,39 @@ #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; isystem_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; ibind ) 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 */ diff --git a/player.h b/player.h index b2e9106..69da509 100644 --- 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 ); diff --git a/player_api.h b/player_api.h index b3b6907..68f5aca 100644 --- a/player_api.h +++ b/player_api.h @@ -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 +}; diff --git a/player_basic_info.c b/player_basic_info.c index 3d6c85a..ffc7ae0 100644 --- a/player_basic_info.c +++ b/player_basic_info.c @@ -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 ); diff --git a/player_basic_info.h b/player_basic_info.h index 12f46c9..815be67 100644 --- a/player_basic_info.h +++ b/player_basic_info.h @@ -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 */ diff --git a/player_common.c b/player_common.c index bfdef1a..2551968 100644 --- a/player_common.c +++ b/player_common.c @@ -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; ient_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 */ diff --git a/player_dead.c b/player_dead.c index 625ff0e..5f4ab72 100644 --- a/player_dead.c +++ b/player_dead.c @@ -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; idrive = 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 */ diff --git a/player_drive.h b/player_drive.h index 0dd135c..76c2557 100644 --- a/player_drive.h +++ b/player_drive.h @@ -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); diff --git a/player_effects.c b/player_effects.c index 9b13445..feca984 100644 --- a/player_effects.c +++ b/player_effects.c @@ -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 ){ diff --git a/player_effects.h b/player_effects.h index c52361d..50caabc 100644 --- a/player_effects.h +++ b/player_effects.h @@ -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 */ diff --git a/player_glide.c b/player_glide.c index 32768f6..f733937 100644 --- a/player_glide.c +++ b/player_glide.c @@ -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; ipart_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; ipart_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; diff --git a/player_ragdoll.h b/player_ragdoll.h index 25b6fad..08ab5e7 100644 --- a/player_ragdoll.h +++ b/player_ragdoll.h @@ -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 ); diff --git a/player_remote.c b/player_remote.c index ba07abe..f829ec0 100644 --- a/player_remote.c +++ b/player_remote.c @@ -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; iactive ) @@ -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; iactive ) 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; itextures ) ) 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 */ diff --git a/player_render.h b/player_render.h index ee98488..cfc48e7 100644 --- a/player_render.h +++ b/player_render.h @@ -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); diff --git a/player_replay.c b/player_replay.c index b0df4f2..1994eb6 100644 --- a/player_replay.c +++ b/player_replay.c @@ -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 */ diff --git a/player_replay.h b/player_replay.h index 38ea253..b7f4a57 100644 --- a/player_replay.h +++ b/player_replay.h @@ -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); diff --git a/player_skate.c b/player_skate.c index b193173..11ff6ae 100644 --- a/player_skate.c +++ b/player_skate.c @@ -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; itrick_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 */ diff --git a/player_skate.h b/player_skate.h index 4118fd6..b6e23f5 100644 --- a/player_skate.h +++ b/player_skate.h @@ -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); diff --git a/player_walk.c b/player_walk.c index d673584..68415dd 100644 --- a/player_walk.c +++ b/player_walk.c @@ -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 ){ diff --git a/player_walk.h b/player_walk.h index 95ce2a0..b121354 100644 --- a/player_walk.h +++ b/player_walk.h @@ -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 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; ipurpose == 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; jattachments); 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; iattachments); 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; iattachments); 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 }, + "", 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 /"all" + * arg2: subname /none + */ +static int render_framebuffer_control( int argc, char const *argv[] ) +{ + if( argc < 2 ){ + vg_error( "Usage: fb \"show/hide\" /\"all\" /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; iattachments); 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; idisplay_name, term, 0 ); + } + } + else if( argc == 3 ){ + int modify_all = 0; + + if( !strcmp( argv[1], "all" ) ) + modify_all = 1; + + for( int i=0; iattachments); 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 ); + } + } + } + } +} diff --git a/render.h b/render.h index a104228..3b69b2b 100644 --- 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; ipurpose == 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; jattachments); 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; iattachments); 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; iattachments); 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 }, - "", 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 /"all" - * arg2: subname /none - */ -static int render_framebuffer_control( int argc, char const *argv[] ) -{ - if( argc < 2 ){ - vg_error( "Usage: fb \"show/hide\" /\"all\" /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; iattachments); 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; idisplay_name, term, 0 ); - } - } - else if( argc == 3 ){ - int modify_all = 0; - - if( !strcmp( argv[1], "all" ) ) - modify_all = 1; - - for( int i=0; iattachments); 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 1009e61..db609ca 100644 --- 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; ifile_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, ®->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 4424bd3..acda301 100644 --- 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 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; ivertex_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; iindice_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; iarrvertices[ 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 d8fac1a..06f36bb 100644 --- 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; ivertex_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; iindice_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; iarrvertices[ 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 ); diff --git a/shaders/blit.h b/shaders/blit.h index 116007a..94d3dce 100644 --- a/shaders/blit.h +++ b/shaders/blit.h @@ -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 */ diff --git a/shaders/blit_transition.h b/shaders/blit_transition.h index f5f3049..f73d1d4 100644 --- a/shaders/blit_transition.h +++ b/shaders/blit_transition.h @@ -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 */ diff --git a/shaders/blitblur.h b/shaders/blitblur.h index ac8f3cc..8a75c38 100644 --- a/shaders/blitblur.h +++ b/shaders/blitblur.h @@ -1,122 +1,48 @@ -#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 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 */ diff --git a/shaders/blitcolour.h b/shaders/blitcolour.h index 91a2e61..1bd3349 100644 --- a/shaders/blitcolour.h +++ b/shaders/blitcolour.h @@ -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 index 0000000..0bc64bb --- /dev/null +++ b/shaders/impl.c @@ -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 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 ); +} + diff --git a/shaders/model_board_view.h b/shaders/model_board_view.h index abbc42f..42eac9e 100644 --- a/shaders/model_board_view.h +++ b/shaders/model_board_view.h @@ -1,626 +1,60 @@ -#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 */ diff --git a/shaders/model_character_view.h b/shaders/model_character_view.h index 2af1bfe..9489520 100644 --- a/shaders/model_character_view.h +++ b/shaders/model_character_view.h @@ -1,626 +1,51 @@ -#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 */ diff --git a/shaders/model_entity.h b/shaders/model_entity.h index a970038..e198e03 100644 --- a/shaders/model_entity.h +++ b/shaders/model_entity.h @@ -1,491 +1,40 @@ -#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 */ diff --git a/shaders/model_font.h b/shaders/model_font.h index 67ce50d..8ba6c7a 100644 --- a/shaders/model_font.h +++ b/shaders/model_font.h @@ -1,192 +1,58 @@ -#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 */ diff --git a/shaders/model_gate.h b/shaders/model_gate.h index 1bc558f..49986ba 100644 --- a/shaders/model_gate.h +++ b/shaders/model_gate.h @@ -1,137 +1,43 @@ -#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 */ diff --git a/shaders/model_gate_unlinked.h b/shaders/model_gate_unlinked.h index 449322a..93ab1e3 100644 --- a/shaders/model_gate_unlinked.h +++ b/shaders/model_gate_unlinked.h @@ -1,168 +1,38 @@ -#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 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 */ diff --git a/shaders/model_sky_space.h b/shaders/model_sky_space.h index c96f2c4..474d072 100644 --- a/shaders/model_sky_space.h +++ b/shaders/model_sky_space.h @@ -1,515 +1,35 @@ -#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 */ diff --git a/shaders/particle.h b/shaders/particle.h index 60bc981..43ad3ac 100644 --- a/shaders/particle.h +++ b/shaders/particle.h @@ -1,108 +1,18 @@ -#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 */ diff --git a/shaders/routeui.h b/shaders/routeui.h index 9e571ab..9be8ddc 100644 --- a/shaders/routeui.h +++ b/shaders/routeui.h @@ -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 */ diff --git a/shaders/scene_cubemapped.h b/shaders/scene_cubemapped.h index 544ac63..f7dfbbd 100644 --- a/shaders/scene_cubemapped.h +++ b/shaders/scene_cubemapped.h @@ -1,553 +1,60 @@ -#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 */ diff --git a/shaders/scene_depth.h b/shaders/scene_depth.h index 6f28ad4..d760b33 100644 --- a/shaders/scene_depth.h +++ b/shaders/scene_depth.h @@ -1,513 +1,45 @@ -#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 */ diff --git a/shaders/scene_foliage.h b/shaders/scene_foliage.h index 041dcd8..2f4249e 100644 --- a/shaders/scene_foliage.h +++ b/shaders/scene_foliage.h @@ -1,541 +1,55 @@ -#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 */ diff --git a/shaders/scene_font.h b/shaders/scene_font.h index 891947d..53f22c3 100644 --- a/shaders/scene_font.h +++ b/shaders/scene_font.h @@ -1,580 +1,65 @@ -#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 */ diff --git a/shaders/scene_fxglow.h b/shaders/scene_fxglow.h index c47d6ab..8147639 100644 --- a/shaders/scene_fxglow.h +++ b/shaders/scene_fxglow.h @@ -1,526 +1,45 @@ -#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 */ diff --git a/shaders/scene_override.h b/shaders/scene_override.h index c84a5ba..3b29c99 100644 --- a/shaders/scene_override.h +++ b/shaders/scene_override.h @@ -1,618 +1,75 @@ -#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 */ diff --git a/shaders/scene_position.h b/shaders/scene_position.h index 9736d94..2e99c02 100644 --- a/shaders/scene_position.h +++ b/shaders/scene_position.h @@ -1,504 +1,45 @@ -#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 */ diff --git a/shaders/scene_route.h b/shaders/scene_route.h index f136afe..b9fc0aa 100644 --- a/shaders/scene_route.h +++ b/shaders/scene_route.h @@ -1,570 +1,55 @@ -#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 */ diff --git a/shaders/scene_scoretext.h b/shaders/scene_scoretext.h index 3b91bec..0be2bf2 100644 --- a/shaders/scene_scoretext.h +++ b/shaders/scene_scoretext.h @@ -1,561 +1,55 @@ -#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 */ diff --git a/shaders/scene_standard.h b/shaders/scene_standard.h index 6a337e7..0dca3c7 100644 --- a/shaders/scene_standard.h +++ b/shaders/scene_standard.h @@ -1,536 +1,50 @@ -#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 */ diff --git a/shaders/scene_standard_alphatest.h b/shaders/scene_standard_alphatest.h index 0d6911c..73fc7a6 100644 --- a/shaders/scene_standard_alphatest.h +++ b/shaders/scene_standard_alphatest.h @@ -1,539 +1,50 @@ -#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 */ diff --git a/shaders/scene_terrain.h b/shaders/scene_terrain.h index d7c58ef..37b6a3c 100644 --- a/shaders/scene_terrain.h +++ b/shaders/scene_terrain.h @@ -1,564 +1,55 @@ -#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 */ diff --git a/shaders/scene_vertex_blend.h b/shaders/scene_vertex_blend.h index 7cc9102..376c81b 100644 --- a/shaders/scene_vertex_blend.h +++ b/shaders/scene_vertex_blend.h @@ -1,548 +1,45 @@ -#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 */ diff --git a/shaders/scene_water.h b/shaders/scene_water.h index 3ac3b9d..d19c02d 100644 --- a/shaders/scene_water.h +++ b/shaders/scene_water.h @@ -1,621 +1,85 @@ -#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 */ diff --git a/shaders/scene_water_fast.h b/shaders/scene_water_fast.h index ac987dd..e0f1b4c 100644 --- a/shaders/scene_water_fast.h +++ b/shaders/scene_water_fast.h @@ -1,588 +1,70 @@ -#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 */ diff --git a/shaders/trail.h b/shaders/trail.h index ee6090c..b9ab766 100644 --- a/shaders/trail.h +++ b/shaders/trail.h @@ -1,113 +1,23 @@ -#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 */ diff --git a/skaterift.c b/skaterift.c index fee0039..8d79e9e 100644 --- a/skaterift.c +++ b/skaterift.c @@ -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" @@ -33,28 +33,23 @@ #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" diff --git a/skaterift.h b/skaterift.h index 92a5963..f3e0258 100644 --- a/skaterift.h +++ b/skaterift.h @@ -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; diff --git a/skeleton.h b/skeleton.h index daa8fdc..9729b64 100644 --- a/skeleton.h +++ b/skeleton.h @@ -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 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 + +/* + * 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; im_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> 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 977f77d..e2ed982 100644 --- a/steam.h +++ b/steam.h @@ -3,303 +3,17 @@ * 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; im_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> 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 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; jcount ++; } -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; icount; 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; icount; 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; icount; 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 58bcb93..82c7d60 100644 --- 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 ); diff --git a/vehicle.c b/vehicle.c index 0576963..35004d6 100644 --- 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 */ diff --git a/vehicle.h b/vehicle.h index d61d1e3..3e60bb7 100644 --- 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); diff --git a/workshop.c b/workshop.c index 469eeea..0b03894 100644 --- a/workshop.c +++ b/workshop.c @@ -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; diff --git a/workshop.h b/workshop.h index 42610d4..be9e3a5 100644 --- a/workshop.h +++ b/workshop.h @@ -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 9ff62bc..9b19387 100644 --- 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 6ff3afb..823b38c 100644 --- 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 ); diff --git a/world_audio.c b/world_audio.c index 826e20a..df3af70 100644 --- a/world_audio.c +++ b/world_audio.c @@ -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 */ diff --git a/world_audio.h b/world_audio.h index b1b14da..07d66d1 100644 --- a/world_audio.h +++ b/world_audio.h @@ -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 ); diff --git a/world_entity.c b/world_entity.c index 957891d..3602530 100644 --- a/world_entity.c +++ b/world_entity.c @@ -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" @@ -13,8 +12,22 @@ #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; jent_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; ient_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 */ diff --git a/world_entity.h b/world_entity.h index a3c5f33..df5cbfa 100644 --- a/world_entity.h +++ b/world_entity.h @@ -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; diff --git a/world_gate.c b/world_gate.c index 1631e05..7212714 100644 --- a/world_gate.c +++ b/world_gate.c @@ -13,16 +13,18 @@ #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; isubmesh_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; ient_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; jent_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; diff --git a/world_gate.h b/world_gate.h index 151e428..03e4568 100644 --- a/world_gate.h +++ b/world_gate.h @@ -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 ); diff --git a/world_gen.c b/world_gen.c index 1bbc2ca..047155e 100644 --- a/world_gen.c +++ b/world_gen.c @@ -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 */ diff --git a/world_load.c b/world_load.c index aaf689f..f124e24 100644 --- a/world_load.c +++ b/world_load.c @@ -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; istatus != 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 */ diff --git a/world_load.h b/world_load.h index 3e4722a..038233d 100644 --- a/world_load.h +++ b/world_load.h @@ -1,17 +1,11 @@ -#ifndef WORLD_LOAD_H -#define WORLD_LOAD_H - +#pragma once #include #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); diff --git a/world_map.c b/world_map.c index c7f6ec8..bc2ab5c 100644 --- a/world_map.c +++ b/world_map.c @@ -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 */ diff --git a/world_map.h b/world_map.h index 4fbd6fc..d4be3b5 100644 --- a/world_map.h +++ b/world_map.h @@ -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); diff --git a/world_physics.c b/world_physics.c index ebe8f89..03be1fc 100644 --- a/world_physics.c +++ b/world_physics.c @@ -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; isurface_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] ); } diff --git a/world_physics.h b/world_physics.h index 8531b8f..ce65e5b 100644 --- a/world_physics.h +++ b/world_physics.h @@ -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 */ diff --git a/world_render.c b/world_render.c index c82bc47..029a95f 100644 --- a/world_render.c +++ b/world_render.c @@ -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 diff --git a/world_render.h b/world_render.h index ecbd3d2..846e2d8 100644 --- a/world_render.h +++ b/world_render.h @@ -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 */ diff --git a/world_routes.c b/world_routes.c index 4ee50d8..c4b3393 100644 --- a/world_routes.c +++ b/world_routes.c @@ -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; ient_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; ient_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; ient_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; ient_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 ); diff --git a/world_routes.h b/world_routes.h index 5fccc9e..6467977 100644 --- a/world_routes.h +++ b/world_routes.h @@ -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 ); diff --git a/world_routes_ui.c b/world_routes_ui.c index 4d39e9c..ace8a3d 100644 --- a/world_routes_ui.c +++ b/world_routes_ui.c @@ -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; ient_route); i++ ){ ent_route_imgui( world, mdl_arritm( &world->ent_route, i ), cursor ); diff --git a/world_routes_ui.h b/world_routes_ui.h index 00bfe42..a821f7f 100644 --- a/world_routes_ui.h +++ b/world_routes_ui.h @@ -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 ); diff --git a/world_sfd.c b/world_sfd.c index fbe07d3..ef4fc3b 100644 --- a/world_sfd.c +++ b/world_sfd.c @@ -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; diff --git a/world_sfd.h b/world_sfd.h index 176425d..e79fbbc 100644 --- a/world_sfd.h +++ b/world_sfd.h @@ -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); diff --git a/world_volumes.c b/world_volumes.c index 7f2b685..ae507d0 100644 --- a/world_volumes.c +++ b/world_volumes.c @@ -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; iwater.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; diff --git a/world_water.h b/world_water.h index b45ee3a..47855b2 100644 --- a/world_water.h +++ b/world_water.h @@ -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 ); -- 2.25.1