diff --git a/assets/shaders/Image-Instanced.vert b/assets/shaders/Image-Instanced.vert new file mode 100644 index 0000000000000000000000000000000000000000..e2cad8b2f9c134ba947503e8221b01ae4ac7b610 --- /dev/null +++ b/assets/shaders/Image-Instanced.vert @@ -0,0 +1,14 @@ +#version 330 core +layout (location = 0) in vec2 aPos; +layout (location = 1) in vec2 aTex; + +uniform mat4 uProj; +uniform mat4 uView; +uniform mat4 uModel[128]; + +out vec2 Texture; + +void main() { + Texture = aTex; + gl_Position = uProj * uView * uModel[gl_InstanceID] * vec4(aPos.x, aPos.y, 0.0, 1.0); +} \ No newline at end of file diff --git a/assets/textures/Armored.png b/assets/textures/Armored.png new file mode 100644 index 0000000000000000000000000000000000000000..b39470eae7d9c3b30ab47fae1f4a8e5f204d6b7b Binary files /dev/null and b/assets/textures/Armored.png differ diff --git a/assets/textures/Neera.png b/assets/textures/Neera.png new file mode 100644 index 0000000000000000000000000000000000000000..01d777dca4146f5ff1d41da072aa59c744c5cc5b Binary files /dev/null and b/assets/textures/Neera.png differ diff --git a/imgui.ini b/imgui.ini new file mode 100644 index 0000000000000000000000000000000000000000..6b73fe54ff07f17b07d20b210e2d40736cf7919f --- /dev/null +++ b/imgui.ini @@ -0,0 +1,8 @@ +[Window][Debug##Default] +Pos=60,60 +Size=400,400 + +[Window][Isometric] +Pos=138,21 +Size=477,101 + diff --git a/source/engine/graphics/back/buffers/ShaderStorageBuffer.hpp b/source/engine/graphics/back/buffers/ShaderStorageBuffer.hpp new file mode 100644 index 0000000000000000000000000000000000000000..778b059821779a7019c1bcfd120d45698989631f --- /dev/null +++ b/source/engine/graphics/back/buffers/ShaderStorageBuffer.hpp @@ -0,0 +1,30 @@ +#pragma once + +#include "Buffer.hpp" + +#include <map> + +#include "../shaders/Program.hpp" + +namespace megu { + template <class T> + class ShaderStorageBuffer : public Buffer { + public: + ShaderStorageBuffer(T * = nullptr); + virtual ~ShaderStorageBuffer(); + + void setData(T *); + void attach(const std::string &, const Program &); + + void bind() const override; + void unbind() const override; + inline GLuint identifier() const override {return this->_id;} + + private: + T * _data; + GLuint _id; + std::map<const Program *, GLuint> _programs; + }; +} + +#include "ShaderStorageBuffer.tpp" \ No newline at end of file diff --git a/source/engine/graphics/back/buffers/ShaderStorageBuffer.tpp b/source/engine/graphics/back/buffers/ShaderStorageBuffer.tpp new file mode 100644 index 0000000000000000000000000000000000000000..163159e9109136e13e21299e73a6696965cfc381 --- /dev/null +++ b/source/engine/graphics/back/buffers/ShaderStorageBuffer.tpp @@ -0,0 +1,45 @@ +#include "ShaderStorageBuffer.hpp" + +namespace megu { + template <class T> + ShaderStorageBuffer<T>::ShaderStorageBuffer(T * data) + : _data(data), _id(0) { + glCreateBuffers(1, &this->_id); + glBindBuffer(GL_SHADER_STORAGE_BUFFER, this->_id); + glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(T), data, GL_DYNAMIC_DRAW); + } + + template <class T> + ShaderStorageBuffer<T>::~ShaderStorageBuffer() { + glDeleteBuffers(1, &this->_id); + } + + template <class T> + void ShaderStorageBuffer<T>::setData(T * data) { + this->_data = data; + glBindBuffer(GL_SHADER_STORAGE_BUFFER, this->_id); + glBufferSubData(GL_SHADER_STORAGE_BUFFER, 0, sizeof(T), data); + } + + template <class T> + void ShaderStorageBuffer<T>::attach(const std::string & name, const Program & program) { + this->_programs.insert(std::pair<const Program *, GLuint>(&program, 0)); + glBindBuffer(GL_SHADER_STORAGE_BUFFER, this->_id); + this->_programs[&program] = glGetProgramResourceIndex(program.id(), GL_SHADER_STORAGE_BLOCK, name.c_str()); + glBindBufferBase(GL_SHADER_STORAGE_BUFFER, this->_programs[&program], this->_id); + } + + template <class T> + void ShaderStorageBuffer<T>::bind() const { + glBindBuffer(GL_SHADER_STORAGE_BUFFER, this->_id); + } + + template <class T> + void ShaderStorageBuffer<T>::unbind() const { + GLint binded = 0; + glGetIntegerv(GL_SHADER_STORAGE_BUFFER, &binded); + if(static_cast<GLuint>(binded) == this->_id) { + glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0); + } + } +} \ No newline at end of file diff --git a/source/engine/graphics/back/geometry/Counter.hpp b/source/engine/graphics/back/geometry/Counter.hpp new file mode 100644 index 0000000000000000000000000000000000000000..84de6dc30ece6b926562d7469d2b9e647fb3c465 --- /dev/null +++ b/source/engine/graphics/back/geometry/Counter.hpp @@ -0,0 +1,93 @@ +#pragma once + +#include <list> +#include <typeindex> + +namespace megu { + template <typename T> + class Counter { + public: + template <T U> + static std::list<T> Count() { + std::list<T> list; + list.push_back(U); + return list; + } + + template <T U> + static std::list<T> Count(std::list<T> & list) { + list.push_back(U); + return list; + } + + template <T U, T V, T ... L> + static std::list<T> Count() { + std::list<T> list; + list.push_back(U); + return Counter<T>::Count<V, L...>(list); + } + + template <T U, T V, T ... L> + static std::list<T> Count(std::list<T> & list) { + list.push_back(U); + return Counter<T>::Count<V, L...>(list); + } + }; + + class Type_Counter { + public: + template <class T> + static std::list<std::type_index> Count() { + std::list<std::type_index> list; + list.push_back(typeid(T)); + return list; + } + + template <class T> + static std::list<std::type_index> Count(std::list<std::type_index> & list) { + list.push_back(typeid(T)); + return list; + } + + template <class T, class U, class ... V> + static std::list<std::type_index> Count() { + std::list<std::type_index> list; + list.push_back(typeid(T)); + return Type_Counter::Count<U, V...>(list); + } + + template <class T, class U, class ... V> + static std::list<std::type_index> Count(std::list<std::type_index> & list) { + list.push_back(typeid(T)); + return Type_Counter::Count<U, V...>(list); + } + }; + + template <typename T> + class Sum { + public: + template <T U> + static constexpr size_t sum() { + size_t sum = U; + return sum; + } + + template <T U> + static constexpr size_t sum(size_t & sum) { + sum += U; + return sum; + } + + template <T U, T V, T ... S> + static constexpr size_t sum() { + size_t sum = U; + return Sum::sum<V, S...>(sum); + } + + template <T U, T V, T ... S> + static constexpr size_t sum(size_t & sum) { + sum += U; + return Sum::sum<V, S...>(sum); + } + }; +} \ No newline at end of file diff --git a/source/engine/graphics/back/geometry/Geometry.hpp b/source/engine/graphics/back/geometry/Geometry.hpp index 7b34f29090660d2aac1b896631091be7a995f7b2..ca78b648733fb414082ae95c5e52ec519f930514 100644 --- a/source/engine/graphics/back/geometry/Geometry.hpp +++ b/source/engine/graphics/back/geometry/Geometry.hpp @@ -8,6 +8,7 @@ #include <GL/glew.h> #include "../buffers/Layout.hpp" +#include "Counter.hpp" namespace megu { using Vertices_t = std::vector<float>; @@ -19,7 +20,13 @@ namespace megu { }; template <Primitive_t P> - class Geometry { + class Primitived { + public: + inline static Primitive_t Primitive() {return P;} + }; + + template <Primitive_t P> + class Geometry : public Primitived<P> { public: Geometry() = delete; Geometry(const Layout &); @@ -27,8 +34,8 @@ namespace megu { virtual const Vertices_t & vertices() const = 0; - inline static Primitive_t Primitive() {return P;} - + inline const Layout & layout() const {return this->_layout;} + private: Layout _layout; }; @@ -43,22 +50,22 @@ namespace megu { virtual const Elements_t & elements() const = 0; }; - template <class T, Primitive_t P> - class Static_Geometry : public Geometry<P> { + template <class T, Primitive_t P, layout::Value ... L> + class Static_Geometry : public Primitived<P> { public: - Static_Geometry() = delete; - Static_Geometry(const Layout &); + Static_Geometry() = default; ~Static_Geometry() = default; - const Vertices_t & vertices() const final override {return Static_Geometry<T, P>::Vertices();} + const Vertices_t & vertices() const {return Static_Geometry<T, P>::Vertices();} + + static Layout Layout() {return Counter<megu::layout::Value>::Count<L...>();} static const Vertices_t & Vertices() {return T::Vertices();} }; - template <class T, Primitive_t P> - class Static_Geometry_Indiced : public Geometry_Indiced<P>, public Static_Geometry<T, P> { + template <class T, Primitive_t P, layout::Value ... L> + class Static_Geometry_Indiced : public Geometry_Indiced<P>, public Static_Geometry<T, P, L> { public: - Static_Geometry_Indiced() = delete; - Static_Geometry_Indiced(const Layout &); + Static_Geometry_Indiced() = default; ~Static_Geometry_Indiced() = default; const Elements_t & elements() const final override {return Static_Geometry_Indiced<T, P>::Elements();} diff --git a/source/engine/graphics/back/geometry/Geometry.tpp b/source/engine/graphics/back/geometry/Geometry.tpp index c8cdbdcb2ac16a8dfbc2aa511f76a82eb78961ab..6bb031da821637d77e7a51cbddfe49c3a7de7c13 100644 --- a/source/engine/graphics/back/geometry/Geometry.tpp +++ b/source/engine/graphics/back/geometry/Geometry.tpp @@ -8,12 +8,4 @@ namespace megu { template <Primitive_t P> Geometry_Indiced<P>::Geometry_Indiced(const Layout & layout) : Geometry<P>(layout) {} - - template <class T, Primitive_t P> - Static_Geometry<T,P>::Static_Geometry(const Layout & layout) - : Geometry<P>(layout) {} - - template <class T, Primitive_t P> - Static_Geometry_Indiced<T, P>:: Static_Geometry_Indiced(const Layout & layout) - : Geometry<P>(layout) {} } \ No newline at end of file diff --git a/source/engine/graphics/back/geometry/Transformable.cpp b/source/engine/graphics/back/geometry/Transformable.cpp index 482a57ef6108f35281fcafc70eed8366e504ab7c..e553b6b3bdc12ec52d2d85a1ef5a37936e06784d 100644 --- a/source/engine/graphics/back/geometry/Transformable.cpp +++ b/source/engine/graphics/back/geometry/Transformable.cpp @@ -42,6 +42,21 @@ namespace megu { this->_updated = true; } + void Transformable::setX(float x) { + this->_position.x = x; + this->_updated = true; + } + + void Transformable::setY(float y) { + this->_position.y = y; + this->_updated = true; + } + + void Transformable::setZ(float z) { + this->_position.z = z; + this->_updated = true; + } + void Transformable::setRotation(float angle, Axis axis) { if((Axis::X & axis) != 0) { this->_rotation.x = angle; @@ -108,4 +123,28 @@ namespace megu { } return this->_model; } + + bool Transformable::operator==(const Transformable & t) const { + return this->_position == t._position; + } + + bool Transformable::operator!=(const Transformable & t) const { + return this->_position != t._position; + } + + bool Transformable::operator>=(const Transformable & t) const { + return this->_position.x <= t._position.x && this->_position.y <= t._position.y; + } + + bool Transformable::operator<=(const Transformable & t) const { + return this->_position.x >= t._position.x && this->_position.y >= t._position.y; + } + + bool Transformable::operator>(const Transformable & t) const { + return this->_position.x < t._position.x && this->_position.y < t._position.y; + } + + bool Transformable::operator<(const Transformable & t) const { + return this->_position.x > t._position.x && this->_position.y > t._position.y; + } } \ No newline at end of file diff --git a/source/engine/graphics/back/geometry/Transformable.hpp b/source/engine/graphics/back/geometry/Transformable.hpp index ce39c3be765e3cd50960b1d48e5e0743703fefb0..c8582090e36a6a4f774493cbd49d4cf0215961ce 100644 --- a/source/engine/graphics/back/geometry/Transformable.hpp +++ b/source/engine/graphics/back/geometry/Transformable.hpp @@ -43,11 +43,15 @@ namespace megu { void setPosition(const glm::vec3 &); void setRotation(float, Axis); void setScaling(const glm::vec3 &); + void setX(float); + void setY(float); + void setZ(float); inline void setMatrix(const glm::mat4 & matrix) {this->_model = matrix;} + inline void setOrigine(const glm::vec3 & position) {this->_origine = position;} inline void setPosition(float x, float y, float z = 0.f) {this->setPosition({x, y, z});} inline void setScaling(float x, float y, float z = 0.f) {this->setScaling({x, y, z});} - inline void setOrigine(const glm::vec3 & position) {this->_origine = position;} + inline void setOrigine(float x, float y, float z = 0.f) {this->setOrigine({x, y, z});} void move(const glm::vec3 &); void rotate(float, Axis); @@ -56,6 +60,13 @@ namespace megu { inline void translate(const glm::vec3 & translation) {this->move(translation);} inline void move(float x, float y, float z = 0.f) {this->move({x, y, z});} inline void scale(float x, float y, float z = 0.f) {this->scale({x, y, z});} + + bool operator==(const Transformable &) const; + bool operator!=(const Transformable &) const; + bool operator>=(const Transformable &) const; + bool operator<=(const Transformable &) const; + bool operator>(const Transformable &) const; + bool operator<(const Transformable &) const; virtual const glm::mat4x4 & model() const; diff --git a/source/engine/graphics/back/shaders/Program.cpp b/source/engine/graphics/back/shaders/Program.cpp index f4f9860b4f24ffc369e34d283e7e098a7f3ae892..9520109bcac16a39c81a1978afa2155874a85b6e 100644 --- a/source/engine/graphics/back/shaders/Program.cpp +++ b/source/engine/graphics/back/shaders/Program.cpp @@ -6,6 +6,7 @@ #include "../../errors/Shader_Error.hpp" #include <iostream> +#include <list> namespace megu { Program::Program() @@ -169,4 +170,11 @@ namespace megu { glUniformMatrix4fv(this->_locations.at(name), static_cast<GLsizei>(value.size()), GL_FALSE, glm::value_ptr(value[0])); } + void Program::setUniform(const std::string & name, const std::vector<std::reference_wrapper<const glm::mat4>> & value) const { + glUniformMatrix4fv(this->_locations.at(name), static_cast<GLsizei>(value.size()), GL_FALSE, glm::value_ptr(value[0].get())); + } + + void Program::setUniform(const std::string & name, const std::set<std::reference_wrapper<const glm::mat4>> & value) const { + glUniformMatrix4fv(this->_locations.at(name), static_cast<GLsizei>(value.size()), GL_FALSE, glm::value_ptr(value.begin()->get())); + } } \ No newline at end of file diff --git a/source/engine/graphics/back/shaders/Program.hpp b/source/engine/graphics/back/shaders/Program.hpp index 5e4b08d0d2d2833296a0487c5cdbecab6d5931ba..0b5df733d627649646e072c89772f3fe85dc49aa 100644 --- a/source/engine/graphics/back/shaders/Program.hpp +++ b/source/engine/graphics/back/shaders/Program.hpp @@ -3,6 +3,7 @@ #include <GL/glew.h> #include <glm/glm.hpp> #include <vector> +#include <set> #include <unordered_map> #include "Source.hpp" @@ -66,5 +67,8 @@ namespace megu { void setUniform(const std::string &, const std::vector<glm::vec2> &) const; void setUniform(const std::string &, const std::vector<glm::vec4> &) const; void setUniform(const std::string &, const std::vector<glm::mat4> &) const; + + void setUniform(const std::string &, const std::vector<std::reference_wrapper<const glm::mat4>> &) const; + void setUniform(const std::string &, const std::set<std::reference_wrapper<const glm::mat4>> &) const; }; } \ No newline at end of file diff --git a/source/engine/graphics/back/textures/Texture.cpp b/source/engine/graphics/back/textures/Texture.cpp index e47163a402c3bdfd815e8ce830234b613f67baed..e913a049b849777323b098d501b06af5070c13d8 100644 --- a/source/engine/graphics/back/textures/Texture.cpp +++ b/source/engine/graphics/back/textures/Texture.cpp @@ -9,6 +9,14 @@ namespace megu { glGenTextures(1, &this->_id); } + Texture::Texture(const std::filesystem::path & path, GLuint slot) + : _id(0), _type(GL_RED), _slot(slot) { + this->store(TextureBuffer(path)); + } + + Texture::Texture(const Texture & texture) + : _id(texture._id), _type(texture._type), _slot(texture._slot) {} + Texture::~Texture() { glDeleteTextures(1, &this->_id); } diff --git a/source/engine/graphics/back/textures/Texture.hpp b/source/engine/graphics/back/textures/Texture.hpp index 55f70524c6e2c60784ee174e6e0a8f02fc6bda27..aeb75f89bb5035327c64ceec1708fa0d16fc002c 100644 --- a/source/engine/graphics/back/textures/Texture.hpp +++ b/source/engine/graphics/back/textures/Texture.hpp @@ -9,7 +9,8 @@ namespace megu { class Texture { public: Texture(GLuint = 0, GLuint = GL_TEXTURE_2D); - Texture(const Texture &) = delete; + Texture(const std::filesystem::path &, GLuint = 0); + Texture(const Texture &); Texture & operator=(const Texture &) = delete; ~Texture(); diff --git a/source/engine/graphics/back/textures/TextureBuffer.cpp b/source/engine/graphics/back/textures/TextureBuffer.cpp index 67013aa8b08ab818a5d8fdb8079a8eca7aa00ec2..52f13a891aac71fcebaae923b311a8189165409f 100644 --- a/source/engine/graphics/back/textures/TextureBuffer.cpp +++ b/source/engine/graphics/back/textures/TextureBuffer.cpp @@ -12,6 +12,11 @@ namespace megu { TextureBuffer::TextureBuffer(GLuint width, GLuint height, GLubyte * data, GLenum format) : _data(data, data + (width * height)), _width(width), _height(height), _format(format) {} + TextureBuffer::TextureBuffer(const std::filesystem::path & path, bool flip) + : _data(), _width(0), _height(0), _format(GL_RED) { + this->load(path, flip); + } + TextureBuffer::TextureBuffer(const TextureBuffer & src) : _data(src._data), _width(src._width), _height(src._height) {} diff --git a/source/engine/graphics/back/textures/TextureBuffer.hpp b/source/engine/graphics/back/textures/TextureBuffer.hpp index 584ed8c28e467091c69ff141755f953dc625c91e..489e72e48042aeab55e49f180f662f76bcddd312 100644 --- a/source/engine/graphics/back/textures/TextureBuffer.hpp +++ b/source/engine/graphics/back/textures/TextureBuffer.hpp @@ -9,6 +9,7 @@ namespace megu { public: TextureBuffer(); TextureBuffer(GLuint, GLuint, GLubyte *, GLenum); + TextureBuffer(const std::filesystem::path &, bool = false); TextureBuffer(const TextureBuffer &); TextureBuffer & operator=(const TextureBuffer & src); ~TextureBuffer() = default; @@ -24,7 +25,7 @@ namespace megu { void flipVerticaly(); void load(const GLubyte *, size_t); - void load(const std::filesystem::path &, bool = true); + void load(const std::filesystem::path &, bool = false); void free(); static int BytePerPixel(GLenum); diff --git a/source/engine/graphics/front/geometry/FlatGeometry.cpp b/source/engine/graphics/front/geometry/FlatGeometry.cpp deleted file mode 100644 index e6e0de17daf4a8e06e0814b8c18f96367a8767fb..0000000000000000000000000000000000000000 --- a/source/engine/graphics/front/geometry/FlatGeometry.cpp +++ /dev/null @@ -1,21 +0,0 @@ -#include "FlatGeometry.hpp" - -namespace megu { - Flat_Geometry::Flat_Geometry() - : Geometry({layout::FLAT, layout::COLOR}) {} - - Vertices_t Static_Flat_Geometry::_Vertices = { - 0.f, 0.f, 0.f, 0.f, - 1.f, 0.f, 1.f, 0.f, - 1.f, 1.f, 1.f, 1.f, - 0.f, 1.f, 0.f, 1.f - }; - - Static_Flat_Geometry::Static_Flat_Geometry() - : Static_Geometry<Static_Flat_Geometry, QUADS>(Static_Flat_Geometry::GetLayout()) {} - - const Vertices_t & Static_Flat_Geometry::Vertices() { - return Static_Flat_Geometry::_Vertices; - } - -} \ No newline at end of file diff --git a/source/engine/graphics/front/geometry/FlatGeometry.hpp b/source/engine/graphics/front/geometry/FlatGeometry.hpp deleted file mode 100644 index 7f56662bcaa71c655fd5d924ad14bd4173eb3976..0000000000000000000000000000000000000000 --- a/source/engine/graphics/front/geometry/FlatGeometry.hpp +++ /dev/null @@ -1,24 +0,0 @@ -#pragma once - -#include <engine/graphics/back/geometry/Geometry.hpp> - -namespace megu { - class Flat_Geometry : public Geometry<QUADS> { - public: - Flat_Geometry(); - ~Flat_Geometry() = default; - }; - - class Static_Flat_Geometry : public Static_Geometry<Static_Flat_Geometry, QUADS> { - public: - Static_Flat_Geometry(); - ~Static_Flat_Geometry() = default; - - inline static Layout GetLayout() {return {layout::FLAT, layout::TEXTURE};} - - static const Vertices_t & Vertices(); - - private: - static Vertices_t _Vertices; - }; -} diff --git a/source/engine/graphics/front/geometry/Quads.cpp b/source/engine/graphics/front/geometry/Quads.cpp new file mode 100644 index 0000000000000000000000000000000000000000..fccb8871cb6f30fb070e1fc8b834732c6ccb5547 --- /dev/null +++ b/source/engine/graphics/front/geometry/Quads.cpp @@ -0,0 +1,10 @@ +#include "Quads.hpp" + +namespace megu { + Vertices_t Quads::_Vertices = { + 0.f, 0.f, 0.f, 0.f, + 1.f, 0.f, 1.f, 0.f, + 1.f, 1.f, 1.f, 1.f, + 0.f, 1.f, 0.f, 1.f + }; +} \ No newline at end of file diff --git a/source/engine/graphics/front/geometry/Quads.hpp b/source/engine/graphics/front/geometry/Quads.hpp new file mode 100644 index 0000000000000000000000000000000000000000..2e70bc67aef40de435784c07c6bc3d1ef07852e1 --- /dev/null +++ b/source/engine/graphics/front/geometry/Quads.hpp @@ -0,0 +1,13 @@ +#pragma once + +#include <engine/graphics/back/geometry/Geometry.hpp> + +namespace megu { + class Quads : public Static_Geometry<Quads, QUADS, layout::FLAT, layout::TEXTURE> { + public: + inline static const Vertices_t & Vertices() {return Quads::_Vertices;} + + private: + static Vertices_t _Vertices; + }; +} diff --git a/source/engine/graphics/front/group/ImageGroup.cpp b/source/engine/graphics/front/group/ImageGroup.cpp index 47fe30a4360cb91119c2ec3b765b8f0f93aeaa8f..5239d8e8c0eb10b79fbf2929e614d8c466a96678 100644 --- a/source/engine/graphics/front/group/ImageGroup.cpp +++ b/source/engine/graphics/front/group/ImageGroup.cpp @@ -1,10 +1,12 @@ #include "ImageGroup.hpp" +#include <tuple> + namespace megu { ImageGroup::ImageGroup() - : _images(nullptr), _vbo(this->_vao, Static_Flat_Geometry::GetLayout(), 400) { + : _vbo(this->_vao, Quads::Layout(), 400) { { - Source vert("assets/shaders/Image.vert", Source::Categorie::VERTEX); + Source vert("assets/shaders/Image-Instanced.vert", Source::Categorie::VERTEX); Source frag("assets/shaders/Image.frag", Source::Categorie::FRAGMENT); this->_program << vert; @@ -15,20 +17,40 @@ namespace megu { frag.release(); } - this->_vbo << Static_Flat_Geometry::Vertices(); + this->_vbo << Quads::Vertices(); + } + + void ImageGroup::add(const Image & image) { + this->_images.insert(image); + } + + void ImageGroup::update() { + std::set<std::reference_wrapper<const Image>, isometric_sorter> source = this->_images; + this->_images.clear(); + for(auto & i : source) { + this->_images.insert(i); + } } void ImageGroup::draw(const Camera & camera) const { this->_vao.bind(); this->_program.use(); - this->_images->texture().bind(0); + std::map<std::reference_wrapper<const Texture>, std::vector<std::reference_wrapper<const glm::mat4>>> data; + + for(auto & image : this->_images) { + data[image.get().texture()].push_back(image.get().transformation().model()); + } + + for(auto &[texture, models] : data) { + texture.get().bind(); - this->_program.setUniform("uProj", camera.projection()); - this->_program.setUniform("uView", camera.view()); - this->_program.setUniform("uModel", this->_images->transformation().model()); - this->_program.setUniform("uSampler", 0); + this->_program.setUniform("uProj", camera.projection()); + this->_program.setUniform("uView", camera.view()); + this->_program.setUniform("uSampler", 0); + this->_program.setUniform("uModel", models); - glDrawArrays(Static_Flat_Geometry::Primitive(), 0, static_cast<GLsizei>(this->_vbo.size())); + glDrawArraysInstanced(Quads::Primitive(), 0, static_cast<GLsizei>(this->_vbo.size()), static_cast<GLsizei>(models.size())); + } } } \ No newline at end of file diff --git a/source/engine/graphics/front/group/ImageGroup.hpp b/source/engine/graphics/front/group/ImageGroup.hpp index 465609efcd3788c70bc94344e10991511e7e96b1..8bad28b9b4526814241590b4149ac26d6f46920d 100644 --- a/source/engine/graphics/front/group/ImageGroup.hpp +++ b/source/engine/graphics/front/group/ImageGroup.hpp @@ -1,6 +1,12 @@ #pragma once #include "DrawGroup.hpp" +#include "reference_sorter.hpp" +#include "isometric_sorter.hpp" + +#include <map> +#include <list> +#include <set> #include <engine/graphics/back/buffers/VertexArray.hpp> #include <engine/graphics/back/buffers/VerticeBuffer.hpp> @@ -16,11 +22,12 @@ namespace megu { void draw(const Camera & camera) const override; - inline void temp_set(Image & image) {this->_images = ℑ} + void add(const Image &); + void update(); private: - Image * _images; - + std::set<std::reference_wrapper<const Image>, isometric_sorter> _images; + VertexArray _vao; VerticeBuffer _vbo; Program _program; diff --git a/source/engine/graphics/front/group/isometric_sorter.cpp b/source/engine/graphics/front/group/isometric_sorter.cpp new file mode 100644 index 0000000000000000000000000000000000000000..b1eb9261b340f9b3c602c7c764ff2054263f031c --- /dev/null +++ b/source/engine/graphics/front/group/isometric_sorter.cpp @@ -0,0 +1,21 @@ +#include "isometric_sorter.hpp" + +#include <engine/graphics/front/object/Image.hpp> + +namespace megu { + bool isometric_sorter::operator()(const Image & img1, const Image & img2) const { + if(img1.transformation().z() != img2.transformation().z()) { + return img1.transformation().z() > img2.transformation().z(); + } + + if(img1.transformation().y() != img2.transformation().y()) { + return img1.transformation().y() < img2.transformation().y(); + } + + if(img1.transformation().x() != img2.transformation().x()) { + return img1.transformation().x() > img2.transformation().x(); + } + + return &img1 > &img2; + } +} \ No newline at end of file diff --git a/source/engine/graphics/front/group/isometric_sorter.hpp b/source/engine/graphics/front/group/isometric_sorter.hpp new file mode 100644 index 0000000000000000000000000000000000000000..6c840065780ce622b62c10abf40565dd6b80c841 --- /dev/null +++ b/source/engine/graphics/front/group/isometric_sorter.hpp @@ -0,0 +1,10 @@ +#pragma once + +namespace megu { + class Image; + + class isometric_sorter { + public: + bool operator()(const Image & img1, const Image & img2) const; + }; +} \ No newline at end of file diff --git a/source/engine/graphics/front/group/reference_sorter.hpp b/source/engine/graphics/front/group/reference_sorter.hpp new file mode 100644 index 0000000000000000000000000000000000000000..df5a8eab1f5dc1da160646482820fff6ecd467cb --- /dev/null +++ b/source/engine/graphics/front/group/reference_sorter.hpp @@ -0,0 +1,15 @@ +#pragma once + +namespace megu { + template <class T> + class reference_sorter { + public: + reference_sorter() = default; + ~reference_sorter() = default; + + friend bool operator<(const T &, const T &); + bool operator()(const T &, const T &) const; + }; +} + +#include "reference_sorter.tpp" \ No newline at end of file diff --git a/source/engine/graphics/front/group/reference_sorter.tpp b/source/engine/graphics/front/group/reference_sorter.tpp new file mode 100644 index 0000000000000000000000000000000000000000..320ee9f694d62abbc1cff1625298176fbce13595 --- /dev/null +++ b/source/engine/graphics/front/group/reference_sorter.tpp @@ -0,0 +1,13 @@ +#include "reference_sorter.hpp" + +namespace megu { + template <class T> + bool operator<(const T & obj_1, const T & obj_2) { + return &obj_1 < &obj_2; + } + + template <class T> + bool reference_sorter<T>::operator()(const T & obj_1, const T & obj_2) const { + return &obj_1 < &obj_2; + } +} \ No newline at end of file diff --git a/source/engine/graphics/front/object/Image.cpp b/source/engine/graphics/front/object/Image.cpp index 42ac510d4d50153fea150b9c9d797e30260d7f1d..dce4a4269d6ffcbb1d3e667dcc10dd4dd08f05d0 100644 --- a/source/engine/graphics/front/object/Image.cpp +++ b/source/engine/graphics/front/object/Image.cpp @@ -3,8 +3,26 @@ namespace megu { Image::Image() : _texture(), - _transformation(), - _geometry() {} + _geometry(), + _transformation() {} + + Image::Image(const std::filesystem::path & path) + : _texture(), + _geometry(), + _transformation() { + this->load(path); + } + + Image::Image(const Texture & texture) + : _texture(texture), + _geometry(), + _transformation() {} + + Image::Image(const Image & src) + : _texture(src._texture), + _geometry(src._geometry), + _transformation(src._transformation) { + } void Image::load(const std::filesystem::path & path, bool flip) { TextureBuffer buffer; diff --git a/source/engine/graphics/front/object/Image.hpp b/source/engine/graphics/front/object/Image.hpp index 0392e9411f0a2068338a2d76664cf29d321633d7..485d7036da82d3fb7a7f399a7bdd9cf3332b174a 100644 --- a/source/engine/graphics/front/object/Image.hpp +++ b/source/engine/graphics/front/object/Image.hpp @@ -6,30 +6,36 @@ #include <engine/graphics/back/geometry/Transformable.hpp> #include <engine/graphics/back/textures/Texture.hpp> -#include <engine/graphics/front/geometry/FlatGeometry.hpp> +#include <engine/graphics/front/geometry/Quads.hpp> namespace megu { class Image { public: Image(); + Image(const std::filesystem::path &); + Image(const Texture &); + Image(const Image &); ~Image() = default; inline glm::vec2 getPosition() const {return glm::vec2(this->_transformation.x(), this->_transformation.y());} inline glm::vec2 getSize() const {return glm::vec2(this->_transformation.scaling().x, this->_transformation.scaling().y);} - inline void setPosition(float x, float y) {this->_transformation.setPosition(x, y);} + inline void setOrigine(float x, float y) {this->_transformation.setOrigine(x, y);} inline void setSize(float x, float y) {this->_transformation.setScaling(x, y);} + inline void setRotation(float a) {this->_transformation.setRotation(a, Transformable::Axis::Z);} + inline void setLayer(float l) {this->_transformation.setZ(l);} void load(const std::filesystem::path &, bool = true); void load(const TextureBuffer &); inline const Texture & texture() const {return this->_texture;} - inline const Transformable & transformation() const {return this->_transformation;} + inline const Quads & geometry() const {return this->_geometry;} + inline const Transformable & transformation() const {return this->_transformation;} private: Texture _texture; + Quads _geometry; Transformable _transformation; - Static_Flat_Geometry _geometry; }; } \ No newline at end of file diff --git a/source/engine/io/Window.cpp b/source/engine/io/Window.cpp index fdc462a7bb2e986c42518b7948065180f25e6675..e73e875ca8453030fbbd0c8d4e33417d57fdfa26 100644 --- a/source/engine/io/Window.cpp +++ b/source/engine/io/Window.cpp @@ -38,6 +38,12 @@ namespace megu { } } + void Window::setTitle(const std::string & title) { + if(this->_pointer != nullptr) { + glfwSetWindowTitle(this->_pointer, title.c_str()); + } + } + void Window::open(const std::string & title, uint16_t width, uint16_t height) { if(this->_pointer == nullptr) { this->_pointer = glfwCreateWindow(width, height, title.c_str(), NULL, NULL); diff --git a/source/engine/io/Window.hpp b/source/engine/io/Window.hpp index b541bf866d0ad45074692b8701231cf5e0345deb..b4412d3dd96b38016b0eff90960b8764a722d659 100644 --- a/source/engine/io/Window.hpp +++ b/source/engine/io/Window.hpp @@ -17,12 +17,15 @@ namespace megu { bool isOpen() const; void resize(uint16_t, uint16_t); + void setTitle(const std::string &); void open(const std::string &, uint16_t, uint16_t); void close(); void pollEvents(); void swapBuffers(); + inline GLFWwindow * ptr() const {return this->_pointer;} + inline static double Time() {return glfwGetTime();} private: diff --git a/source/main.cpp b/source/main.cpp index 7b6a23deed8bb2680d0b18276470c08012337f54..853f72d3bd17605040b345d57348ea059d7e93e3 100644 --- a/source/main.cpp +++ b/source/main.cpp @@ -3,6 +3,10 @@ #include <GL/glew.h> #include <GLFW/glfw3.h> +#include <imgui.h> +#include <imgui_impl_glfw.h> +#include <imgui_impl_opengl3.h> + #define WINDOW_WIDTH 1200 #define WINDOW_HEIGHT 720 @@ -12,42 +16,22 @@ #include <engine/graphics/front/group/ImageGroup.hpp> #include <engine/graphics/errors.hpp> -int main(int argc, const char * argv[]) { - try { - /*//? GLFW - if(glfwInit() == GLFW_FALSE) { - std::cerr << "GLFW : GLFW Init Error" << std::endl; - return EXIT_FAILURE; - } - - GLFWmonitor * monitore = glfwGetPrimaryMonitor(); - const GLFWvidmode * videoMode = glfwGetVideoMode(monitore); +#define NORMALIZE(X) X/255.f - glfwWindowHint(GLFW_RED_BITS, videoMode->redBits); - glfwWindowHint(GLFW_GREEN_BITS, videoMode->greenBits); - glfwWindowHint(GLFW_BLUE_BITS, videoMode->blueBits); - glfwWindowHint(GLFW_REFRESH_RATE, videoMode->refreshRate); +const float i_x = 1.f; +const float i_y = 0.5f; +const float j_x = -1.f; +const float j_y = 0.5f; - glfwWindowHint(GLFW_RESIZABLE, true); - glfwWindowHint(GLFW_DECORATED, true); - glfwWindowHint(GLFW_VISIBLE, true); - glfwWindowHint(GLFW_DOUBLEBUFFER, true); +glm::vec2 to_screen_coordinate(const glm::vec2 & tile, float w, float h, float layer = 0.0f) { + return { + (tile.x + layer) * i_x * 0.5f * w + (tile.y + layer) * j_x * 0.5f * w, + (tile.x + layer) * i_y * 0.5f * h + (tile.y + layer) * j_y * 0.5f * h + }; +} - GLFWwindow * window = glfwCreateWindow(WINDOW_WIDTH, WINDOW_HEIGHT, "Scene", NULL, NULL); - if(window == NULL) { - std::cerr << "GLFW : Window Init Error" << std::endl; - return EXIT_FAILURE; - } - - glfwMakeContextCurrent(window); - glfwSwapInterval(0); - std::cout << "GLFW Inited" << std::endl; - - //? Glew - if(glewInit()) { - std::cerr << "Failed to initialize GLAD" << std::endl; - return EXIT_FAILURE; - }*/ +int main(int argc, const char * argv[]) { + try { //? Window megu::Window window; window.open("Window", WINDOW_WIDTH, WINDOW_HEIGHT); @@ -56,31 +40,151 @@ int main(int argc, const char * argv[]) { std::cout << "Window Inited" << std::endl; //? Camera - megu::View view(0, 0, WINDOW_WIDTH, WINDOW_HEIGHT); + megu::View view(0, 0, 320, 240); std::cout << "View Initied" << std::endl; - //? Image - megu::Image image; - image.load("assets/textures/Cube_Red.png"); - - std::cout << "Image Inited" << std::endl; - //? Group megu::ImageGroup group; - group.temp_set(image); std::cout << "Group Inited" << std::endl; + //? Image + std::vector<int> map = { + 1, 0, 0, 0, 1, 1, 0, 0, 0, 1, + 0, 1, 0, 1, 0, 0, 1, 0, 1, 0, + 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, + 0, 1, 0, 1, 0, 0, 1, 0, 1, 0, + 1, 0, 0, 0, 1, 1, 0, 0, 0, 1, + 1, 0, 0, 0, 1, 1, 0, 0, 0, 1, + 0, 1, 0, 1, 0, 0, 1, 0, 1, 0, + 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, + 0, 1, 0, 1, 0, 0, 1, 0, 1, 0, + 1, 0, 0, 0, 1, 1, 0, 0, 0, 1, + }; + + std::vector<std::string> textures = { + "assets/textures/Cube_Red.png", + "assets/textures/Cube_Blue.png", + "assets/textures/Cube_Green.png", + "assets/textures/Cube_Cyan.png", + "assets/textures/Cube_Pink.png", + "assets/textures/Cube_Yellow.png", + "assets/textures/Cube_Magenta.png", + "assets/textures/Cube_Purple.png", + "assets/textures/Cube_Gray.png", + "assets/textures/Cube_Orange.png" + }; + + size_t x = 0; + size_t y = 0; + + std::vector<std::unique_ptr<megu::Image>> images; + + for(auto id : map) { + if(x == 10) { + x = 0; + ++y; + } + + images.push_back(std::make_unique<megu::Image>(textures.at(3))); + glm::vec2 pos = to_screen_coordinate({x, y}, 32.f, 32.f); + + images.back()->setPosition(pos.x + 160, pos.y); + + ++x; + } + + for(auto & i : images) { + group.add(*i); + } + + std::cout << "Image Inited" << std::endl; + + //? ImGui + ImGui::CreateContext(); + ImGui_ImplOpenGL3_Init(); + ImGui_ImplGlfw_InitForOpenGL(window.ptr(), true); + //? Render Loop - glClearColor(0.0f, 0.0f, 0.0f, 0.f); + glClearColor(NORMALIZE(110), NORMALIZE(110), NORMALIZE(255), 0.f); + + double lastTime = glfwGetTime(); + int nbFrames = 0; std::cout << "Render Loop Begin !" << std::endl; + + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + glEnable(GL_BLEND); + + glm::vec2 xy = {0, 0}; + while(window.isOpen()) { + double currentTime = glfwGetTime(); + nbFrames++; + if ( currentTime - lastTime >= 1.0 ){ // If last prinf() was more than 1 sec ago + // printf and reset timer + window.setTitle(std::to_string(nbFrames)); + nbFrames = 0; + lastTime += 1.0; + } + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); window.pollEvents(); group.draw(view); - image.setPosition(static_cast<float>(sin(glfwGetTime()) * WINDOW_WIDTH/2), static_cast<float>(cos(glfwGetTime()) * WINDOW_HEIGHT/2)); + ImGui_ImplOpenGL3_NewFrame(); + ImGui_ImplGlfw_NewFrame(); + ImGui::NewFrame(); + + if(ImGui::Begin("Isometric")) { + ImGui::Text("Position : %i / %i", static_cast<int>(xy.x), static_cast<int>(xy.y)); + + ImGui::Text("x : "); + ImGui::SameLine(); + if(ImGui::Button("+")) { + ++xy.x; + glm::vec2 pos = to_screen_coordinate(xy, 32, 32, 0.f); + images[1]->setPosition(pos.x, pos.y); + group.update(); + + } + + ImGui::SameLine(); + if(ImGui::Button("-")) { + --xy.x; + glm::vec2 pos = to_screen_coordinate(xy, 32, 32, 0.f); + images[1]->setPosition(pos.x, pos.y); + group.update(); + + } + + ImGui::PushID(1); + + ImGui::Text("y : "); + ImGui::SameLine(); + if(ImGui::Button("+")) { + ++xy.y; + glm::vec2 pos = to_screen_coordinate(xy, 32, 32, 0.f); + images[1]->setPosition(pos.x, pos.y); + group.update(); + + } + + ImGui::SameLine(); + if(ImGui::Button("-")) { + --xy.y; + glm::vec2 pos = to_screen_coordinate(xy, 32, 32, 0.f); + images[1]->setPosition(pos.x, pos.y); + group.update(); + + } + + ImGui::PopID(); + } + ImGui::End(); + + ImGui::Render(); + ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData()); window.swapBuffers(); }