From a42eabd69477a166d996291f242b048d0fae225a Mon Sep 17 00:00:00 2001 From: Vitor Fernandes Date: Sun, 21 Jun 2020 21:46:07 +0100 Subject: [PATCH] Abstracting shaders --- src/opengl/CMakeLists.txt | 4 ++ src/opengl/Shader.cpp | 125 +++++++++++++++++++++++++++++++++++ src/opengl/Shader.h | 33 +++++++++ src/opengl/VertexBuffer.h | 6 ++ src/opengl/gl1.cpp | 136 +++++++------------------------------- src/opengl/utils.h | 8 +++ 6 files changed, 201 insertions(+), 111 deletions(-) create mode 100644 src/opengl/Shader.cpp create mode 100644 src/opengl/Shader.h create mode 100644 src/opengl/utils.h diff --git a/src/opengl/CMakeLists.txt b/src/opengl/CMakeLists.txt index 0bc85a5..fbfcfc7 100644 --- a/src/opengl/CMakeLists.txt +++ b/src/opengl/CMakeLists.txt @@ -4,12 +4,15 @@ find_package(glfw3 3.3 REQUIRED) #find_package(GLEW REQUIRED) # Search for OpenGL find_package(OpenGL REQUIRED) +add_compile_definitions(IS_DEBUG=1) + # Add gl1 executable build from gl1.cpp, glew.c and Renderer.cpp add_executable( gl1 gl1.cpp + Shader.cpp Renderer.cpp VertexBuffer.cpp IndexBuffer.cpp @@ -17,6 +20,7 @@ add_executable( glew.c ) + # Link gl1 with glew #target_link_libraries(gl1 glew) # Link gl1 with glfw lib diff --git a/src/opengl/Shader.cpp b/src/opengl/Shader.cpp new file mode 100644 index 0000000..30535dd --- /dev/null +++ b/src/opengl/Shader.cpp @@ -0,0 +1,125 @@ +#pragma once + +#include +#include +#include + +#include "Shader.h" +#include "Renderer.h" +#include "utils.h" + +Shader::Shader(const std::string &filepath) + : m_FilePath(filepath), m_RendererID(0) +{ + //ShaderProgramSource source = ParseShader(m_FilePath); + //m_RendererID = CreateShader(source.VertexSource, source.FragmentSource); +} + + +Shader::~Shader() +{ +} + +void Shader::Bind() +{ +} + +void Shader::Unbind() +{ +} + +//Set uniforms +void Shader::SetUniform4f(const std::string &name, float v0, float v1, float v2, float v3) +{ +} +unsigned int Shader::GetUniformLocation(const std::string &name) +{ +} + +/** + * Creates both shaders, links them and returns an identifier + */ +unsigned int Shader::CreateShader(const std::string &vertexShader, const std::string &fragmentShader) +{ + unsigned int program = glCreateProgram(); + unsigned int vs = CompileShader(GL_VERTEX_SHADER, vertexShader); + unsigned int fs = CompileShader(GL_FRAGMENT_SHADER, fragmentShader); + + glAttachShader(program, vs); + glAttachShader(program, fs); + glLinkProgram(program); + glValidateProgram(program); + + glDeleteShader(vs); + glDeleteShader(fs); + + return program; +} + +unsigned int Shader::CompileShader(unsigned int type, const std::string &source) +{ + unsigned int id = glCreateShader(type); + LOG("Shader ID: " << id); + const char *const src = source.c_str(); + LOG("Source: " << std::endl + << src << std::endl); + glShaderSource(id, 1, &src, nullptr); + + int result; + glGetShaderiv(id, GL_COMPILE_STATUS, &result); + + if (result == GL_FALSE) + { + int length; + glGetShaderiv(id, GL_INFO_LOG_LENGTH, &length); + + LOG("Length: " << length); + + char *message = (char *)malloc(length * sizeof(char)); + glGetShaderInfoLog(id, length, &length, message); + + LOG("Failed to compile " + << (type == GL_VERTEX_SHADER ? "vertex" : "fragment") << " shader: " << std::endl); + + LOG(message); + free(message); + glDeleteProgram(id); + return 0; + } + return id; +} + +ShaderProgramSource Shader::ParseShader(const std::string &path) +{ + std::ifstream stream(path); + std::string line; + enum class ShaderType + { + NONE = -1, + VERTEX = 0, + FRAGMENT = 1 + }; + std::stringstream ss[2]; + ShaderType type = ShaderType::NONE; + while (getline(stream, line)) + { + if (line.find("#shader") != std::string::npos) + { + if (line.find("vertex") != std::string::npos) + { + //vertex + type = ShaderType::VERTEX; + } + else if (line.find("fragment") != std::string::npos) + { + //Fragment + type = ShaderType::FRAGMENT; + } + } + else + { + ss[(int)type] << line << '\n'; + } + } + return {ss[0].str(), ss[1].str()}; +} \ No newline at end of file diff --git a/src/opengl/Shader.h b/src/opengl/Shader.h new file mode 100644 index 0000000..679d2b6 --- /dev/null +++ b/src/opengl/Shader.h @@ -0,0 +1,33 @@ +#pragma once + +#include + +struct ShaderProgramSource +{ + std::string VertexSource; + std::string FragmentSource; +}; + +/** + * Class to abstrac shaders + */ +class Shader +{ +private: + unsigned int m_RendererID; + std::string m_FilePath; + ShaderProgramSource ParseShader(const std::string &filepath); + unsigned int CreateShader(const std::string &vertexShader, const std::string &fragmentShader); + unsigned int CompileShader(unsigned int type, const std::string &source); + unsigned int GetUniformLocation(const std::string &name); + +public: + Shader(const std::string &filepath); + ~Shader(); + + void Bind(); + void Unbind(); + + //Set uniforms + void SetUniform4f(const std::string &name, float v0, float v1, float v2, float v3); +}; \ No newline at end of file diff --git a/src/opengl/VertexBuffer.h b/src/opengl/VertexBuffer.h index dae3998..fd5e33c 100644 --- a/src/opengl/VertexBuffer.h +++ b/src/opengl/VertexBuffer.h @@ -1,4 +1,5 @@ #pragma once +#include class VertexBuffer { @@ -11,5 +12,10 @@ public: void Bind() const; void Unbind() const; + + //Overload to enable toString operations + friend std::ostream& operator<<(std::ostream &stream, VertexBuffer const &vb){ + return stream << "[VertexBuffer rendererID=" << vb.m_RendererID; + } }; diff --git a/src/opengl/gl1.cpp b/src/opengl/gl1.cpp index 1b29b70..6204462 100644 --- a/src/opengl/gl1.cpp +++ b/src/opengl/gl1.cpp @@ -4,131 +4,44 @@ #include #include #include + +#include "Shader.h" #include "Renderer.h" #include "VertexBuffer.h" #include "IndexBuffer.h" #include "VertexArray.h" +#include "utils.h" -typedef unsigned int uint; - -struct ShaderProgramSource -{ - std::string VertexSource; - std::string FragmentSource; -}; - -const std::string SHADERS_PATH = "src/opengl/res/shaders/Basic.shader"; - -static ShaderProgramSource ParseShader(const std::string path) -{ - std::ifstream stream(path); - std::string line; - enum class ShaderType - { - NONE = -1, - VERTEX = 0, - FRAGMENT = 1 - }; - std::stringstream ss[2]; - ShaderType type = ShaderType::NONE; - while (getline(stream, line)) - { - if (line.find("#shader") != std::string::npos) - { - if (line.find("vertex") != std::string::npos) - { - //vertex - type = ShaderType::VERTEX; - } - else if (line.find("fragment") != std::string::npos) - { - //Fragment - type = ShaderType::FRAGMENT; - } - } - else - { - ss[(int)type] << line << '\n'; - } - } - return {ss[0].str(), ss[1].str()}; -} - -static uint CompileShader(uint type, const std::string &source) -{ - uint id = glCreateShader(type); - std::cout << "Shader ID: " << id << std::endl; - const char *const src = source.c_str(); - - //std::cout << "Source: " << std::endl << src << std::endl << std::endl; - glShaderSource(id, 1, &src, nullptr); - - int result; - glGetShaderiv(id, GL_COMPILE_STATUS, &result); - - if (result == GL_FALSE) - { - int length; - glGetShaderiv(id, GL_INFO_LOG_LENGTH, &length); - std::cout << "Length: " << length << std::endl; - char *message = (char *)malloc(length * sizeof(char)); - glGetShaderInfoLog(id, length, &length, message); - - std::cout << "Failed to compile " - << (type == GL_VERTEX_SHADER ? "vertex" : "fragment") << " shader: " << std::endl; - - std::cout << message << std::endl; - free(message); - glDeleteProgram(id); - return 0; - } - - return id; -}; - -/** - * Creates both shaders, links them and returns an identifier - */ -static uint CreateShader(const std::string &vertexShader, const std::string &fragmentShader) -{ - uint program = glCreateProgram(); - uint vs = CompileShader(GL_VERTEX_SHADER, vertexShader); - uint fs = CompileShader(GL_FRAGMENT_SHADER, fragmentShader); - - glAttachShader(program, vs); - glAttachShader(program, fs); - glLinkProgram(program); - glValidateProgram(program); - - glDeleteShader(vs); - glDeleteShader(fs); - - return program; -}; +//const std::string SHADERS_PATH = "src/opengl/res/shaders/Basic.shader"; int main(void) { + LOG("Start OpenGL Demo"); GLFWwindow *window; //glDebugMessageCallback(ErrorGLCallback,0); Enable when glew installed properly /* Initialize the library */ + LOG("Initialize glfw"); if (!glfwInit()) return -1; /* Create a windowed mode window and its OpenGL context */ + LOG("Create Window"); window = glfwCreateWindow(640, 480, "OpenGL Window", NULL, NULL); if (!window) { + LOG("Terminate because not window"); glfwTerminate(); return -1; } /* Make the window's context current */ + LOG("GLFW Make context"); glfwMakeContextCurrent(window); glfwSwapInterval(1); //Print opengl version - std::cout << glGetString(GL_VERSION) << std::endl; + LOG("GL_VERSION: " << glGetString(GL_VERSION)); float positions[] = { @@ -142,26 +55,26 @@ int main(void) //Create buffer //Buffer id - VertexArray va ; + + LOG("VertexArray defining"); + VertexArray va; + LOG("VertexArray defined"); + + LOG("VertexBuffer to be created"); VertexBuffer vb(positions, 4 * 2 * sizeof(float)); + //LOG("Create VertexBuffer: " << vb); VertexBufferLayout layout; layout.Push(2); va.AddBuffer(vb,layout); IndexBuffer ib(indexes,6); - ShaderProgramSource source = ParseShader(SHADERS_PATH); - uint shader = CreateShader(source.VertexSource, source.FragmentSource); - GLCall(glUseProgram(shader)); //Find the shader uniform color - int uniform_location = glGetUniformLocation(shader, "u_color"); + //int uniform_location = glGetUniformLocation(shader, "u_color"); - if (uniform_location == -1) - { - std::cout << "Error fetching uniform location" << std::endl; - } + //if (uniform_location == -1) LOG("Error fetching uniform location"); float red = 0.0f; float increment = 0.05f; @@ -183,13 +96,13 @@ int main(void) //glDrawArrays(GL_TRIANGLES, 0, 12); //GLClearError(); - GLCall(glUseProgram(shader)); + //GLCall(glUseProgram(shader)); - GLCall(glUniform4f(uniform_location, 0.2f, 0.3f, 0.8f, 1.0f)); + //GLCall(glUniform4f(uniform_location, 0.2f, 0.3f, 0.8f, 1.0f)); - ib.Bind(); + //ib.Bind(); - GLCall(glDrawElements(GL_TRIANGLES, 6 * sizeof(uint), GL_UNSIGNED_INT, nullptr)); + //GLCall(glDrawElements(GL_TRIANGLES, 6 * sizeof(uint), GL_UNSIGNED_INT, nullptr)); if (red > 1.0f) increment = -0.05f; @@ -206,5 +119,6 @@ int main(void) } glfwTerminate(); + return 0; -} \ No newline at end of file +} diff --git a/src/opengl/utils.h b/src/opengl/utils.h new file mode 100644 index 0000000..a3f0ed6 --- /dev/null +++ b/src/opengl/utils.h @@ -0,0 +1,8 @@ +#pragma once +#include + +#if IS_DEBUG==1 + #define LOG(x) std::cout << x << std::endl +#else + #define LOG(x) +#endif