X-Git-Url: https://harrygodden.com/git/?p=vg.git;a=blobdiff_plain;f=vg_shader.c;fp=vg_shader.c;h=4b41c2e697cbc5ca19297a81cde52718fc3419a3;hp=0000000000000000000000000000000000000000;hb=3b14f3dcd5bf9dd3c85144f2123d667bfa4bb63f;hpb=fce86711735b15bff37de0f70716808410fcf269 diff --git a/vg_shader.c b/vg_shader.c new file mode 100644 index 0000000..4b41c2e --- /dev/null +++ b/vg_shader.c @@ -0,0 +1,187 @@ +/* Copyright (C) 2021-2024 Harry Godden (hgn) - All Rights Reserved */ + +#pragma once +#include "vg_platform.h" +#include "vg_shader.h" +#include "vg_engine.h" + +#define STB_INCLUDE_IMPLEMENTATION +#define STB_INCLUDE_LINE_GLSL +#define STB_MALLOC vg_alloc +#define STB_FREE vg_free +#define STB_REALLOC vg_realloc +#include "submodules/stb/stb_include.h" + +const char *vg_shader_gl_ver = "#version 330 core\n"; + +struct vg_shaders vg_shaders; + +static GLuint vg_shader_subshader( const char *src, GLint gliShaderType ) +{ + GLint shader = glCreateShader( gliShaderType ); + + if( shader == GL_NONE ) + { + vg_error( "Could not 'glCreateShader()'\n" ); + return 0; + } + + glShaderSource( shader, 2, (const char*[2]){ vg_shader_gl_ver, src }, NULL ); + glCompileShader( shader ); + + GLint status; + glGetShaderiv( shader, GL_COMPILE_STATUS, &status ); + + if( status != GL_TRUE ) + { + GLchar info[1024]; + GLsizei len; + + glGetShaderInfoLog( shader, sizeof(info), &len, info ); + vg_error( "Error info:\n%s\n", info ); + return 0; + } + + return shader; +} + +int vg_shader_compile( struct vg_shader *shader ) +{ + GLuint program, vert, frag; + + /* If we are compiling this again, we obviously need to try to take the src + * from the disk instead. + * + * Only do this if we have filenames set on the shader, so engine shaders + * dont have to do it (text.. etc). + */ + + int use_source_files = 0; + if( shader->compiled ){ + if( shader->vs.orig_file && shader->fs.orig_file ){ + use_source_files = 1; + } + else { + vg_warn( "No source files for shader '%s'\n", shader->name ); + return 1; + } + } + + vg_info( "Compile shader '%s'\n", shader->name ); + + if( use_source_files ){ + char error[260]; + char path[260]; + + strcpy( path, "../../" ); + strcat( path, shader->vs.orig_file ); + char *vertex_src = stb_include_file( path, "", "../../shaders", error ); + + strcpy( path, "../../" ); + strcat( path, shader->fs.orig_file ); + char *fragment_src = stb_include_file( path, "", "../../shaders", error ); + + if( !vertex_src || !fragment_src ){ + const char *errstr = "Could not find shader source files (%s)\n"; + if( shader->compiled ){ + vg_warn( errstr, shader->vs.orig_file ); + free( vertex_src ); + free( fragment_src ); + return 1; + } + else{ + vg_error( errstr, shader->vs.orig_file ); + free( vertex_src ); + free( fragment_src ); + return 0; + } + } + + vert = vg_shader_subshader( vertex_src, GL_VERTEX_SHADER ); + frag = vg_shader_subshader( fragment_src, GL_FRAGMENT_SHADER ); + + free( vertex_src ); + free( fragment_src ); + } + else{ + vert = vg_shader_subshader( shader->vs.static_src, GL_VERTEX_SHADER ); + frag = vg_shader_subshader( shader->fs.static_src, GL_FRAGMENT_SHADER ); + } + + if( !vert || !frag ) + return 0; + + program = glCreateProgram(); + + glAttachShader( program, vert ); + glAttachShader( program, frag ); + glLinkProgram( program ); + + glDeleteShader( vert ); + glDeleteShader( frag ); + + /* Check for link errors */ + char infoLog[ 512 ]; + int success_link = 1; + + glGetProgramiv( program, GL_LINK_STATUS, &success_link ); + if( !success_link ) + { + glGetProgramInfoLog( program, 512, NULL, infoLog ); + vg_error( "Link failed: %s\n", infoLog ); + glDeleteProgram( program ); + return 0; + } + + if( shader->compiled ) + glDeleteProgram( shader->id ); + + shader->id = program; + shader->compiled = 1; + if( shader->link ) + shader->link(); + return 1; +} + +static void vg_free_shader( struct vg_shader *shader ) +{ + if( shader->compiled ) + { + glDeleteProgram( shader->id ); + shader->compiled = 0; + } +} + +void vg_shaders_compile(void) +{ + vg_info( "Compiling shaders\n" ); + + for( int i=0; icompiled = 0; + shader->id = 0; /* TODO: make this an error shader */ + vg_shaders.shaders[ vg_shaders.count ++ ] = shader; +}