From deb49cc59884e298467c497d46518243ddb5a209 Mon Sep 17 00:00:00 2001 From: hgn Date: Tue, 19 Jul 2022 14:51:45 +0100 Subject: [PATCH] its ot' --- dep/stb/stb_include.h | 295 ++++++++++++++++++++++++++++++++++++++++++ src/shader.c | 230 ++++++++++++++++++++++++++++++++ src/vg/vg.h | 92 +++++++------ src/vg/vg_audio.h | 19 ++- src/vg/vg_input.h | 76 ++++++++--- src/vg/vg_lines.h | 75 +++++++++-- src/vg/vg_m.h | 211 +++++++++++++++++++++++++++++- src/vg/vg_shader.h | 198 ++++++++++++++-------------- src/vg/vg_shader2.h | 13 ++ src/vg/vg_ui.h | 119 +++++++++++++++-- vg_compiler.sh | 54 +++++--- 11 files changed, 1167 insertions(+), 215 deletions(-) create mode 100644 dep/stb/stb_include.h create mode 100644 src/shader.c create mode 100644 src/vg/vg_shader2.h diff --git a/dep/stb/stb_include.h b/dep/stb/stb_include.h new file mode 100644 index 0000000..c5db201 --- /dev/null +++ b/dep/stb/stb_include.h @@ -0,0 +1,295 @@ +// stb_include.h - v0.02 - parse and process #include directives - public domain +// +// To build this, in one source file that includes this file do +// #define STB_INCLUDE_IMPLEMENTATION +// +// This program parses a string and replaces lines of the form +// #include "foo" +// with the contents of a file named "foo". It also embeds the +// appropriate #line directives. Note that all include files must +// reside in the location specified in the path passed to the API; +// it does not check multiple directories. +// +// If the string contains a line of the form +// #inject +// then it will be replaced with the contents of the string 'inject' passed to the API. +// +// Options: +// +// Define STB_INCLUDE_LINE_GLSL to get GLSL-style #line directives +// which use numbers instead of filenames. +// +// Define STB_INCLUDE_LINE_NONE to disable output of #line directives. +// +// Standard libraries: +// +// stdio.h FILE, fopen, fclose, fseek, ftell +// stdlib.h malloc, realloc, free +// string.h strcpy, strncmp, memcpy +// +// Credits: +// +// Written by Sean Barrett. +// +// Fixes: +// Michal Klos + +#ifndef STB_INCLUDE_STB_INCLUDE_H +#define STB_INCLUDE_STB_INCLUDE_H + +// Do include-processing on the string 'str'. To free the return value, pass it to free() +char *stb_include_string(char *str, char *inject, char *path_to_includes, char *filename_for_line_directive, char error[256]); + +// Concatenate the strings 'strs' and do include-processing on the result. To free the return value, pass it to free() +char *stb_include_strings(char **strs, int count, char *inject, char *path_to_includes, char *filename_for_line_directive, char error[256]); + +// Load the file 'filename' and do include-processing on the string therein. note that +// 'filename' is opened directly; 'path_to_includes' is not used. To free the return value, pass it to free() +char *stb_include_file(char *filename, char *inject, char *path_to_includes, char error[256]); + +#endif + + +#ifdef STB_INCLUDE_IMPLEMENTATION + +#include +#include +#include + +static char *stb_include_load_file(char *filename, size_t *plen) +{ + char *text; + size_t len; + FILE *f = fopen(filename, "rb"); + if (f == 0) return 0; + fseek(f, 0, SEEK_END); + len = (size_t) ftell(f); + if (plen) *plen = len; + text = (char *) malloc(len+1); + if (text == 0) return 0; + fseek(f, 0, SEEK_SET); + fread(text, 1, len, f); + fclose(f); + text[len] = 0; + return text; +} + +typedef struct +{ + int offset; + int end; + char *filename; + int next_line_after; +} include_info; + +static include_info *stb_include_append_include(include_info *array, int len, int offset, int end, char *filename, int next_line) +{ + include_info *z = (include_info *) realloc(array, sizeof(*z) * (len+1)); + z[len].offset = offset; + z[len].end = end; + z[len].filename = filename; + z[len].next_line_after = next_line; + return z; +} + +static void stb_include_free_includes(include_info *array, int len) +{ + int i; + for (i=0; i < len; ++i) + free(array[i].filename); + free(array); +} + +static int stb_include_isspace(int ch) +{ + return (ch == ' ' || ch == '\t' || ch == '\r' || ch == '\n'); +} + +// find location of all #include and #inject +static int stb_include_find_includes(char *text, include_info **plist) +{ + int line_count = 1; + int inc_count = 0; + char *s = text, *start; + include_info *list = NULL; + while (*s) { + // parse is always at start of line when we reach here + start = s; + while (*s == ' ' || *s == '\t') + ++s; + if (*s == '#') { + ++s; + while (*s == ' ' || *s == '\t') + ++s; + if (0==strncmp(s, "include", 7) && stb_include_isspace(s[7])) { + s += 7; + while (*s == ' ' || *s == '\t') + ++s; + if (*s == '"') { + char *t = ++s; + while (*t != '"' && *t != '\n' && *t != '\r' && *t != 0) + ++t; + if (*t == '"') { + char *filename = (char *) malloc(t-s+1); + memcpy(filename, s, t-s); + filename[t-s] = 0; + s=t; + while (*s != '\r' && *s != '\n' && *s != 0) + ++s; + // s points to the newline, so s-start is everything except the newline + list = stb_include_append_include(list, inc_count++, start-text, s-text, filename, line_count+1); + } + } + } else if (0==strncmp(s, "inject", 6) && (stb_include_isspace(s[6]) || s[6]==0)) { + while (*s != '\r' && *s != '\n' && *s != 0) + ++s; + list = stb_include_append_include(list, inc_count++, start-text, s-text, NULL, line_count+1); + } + } + while (*s != '\r' && *s != '\n' && *s != 0) + ++s; + if (*s == '\r' || *s == '\n') { + s = s + (s[0] + s[1] == '\r' + '\n' ? 2 : 1); + } + ++line_count; + } + *plist = list; + return inc_count; +} + +// avoid dependency on sprintf() +static void stb_include_itoa(char str[9], int n) +{ + int i; + for (i=0; i < 8; ++i) + str[i] = ' '; + str[i] = 0; + + for (i=1; i < 8; ++i) { + str[7-i] = '0' + (n % 10); + n /= 10; + if (n == 0) + break; + } +} + +static char *stb_include_append(char *str, size_t *curlen, char *addstr, size_t addlen) +{ + str = (char *) realloc(str, *curlen + addlen); + memcpy(str + *curlen, addstr, addlen); + *curlen += addlen; + return str; +} + +char *stb_include_string(char *str, char *inject, char *path_to_includes, char *filename, char error[256]) +{ + char temp[4096]; + include_info *inc_list; + int i, num = stb_include_find_includes(str, &inc_list); + size_t source_len = strlen(str); + char *text=0; + size_t textlen=0, last=0; + for (i=0; i < num; ++i) { + text = stb_include_append(text, &textlen, str+last, inc_list[i].offset - last); + // write out line directive for the include + #ifndef STB_INCLUDE_LINE_NONE + #ifdef STB_INCLUDE_LINE_GLSL + if (textlen != 0) // GLSL #version must appear first, so don't put a #line at the top + #endif + { + strcpy(temp, "#line "); + stb_include_itoa(temp+6, 1); + strcat(temp, " "); + #ifdef STB_INCLUDE_LINE_GLSL + stb_include_itoa(temp+15, i+1); + #else + strcat(temp, "\""); + if (inc_list[i].filename == 0) + strcmp(temp, "INJECT"); + else + strcat(temp, inc_list[i].filename); + strcat(temp, "\""); + #endif + strcat(temp, "\n"); + text = stb_include_append(text, &textlen, temp, strlen(temp)); + } + #endif + if (inc_list[i].filename == 0) { + if (inject != 0) + text = stb_include_append(text, &textlen, inject, strlen(inject)); + } else { + char *inc; + strcpy(temp, path_to_includes); + strcat(temp, "/"); + strcat(temp, inc_list[i].filename); + inc = stb_include_file(temp, inject, path_to_includes, error); + if (inc == NULL) { + stb_include_free_includes(inc_list, num); + return NULL; + } + text = stb_include_append(text, &textlen, inc, strlen(inc)); + free(inc); + } + // write out line directive + #ifndef STB_INCLUDE_LINE_NONE + strcpy(temp, "\n#line "); + stb_include_itoa(temp+6, inc_list[i].next_line_after); + strcat(temp, " "); + #ifdef STB_INCLUDE_LINE_GLSL + stb_include_itoa(temp+15, 0); + #else + strcat(temp, filename != 0 ? filename : "source-file"); + #endif + text = stb_include_append(text, &textlen, temp, strlen(temp)); + // no newlines, because we kept the #include newlines, which will get appended next + #endif + last = inc_list[i].end; + } + text = stb_include_append(text, &textlen, str+last, source_len - last + 1); // append '\0' + stb_include_free_includes(inc_list, num); + return text; +} + +char *stb_include_strings(char **strs, int count, char *inject, char *path_to_includes, char *filename, char error[256]) +{ + char *text; + char *result; + int i; + size_t length=0; + for (i=0; i < count; ++i) + length += strlen(strs[i]); + text = (char *) malloc(length+1); + length = 0; + for (i=0; i < count; ++i) { + strcpy(text + length, strs[i]); + length += strlen(strs[i]); + } + result = stb_include_string(text, inject, path_to_includes, filename, error); + free(text); + return result; +} + +char *stb_include_file(char *filename, char *inject, char *path_to_includes, char error[256]) +{ + size_t len; + char *result; + char *text = stb_include_load_file(filename, &len); + if (text == NULL) { + strcpy(error, "Error: couldn't load '"); + strcat(error, filename); + strcat(error, "'"); + return 0; + } + result = stb_include_string(text, inject, path_to_includes, filename, error); + free(text); + return result; +} + +#if 0 // @TODO, GL_ARB_shader_language_include-style system that doesn't touch filesystem +char *stb_include_preloaded(char *str, char *inject, char *includes[][2], char error[256]) +{ + +} +#endif + +#endif // STB_INCLUDE_IMPLEMENTATION diff --git a/src/shader.c b/src/shader.c new file mode 100644 index 0000000..2f7c167 --- /dev/null +++ b/src/shader.c @@ -0,0 +1,230 @@ +#define STB_INCLUDE_IMPLEMENTATION +#define STB_INCLUDE_LINE_GLSL +#include "../dep/stb/stb_include.h" +#define VG_TOOLS +#include "vg/vg.h" + +struct uniform +{ + char name[30]; + char type[20]; +} +uniform_buffer[100]; +static int uniform_count; + +static int compile_subshader( FILE *header, char *name ) +{ + char error[256]; + char *full = stb_include_file( name, "", ".", error ); + + if( !full ) + { + fprintf( stderr, "stb_include_file error:\n%s\n", error ); + return 0; + } + else + { + /* VG */ + + fprintf( header, "{\n" + ".orig_file = \"../shaders/%s\",\n" + ".static_src = \n", name ); + + char *cur = full, *start = full; + while( 1 ) + { + char c = *cur; + if( c == '\n' || c == '\0' ) + { + *cur = '\0'; + fputs( "\"", header ); + fputs( start, header ); + + if( !strncmp(start,"uniform",7) ) + { + start += 8; + struct uniform *uf = &uniform_buffer[ uniform_count ++ ]; + for( int i=0;; i++ ) + { + if( start[i] == '\0' ) + break; + + if( start[i] == ';' ) + { + start[i] = '\0'; + strncpy( uf->name, start, sizeof(uf->name) ); + } + + if( start[i] == ' ' ) + { + start[i] = '\0'; + strncpy( uf->type, start, sizeof(uf->type) ); + start = start+i+1; + i=0; + } + } + } + + if( c == '\0' ) + { + fputs( "\"", header ); + break; + } + + fputs( "\\n\"\n", header ); + start = cur+1; + } + cur ++; + } + + fputs( "},", header ); + } + + free( full ); + return 1; +} + +int main( int argc, char *argv[] ) +{ + if( argc < 2 || (argc-1)%3 != 0 ) + { + fprintf( stderr, "invalid\n" ); + return 0; + } + + char path[260]; + int shader_count = (argc-1)/3; + for( int i=0; iname); + } + + for( int i=0; itype,"vec2") ) + { + fprintf( header, "static void shader_%s_%s(v2f v){\n" + " glUniform2fv( _uniform_%s_%s, 1, v );\n" + "}\n", args[0], uf->name, args[0], uf->name ); + } + if( !strcmp(uf->type,"vec3") ) + { + fprintf( header, "static void shader_%s_%s(v3f v){\n" + " glUniform3fv( _uniform_%s_%s, 1, v );\n" + "}\n", args[0], uf->name, args[0], uf->name ); + } + if( !strcmp(uf->type,"vec4") ) + { + fprintf( header, "static void shader_%s_%s(v4f v){\n" + " glUniform4fv( _uniform_%s_%s, 1, v );\n" + "}\n", args[0], uf->name, args[0], uf->name ); + } + if( !strcmp(uf->type,"sampler2D") ) + { + fprintf( header, "static void shader_%s_%s(int i){\n" + " glUniform1i( _uniform_%s_%s, i );\n" + "}\n", args[0], uf->name, args[0], uf->name ); + } + if( !strcmp(uf->type,"float") ) + { + fprintf( header, "static void shader_%s_%s(float f){\n" + " glUniform1f( _uniform_%s_%s, f );\n" + "}\n", args[0], uf->name, args[0], uf->name ); + } + if( !strcmp(uf->type,"mat4x3") ) + { + fprintf( header, + "static void shader_%s_%s(m4x3f m){\n" + " glUniformMatrix4x3fv" + "( _uniform_%s_%s, 1, GL_FALSE, (float *)m );\n" + "}\n", args[0], uf->name, args[0], uf->name ); + } + if( !strcmp(uf->type,"mat3") ) + { + fprintf( header, + "static void shader_%s_%s(m3x3f m){\n" + " glUniformMatrix3fv" + "( _uniform_%s_%s, 1, GL_FALSE, (float *)m );\n" + "}\n", args[0], uf->name, args[0], uf->name ); + } + if( !strcmp(uf->type,"mat4") ) + { + fprintf( header, + "static void shader_%s_%s(m4x4f m){\n" + " glUniformMatrix4fv" + "( _uniform_%s_%s, 1, GL_FALSE, (float *)m );\n" + "}\n", args[0], uf->name, args[0], uf->name ); + } + } + + fprintf( header, + "static void shader_%s_register(void){\n" + " vg_shader_register( &_shader_%s );\n" + "}\n", + args[0],args[0] ); + + fprintf( header, + "static void shader_%s_use(void){ glUseProgram(_shader_%s.id); }\n", + args[0], args[0] ); + + fprintf( header, + "static void shader_%s_link(void){\n", + args[0] ); + + for( int i=0; iname, + args[0], uf->name ); + } + + fprintf( header, "}\n" ); + fprintf( header, "#endif /* SHADER_%s_H */\n", args[0] ); + fclose( header ); + } +} diff --git a/src/vg/vg.h b/src/vg/vg.h index a36697b..31cfa80 100644 --- a/src/vg/vg.h +++ b/src/vg/vg.h @@ -222,58 +222,64 @@ static void vg_init( int argc, char *argv[], const char *window_name ) vg_register(); vg_register_exit( &vg_free, "vg_free" ); + + + vg_shaders_recompile(0,NULL); + vg_register_exit( &vg_shaders_free, "vg_shaders_free" ); + vg_function_push( (struct vg_cmd){ + .name = "shaders", + .function = vg_shaders_recompile + }); + - if( vg_shaders_compile() ) - { - vg_start(); + vg_start(); + + vg_console_init(); + vg_register_exit( &vg_console_free, "Console" ); + + vg_audio_init(); + vg_register_exit( &vg_audio_free, "vg_audio_free" ); - vg_console_init(); - vg_register_exit( &vg_console_free, "Console" ); + vg_debugtools_setup(); - vg_audio_init(); - vg_register_exit( &vg_audio_free, "vg_audio_free" ); + /* + * Main gameloop + */ + while( !glfwWindowShouldClose( vg_window ) ) + { + v2_copy( (v2f){ 0.0f, 0.0f }, vg_mouse_wheel ); + + glfwPollEvents(); - vg_debugtools_setup(); + #ifdef VG_STEAM + sw_event_loop(); + #endif + + vg_time_last = vg_time; + vg_time = glfwGetTime(); + vg_time_delta = vg_minf( vg_time - vg_time_last, 0.1f ); + + vg_update_inputs(); + vg_update(); + vg_render(); + + vg_lines_drawall((float*)vg_pv); - /* - * Main gameloop - */ - while( !glfwWindowShouldClose( vg_window ) ) { - v2_copy( (v2f){ 0.0f, 0.0f }, vg_mouse_wheel ); - - glfwPollEvents(); - - #ifdef VG_STEAM - sw_event_loop(); - #endif + ui_begin( &ui_global_ctx, vg_window_x, vg_window_y ); + ui_set_mouse( &ui_global_ctx, vg_mouse[0], vg_mouse[1], + vg_get_button_state( "primary" ) ); - vg_time_last = vg_time; - vg_time = glfwGetTime(); - vg_time_delta = vg_minf( vg_time - vg_time_last, 0.1f ); + vg_ui(); + vg_console_draw(); + vg_debugtools_draw(); - vg_update_inputs(); - vg_update(); - vg_render(); - - vg_lines_drawall((float*)vg_pv); - - { - ui_begin( &ui_global_ctx, vg_window_x, vg_window_y ); - ui_set_mouse( &ui_global_ctx, vg_mouse[0], vg_mouse[1], - vg_get_button_state( "primary" ) ); - - vg_ui(); - vg_console_draw(); - vg_debugtools_draw(); - - ui_resolve( &ui_global_ctx ); - ui_draw( &ui_global_ctx, NULL ); - } - - glfwSwapBuffers( vg_window ); - VG_CHECK_GL(); + ui_resolve( &ui_global_ctx ); + ui_draw( &ui_global_ctx, NULL ); } + + glfwSwapBuffers( vg_window ); + VG_CHECK_GL(); } vg_exit(); diff --git a/src/vg/vg_audio.h b/src/vg/vg_audio.h index 6ef64eb..024d87c 100644 --- a/src/vg/vg_audio.h +++ b/src/vg/vg_audio.h @@ -36,7 +36,9 @@ struct sfx_system /* Modifiers */ sfx_vol_control *vol_src; - float vol, cvol; + float vol, cvol, pan; + + u32 delay; /* Info */ u32 ch, end, cur; @@ -223,7 +225,8 @@ static float sfx_get_master(void) return val; } -void audio_mixer_callback( ma_device *pDevice, void *pOutBuf, const void *pInput, ma_uint32 frameCount ); +void audio_mixer_callback( ma_device *pDevice, void *pOutBuf, + const void *pInput, ma_uint32 frameCount ); static void vg_audio_init(void) { @@ -323,6 +326,7 @@ void audio_mixer_callback( ma_device *pDevice, void *pOutBuf, if( sys->flags & SFX_FLAG_PERSISTENT ) { sys->vol = sys->persisitent_source->vol * g_master_volume; + sys->pan = sys->persisitent_source->pan; /* Fadeout effect ( + remove ) */ if( sys->persisitent_source->fadeout ) @@ -377,7 +381,7 @@ void audio_mixer_callback( ma_device *pDevice, void *pOutBuf, samples_this_run = VG_MIN( samples_this_run, sys->fadeout_current ); } - for( u32 j = 0; j < samples_this_run; j ++ ) + for( u32 j=0; jsource, cursor, sys->ch ); @@ -394,8 +398,11 @@ void audio_mixer_callback( ma_device *pDevice, void *pOutBuf, break; } - pOut32F[ buffer_pos*2+0 ] += pcf[0] * vol; - pOut32F[ buffer_pos*2+1 ] += pcf[1] * vol; + float sl = 1.0f-sys->pan, + sr = 1.0f+sys->pan; + + pOut32F[ buffer_pos*2+0 ] += pcf[0] * vol * sl; + pOut32F[ buffer_pos*2+1 ] += pcf[1] * vol * sr; cursor ++; buffer_pos ++; @@ -407,7 +414,7 @@ void audio_mixer_callback( ma_device *pDevice, void *pOutBuf, { if( frames_write ) { - cursor = 0; + cursor = sys->clip_start; continue; } } diff --git a/src/vg/vg_input.h b/src/vg/vg_input.h index 2506ba4..76b3b95 100644 --- a/src/vg/vg_input.h +++ b/src/vg/vg_input.h @@ -1,4 +1,6 @@ /* Copyright (C) 2021-2022 Harry Godden (hgn) - All Rights Reserved */ +#ifndef VG_INPUT_H +#define VG_INPUT_H static inline float vg_get_axis( const char *axis ); static inline int vg_get_button( const char *button ); @@ -45,11 +47,11 @@ static struct button_binding { const char *name; int bind; - int controller; int value; int prev; } -vg_button_binds[]; +vg_button_binds[], +vg_controller_binds[]; #include "vg_config.h" @@ -59,43 +61,72 @@ vg_button_binds[]; static inline float vg_get_axis( const char *axis ) { for( int i = 0; i < vg_list_size( vg_axis_binds ); i ++ ) - { if( !strcmp( axis, vg_axis_binds[i].name ) ) - { return vg_axis_binds[i].value; - } - } } static inline struct button_binding *vg_get_button_ptr( const char *button ) { for( int i=0; ivalue; + *prev |= bind->prev; + } + + if( bindc ) + { + *cur |= bindc->value; + *prev |= bindc->prev; + } +} + static inline int vg_get_button( const char *button ) { - return vg_get_button_ptr( button )->value && !vg_console_enabled(); + int cur, prev; + vg_get_button_states( button, &cur, &prev ); + + return cur && !vg_console_enabled(); } static inline int vg_get_button_down( const char *button ) { - struct button_binding *bind = vg_get_button_ptr( button ); - return bind->value & (bind->value ^ bind->prev) && !vg_console_enabled(); + int cur, prev; + vg_get_button_states( button, &cur, &prev ); + + return cur & (cur ^ prev) && !vg_console_enabled(); } static inline int vg_get_button_up( const char *button ) { - struct button_binding *bind = vg_get_button_ptr( button ); - return bind->prev & (bind->value ^ bind->prev) && !vg_console_enabled(); + int cur, prev; + vg_get_button_states( button, &cur, &prev ); + + return prev & (cur ^ prev) && !vg_console_enabled(); } static inline enum vg_button_state vg_get_button_state( const char *button ) @@ -133,12 +164,15 @@ void vg_update_inputs(void) { struct button_binding *binding = vg_button_binds + i; binding->prev = binding->value; - - if( binding->controller ) - binding->value = vg_gamepad.buttons[ binding->controller ]; - else - binding->value = get_button_cross_device( binding->bind ); + binding->value = get_button_cross_device( binding->bind ); } + + for( int i=0; iprev = binding->value; + binding->value = vg_gamepad.buttons[ binding->bind ]; + } /* Update axis inputs */ for( int i = 0; i < vg_list_size( vg_axis_binds ); i ++ ) @@ -169,3 +203,5 @@ static void vg_gamepad_init(void) } } } + +#endif diff --git a/src/vg/vg_lines.h b/src/vg/vg_lines.h index 704d9bd..e14d338 100644 --- a/src/vg/vg_lines.h +++ b/src/vg/vg_lines.h @@ -8,7 +8,15 @@ static int debug_lines_enable = 1; typedef v2f line_co; #endif -SHADER_DEFINE( vg_line_shader, +static struct vg_shader _shader_lines = +{ + .name = "[vg] lines", + .link = NULL, + .vs = + { + .orig_file = NULL, + .static_src = + #ifdef VG_3D "uniform mat4 uPv;" "layout (location=0) in vec3 a_co;" @@ -29,9 +37,13 @@ SHADER_DEFINE( vg_line_shader, #endif " s_colour = a_colour;" " gl_Position = vert_pos;" - "}", - - // FRAGMENT + "}" + }, + .fs = + { + .orig_file = NULL, + .static_src = + "out vec4 FragColor;" "" "in vec4 s_colour;" @@ -40,9 +52,8 @@ SHADER_DEFINE( vg_line_shader, "{" " FragColor = s_colour;" "}" - , - UNIFORMS({ "uPv" }) -) + } +}; struct { @@ -72,8 +83,8 @@ static void vg_lines_init(void) .opt_i32 = { .min=0, .max=1, .clamp=1 }, .persistent = 1 }); - - SHADER_INIT( vg_line_shader ); + + vg_shader_register( &_shader_lines ); glGenVertexArrays( 1, &vg_lines.vao ); glGenBuffers( 1, &vg_lines.vbo ); @@ -119,14 +130,14 @@ static void vg_lines_free(void) static void vg_lines_drawall( float* projection ) { - SHADER_USE( vg_line_shader ); + glUseProgram( _shader_lines.id ); #ifdef VG_3D glUniformMatrix4fv #else glUniformMatrix3fv #endif - ( SHADER_UNIFORM( vg_line_shader, "uPv" ), 1, GL_FALSE, projection ); + ( glGetUniformLocation( _shader_lines.id, "uPv" ), 1, GL_FALSE, projection ); glBindVertexArray( vg_lines.vao ); glBindBuffer( GL_ARRAY_BUFFER, vg_lines.vbo ); @@ -210,6 +221,48 @@ static void vg_line_boxf( boxf box, u32 colour ) vg_line( p111, p011, colour ); } +static void vg_line_boxf_transformed( m4x3f m, boxf box, u32 colour ) +{ + v3f p000, p001, p010, p011, p100, p101, p110, p111; + + p000[0]=box[0][0];p000[1]=box[0][1];p000[2]=box[0][2]; + p001[0]=box[0][0];p001[1]=box[0][1];p001[2]=box[1][2]; + p010[0]=box[0][0];p010[1]=box[1][1];p010[2]=box[0][2]; + p011[0]=box[0][0];p011[1]=box[1][1];p011[2]=box[1][2]; + + p100[0]=box[1][0];p100[1]=box[0][1];p100[2]=box[0][2]; + p101[0]=box[1][0];p101[1]=box[0][1];p101[2]=box[1][2]; + p110[0]=box[1][0];p110[1]=box[1][1];p110[2]=box[0][2]; + p111[0]=box[1][0];p111[1]=box[1][1];p111[2]=box[1][2]; + + m4x3_mulv( m, p000, p000 ); + m4x3_mulv( m, p001, p001 ); + m4x3_mulv( m, p010, p010 ); + m4x3_mulv( m, p011, p011 ); + m4x3_mulv( m, p100, p100 ); + m4x3_mulv( m, p101, p101 ); + m4x3_mulv( m, p110, p110 ); + m4x3_mulv( m, p111, p111 ); + + vg_line( p000, p001, colour ); + vg_line( p001, p011, colour ); + vg_line( p011, p010, colour ); + vg_line( p010, p000, colour ); + + vg_line( p100, p101, colour ); + vg_line( p101, p111, colour ); + vg_line( p111, p110, colour ); + vg_line( p110, p100, colour ); + + vg_line( p100, p000, colour ); + vg_line( p101, p001, colour ); + vg_line( p110, p010, colour ); + vg_line( p111, p011, colour ); + + vg_line( p000, p110, colour ); + vg_line( p100, p010, colour ); +} + static void vg_line_pt3( v3f pt, float size, u32 colour ) { boxf box = diff --git a/src/vg/vg_m.h b/src/vg/vg_m.h index c71f3ab..8ecadbd 100644 --- a/src/vg/vg_m.h +++ b/src/vg/vg_m.h @@ -28,11 +28,21 @@ static inline float vg_randf(void) return (float)rand()/(float)(RAND_MAX); } -static inline float vg_randint(int max) +static inline int vg_randint(int max) { return rand()%max; } +static float stable_force( float current, float diff ) +{ + float fnew = current + diff; + + if( fnew * current < 0.0f ) + return 0.0f; + + return fnew; +} + #define VG_MIN( A, B ) ((A)<(B)?(A):(B)) #define VG_MAX( A, B ) ((A)>(B)?(A):(B)) @@ -177,6 +187,12 @@ static inline void v2_normalize( v2f a ) v2_muls( a, 1.f / v2_length( a ), a ); } +static inline void v2_floor( v2f a, v2f b ) +{ + b[0] = floorf( a[0] ); + b[1] = floorf( a[1] ); +} + /* * Vector 3 */ @@ -368,7 +384,15 @@ static inline void v4_zero( v4f a ) a[0] = 0.f; a[1] = 0.f; a[2] = 0.f; a[3] = 0.f; } -static inline void v4_muladds( v3f a, v3f b, float s, v3f d ) +static inline void v4_muls( v4f a, float s, v4f d ) +{ + d[0] = a[0]*s; + d[1] = a[1]*s; + d[2] = a[2]*s; + d[3] = a[3]*s; +} + +static inline void v4_muladds( v4f a, v4f b, float s, v4f d ) { d[0] = a[0]+b[0]*s; d[1] = a[1]+b[1]*s; @@ -658,6 +682,20 @@ static inline void m4x3_mulv( m4x3f m, v3f v, v3f d ) v3_copy( res, d ); } +/* + * Transform plane ( xyz, distance ) + */ +static inline void m4x3_mulp( m4x3f m, v4f p, v4f d ) +{ + v3f o; + + v3_muls( p, p[3], o ); + m4x3_mulv( m, o, o ); + m3x3_mulv( m, p, d ); + + d[3] = v3_dot( o, d ); +} + /* * Affine transforms */ @@ -676,6 +714,13 @@ static inline void m4x3_scale( m4x3f m, float s ) v3_muls( m[2], s, m[2] ); } +static inline void m4x3_scalev( m4x3f m, v3f v ) +{ + v3_muls(m[0], v[0], m[0]); + v3_muls(m[1], v[1], m[1]); + v3_muls(m[2], v[2], m[2]); +} + static inline void m4x3_rotate_x( m4x3f m, float angle ) { m4x3f t = M4X3_IDENTITY; @@ -763,6 +808,15 @@ static inline void box_copy( boxf a, boxf b ) v3_copy( a[1], b[1] ); } +static inline int box_overlap( boxf a, boxf b ) +{ + return + ( a[0][0] <= b[1][0] && a[1][0] >= b[0][0] ) && + ( a[0][1] <= b[1][1] && a[1][1] >= b[0][1] ) && + ( a[0][2] <= b[1][2] && a[1][2] >= b[0][2] ) + ; +} + static inline void box_init_inf( boxf box ) { v3_fill( box[0], INFINITY ); @@ -778,14 +832,35 @@ static inline void m4x3_transform_aabb( m4x3f m, boxf box ) v3_fill( box[0], INFINITY ); v3_fill( box[1], -INFINITY ); - m4x3_expand_aabb_point( m, box, a ); + m4x3_expand_aabb_point( m, box, (v3f){ a[0], a[1], a[2] } ); m4x3_expand_aabb_point( m, box, (v3f){ a[0], b[1], a[2] } ); - m4x3_expand_aabb_point( m, box, (v3f){ b[0], a[1], a[2] } ); m4x3_expand_aabb_point( m, box, (v3f){ b[0], b[1], a[2] } ); - m4x3_expand_aabb_point( m, box, b ); + m4x3_expand_aabb_point( m, box, (v3f){ b[0], a[1], a[2] } ); + + m4x3_expand_aabb_point( m, box, (v3f){ a[0], a[1], b[2] } ); m4x3_expand_aabb_point( m, box, (v3f){ a[0], b[1], b[2] } ); - m4x3_expand_aabb_point( m, box, (v3f){ b[0], a[1], b[2] } ); m4x3_expand_aabb_point( m, box, (v3f){ b[0], b[1], b[2] } ); + m4x3_expand_aabb_point( m, box, (v3f){ b[0], a[1], b[2] } ); +} + +int ray_aabb( boxf box, v3f co, v3f dir, float dist ) +{ + v3f v0, v1; + float tmin, tmax; + + v3_sub( box[0], co, v0 ); + v3_sub( box[1], co, v1 ); + v3_div( v0, dir, v0 ); + v3_div( v1, dir, v1 ); + + tmin = vg_minf( v0[0], v1[0] ); + tmax = vg_maxf( v0[0], v1[0] ); + tmin = vg_maxf( tmin, vg_minf( v0[1], v1[1] )); + tmax = vg_minf( tmax, vg_maxf( v0[1], v1[1] )); + tmin = vg_maxf( tmin, vg_minf( v0[2], v1[2] )); + tmax = vg_minf( tmax, vg_maxf( v0[2], v1[2] )); + + return tmax >= tmin && tmin < dist && tmax > 0; } static inline void m4x3_lookat( m4x3f m, v3f pos, v3f target, v3f up ) @@ -811,6 +886,10 @@ static inline void m4x3_lookat( m4x3f m, v3f pos, v3f target, v3f up ) { 0.0f, 1.0f, 0.0f, 0.0f },\ { 0.0f, 0.0f, 1.0f, 0.0f },\ { 0.0f, 0.0f, 0.0f, 1.0f }} +#define M4X4_ZERO {{0.0f, 0.0f, 0.0f, 0.0f },\ + { 0.0f, 0.0f, 0.0f, 0.0f },\ + { 0.0f, 0.0f, 0.0f, 0.0f },\ + { 0.0f, 0.0f, 0.0f, 0.0f }} static void m4x4_projection( m4x4f m, float angle, float ratio, float near, float far ) @@ -860,6 +939,12 @@ static inline void m4x4_identity( m4x4f a ) m4x4_copy( id, a ); } +static inline void m4x4_zero( m4x4f a ) +{ + m4x4f zero = M4X4_ZERO; + m4x4_copy( zero, a ); +} + static inline void m4x4_mul( m4x4f a, m4x4f b, m4x4f d ) { float a00 = a[0][0], a01 = a[0][1], a02 = a[0][2], a03 = a[0][3], @@ -890,6 +975,75 @@ static inline void m4x4_mul( m4x4f a, m4x4f b, m4x4f d ) d[3][3] = a03*b30 + a13*b31 + a23*b32 + a33*b33; } +static inline void m4x4_mulv( m4x4f m, v4f v, v4f d ) +{ + v4f res; + + res[0] = m[0][0]*v[0] + m[1][0]*v[1] + m[2][0]*v[2] + m[3][0]*v[3]; + res[1] = m[0][1]*v[0] + m[1][1]*v[1] + m[2][1]*v[2] + m[3][1]*v[3]; + res[2] = m[0][2]*v[0] + m[1][2]*v[1] + m[2][2]*v[2] + m[3][2]*v[3]; + res[3] = m[0][3]*v[0] + m[1][3]*v[1] + m[2][3]*v[2] + m[3][3]*v[3]; + + v4_copy( res, d ); +} + +static inline void m4x4_inv( m4x4f a, m4x4f d ) +{ + float a00 = a[0][0], a01 = a[0][1], a02 = a[0][2], a03 = a[0][3], + a10 = a[1][0], a11 = a[1][1], a12 = a[1][2], a13 = a[1][3], + a20 = a[2][0], a21 = a[2][1], a22 = a[2][2], a23 = a[2][3], + a30 = a[3][0], a31 = a[3][1], a32 = a[3][2], a33 = a[3][3], + det, + t[6]; + + t[0] = a22*a33 - a32*a23; + t[1] = a21*a33 - a31*a23; + t[2] = a21*a32 - a31*a22; + t[3] = a20*a33 - a30*a23; + t[4] = a20*a32 - a30*a22; + t[5] = a20*a31 - a30*a21; + + d[0][0] = a11*t[0] - a12*t[1] + a13*t[2]; + d[1][0] =-(a10*t[0] - a12*t[3] + a13*t[4]); + d[2][0] = a10*t[1] - a11*t[3] + a13*t[5]; + d[3][0] =-(a10*t[2] - a11*t[4] + a12*t[5]); + + d[0][1] =-(a01*t[0] - a02*t[1] + a03*t[2]); + d[1][1] = a00*t[0] - a02*t[3] + a03*t[4]; + d[2][1] =-(a00*t[1] - a01*t[3] + a03*t[5]); + d[3][1] = a00*t[2] - a01*t[4] + a02*t[5]; + + t[0] = a12*a33 - a32*a13; + t[1] = a11*a33 - a31*a13; + t[2] = a11*a32 - a31*a12; + t[3] = a10*a33 - a30*a13; + t[4] = a10*a32 - a30*a12; + t[5] = a10*a31 - a30*a11; + + d[0][2] = a01*t[0] - a02*t[1] + a03*t[2]; + d[1][2] =-(a00*t[0] - a02*t[3] + a03*t[4]); + d[2][2] = a00*t[1] - a01*t[3] + a03*t[5]; + d[3][2] =-(a00*t[2] - a01*t[4] + a02*t[5]); + + t[0] = a12*a23 - a22*a13; + t[1] = a11*a23 - a21*a13; + t[2] = a11*a22 - a21*a12; + t[3] = a10*a23 - a20*a13; + t[4] = a10*a22 - a20*a12; + t[5] = a10*a21 - a20*a11; + + d[0][3] =-(a01*t[0] - a02*t[1] + a03*t[2]); + d[1][3] = a00*t[0] - a02*t[3] + a03*t[4]; + d[2][3] =-(a00*t[1] - a01*t[3] + a03*t[5]); + d[3][3] = a00*t[2] - a01*t[4] + a02*t[5]; + + det = 1.0f / (a00*d[0][0] + a01*d[1][0] + a02*d[2][0] + a03*d[3][0]); + v4_muls( d[0], det, d[0] ); + v4_muls( d[1], det, d[1] ); + v4_muls( d[2], det, d[2] ); + v4_muls( d[3], det, d[3] ); +} + /* * Planes (double precision) */ @@ -1073,3 +1227,48 @@ static void m3x3_q( m3x3f m, v4f q ) q[3] = rinv * (m[0][1] - m[1][0]); } } + +static int ray_tri( v3f tri[3], v3f co, v3f dir, float *dist ) +{ + float const kEpsilon = 0.00001f; + + v3f v0, v1, h, s, q, n; + float a,f,u,v,t; + + float *pa = tri[0], + *pb = tri[1], + *pc = tri[2]; + + v3_sub( pb, pa, v0 ); + v3_sub( pc, pa, v1 ); + v3_cross( dir, v1, h ); + v3_cross( v0, v1, n ); + + if( v3_dot( n, dir ) > 0.0f ) /* Backface culling */ + return 0; + + /* Parralel */ + a = v3_dot( v0, h ); + if( a > -kEpsilon && a < kEpsilon ) + return 0; + + f = 1.0f/a; + v3_sub( co, pa, s ); + + u = f * v3_dot(s, h); + if( u < 0.0f || u > 1.0f ) + return 0; + + v3_cross( s, v0, q ); + v = f * v3_dot( dir, q ); + if( v < 0.0f || u+v > 1.0f ) + return 0; + + t = f * v3_dot(v1, q); + if( t > kEpsilon ) + { + *dist = t; + return 1; + } + else return 0; +} diff --git a/src/vg/vg_shader.h b/src/vg/vg_shader.h index 0f1303b..1c93734 100644 --- a/src/vg/vg_shader.h +++ b/src/vg/vg_shader.h @@ -1,65 +1,24 @@ -/* Copyright (C) 2021-2022 Harry Godden (hgn) - All Rights Reserved */ +/* TODO: TUrn off in release */ +#define STB_INCLUDE_IMPLEMENTATION +#define STB_INCLUDE_LINE_GLSL +#include "stb/stb_include.h" const char *vg_shader_gl_ver = "#version 330 core\n"; -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wreturn-type" -static inline int static_str_index( const char *list[], int len, - const char *str ) -{ - for( int i = 0; i < len; i ++ ) - { - if( !strcmp(list[i],str) ) - return i; - } - - #ifndef VG_RELEASE - fprintf( stderr, "That was not a static string index!! (%s)\n", str ); - abort(); - #endif -} -#pragma GCC diagnostic pop - -#define SHADER_NAME( NAME ) (NAME##_static_shader.program) -#define SHADER_USE( NAME ) glUseProgram( NAME##_static_shader.program ) - -#define SHADER_UNIFORM( NAME, U ) \ - NAME##_shader_uniforms[ STR_STATIC_INDEX( NAME##_shader_names, U ) ] -#define SHADER_UNIFORM_NAME( NAME, UID ) NAME##_shader_names[ UID ] -#define STR_STATIC_INDEX( LIST, STR ) \ - static_str_index( LIST, vg_list_size(LIST), STR ) - -#define UNIFORMS(...) __VA_ARGS__ - -#define SHADER_DEFINE( NAME, VERT, FRAG, UNIFORMS ) \ - const char * NAME##_shader_names[] = UNIFORMS; \ - GLint NAME##_shader_uniforms[ vg_list_size( NAME##_shader_names ) ]; \ - struct vg_shader NAME##_static_shader = { \ - .src_vert = VERT, .src_frag = FRAG, \ - .sym = #NAME "_static.shader", \ - .uniform_names = NAME##_shader_names, \ - .uniforms = NAME##_shader_uniforms, \ - .uniform_count = vg_list_size( NAME##_shader_names ), \ - }; - -#define SHADER_INIT( NAME ) arrpush( vg_shaders_active, &NAME##_static_shader ) - -#define SHADER_STATUS_NONE 0x00 -#define SHADER_STATUS_COMPILED 0x1 - struct vg_shader { - GLuint program; + GLuint id; + const char *name; - const char *src_vert; - const char *src_frag; - const char *src_geo; - const char *sym; - - const char **uniform_names; - GLint *uniforms; - u32 uniform_count; - u32 status; + struct vg_subshader + { + const char *orig_file, + *static_src; + } + vs, fs; + + void (*link)(void); + int compiled; } ** vg_shaders_active = NULL; @@ -73,7 +32,7 @@ static GLuint vg_shader_subshader( const char *src, GLint gliShaderType ) return 0; } - glShaderSource( shader, 2, (const char *[2]){ vg_shader_gl_ver, src }, NULL ); + glShaderSource( shader, 2, (const char*[2]){ vg_shader_gl_ver, src }, NULL ); glCompileShader( shader ); GLint status; @@ -94,60 +53,94 @@ static GLuint vg_shader_subshader( const char *src, GLint gliShaderType ) static int vg_shader_compile( struct vg_shader *shader ) { - vg_info( "Compile shader '%s'\n", shader->sym ); + vg_info( "Compile shader '%s'\n", shader->name ); - GLuint vert, frag, geo = 0; + GLuint program, vert, frag; + const char *svs, *sfs; + char *avs, *afs; + + int static_src = 1; + + /* If we are compiling this again, we obviously need to try to take the src + * from the disk instead. + * + * Only do this if we have filenames set on the shader, so engine shaders + * dont have to do it (text.. etc). + */ + if( shader->compiled ) + { + if( shader->vs.orig_file && shader->fs.orig_file ) + static_src = 0; + else return 1; + } + + if( static_src ) + { + svs = shader->vs.static_src; + sfs = shader->fs.static_src; + } + else + { + char error[260]; + char path[260]; + strcpy( path, shader->vs.orig_file ); + avs = stb_include_file( path, "", "../shaders", error ); + + strcpy( path, shader->fs.orig_file ); + afs = stb_include_file( path, "", "../shaders", error ); + + if( !avs || !afs ) + { + free( avs ); + free( afs ); + return 0; + } + + svs = avs; + sfs = afs; + } - vert = vg_shader_subshader( shader->src_vert, GL_VERTEX_SHADER ); - frag = vg_shader_subshader( shader->src_frag, GL_FRAGMENT_SHADER ); + vert = vg_shader_subshader( svs, GL_VERTEX_SHADER ); + frag = vg_shader_subshader( sfs, GL_FRAGMENT_SHADER ); + if( !static_src ) + { + free( avs ); + free( afs ); + } + if( !vert || !frag ) return 0; - if( shader->src_geo ) - { - geo = vg_shader_subshader( shader->src_geo, GL_GEOMETRY_SHADER ); - - if( !geo ) - return 0; - } - - shader->program = glCreateProgram(); - if( geo ) - glAttachShader( shader->program, geo ); + program = glCreateProgram(); - glAttachShader( shader->program, vert ); - glAttachShader( shader->program, frag ); - glLinkProgram( shader->program ); + glAttachShader( program, vert ); + glAttachShader( program, frag ); + glLinkProgram( program ); glDeleteShader( vert ); glDeleteShader( frag ); - - if( geo ) - glDeleteShader( geo ); /* Check for link errors */ char infoLog[ 512 ]; int success_link = 1; - glGetProgramiv( shader->program, GL_LINK_STATUS, &success_link ); + glGetProgramiv( program, GL_LINK_STATUS, &success_link ); if( !success_link ) { - glGetProgramInfoLog( shader->program, 512, NULL, infoLog ); + glGetProgramInfoLog( program, 512, NULL, infoLog ); vg_error( "Link failed: %s\n", infoLog ); - glDeleteProgram( shader->program ); - + glDeleteProgram( program ); return 0; } - /* Complete linkeage */ - for( int i = 0; i < shader->uniform_count; i ++ ) - { - shader->uniforms[ i ] = - glGetUniformLocation( shader->program, shader->uniform_names[i] ); - } - - shader->status |= SHADER_STATUS_COMPILED; + if( shader->compiled ) + glDeleteProgram( shader->id ); + + shader->id = program; + shader->compiled = 1; + if( shader->link ) + shader->link(); return 1; } @@ -157,27 +150,28 @@ static void vg_shaders_free(void) { struct vg_shader *shader = vg_shaders_active[i]; - if( shader->status & SHADER_STATUS_COMPILED ) - glDeleteProgram( shader->program ); + if( shader->compiled ) + glDeleteProgram( shader->id ); } arrfree( vg_shaders_active ); } -static int vg_shaders_compile(void) +static int vg_shaders_recompile(int argc, const char *argv[]) { vg_info( "Compiling shaders\n" ); - for( int i = 0; i < arrlen( vg_shaders_active ); i ++ ) { struct vg_shader *shader = vg_shaders_active[i]; - if( !vg_shader_compile( shader ) ) - { - vg_shaders_free(); - return 0; - } + vg_shader_compile( shader ); } - - vg_register_exit( &vg_shaders_free, "vg_shaders_free" ); - return 1; + + return 0; +} + +static void vg_shader_register( struct vg_shader *shader ) +{ + shader->compiled = 0; + shader->id = 0; /* TODO: make this an error shader */ + arrpush( vg_shaders_active, shader ); } diff --git a/src/vg/vg_shader2.h b/src/vg/vg_shader2.h new file mode 100644 index 0000000..7201dac --- /dev/null +++ b/src/vg/vg_shader2.h @@ -0,0 +1,13 @@ +struct vg_subshader +{ + const char *static_src, + *orig_file; + + void (*uniform_register)(void); +}; + +struct vg_shader +{ + struct vg_subshader vs, fs; +}; + diff --git a/src/vg/vg_ui.h b/src/vg/vg_ui.h index f36d363..5b97133 100644 --- a/src/vg/vg_ui.h +++ b/src/vg/vg_ui.h @@ -3,8 +3,14 @@ #ifndef VG_UI_H #define VG_UI_H -SHADER_DEFINE( shader_ui, - +static struct vg_shader _shader_ui = +{ + .name = "[vg] ui", + .link = NULL, + .vs = + { + .orig_file = NULL, + .static_src = "layout (location=0) in vec2 a_co;" "layout (location=1) in vec2 a_uv;" "layout (location=2) in vec4 a_colour;" @@ -25,8 +31,11 @@ SHADER_DEFINE( shader_ui, "aWsp = a_co;" "aClip = a_clip;" "}", - - /* Fragment */ + }, + .fs = + { + .orig_file = NULL, + .static_src = "uniform sampler2D uTexGlyphs;" "out vec4 FragColor;" "" @@ -57,9 +66,8 @@ SHADER_DEFINE( shader_ui, "FragColor = vec4( aColour.rgb, glyph.a*clip_blend );" "}" - , - UNIFORMS({ "uPv", "uTexGlyphs" }) -) + } +}; typedef i16 ui_px; typedef u32 ui_colour; @@ -260,7 +268,7 @@ static void ui_default_init(void) free( image ); - SHADER_INIT( shader_ui ); + vg_shader_register( &_shader_ui ); ui_init_context( &ui_global_ctx, 20000 ); } @@ -298,7 +306,7 @@ static void ui_draw( ui_ctx *ctx, m3x3f view_override ) glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glBlendEquation(GL_FUNC_ADD); - SHADER_USE( shader_ui ); + glUseProgram( _shader_ui.id ); m3x3f view = M3X3_IDENTITY; @@ -311,12 +319,13 @@ static void ui_draw( ui_ctx *ctx, m3x3f view_override ) -1.0f/((float)vg_window_y*0.5f), 1.0f } ); } - glUniformMatrix3fv( SHADER_UNIFORM( shader_ui, "uPv" ), 1, + /* TODO? */ + glUniformMatrix3fv( glGetUniformLocation( _shader_ui.id, "uPv" ), 1, GL_FALSE, (float *)view_override ); glActiveTexture( GL_TEXTURE0 ); glBindTexture( GL_TEXTURE_2D, ui_glyph_texture ); - glUniform1i( SHADER_UNIFORM( shader_ui, "uTexGlyphs" ), 0 ); + glUniform1i( glGetUniformLocation( _shader_ui.id, "uTexGlyphs" ), 0 ); glDrawElements( GL_TRIANGLES, num_indices_normal, GL_UNSIGNED_SHORT, (void*)(0) ); @@ -826,6 +835,94 @@ static void ui_push_image( ui_ctx *ctx, ui_rect rc, GLuint image ) img->image = image; } +struct ui_slider +{ + float *data; + float min, max; +}; + +struct ui_slider_vector +{ + float *data, min, max; + struct ui_slider sub[4]; + u32 len; +}; + +struct ui_checkbox +{ + int *data; +}; + +static void ui_slider( ui_ctx *ctx, struct ui_slider *slider ) +{ + ui_new_node( ctx ); + + ui_px slider_start = ctx->cursor[0]; + + float const ftotal = ctx->cursor[2], + fwidth = ftotal*0.25f, + fmove = ftotal - fwidth, + fstart = fwidth*0.5f, + frange = slider->max-slider->min, + fpos = (*slider->data - slider->min) / frange; + + ui_fill_rect( ctx, ctx->cursor, 0xff111111 ); + ctx->cursor[2] = fwidth; + ctx->cursor[0] = slider_start + fpos * fmove; + + /* TODO.. */ + u32 uid = (u32)(u64)slider->data; + int status = ui_button( ctx, uid ); + + if( ctx->capture_lock && + (ctx->capture_mouse_id == ui_group_id( ctx, uid ))) + { + float ui_new = ctx->mouse[0], + local = ui_new - (slider_start + fstart), + zo = vg_clampf(local / fmove,0.0f,1.0f); + + *slider->data = vg_lerpf( slider->min, slider->max, zo ); + } + + ctx->cursor[0] += 4; + ctx->cursor[1] += 4; + + char buf[12]; + snprintf( buf, 12, "%.2f", *slider->data ); + ui_text( ctx, ctx->cursor, buf, 1, 0 ); + ui_end_down( ctx ); + + ui_end_down( ctx ); +} + +static void ui_slider_vector( ui_ctx *ctx, struct ui_slider_vector *slider ) +{ + for( int i=0; ilen; i++ ) + { + slider->sub[i].data = &slider->data[i]; + slider->sub[i].min = slider->min; + slider->sub[i].max = slider->max; + ui_slider( ctx, &slider->sub[i] ); + } +} + +static void ui_checkbox( ui_ctx *ctx, struct ui_checkbox *cb ) +{ + u32 uid = (u32)(u64)cb->data; + if( ui_button(ctx,uid) == k_button_click ) + *cb->data ^= 0x1; + + ui_new_node(ctx); + ui_rect_pad( ctx->cursor, 4 ); + if( *cb->data ) + ui_fill_rect( ctx, ctx->cursor, 0xff00e052 ); + else + ui_fill_rect( ctx, ctx->cursor, 0xff0052e0 ); + + ui_end(ctx); + ui_end_down(ctx); +} + /* Shortnames */ #define gui_draw(...) ui_draw( &ui_global_ctx, __VA_ARGS__) #define gui_current(...) ui_current( &ui_global_ctx, __VA_ARGS__) diff --git a/vg_compiler.sh b/vg_compiler.sh index 9a60b3d..33d8057 100755 --- a/vg_compiler.sh +++ b/vg_compiler.sh @@ -6,6 +6,7 @@ vg_root=`dirname $vg_root` vg_version="0.2" opt_assets=false +opt_shaders=false opt_release=false opt_play=false opt_linux=false @@ -17,6 +18,7 @@ opt_steam="" target_platform_include="" target_standard="-std=c99" target_link_steam=false +target_shaders="" # Util # =========================================== @@ -73,7 +75,7 @@ target_os_windows(){ target_os_linux(){ target_ext="" - target_compiler="clang" + target_compiler="gcc" target_libs="-lGL -lglfw3 -lX11 -lXxf86vm -lXrandr -lm -pthread -lXi -ldl" target_libs_steam="-lsteam_api" #target_platform_include="-include $vg_root/platformutils/force_link_glibc_2.23.h" @@ -163,17 +165,6 @@ compile_main(){ if [ "$opt_steam" != "" ]; then cp $vg_root/dep/steam/$target_steam_api $target_dir/$target_steam_api fi - - # Clear and copy assets - rm -r $target_dir/textures - rm -r $target_dir/sound - rm -r $target_dir/maps - - cp -r .temp_textures $target_dir - mv $target_dir/.temp_textures $target_dir/textures - cp -r sound $target_dir - cp -r maps $target_dir - cp -r models $target_dir } compile_tools(){ @@ -188,10 +179,10 @@ compile_tools(){ compile_x $vg_root/src/fontcomp.c $vg_root/bin/fontcomp compile_x $vg_root/src/texsheet.c $vg_root/bin/texsheet compile_x $vg_root/src/qoiconv.c $vg_root/bin/qoiconv + compile_x $vg_root/src/shader.c $vg_root/bin/shader opt_steam=$steam_prev } - compile_assets(){ titleit "Assets" [[ -d .temp_textures ]] && rm -r .temp_textures @@ -205,7 +196,6 @@ compile_assets(){ done if [[ -d "textures_combine" ]]; then - # Autocombine textures echo " [combine]:" auto_combine="" @@ -214,7 +204,7 @@ compile_assets(){ do logit " combine: $f"; auto_combine="$auto_combine $f" done - $vg_root/bin/texsheet$taget_ext ../.temp_textures/autocombine.qoi ../sprites_autocombine.h sprites_auto_combine $auto_combine + $vg_root/bin/texsheet$target_ext ../.temp_textures/autocombine.qoi ../sprites_autocombine.h sprites_auto_combine $auto_combine cd .. fi @@ -222,12 +212,37 @@ compile_assets(){ echo "" echo "Compile fonts:" $vg_root/bin/fontcomp$target_ext $vg_root/src/fonts/vg_font.png $vg_root/src/vg/vg_pxfont.h + + # Clear and copy assets + rm -r $target_dir/textures + rm -r $target_dir/sound + rm -r $target_dir/maps + + cp -r .temp_textures $target_dir + mv $target_dir/.temp_textures $target_dir/textures + cp -r sound $target_dir + cp -r maps $target_dir + cp -r models $target_dir +} + +compile_shaders(){ + titleit "Shaders" + + if [[ -d "shaders" ]]; then + cd shaders + $vg_root/bin/shader$target_ext $target_shaders + cd .. + fi +} + +shader(){ + target_shaders="$target_shaders $1 $2 $3" } # ============================================================== # Compile process -options=rptlwa +options=rptlwas longopts=release,build-linux,build-windows,steam,play,build-tools,assets,full,miniaudio,template parsed=$(getopt --options=$options --longoptions=$longopts --name "vgc" -- "$@") @@ -239,8 +254,13 @@ fi eval set -- "$parsed" while true; do case "$1" in + -s|--shaders) + opt_shaders=true + shift; + ;; -a|--assets) opt_assets=true + opt_shaders=true shift; ;; -r|--release) @@ -326,6 +346,7 @@ detect_os titleit " vgc ver: $vg_version\n host: $host_os" logit " assets: $opt_assets" +logit " shaders: $opt_shaders" logit " release: $opt_release" logit " play: $opt_play" logit " build-linux: $opt_linux" @@ -338,6 +359,7 @@ logit " miniaudio: $opt_recompile_mini_audio" if [ $opt_tools = true ]; then detect_os; compile_tools; fi if [ $opt_assets = true ]; then compile_assets; fi +if [ $opt_shaders = true ]; then compile_shaders; fi if [ $opt_linux = true ]; then target_os_linux; compile_main; fi if [ $opt_windows = true ]; then target_os_windows -- 2.25.1