allow other channel for non-dsp sounds (2D oneshots)
[vg.git] / src / shader.c
1 #define STB_INCLUDE_IMPLEMENTATION
2 #define STB_INCLUDE_LINE_GLSL
3 #include "../dep/stb/stb_include.h"
4 #define VG_TOOLS
5 #include "vg/vg.h"
6
7 struct uniform
8 {
9 char name[30];
10 char type[20];
11
12 int array;
13 }
14 uniform_buffer[100];
15 static int uniform_count;
16
17 static int compile_subshader( FILE *header, char *name )
18 {
19 char error[256];
20 char *full = stb_include_file( name, "", ".", error );
21
22 if( !full )
23 {
24 fprintf( stderr, "stb_include_file error:\n%s\n", error );
25 return 0;
26 }
27 else
28 {
29 /* VG */
30
31 fprintf( header, "{\n"
32 ".orig_file = \"../../shaders/%s\",\n"
33 ".static_src = \n", name );
34
35 char *cur = full, *start = full;
36 while( 1 )
37 {
38 char c = *cur;
39 if( c == '\n' || c == '\0' )
40 {
41 *cur = '\0';
42 fputs( "\"", header );
43 fputs( start, header );
44
45 if( !strncmp(start,"uniform",7) )
46 {
47 start += 8;
48 struct uniform *uf = &uniform_buffer[ uniform_count ++ ];
49 uf->array = 0;
50 for( int i=0;; i++ )
51 {
52 if( start[i] == '\0' )
53 break;
54
55 if( start[i] == ';' )
56 {
57 start[i] = '\0';
58 strncpy( uf->name, start, sizeof(uf->name) );
59 }
60
61 if( start[i] == '[' )
62 {
63 start[i] = '\0';
64 strncpy( uf->name, start, sizeof(uf->name) );
65 uf->array = 1;
66 }
67
68 if( start[i] == ' ' )
69 {
70 start[i] = '\0';
71 strncpy( uf->type, start, sizeof(uf->type) );
72 start = start+i+1;
73 i=0;
74 }
75 }
76 }
77
78 if( c == '\0' )
79 {
80 fputs( "\"", header );
81 break;
82 }
83
84 fputs( "\\n\"\n", header );
85 start = cur+1;
86 }
87 cur ++;
88 }
89
90 fputs( "},", header );
91 }
92
93 free( full );
94 return 1;
95 }
96
97 int main( int argc, char *argv[] )
98 {
99 if( argc < 2 || (argc-1)%3 != 0 )
100 {
101 fprintf( stderr, "invalid\n" );
102 return 0;
103 }
104
105 char path[260];
106 int shader_count = (argc-1)/3;
107 for( int i=0; i<shader_count; i++ )
108 {
109 char **args = &argv[1+i*3];
110 strcpy( path, args[0] );
111 strcat( path, ".h" );
112
113 printf( "Compiling shader called '%s'\n", args[0] );
114
115 FILE *header = fopen( path, "w" );
116 if( !header )
117 {
118 fprintf(stderr, "Could not open '%s'\n", path );
119 continue;
120 }
121
122 fprintf( header, "#ifndef SHADER_%s_H\n"
123 "#define SHADER_%s_H\n", args[0], args[0] );
124 fprintf( header, "static void shader_%s_link(void);\n", args[0] );
125 fprintf( header, "static void shader_%s_register(void);\n", args[0] );
126 fprintf( header, "static struct vg_shader _shader_%s = {\n"
127 " .name = \"%s\",\n"
128 " .link = shader_%s_link,\n"
129 " .vs = \n", args[0], args[0], args[0] );
130
131 uniform_count = 0;
132 if( !compile_subshader(header,args[1]) )
133 {
134 fclose( header );
135 continue;
136 }
137
138 fprintf( header, "\n .fs = \n" );
139 if( !compile_subshader(header,args[2]) )
140 {
141 fclose( header );
142 continue;
143 }
144
145 fprintf( header, "\n};\n\n" );
146
147 for( int i=0; i<uniform_count; i++ )
148 {
149 struct uniform *uf = &uniform_buffer[i];
150 fprintf( header, "static GLuint _uniform_%s_%s;\n", args[0], uf->name);
151 }
152
153 for( int i=0; i<uniform_count; i++ )
154 {
155 struct uniform *uf = &uniform_buffer[i];
156 if( uf->array ) continue;
157
158 if( !strcmp(uf->type,"vec2") )
159 {
160 fprintf( header, "static void shader_%s_%s(v2f v){\n"
161 " glUniform2fv( _uniform_%s_%s, 1, v );\n"
162 "}\n", args[0], uf->name, args[0], uf->name );
163 }
164 if( !strcmp(uf->type,"vec3") )
165 {
166 fprintf( header, "static void shader_%s_%s(v3f v){\n"
167 " glUniform3fv( _uniform_%s_%s, 1, v );\n"
168 "}\n", args[0], uf->name, args[0], uf->name );
169 }
170 if( !strcmp(uf->type,"vec4") )
171 {
172 fprintf( header, "static void shader_%s_%s(v4f v){\n"
173 " glUniform4fv( _uniform_%s_%s, 1, v );\n"
174 "}\n", args[0], uf->name, args[0], uf->name );
175 }
176 if( !strcmp(uf->type,"sampler2D") )
177 {
178 fprintf( header, "static void shader_%s_%s(int i){\n"
179 " glUniform1i( _uniform_%s_%s, i );\n"
180 "}\n", args[0], uf->name, args[0], uf->name );
181 }
182 if( !strcmp(uf->type,"float") )
183 {
184 fprintf( header, "static void shader_%s_%s(float f){\n"
185 " glUniform1f( _uniform_%s_%s, f );\n"
186 "}\n", args[0], uf->name, args[0], uf->name );
187 }
188 if( !strcmp(uf->type,"mat4x3") )
189 {
190 fprintf( header,
191 "static void shader_%s_%s(m4x3f m){\n"
192 " glUniformMatrix4x3fv"
193 "( _uniform_%s_%s, 1, GL_FALSE, (float *)m );\n"
194 "}\n", args[0], uf->name, args[0], uf->name );
195 }
196 if( !strcmp(uf->type,"mat3") )
197 {
198 fprintf( header,
199 "static void shader_%s_%s(m3x3f m){\n"
200 " glUniformMatrix3fv"
201 "( _uniform_%s_%s, 1, GL_FALSE, (float *)m );\n"
202 "}\n", args[0], uf->name, args[0], uf->name );
203 }
204 if( !strcmp(uf->type,"mat4") )
205 {
206 fprintf( header,
207 "static void shader_%s_%s(m4x4f m){\n"
208 " glUniformMatrix4fv"
209 "( _uniform_%s_%s, 1, GL_FALSE, (float *)m );\n"
210 "}\n", args[0], uf->name, args[0], uf->name );
211 }
212 }
213
214 fprintf( header,
215 "static void shader_%s_register(void){\n"
216 " vg_shader_register( &_shader_%s );\n"
217 "}\n",
218 args[0],args[0] );
219
220 fprintf( header,
221 "static void shader_%s_use(void){ glUseProgram(_shader_%s.id); }\n",
222 args[0], args[0] );
223
224 fprintf( header,
225 "static void shader_%s_link(void){\n",
226 args[0] );
227
228 for( int i=0; i<uniform_count; i++ )
229 {
230 struct uniform *uf = &uniform_buffer[i];
231 fprintf( header,
232 " _uniform_%s_%s = "
233 "glGetUniformLocation( _shader_%s.id, \"%s\" );\n",
234 args[0], uf->name,
235 args[0], uf->name );
236 }
237
238 fprintf( header, "}\n" );
239 fprintf( header, "#endif /* SHADER_%s_H */\n", args[0] );
240 fclose( header );
241 }
242 }