From 1c4587cd358f8ccc8902738ded236268ffcd9039 Mon Sep 17 00:00:00 2001 From: Abdelrahman Date: Sun, 3 Nov 2024 15:09:22 +0000 Subject: [PATCH] Add basic Shader class --- src/main.cc | 155 +++++++++++++++++++++++++++++++++++----------------- 1 file changed, 106 insertions(+), 49 deletions(-) diff --git a/src/main.cc b/src/main.cc index fcbce97..f3416db 100644 --- a/src/main.cc +++ b/src/main.cc @@ -39,7 +39,18 @@ enum exit_codes : int { EXIT_CODE_GLAD_LOADER_FAILED, }; -std::string load_shader(const std::string &filepath); +class Shader { + public: + Shader(const std::string &vert_file, const std::string &frag_file); + ~Shader(); + void activate(); + private: + GLuint program; + void link_program(GLuint vert, GLuint frag); + GLuint load_and_compile_shader(const std::string &filepath, GLenum shader_type); + std::string load_shader_from_file(const std::string &filepath); + static const char *get_shader_type_string(GLenum shader_type); +}; int main() { if (SDL_Init(SDL_INIT_EVERYTHING) != 0) { @@ -105,52 +116,7 @@ int main() { glDisableVertexAttribArray(0); glDisableVertexAttribArray(1); - std::string vs_shader = load_shader("shaders/vert.glsl"); - const char *vs_source = vs_shader.c_str(); - GLuint vs = glCreateShader(GL_VERTEX_SHADER); - glShaderSource(vs, 1, &vs_source, NULL); - glCompileShader(vs); - GLint vs_compiled; - glGetShaderiv(vs, GL_COMPILE_STATUS, &vs_compiled); - if (vs_compiled != GL_TRUE) - { - GLsizei log_length = 0; - GLchar message[1024]; - glGetShaderInfoLog(vs, 1024, &log_length, message); - printf("Failed to compile vertex shader: %s\n", message); - } - - std::string fs_shader = load_shader("shaders/frag.glsl"); - const char *fs_source = fs_shader.c_str(); - GLuint fs = glCreateShader(GL_FRAGMENT_SHADER); - glShaderSource(fs, 1, &fs_source, NULL); - glCompileShader(fs); - GLint fs_compiled; - glGetShaderiv(fs, GL_COMPILE_STATUS, &fs_compiled); - if (fs_compiled != GL_TRUE) - { - GLsizei log_length = 0; - GLchar message[1024]; - glGetShaderInfoLog(fs, 1024, &log_length, message); - printf("Failed to compile fragment shader: %s\n", message); - } - - GLuint program = glCreateProgram(); - glAttachShader(program, vs); - glAttachShader(program, fs); - glLinkProgram(program); - GLint program_linked; - glGetProgramiv(program, GL_LINK_STATUS, &program_linked); - if (program_linked != GL_TRUE) - { - GLsizei log_length = 0; - GLchar message[1024]; - glGetProgramInfoLog(program, 1024, &log_length, message); - printf("Failed to link program: %s\n", message); - } - - glDeleteShader(vs); - glDeleteShader(fs); + Shader main_shader {"shaders/vert.glsl", "shaders/frag.glsl"}; bool running = true; SDL_Event event = {}; @@ -182,7 +148,7 @@ int main() { glClearColor(0.2f, 0.3f, 0.3f, 1.0f); glClear(GL_COLOR_BUFFER_BIT); - glUseProgram(program); + main_shader.activate(); glBindVertexArray(vao); glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_INT, NULL); @@ -196,7 +162,68 @@ int main() { return EXIT_CODE_SUCCESS; } -std::string load_shader(const std::string &filepath) { + +Shader::Shader(const std::string &vert_file, const std::string &frag_file) { + GLuint vert = load_and_compile_shader(vert_file, GL_VERTEX_SHADER); + GLuint frag = load_and_compile_shader(frag_file, GL_FRAGMENT_SHADER); + link_program(vert, frag); + glDeleteShader(vert); + glDeleteShader(frag); +} + +Shader::~Shader() { + if (program > 0) { + glDeleteProgram(program); + } +} + +void Shader::activate() { + if (program > 0) { + glUseProgram(program); + } +} + +void Shader::link_program(GLuint vert, GLuint frag) { + program = glCreateProgram(); + glAttachShader(program, vert); + glAttachShader(program, frag); + + glLinkProgram(program); + GLint program_linked; + glGetProgramiv(program, GL_LINK_STATUS, &program_linked); + if (program_linked != GL_TRUE) + { + GLsizei log_length = 0; + GLchar message[1024]; + glGetProgramInfoLog(program, 1024, &log_length, message); + printf("Failed to link program: %s\n", message); + program = 0; + } +} + +GLuint Shader::load_and_compile_shader(const std::string &filepath, GLenum shader_type) { + std::string src = load_shader_from_file(filepath); + const char *shader_src = src.c_str(); + + GLuint shader = glCreateShader(shader_type); + glShaderSource(shader, 1, &shader_src, NULL); + glCompileShader(shader); + + GLint shader_compiled; + glGetShaderiv(shader, GL_COMPILE_STATUS, &shader_compiled); + if (shader_compiled != GL_TRUE) + { + GLsizei log_length = 0; + GLchar message[1024]; + glGetShaderInfoLog(shader, 1024, &log_length, message); + printf("Failed to compile %s shader: %s\n", get_shader_type_string(shader_type), message); + return 0; + } + + return shader; +} + +std::string Shader::load_shader_from_file(const std::string &filepath) { FILE *fp = fopen(filepath.c_str(), "r"); if (!fp) { return ""; @@ -211,3 +238,33 @@ std::string load_shader(const std::string &filepath) { return output; } + +const char *Shader::get_shader_type_string(GLenum shader_type) { + const char *output; + + switch (shader_type) { + case GL_COMPUTE_SHADER: + output = "compute"; + break; + case GL_VERTEX_SHADER: + output = "vertex"; + break; + case GL_TESS_CONTROL_SHADER: + output = "tess_control"; + break; + case GL_TESS_EVALUATION_SHADER: + output = "tess_evaluation"; + break; + case GL_GEOMETRY_SHADER: + output = "geometry"; + break; + case GL_FRAGMENT_SHADER: + output = "fragment"; + break; + default: + output = "UNKNOWN"; + break; + } + + return output; +}