diff --git a/src/graphics/core/Batch3D.cpp b/src/graphics/core/Batch3D.cpp index dd6261e5..41db4294 100644 --- a/src/graphics/core/Batch3D.cpp +++ b/src/graphics/core/Batch3D.cpp @@ -118,12 +118,12 @@ void Batch3D::texture(const Texture* new_texture){ } void Batch3D::sprite( - glm::vec3 pos, - glm::vec3 up, - glm::vec3 right, + const glm::vec3& pos, + const glm::vec3& up, + const glm::vec3& right, float w, float h, const UVRegion& uv, - glm::vec4 color + const glm::vec4& color ){ const float r = color.r; const float g = color.g; @@ -175,7 +175,7 @@ inline glm::vec4 do_tint(float value) { } void Batch3D::xSprite( - float w, float h, const UVRegion& uv, const glm::vec4 tint, bool shading + float w, float h, const UVRegion& uv, const glm::vec4& tint, bool shading ) { face( glm::vec3(-w * 0.25f, 0.0f, -w * 0.25f), @@ -194,10 +194,10 @@ void Batch3D::xSprite( } void Batch3D::cube( - const glm::vec3 coord, - const glm::vec3 size, + const glm::vec3& coord, + const glm::vec3& size, const UVRegion(&texfaces)[6], - const glm::vec4 tint, + const glm::vec4& tint, bool shading ) { const glm::vec3 X(1.0f, 0.0f, 0.0f); @@ -237,22 +237,24 @@ void Batch3D::cube( } void Batch3D::blockCube( - const glm::vec3 size, + const glm::vec3& size, const UVRegion(&texfaces)[6], - const glm::vec4 tint, + const glm::vec4& tint, bool shading ) { cube((1.0f - size) * -0.5f, size, texfaces, tint, shading); } -void Batch3D::vertex(glm::vec3 coord, glm::vec2 uv, glm::vec4 tint) { +void Batch3D::vertex( + const glm::vec3& coord, const glm::vec2& uv, const glm::vec4& tint +) { if (index + B3D_VERTEX_SIZE >= capacity) { flush(); } vertex(coord, uv, tint.r, tint.g, tint.b, tint.a); } -void Batch3D::point(glm::vec3 coord, glm::vec4 tint) { +void Batch3D::point(const glm::vec3& coord, const glm::vec4& tint) { if (index + B3D_VERTEX_SIZE >= capacity) { flushPoints(); } diff --git a/src/graphics/core/Batch3D.hpp b/src/graphics/core/Batch3D.hpp index bd5f7b4e..672021fd 100644 --- a/src/graphics/core/Batch3D.hpp +++ b/src/graphics/core/Batch3D.hpp @@ -49,36 +49,36 @@ public: void begin(); void texture(const Texture* texture); void sprite( - glm::vec3 pos, - glm::vec3 up, - glm::vec3 right, + const glm::vec3& pos, + const glm::vec3& up, + const glm::vec3& right, float w, float h, const UVRegion& uv, - glm::vec4 tint + const glm::vec4& tint ); void xSprite( float w, float h, const UVRegion& uv, - const glm::vec4 tint, + const glm::vec4& tint, bool shading = true ); void cube( - const glm::vec3 coords, - const glm::vec3 size, + const glm::vec3& coords, + const glm::vec3& size, const UVRegion (&texfaces)[6], - const glm::vec4 tint, + const glm::vec4& tint, bool shading = true ); void blockCube( - const glm::vec3 size, + const glm::vec3& size, const UVRegion (&texfaces)[6], - const glm::vec4 tint, + const glm::vec4& tint, bool shading = true ); - void vertex(glm::vec3 pos, glm::vec2 uv, glm::vec4 tint); - void point(glm::vec3 pos, glm::vec4 tint); + void vertex(const glm::vec3& pos, const glm::vec2& uv, const glm::vec4& tint); + void point(const glm::vec3& pos, const glm::vec4& tint); void flush() override; void flushPoints(); }; diff --git a/src/graphics/render/MainBatch.cpp b/src/graphics/render/MainBatch.cpp new file mode 100644 index 00000000..11ef9835 --- /dev/null +++ b/src/graphics/render/MainBatch.cpp @@ -0,0 +1,61 @@ +#include "MainBatch.hpp" + +#include "graphics/core/Texture.hpp" +#include "graphics/core/Mesh.hpp" +#include "graphics/core/ImageData.hpp" + +#include "typedefs.hpp" + +static const vattr attrs[] = { + {3}, {2}, {3}, {1}, {0} +}; + +MainBatch::MainBatch(size_t capacity) + : buffer(std::make_unique(capacity * VERTEX_SIZE)), + capacity(capacity), + index(0), + mesh(std::make_unique(buffer.get(), 0, attrs)) { + + const ubyte pixels[] = { + 255, 255, 255, 255, + }; + ImageData image(ImageFormat::rgba8888, 1, 1, pixels); + blank = Texture::from(&image); +} + +MainBatch::~MainBatch() = default; + +void MainBatch::setTexture(const Texture* texture) { + if (texture == nullptr) { + texture = blank.get(); + } + if (texture != this->texture) { + flush(); + } + this->texture = texture; + region = UVRegion {0.0f, 0.0f, 1.0f, 1.0f}; +} + +void MainBatch::setTexture(const Texture* texture, const UVRegion& region) { + setTexture(texture); + this->region = region; +} + +void MainBatch::flush() { + if (index == 0) { + return; + } + if (texture == nullptr) { + texture = blank.get(); + } + texture->bind(); + mesh->reload(buffer.get(), index / VERTEX_SIZE); + mesh->draw(); + index = 0; +} + +void MainBatch::prepare(int vertices) { + if (index + VERTEX_SIZE * vertices > capacity * VERTEX_SIZE) { + flush(); + } +} diff --git a/src/graphics/render/MainBatch.hpp b/src/graphics/render/MainBatch.hpp new file mode 100644 index 00000000..9bc46366 --- /dev/null +++ b/src/graphics/render/MainBatch.hpp @@ -0,0 +1,61 @@ +#pragma once + +#include +#include +#include + +#include "maths/UVRegion.hpp" + +class Mesh; +class Texture; + +class MainBatch { + std::unique_ptr const buffer; + size_t const capacity; + size_t index; + + UVRegion region {0.0f, 0.0f, 1.0f, 1.0f}; + + std::unique_ptr mesh; + std::unique_ptr blank; + + const Texture* texture = nullptr; +public: + /// xyz, uv, color, compressed lights + static inline constexpr uint VERTEX_SIZE = 9; + + MainBatch(size_t capacity); + + ~MainBatch(); + + void prepare(int vertices); + void setTexture(const Texture* texture); + void setTexture(const Texture* texture, const UVRegion& region); + void flush(); + + inline void vertex( + glm::vec3 pos, glm::vec2 uv, glm::vec4 light, glm::vec3 tint + ) { + float* buffer = this->buffer.get(); + buffer[index++] = pos.x; + buffer[index++] = pos.y; + buffer[index++] = pos.z; + buffer[index++] = uv.x * region.getWidth() + region.u1; + buffer[index++] = uv.y * region.getHeight() + region.v1; + buffer[index++] = tint.x; + buffer[index++] = tint.y; + buffer[index++] = tint.z; + + union { + float floating; + uint32_t integer; + } compressed; + + compressed.integer = (static_cast(light.r * 255) & 0xff) << 24; + compressed.integer |= (static_cast(light.g * 255) & 0xff) << 16; + compressed.integer |= (static_cast(light.b * 255) & 0xff) << 8; + compressed.integer |= (static_cast(light.a * 255) & 0xff); + + buffer[index++] = compressed.floating; + } +}; diff --git a/src/graphics/render/ModelBatch.cpp b/src/graphics/render/ModelBatch.cpp index f6a1b58b..02615602 100644 --- a/src/graphics/render/ModelBatch.cpp +++ b/src/graphics/render/ModelBatch.cpp @@ -10,6 +10,7 @@ #include "voxels/Chunks.hpp" #include "lighting/Lightmap.hpp" #include "settings.hpp" +#include "MainBatch.hpp" #define GLM_ENABLE_EXPERIMENTAL #include @@ -18,13 +19,6 @@ #include -/// xyz, uv, color, compressed lights -inline constexpr uint VERTEX_SIZE = 9; - -static const vattr attrs[] = { - {3}, {2}, {3}, {1}, {0} -}; - inline constexpr glm::vec3 X(1, 0, 0); inline constexpr glm::vec3 Y(0, 1, 0); inline constexpr glm::vec3 Z(0, 0, 1); @@ -57,18 +51,10 @@ ModelBatch::ModelBatch( Chunks* chunks, const EngineSettings* settings ) - : buffer(std::make_unique(capacity * VERTEX_SIZE)), - capacity(capacity), - index(0), - mesh(std::make_unique(buffer.get(), 0, attrs)), + : batch(std::make_unique(capacity)), assets(assets), chunks(chunks), settings(settings) { - const ubyte pixels[] = { - 255, 255, 255, 255, - }; - ImageData image(ImageFormat::rgba8888, 1, 1, pixels); - blank = Texture::from(&image); } ModelBatch::~ModelBatch() = default; @@ -94,15 +80,13 @@ void ModelBatch::draw(const model::Mesh& mesh, const glm::mat4& matrix, size_t vcount = mesh.vertices.size(); const auto& vertexData = mesh.vertices.data(); for (size_t i = 0; i < vcount / 3; i++) { - if (index + VERTEX_SIZE * 3 > capacity * VERTEX_SIZE) { - flush(); - } + batch->prepare(3); for (size_t j = 0; j < 3; j++) { const auto vert = vertexData[i * 3 + j]; auto norm = rotation * vert.normal; float d = glm::dot(norm, SUN_VECTOR); d = 0.8f + d * 0.2f; - vertex(matrix * glm::vec4(vert.coord, 1.0f), vert.uv, lights*d, tint); + batch->vertex(matrix * glm::vec4(vert.coord, 1.0f), vert.uv, lights*d, tint); } } } @@ -135,7 +119,7 @@ void ModelBatch::render() { backlight ); } - flush(); + batch->flush(); entries.clear(); } @@ -148,37 +132,11 @@ void ModelBatch::setTexture(const std::string& name, if (varTextures && name.at(0) == '$') { const auto& found = varTextures->find(name); if (found == varTextures->end()) { - return setTexture(nullptr); + return batch->setTexture(nullptr); } else { return setTexture(found->second, varTextures); } } - - auto textureRegion = util::get_texture_region(*assets, name, "blocks:notfound"); - setTexture(textureRegion.texture); - region = textureRegion.region; -} - -void ModelBatch::setTexture(const Texture* texture) { - if (texture == nullptr) { - texture = blank.get(); - } - if (texture != this->texture) { - flush(); - } - this->texture = texture; - region = UVRegion {0.0f, 0.0f, 1.0f, 1.0f}; -} - -void ModelBatch::flush() { - if (index == 0) { - return; - } - if (texture == nullptr) { - texture = blank.get(); - } - texture->bind(); - mesh->reload(buffer.get(), index / VERTEX_SIZE); - mesh->draw(); - index = 0; + auto region = util::get_texture_region(*assets, name, "blocks:notfound"); + batch->setTexture(region.texture, region.region); } diff --git a/src/graphics/render/ModelBatch.hpp b/src/graphics/render/ModelBatch.hpp index 523eb300..5781baa1 100644 --- a/src/graphics/render/ModelBatch.hpp +++ b/src/graphics/render/ModelBatch.hpp @@ -13,6 +13,7 @@ class Texture; class Chunks; class Assets; struct EngineSettings; +class MainBatch; namespace model { struct Mesh; @@ -22,47 +23,15 @@ namespace model { using texture_names_map = std::unordered_map; class ModelBatch { - std::unique_ptr const buffer; - size_t const capacity; - size_t index; - - std::unique_ptr mesh; - std::unique_ptr blank; - Assets* assets; Chunks* chunks; - const Texture* texture = nullptr; - UVRegion region {0.0f, 0.0f, 1.0f, 1.0f}; + const EngineSettings* settings; glm::vec3 lightsOffset {}; static inline glm::vec3 SUN_VECTOR {0.411934f, 0.863868f, -0.279161f}; - inline void vertex( - glm::vec3 pos, glm::vec2 uv, glm::vec4 light, glm::vec3 tint - ) { - float* buffer = this->buffer.get(); - buffer[index++] = pos.x; - buffer[index++] = pos.y; - buffer[index++] = pos.z; - buffer[index++] = uv.x * region.getWidth() + region.u1; - buffer[index++] = uv.y * region.getHeight() + region.v1; - buffer[index++] = tint.x; - buffer[index++] = tint.y; - buffer[index++] = tint.z; - - union { - float floating; - uint32_t integer; - } compressed; - - compressed.integer = (static_cast(light.r * 255) & 0xff) << 24; - compressed.integer |= (static_cast(light.g * 255) & 0xff) << 16; - compressed.integer |= (static_cast(light.b * 255) & 0xff) << 8; - compressed.integer |= (static_cast(light.a * 255) & 0xff); - - buffer[index++] = compressed.floating; - } + std::unique_ptr batch; void draw(const model::Mesh& mesh, const glm::mat4& matrix, @@ -72,8 +41,6 @@ class ModelBatch { bool backlight); void setTexture(const std::string& name, const texture_names_map* varTextures); - void setTexture(const Texture* texture); - void flush(); struct DrawEntry { glm::mat4 matrix;