@ -21,11 +21,13 @@
# define DESKTOP
# define WINDOWS
# define SOKOL_GLCORE33
# define SAMPLE_COUNT 4
# endif
# if defined(__EMSCRIPTEN__)
# define WEB
# define SOKOL_GLES2
# define SOKOL_GLES3
# define SAMPLE_COUNT 4
# endif
# define DRWAV_ASSERT game_assert
@ -41,8 +43,6 @@
# pragma warning(push, 3)
# include <Windows.h>
# include <processthreadsapi.h>
# include <dbghelp.h>
# include <stdint.h>
// https://developer.download.nvidia.com/devzone/devcenter/gamegraphics/files/OptimusRenderingPolicies.pdf
@ -53,13 +53,15 @@ __declspec(dllexport) uint32_t AmdPowerXpressRequestHighPerformance = 0x00000001
# endif
# define STRINGIZE(x) STRINGIZE2(x)
# define STRINGIZE2(x) #x
# include "buff.h"
# include "sokol_app.h"
# pragma warning(push)
# pragma warning(disable : 4191) // unsafe function calling
# ifdef WEB
# include <GLES3 / gl3.h>
# undef glGetError
# define glGetError() (GL_NO_ERROR)
# endif
# include "sokol_gfx.h"
# pragma warning(pop)
# include "sokol_time.h"
@ -365,6 +367,7 @@ float float_rand(float min, float max)
float scale = rand ( ) / ( float ) RAND_MAX ; /* [0, 1.0] */
return min + scale * ( max - min ) ; /* [min, max] */
}
// always randomizes pitch
void play_audio ( AudioSample * sample , float volume )
{
AudioPlayer * to_use = 0 ;
@ -466,6 +469,7 @@ LPCWSTR windows_string(MD_String8 s)
# ifdef DESKTOP
# ifdef WINDOWS
# pragma warning(push, 3)
# pragma comment(lib, "WinHttp")
# include <WinHttp.h>
# include <process.h>
# pragma warning(pop)
@ -835,18 +839,15 @@ sg_image load_image(MD_String8 path)
{
. width = png_width ,
. height = png_height ,
. pixel_format = SG_PIXELFORMAT_RGBA8 ,
. min_filter = SG_FILTER_LINEAR ,
. pixel_format = sapp_sgcontext ( ) . color_format ,
. num_mipmaps = 1 ,
. wrap_u = SG_WRAP_CLAMP_TO_EDGE ,
. wrap_v = SG_WRAP_CLAMP_TO_EDGE ,
. mag_filter = SG_FILTER_LINEAR ,
. data . subimage [ 0 ] [ 0 ] =
{
. ptr = pixels ,
. size = ( size_t ) ( png_width * png_height * num_channels ) ,
}
} ) ;
loaded - > image = to_return ;
MD_ReleaseScratch ( scratch ) ;
return to_return ;
@ -1225,14 +1226,6 @@ Armature load_armature(MD_Arena *arena, MD_String8 binary_file, MD_String8 armat
. width = to_return . bones_texture_width ,
. height = to_return . bones_texture_height ,
. pixel_format = SG_PIXELFORMAT_RGBA8 ,
. min_filter = SG_FILTER_NEAREST ,
. mag_filter = SG_FILTER_NEAREST ,
// for webgl NPOT texures https://developer.mozilla.org/en-US/docs/Web/API/WebGL_API/Tutorial/Using_textures_in_WebGL
. wrap_u = SG_WRAP_CLAMP_TO_EDGE ,
. wrap_v = SG_WRAP_CLAMP_TO_EDGE ,
. wrap_w = SG_WRAP_CLAMP_TO_EDGE ,
. usage = SG_USAGE_STREAM ,
} ) ;
@ -2654,26 +2647,34 @@ Shadow_State init_shadow_state();
static struct
{
sg_pass_action clear_everything_pass_action ;
sg_pass_action threedee_msaa_pass_action ;
sg_pass_action clear_depth_buffer_pass_action ;
sg_pipeline twodee_pip ;
sg_bindings bind ;
sg_pipeline threedee_pip ;
sg_pipeline threedee_alpha_blended_pip ;
sg_pipeline armature_pip ;
sg_bindings threedee_bind ;
sg_image outline_pass_image ;
sg_image outline_pass_resolve_image ;
sg_pass outline_pass ;
sg_pipeline outline_mesh_pip ;
sg_pipeline outline_armature_pip ;
sg_pass threedee_pass ; // is a pass so I can do post processing in a shader
sg_image threedee_pass_image ;
sg_image threedee_pass_resolve_image ;
sg_image threedee_pass_depth_image ;
sg_pipeline twodee_outline_pip ;
sg_pipeline twodee_colorcorrect_pip ;
sg_sampler sampler_linear ;
sg_sampler sampler_linear_border ;
sg_sampler sampler_nearest ;
Shadow_State shadows ;
} state ;
@ -2688,7 +2689,9 @@ void create_screenspace_gfx_state()
MAYBE_DESTROY ( state . threedee_pass , sg_destroy_pass ) ;
MAYBE_DESTROY ( state . outline_pass_image , sg_destroy_image ) ;
MAYBE_DESTROY ( state . outline_pass_resolve_image , sg_destroy_image ) ;
MAYBE_DESTROY ( state . threedee_pass_image , sg_destroy_image ) ;
MAYBE_DESTROY ( state . threedee_pass_resolve_image , sg_destroy_image ) ;
MAYBE_DESTROY ( state . threedee_pass_depth_image , sg_destroy_image ) ;
# undef MAYBE_DESTROY
@ -2702,7 +2705,7 @@ void create_screenspace_gfx_state()
. depth = {
0
} ,
. sample_count = 1 ,
. sample_count = SAMPLE_COUNT ,
. layout = {
. attrs =
{
@ -2732,7 +2735,7 @@ void create_screenspace_gfx_state()
. depth = {
. pixel_format = SG_PIXELFORMAT_NONE ,
} ,
. sample_count = 1 ,
. sample_count = SAMPLE_COUNT ,
. layout = {
. attrs =
{
@ -2758,18 +2761,17 @@ void create_screenspace_gfx_state()
. render_target = true ,
. width = sapp_width ( ) ,
. height = sapp_height ( ) ,
. pixel_format = SG_PIXELFORMAT_RGBA8 ,
. min_filter = SG_FILTER_LINEAR ,
. mag_filter = SG_FILTER_LINEAR ,
. wrap_u = SG_WRAP_CLAMP_TO_BORDER ,
. wrap_v = SG_WRAP_CLAMP_TO_BORDER ,
. border_color = SG_BORDERCOLOR_OPAQUE_WHITE ,
. sample_count = 1 ,
. pixel_format = sapp_sgcontext ( ) . color_format ,
. label = " outline-pass-render-target " ,
} ;
desc . sample_count = SAMPLE_COUNT ;
state . outline_pass_image = sg_make_image ( & desc ) ;
desc . sample_count = 1 ;
state . outline_pass_resolve_image = sg_make_image ( & desc ) ;
state . outline_pass = sg_make_pass ( & ( sg_pass_desc ) {
. color_attachments [ 0 ] . image = state . outline_pass_image ,
. resolve_attachments [ 0 ] . image = state . outline_pass_resolve_image ,
. depth_stencil_attachment = {
0
} ,
@ -2779,14 +2781,21 @@ void create_screenspace_gfx_state()
desc . sample_count = 1 ;
desc . label = " threedee-pass-render-target " ;
desc . sample_count = SAMPLE_COUNT ;
state . threedee_pass_image = sg_make_image ( & desc ) ;
desc . label = " threedee-pass-resolve-render-target " ;
desc . sample_count = 1 ;
state . threedee_pass_resolve_image = sg_make_image ( & desc ) ;
desc . label = " threedee-pass-depth-render-target " ;
desc . pixel_format = sapp_depth_format ( ) ;
desc . pixel_format = SG_PIXELFORMAT_DEPTH ;
desc . sample_count = SAMPLE_COUNT ;
state . threedee_pass_depth_image = sg_make_image ( & desc ) ;
state . threedee_pass = sg_make_pass ( & ( sg_pass_desc ) {
. color_attachments [ 0 ] . image = state . threedee_pass_image ,
. resolve_attachments [ 0 ] . image = state . threedee_pass_resolve_image ,
. depth_stencil_attachment = ( sg_pass_attachment_desc ) {
. image = state . threedee_pass_depth_image ,
. mip_level = 0 ,
@ -3006,8 +3015,8 @@ Color blendalpha(Color c, float alpha)
// in pixels
Vec2 img_size ( sg_image img )
{
sg_image_ info info = sg_query_image_info ( img ) ;
return V2 ( ( float ) info. width , ( float ) info . height ) ;
sg_image_ desc desc = sg_query_image_desc ( img ) ;
return V2 ( ( float ) desc. width , ( float ) desc . height ) ;
}
# ifdef DEVTOOLS
@ -3129,8 +3138,6 @@ LoadedFont load_font(MD_Arena *arena, MD_String8 font_filepath, float font_size)
. width = font_bitmap_width ,
. height = font_bitmap_width ,
. pixel_format = SG_PIXELFORMAT_RGBA8 ,
. min_filter = SG_FILTER_LINEAR ,
. mag_filter = SG_FILTER_LINEAR ,
. data . subimage [ 0 ] [ 0 ] =
{
. ptr = font_bitmap_rgba ,
@ -3158,6 +3165,7 @@ Armature player_armature = {0};
Armature farmer_armature = { 0 } ;
Armature shifted_farmer_armature = { 0 } ;
Armature man_in_black_armature = { 0 } ;
Armature angel_armature = { 0 } ;
// armatureanimations are processed once every visual frame from this list
Armature * armatures [ ] = {
@ -3165,6 +3173,7 @@ Armature *armatures[] = {
& farmer_armature ,
& shifted_farmer_armature ,
& man_in_black_armature ,
& angel_armature ,
} ;
Mesh mesh_player = { 0 } ;
@ -3205,6 +3214,7 @@ void init(void)
sg_setup ( & ( sg_desc ) {
. context = sapp_sgcontext ( ) ,
. buffer_pool_size = 512 ,
. logger . func = slog_func ,
} ) ;
stm_setup ( ) ;
saudio_setup ( & ( saudio_desc ) {
@ -3232,6 +3242,9 @@ void init(void)
man_in_black_armature = load_armature ( persistent_arena , binary_file , MD_S8Lit ( " Man In Black " ) ) ;
man_in_black_armature . image = image_man_in_black ;
angel_armature = load_armature ( persistent_arena , binary_file , MD_S8Lit ( " Angel " ) ) ;
angel_armature . image = image_angel ;
binary_file = MD_LoadEntireFile ( frame_arena , MD_S8Lit ( " assets/exported_3d/Farmer.bin " ) ) ;
farmer_armature = load_armature ( persistent_arena , binary_file , MD_S8Lit ( " Farmer.bin " ) ) ;
@ -3362,29 +3375,38 @@ void init(void)
assert ( desc ) ;
shd = sg_make_shader ( desc ) ;
state . threedee_pip = sg_make_pipeline ( & ( sg_pipeline_desc ) {
{
sg_pipeline_desc threedee_pip_desc = {
. shader = shd ,
. layout = { . attrs = {
[ ATTR_threedee_vs_pos_in ] . format = SG_VERTEXFORMAT_FLOAT3 ,
[ ATTR_threedee_vs_uv_in ] . format = SG_VERTEXFORMAT_FLOAT2 ,
} } ,
. depth = {
. pixel_format = sapp_depth_format ( ) ,
. pixel_format = SG_PIXELFORMAT_DEPTH ,
. compare = SG_COMPAREFUNC_LESS_EQUAL ,
. write_enabled = true ,
} ,
. colors [ 0 ] . blend = ( sg_blend_state ) {
. alpha_to_coverage_enabled = true ,
. sample_count = SAMPLE_COUNT ,
. colors [ 0 ] . blend . enabled = false ,
. label = " threedee " ,
} ;
state . threedee_pip = sg_make_pipeline ( & threedee_pip_desc ) ;
threedee_pip_desc . depth . write_enabled = false ;
threedee_pip_desc . alpha_to_coverage_enabled = false ;
threedee_pip_desc . colors [ 0 ] . blend = ( sg_blend_state ) {
// allow transparency
. enabled = true ,
. src_factor_rgb = SG_BLENDFACTOR_SRC_ALPHA ,
. dst_factor_rgb = SG_BLENDFACTOR_ONE_MINUS_SRC_ALPHA ,
. op_rgb = SG_BLENDOP_ADD ,
. src_factor_alpha = SG_BLENDFACTOR_ONE ,
. src_factor_alpha = SG_BLENDFACTOR_ SRC_ALPHA ,
. dst_factor_alpha = SG_BLENDFACTOR_ONE_MINUS_SRC_ALPHA ,
. op_alpha = SG_BLENDOP_ADD ,
} ,
. label = " threedee " ,
} ) ;
state . threedee_alpha_blended_pip = sg_make_pipeline ( & threedee_pip_desc ) ;
}
desc = threedee_armature_shader_desc ( sg_query_backend ( ) ) ;
assert ( desc ) ;
@ -3394,10 +3416,11 @@ void init(void)
{
. shader = shd ,
. depth = {
. pixel_format = sapp_depth_format ( ) ,
. pixel_format = SG_PIXELFORMAT_DEPTH ,
. compare = SG_COMPAREFUNC_LESS_EQUAL ,
. write_enabled = true
} ,
. sample_count = SAMPLE_COUNT ,
. layout = {
. attrs =
{
@ -3421,11 +3444,45 @@ void init(void)
state . clear_depth_buffer_pass_action = ( sg_pass_action )
{
. colors [ 0 ] = { . action = SG_ ACTION_LOAD } ,
. depth = { . action = SG_ ACTION_CLEAR, . value = 1.0f } ,
. colors [ 0 ] = { . load_ action = SG_ LOAD ACTION_LOAD } ,
. depth = { . load_ action = SG_ LOAD ACTION_CLEAR, . clear_ value = 1.0f } ,
} ;
state . clear_everything_pass_action = state . clear_depth_buffer_pass_action ;
state . clear_everything_pass_action . colors [ 0 ] = ( sg_color_attachment_action ) { . action = SG_ACTION_CLEAR , . value = { clearcol . r , clearcol . g , clearcol . b , 1.0f } } ;
state . clear_everything_pass_action . colors [ 0 ] = ( sg_color_attachment_action ) { . load_action = SG_LOADACTION_CLEAR , . clear_value = { clearcol . r , clearcol . g , clearcol . b , 1.0f } } ;
state . threedee_msaa_pass_action = state . clear_everything_pass_action ;
state . threedee_msaa_pass_action . colors [ 0 ] . load_action = SG_LOADACTION_CLEAR ;
state . threedee_msaa_pass_action . colors [ 0 ] . store_action = SG_STOREACTION_DONTCARE ;
state . sampler_linear = sg_make_sampler ( & ( sg_sampler_desc ) {
. min_filter = SG_FILTER_LINEAR ,
. mag_filter = SG_FILTER_LINEAR ,
// .mipmap_filter = SG_FILTER_LINEAR,
. wrap_u = SG_WRAP_CLAMP_TO_EDGE ,
. wrap_v = SG_WRAP_CLAMP_TO_EDGE ,
// .max_anisotropy = 16,
. label = " sampler-linear " ,
} ) ;
state . sampler_linear_border = sg_make_sampler ( & ( sg_sampler_desc ) {
. min_filter = SG_FILTER_LINEAR ,
. mag_filter = SG_FILTER_LINEAR ,
. wrap_u = SG_WRAP_CLAMP_TO_BORDER ,
. wrap_v = SG_WRAP_CLAMP_TO_BORDER ,
. border_color = SG_BORDERCOLOR_OPAQUE_WHITE ,
. label = " sampler-linear-border " ,
} ) ;
state . sampler_nearest = sg_make_sampler ( & ( sg_sampler_desc ) {
. min_filter = SG_FILTER_NEAREST ,
. mag_filter = SG_FILTER_NEAREST ,
// for webgl NPOT texures https://developer.mozilla.org/en-US/docs/Web/API/WebGL_API/Tutorial/Using_textures_in_WebGL
. wrap_u = SG_WRAP_CLAMP_TO_EDGE ,
. wrap_v = SG_WRAP_CLAMP_TO_EDGE ,
. wrap_w = SG_WRAP_CLAMP_TO_EDGE ,
. label = " sampler-nearest " ,
} ) ;
}
Vec2 screen_size ( )
@ -3716,9 +3773,16 @@ void flush_quad_batch()
state . bind . vertex_buffer_offsets [ 0 ] = sg_append_buffer ( state . bind . vertex_buffers [ 0 ] , & ( sg_range ) { cur_batch_data , cur_batch_data_index * sizeof ( * cur_batch_data ) } ) ;
state . bind . fs_images [ SLOT_threedee_twodee_tex ] = cur_batch_image ;
state . bind . fs . images [ SLOT_threedee_twodee_tex ] = cur_batch_image ; // NOTE that this might get FUCKED if a custom pipeline is provided with more/less texture slots!!!
state . bind . fs . samplers [ SLOT_threedee_fs_twodee_smp ] = state . sampler_linear ; // NOTE that this might get FUCKED if a custom pipeline is provided with more/less sampler slots!!!
sg_apply_bindings ( & state . bind ) ;
cur_batch_params . tex_size = img_size ( cur_batch_image ) ;
cur_batch_params . screen_size = screen_size ( ) ;
# if defined(SOKOL_GLCORE33) || defined(SOKOL_GLES3)
cur_batch_params . flip_and_swap_rgb = 0 ;
# else
cur_batch_params . flip_and_swap_rgb = 1 ;
# endif
sg_apply_uniforms ( SG_SHADERSTAGE_FS , SLOT_threedee_twodee_fs_params , & SG_RANGE ( cur_batch_params ) ) ;
cur_batch_params . tex_size = V2 ( 0 , 0 ) ; // unsure if setting the tex_size to something nonzero fucks up the batching so I'm just resetting it back here
assert ( cur_batch_data_index % FLOATS_PER_VERTEX = = 0 ) ;
@ -3731,10 +3795,11 @@ void flush_quad_batch()
typedef enum
{
LAYER_ TILEMAP ,
LAYER_ INVALID ,
LAYER_WORLD ,
LAYER_UI ,
LAYER_UI_FG ,
LAYER_UI_TEXTINPUT ,
LAYER_SCREENSPACE_EFFECTS ,
LAYER_LAST
@ -3743,9 +3808,11 @@ typedef enum
typedef BUFF ( char , 200 ) StacktraceElem ;
typedef BUFF ( StacktraceElem , 16 ) StacktraceInfo ;
#if 0 // #ifdef WINDOWS
# include <dbghelp.h>
# pragma comment(lib, "DbgHelp")
StacktraceInfo get_stacktrace ( )
{
# ifdef WINDOWS
StacktraceInfo to_return = { 0 } ;
void * stack [ ARRLEN ( to_return . data ) ] = { 0 } ;
int captured = CaptureStackBackTrace ( 0 , ARRLEN ( to_return . data ) , stack , 0 ) ;
@ -3779,10 +3846,13 @@ StacktraceInfo get_stacktrace()
free ( symbol ) ;
}
return to_return ;
}
# else
StacktraceInfo get_stacktrace ( )
{
return ( StacktraceInfo ) { 0 } ;
# endif
}
# endif
typedef struct DrawParams
{
@ -3965,7 +4035,7 @@ void line(Vec2 from, Vec2 to, float line_width, Color color)
}
# ifdef DEVTOOLS
bool show_devtools = tru e;
bool show_devtools = fals e;
# ifdef PROFILING
extern bool profiling ;
# else
@ -4204,6 +4274,7 @@ typedef struct TextParams
Color * colors ; // color per character, if not null must be array of same length as text
bool do_clipping ;
LoadedFont * use_font ; // if null, uses default font
Layer layer ;
} TextParams ;
// returns bounds. To measure text you can set dry run to true and get the bounds
@ -4297,7 +4368,12 @@ AABB draw_text(TextParams t)
col = t . colors [ i ] ;
}
draw_quad ( ( DrawParams ) { to_draw , font . image , font_atlas_region , col , t . clip_to , . layer = LAYER_UI_FG , . do_clipping = t . do_clipping } ) ;
Layer to_use = LAYER_UI_FG ;
if ( t . layer ! = LAYER_INVALID )
{
to_use = t . layer ;
}
draw_quad ( ( DrawParams ) { to_draw , font . image , font_atlas_region , col , t . clip_to , . layer = to_use , . do_clipping = t . do_clipping } ) ;
}
}
}
@ -4815,8 +4891,8 @@ Shadow_State init_shadow_state() {
shadows . pass_action = ( sg_pass_action ) {
. colors [ 0 ] = {
. action = SG_ ACTION_CLEAR,
. value = { 1.0f , 1.0f , 1.0f , 1.0f }
. load_ action = SG_ LOAD ACTION_CLEAR,
. clear_ value = { 1.0f , 1.0f , 1.0f , 1.0f }
}
} ;
@ -4826,17 +4902,13 @@ Shadow_State init_shadow_state() {
be pertinent to just dig into sokol and add the functionality we want later ,
but as a first pass , we will just do as the romans do . I . e . have both a colour
and depth component . - Canada Day 2023.
TODO : with GLES3 , depth only rendering passes are now supported
*/
sg_image_desc img_desc = {
. render_target = true ,
. width = SHADOW_MAP_DIMENSION ,
. height = SHADOW_MAP_DIMENSION ,
. pixel_format = SG_PIXELFORMAT_RGBA8 ,
. min_filter = SG_FILTER_LINEAR ,
. mag_filter = SG_FILTER_LINEAR ,
. wrap_u = SG_WRAP_CLAMP_TO_BORDER ,
. wrap_v = SG_WRAP_CLAMP_TO_BORDER ,
. border_color = SG_BORDERCOLOR_OPAQUE_WHITE ,
. pixel_format = sapp_sgcontext ( ) . color_format ,
. sample_count = 1 ,
. label = " shadow-map-color-image "
} ;
@ -4867,7 +4939,7 @@ Shadow_State init_shadow_state() {
. compare = SG_COMPAREFUNC_LESS_EQUAL ,
. write_enabled = true ,
} ,
. colors [ 0 ] . pixel_format = SG_PIXELFORMAT_RGBA8 ,
. colors [ 0 ] . pixel_format = sapp_sgcontext ( ) . color_format ,
. label = " shadow-map-pipeline "
} ;
@ -4875,7 +4947,7 @@ Shadow_State init_shadow_state() {
desc . label = " armature-shadow-map-pipeline " ;
desc . shader = sg_make_shader ( threedee_armature_shadow_mapping_shader_desc ( sg_query_backend ( ) ) ) ;
sg_vertex_attr_ desc skeleton_vertex_attrs [ ] = {
sg_vertex_attr_ state skeleton_vertex_attrs [ ] = {
[ ATTR_threedee_vs_skeleton_pos_in ] . format = SG_VERTEXFORMAT_FLOAT3 ,
[ ATTR_threedee_vs_skeleton_uv_in ] . format = SG_VERTEXFORMAT_FLOAT2 ,
[ ATTR_threedee_vs_skeleton_indices_in ] . format = SG_VERTEXFORMAT_USHORT4N ,
@ -5075,12 +5147,22 @@ void actually_draw_thing(DrawnThing *it, Mat4 light_space_matrix, bool for_outli
{
if ( for_outline )
sg_apply_pipeline ( state . outline_mesh_pip ) ;
else if ( it - > alpha_blend )
sg_apply_pipeline ( state . threedee_alpha_blended_pip ) ;
else
sg_apply_pipeline ( state . threedee_pip ) ;
sg_bindings bindings = { 0 } ;
bindings . fs_images [ SLOT_threedee_tex ] = it - > mesh - > image ;
if ( ! for_outline )
bindings . fs_images [ SLOT_threedee_shadow_map ] = state . shadows . color_img ;
bindings . fs . images [ SLOT_threedee_tex ] = it - > mesh - > image ;
if ( for_outline )
{
bindings . fs . samplers [ SLOT_threedee_fs_outline_smp ] = state . sampler_linear ;
}
else
{
bindings . fs . images [ SLOT_threedee_shadow_map ] = state . shadows . color_img ;
bindings . fs . samplers [ SLOT_threedee_fs_shadow_smp ] = state . sampler_linear_border ;
bindings . fs . samplers [ SLOT_threedee_fs_smp ] = state . sampler_linear ;
}
bindings . vertex_buffers [ 0 ] = it - > mesh - > loaded_buffer ;
sg_apply_bindings ( & bindings ) ;
@ -5106,10 +5188,19 @@ void actually_draw_thing(DrawnThing *it, Mat4 light_space_matrix, bool for_outli
else
sg_apply_pipeline ( state . armature_pip ) ;
sg_bindings bindings = { 0 } ;
bindings . vs_images [ SLOT_threedee_bones_tex ] = it - > armature - > bones_texture ;
bindings . fs_images [ SLOT_threedee_tex ] = it - > armature - > image ;
if ( ! for_outline )
bindings . fs_images [ SLOT_threedee_shadow_map ] = state . shadows . color_img ;
bindings . vs . images [ SLOT_threedee_bones_tex ] = it - > armature - > bones_texture ;
bindings . vs . samplers [ SLOT_threedee_vs_skeleton_smp ] = state . sampler_nearest ;
bindings . fs . images [ SLOT_threedee_tex ] = it - > armature - > image ;
if ( for_outline )
{
bindings . fs . samplers [ SLOT_threedee_fs_outline_smp ] = state . sampler_linear ;
}
else
{
bindings . fs . images [ SLOT_threedee_shadow_map ] = state . shadows . color_img ;
bindings . fs . samplers [ SLOT_threedee_fs_shadow_smp ] = state . sampler_linear_border ;
bindings . fs . samplers [ SLOT_threedee_fs_smp ] = state . sampler_linear ;
}
bindings . vertex_buffers [ 0 ] = it - > armature - > loaded_buffer ;
sg_apply_bindings ( & bindings ) ;
@ -5253,7 +5344,8 @@ void flush_all_drawn_things(Vec3 light_dir, Vec3 cam_pos, Vec3 cam_facing, Vec3
if ( it - > mesh )
{
sg_bindings bindings = { 0 } ;
bindings . fs_images [ SLOT_threedee_tex ] = it - > mesh - > image ;
bindings . fs . images [ SLOT_threedee_tex ] = it - > mesh - > image ;
bindings . fs . samplers [ SLOT_threedee_fs_shadow_mapping_smp ] = state . sampler_linear ;
bindings . vertex_buffers [ 0 ] = it - > mesh - > loaded_buffer ;
sg_apply_bindings ( & bindings ) ;
@ -5278,8 +5370,10 @@ void flush_all_drawn_things(Vec3 light_dir, Vec3 cam_pos, Vec3 cam_facing, Vec3
if ( it - > armature )
{
sg_bindings bindings = { 0 } ;
bindings . vs_images [ SLOT_threedee_bones_tex ] = it - > armature - > bones_texture ;
bindings . fs_images [ SLOT_threedee_tex ] = it - > armature - > image ;
bindings . vs . images [ SLOT_threedee_bones_tex ] = it - > armature - > bones_texture ;
bindings . vs . samplers [ SLOT_threedee_vs_skeleton_smp ] = state . sampler_nearest ;
bindings . fs . images [ SLOT_threedee_tex ] = it - > armature - > image ;
bindings . fs . samplers [ SLOT_threedee_fs_shadow_mapping_smp ] = state . sampler_linear ;
bindings . vertex_buffers [ 0 ] = it - > armature - > loaded_buffer ;
sg_apply_bindings ( & bindings ) ;
@ -5305,8 +5399,8 @@ void flush_all_drawn_things(Vec3 light_dir, Vec3 cam_pos, Vec3 cam_facing, Vec3
{
sg_begin_pass ( state . outline_pass , & ( sg_pass_action ) {
. colors [ 0 ] = {
. action = SG_ ACTION_CLEAR,
. value = { 0.0f , 0.0f , 0.0f , 0.0f } ,
. load_ action = SG_ LOAD ACTION_CLEAR,
. clear_ value = { 0.0f , 0.0f , 0.0f , 0.0f } ,
}
} ) ;
@ -5323,7 +5417,7 @@ void flush_all_drawn_things(Vec3 light_dir, Vec3 cam_pos, Vec3 cam_facing, Vec3
// actually draw, IMPORTANT after this drawn_this_frame is zeroed out!
{
sg_begin_pass ( state . threedee_pass , & state . clear_everything _pass_action) ;
sg_begin_pass ( state . threedee_pass , & state . threedee_msaa _pass_action) ;
// draw meshes
SLICE_ITER ( DrawnThing , drawn_this_frame )
@ -5570,6 +5664,8 @@ void frame(void)
to_use = & farmer_armature ;
else if ( it - > npc_kind = = NPC_Raphael )
to_use = & man_in_black_armature ;
else if ( it - > npc_kind = = NPC_Angel )
to_use = & angel_armature ;
else
assert ( false ) ;
@ -5662,8 +5758,8 @@ void frame(void)
flush_all_drawn_things ( light_dir , cam_pos , facing , right ) ;
// draw the 3d render
draw_quad ( ( DrawParams ) { quad_at ( V2 ( 0.0 , screen_size ( ) . y ) , screen_size ( ) ) , IMG ( state . threedee_pass_ image) , WHITE , . layer = LAYER_WORLD , . custom_pipeline = state . twodee_colorcorrect_pip } ) ;
draw_quad ( ( DrawParams ) { quad_at ( V2 ( 0.0 , screen_size ( ) . y ) , screen_size ( ) ) , IMG ( state . outline_pass_ image) , WHITE , . custom_pipeline = state . twodee_outline_pip , . layer = LAYER_UI } ) ;
draw_quad ( ( DrawParams ) { quad_at ( V2 ( 0.0 , screen_size ( ) . y ) , screen_size ( ) ) , IMG ( state . threedee_pass_ resolve_ image) , WHITE , . layer = LAYER_WORLD , . custom_pipeline = state . twodee_colorcorrect_pip } ) ;
draw_quad ( ( DrawParams ) { quad_at ( V2 ( 0.0 , screen_size ( ) . y ) , screen_size ( ) ) , IMG ( state . outline_pass_ resolve_ image) , WHITE , . custom_pipeline = state . twodee_outline_pip , . layer = LAYER_UI } ) ;
// 2d drawing TODO move this to when the drawing is flushed.
sg_begin_default_pass ( & state . clear_depth_buffer_pass_action , sapp_width ( ) , sapp_height ( ) ) ;
@ -5671,15 +5767,15 @@ void frame(void)
// @Place(text input drawing)
# ifdef DESKTOP
draw_quad ( ( DrawParams ) { quad_at ( V2 ( 0 , screen_size ( ) . y ) , screen_size ( ) ) , IMG ( image_white_square ) , blendalpha ( BLACK , text_input_fade * 0.3f ) , . layer = LAYER_UI_ FG } ) ;
draw_quad ( ( DrawParams ) { quad_at ( V2 ( 0 , screen_size ( ) . y ) , screen_size ( ) ) , IMG ( image_white_square ) , blendalpha ( BLACK , text_input_fade * 0.3f ) , . layer = LAYER_UI_ TEXTINPUT } ) ;
Vec2 edge_of_text = MulV2F ( screen_size ( ) , 0.5f ) ;
if ( text_input_buffer_length > 0 )
{
AABB bounds = draw_centered_text ( ( TextParams ) { false , MD_S8 ( text_input_buffer , text_input_buffer_length ) , MulV2F ( screen_size ( ) , 0.5f ) , blendalpha ( WHITE , text_input_fade ) , 1.0f , . use_font = & font_for_text_input }) ;
AABB bounds = draw_centered_text ( ( TextParams ) { false , MD_S8 ( text_input_buffer , text_input_buffer_length ) , MulV2F ( screen_size ( ) , 0.5f ) , blendalpha ( WHITE , text_input_fade ) , 1.0f , . use_font = & font_for_text_input , . layer = LAYER_UI_TEXTINPUT }) ;
edge_of_text = bounds . lower_right ;
}
Vec2 cursor_center = V2 ( edge_of_text . x , screen_size ( ) . y / 2.0f ) ;
draw_quad ( ( DrawParams ) { quad_centered ( cursor_center , V2 ( 3.0f , 80.0f ) ) , IMG ( image_white_square ) , blendalpha ( WHITE , text_input_fade * ( sinf ( ( float ) elapsed_time * 8.0f ) / 2.0f + 0.5f ) ) , . layer = LAYER_UI_ FG } ) ;
draw_quad ( ( DrawParams ) { quad_centered ( cursor_center , V2 ( 3.0f , 80.0f ) ) , IMG ( image_white_square ) , blendalpha ( WHITE , text_input_fade * ( sinf ( ( float ) elapsed_time * 8.0f ) / 2.0f + 0.5f ) ) , . layer = LAYER_UI_ TEXTINPUT } ) ;
# endif
// Draw Tilemap draw tilemap tilemap drawing
@ -5877,10 +5973,8 @@ void frame(void)
static bool player_in_combat = false ;
float speed_target = 1.0f ;
gs . stopped_time = cur_unread_entity ! = 0 ;
gs . stopped_time = cur_unread_entity ! = 0 | | ( ! gs . no_angel_screen ) ;
if ( gs . stopped_time ) speed_target = 0.0f ;
// pausing the game
speed_factor = Lerp ( speed_factor , unwarped_dt * 10.0f , speed_target ) ;
@ -6851,6 +6945,76 @@ ISANERROR("Don't know how to do this stuff on this platform.")
draw_centered_text ( ( TextParams ) { false , MD_S8Lit ( " The AI server is having technical difficulties... " ) , text_center , WHITE , 1.0f } ) ;
}
// angel screen
gs . no_angel_screen = true ;
{
static float visible = 1.0f ;
bool should_be_visible = ! gs . no_angel_screen ;
visible = Lerp ( visible , unwarped_dt * 2.0f , should_be_visible ? 1.0f : 0.0f ) ;
Entity * angel_entity = 0 ;
ENTITIES_ITER ( gs . entities )
{
if ( it - > is_npc & & it - > npc_kind = = NPC_Angel )
{
assert ( ! angel_entity ) ;
angel_entity = it ;
}
}
assert ( angel_entity ) ;
if ( should_be_visible ) gs . player - > talking_to = frome ( angel_entity ) ;
draw_quad ( ( DrawParams ) { quad_at ( V2 ( 0 , screen_size ( ) . y ) , screen_size ( ) ) , IMG ( image_white_square ) , blendalpha ( BLACK , visible ) , . layer = LAYER_UI_FG } ) ;
static MD_String8List to_say = { 0 } ;
static double cur_characters = 0 ;
if ( to_say . node_count = = 0 )
{
to_say = split_by_word ( persistent_arena , MD_S8Lit ( " You've been asleep for a long long time... " ) ) ;
cur_characters = 0 ;
}
MD_String8 cur_word = { 0 } ;
MD_String8Node * cur_word_node = 0 ;
double chars_said = cur_characters ;
for ( MD_String8Node * cur = to_say . first ; cur ; cur = cur - > next )
{
if ( ( int ) chars_said < cur - > string . size )
{
cur_word = cur - > string ;
cur_word_node = cur ;
break ;
}
chars_said - = ( double ) cur - > string . size ;
}
if ( ! cur_word . str )
{
cur_word = to_say . last - > string ;
cur_word_node = to_say . last ;
}
cur_characters + = unwarped_dt * ANGEL_CHARACTERS_PER_SEC ;
chars_said + = unwarped_dt * ANGEL_CHARACTERS_PER_SEC ;
if ( chars_said > cur_word . size & & cur_word_node - > next )
{
play_audio ( & sound_angel_grunt_0 , 1.0f ) ;
}
assert ( cur_word_node ) ;
MD_String8Node * prev_next = cur_word_node - > next ;
cur_word_node - > next = 0 ;
MD_String8 without_unsaid = MD_S8ListJoin ( frame_arena , to_say , & ( MD_StringJoin ) { . mid = MD_S8Lit ( " " ) } ) ;
cur_word_node - > next = prev_next ;
draw_centered_text ( ( TextParams ) { false , without_unsaid , V2 ( screen_size ( ) . x * 0.5f , screen_size ( ) . y * 0.75f ) , blendalpha ( WHITE , visible ) , 1.0f , . use_font = & font_for_text_input } ) ;
draw_centered_text ( ( TextParams ) { false , MD_S8Lit ( " (Press E to speak) " ) , V2 ( screen_size ( ) . x * 0.5f , screen_size ( ) . y * 0.25f ) , blendalpha ( WHITE , visible * 0.5f ) , 0.8f , . use_font = & font_for_text_input } ) ;
if ( pressed . interact )
{
begin_text_input ( ) ;
}
}
// win screen
{
static float visible = 0.0f ;
@ -6937,7 +7101,7 @@ ISANERROR("Don't know how to do this stuff on this platform.")
{
Vec2 depth_size = V2 ( 200.0f , 200.0f ) ;
draw_quad ( ( DrawParams ) { quad_at ( V2 ( screen_size ( ) . x - depth_size . x , screen_size ( ) . y ) , depth_size ) , IMG ( state . shadows . color_img ) , WHITE , . layer = LAYER_UI_FG } ) ;
draw_quad ( ( DrawParams ) { quad_at ( V2 ( 0.0 , screen_size ( ) . y / 2.0f ) , MulV2F ( screen_size ( ) , 0.1f ) ) , IMG ( state . outline_pass_ image) , WHITE , . layer = LAYER_UI_FG } ) ;
draw_quad ( ( DrawParams ) { quad_at ( V2 ( 0.0 , screen_size ( ) . y / 2.0f ) , MulV2F ( screen_size ( ) , 0.1f ) ) , IMG ( state . outline_pass_ resolve_ image) , WHITE , . layer = LAYER_UI_FG } ) ;
Vec3 view_cam_pos = MulM4V4 ( InvGeneralM4 ( view ) , V4 ( 0 , 0 , 0 , 1 ) ) . xyz ;
//if(view_cam_pos.y >= 4.900f) // causes nan if not true... not good...
@ -7040,6 +7204,7 @@ ISANERROR("Don't know how to do this stuff on this platform.")
Vec2 * points = d . quad . points ;
threedee_twodee_fs_params_t params = {
. tint = d . tint ,
. time = ( float ) fmod ( elapsed_time , 100 ) ,
} ;
params . alpha_clip_threshold = d . alpha_clip_threshold ;
if ( d . do_clipping )
@ -7098,10 +7263,10 @@ ISANERROR("Don't know how to do this stuff on this platform.")
} ;
// convert to uv space
sg_image_ info info = sg_query_image_info ( d . image ) ;
sg_image_ desc desc = sg_query_image_desc ( d . image ) ;
for ( int i = 0 ; i < 4 ; i + + )
{
tex_coords [ i ] = DivV2 ( tex_coords [ i ] , V2 ( ( float ) info. width , ( float ) info . height ) ) ;
tex_coords [ i ] = DivV2 ( tex_coords [ i ] , V2 ( ( float ) desc. width , ( float ) desc . height ) ) ;
}
for ( int i = 0 ; i < 4 ; i + + )
{
@ -7221,9 +7386,31 @@ void event(const sapp_event *e)
}
# endif
if ( e - > type = = SAPP_EVENTTYPE_KEY_DOWN & & e - > key_code = = SAPP_KEYCODE_F11 )
if ( e - > type = = SAPP_EVENTTYPE_KEY_DOWN & &
( e - > key_code = = SAPP_KEYCODE_F11 | |
e - > key_code = = SAPP_KEYCODE_ENTER & & ( ( e - > modifiers & SAPP_MODIFIER_ALT ) | | ( e - > modifiers & SAPP_MODIFIER_SHIFT ) ) ) )
{
# ifdef DESKTOP
sapp_toggle_fullscreen ( ) ;
# else
EM_ASM ( {
var elem = document . documentElement ;
if ( document . fullscreenElement | | document . webkitFullscreenElement | | document . mozFullScreenElement | | document . msFullscreenElement )
{
if ( document . exitFullscreen ) document . exitFullscreen ( ) ;
else if ( document . webkitExitFullscreen ) document . webkitExitFullscreen ( ) ;
else if ( document . mozCancelFullScreen ) document . mozCancelFullScreen ( ) ;
else if ( document . msExitFullscreen ) document . msExitFullscreen ( ) ;
}
else
{
if ( elem . requestFullscreen ) elem . requestFullscreen ( ) ;
else if ( elem . webkitRequestFullscreen ) elem . webkitRequestFullscreen ( ) ;
else if ( elem . mozRequestFullScreen ) elem . mozRequestFullScreen ( ) ;
else if ( elem . msRequestFullscreen ) elem . msRequestFullscreen ( ) ;
}
} ) ;
# endif
}
# ifdef DEVTOOLS
@ -7447,13 +7634,13 @@ sapp_desc sokol_main(int argc, char* argv[])
. frame_cb = frame ,
. cleanup_cb = cleanup ,
. event_cb = event ,
. sample_count = 1 , // bumping this back to 4 is troublesome for web, because there's a mismatch in sample counts. Perhaps we must upgrade to gles3, in doing so, we should upgrade to the newest sokol gfx.
. sample_count = 1 ,
. width = 800 ,
. height = 600 ,
//.gl_force_gles2 = true, not sure why this was here in example, look into
. window_title = " RPGPT " ,
. window_title = " Dante's Cowboy " ,
. win32_console_attach = true ,
. win32_console_create = true ,
. icon . sokol_default = true ,
. logger . func = slog_func ,
} ;
}