1 /* Copyright (C) 2021-2024 Harry Godden (hgn) - All Rights Reserved */
4 #include "vg_platform.h"
8 #define STB_INCLUDE_IMPLEMENTATION
9 #define STB_INCLUDE_LINE_GLSL
10 #define STB_MALLOC vg_alloc
11 #define STB_FREE vg_free
12 #define STB_REALLOC vg_realloc
13 #include "submodules/stb/stb_include.h"
15 const char *vg_shader_gl_ver
= "#version 330 core\n";
17 struct vg_shaders vg_shaders
;
19 static GLuint
vg_shader_subshader( const char *src
, GLint gliShaderType
)
21 GLint shader
= glCreateShader( gliShaderType
);
23 if( shader
== GL_NONE
)
25 vg_error( "Could not 'glCreateShader()'\n" );
29 glShaderSource( shader
, 2, (const char*[2]){ vg_shader_gl_ver
, src
}, NULL
);
30 glCompileShader( shader
);
33 glGetShaderiv( shader
, GL_COMPILE_STATUS
, &status
);
35 if( status
!= GL_TRUE
)
40 glGetShaderInfoLog( shader
, sizeof(info
), &len
, info
);
41 vg_error( "Error info:\n%s\n", info
);
48 int vg_shader_compile( struct vg_shader
*shader
)
50 GLuint program
, vert
, frag
;
52 /* If we are compiling this again, we obviously need to try to take the src
53 * from the disk instead.
55 * Only do this if we have filenames set on the shader, so engine shaders
56 * dont have to do it (text.. etc).
59 int use_source_files
= 0;
60 if( shader
->compiled
){
61 if( shader
->vs
.orig_file
&& shader
->fs
.orig_file
){
65 vg_warn( "No source files for shader '%s'\n", shader
->name
);
70 vg_info( "Compile shader '%s'\n", shader
->name
);
72 if( use_source_files
){
76 strcpy( path
, "../../" );
77 strcat( path
, shader
->vs
.orig_file
);
78 char *vertex_src
= stb_include_file( path
, "", "../../shaders", error
);
80 strcpy( path
, "../../" );
81 strcat( path
, shader
->fs
.orig_file
);
82 char *fragment_src
= stb_include_file( path
, "", "../../shaders", error
);
84 if( !vertex_src
|| !fragment_src
){
85 const char *errstr
= "Could not find shader source files (%s)\n";
86 if( shader
->compiled
){
87 vg_warn( errstr
, shader
->vs
.orig_file
);
93 vg_error( errstr
, shader
->vs
.orig_file
);
100 vert
= vg_shader_subshader( vertex_src
, GL_VERTEX_SHADER
);
101 frag
= vg_shader_subshader( fragment_src
, GL_FRAGMENT_SHADER
);
104 free( fragment_src
);
107 vert
= vg_shader_subshader( shader
->vs
.static_src
, GL_VERTEX_SHADER
);
108 frag
= vg_shader_subshader( shader
->fs
.static_src
, GL_FRAGMENT_SHADER
);
114 program
= glCreateProgram();
116 glAttachShader( program
, vert
);
117 glAttachShader( program
, frag
);
118 glLinkProgram( program
);
120 glDeleteShader( vert
);
121 glDeleteShader( frag
);
123 /* Check for link errors */
125 int success_link
= 1;
127 glGetProgramiv( program
, GL_LINK_STATUS
, &success_link
);
130 glGetProgramInfoLog( program
, 512, NULL
, infoLog
);
131 vg_error( "Link failed: %s\n", infoLog
);
132 glDeleteProgram( program
);
136 if( shader
->compiled
)
137 glDeleteProgram( shader
->id
);
139 shader
->id
= program
;
140 shader
->compiled
= 1;
144 static void vg_free_shader( struct vg_shader
*shader
)
146 if( shader
->compiled
)
148 glDeleteProgram( shader
->id
);
149 shader
->compiled
= 0;
153 #ifdef VG_CUSTOM_SHADERS
154 void vg_auto_shader_link(void);
157 void vg_shaders_compile(void)
159 vg_info( "Compiling shaders\n" );
161 for( int i
=0; i
<vg_shaders
.count
; i
++ ){
162 vg_shader
*shader
= vg_shaders
.shaders
[i
];
164 if( !vg_shader_compile( shader
) )
165 vg_fatal_error( "Failed to compile shader" );
168 #ifdef VG_CUSTOM_SHADERS
169 vg_auto_shader_link();
173 int vg_shaders_live_recompile(int argc
, const char *argv
[])
175 vg_info( "Recompiling shaders\n" );
176 for( int i
=0; i
<vg_shaders
.count
; i
++ )
178 struct vg_shader
*shader
= vg_shaders
.shaders
[i
];
179 vg_shader_compile( shader
);
185 void vg_shader_register( struct vg_shader
*shader
)
187 if( vg_shaders
.count
== vg_list_size(vg_shaders
.shaders
) )
188 vg_fatal_error( "Too many shaders" );
190 shader
->compiled
= 0;
191 shader
->id
= 0; /* TODO: make this an error shader */
192 vg_shaders
.shaders
[ vg_shaders
.count
++ ] = shader
;