work on moving shader loading/compilation to a separate file
This commit is contained in:
88
src/shaders.cpp
Normal file
88
src/shaders.cpp
Normal file
@@ -0,0 +1,88 @@
|
||||
#include <typeinfo>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "util.hpp"
|
||||
#include "shaders.hpp"
|
||||
|
||||
#define MAX_ERR_MSG_LEN 256
|
||||
|
||||
|
||||
// Visit/Variant overload pattern
|
||||
// https://www.modernescpp.com/index.php/visiting-a-std-variant-with-the-overload-pattern/
|
||||
template<typename ... Ts>
|
||||
struct overload : Ts ... {
|
||||
using Ts::operator() ...;
|
||||
};
|
||||
template<class... Ts> overload(Ts...) -> overload<Ts...>;
|
||||
|
||||
namespace shader {
|
||||
|
||||
bool _compile_shader(uint *out_id, const char* filepath, int shader_type);
|
||||
|
||||
bool load(uint* out_id, const char* vertex_filepath, const char* fragment_filepath) {
|
||||
uint vertex_id;
|
||||
if (!_compile_shader(&vertex_id, vertex_filepath, GL_VERTEX_SHADER))
|
||||
return false;
|
||||
|
||||
uint fragment_id;
|
||||
if (!_compile_shader(&fragment_id, fragment_filepath, GL_FRAGMENT_SHADER))
|
||||
return false;
|
||||
|
||||
uint program_id = glCreateProgram();
|
||||
glAttachShader(program_id, vertex_id);
|
||||
glAttachShader(program_id, fragment_id);
|
||||
glLinkProgram(program_id);
|
||||
|
||||
int status;
|
||||
glGetProgramiv(program_id, GL_LINK_STATUS, &status);
|
||||
if (status == GL_FALSE) {
|
||||
char err_msg[MAX_ERR_MSG_LEN];
|
||||
glGetProgramInfoLog(program_id, MAX_ERR_MSG_LEN, NULL, err_msg);
|
||||
printf("Error linking shaders %s and %s\n", vertex_filepath, fragment_filepath);
|
||||
printf("Error msg: %s\n", err_msg);
|
||||
return false;
|
||||
}
|
||||
|
||||
glDeleteShader(vertex_id);
|
||||
glDeleteShader(fragment_id);
|
||||
|
||||
*out_id = program_id;
|
||||
return true;
|
||||
}
|
||||
|
||||
void use(uint id) { glUseProgram(id); }
|
||||
|
||||
void set_uniform(uint id, const char* name, uniform_variant value) {
|
||||
const auto visitor = overload {
|
||||
[id, name](int i) { glUniform1i(glGetUniformLocation(id, name), i); },
|
||||
[id, name](float f) { glUniform1f(glGetUniformLocation(id, name), f); },
|
||||
[id, name](bool b) { glUniform1i(glGetUniformLocation(id, name), b); },
|
||||
};
|
||||
visit(visitor, value);
|
||||
}
|
||||
|
||||
// Privates
|
||||
|
||||
bool _compile_shader(uint *out_id, const char* filepath, int shader_type) {
|
||||
Array<char> source;
|
||||
if (!read_file(&source, filepath))
|
||||
return false;
|
||||
|
||||
uint id = glCreateShader(shader_type);
|
||||
glShaderSource(id, 1, &source._data, (int*)&source.len);
|
||||
glCompileShader(id);
|
||||
|
||||
int status;
|
||||
glGetShaderiv(id, GL_COMPILE_STATUS, &status);
|
||||
if (status == GL_FALSE) {
|
||||
char err_msg[MAX_ERR_MSG_LEN];
|
||||
glGetShaderInfoLog(id, MAX_ERR_MSG_LEN, NULL, err_msg);
|
||||
printf("Error compiling shader %s\n", filepath);
|
||||
printf("%.*s\n", (int)source.len, source._data);
|
||||
printf("Error msg: %s\n", err_msg);
|
||||
}
|
||||
*out_id = id;
|
||||
return status == GL_TRUE;
|
||||
}
|
||||
|
||||
} // namespace shader
|
||||
Reference in New Issue
Block a user