diff --git a/Blue/src/IndexBuffer.cpp b/Blue/src/IndexBuffer.cpp index 8bf79e3..18b95df 100644 --- a/Blue/src/IndexBuffer.cpp +++ b/Blue/src/IndexBuffer.cpp @@ -16,12 +16,12 @@ IndexBuffer::~IndexBuffer() glDeleteBuffers(1, &m_RendererID); } -void IndexBuffer::Bind() +void IndexBuffer::Bind() const { glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_RendererID); } -void IndexBuffer::Unbind() +void IndexBuffer::Unbind() const { glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); } \ No newline at end of file diff --git a/Blue/src/IndexBuffer.h b/Blue/src/IndexBuffer.h index 4b6babb..1f9834b 100644 --- a/Blue/src/IndexBuffer.h +++ b/Blue/src/IndexBuffer.h @@ -12,8 +12,8 @@ class IndexBuffer IndexBuffer(const unsigned *data, unsigned int count); ~IndexBuffer(); - void Bind(); - void Unbind(); + void Bind() const; + void Unbind() const; inline unsigned int GetCount() const { return m_Count; } }; \ No newline at end of file diff --git a/Blue/src/Renderer.cpp b/Blue/src/Renderer.cpp index 79a3c22..9df5124 100644 --- a/Blue/src/Renderer.cpp +++ b/Blue/src/Renderer.cpp @@ -1 +1,13 @@ -#include "Renderer.h" \ No newline at end of file +#include "Renderer.h" + +void Renderer::Clear() const +{ + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); +} +void Renderer::Draw(const VertexArray &va, const IndexBuffer &ib, const Shader &shader) const +{ + shader.Bind(); + va.Bind(); + ib.Bind(); + glDrawElements(GL_TRIANGLES, ib.GetCount(), GL_UNSIGNED_INT, nullptr); +} \ No newline at end of file diff --git a/Blue/src/Renderer.h b/Blue/src/Renderer.h index 81d52f6..dc551b3 100644 --- a/Blue/src/Renderer.h +++ b/Blue/src/Renderer.h @@ -1,4 +1,16 @@ #pragma once #include "GL/glew.h" -#include "GLFW/glfw3.h" \ No newline at end of file +#include "GLFW/glfw3.h" +#include "VertexArray.h" +#include "IndexBuffer.h" +#include "Shader.h" + +class Renderer +{ + +private: +public: + void Clear() const; + void Draw(const VertexArray &va, const IndexBuffer &ib, const Shader &shader) const; +}; \ No newline at end of file diff --git a/Blue/src/Shader.cpp b/Blue/src/Shader.cpp new file mode 100644 index 0000000..cb64d88 --- /dev/null +++ b/Blue/src/Shader.cpp @@ -0,0 +1,111 @@ +#include "Shader.h" +#include +#include +#include +#include + +Shader::Shader(const std::string &filepath) + : m_FilePath(filepath), m_RendererID(0) +{ + struct ShaderProgramSource shaderSource = ParseShader(filepath); + m_RendererID = CreateShader(shaderSource.VertexSource, shaderSource.FragmentSource); +} + +Shader::~Shader() +{ + glDeleteProgram(m_RendererID); +} + +struct ShaderProgramSource Shader::ParseShader(std::string filePath) +{ + enum class ShaderType + { + NONE = -1, + VERTEX = 0, + FRAGMENT = 1 + }; + std::ifstream stream(filePath); + std::string line; + 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) + type = ShaderType::VERTEX; + else if (line.find("fragment") != std::string::npos) + type = ShaderType::FRAGMENT; + } + else + ss[(int)type] << line << "\n"; + } + return {ss[0].str(), ss[1].str()}; +} + +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, fs); + glAttachShader(program, vs); + glLinkProgram(program); + + return program; +} + +unsigned int Shader::CompileShader(unsigned int type, const std::string &source) +{ + unsigned int id = glCreateShader(type); + const char *src = source.c_str(); + glShaderSource(id, 1, &src, NULL); + glCompileShader(id); + + int result; + glGetShaderiv(id, GL_COMPILE_STATUS, &result); + if (result == GL_FALSE) + { + int length; + glGetShaderiv(id, GL_INFO_LOG_LENGTH, &length); + char message[length]; + glGetShaderInfoLog(id, length, &length, message); + std::cout << "Failed to compile " << (type == GL_VERTEX_SHADER ? "vertex" : "fragment") << "shader" << std::endl; + std::cout << message << std::endl; + glDeleteShader(id); + return 0; + } + + return id; +} + +void Shader::Bind() const +{ + glUseProgram(m_RendererID); +} + +void Shader::Unbind() const +{ + glUseProgram(0); +} + +void Shader::SetUniform4f(const std::string &name, float v0, float v1, float v2, float v3) +{ + glUniform4f(GetUniformLocation(name), v0, v1, v2, v3); +} + +int Shader::GetUniformLocation(const std::string &name) +{ + if (m_UniformLocationCache.find(name) != m_UniformLocationCache.end()) + return m_UniformLocationCache[name]; + + int location = glGetUniformLocation(m_RendererID, name.c_str()); + if (location == -1) + std::cout << "Warning: Uniform " << name << " doesn't exist !" << std::endl; + else + m_UniformLocationCache[name] = location; + return location; +} \ No newline at end of file diff --git a/Blue/src/Shader.h b/Blue/src/Shader.h new file mode 100644 index 0000000..a590676 --- /dev/null +++ b/Blue/src/Shader.h @@ -0,0 +1,34 @@ +#pragma once +#include +#include "GL/glew.h" +#include "GLFW/glfw3.h" +#include + +struct ShaderProgramSource +{ + std::string VertexSource; + std::string FragmentSource; +}; + +class Shader +{ +private: + unsigned int m_RendererID; + std::string m_FilePath; + std::unordered_map m_UniformLocationCache; + +public: + Shader(const std::string &filepath); + ~Shader(); + + void Bind() const; + void Unbind() const; + + void SetUniform4f(const std::string &name, float v0, float v1, float v2, float v3); + +private: + unsigned int CompileShader(unsigned int type, const std::string &source); + int GetUniformLocation(const std::string &name); + unsigned int CreateShader(const std::string vertexShader, const std::string fragmentShader); + struct ShaderProgramSource ParseShader(std::string filePath); +}; \ No newline at end of file diff --git a/Blue/src/VertexArray.h b/Blue/src/VertexArray.h index 432250c..cf8ba98 100644 --- a/Blue/src/VertexArray.h +++ b/Blue/src/VertexArray.h @@ -14,5 +14,5 @@ class VertexArray void AddBuffer(const VertexBuffer &vb, const VertexBufferLayout &layout); void Bind() const; - void UnBind() const; + void Unbind() const; }; \ No newline at end of file diff --git a/Blue/src/VertexBufferLayout.cpp b/Blue/src/VertexBufferLayout.cpp index 9e09643..a6f46b9 100644 --- a/Blue/src/VertexBufferLayout.cpp +++ b/Blue/src/VertexBufferLayout.cpp @@ -3,20 +3,20 @@ template <> void VertexBufferLayout::Push(unsigned int count) { - m_Elements.push_back({count, GL_FLOAT, GL_FALSE}); + m_Elements.push_back({GL_FLOAT, count, GL_FALSE}); m_Stride += sizeof(GLfloat) * count; } template <> void VertexBufferLayout::Push(unsigned int count) { - m_Elements.push_back({count, GL_UNSIGNED_INT, GL_FALSE}); + m_Elements.push_back({GL_UNSIGNED_INT, count, GL_FALSE}); m_Stride += sizeof(GLuint) * count; } template <> void VertexBufferLayout::Push(unsigned int count) { - m_Elements.push_back({count, GL_UNSIGNED_BYTE, GL_TRUE}); + m_Elements.push_back({GL_UNSIGNED_BYTE, count, GL_TRUE}); m_Stride += sizeof(GLbyte) * count; } diff --git a/src/IndexBuffer.h b/src/IndexBuffer.h index 24bd70e..5f4a674 100644 --- a/src/IndexBuffer.h +++ b/src/IndexBuffer.h @@ -24,11 +24,11 @@ class IndexBuffer glDeleteBuffers(1, &m_RendererID); } - void Bind() + void Bind() const { glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_RendererID); } - void Unbind() + void Unbind() const { glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); } diff --git a/src/Renderer.h b/src/Renderer.h index 81d52f6..7ea026d 100644 --- a/src/Renderer.h +++ b/src/Renderer.h @@ -1,4 +1,29 @@ #pragma once #include "GL/glew.h" -#include "GLFW/glfw3.h" \ No newline at end of file +#include "GLFW/glfw3.h" +#include "VertexArray.h" +#include "IndexBuffer.h" +#include "Shader.h" + +class Renderer +{ + +private: +public: + void Clear() const; + void Draw(const VertexArray &va, const IndexBuffer &ib, const Shader &shader) const; +}; + +void Renderer::Draw(const VertexArray &va, const IndexBuffer &ib, const Shader &shader) const +{ + shader.Bind(); + va.Bind(); + ib.Bind(); + glDrawElements(GL_TRIANGLES, ib.GetCount(), GL_UNSIGNED_INT, nullptr); +} + +void Renderer::Clear() const +{ + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); +} \ No newline at end of file diff --git a/src/Shader.h b/src/Shader.h new file mode 100644 index 0000000..8999d18 --- /dev/null +++ b/src/Shader.h @@ -0,0 +1,143 @@ +#pragma once +#include +#include +#include +#include +#include +#include + +#include "GL/glew.h" +#include "GLFW/glfw3.h" +struct ShaderProgramSource +{ + std::string VertexSource; + std::string FragmentSource; +}; + +class Shader +{ +private: + unsigned int m_RendererID; + std::string m_FilePath; + std::unordered_map m_UniformLocationCache; + +public: + Shader(const std::string &filepath); + ~Shader(); + + void Bind() const; + void Unbind() const; + + void SetUniform4f(const std::string &name, float v0, float v1, float v2, float v3); + +private: + unsigned int CompileShader(unsigned int type, const std::string &source); + int GetUniformLocation(const std::string &name); + unsigned int CreateShader(const std::string vertexShader, const std::string fragmentShader); + struct ShaderProgramSource ParseShader(std::string filePath); +}; + +Shader::Shader(const std::string &filepath) + : m_FilePath(filepath), m_RendererID(0) +{ + struct ShaderProgramSource shaderSource = ParseShader(filepath); + m_RendererID = CreateShader(shaderSource.VertexSource, shaderSource.FragmentSource); +} + +Shader::~Shader() +{ + glDeleteProgram(m_RendererID); +} + +struct ShaderProgramSource Shader::ParseShader(std::string filePath) +{ + enum class ShaderType + { + NONE = -1, + VERTEX = 0, + FRAGMENT = 1 + }; + std::ifstream stream(filePath); + std::string line; + 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) + type = ShaderType::VERTEX; + else if (line.find("fragment") != std::string::npos) + type = ShaderType::FRAGMENT; + } + else + ss[(int)type] << line << "\n"; + } + return {ss[0].str(), ss[1].str()}; +} + +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, fs); + glAttachShader(program, vs); + glLinkProgram(program); + + return program; +} + +unsigned int Shader::CompileShader(unsigned int type, const std::string &source) +{ + unsigned int id = glCreateShader(type); + const char *src = source.c_str(); + glShaderSource(id, 1, &src, NULL); + glCompileShader(id); + + int result; + glGetShaderiv(id, GL_COMPILE_STATUS, &result); + if (result == GL_FALSE) + { + int length; + glGetShaderiv(id, GL_INFO_LOG_LENGTH, &length); + char message[length]; + glGetShaderInfoLog(id, length, &length, message); + std::cout << "Failed to compile " << (type == GL_VERTEX_SHADER ? "vertex" : "fragment") << "shader" << std::endl; + std::cout << message << std::endl; + glDeleteShader(id); + return 0; + } + + return id; +} + +void Shader::Bind() const +{ + glUseProgram(m_RendererID); +} + +void Shader::Unbind() const +{ + glUseProgram(0); +} + +void Shader::SetUniform4f(const std::string &name, float v0, float v1, float v2, float v3) +{ + glUniform4f(GetUniformLocation(name), v0, v1, v2, v3); +} + +int Shader::GetUniformLocation(const std::string &name) +{ + if (m_UniformLocationCache.find(name) != m_UniformLocationCache.end()) + return m_UniformLocationCache[name]; + int location = glGetUniformLocation(m_RendererID, name.c_str()); + if (location == -1) + std::cout << "Warning: Uniform " << name << " doesn't exist !" << std::endl; + else + m_UniformLocationCache[name] = location; + return location; +} \ No newline at end of file diff --git a/src/VertexArray.h b/src/VertexArray.h index 4e2719f..de1b419 100644 --- a/src/VertexArray.h +++ b/src/VertexArray.h @@ -14,7 +14,7 @@ class VertexArray void AddBuffer(const VertexBuffer &vb, const VertexBufferLayout &layout); void Bind() const; - void UnBind() const; + void Unbind() const; }; VertexArray::VertexArray() @@ -33,7 +33,7 @@ void VertexArray::Bind() const glBindVertexArray(m_RenedererID); } -void VertexArray::UnBind() const +void VertexArray::Unbind() const { glBindVertexArray(0); } @@ -48,7 +48,7 @@ void VertexArray::AddBuffer(const VertexBuffer &vb, const VertexBufferLayout &la { const auto &element = elements[i]; glEnableVertexAttribArray(i); - glVertexAttribPointer(i, element.count, element.type, element.normalize, layout.GetStride(), (const void *)offSet); + glVertexAttribPointer(i, element.count, element.type, element.normalize, layout.GetStride(), 0); offSet += element.count * VertexBufferElement::GetSizeOfType(element.type); } } \ No newline at end of file diff --git a/src/VertexBufferLayout.h b/src/VertexBufferLayout.h index e4614f9..8aa8d23 100644 --- a/src/VertexBufferLayout.h +++ b/src/VertexBufferLayout.h @@ -19,6 +19,7 @@ struct VertexBufferElement case GL_UNSIGNED_BYTE: return 1; } + // std::cout << type << std::endl; assert(false); return 0; } @@ -37,7 +38,7 @@ class VertexBufferLayout template void Push(unsigned int count) { - static_assert(false); + static_assert(true, "Assertion Failed"); } inline const std::vector GetElements() const { return m_Elements; } @@ -47,20 +48,20 @@ class VertexBufferLayout template <> void VertexBufferLayout::Push(unsigned int count) { - m_Elements.push_back({count, GL_FLOAT, GL_FALSE}); + m_Elements.push_back({GL_FLOAT, count, GL_FALSE}); m_Stride += count * VertexBufferElement::GetSizeOfType(GL_FLOAT); } template <> void VertexBufferLayout::Push(unsigned int count) { - m_Elements.push_back({count, GL_UNSIGNED_INT, GL_FALSE}); + m_Elements.push_back({GL_UNSIGNED_INT, count, GL_FALSE}); m_Stride += count * VertexBufferElement::GetSizeOfType(GL_UNSIGNED_INT); } template <> void VertexBufferLayout::Push(unsigned int count) { - m_Elements.push_back({count, GL_UNSIGNED_BYTE, GL_TRUE}); + m_Elements.push_back({GL_UNSIGNED_BYTE, count, GL_TRUE}); m_Stride += count * VertexBufferElement::GetSizeOfType(GL_UNSIGNED_BYTE); } diff --git a/src/a.out b/src/a.out index a2d944c..2193bb2 100755 Binary files a/src/a.out and b/src/a.out differ diff --git a/src/main.cpp b/src/main.cpp index d021e79..0b2b269 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -6,40 +6,8 @@ #include "Renderer.h" #include "VertexBuffer.h" #include "IndexBuffer.h" -// #include "VertexArray.h" - -struct ShaderProgramSource -{ - std::string VertexSource; - std::string FragmentSource; -}; -static struct ShaderProgramSource ParseShader(std::string filePath) -{ - enum class ShaderType - { - NONE = -1, - VERTEX = 0, - FRAGMENT = 1 - }; - std::ifstream stream(filePath); - std::string line; - 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) - type = ShaderType::VERTEX; - else if (line.find("fragment") != std::string::npos) - type = ShaderType::FRAGMENT; - } - else - ss[(int)type] << line << "\n"; - } - return {ss[0].str(), ss[1].str()}; -} +#include "VertexArray.h" +#include "Shader.h" static void GLClearError() { @@ -55,44 +23,6 @@ static void GLCheckError() } } -static unsigned int CompileShader(unsigned int type, const std::string &source) -{ - unsigned int id = glCreateShader(type); - const char *src = source.c_str(); - glShaderSource(id, 1, &src, NULL); - glCompileShader(id); - - int result; - glGetShaderiv(id, GL_COMPILE_STATUS, &result); - if (result == GL_FALSE) - { - int length; - glGetShaderiv(id, GL_INFO_LOG_LENGTH, &length); - char message[length]; - glGetShaderInfoLog(id, length, &length, message); - std::cout << "Failed to compile " << (type == GL_VERTEX_SHADER ? "vertex" : "fragment") << "shader" << std::endl; - std::cout << message << std::endl; - glDeleteShader(id); - return 0; - } - - return id; -} - -static unsigned int 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, fs); - glAttachShader(program, vs); - glLinkProgram(program); - - return program; -} - int main() { @@ -141,38 +71,38 @@ int main() glGenVertexArrays(1, &vao); glBindVertexArray(vao); - // VertexArray va; + VertexArray va; VertexBuffer vb(points, 12 * sizeof(float)); - // VertexBufferLayout layout; - // layout.Push(3); - // va.AddBuffer(vb, layout); + VertexBufferLayout layout; + layout.Push(3); + va.AddBuffer(vb, layout); - glEnableVertexAttribArray(0); - glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, NULL); + // glEnableVertexAttribArray(0); + // glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, NULL); IndexBuffer ib(indices, 6); - struct ShaderProgramSource shaderSource = ParseShader("Basic.shader"); - unsigned int shader = CreateShader(shaderSource.VertexSource, shaderSource.FragmentSource); + Shader shader("Basic.shader"); + shader.Bind(); - int location = glGetUniformLocation(shader, "u_Color"); - if (location == -1) - std::cout << "Location not found" << std::endl; - glUniform4f(location, 0.0f, 0.7f, 0.5f, 1.0f); + shader.SetUniform4f("u_Color", 0.0f, 0.7f, 0.5f, 1.0f); + + va.Unbind(); vb.Unbind(); - glUseProgram(0); - glBindVertexArray(0); + ib.Unbind(); + shader.Unbind(); + + Renderer renderer; float r = 0.0f, increment = 0.05f; while (!glfwWindowShouldClose(window)) { // wipe the drawing surface clear - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + renderer.Clear(); + + shader.Bind(); + shader.SetUniform4f("u_Color", r, 0.7f, 0.5f, 1.0f); - glUseProgram(shader); - glUniform4f(location, r, 0.7f, 0.5f, 1.0f); - glBindVertexArray(vao); - // va.Bind(); - ib.Bind(); + renderer.Draw(va, ib, shader); if (r > 1.0f) increment = -0.05; else if (r < 0.0f) @@ -180,8 +110,6 @@ int main() r += increment; - // draw points 0-3 from the currently bound VAO with current in-use shader - glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, nullptr); // update other events like input handling glfwPollEvents(); // put the stuff we've been drawing onto the display