its ot'
authorhgn <hgodden00@gmail.com>
Tue, 19 Jul 2022 13:51:45 +0000 (14:51 +0100)
committerhgn <hgodden00@gmail.com>
Tue, 19 Jul 2022 13:51:45 +0000 (14:51 +0100)
dep/stb/stb_include.h [new file with mode: 0644]
src/shader.c [new file with mode: 0644]
src/vg/vg.h
src/vg/vg_audio.h
src/vg/vg_input.h
src/vg/vg_lines.h
src/vg/vg_m.h
src/vg/vg_shader.h
src/vg/vg_shader2.h [new file with mode: 0644]
src/vg/vg_ui.h
vg_compiler.sh

diff --git a/dep/stb/stb_include.h b/dep/stb/stb_include.h
new file mode 100644 (file)
index 0000000..c5db201
--- /dev/null
@@ -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 <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+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 (file)
index 0000000..2f7c167
--- /dev/null
@@ -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; i<shader_count; i++ )
+   {
+      char **args = &argv[1+i*3];
+      strcpy( path, args[0] );
+      strcat( path, ".h" );
+
+      printf( "Compiling shader called '%s'\n", args[0] );
+
+      FILE *header = fopen( path, "w" );
+      if( !header )
+      {
+         fprintf(stderr, "Could not open '%s'\n", path );
+         continue;
+      }
+      
+      fprintf( header, "#ifndef SHADER_%s_H\n"
+                       "#define SHADER_%s_H\n", args[0], args[0] );
+      fprintf( header, "static void shader_%s_link(void);\n", args[0] );
+      fprintf( header, "static void shader_%s_register(void);\n", args[0] );
+      fprintf( header, "static struct vg_shader _shader_%s = {\n"
+                       "   .name = \"%s\",\n"
+                       "   .link = shader_%s_link,\n"
+                       "   .vs = \n", args[0], args[0], args[0] );
+
+      uniform_count = 0;
+      if( !compile_subshader(header,args[1]) )
+      {
+         fclose( header );
+         continue;
+      }
+
+      fprintf( header, "\n   .fs = \n" );
+      if( !compile_subshader(header,args[2]) )
+      {
+         fclose( header );
+         continue;
+      }
+
+      fprintf( header, "\n};\n\n" );
+      
+      for( int i=0; i<uniform_count; i++ )
+      {
+         struct uniform *uf = &uniform_buffer[i];
+         fprintf( header, "static GLuint _uniform_%s_%s;\n", args[0], uf->name);
+      }
+
+      for( int i=0; i<uniform_count; i++ )
+      {
+         struct uniform *uf = &uniform_buffer[i];
+         if( !strcmp(uf->type,"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; i<uniform_count; i++ )
+      {
+         struct uniform *uf = &uniform_buffer[i];
+         fprintf( header, 
+            "   _uniform_%s_%s = "
+               "glGetUniformLocation( _shader_%s.id, \"%s\" );\n",
+            args[0], uf->name,
+            args[0], uf->name );
+      }
+
+      fprintf( header, "}\n" );
+      fprintf( header, "#endif /* SHADER_%s_H */\n", args[0] );
+      fclose( header );
+   }
+}
index a36697b516a77ce3e7ea8298bb2c271438aeb7a9..31cfa8065529233f091bad686717ae2b166ac12d 100644 (file)
@@ -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();
index 6ef64ebc11278cbb65671376af532cf93e3bfa3f..024d87c7b23c27b13aeb8ccb8f3d080bd5e3f696 100644 (file)
@@ -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; j<samples_this_run; j++ )
                        {
                                audio_mixer_getsamples( pcf, sys->source, 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;
                                }
                        }
index 2506ba412d7686cde0b8fba74c863aea89e6eccf..76b3b95e7781934783363c6cb3345f0cf526661e 100644 (file)
@@ -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; i<vg_list_size(vg_button_binds); i ++ )
-       {
                if( !strcmp(button,vg_button_binds[i].name) )
-               {
                        return vg_button_binds + i;
-               }
-       }
+   return NULL;
+}
+
+static inline struct button_binding *vg_get_button_ptr_c( const char *button )
+{
+       for( int i=0; i<vg_list_size(vg_controller_binds); i ++ )
+               if( !strcmp(button,vg_controller_binds[i].name) )
+                       return vg_controller_binds + i;
+   return NULL;
 }
+
 #pragma GCC diagnostic pop
 
 static int vg_console_enabled(void);
 
+static inline void vg_get_button_states( const char *name, int *cur, int *prev )
+{
+       struct button_binding *bind = vg_get_button_ptr( name ),
+                        *bindc = vg_get_button_ptr_c( name );
+   
+   *cur = 0; *prev = 0;
+
+   if( bind ) 
+   {
+      *cur |= bind->value;
+      *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; i<vg_list_size( vg_controller_binds ); i++ )
+   {
+               struct button_binding *binding = vg_controller_binds + i;
+               binding->prev = 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
index 704d9bde796b28ae16da8005e6d95d20fb376ddc..e14d3381d3e4bf65942601afcb79a53ee052bb45 100644 (file)
@@ -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 =
index c71f3abd5af081f077c6547855d55de8a1841208..8ecadbdbdf1a19eddaa336f5c6f82efc2a4fa1d9 100644 (file)
@@ -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;
+}
index 0f1303bc3c540768e3218c57f5047af7c3c3e462..1c9373493cc1458f0dde12fd30f29753be501c1f 100644 (file)
@@ -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 (file)
index 0000000..7201dac
--- /dev/null
@@ -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;
+};
+
index f36d3630dc7de62e3abb956df39616c8b995f2a9..5b97133b3b1ceebe096300d0de8a9bdc0563a83d 100644 (file)
@@ -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; i<slider->len; 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__)
index 9a60b3df574405b94f3c86aec4ab8583c7839d43..33d80575df8953dfb5110d137cd20109c513409c 100755 (executable)
@@ -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