bad char
[vg.git] / vg_build_utils_shader.h
index 77ce897e4f32297706aa692b2b9ff670b10742c5..1e1c8b1c399f76ae31f3f1c91424773beae54003 100644 (file)
@@ -1,9 +1,3 @@
-#include "vg.h"
-
-#ifdef VG_GAME
-  #error !
-#endif
-
 #define STB_INCLUDE_IMPLEMENTATION
 #define STB_INCLUDE_LINE_GLSL
 #include "submodules/stb/stb_include.h"
@@ -24,6 +18,12 @@ struct
          uniform_uid;
    char  shader_dir[ 256 ];
    char  current_shader_name[ 128 ];
+
+   vg_str code_register,
+          code_link,
+          code_function_body;
+
+   bool init;
 }
 static vg_shaderbuild;
 
@@ -35,6 +35,8 @@ static void vg_shader_set_include_dir( char *dir )
 static void parse_uniform_name( char *start, struct uniform *uf )
 {
    uf->array = 0;
+   int type_set = 0;
+
    for( int i=0;; i++ )
    {
       if( start[i] == '\0' )
@@ -43,20 +45,28 @@ static void parse_uniform_name( char *start, struct uniform *uf )
       if( start[i] == ';' )
       {
          start[i] = '\0';
-         strncpy( uf->name, start, sizeof(uf->name) );
+         vg_strncpy( start, uf->name, sizeof(uf->name), 
+                     k_strncpy_always_add_null );
       }
 
       if( start[i] == '[' )
       {
          start[i] = '\0';
-         strncpy( uf->name, start, sizeof(uf->name) );
+         vg_strncpy( start, uf->name, sizeof(uf->name),
+                     k_strncpy_always_add_null );
          uf->array = 1;
       }
       
       if( start[i] == ' ' )
       {
          start[i] = '\0';
-         strncpy( uf->type, start, sizeof(uf->type) );
+
+         if( !type_set )
+         {
+            vg_strncpy( start, uf->type, sizeof(uf->type),
+                        k_strncpy_always_add_null );
+            type_set = 1;
+         }
          start = start+i+1;
          i=0;
       }
@@ -67,7 +77,7 @@ static void parse_uniform_name( char *start, struct uniform *uf )
              uf->name );
 }
 
-static int compile_subshader( FILE *header, char *name )
+static int compile_subshader( vg_str *str, char *name )
 {
    char error[256];
    char *full = stb_include_file( name, "", vg_shaderbuild.shader_dir, error );
@@ -79,8 +89,10 @@ static int compile_subshader( FILE *header, char *name )
    }
    else
    {
-      fprintf( header, "{\n"
-                       ".static_src = \n" );
+      vg_strcatf( str, "{\n"
+                       ".orig_file = \"%s\",\n" 
+                       ".static_src = \n",
+                       name );
 
       char *cur = full, *start = full;
       while( 1 )
@@ -89,8 +101,8 @@ static int compile_subshader( FILE *header, char *name )
          if( c == '\n' || c == '\0' )
          {
             *cur = '\0';
-            fputs( "\"", header );
-            fputs( start, header );
+            vg_strcatf( str, "\"" );
+            vg_strcatf( str, start );
 
             if( !strncmp(start,"uniform",7) )
             {
@@ -104,76 +116,104 @@ static int compile_subshader( FILE *header, char *name )
 
             if( c == '\0' )
             {
-               fputs( "\"", header );
+               vg_strcatf( str, "\"" );
                break;
             }
 
-            fputs( "\\n\"\n", header );
+            vg_strcatf( str, "\\n\"\n" );
             start = cur+1;
          }
          cur ++;
       }
 
-      fputs( "},", header );
+      vg_strcatf( str, "}," );
    }
 
    free( full );
    return 1;
 }
 
+void vg_build_shader_impl( char *path )
+{
+   FILE *fp = fopen( path, "w" );
+   fputs( vg_shaderbuild.code_function_body.buffer, fp );
+   fputs( "\n\n", fp );
+
+   fputs( "void vg_auto_shader_link(void)\n{\n", fp );
+   fputs( vg_shaderbuild.code_link.buffer, fp );
+   fputs( "}\n\n", fp );
+
+   fputs( "void vg_auto_shader_register(void)\n{\n", fp );
+   fputs( vg_shaderbuild.code_register.buffer, fp );
+   fputs( "}\n\n", fp );
+
+   fclose( fp );
+}
+
 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];
+   if( !vg_shaderbuild.init )
+   {
+      vg_strnull( &vg_shaderbuild.code_link, NULL, -1 );
+      vg_strnull( &vg_shaderbuild.code_register, NULL, -1 );
+      vg_strnull( &vg_shaderbuild.code_function_body, NULL, -1 );
+      vg_shaderbuild.init = 1;
+   }
+
+   vg_str *c_link = &vg_shaderbuild.code_link,
+          *c_reg  = &vg_shaderbuild.code_register,
+          *c_body = &vg_shaderbuild.code_function_body;
+
+   char path_header[260];
    
    strcpy( vg_shaderbuild.current_shader_name, name );
