bad char
[vg.git] / src / vg / vg_shader.h
1 /* TODO: TUrn off in release */
2 #define STB_INCLUDE_IMPLEMENTATION
3 #define STB_INCLUDE_LINE_GLSL
4 #include "stb/stb_include.h"
5
6 const char *vg_shader_gl_ver = "#version 330 core\n";
7
8 struct vg_shader
9 {
10 GLuint id;
11 const char *name;
12
13 struct vg_subshader
14 {
15 const char *orig_file,
16 *static_src;
17 }
18 vs, fs;
19
20 void (*link)(void);
21 int compiled;
22 }
23 ** vg_shaders_active = NULL;
24
25 static GLuint vg_shader_subshader( const char *src, GLint gliShaderType )
26 {
27 GLint shader = glCreateShader( gliShaderType );
28
29 if( shader == GL_NONE )
30 {
31 vg_error( "Could not 'glCreateShader()'\n" );
32 return 0;
33 }
34
35 glShaderSource( shader, 2, (const char*[2]){ vg_shader_gl_ver, src }, NULL );
36 glCompileShader( shader );
37
38 GLint status;
39 glGetShaderiv( shader, GL_COMPILE_STATUS, &status );
40
41 if( status != GL_TRUE )
42 {
43 GLchar info[1024];
44 GLsizei len;
45
46 glGetShaderInfoLog( shader, sizeof(info), &len, info );
47 vg_error( "Error info:\n%s\n", info );
48 return 0;
49 }
50
51 return shader;
52 }
53
54 static int vg_shader_compile( struct vg_shader *shader )
55 {
56 vg_info( "Compile shader '%s'\n", shader->name );
57
58 GLuint program, vert, frag;
59 const char *svs, *sfs;
60 char *avs, *afs;
61
62 int static_src = 1;
63
64 /* If we are compiling this again, we obviously need to try to take the src
65 * from the disk instead.
66 *
67 * Only do this if we have filenames set on the shader, so engine shaders
68 * dont have to do it (text.. etc).
69 */
70 if( shader->compiled )
71 {
72 if( shader->vs.orig_file && shader->fs.orig_file )
73 static_src = 0;
74 else return 1;
75 }
76
77 if( static_src )
78 {
79 svs = shader->vs.static_src;
80 sfs = shader->fs.static_src;
81 }
82 else
83 {
84 char error[260];
85 char path[260];
86 strcpy( path, shader->vs.orig_file );
87 avs = stb_include_file( path, "", "../shaders", error );
88
89 strcpy( path, shader->fs.orig_file );
90 afs = stb_include_file( path, "", "../shaders", error );
91
92 if( !avs || !afs )
93 {
94 free( avs );
95 free( afs );
96 return 0;
97 }
98
99 svs = avs;
100 sfs = afs;
101 }
102
103 vert = vg_shader_subshader( svs, GL_VERTEX_SHADER );
104 frag = vg_shader_subshader( sfs, GL_FRAGMENT_SHADER );
105
106 if( !static_src )
107 {
108 free( avs );
109 free( afs );
110 }
111
112 if( !vert || !frag )
113 return 0;
114
115 program = glCreateProgram();
116
117 glAttachShader( program, vert );
118 glAttachShader( program, frag );
119 glLinkProgram( program );
120
121 glDeleteShader( vert );
122 glDeleteShader( frag );
123
124 /* Check for link errors */
125 char infoLog[ 512 ];
126 int success_link = 1;
127
128 glGetProgramiv( program, GL_LINK_STATUS, &success_link );
129 if( !success_link )
130 {
131 glGetProgramInfoLog( program, 512, NULL, infoLog );
132 vg_error( "Link failed: %s\n", infoLog );
133 glDeleteProgram( program );
134 return 0;
135 }
136
137 if( shader->compiled )
138 glDeleteProgram( shader->id );
139
140 shader->id = program;
141 shader->compiled = 1;
142 if( shader->link )
143 shader->link();
144 return 1;
145 }
146
147 static void vg_shaders_free(void)
148 {
149 for( int i = 0; i < arrlen( vg_shaders_active ); i ++ )
150 {
151 struct vg_shader *shader = vg_shaders_active[i];
152
153 if( shader->compiled )
154 glDeleteProgram( shader->id );
155 }
156
157 arrfree( vg_shaders_active );
158 }
159
160 static int vg_shaders_recompile(int argc, const char *argv[])
161 {
162 vg_info( "Compiling shaders\n" );
163 for( int i = 0; i < arrlen( vg_shaders_active ); i ++ )
164 {
165 struct vg_shader *shader = vg_shaders_active[i];
166 vg_shader_compile( shader );
167 }
168
169 return 0;
170 }
171
172 static void vg_shader_register( struct vg_shader *shader )
173 {
174 shader->compiled = 0;
175 shader->id = 0; /* TODO: make this an error shader */
176 arrpush( vg_shaders_active, shader );
177 }