diff options
-rw-r--r-- | .gitignore | 1 | ||||
-rw-r--r-- | LICENSE | 2 | ||||
-rw-r--r-- | README.md | 3 | ||||
-rw-r--r-- | include/RenderBackend/OpenGL/DeviceMemory.hpp | 3 | ||||
-rw-r--r-- | include/RenderBackend/OpenGL/ShaderProgram.hpp | 7 | ||||
-rw-r--r-- | include/RenderBackend/OpenGL/Uniform.hpp | 29 | ||||
-rw-r--r-- | include/Result.hpp | 12 | ||||
-rw-r--r-- | include/Triangle.hpp | 23 | ||||
-rw-r--r-- | include/Triangle2D.hpp | 16 | ||||
-rw-r--r-- | include/Vertex.hpp | 28 | ||||
-rw-r--r-- | include/Vertex2D.hpp | 18 | ||||
-rw-r--r-- | shaders/fragment.frag | 3 | ||||
-rw-r--r-- | shaders/vertex.vert | 8 | ||||
-rw-r--r-- | src/RenderBackend/OpenGL/DeviceMemory.cpp | 9 | ||||
-rw-r--r-- | src/RenderBackend/OpenGL/ShaderProgram.cpp | 19 | ||||
-rw-r--r-- | src/RenderBackend/OpenGL/Uniform.cpp | 24 | ||||
-rw-r--r-- | src/main.cpp | 101 |
17 files changed, 226 insertions, 80 deletions
@@ -1,3 +1,4 @@ sibs-build .kdev4 amalgine.kdev4 +compile_commands.json @@ -1,4 +1,4 @@ -Copyright (c) 2017 dec05eba +Copyright (c) 2017 DEC05EBA Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: @@ -3,3 +3,6 @@ glfw3 glew glm sibs (https://github.com/DEC05EBA/sibs) + +# TODO +Make use shader a no-op if already in use
\ No newline at end of file diff --git a/include/RenderBackend/OpenGL/DeviceMemory.hpp b/include/RenderBackend/OpenGL/DeviceMemory.hpp index c9c8b23..3ccd0c9 100644 --- a/include/RenderBackend/OpenGL/DeviceMemory.hpp +++ b/include/RenderBackend/OpenGL/DeviceMemory.hpp @@ -2,7 +2,7 @@ #include "../../DataView.hpp" #include "../../utils.hpp" -#include "../../Triangle2D.hpp" +#include "../../Triangle.hpp" namespace amalgine { enum class DeviceMemoryType { @@ -37,6 +37,7 @@ namespace amalgine { ~DeviceMemory(); //void copy(const DataView<f32> &data, StorageType storageType, PrimitiveType primitiveType = PrimitiveType::TRIANGLE); void copy(const DataView<Triangle2D> &triangles, StorageType storageType); + void copy(const DataView<Triangle3D> &triangles, StorageType storageType); void draw(); DeviceMemoryType get_type() const { return type; } diff --git a/include/RenderBackend/OpenGL/ShaderProgram.hpp b/include/RenderBackend/OpenGL/ShaderProgram.hpp index ca96d0c..f1fea00 100644 --- a/include/RenderBackend/OpenGL/ShaderProgram.hpp +++ b/include/RenderBackend/OpenGL/ShaderProgram.hpp @@ -4,9 +4,13 @@ #include "../../types.hpp" #include "../../utils.hpp" #include "../../Vec.hpp" +#include "Uniform.hpp" #include "DeviceMemory.hpp" + #include <vector> #include <memory> +#include <glm/gtc/matrix_transform.hpp> +#include <glm/gtc/type_ptr.hpp> namespace amalgine { class Shader; @@ -17,7 +21,8 @@ namespace amalgine { public: ~ShaderProgram(); static Result<std::unique_ptr<ShaderProgram>> build(const std::vector<Shader*> &shaders); - int set_uniform(const char *name, const vec3f &value); + + Result<Uniform> get_uniform_by_name(const char *name); int set_vertex_input(const char *name, const DeviceMemory &data); void use(); diff --git a/include/RenderBackend/OpenGL/Uniform.hpp b/include/RenderBackend/OpenGL/Uniform.hpp new file mode 100644 index 0000000..288c9b8 --- /dev/null +++ b/include/RenderBackend/OpenGL/Uniform.hpp @@ -0,0 +1,29 @@ +#pragma once + +#include "../../Result.hpp" +#include "../../types.hpp" +#include "../../utils.hpp" +#include "../../Vec.hpp" + +#include <glm/gtc/type_ptr.hpp> + +namespace amalgine { + class Uniform { + DISABLE_COPY(Uniform) + friend class ShaderProgram; + friend class Result<Uniform>; + public: + Uniform(Uniform&&) = default; + ~Uniform(); + + void set(const vec3f &value); + void set(const glm::mat4 &value); + private: + Uniform(){} + Uniform(i32 uniform_id, u32 shader_program_id); + void use(); + private: + i32 uniform_id; + u32 program_id; + }; +} diff --git a/include/Result.hpp b/include/Result.hpp index 50a0d0c..86ae176 100644 --- a/include/Result.hpp +++ b/include/Result.hpp @@ -11,9 +11,7 @@ namespace amalgine public: static Result<T> Ok(T data) { - Result<T> result; - result.data = std::move(data); - result.errorCode = 0; + Result<T> result(std::move(data)); return result; } @@ -42,11 +40,17 @@ namespace amalgine assert(isOk()); return data; } + + T* operator -> () { + assert(isOk()); + return &data; + } const std::string& getErrorMsg() const { return errorMsg; } int getErrorCode() const { return errorCode; } private: - Result(){} + Result() {} + Result(T data) : data(std::move(data)), errorCode(0) {} private: T data; int errorCode; diff --git a/include/Triangle.hpp b/include/Triangle.hpp new file mode 100644 index 0000000..5caff05 --- /dev/null +++ b/include/Triangle.hpp @@ -0,0 +1,23 @@ +#pragma once + +#include "Vertex.hpp" + +namespace amalgine { + class Triangle2D { + public: + Triangle2D(const Vertex2D &_p1, const Vertex2D &_p2, const Vertex2D &_p3) : p1(_p1), p2(_p2), p3(_p3) {} + + Vertex2D p1; + Vertex2D p2; + Vertex2D p3; + }; + + class Triangle3D { + public: + Triangle3D(const Vertex3D &_p1, const Vertex3D &_p2, const Vertex3D &_p3) : p1(_p1), p2(_p2), p3(_p3) {} + + Vertex3D p1; + Vertex3D p2; + Vertex3D p3; + }; +} diff --git a/include/Triangle2D.hpp b/include/Triangle2D.hpp deleted file mode 100644 index d5d76bd..0000000 --- a/include/Triangle2D.hpp +++ /dev/null @@ -1,16 +0,0 @@ -#pragma once - -#include "Vertex2D.hpp" - -namespace amalgine -{ - class Triangle2D - { - public: - Triangle2D(const Vertex2D &_p1, const Vertex2D &_p2, const Vertex2D &_p3) : p1(_p1), p2(_p2), p3(_p3) {} - - Vertex2D p1; - Vertex2D p2; - Vertex2D p3; - }; -} diff --git a/include/Vertex.hpp b/include/Vertex.hpp new file mode 100644 index 0000000..ab98d3b --- /dev/null +++ b/include/Vertex.hpp @@ -0,0 +1,28 @@ +#pragma once + +#include "types.hpp" + +namespace amalgine { + class Vertex2D { + public: + Vertex2D(f32 _x = 0.0f, f32 _y = 0.0f) : x(_x), y(_y) + { + + } + + f32 x; + f32 y; + }; + + class Vertex3D { + public: + Vertex3D(f32 _x = 0.0f, f32 _y = 0.0f, f32 _z = 0.0f) : x(_x), y(_y), z(_z) + { + + } + + f32 x; + f32 y; + f32 z; + }; +}
\ No newline at end of file diff --git a/include/Vertex2D.hpp b/include/Vertex2D.hpp deleted file mode 100644 index de22cd9..0000000 --- a/include/Vertex2D.hpp +++ /dev/null @@ -1,18 +0,0 @@ -#pragma once - -#include "types.hpp" - -namespace amalgine -{ - class Vertex2D - { - public: - Vertex2D(f32 _x = 0.0f, f32 _y = 0.0f) : x(_x), y(_y) - { - - } - - f32 x; - f32 y; - }; -} diff --git a/shaders/fragment.frag b/shaders/fragment.frag index ea1ca7d..60791c2 100644 --- a/shaders/fragment.frag +++ b/shaders/fragment.frag @@ -1,8 +1,9 @@ #version 330 core -uniform vec3 triangle_color; out vec4 out_color; +uniform vec3 triangle_color; + void main() { out_color = vec4(triangle_color, 1.0); }
\ No newline at end of file diff --git a/shaders/vertex.vert b/shaders/vertex.vert index d1cc433..a44217b 100644 --- a/shaders/vertex.vert +++ b/shaders/vertex.vert @@ -1,7 +1,11 @@ #version 330 core -in vec2 position; +in vec3 position; + +uniform mat4 proj; +uniform mat4 view; +uniform mat4 model; void main() { - gl_Position = vec4(position, 0.0, 1.0); + gl_Position = proj * view * model * vec4(position, 1.0); }
\ No newline at end of file diff --git a/src/RenderBackend/OpenGL/DeviceMemory.cpp b/src/RenderBackend/OpenGL/DeviceMemory.cpp index 2d40569..f071cd8 100644 --- a/src/RenderBackend/OpenGL/DeviceMemory.cpp +++ b/src/RenderBackend/OpenGL/DeviceMemory.cpp @@ -65,6 +65,15 @@ namespace amalgine numVertices = triangles.size * 3; type = DeviceMemoryType::VEC2; } + + void DeviceMemory::copy(const DataView<Triangle3D> &triangles, StorageType storageType) + { + glBindBuffer(GL_ARRAY_BUFFER, vertexBufferObjectId); + glBufferData(GL_ARRAY_BUFFER, triangles.getByteSize(), triangles.data, getOpenglStorageType(storageType)); + primitiveType = GL_TRIANGLES; + numVertices = triangles.size * 3; + type = DeviceMemoryType::VEC3; + } void DeviceMemory::draw() { diff --git a/src/RenderBackend/OpenGL/ShaderProgram.cpp b/src/RenderBackend/OpenGL/ShaderProgram.cpp index e613668..389a929 100644 --- a/src/RenderBackend/OpenGL/ShaderProgram.cpp +++ b/src/RenderBackend/OpenGL/ShaderProgram.cpp @@ -64,13 +64,13 @@ namespace amalgine { return Result<std::unique_ptr<ShaderProgram>>::Ok(std::move(shader_program)); } - int ShaderProgram::set_uniform(const char *name, const vec3f &value) { - GLint uniformId = glGetUniformLocation(program_id, name); - if(uniformId == -1) - return -1; - use(); - glUniform3f(uniformId, value.x, value.y, value.z); - return 0; + Result<Uniform> ShaderProgram::get_uniform_by_name(const char *name) { + GLint uniform_id = glGetUniformLocation(program_id, name); + if(uniform_id == -1) + return Result<Uniform>::Err(std::string("Uniform with name ") + name + " was not found"); + + Uniform uniform(uniform_id, program_id); + return Result<Uniform>::Ok(std::move(uniform)); } int ShaderProgram::set_vertex_input(const char *name, const DeviceMemory &data) { @@ -88,7 +88,10 @@ namespace amalgine { glVertexAttribPointer(attrib_location, 2, GL_FLOAT, GL_FALSE, 0, 0); break; } - case DeviceMemoryType::VEC3: assert(false); return -1; + case DeviceMemoryType::VEC3: { + glVertexAttribPointer(attrib_location, 3, GL_FLOAT, GL_FALSE, 0, 0); + break; + } } glEnableVertexAttribArray(attrib_location); return 0; diff --git a/src/RenderBackend/OpenGL/Uniform.cpp b/src/RenderBackend/OpenGL/Uniform.cpp new file mode 100644 index 0000000..67cf3c6 --- /dev/null +++ b/src/RenderBackend/OpenGL/Uniform.cpp @@ -0,0 +1,24 @@ +#include "../../../include/RenderBackend/OpenGL/Uniform.hpp" +#include "../../../include/RenderBackend/OpenGL/opengl.hpp" + +namespace amalgine { + Uniform::~Uniform() {} + + void Uniform::set(const vec3f &value) { + use(); + glUniform3f(uniform_id, value.x, value.y, value.z); + } + + void Uniform::set(const glm::mat4 &value) { + use(); + glUniformMatrix4fv(uniform_id, 1, GL_FALSE, glm::value_ptr(value)); + } + + Uniform::Uniform(i32 uniform_id, u32 shader_program_id) : uniform_id(uniform_id), program_id(shader_program_id) { + + } + + void Uniform::use() { + glUseProgram(program_id); + } +}
\ No newline at end of file diff --git a/src/main.cpp b/src/main.cpp index f6f827f..c073a43 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,13 +1,12 @@ -#include <cstdio> #include "../include/RenderBackend/OpenGL/opengl.hpp" #include "../include/RenderBackend/OpenGL/Shader.hpp" #include "../include/RenderBackend/OpenGL/ShaderProgram.hpp" #include "../include/RenderBackend/OpenGL/DeviceMemory.hpp" #include "../include/RenderBackend/OpenGL/DeviceFrame.hpp" -#include "../include/Triangle2D.hpp" +#include "../include/Triangle.hpp" -// TODO: Disallow shader variables that begin with "gl_" as reserved variables -// start with that. What about hlsl? +#include <cstdio> +#include <chrono> // TODO: Creating buffers etc should be somehow created/drawn using the window object, since they are associated with the window // opengl context @@ -20,43 +19,83 @@ static void initGlfw(); static void initGlew(); static GLFWwindow *createWindow(); static std::unique_ptr<Shader> load_shader_from_file(const char *filepath, Shader::Type shader_type); +static std::unique_ptr<ShaderProgram> build_shader_program_from_shaders(const std::vector<Shader*> &shaders); int main() { initGlfw(); glfwSetErrorCallback(glfwErrorHandler); GLFWwindow *window = createWindow(); + int window_width = 1; + int window_height = 1; + glfwGetWindowSize(window, &window_width, &window_height); DeviceFrame frame; - Triangle2D cpuTriangle( - Vertex2D(0.0f, 0.5f), - Vertex2D(0.5f, -0.5f), - Vertex2D(-0.5f, -0.5f) - ); - DataView<Triangle2D> cpuTriangles(&cpuTriangle, 1); + std::array<Triangle3D, 2> cpuTriangle = { + Triangle3D( + Vertex3D(0.0f, 0.0f, 0.0f), + Vertex3D(1.0f, 0.0f, 0.0f), + Vertex3D(0.0f, 1.0f, 0.0f) + ), + Triangle3D( + Vertex3D(1.0f, 0.0f, 0.0f), + Vertex3D(1.0f, 1.0f, 0.0f), + Vertex3D(0.0f, 1.0f, 0.0f) + ), + }; + DataView<Triangle3D> cpuTriangles(cpuTriangle.data(), cpuTriangle.size()); DeviceMemory *gpuTriangle = frame.alloc(); gpuTriangle->copy(cpuTriangles, DeviceMemory::StorageType::STATIC); std::unique_ptr<Shader> vertex_shader = load_shader_from_file("shaders/vertex.vert", Shader::Type::VERTEX); std::unique_ptr<Shader> pixel_shader = load_shader_from_file("shaders/fragment.frag", Shader::Type::PIXEL); - - Result<std::unique_ptr<ShaderProgram>> shader_program_result = ShaderProgram::build({ vertex_shader.get(), pixel_shader.get() }); - if(!shader_program_result) { - fprintf(stderr, "Failed to link shaders, error: %s\n", shader_program_result.getErrorMsg().c_str()); - exit(13); - } - std::unique_ptr<ShaderProgram> shader_program = std::move(shader_program_result.unwrap()); - + std::unique_ptr<ShaderProgram> shader_program = build_shader_program_from_shaders({ vertex_shader.get(), pixel_shader.get() }); + shader_program->set_vertex_input("position", *gpuTriangle); - shader_program->set_uniform("triangle_color", vec3f{ 1.0f, 0.0f, 0.0f }); + + Result<Uniform> proj_uniform = shader_program->get_uniform_by_name("proj"); + glm::mat4 proj = glm::perspective(glm::radians(75.0f), (float)window_width / (float)window_height, 0.2f, 1000.0f); + proj_uniform->set(proj); + + Result<Uniform> triangle_color_uniform = shader_program->get_uniform_by_name("triangle_color"); + triangle_color_uniform->set(vec3f{ 1.0f, 0.0f, 0.0f }); + + Result<Uniform> view_uniform = shader_program->get_uniform_by_name("view"); + Result<Uniform> model_uniform = shader_program->get_uniform_by_name("model"); + + glm::vec3 character_pos(0.0f, 3.0f, 3.0f); + auto t_start = std::chrono::high_resolution_clock::now(); - while(!glfwWindowShouldClose(window)) - { + while(!glfwWindowShouldClose(window)) { glfwPollEvents(); if(glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS) glfwSetWindowShouldClose(window, GL_TRUE); + auto t_now = std::chrono::high_resolution_clock::now(); + float time_delta = std::chrono::duration_cast<std::chrono::duration<float>>(t_now - t_start).count(); + t_start = t_now; + + if(glfwGetKey(window, GLFW_KEY_W)) + character_pos.y -= time_delta; + if(glfwGetKey(window, GLFW_KEY_S)) + character_pos.y += time_delta; + + glm::mat4 view = glm::lookAt( + character_pos, + character_pos - glm::vec3(0.0f, 3.0f, 3.0f), + glm::vec3(0.0f, 0.0f, 1.0f) + ); + view_uniform->set(view); + + glm::mat4 model = glm::mat4(1.0f); + model = glm::rotate( + model, + 0.0f, + glm::vec3(0.0f, 0.0f, 1.0f) + ); + model_uniform->set(model); + // Set color for clearing glClearColor(0.0f, 0.0f, 0.0f, 1.0f); // Do the actual screen clearing, using the color set using glClearColor @@ -90,19 +129,16 @@ void initGlfw() glfwWindowHint(GLFW_RESIZABLE, GL_FALSE); } -void initGlew() -{ +void initGlew() { glewExperimental = true; - if(glewInit() != GLEW_OK) - { + if(glewInit() != GLEW_OK) { fprintf(stderr, "Failed to initialize GLEW\n"); glfwTerminate(); exit(-1); } } -GLFWwindow* createWindow() -{ +GLFWwindow* createWindow() { GLFWwindow *window = glfwCreateWindow(1280, 720, "Amalgine", nullptr, nullptr); if(!window) { @@ -111,7 +147,7 @@ GLFWwindow* createWindow() exit(10); } - glfwSetInputMode(window, GLFW_STICKY_KEYS, GL_TRUE); + glfwSetInputMode(window, GLFW_STICKY_KEYS, GL_FALSE); glfwMakeContextCurrent(window); glfwSwapInterval(0); initGlew(); @@ -145,4 +181,13 @@ std::unique_ptr<Shader> load_shader_from_file(const char *filepath, Shader::Type exit(12); } return std::move(vertex_shader_result.unwrap()); +} + +std::unique_ptr<ShaderProgram> build_shader_program_from_shaders(const std::vector<Shader*> &shaders) { + Result<std::unique_ptr<ShaderProgram>> shader_program_result = ShaderProgram::build(shaders); + if(!shader_program_result) { + fprintf(stderr, "Failed to link shaders, error: %s\n", shader_program_result.getErrorMsg().c_str()); + exit(13); + } + return std::move(shader_program_result.unwrap()); }
\ No newline at end of file |