Skip to content

Commit

Permalink
Started Renderer::BatchDrawer
Browse files Browse the repository at this point in the history
  • Loading branch information
WillisMedwell committed Jan 29, 2024
1 parent 0add3a5 commit cfc8383
Show file tree
Hide file tree
Showing 18 changed files with 195 additions and 34 deletions.
4 changes: 2 additions & 2 deletions code/Demos/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,10 @@ if(DEFINED EMSCRIPTEN)

# Asset embedding.
file(COPY ${CMAKE_CURRENT_SOURCE_DIR}/assets DESTINATION ${CMAKE_BINARY_DIR})
file(GLOB_RECURSE ASSET_FILES "${CMAKE_BINARY_DIR}/assets/*")
file(GLOB_RECURSE ASSET_FILES "${CMAKE_CURRENT_SOURCE_DIR}/assets/*")
set(PRELOAD_FILES "")
foreach(FILE ${ASSET_FILES})
file(RELATIVE_PATH REL_FILE ${CMAKE_BINARY_DIR} ${FILE})
file(RELATIVE_PATH REL_FILE ${CMAKE_CURRENT_SOURCE_DIR} ${FILE})
set(PRELOAD_FILES "${PRELOAD_FILES} --preload-file ${REL_FILE}")
endforeach()
message(STATUS "PRELOAD FILES: \"${PRELOAD_FILES}\"")
Expand Down
2 changes: 1 addition & 1 deletion code/Demos/src/Main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ struct SpinningTeapotLogic {
.on_value([&](auto& id) {
data.ib_id = id;
});
renderer.add_vertex_array(Model::StaticVertexLayout {}, data.vb_id)
renderer.add_vertex_array(Model::Vertex::VBL {}, data.vb_id)
.on_error(Utily::ErrorHandler::print_then_quit)
.on_value([&](auto& id) {
data.va_id = id;
Expand Down
2 changes: 1 addition & 1 deletion code/Engine/include/AppRenderer.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ class AppRenderer
offset += element.count * element.type_size;
}
return 0;
}
}

void stop() noexcept;
};
26 changes: 22 additions & 4 deletions code/Engine/include/Model/Types.hpp
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
#pragma once

#include "Renderer/VertexBufferLayout.hpp"
#include <array>
#include <iostream>
#include <glm/ext/quaternion_common.hpp>
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include "Renderer/VertexBufferLayout.hpp"
#include <iostream>

namespace Model {
using Vec2 = glm::vec2;
Expand All @@ -22,12 +22,30 @@ namespace Model {
stream << "v(" << vertex.position.x << ',' << vertex.position.y << ',' << vertex.position.z << ") \t"
<< "n(" << vertex.normal.x << ',' << vertex.normal.y << ',' << vertex.normal.z << ") \t"
<< "uv(" << vertex.uv_coord.x << ',' << vertex.uv_coord.y << ")";

return stream;
}
using VBL = Renderer::VertexBufferLayout<glm::vec3, glm::vec3, glm::vec2>;
};

using StaticVertexLayout = Renderer::VertexBufferLayout<glm::vec3, glm::vec3, glm::vec2>;
struct BatchingVertex {
Vec3 position;
Vec3 normal;
Vec2 uv_coord;
uint32_t texture_unit_index;
uint32_t model_transform_index;

friend auto operator<<(std::ostream& stream, const BatchingVertex& vertex) -> std::ostream& {
stream << "v(" << vertex.position.x << ',' << vertex.position.y << ',' << vertex.position.z << ") \t"
<< "n(" << vertex.normal.x << ',' << vertex.normal.y << ',' << vertex.normal.z << ") \t"
<< "uv(" << vertex.uv_coord.x << ',' << vertex.uv_coord.y << ") \t"
<< "tui(" << vertex.texture_unit_index << ") \t"
<< "mti(" << vertex.model_transform_index << ")";

return stream;
}

using VBL = Renderer::VertexBufferLayout<glm::vec3, glm::vec3, glm::vec2, uint32_t, uint32_t>;
};

using Index = uint32_t;

Expand Down
102 changes: 102 additions & 0 deletions code/Engine/include/Renderer/BatchDrawer.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
#pragma once