+   strcpy( path_header, dst_h );
+   strcat( path_header, "/" );
+   strcat( path_header, name );
+   strcat( path_header, ".h" );
 
-   strcpy( path, dst_h );
-   strcat( path, "/" );
-   strcat( path, name );
-   strcat( path, ".h" );
+   vg_low( "Compiling shader called '%s'\r", name );
 
-   printf( "Compiling shader called '%s'\n", name );
-
-   FILE *header = fopen( path, "w" );
+   FILE *header = fopen( path_header, "w" );
    if( !header )
    {
-      fprintf(stderr, "Could not open '%s'\n", path );
+      fprintf(stderr, "Could not open '%s'\n", path_header );
       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 );
+   fprintf( header, "#pragma once\n" );
+   fprintf( header, "#include \"vg/vg_engine.h\"\n" );
+   vg_strcatf( c_body, "#include \"%s\"\n", path_header );
+   fprintf( header, "extern struct vg_shader _shader_%s;\n", name );
+   vg_strcatf( c_body, "struct vg_shader _shader_%s = {\n"
+                       "   .name = \"%s\",\n"
+                       "   .vs = \n", name, name, name );
 
    vg_shaderbuild.uniform_count = 0;
-   if( !compile_subshader(header,src_vert) )
+   if( !compile_subshader( c_body, src_vert ) )
    {
       fclose( header );
       return 0;
    }
 
-   fprintf( header, "\n   .fs = \n" );
-   if( !compile_subshader(header,src_frag) )
+   vg_strcatf( c_body, "\n   .fs = \n" );
+   if( !compile_subshader( c_body, src_frag ) )
    {
       fclose( header );
       return 0;
    }
 
-   fprintf( header, "\n};\n\n" );
+   vg_strcatf( c_body, "\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 );
+      fprintf( header, "extern GLuint %s;\n", uf->uniform_code_id );
+      vg_strcatf( c_body, "GLuint %s;\n", uf->uniform_code_id );
    }
 
    struct type_info
@@ -184,22 +224,25 @@ int vg_build_shader( char *src_vert, /* path/to/vert.vs    */
    }
    types[] =
    {
-      { "float", "float f", "glUniform1f(%s,f);" },
-
+      { "float", "f32 f", "glUniform1f(%s,f);" },
+      { "bool", "int b", "glUniform1i(%s,b);" },
+      { "int",  "int b", "glUniform1i(%s,b);" },
       { "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);" },
+      { "samplerCube", "int i", "glUniform1i(%s,i);" },
+      { "mat2", "m2x2f m", "glUniformMatrix2fv(%s,1,GL_FALSE,(f32*)m);" },
+      { "mat4x3", "m4x3f m", "glUniformMatrix4x3fv(%s,1,GL_FALSE,(f32*)m);" },
+      { "mat3", "m3x3f m", "glUniformMatrix3fv(%s,1,GL_FALSE,(f32*)m);" },
+      { "mat4", "m4x4f m", "glUniformMatrix4fv(%s,1,GL_FALSE,(f32*)m);" },
    };
 
    for( int i=0; i<vg_shaderbuild.uniform_count; i++ )
    {
       struct uniform *uf = &vg_shaderbuild.uniform_buffer[i];
-      if( uf->array ) continue;
+      if( uf->array ) 
+         continue;
 
       for( int j=0; j<vg_list_size(types); j ++ )
       {
@@ -207,8 +250,8 @@ int vg_build_shader( char *src_vert, /* path/to/vert.vs    */
 
          if( !strcmp( inf->glsl_type, uf->type ) )
          {
-            fprintf( header, "static void shader_%s_%s(%s){\n", 
-                              name, uf->name, inf->args );
+            fprintf( header, "static inline void shader_%s_%s(%s)\n{\n", 
+                     name, uf->name, inf->args );
             fprintf( header, "   " );
             fprintf( header, inf->gl_call_pattern, uf->uniform_code_id );
             fprintf( header, "\n}\n" );
@@ -216,33 +259,21 @@ int vg_build_shader( char *src_vert, /* path/to/vert.vs    */
       }
    }
 
-   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 );
+   vg_strcatf( c_reg, "   vg_shader_register( &_shader_%s );\n", name );
+   fprintf( header,    "static inline void shader_%s_use(void);\n", name );
+   fprintf( header, "static inline void shader_%s_use(void)\n{\n", name );
+   fprintf( header, "   glUseProgram(_shader_%s.id);\n}\n", name );
 
    for( int i=0; i<vg_shaderbuild.uniform_count; i++ )
    {
       struct uniform *uf = &vg_shaderbuild.uniform_buffer[i];
-      fprintf( header
+      vg_strcatf( c_link
          "   _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;
 }