Add basic Shader class

This commit is contained in:
Abdelrahman Said 2024-11-03 15:09:22 +00:00
parent 579d8c3b1a
commit 1c4587cd35

View File

@ -39,7 +39,18 @@ enum exit_codes : int {
EXIT_CODE_GLAD_LOADER_FAILED, 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() { int main() {
if (SDL_Init(SDL_INIT_EVERYTHING) != 0) { if (SDL_Init(SDL_INIT_EVERYTHING) != 0) {
@ -105,52 +116,7 @@ int main() {
glDisableVertexAttribArray(0); glDisableVertexAttribArray(0);
glDisableVertexAttribArray(1); glDisableVertexAttribArray(1);
std::string vs_shader = load_shader("shaders/vert.glsl"); Shader main_shader {"shaders/vert.glsl", "shaders/frag.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);
bool running = true; bool running = true;
SDL_Event event = {}; SDL_Event event = {};
@ -182,7 +148,7 @@ int main() {
glClearColor(0.2f, 0.3f, 0.3f, 1.0f); glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT); glClear(GL_COLOR_BUFFER_BIT);
glUseProgram(program); main_shader.activate();
glBindVertexArray(vao); glBindVertexArray(vao);
glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_INT, NULL); glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_INT, NULL);
@ -196,7 +162,68 @@ int main() {
return EXIT_CODE_SUCCESS; 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"); FILE *fp = fopen(filepath.c_str(), "r");
if (!fp) { if (!fp) {
return ""; return "";
@ -211,3 +238,33 @@ std::string load_shader(const std::string &filepath) {
return output; 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;
}