diff --git a/src/ShaderLoader.cpp b/src/ShaderLoader.cpp new file mode 100644 index 0000000..2c71c18 --- /dev/null +++ b/src/ShaderLoader.cpp @@ -0,0 +1,87 @@ +#include "ShaderLoader.h" + +ShaderLoader::ShaderLoader(const char *vertexPath, const char *fragmentPath) { + std::string vertexCode; + std::string fragmentCode; + + std::ifstream vShaderFile; + std::ifstream fShaderFile; + + vShaderFile.exceptions(std::ifstream::failbit | std::ifstream::badbit); + fShaderFile.exceptions(std::ifstream::failbit | std::ifstream::badbit); + try { + // Open Files + vShaderFile.open(vertexPath); + fShaderFile.open(fragmentPath); + std::stringstream vShaderStream, fShaderStream; + // read file's buffer contents into streams + vShaderStream << vShaderFile.rdbuf(); + fShaderStream << fShaderFile.rdbuf(); + // close file handlers + vShaderFile.close(); + fShaderFile.close(); + // convert stream into string + vertexCode = vShaderStream.str(); + fragmentCode = fShaderStream.str(); + } catch (std::string e) { + error.crash("Failed to read shaderfiles", e); + } + const char *vShaderCode = vertexCode.c_str(); + const char *fShaderCode = fragmentCode.c_str(); + + // Compile shaders + unsigned int vertex, fragment; + int success; + char infoLog[512]; + + // Vertex Shader + vertex = glCreateShader(GL_VERTEX_SHADER); + glShaderSource(vertex, 1, &vShaderCode, NULL); + glCompileShader(vertex); + // Try to communicate errors if they exist + glGetShaderInfoLog(vertex, 512, NULL, infoLog); + if (!success) { + glGetShaderInfoLog(vertex, 512, NULL, infoLog); + error.crash("Vertex shader compilation failed", infoLog); + } + + // create fragment shader + fragment = glCreateShader(GL_FRAGMENT_SHADER); + // compile fragment shader + glShaderSource(fragment, 1, &fShaderCode, NULL); + glCompileShader(fragment); + // https://learnopengl.com/Getting-started/Hello-Triangle + glGetShaderiv(fragment, GL_COMPILE_STATUS, &success); + if (!success) { + glGetShaderInfoLog(fragment, 512, NULL, infoLog); + error.crash("Fragment shader compilation failed", infoLog); + } + + // shader Program + ID = glCreateProgram(); + glAttachShader(ID, vertex); + glAttachShader(ID, fragment); + glLinkProgram(ID); + // print linking errors if any + glGetProgramiv(ID, GL_LINK_STATUS, &success); + if (!success) { + glGetProgramInfoLog(ID, 512, NULL, infoLog); + error.crash("Shader Linking failed", infoLog); + } + + // delete the shaders as they're linked into our program now and no longer + // necessary + glDeleteShader(vertex); + glDeleteShader(fragment); +} + +void ShaderLoader::use() { glUseProgram(ID); } +void ShaderLoader::setBool(const std::string &name, bool value) const { + glUniform1i(glGetUniformLocation(ID, name.c_str()), (int)value); +} +void ShaderLoader::setInt(const std::string &name, int value) const { + glUniform1i(glGetUniformLocation(ID, name.c_str()), value); +} +void ShaderLoader::setFloat(const std::string &name, float value) const { + glUniform1f(glGetUniformLocation(ID, name.c_str()), value); +} diff --git a/src/ShaderLoader.h b/src/ShaderLoader.h new file mode 100644 index 0000000..38a9d01 --- /dev/null +++ b/src/ShaderLoader.h @@ -0,0 +1,28 @@ +#pragma once +#include +// Make sure Glew is loaded first +#include +// File reader +#include "Error.h" +#include +#include +#include +#include + +class ShaderLoader { +private: + unsigned int ID; + Error error = Error("ShaderLoader"); + +public: + // constructor builds shader + ShaderLoader(const char *vertexPath, const char *fragmentPath); + + // use the shader + void use(); + + // utility uniform functions + void setBool(const std::string &name, bool value) const; + void setInt(const std::string &name, int value) const; + void setFloat(const std::string &name, float value) const; +}; diff --git a/src/main.cpp b/src/main.cpp index 098a490..b66a695 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -9,6 +9,8 @@ #include #include #include +// Shader +#include "ShaderLoader.h" // Include error class #include "Error.h" @@ -138,7 +140,6 @@ int main(int argc, char **argv) { // compile vertex shader glShaderSource(vertexShader, 1, &vertShaderSrc, NULL); glCompileShader(vertexShader); - // TODO: test the shader was compiled // https://learnopengl.com/Getting-started/Hello-Triangle int success; char infoLog[512]; @@ -154,7 +155,6 @@ int main(int argc, char **argv) { // compile fragment shader glShaderSource(fragmentShader, 1, &fragShaderSrc, NULL); glCompileShader(fragmentShader); - // TODO: test the shader was compiled // https://learnopengl.com/Getting-started/Hello-Triangle glGetShaderiv(fragmentShader, GL_COMPILE_STATUS, &success); if (!success) { @@ -190,6 +190,8 @@ int main(int argc, char **argv) { glDeleteShader(vertexShader); glDeleteShader(fragmentShader); + ShaderLoader shader("src/vertex.glsl", "src/fragment.glsl"); + // Game loop bool running = true; while (running) { @@ -205,7 +207,9 @@ int main(int argc, char **argv) { glClearColor(0.0f, 0.0f, 0.0f, 0.0f); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Make every shader/rendering call from this point on use our shader - glUseProgram(shaderProgram); + // glUseProgram(shaderProgram); + + shader.use(); // I think this is meant to be here but it breaks... // shove vertex array into buffer