16#define GLSL_VERSION "#version 150\n\n"
17#define GLSL_SUBROUTINE "#define HAS_GL_ARB_shader_subroutine 1\n"
22static char* gl_shader_preprocess(
size_t *size,
const char *fbuf,
size_t fbufsize,
const char *prepend,
const char *filename );
23static char* gl_shader_loadfile(
const char *filename,
size_t *size,
const char *prepend );
24static GLuint gl_shader_compile( GLuint type,
const char *buf,
25 GLint length,
const char *filename);
26static int gl_program_link( GLuint program );
27static GLuint gl_program_make( GLuint vertex_shader, GLuint fragment_shader, GLuint geometry_shader );
28static int gl_log_says_anything(
const char* log );
38static char* gl_shader_loadfile(
const char *filename,
size_t *size,
const char *prepend )
46 snprintf(path,
sizeof(path), GLSL_PATH
"%s", filename);
49 WARN( _(
"Shader '%s' not found."), path);
52 buf = gl_shader_preprocess( size, fbuf, fbufsize, prepend, filename );
67static char* gl_shader_preprocess(
size_t *size,
const char *fbuf,
size_t fbufsize,
const char *prepend,
const char *filename )
69 size_t i, bufsize, ibufsize;
70 char *buf, *ibuf, *newbuf;
71 char include[
PATH_MAX-
sizeof(GLSL_PATH)-1];
72 const char *substart, *subs, *subss, *keyword;
76 if (prepend != NULL) {
77 bufsize = SDL_asprintf( &buf,
"%s%s", prepend, fbuf ) + 1 ;
92 while ((substart =
strnstr( subs, keyword, bufsize-(subs-buf) ))!=NULL) {
93 subs = substart+strlen(keyword)+1;
96 subss =
strnstr( subs,
"\"", bufsize-(subs-buf));
98 WARN(_(
"Invalid #include syntax in '%s%s'!"), GLSL_PATH, filename);
102 while (isprint(*subs) && (i<
sizeof(include)) && (*subs!=
'"')) {
103 include[i++] = *subs;
107 WARN(_(
"Invalid #include syntax in '%s%s'!"), GLSL_PATH, filename);
113 ibuf = gl_shader_loadfile( include, &ibufsize, NULL );
116 newbuf = malloc( bufsize+ibufsize );
119 strncpy( &newbuf[offset], buf, len );
122 strncpy( &newbuf[offset], ibuf, len );
125 len = bufsize-(subs-buf);
126 strncpy( &newbuf[offset], subs, bufsize-(subs-buf) );
128 newbuf[offset] =
'\0';
131 subs = &newbuf[subs-buf];
149static GLuint gl_shader_compile( GLuint type,
const char *buf,
150 GLint length,
const char *filename)
153 GLint compile_status, log_length;
156 shader = glCreateShader(type);
157 glShaderSource(shader, 1, (
const char**)&buf, &length);
158 glCompileShader(shader);
161 glGetShaderiv(shader, GL_COMPILE_STATUS, &compile_status);
162 glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &log_length);
163 if (log_length > 0) {
164 char *log = malloc(log_length + 1);
165 glGetShaderInfoLog(shader, log_length, &log_length, log);
166 if (gl_log_says_anything( log )) {
168 WARN(
"compile_status==%d: %s: [[\n%s\n]]", compile_status, filename, log);
171 if (compile_status == GL_FALSE)
184static int gl_program_link( GLuint program )
186 GLint link_status, log_length;
188 glLinkProgram(program);
191 glGetProgramiv(program, GL_LINK_STATUS, &link_status);
192 glGetProgramiv(program, GL_INFO_LOG_LENGTH, &log_length);
193 if (log_length > 0) {
194 char *log = malloc(log_length + 1);
195 glGetProgramInfoLog(program, log_length, &log_length, log);
196 if (gl_log_says_anything( log ))
197 WARN(
"link_status==%d: [[\n%s\n]]", link_status, log);
199 if (link_status == GL_FALSE)
214GLuint gl_program_vert_frag(
const char *vertfile,
const char *fragfile,
const char *geomfile )
216 char *vert_str, *frag_str, prepend[STRMAX];
217 size_t vert_size, frag_size;
218 GLuint vertex_shader, fragment_shader, geometry_shader, program;
220 strncpy( prepend, GLSL_VERSION,
sizeof(prepend)-1 );
221 if (gl_has( OPENGL_SUBROUTINES ))
222 strncat( prepend, GLSL_SUBROUTINE,
sizeof(prepend)-strlen(prepend)-1 );
224 vert_str = gl_shader_loadfile( vertfile, &vert_size, prepend );
225 frag_str = gl_shader_loadfile( fragfile, &frag_size, prepend );
227 vertex_shader = gl_shader_compile( GL_VERTEX_SHADER, vert_str, vert_size, vertfile );
228 fragment_shader = gl_shader_compile( GL_FRAGMENT_SHADER, frag_str, frag_size, fragfile );
233 if (geomfile != NULL) {
235 char *geom_str = gl_shader_loadfile( geomfile, &geom_size, prepend );
236 geometry_shader = gl_shader_compile( GL_GEOMETRY_SHADER, geom_str, geom_size, geomfile );
242 program = gl_program_make( vertex_shader, fragment_shader, geometry_shader );
244 WARN(_(
"Failed to link vertex shader '%s' and fragment shader '%s'!"), vertfile, fragfile);
258GLuint gl_program_vert_frag_string(
const char *vert,
size_t vert_size,
const char *frag,
size_t frag_size )
260 GLuint vertex_shader, fragment_shader;
264 vbuf = gl_shader_preprocess( &vlen, vert, vert_size, NULL, NULL );
265 fbuf = gl_shader_preprocess( &flen, frag, frag_size, NULL, NULL );
268 vertex_shader = gl_shader_compile( GL_VERTEX_SHADER, vbuf, vlen, NULL );
269 fragment_shader = gl_shader_compile( GL_FRAGMENT_SHADER, fbuf, flen, NULL );
276 return gl_program_make( vertex_shader, fragment_shader, 0 );
287static GLuint gl_program_make( GLuint vertex_shader, GLuint fragment_shader, GLuint geometry_shader )
290 if (vertex_shader != 0 && fragment_shader != 0) {
291 program = glCreateProgram();
292 glAttachShader(program, vertex_shader);
293 glAttachShader(program, fragment_shader);
294 if (geometry_shader != 0)
295 glAttachShader(program, geometry_shader);
297 if (gl_program_link(program) == -1) {
302 glDeleteShader(vertex_shader);
303 glDeleteShader(fragment_shader);
304 if (geometry_shader != 0)
305 glDeleteShader(geometry_shader);
313void gl_uniformColour(GLint location,
const glColour *
c)
315 glUniform4f(location,
c->r,
c->g,
c->b,
c->a);
318void gl_uniformAColour(GLint location,
const glColour *
c, GLfloat a)
320 glUniform4f(location,
c->r,
c->g,
c->b, a);
323void gl_uniformMat4( GLint location,
const mat4 *m )
325 glUniformMatrix4fv(location, 1, GL_FALSE, m->ptr );
332static int gl_log_says_anything(
const char* log )
334 const char *junk[] = {
343 for (
size_t i = 0; i*
sizeof(junk[0]) <
sizeof(junk); i++)
344 if (!strncmp(log, junk[i], strlen(junk[i]))) {
345 log += strlen(junk[i]);
Header file with generic functions and naev-specifics.
void * ndata_read(const char *path, size_t *filesize)
Reads a file from the ndata (will be NUL terminated).
void print_with_line_numbers(const char *str)
Prints to stderr with line numbers.
char * strnstr(const char *haystack, const char *needle, size_t size)
A bounded version of strstr. Conforms to BSD semantics.