#include "Components/Components.hpp"
#include "Model/Static.hpp"
#include "Renderer/IndexBuffer.hpp"
#include "Renderer/Shader.hpp"
#include "Renderer/Texture.hpp"
#include "Renderer/VertexArray.hpp"
#include "Renderer/VertexBuffer.hpp"

#include <algorithm>
#include <array>
#include <cassert>
#include <ranges>
#include <tuple>

namespace Renderer {
class BatchDrawer
{
public:
static auto to_3_digit(uint32_t num) noexcept -> std::array<char, 3> {
assert(num < 1000);
// via stack overflow: https://stackoverflow.com/a/1861020
std::array<char, 3> result = { '0', '0', '0' };
for (int i = result.size() - 1; i >= 0; i--) {
result[i] = static_cast<char>(num % 10) + '0';
num /= 10;
}
// could use std::from_chars but that requires a rotate so no thanks.
return result;
}
using TexturedStaticModel = std::tuple<Model::Static&, Components::Transform&, Renderer::Texture&>;
#if 1
template <size_t N>
void batch(VertexBuffer& vb, IndexBuffer& ib, VertexArray& va, Shader& shader, std::array<TexturedStaticModel, N>& textured_models) {
static std::vector<Model::BatchingVertex> vertices_buffer;
static std::vector<Model::Index> indices_buffer;

// Predetermine size for only one alloc.
const size_t total_vertex_count = std::reduce(
textured_models.begin(),
textured_models.end(),
size_t(0),
[](const size_t& agg, const auto& tm) { return agg + std::get<0>(tm).vertices.size(); });
const size_t total_index_count = std::reduce(
textured_models.begin(),
textured_models.end(),
size_t(0),
[](const size_t& agg, const auto& tm) { return agg + std::get<0>(tm).indices.size(); });
vertices_buffer.resize(total_vertex_count);
indices_buffer.resize(total_index_count);

shader.bind();
va.bind();
vb.bind();
ib.bind();

// Move replacement info to compile time.
constexpr static std::string_view mm_uniform_string = "u_model_transfrom[$$$]";
constexpr static size_t mm_unifrom_string_size = mm_uniform_string.size();
constexpr static std::ptrdiff_t mm_uniform_replacement_offset = std::distance(mm_uniform_string.begin(), std::ranges::find(mm_uniform_string, '$'));

// Copy and ensure null ended string.
std::array<char, mm_unifrom_string_size + 1> mm_uniform = { mm_uniform_string.begin(), mm_uniform_string.end() };
mm_uniform.back() = '\0';

uint32_t i = 0;
auto vert_iter = vertices_buffer.begin();
auto indi_iter = vertices_buffer.begin();
for (auto& [model, transform, texture] : textured_models) {
const auto tex_unit = texture.bind(true).on_error(Utily::ErrorHandler::print_then_quit).value();
const auto index_offset = static_cast<Model::Index>(std::distance(vertices_buffer.begin(), vert_iter));

// Pass model transform as uniform.
auto i_chars = BatchDrawer::to_3_digit(i);
std::ranges::copy(i_chars, mm_uniform.data() + mm_uniform_replacement_offset);
shader.set_uniform(std::string_view { mm_uniform.data() }, transform.calc_transform_mat());

// Account for index offset
auto add_index_offset = [&](Model::Index index) { return index + index_offset; };
auto indi_iter = std::ranges::copy(model.indices | add_index_offset, indi_iter);

// Add texture index and model transform index
auto add_tex_unit = [&](const Model::Vertex& v) { return Model::BatchingVertex { v.position, v.normal, v.uv_coord, tex_unit, i }; };
auto vert_iter = std::ranges::copy(model.vertices | add_tex_unit, vert_iter);

++i;
}

// upload and draw.
ib.load_indices(indices_buffer);
vb.load_vertices(vertices_buffer);
glDrawElements(GL_TRIANGLES, ib.get_count(), GL_UNSIGNED_INT, (void*)0);

// unlock the locked-bound textures.
for (auto& [model, texture] : textured_models) {
auto tex_unit = texture.bind(false).on_error(Utily::ErrorHandler::print_then_quit).value();
}
}
#endif
};
}
5 changes: 5 additions & 0 deletions code/Engine/include/Renderer/IndexBuffer.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,12 @@ namespace Renderer {
void load_indices(const Range& indices) noexcept {
this->bind();
size_t size_in_bytes = indices.size() * sizeof(uint32_t);
#if defined(CONFIG_TARGET_NATIVE)
glBufferData(GL_ELEMENT_ARRAY_BUFFER, size_in_bytes, &(*indices.begin()), GL_DYNAMIC_DRAW);
#elif defined(CONFIG_TARGET_WEB)
// for some reason, GL_DYNAMIC_DRAW has a very small buffer capacity.
glBufferData(GL_ELEMENT_ARRAY_BUFFER, size_in_bytes, &(*indices.begin()), GL_STATIC_DRAW);
#endif
_count = indices.size();
}

Expand Down
2 changes: 1 addition & 1 deletion code/Engine/include/Renderer/VertexBuffer.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ namespace Renderer {
void bind() noexcept;
void unbind() noexcept;

~VertexBuffer();
~VertexBuffer() noexcept;

template <typename Range>
requires std::ranges::range<Range>
Expand Down
4 changes: 3 additions & 1 deletion code/Engine/src/Renderer/Framebuffer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,9 @@ namespace Renderer {

FrameBuffer::FrameBuffer(FrameBuffer&& other) noexcept
: _id(std::exchange(other._id, std::nullopt))
, _colour_attachment_index(std::exchange(other._id, std::nullopt)) { }
, _colour_attachment_index(std::exchange(other._id, std::nullopt)) {
last_bound = nullptr;
}

auto FrameBuffer::init(uint32_t width, uint32_t height) noexcept -> Utily::Result<void, Utily::Error> {
if (_id) {
Expand Down
14 changes: 7 additions & 7 deletions code/Engine/src/Renderer/IndexBuffer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,13 @@

namespace Renderer {
constexpr static uint32_t INVALID_BUFFER_ID = 0;
static IndexBuffer* last_bound = nullptr;

IndexBuffer::IndexBuffer(IndexBuffer&& other) noexcept
: _id(std::exchange(other._id, std::nullopt))
, _count(std::exchange(other._count, 0)) { }
, _count(std::exchange(other._count, 0)) {
last_bound = nullptr;
}

auto IndexBuffer::init() noexcept -> Utily::Result<void, Utily::Error> {
if (_id.has_value()) {
Expand All @@ -22,29 +25,26 @@ namespace Renderer {
}
return {};
}

static IndexBuffer* last_bound = nullptr;


void IndexBuffer::stop() noexcept {
if (_id.value_or(INVALID_BUFFER_ID) != INVALID_BUFFER_ID) {
glDeleteBuffers(1, &_id.value());
}
_id = std::nullopt;
_count = 0;
if(last_bound == this) {
if (last_bound == this) {
last_bound = nullptr;
}
}


void IndexBuffer::bind() noexcept {
if constexpr (Config::DEBUG_LEVEL != Config::DebugInfo::none) {
if (_id.value_or(INVALID_BUFFER_ID) == INVALID_BUFFER_ID) {
std::cerr << "Trying to unbind invalid vertex buffer.";
assert(false);
}
}
if(last_bound != this) {
if (last_bound != this) {
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _id.value_or(INVALID_BUFFER_ID));
last_bound = this;
}
Expand Down
8 changes: 6 additions & 2 deletions code/Engine/src/Renderer/Shader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,14 @@
using namespace std::literals;

namespace Renderer {

static Shader* last_bound = nullptr;

Shader::Shader(Shader&& other)
: _program_id(std::exchange(other._program_id, std::nullopt))
, _cached_uniforms(std::move(other._cached_uniforms)) { }
, _cached_uniforms(std::move(other._cached_uniforms)) {
last_bound = nullptr;
}

auto Shader::compile_shader(Type type, const std::string_view& source) -> Utily::Result<uint32_t, Utily::Error> {
constexpr static auto shader_verison =
Expand Down Expand Up @@ -103,7 +108,6 @@ namespace Renderer {
}

// cache it so we dont query the GPU over already bound stuff.
static Shader* last_bound = nullptr;

void Shader::bind() noexcept {
if constexpr (Config::DEBUG_LEVEL != Config::DebugInfo::none) {
Expand Down
1 change: 1 addition & 0 deletions code/Engine/src/Renderer/Texture.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ namespace Renderer {
}
return {};
}

auto Texture::upload_image(
Media::Image& image,
Filter filter,
Expand Down
9 changes: 5 additions & 4 deletions code/Engine/src/Renderer/VertexArray.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,12 @@

namespace Renderer {
constexpr static uint32_t INVALID_ARRAY_OBJECT_ID = 0;
static VertexArray* last_bound = nullptr;

VertexArray::VertexArray(VertexArray&& other)
: _id(std::exchange(other._id, std::nullopt)) { }
: _id(std::exchange(other._id, std::nullopt)) {
last_bound = nullptr;
}

auto VertexArray::init() noexcept -> Utily::Result<void, Utily::Error> {
if (_id) {
Expand All @@ -21,14 +24,12 @@ namespace Renderer {
return {};
}

static VertexArray* last_bound = nullptr;

void VertexArray::stop() noexcept {
if (_id.value_or(INVALID_ARRAY_OBJECT_ID) == INVALID_ARRAY_OBJECT_ID) {
glDeleteVertexArrays(1, &_id.value());
}
_id = std::nullopt;
if(last_bound == this) {
if (last_bound == this) {
last_bound = nullptr;
}
}
Expand Down
14 changes: 7 additions & 7 deletions code/Engine/src/Renderer/VertexBuffer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,12 @@

namespace Renderer {
constexpr static uint32_t INVALID_BUFFER_ID = 0;
static VertexBuffer* last_bound = nullptr;

VertexBuffer::VertexBuffer(VertexBuffer&& other) noexcept
: _id(std::exchange(other._id, std::nullopt)) { }
: _id(std::exchange(other._id, std::nullopt)) {
last_bound = nullptr;
}

auto VertexBuffer::init() noexcept -> Utily::Result<void, Utily::Error> {
if (_id) {
Expand All @@ -21,16 +24,13 @@ namespace Renderer {
return {};
}

static VertexBuffer* last_bound = nullptr;


void VertexBuffer::stop() noexcept {
if (_id.value_or(INVALID_BUFFER_ID) != INVALID_BUFFER_ID) {
glDeleteBuffers(1, &_id.value());
}
_id = std::nullopt;
if(last_bound == this) {

if (last_bound == this) {
last_bound = this;
}
}
Expand Down Expand Up @@ -63,7 +63,7 @@ namespace Renderer {
}
}

VertexBuffer::~VertexBuffer() {
VertexBuffer::~VertexBuffer() noexcept {
stop();
}
}
6 changes: 3 additions & 3 deletions code/Test/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,11 @@ if(DEFINED EMSCRIPTEN)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -s EXPORTED_FUNCTIONS='_main' --closure 1")

# Asset embedding.
file(COPY ${CMAKE_CURRENT_SOURCE_DIR}/assets DESTINATION ${CMAKE_CURRENT_BINARY_DIR})
file(GLOB_RECURSE ASSET_FILES "${CMAKE_CURRENT_BINARY_DIR}/assets/*")
file(COPY ${CMAKE_CURRENT_SOURCE_DIR}/assets DESTINATION ${CMAKE_BINARY_DIR})
file(GLOB_RECURSE ASSET_FILES "${CMAKE_CURRENT_SOURCE_DIR}/assets/*")
set(PRELOAD_FILES "")
foreach(FILE ${ASSET_FILES})
file(RELATIVE_PATH REL_FILE ${CMAKE_CURRENT_BINARY_DIR} ${FILE})
file(RELATIVE_PATH REL_FILE ${CMAKE_CURRENT_SOURCE_DIR} ${FILE})
set(PRELOAD_FILES "${PRELOAD_FILES} --preload-file ${REL_FILE}")
endforeach()
message(STATUS "PRELOAD FILES: \"${PRELOAD_FILES}\"")
Expand Down
1 change: 1 addition & 0 deletions code/Test/assets/text.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
hello world
2 changes: 1 addition & 1 deletion code/Test/include/Integration/BasicApps.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -233,7 +233,7 @@ struct SpinningTeapotLogic {
.on_value([&](auto& id) {
data.ib_id = id;
});
renderer.add_vertex_array(Model::StaticVertexLayout {}, data.vb_id)
renderer.add_vertex_array(Model::Vertex::VBL {}, data.vb_id)
.on_error(Utily::ErrorHandler::print_then_quit)
.on_value([&](auto& id) {
data.va_id = id;
Expand Down
Loading

0 comments on commit cfc8383

Please sign in to comment.