diff --git a/src/graphics/core/Batch3D.cpp b/src/graphics/core/Batch3D.cpp index 7481ec6f..68e59c78 100644 --- a/src/graphics/core/Batch3D.cpp +++ b/src/graphics/core/Batch3D.cpp @@ -5,7 +5,9 @@ #include #include "../../typedefs.hpp" +#include "../../maths/UVRegion.hpp" +/// xyz, uv, rgba inline constexpr uint B3D_VERTEX_SIZE = 9; Batch3D::Batch3D(size_t capacity) diff --git a/src/graphics/core/Batch3D.hpp b/src/graphics/core/Batch3D.hpp index 6ff42caa..61ef2eb0 100644 --- a/src/graphics/core/Batch3D.hpp +++ b/src/graphics/core/Batch3D.hpp @@ -1,7 +1,6 @@ #ifndef GRAPHICS_CORE_BATCH3D_HPP_ #define GRAPHICS_CORE_BATCH3D_HPP_ -#include "../../maths/UVRegion.hpp" #include "../../typedefs.hpp" #include @@ -10,6 +9,7 @@ class Mesh; class Texture; +struct UVRegion; class Batch3D { std::unique_ptr buffer; diff --git a/src/graphics/render/ModelBatch.cpp b/src/graphics/render/ModelBatch.cpp new file mode 100644 index 00000000..9d033790 --- /dev/null +++ b/src/graphics/render/ModelBatch.cpp @@ -0,0 +1,103 @@ +#include "ModelBatch.hpp" + +#include "../core/Mesh.hpp" +#include "../core/Texture.hpp" +#include "../../window/Window.hpp" + +#include +#include +#include + +/// xyz, uv, compressed rgba +inline constexpr uint VERTEX_SIZE = 6; + +static const vattr attrs[] = { + {3}, {2}, {1}, {0} +}; + +static glm::vec3 SUN_VECTOR (0.411934f, 0.863868f, -0.279161f); +inline constexpr glm::vec3 X(1, 0, 0); +inline constexpr glm::vec3 Y(0, 1, 0); +inline constexpr glm::vec3 Z(0, 0, 1); + +ModelBatch::ModelBatch(size_t capacity) + : buffer(std::make_unique(capacity * VERTEX_SIZE)), + capacity(capacity), + index(0), + mesh(std::make_unique(buffer.get(), 0, attrs)), + combined(1.0f) +{ + ubyte pixels[] = { + 255, 255, 255, 255, + }; + blank = std::make_unique(pixels, 1, 1, ImageFormat::rgba8888); +} + +ModelBatch::~ModelBatch() { +} + +void ModelBatch::test(glm::vec3 pos, glm::vec3 size) { + float time = static_cast(Window::time()); + pushMatrix(glm::translate(glm::mat4(1.0f), pos)); + pushMatrix(glm::rotate(glm::mat4(1.0f), time, glm::vec3(0,1,0))); + pushMatrix(glm::translate(glm::mat4(1.0f), glm::vec3(0, glm::sin(time*2), 0))); + box({}, size); + popMatrix(); + popMatrix(); + popMatrix(); +} + +void ModelBatch::box(glm::vec3 pos, glm::vec3 size) { + plane(pos+Z, X*size, Y*size, Z); + plane(pos-Z, -X*size, Y*size, -Z); + + plane(pos+Y, X*size, -Z*size, Y); + plane(pos-Y, X*size, Z*size, -Y); + + plane(pos+X, -Z*size, Y*size, X); + plane(pos-X, Z*size, Y*size, -X); +} + +void ModelBatch::flush() { + if (index == 0) { + return; + } + blank->bind(); + mesh->reload(buffer.get(), index / VERTEX_SIZE); + mesh->draw(); + index = 0; +} + +void ModelBatch::pushMatrix(glm::mat4 matrix) { + matrices.push_back(combined); + combined = matrix * combined; + + decomposed = {}; + glm::quat rotation; + glm::decompose( + combined, + decomposed.scale, + rotation, + decomposed.translation, + decomposed.skew, + decomposed.perspective + ); + decomposed.rotation = glm::toMat3(rotation); +} + +void ModelBatch::popMatrix() { + combined = matrices[matrices.size()-1]; + matrices.erase(matrices.end()-1); + + decomposed = {}; + glm::quat rotation; + glm::decompose( + combined, + decomposed.scale, + rotation, + decomposed.translation, + decomposed.skew, + decomposed.perspective + ); + decomposed.rotation = glm::toMat3(rotation); +} diff --git a/src/graphics/render/ModelBatch.hpp b/src/graphics/render/ModelBatch.hpp new file mode 100644 index 00000000..848a84d3 --- /dev/null +++ b/src/graphics/render/ModelBatch.hpp @@ -0,0 +1,84 @@ +#ifndef GRAPHICS_RENDER_MODEL_BATCH_HPP_ +#define GRAPHICS_RENDER_MODEL_BATCH_HPP_ + +#include +#include +#include + +class Mesh; +class Texture; + +struct DecomposedMat4 { + glm::vec3 scale; + glm::mat3 rotation; + glm::vec3 translation; + glm::vec3 skew; + glm::vec4 perspective; +}; +#include +class ModelBatch { + std::unique_ptr buffer; + size_t capacity; + size_t index; + + std::unique_ptr mesh; + std::unique_ptr blank; + + glm::mat4 combined; + std::vector matrices; + + DecomposedMat4 decomposed {}; + + inline void vertex( + glm::vec3 pos, glm::vec2 uv, glm::vec4 color + ) { + float* buffer = this->buffer.get(); + pos = combined * glm::vec4(pos, 1.0f); + buffer[index++] = pos.x; + buffer[index++] = pos.y; + buffer[index++] = pos.z; + buffer[index++] = uv.x; + buffer[index++] = uv.y; + + union { + float floating; + uint32_t integer; + } compressed; + + compressed.integer = (static_cast(color.r * 255) & 0xff) << 24; + compressed.integer |= (static_cast(color.g * 255) & 0xff) << 16; + compressed.integer |= (static_cast(color.b * 255) & 0xff) << 8; + compressed.integer |= (static_cast(color.a * 255) & 0xff); + + buffer[index++] = compressed.floating; + } + + inline void plane(glm::vec3 pos, glm::vec3 right, glm::vec3 up, glm::vec3 norm) { + norm = decomposed.rotation * norm; + glm::vec4 color {norm.x, norm.y, norm.z, 0.0f}; + color.r = glm::max(0.0f, color.r); + color.g = glm::max(0.0f, color.g); + color.b = glm::max(0.0f, color.b); + + vertex(pos-right-up, {0,0}, color); + vertex(pos+right-up, {1,0}, color); + vertex(pos+right+up, {1,1}, color); + + vertex(pos-right-up, {0,0}, color); + vertex(pos+right+up, {1,1}, color); + vertex(pos-right+up, {0,1}, color); + } +public: + ModelBatch(size_t capacity); + ~ModelBatch(); + + void pushMatrix(glm::mat4 matrix); + void popMatrix(); + + void box(glm::vec3 pos, glm::vec3 size); + + void test(glm::vec3 pos, glm::vec3 size); + void flush(); +}; + +#endif // GRAPHICS_RENDER_MODEL_BATCH_HPP_ diff --git a/src/graphics/render/Skybox.cpp b/src/graphics/render/Skybox.cpp index c98406da..65b255a9 100644 --- a/src/graphics/render/Skybox.cpp +++ b/src/graphics/render/Skybox.cpp @@ -9,6 +9,7 @@ #include "../../graphics/core/DrawContext.hpp" #include "../../window/Window.hpp" #include "../../window/Camera.hpp" +#include "../../maths/UVRegion.hpp" #include #include diff --git a/src/graphics/render/WorldRenderer.cpp b/src/graphics/render/WorldRenderer.cpp index 795e4c0d..fe49d8bc 100644 --- a/src/graphics/render/WorldRenderer.cpp +++ b/src/graphics/render/WorldRenderer.cpp @@ -1,6 +1,7 @@ #include "WorldRenderer.hpp" #include "ChunksRenderer.hpp" +#include "ModelBatch.hpp" #include "Skybox.hpp" #include "../../assets/Assets.hpp" @@ -47,7 +48,8 @@ WorldRenderer::WorldRenderer(Engine* engine, LevelFrontend* frontend, Player* pl level(frontend->getLevel()), player(player), frustumCulling(std::make_unique()), - lineBatch(std::make_unique()) + lineBatch(std::make_unique()), + modelBatch(std::make_unique(1000)) { renderer = std::make_unique( level, @@ -191,6 +193,10 @@ void WorldRenderer::renderLevel( drawChunks(level->chunks.get(), camera, shader); + shader->uniformMatrix("u_model", glm::mat4(1.0f)); + modelBatch->test(glm::vec3(0, 68, 0), glm::vec3(1.0f)); + modelBatch->flush(); + skybox->unbind(); } diff --git a/src/graphics/render/WorldRenderer.hpp b/src/graphics/render/WorldRenderer.hpp index 27d1a569..2f3517e1 100644 --- a/src/graphics/render/WorldRenderer.hpp +++ b/src/graphics/render/WorldRenderer.hpp @@ -23,6 +23,7 @@ class LevelFrontend; class Skybox; class PostProcessing; class DrawContext; +class ModelBatch; struct EngineSettings; class WorldRenderer { @@ -34,6 +35,7 @@ class WorldRenderer { std::unique_ptr renderer; std::unique_ptr skybox; std::unique_ptr batch3d; + std::unique_ptr modelBatch; bool drawChunk(size_t index, Camera* camera, Shader* shader, bool culling); void drawChunks(Chunks* chunks, Camera* camera, Shader* shader);