From bc212b29279c3af22c37e00b682951816c2d5dab Mon Sep 17 00:00:00 2001 From: Naman Kumar Jaiswal <128512002+Jaiswal-on-Fire@users.noreply.github.com> Date: Sun, 4 Jun 2023 06:40:47 +0530 Subject: [PATCH] Committing Assignment 1 --- Main.cpp | 77 ++++++++++++++++++++++++ Renderer.cpp | 163 +++++++++++++++++++++++++++++++++++++++++++++++++++ Renderer.h | 58 ++++++++++++++++++ Shader.cpp | 130 ++++++++++++++++++++++++++++++++++++++++ Shader.h | 32 ++++++++++ 5 files changed, 460 insertions(+) create mode 100644 Main.cpp create mode 100644 Renderer.cpp create mode 100644 Renderer.h create mode 100644 Shader.cpp create mode 100644 Shader.h diff --git a/Main.cpp b/Main.cpp new file mode 100644 index 0000000..ed1edd0 --- /dev/null +++ b/Main.cpp @@ -0,0 +1,77 @@ +#include +#include "Config.h" +#include "rendering/Renderer.h" +#include "rendering/Shader.h" +Renderer renderer; + +// Task 3.1 defining vertices +float tr1[] = { + -0.5f, -0.5f, 0.0f, + 0.2f, -0.5f, 0.0f, + 0.9f, 0.7f, 0.0f, + 0.0f, 0.5f, 0.0f, + -0.8f, -0.8f, 0.0f }; +unsigned int indices1[] = { + 0,1,2,0,3,4}; +VertexArray varray; + +int main() +{ + renderer.initialise_glfw(); + if (!renderer.create_window()) + { + return -1; + } + + renderer.setup_window_data(); + Shader shdr("../../shaders/defaultShader.vs", "../../shaders/defaultShader.fs"); + + varray.generate_buffers(); + varray.bind_vao(); + // plotting triangles task 3.1 + varray.bind_vbo(6, 3 * sizeof(float), tr1); + varray.bind_ebo(6, indices1); + varray.set_attribute_array(0, 3, 3 * sizeof(float)); + varray.unbind_vbo(); + varray.unbind_vao(); + + renderer.start_timer(); + while (!renderer.close_window()) + { + renderer.new_frame(); + std::cout << renderer.deltaTime << " " << (int)(1.0f / renderer.deltaTime) << std::endl; + + // time ratio is used to vary the RGB values Task 2 + float time = (0.5*glfwGetTime() - (floor)(0.5*glfwGetTime()))*2; + if (renderer.check_key(GLFW_KEY_ESCAPE)) + { + glfwSetWindowShouldClose(renderer.window, true); + } + if (renderer.check_key(GLFW_KEY_R)) + { + glClearColor(1.0f*time, 0.0f, 0.0f, 1.0f); + } + else if (renderer.check_key(GLFW_KEY_G)) + { + glClearColor(0.0f, 1.0f*time, 0.0f, 1.0f); + } + else if (renderer.check_key(GLFW_KEY_B)) + { + glClearColor(0.0f, 0.0f, 1.0f*time, 1.0f); + } + else + { + glClearColor(0.2f, 0.1f, 0.3f, 1.0f); + } + glClear(GL_COLOR_BUFFER_BIT); + // Drawing Shapes and Objects + shdr.use(); + // varray.draw_triangle(3, 0); + varray.draw_indices(6); + // End of Frame + renderer.swap_buffers(false); + } + + renderer.terminate_glfw(); + return 0; +} diff --git a/Renderer.cpp b/Renderer.cpp new file mode 100644 index 0000000..c4a5d90 --- /dev/null +++ b/Renderer.cpp @@ -0,0 +1,163 @@ +#include "rendering/Renderer.h" + +Renderer::Renderer(int major_, int minor_, int width_, int height_) +{ + major = major_; + minor = minor_; + width = width_; + height = height_; +} + +void Renderer::initialise_glfw() +{ + glfwInit(); + glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, major); + glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, minor); + glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); +#if __APPLE__ + glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE); +#endif +} + +void Renderer::terminate_glfw() +{ + glfwTerminate(); +} + +bool Renderer::create_window() +{ + // glfwGetPrimaryMonitor() sets window to full Screen Task 1.1 + window = glfwCreateWindow(width, height, WINDOW_NAME, glfwGetPrimaryMonitor(), NULL); + //window = glfwCreateWindow(width, height, WINDOW_NAME, NULL, NULL); + + // glfwSetWindowAspectRatio sets aspect ratio to 16/9 Task 1.2 + glfwSetWindowAspectRatio(window, 16, 9); + + // glfwSetWindowSizeLimits sets window maximum and minimum resolutions Task 1.3 + glfwSetWindowSizeLimits(window, 320, 180, 1600, 900); + // min area is 320 by 180 + // max area is 1600 by 900 + + if (window == NULL) + { + std::cout << "Failed to create GLFW window" << std::endl; + terminate_glfw(); + return false; + } + return true; +} + +void Renderer::setup_window_data() +{ + glfwMakeContextCurrent(window); + glfwSetFramebufferSizeCallback(window, framebuffer_size_callback); + + if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress)) + { + std::cout << "Failed to initialize GLAD" << std::endl; + } +} + +bool Renderer::close_window() +{ + return glfwWindowShouldClose(window); +} + +void Renderer::swap_buffers(bool lockFrameRate) +{ + glfwSwapBuffers(window); + glfwPollEvents(); + + if (!lockFrameRate) + { + glfwSwapInterval(0); + } + else + { + glfwSwapInterval(1); + } +} + +bool Renderer::check_key(int key) +{ + return (glfwGetKey(window, key) == GLFW_PRESS); +} + +void Renderer::start_timer() +{ + currentTime = glfwGetTime(); + previousTime = currentTime; + deltaTime = 0.0f; +} + +void Renderer::new_frame() +{ + currentTime = glfwGetTime(); + deltaTime = currentTime - previousTime; + previousTime = currentTime; +} + +//------------------------------------------------------------ + +void framebuffer_size_callback(GLFWwindow *window, int width, int height) +{ + glViewport(0, 0, width, height); +} + +//--------------------------------------------------------- + +void VertexArray::generate_buffers() +{ + glGenVertexArrays(1, &VAO); + glGenBuffers(1, &VBO); + glGenBuffers(1, &EBO); +} +void VertexArray::bind_vao() +{ + glBindVertexArray(VAO); +} +void VertexArray::unbind_vao() +{ + glBindVertexArray(0); +} +void VertexArray::bind_vbo(int vertexCount, GLsizeiptr stride, void *pointer) +{ + glBindBuffer(GL_ARRAY_BUFFER, VBO); + glBufferData(GL_ARRAY_BUFFER, vertexCount * stride, pointer, GL_STATIC_DRAW); +} +void VertexArray::unbind_vbo() +{ + glBindBuffer(GL_ARRAY_BUFFER, 0); +} +void VertexArray::bind_ebo(int indexCount, void *pointer) +{ + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO); + glBufferData(GL_ELEMENT_ARRAY_BUFFER, indexCount * sizeof(unsigned int), pointer, GL_STATIC_DRAW); +} +void VertexArray::unbind_ebo() +{ + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); +} +void VertexArray::set_attribute_array(int layoutLayer, int count, GLsizeiptr stride, const void *pointer) +{ + glEnableVertexAttribArray(layoutLayer); + glVertexAttribPointer(layoutLayer, count, GL_FLOAT, GL_FALSE, stride, pointer); +} +void VertexArray::draw_triangle(int count, int startIndex) +{ + bind_vao(); + glDrawArrays(GL_TRIANGLES, startIndex, count); + unbind_vao(); +} +void VertexArray::draw_indices(int indexCount) +{ + bind_vao(); + glDrawElements(GL_TRIANGLES, indexCount, GL_UNSIGNED_INT, 0); + unbind_vao(); +} +void VertexArray::free_data() +{ + glDeleteVertexArrays(1, &VAO); + glDeleteBuffers(1, &VBO); + glDeleteBuffers(1, &EBO); +} \ No newline at end of file diff --git a/Renderer.h b/Renderer.h new file mode 100644 index 0000000..ddea77c --- /dev/null +++ b/Renderer.h @@ -0,0 +1,58 @@ +#ifndef RENDERER_H +#define RENDERER_H +#include +#include "Config.h" +#include "thirdparty/glad/glad.h" +#include "thirdparty/GLFW/glfw3.h" + +class VertexArray +{ +private: +public: + unsigned int VAO, VBO, EBO; + void generate_buffers(); + void bind_vao(); + void bind_vbo(int vertexCount, GLsizeiptr stride, void *pointer); + void bind_ebo(int indexCount, void *pointer); + void unbind_vao(); + void unbind_vbo(); + void unbind_ebo(); + void set_attribute_array(int layoutLayer, int count, GLsizeiptr stride, const void *pointer = (void *)0); + void draw_triangle(int count, int startIndex); + void draw_indices(int indexCount); + void free_data(); +}; + +// Rendering class +class Renderer +{ +private: + float previousTime; + float currentTime; + +public: + int major; + int minor; + int width; + int height; + + float deltaTime; + + GLFWwindow *window; + + Renderer(int major_ = OPENGL_MAJOR_VERSION, int minor_ = OPENGL_MINOR_VERSION, int width_ = WINDOW_WIDTH, int height_ = WINDOW_HEIGHT); + void initialise_glfw(); + void terminate_glfw(); + + bool create_window(); + void setup_window_data(); + bool close_window(); + void swap_buffers(bool lockFrameRate); + bool check_key(int key); + void start_timer(); + void new_frame(); +}; + +void framebuffer_size_callback(GLFWwindow *window, int width, int height); + +#endif \ No newline at end of file diff --git a/Shader.cpp b/Shader.cpp new file mode 100644 index 0000000..0c520d8 --- /dev/null +++ b/Shader.cpp @@ -0,0 +1,130 @@ +#include "rendering/Shader.h" + +Shader::Shader() +{ +} + +Shader::Shader(const char *vertexPath, const char *fragmentPath) +{ + create_shader(vertexPath, fragmentPath); +} + +void Shader::create_shader(const char *vertexPath, const char *fragmentPath) +{ + std::string vertexCode; + std::string fragmentCode; + + std::ifstream vertexShaderFile; + std::ifstream fragmentShaderFile; + + vertexShaderFile.exceptions(std::ifstream::failbit || std::ifstream::badbit); + fragmentShaderFile.exceptions(std::ifstream::failbit || std::ifstream::badbit); + + try + { + vertexShaderFile.open(vertexPath); + fragmentShaderFile.open(fragmentPath); + + std::stringstream vertexShaderStream, fragmentShaderStream; + + vertexShaderStream << vertexShaderFile.rdbuf(); + fragmentShaderStream << fragmentShaderFile.rdbuf(); + + vertexShaderFile.close(); + fragmentShaderFile.close(); + + vertexCode = vertexShaderStream.str(); + fragmentCode = fragmentShaderStream.str(); + } + catch (std::ifstream::failure e) + { + std::cout << "Error Shader File Not loaded successfully" << std::endl; + } + + unsigned int vertex, fragment; + vertex = compile_shader(vertexCode.c_str(), VERTEX_SHADER); + + if (check_compile_errors(vertex, VERTEX_SHADER)) + { + return; + } + fragment = compile_shader(fragmentCode.c_str(), FRAGMENT_SHADER); + + if (check_compile_errors(fragment, FRAGMENT_SHADER)) + { + return; + } + + id = glCreateProgram(); + glAttachShader(id, vertex); + glAttachShader(id, fragment); + + glLinkProgram(id); + + if (check_compile_errors(id, COMBINED_SHADER)) + { + return; + } + + glDeleteShader(vertex); + glDeleteShader(fragment); +} + +unsigned int Shader::compile_shader(const char *code, SHADER_TYPE type) +{ + unsigned int shader; + + if (type == VERTEX_SHADER) + { + shader = glCreateShader(GL_VERTEX_SHADER); + } + else if (type == FRAGMENT_SHADER) + { + shader = glCreateShader(GL_FRAGMENT_SHADER); + } + + glShaderSource(shader, 1, &code, NULL); + glCompileShader(shader); + return shader; +} + +void Shader::use() +{ + glUseProgram(id); +} + +void Shader::free_data() +{ + glDeleteProgram(id); +} + +bool Shader::check_compile_errors(unsigned int shader, SHADER_TYPE type) +{ + int success; + + char infoLog[1024]; + + if (type == COMBINED_SHADER) + { + glGetProgramiv(shader, GL_LINK_STATUS, &success); + + if (!success) + { + glGetProgramInfoLog(shader, 1024, NULL, infoLog); + std::cout << "ERROR::SHADER::PROGRAM::LINKING FAILED OF TYPE" << std::endl + << infoLog << std::endl; + } + } + else + { + glGetShaderiv(shader, GL_COMPILE_STATUS, &success); + + if (!success) + { + glGetShaderInfoLog(shader, 1024, NULL, infoLog); + std::cout << "ERROR::SHADER::COMPILE::LINKING FAILED OF TYPE" << std::endl + << infoLog << std::endl; + } + } + return success == 0; +} diff --git a/Shader.h b/Shader.h new file mode 100644 index 0000000..dead94b --- /dev/null +++ b/Shader.h @@ -0,0 +1,32 @@ +#ifndef SHADER_H +#define SHADER_H + +#include "thirdparty/glad/glad.h" + +#include +#include +#include +#include + + +enum SHADER_TYPE {VERTEX_SHADER, FRAGMENT_SHADER, COMBINED_SHADER}; + +class Shader +{ + public: + unsigned int id; + + Shader(); + Shader(const char* vertexPath, const char* fragmentPath); + void create_shader(const char* vertexPath, const char* fragmentPath); + unsigned int compile_shader(const char* code, SHADER_TYPE type); + void use(); + void free_data(); + + private: + bool check_compile_errors(unsigned int shader, SHADER_TYPE type); + + +}; + +#endif \ No newline at end of file