]> code.bitgloo.com Git - clyne/gamedev2.git/commitdiff
Modified WindowSystem into full render system
authorAndy Belle-Isle <drumsetmonkey@gmail.com>
Sun, 1 Sep 2019 03:36:00 +0000 (23:36 -0400)
committerAndy Belle-Isle <drumsetmonkey@gmail.com>
Sun, 1 Sep 2019 03:36:00 +0000 (23:36 -0400)
This is does because EntityX doesn't guarantee system initialization order

src/engine.cpp
src/render.cpp [new file with mode: 0644]
src/render.hpp [new file with mode: 0644]
src/shader.cpp [new file with mode: 0644]
src/shader.hpp [new file with mode: 0644]
src/window.hpp [deleted file]

index 317e11616f365c84128fbd5b6f763746e6afed60..a89a876dfbb5346369056632ede9aadc2a521f6d 100644 (file)
@@ -22,8 +22,8 @@
 #include "engine.hpp"
 #include "gamerun.hpp"
 #include "input.hpp"
-#include "window.hpp"
 #include "script.hpp"
+#include "render.hpp"
 
 #include "components/Script.hpp"
 #include "components/Position.hpp"
@@ -32,7 +32,7 @@ int Engine::init(void)
 {
        systems.add<GameRunSystem>();
        systems.add<InputSystem>();
-       systems.add<WindowSystem>();
+    systems.add<RenderSystem>();
     systems.add<ScriptSystem>();
 
        systems.configure();
@@ -62,7 +62,7 @@ void Engine::logicLoop(void)
 void Engine::renderLoop(void)
 {
        while (shouldRun()) {
-               systems.update<WindowSystem>(0);
+               systems.update<RenderSystem>(0);
                std::this_thread::yield();
        }
 }
diff --git a/src/render.cpp b/src/render.cpp
new file mode 100644 (file)
index 0000000..30fd396
--- /dev/null
@@ -0,0 +1,159 @@
+/**
+ * @file render.cpp
+ *
+ * Copyright (C) 2019 Clyne Sullivan
+ * Copyright (C) 2019  Belle-Isle, Andrew <drumsetmonkey@gmail.com>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <render.hpp>
+
+void RenderSystem::configure([[maybe_unused]]entityx::EntityManager& entities,
+                             [[maybe_unused]]entityx::EventManager& events)
+{
+    init();
+}
+
+void RenderSystem::update([[maybe_unused]] entityx::EntityManager& entites,
+                          [[maybe_unused]] entityx::EventManager& events,
+                          [[maybe_unused]] entityx::TimeDelta dt)
+{
+    static GLfloat tri_data[] = {
+            -1.0, -1.0, 0.0,
+            1.0, -1.0, 0.0,
+            0.0, 1.0, 0.0,
+    };
+    
+    GLuint s = worldShader.getProgram();
+    GLuint v = worldShader.getUniform("view");
+    GLuint p = worldShader.getUniform("projection");
+    GLuint m = worldShader.getUniform("model");
+    GLuint a = worldShader.getAttribute("vertex");
+
+    /***********
+    *  SETUP  *
+    ***********/
+    
+    glm::mat4 view = glm::lookAt(glm::vec3(0.0f, 0.0f, 5.0f),  // Pos
+                                 glm::vec3(0.0f, 0.0f, 0.0f),  // Facing
+                                 glm::vec3(0.0f, 1.0f, 0.0f)); // Up
+
+    glm::mat4 projection = glm::perspective(45.0f, 
+                                            ((float)width/(float)height), 
+                                            0.01f, 
+                                            2048.0f);
+
+    glm::mat4 model = glm::mat4(1.0f);
+
+    glUseProgram(s);
+
+    glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
+    glEnable(GL_DEPTH_TEST);
+
+    glUniformMatrix4fv(v, 1, GL_FALSE, glm::value_ptr(view));
+    glUniformMatrix4fv(p, 1, GL_FALSE, glm::value_ptr(projection));
+    glUniformMatrix4fv(m, 1, GL_FALSE, glm::value_ptr(model));
+
+    glEnable(GL_CULL_FACE);
+    glEnable(GL_POLYGON_OFFSET_FILL);
+
+    glEnableVertexAttribArray(a);
+
+    /*************
+    *  DRAWING  *
+    *************/
+
+    GLuint tri_vbo;
+    
+    glGenBuffers(1, &tri_vbo);
+    glBindBuffer(GL_ARRAY_BUFFER, tri_vbo);
+    glBufferData(GL_ARRAY_BUFFER, sizeof(tri_data), tri_data, GL_STREAM_DRAW);
+
+    glVertexAttribPointer(a, 3, GL_FLOAT, GL_FALSE, 0, 0);
+    glDrawArrays(GL_TRIANGLES, 0, 3);
+    
+
+    /*************
+    *  CLEANUP  *
+    *************/
+    glDisableVertexAttribArray(a);
+
+    glDisable(GL_POLYGON_OFFSET_FILL);
+    glDisable(GL_CULL_FACE);
+
+    glUseProgram(0);
+
+    SDL_GL_SwapWindow(window.get());
+}
+
+int RenderSystem::init(void)
+{
+    // Select an OpenGL 4.3 profile.
+    SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 4);
+    SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 3);
+
+    if (SDL_InitSubSystem(SDL_INIT_VIDEO) != 0) {
+        std::cerr << "SDL video failed to initialize: "
+            << SDL_GetError() << std::endl;
+        return -1;
+    }
+
+    // Create window, managed by the unique_ptr
+    window.reset(SDL_CreateWindow(title,
+        SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED,
+        width, height,
+        SDL_WINDOW_OPENGL));
+
+    if (window.get() == nullptr) {
+        std::cerr << "SDL window creation failed: "
+            << SDL_GetError() << std::endl;
+        return -1;
+    }
+
+    context = SDL_GL_CreateContext(window.get());
+
+    GLenum err;
+    glewExperimental = GL_TRUE;
+    if((err=glewInit()) != GLEW_OK){
+        std::cerr << "GLEW was not able to initialize! Error: " << 
+            glewGetErrorString(err) << std::endl;
+        return -1;
+    }
+
+    SDL_GL_SetSwapInterval(0);
+
+    glEnable(GL_BLEND);
+    glEnable(GL_DEPTH_TEST);
+    //glDepthFunc(GL_LESS);
+    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); 
+
+    worldShader.createProgram("Shaders/world.vert", "Shaders/world.frag");
+
+    worldShader.addUniform("projection");
+    worldShader.addUniform("view");
+    worldShader.addUniform("model");
+
+    worldShader.addAttribute("vertex");
+
+    glEnableVertexAttribArray(worldShader.getAttribute("vertex"));
+    glUseProgram(worldShader.getProgram());
+
+    // TODO
+    //glPolygonOffset(1.0, 1.0);
+
+    glClearColor(0.6, 0.8, 1.0, 0.0);
+
+    return 0;
+}
diff --git a/src/render.hpp b/src/render.hpp
new file mode 100644 (file)
index 0000000..fa609a3
--- /dev/null
@@ -0,0 +1,79 @@
+/**
+ * @file render.hpp
+ * Handles all in game rendering
+ *
+ * Copyright (C) 2019 Clyne Sullivan
+ * Copyright (C) 2019  Belle-Isle, Andrew <drumsetmonkey@gmail.com>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef RENDER_HPP_
+#define RENDER_HPP_
+
+#include <entityx/entityx.h>
+
+#include <shader.hpp>
+
+#include <SDL2/SDL.h>
+
+#define GLM_FORCE_RADIANS
+#include <glm/glm.hpp>
+#include <glm/gtc/matrix_transform.hpp>
+#include <glm/gtc/type_ptr.hpp>
+#include <glm/gtc/noise.hpp>
+
+class RenderSystem : public entityx::System<RenderSystem>
+{
+private:
+       constexpr static const char *title = "gamedev2";
+       constexpr static int width = 640;
+       constexpr static int height = 480;
+
+       std::unique_ptr<SDL_Window, void (*)(SDL_Window *)> window;
+       SDL_GLContext context;
+
+    Shader worldShader;
+public:
+    RenderSystem(void):
+           window(nullptr, SDL_DestroyWindow)
+    {}
+
+    ~RenderSystem(void)
+    {
+           SDL_GL_DeleteContext(context);
+        SDL_Quit();
+    }
+
+    /**
+     * Prepares the system for running.
+     */
+    void configure([[maybe_unused]]entityx::EntityManager& entities,
+                   [[maybe_unused]]entityx::EventManager& events) final;
+    
+    /**
+     * Updates the render system.
+     */
+    void update([[maybe_unused]] entityx::EntityManager& entites,
+                [[maybe_unused]] entityx::EventManager& events,
+                [[maybe_unused]] entityx::TimeDelta dt) final;
+
+    /**
+     * Initializes the rendering system
+     * @return Zero on success, non-zero on error
+     */
+    int init(void);
+};
+
+#endif//RENDER_HPP_
diff --git a/src/shader.cpp b/src/shader.cpp
new file mode 100644 (file)
index 0000000..bb62ac9
--- /dev/null
@@ -0,0 +1,146 @@
+/**
+ * @file shader.cpp
+ *
+ * Copyright (C) 2019  Belle-Isle, Andrew <drumsetmonkey@gmail.com>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <shader.hpp>
+
+#include <fstream>
+#include <iostream>
+#include <vector>
+
+#include <SDL2/SDL.h>
+
+/*************
+*  PRIVATE  *
+*************/
+
+std::string Shader::readShader(std::string filepath)
+{
+    std::string contents = "";
+    std::ifstream file(filepath, std::ios::in);
+
+    if (!file.is_open()) {
+        std::cerr << "Could not read shader " << filepath << 
+                     ". Shader doesn't exist" << std::endl;
+        return "";
+    }
+
+    std::string line = "";
+    while (!file.eof()) {
+        std::getline(file, line);
+        contents.append(line + "\n");
+    }
+
+    file.close();
+    return contents;
+}
+
+GLuint Shader::createShader(std::string filepath, GLenum shaderType)
+{
+    GLuint shader = glCreateShader(shaderType);
+
+    std::string shaderStr = readShader(filepath);
+    const char* shaderSrc = shaderStr.c_str();
+
+    GLint result = GL_FALSE;
+    int logLength;
+
+    glShaderSource(shader, 1, &shaderSrc, NULL);
+    glCompileShader(shader);
+
+    glGetShaderiv(shader, GL_COMPILE_STATUS, &result);
+    glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &logLength);
+    std::vector<char> shaderError((logLength > 1) ? logLength : 1);
+    glGetShaderInfoLog(shader, logLength, NULL, &shaderError[0]);
+    std::cerr << &shaderError[0] << std::endl;
+
+    return shader;
+}
+
+/************
+*  PUBLIC  *
+************/
+
+GLuint Shader::createProgram(std::string vertexPath, std::string fragmentPath)
+{
+    GLuint vertex = createShader(vertexPath, GL_VERTEX_SHADER);
+    GLuint fragment = createShader(fragmentPath, GL_FRAGMENT_SHADER);
+
+    GLuint program = glCreateProgram();
+    glAttachShader(program, vertex);
+    glAttachShader(program, fragment);
+    glLinkProgram(program);
+
+    GLint result = GL_FALSE;
+    int logLength;
+
+    glGetProgramiv(program, GL_COMPILE_STATUS, &result);
+    glGetProgramiv(program, GL_INFO_LOG_LENGTH, &logLength);
+    std::vector<char> programError((logLength > 1) ? logLength : 1);
+    glGetProgramInfoLog(program, logLength, NULL, &programError[0]);
+    std::cerr << &programError[0] << std::endl;
+
+    glDeleteShader(vertex);
+    glDeleteShader(fragment);
+
+    this->program = program;
+
+    return program;
+}
+
+// TODO exceptions
+GLint Shader::addAttribute(std::string attrib)
+{
+    GLint attribute = glGetAttribLocation(program, attrib.c_str());
+
+    if (attribute == -1)
+        SDL_LogMessage(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_ERROR,
+                "Could not bind attribute %s", attrib.c_str());
+
+    attributes.emplace(attrib, attribute);
+    return attribute;
+}
+
+GLint Shader::addUniform(std::string unfi)
+{
+    GLint uniform = glGetUniformLocation(program, unfi.c_str());
+
+    if (uniform == -1)
+        SDL_LogMessage(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_ERROR,
+                "Could not bind uniform %s", unfi.c_str());
+
+    uniforms.emplace(unfi, uniform);
+    return uniform;
+}
+
+// TODO exceptions
+GLint Shader::getAttribute(std::string attrib)
+{
+    return attributes.at(attrib);
+}
+
+GLint Shader::getUniform(std::string unfi)
+{
+    return uniforms.at(unfi);
+}
+
+GLuint Shader::getProgram()
+{
+    return program;
+}
+
diff --git a/src/shader.hpp b/src/shader.hpp
new file mode 100644 (file)
index 0000000..e67a4a0
--- /dev/null
@@ -0,0 +1,107 @@
+/**
+ * @file shader.hpp
+ *
+ * Copyright (C) 2019  Belle-Isle, Andrew <drumsetmonkey@gmail.com>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef SHADER_HPP
+#define SHADER_HPP
+
+#include <string>
+#include <unordered_map>
+
+#include <GL/glew.h>
+
+class Shader
+{
+    private:
+        /**
+         * Reads the contents of a shader file and returns a c++ string
+         * object representing the contents
+         * @param The file path
+         * @return The shader contents
+         */
+        std::string readShader(std::string); 
+
+        /**
+         * Creates a shader from a filename and a shader type
+         * @param The file path containing the shader data
+         * @param What type of shader to create
+         * @return Memory address of shader location
+         */
+        GLuint createShader(std::string, GLenum);
+
+        GLuint program; /**< GPU Memory address of shader program */
+
+        /**
+         * Name of shader attributes and their corresponding memory
+         * locations in which the data exists
+         */
+        std::unordered_map<std::string, GLuint> attributes;
+        
+        /**
+         * Name of shader uniforms in and their corresponding memory
+         * locations in which the data exists
+         */
+        std::unordered_map<std::string, GLuint> uniforms;
+    public:
+        Shader(): program(-1) {}
+        /**
+         * Given the file paths of two shaders, create a shader program.
+         * @param v The file path of the vertex shader file.
+         * @param f The file path of the fragment shader file.
+         * @return The GPU Memory location of the shader program
+         */
+        GLuint createProgram(std::string v, std::string f); 
+
+        /**
+         * Finds and binds an attribute to the current shader if possible
+         * @param The attribute to bind in the shader
+         * @return The memory address of the new attribute, or -1 if the
+         * attribute doesn't exist in the shader
+         */
+        GLint addAttribute(std::string);
+        /**
+         * Finds and binds a uniform to the current shader if possible
+         * @param The uniform to bind in the shader
+         * @return The memory address of the new uniform, or -1 if the
+         * uniform doesn't exist in the shader
+         */
+        GLint addUniform(std::string);
+
+        /**
+         * Finds the GPU memory address of the given attribute in the shader
+         * program
+         * @param The attribute to find
+         * @return The attribute memory location, or -1 if it doesn't exist
+         */
+        GLint getAttribute(std::string);
+        /**
+         * Finds the GPU memory address of the given uniform in the shader
+         * program
+         * @param The uniform to find
+         * @return The uniform memory location, or -1 if it doesn't exist
+         */
+        GLint getUniform(std::string);
+
+        /**
+         * Gets the memory address of the program stored in this object
+         * @return The GPU memory address of the shader program stored
+         */
+        GLuint getProgram();
+};
+
+#endif // SHADER_HPP
diff --git a/src/window.hpp b/src/window.hpp
deleted file mode 100644 (file)
index ef6632a..0000000
+++ /dev/null
@@ -1,95 +0,0 @@
-/**
- * @file window.hpp
- * Manages window creation.
- *
- * Copyright (C) 2019 Clyne Sullivan
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program.  If not, see <https://www.gnu.org/licenses/>.
- */
-
-#ifndef WINDOW_HPP_
-#define WINDOW_HPP_
-
-#include <entityx/entityx.h>
-#include <SDL2/SDL.h>
-
-/**
- * @class WindowSystem
- * Handles the game's window.
- */
-class WindowSystem : public entityx::System<WindowSystem> {
-private:
-       constexpr static const char *title = "gamedev2";
-       constexpr static int width = 640;
-       constexpr static int height = 480;
-
-       std::unique_ptr<SDL_Window, void (*)(SDL_Window *)> window;
-       SDL_GLContext context;
-
-public:
-       WindowSystem(void) :
-               window(nullptr, SDL_DestroyWindow) {}
-
-       ~WindowSystem(void) {
-               SDL_GL_DeleteContext(context);
-       }
-
-       /**
-        * Creates and initializes the window.
-        * @return Zero on success, non-zero on error
-        */
-       int init(void) {
-               if (SDL_InitSubSystem(SDL_INIT_VIDEO) != 0) {
-                       std::cerr << "SDL video failed to initialize: "
-                               << SDL_GetError() << std::endl;
-                       return -1;
-               }
-
-               // Create window, managed by the unique_ptr
-               window.reset(SDL_CreateWindow(title,
-                       SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED,
-                       width, height,
-                       SDL_WINDOW_OPENGL));
-
-               if (window.get() == nullptr) {
-                       std::cerr << "SDL window creation failed: "
-                               << SDL_GetError() << std::endl;
-                       return -1;
-               }
-
-               context = SDL_GL_CreateContext(window.get());
-
-               return 0;
-       }
-
-       /**
-        * Prepares the system for running.
-        */
-       void configure([[maybe_unused]] entityx::EntityManager& entities,
-               [[maybe_unused]] entityx::EventManager& events) final {
-               init();
-       }
-
-       /**
-        * Updates/refreshes the window.
-        */
-       void update([[maybe_unused]] entityx::EntityManager& entities,
-               [[maybe_unused]] entityx::EventManager& events,
-               [[maybe_unused]] entityx::TimeDelta dt) final {
-               SDL_GL_SwapWindow(window.get());
-       }
-};
-
-#endif // WINDOW_HPP_
-