bad char
[vg.git] / vg_shader.h
1 /* Copyright (C) 2021-2022 Harry Godden (hgn) - All Rights Reserved */
2
3 #ifndef VG_SHADER_H
4 #define VG_SHADER_H
5
6 #define VG_GAME
7 #include "vg/vg.h"
8 #include "vg/vg_platform.h"
9
10 #if 0
11 #define STB_INCLUDE_IMPLEMENTATION
12 #define STB_INCLUDE_LINE_GLSL
13 #define STB_MALLOC vg_alloc
14 #define STB_FREE vg_free
15 #define STB_REALLOC vg_realloc
16 #include "stb/stb_include.h"
17 #endif
18
19 const char *vg_shader_gl_ver = "#version 330 core\n";
20
21 typedef struct vg_shader vg_shader;
22
23 struct
24 {
25 struct vg_shader
26 {
27 GLuint id;
28 const char *name;
29
30 struct vg_subshader
31 {
32 const char *orig_file,
33 *static_src;
34 }
35 vs, fs;
36
37 void (*link)(void);
38 int compiled;
39 }
40 * shaders[32];
41 u32 count;
42 }
43 static vg_shaders;
44
45 VG_STATIC GLuint vg_shader_subshader( const char *src, GLint gliShaderType )
46 {
47 GLint shader = glCreateShader( gliShaderType );
48
49 if( shader == GL_NONE )
50 {
51 vg_error( "Could not 'glCreateShader()'\n" );
52 return 0;
53 }
54
55 glShaderSource( shader, 2, (const char*[2]){ vg_shader_gl_ver, src }, NULL );
56 glCompileShader( shader );
57
58 GLint status;
59 glGetShaderiv( shader, GL_COMPILE_STATUS, &status );
60
61 if( status != GL_TRUE )
62 {
63 GLchar info[1024];
64 GLsizei len;
65
66 glGetShaderInfoLog( shader, sizeof(info), &len, info );
67 vg_error( "Error info:\n%s\n", info );
68 return 0;
69 }
70
71 return shader;
72 }
73
74 VG_STATIC int vg_shader_compile( struct vg_shader *shader )
75 {
76 vg_info( "Compile shader '%s'\n", shader->name );
77
78 GLuint program, vert, frag;
79 const char *svs, *sfs;
80 char *avs, *afs;
81
82 int static_src = 1;
83
84 /* If we are compiling this again, we obviously need to try to take the src
85 * from the disk instead.
86 *
87 * Only do this if we have filenames set on the shader, so engine shaders
88 * dont have to do it (text.. etc).
89 */
90 if( shader->compiled )
91 {
92 if( shader->vs.orig_file && shader->fs.orig_file )
93 static_src = 0;
94 else return 1;
95 }
96
97 if( static_src )
98 {
99 svs = shader->vs.static_src;
100 sfs = shader->fs.static_src;
101 }
102 else
103 {
104 vg_fatal_exit_loop( "Unimplemented" );
105
106 #if 0
107 char error[260];
108 char path[260];
109 strcpy( path, shader->vs.orig_file );
110 avs = stb_include_file( path, "", "../../shaders", error );
111
112 strcpy( path, shader->fs.orig_file );
113 afs = stb_include_file( path, "", "../../shaders", error );
114
115 if( !avs || !afs )
116 {
117 vg_error( "Could not find shader source files (%s)\n",
118 shader->vs.orig_file );
119
120 vg_free( avs );
121 vg_free( afs );
122 return 0;
123 }
124
125 svs = avs;
126 sfs = afs;
127 #endif
128 }
129
130 vert = vg_shader_subshader( svs, GL_VERTEX_SHADER );
131 frag = vg_shader_subshader( sfs, GL_FRAGMENT_SHADER );
132
133 #if 0
134 if( !static_src )
135 {
136 free( avs );
137 free( afs );
138 }
139 #endif
140
141 if( !vert || !frag )
142 return 0;
143
144 program = glCreateProgram();
145
146 glAttachShader( program, vert );
147 glAttachShader( program, frag );
148 glLinkProgram( program );
149
150 glDeleteShader( vert );
151 glDeleteShader( frag );
152
153 /* Check for link errors */
154 char infoLog[ 512 ];
155 int success_link = 1;
156
157 glGetProgramiv( program, GL_LINK_STATUS, &success_link );
158 if( !success_link )
159 {
160 glGetProgramInfoLog( program, 512, NULL, infoLog );
161 vg_error( "Link failed: %s\n", infoLog );
162 glDeleteProgram( program );
163 return 0;
164 }
165
166 if( shader->compiled )
167 glDeleteProgram( shader->id );
168
169 shader->id = program;
170 shader->compiled = 1;
171 if( shader->link )
172 shader->link();
173 return 1;
174 }
175
176 VG_STATIC void vg_free_shader( struct vg_shader *shader )
177 {
178 if( shader->compiled )
179 {
180 glDeleteProgram( shader->id );
181 shader->compiled = 0;
182 }
183 }
184
185 VG_STATIC void vg_shaders_compile(void)
186 {
187 vg_info( "Compiling shaders\n" );
188
189 for( int i=0; i<vg_shaders.count; i ++ )
190 {
191 vg_shader *shader = vg_shaders.shaders[i];
192
193 if( !vg_shader_compile( shader ) )
194 vg_fatal_exit_loop( "Failed to compile shader" );
195 }
196 }
197
198 VG_STATIC int vg_shaders_live_recompile(int argc, const char *argv[])
199 {
200 vg_info( "Recompiling shaders\n" );
201 for( int i=0; i<vg_shaders.count; i ++ )
202 {
203 struct vg_shader *shader = vg_shaders.shaders[i];
204 vg_shader_compile( shader );
205 }
206
207 return 0;
208 }
209
210 VG_STATIC void vg_shader_register( struct vg_shader *shader )
211 {
212 if( vg_shaders.count == vg_list_size(vg_shaders.shaders) )
213 vg_fatal_exit_loop( "Too many shaders" );
214
215 shader->compiled = 0;
216 shader->id = 0; /* TODO: make this an error shader */
217 vg_shaders.shaders[ vg_shaders.count ++ ] = shader;
218 }
219
220 #endif /* VG_SHADER_H */