X-Git-Url: https://harrygodden.com/git/?a=blobdiff_plain;f=vg_build_utils_shader.h;fp=vg_build_utils_shader.h;h=77ce897e4f32297706aa692b2b9ff670b10742c5;hb=76f30a0f4aef82c10b4affbeab3f0271936ce7ca;hp=0000000000000000000000000000000000000000;hpb=4c48fe01a5d1983be89b7dce6f08e6b708cfbb05;p=vg.git diff --git a/vg_build_utils_shader.h b/vg_build_utils_shader.h new file mode 100644 index 0000000..77ce897 --- /dev/null +++ b/vg_build_utils_shader.h @@ -0,0 +1,248 @@ +#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; iuniform_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; iarray ) continue; + + for( int j=0; jglsl_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; iname, + name, uf->name ); + } + + fprintf( header, "}\n" ); + fprintf( header, "#endif /* SHADER_%s_H */\n", name ); + fclose( header ); + + return 1; +}