/*
- .-. VG Event loop
+ .-. VG Event loop
| 0 |
-| | .-----------.
-|API| | vg_enter |
-| | '-----------'
+| | .---------------------------------------------------------.
+|API| | vg_enter( int argc, char *argv[], const char *window_name |
+| | '---------------------------------------------------------'
| | |
| | v
|IMP| vg_launch_opt(void) <--.
|IMP| | vg_ui(void)
| | | |
| | '----'
+'___'
+
+ .-.
+| ? |
+| | .-------------------------------------.
+|API| | vg_fatal_exit_loop( const char *err ) |
+| | '-------------------------------------'
+| | |
+| | .------+.
+| | | |
+| | | v
+|IMP| '- vg_framebuffer_resize(void)
'___'
*/
};
VG_STATIC void vg_fatal_exit_loop( const char *error );
-VG_STATIC void vg_required( void *ptr, const char *path )
-{
- if( !ptr )
- {
- vg_fatal_exit_loop( path );
- }
-}
VG_STATIC void vg_ensure_engine_running(void)
{
}
}
-VG_STATIC void vg_process_launch_opts_internal(void)
+VG_STATIC void vg_process_launch_opts_internal( int argc, char *argv[] )
{
char *arg;
while( vg_argp( argc, argv ) )
}
}
-VG_STATIC void vg_init_window(void)
+VG_STATIC void vg_init_window( const char *window_name )
{
if( SDL_Init(SDL_INIT_VIDEO|SDL_INIT_AUDIO|SDL_INIT_GAMECONTROLLER) != 0 )
{
VG_STATIC void vg_enter( int argc, char *argv[], const char *window_name )
{
- vg_process_launch_opts_internal();
+ vg_process_launch_opts_internal( argc, argv );
/* Systems init */
vg_alloc_quota();
vg_log_init();
vg_console_init();
- vg_init_window();
+ vg_init_window( window_name );
SDL_SetRelativeMouseMode(1);
vg.thread_id_main = SDL_GetThreadID(NULL);
--- /dev/null
+#include "vg.h"
+
+#ifdef VG_GAME
+ #error !
+#endif
+
+#define STB_INCLUDE_IMPLEMENTATION
+#define STB_INCLUDE_LINE_GLSL
+#include "submodules/stb/stb_include.h"
+
+struct
+{
+ struct uniform
+ {
+ char name[32];
+ char type[20];
+ char uniform_code_id[128];
+
+ int array;
+ }
+ uniform_buffer[100];
+
+ int uniform_count,
+ uniform_uid;
+ char shader_dir[ 256 ];
+ char current_shader_name[ 128 ];
+}
+static vg_shaderbuild;
+
+static void vg_shader_set_include_dir( char *dir )
+{
+ strcpy( vg_shaderbuild.shader_dir, dir );
+}
+
+static void parse_uniform_name( char *start, struct uniform *uf )
+{
+ uf->array = 0;
+ 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->name, start, sizeof(uf->name) );
+ uf->array = 1;
+ }
+
+ if( start[i] == ' ' )
+ {
+ start[i] = '\0';
+ strncpy( uf->type, start, sizeof(uf->type) );
+ start = start+i+1;
+ i=0;
+ }
+ }
+
+ snprintf( uf->uniform_code_id, 64, "_uniform_%s_%s",
+ vg_shaderbuild.current_shader_name,
+ uf->name );
+}
+
+static int compile_subshader( FILE *header, char *name )
+{
+ char error[256];
+ char *full = stb_include_file( name, "", vg_shaderbuild.shader_dir, error );
+
+ if( !full )
+ {
+ fprintf( stderr, "stb_include_file error:\n%s\n", error );
+ return 0;
+ }
+ else
+ {
+ fprintf( header, "{\n"
+ ".static_src = \n" );
+
+ 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 =
+ &vg_shaderbuild.uniform_buffer[
+ vg_shaderbuild.uniform_count ++ ];
+
+ parse_uniform_name( start, uf );
+ }
+
+ if( c == '\0' )
+ {
+ fputs( "\"", header );
+ break;
+ }
+
+ fputs( "\\n\"\n", header );
+ start = cur+1;
+ }
+ cur ++;
+ }
+
+ fputs( "},", header );
+ }
+
+ free( full );
+ return 1;
+}
+
+int vg_build_shader( char *src_vert, /* path/to/vert.vs */
+ char *src_frag, /* path/to/frag.fs */
+ char *src_geo, /* unused currently */
+ char *dst_h, /* folder where .h go */
+ char *name /* shader name */ )
+{
+ char path[260];
+
+ strcpy( vg_shaderbuild.current_shader_name, name );
+
+ strcpy( path, dst_h );
+ strcat( path, "/" );
+ strcat( path, name );
+ strcat( path, ".h" );
+
+ printf( "Compiling shader called '%s'\n", name );
+
+ FILE *header = fopen( path, "w" );
+ if( !header )
+ {
+ fprintf(stderr, "Could not open '%s'\n", path );
+ return 0;
+ }
+
+ fprintf( header, "#ifndef SHADER_%s_H\n"
+ "#define SHADER_%s_H\n", name, name );
+ fprintf( header, "static void shader_%s_link(void);\n", name );
+ fprintf( header, "static void shader_%s_register(void);\n", name );
+ fprintf( header, "static struct vg_shader _shader_%s = {\n"
+ " .name = \"%s\",\n"
+ " .link = shader_%s_link,\n"
+ " .vs = \n", name, name, name );
+
+ vg_shaderbuild.uniform_count = 0;
+ if( !compile_subshader(header,src_vert) )
+ {
+ fclose( header );
+ return 0;
+ }
+
+ fprintf( header, "\n .fs = \n" );
+ if( !compile_subshader(header,src_frag) )
+ {
+ fclose( header );
+ return 0;
+ }
+
+ fprintf( header, "\n};\n\n" );
+
+ for( int i=0; i<vg_shaderbuild.uniform_count; i++ )
+ {
+ struct uniform *uf = &vg_shaderbuild.uniform_buffer[i];
+ fprintf( header, "static GLuint %s;\n", uf->uniform_code_id );
+ }
+
+ struct type_info
+ {
+ const char *glsl_type,
+ *args,
+ *gl_call_pattern;
+ }
+ types[] =
+ {
+ { "float", "float f", "glUniform1f(%s,f);" },
+
+ { "vec2", "v2f v", "glUniform2fv(%s,1,v);" },
+ { "vec3", "v3f v", "glUniform3fv(%s,1,v);" },
+ { "vec4", "v4f v", "glUniform4fv(%s,1,v);" },
+
+ { "sampler2D", "int i", "glUniform1i(%s,i);" },
+ { "mat4x3", "m4x3f m", "glUniformMatrix4x3fv(%s,1,GL_FALSE,(float*)m);" },
+ { "mat3", "m3x3f m", "glUniformMatrix3fv(%s,1,GL_FALSE,(float*)m);" },
+ { "mat4", "m4x4f m", "glUniformMatrix4fv(%s,1,GL_FALSE,(float*)m);" },
+ };
+
+ for( int i=0; i<vg_shaderbuild.uniform_count; i++ )
+ {
+ struct uniform *uf = &vg_shaderbuild.uniform_buffer[i];
+ if( uf->array ) continue;
+
+ for( int j=0; j<vg_list_size(types); j ++ )
+ {
+ struct type_info *inf = &types[j];
+
+ if( !strcmp( inf->glsl_type, uf->type ) )
+ {
+ fprintf( header, "static void shader_%s_%s(%s){\n",
+ name, uf->name, inf->args );
+ fprintf( header, " " );
+ fprintf( header, inf->gl_call_pattern, uf->uniform_code_id );
+ fprintf( header, "\n}\n" );
+ }
+ }
+ }
+
+ fprintf( header,
+ "static void shader_%s_register(void){\n"
+ " vg_shader_register( &_shader_%s );\n"
+ "}\n",
+ name,name );
+
+ fprintf( header,
+ "static void shader_%s_use(void){ glUseProgram(_shader_%s.id); }\n",
+ name, name );
+
+ fprintf( header,
+ "static void shader_%s_link(void){\n",
+ name );
+
+ for( int i=0; i<vg_shaderbuild.uniform_count; i++ )
+ {
+ struct uniform *uf = &vg_shaderbuild.uniform_buffer[i];
+ fprintf( header,
+ " _uniform_%s_%s = "
+ "glGetUniformLocation( _shader_%s.id, \"%s\" );\n",
+ name, uf->name,
+ name, uf->name );
+ }
+
+ fprintf( header, "}\n" );
+ fprintf( header, "#endif /* SHADER_%s_H */\n", name );
+ fclose( header );
+
+ return 1;
+}