working batch renderer for 2d rectangles
parent
e37fc6b321
commit
26c659fc3f
|
@ -0,0 +1,24 @@
|
||||||
|
#ifdef __cplusplus
|
||||||
|
#include <string>
|
||||||
|
const std::string shader_2d_textured_frag = R"("
|
||||||
|
#version 300 es
|
||||||
|
precision mediump float;
|
||||||
|
|
||||||
|
out vec4 FragColor;
|
||||||
|
in vec2 uv;
|
||||||
|
in vec2 pos;
|
||||||
|
|
||||||
|
uniform sampler2D tex;
|
||||||
|
uniform vec4 color;
|
||||||
|
uniform vec4 use_texture;
|
||||||
|
|
||||||
|
vec4 linear_iter(vec4 i, vec4 p, float factor){
|
||||||
|
return (i + p) * factor;
|
||||||
|
}
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
FragColor = (texture(tex, uv) * use_texture) + color;
|
||||||
|
}
|
||||||
|
|
||||||
|
")";
|
||||||
|
#endif
|
|
@ -0,0 +1,31 @@
|
||||||
|
#ifdef __cplusplus
|
||||||
|
#include <string>
|
||||||
|
const std::string shader_2d_textured_vert = R"("
|
||||||
|
#version 300 es
|
||||||
|
precision mediump float;
|
||||||
|
|
||||||
|
layout (location = 0) in vec3 vertex;
|
||||||
|
layout (location = 1) in vec2 uv_in;
|
||||||
|
|
||||||
|
out vec2 pos;
|
||||||
|
out vec2 uv;
|
||||||
|
|
||||||
|
layout (std140) uniform GlobalMatrices
|
||||||
|
{
|
||||||
|
mat4 projection;
|
||||||
|
mat4 ortho;
|
||||||
|
mat4 view;
|
||||||
|
mat4 pvm;
|
||||||
|
mat4 ovm;
|
||||||
|
};
|
||||||
|
|
||||||
|
uniform mat4 model;
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
gl_Position = ortho * model * vec4(vertex, 1.0);
|
||||||
|
pos = vertex.xy;
|
||||||
|
uv = uv_in;
|
||||||
|
}
|
||||||
|
|
||||||
|
")";
|
||||||
|
#endif
|
|
@ -21,26 +21,86 @@
|
||||||
|
|
||||||
#include "blt/gfx/model.h"
|
#include "blt/gfx/model.h"
|
||||||
#include "blt/gfx/shader.h"
|
#include "blt/gfx/shader.h"
|
||||||
|
#include "blt/gfx/renderer/resource_manager.h"
|
||||||
|
#include <blt/std/hashmap.h>
|
||||||
|
#include <blt/std/memory_util.h>
|
||||||
|
#include <blt/math/vectors.h>
|
||||||
|
#include <string_view>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
namespace blt::gfx
|
namespace blt::gfx
|
||||||
{
|
{
|
||||||
|
struct rectangle_t
|
||||||
struct rectangle
|
|
||||||
{
|
{
|
||||||
float x, y, width, height;
|
float x, y, width, height, rotation = 0;
|
||||||
|
|
||||||
|
rectangle_t(float x, float y, float width, float height, float rotation): x(x), y(y), width(width), height(height), rotation(rotation)
|
||||||
|
{}
|
||||||
|
|
||||||
|
rectangle_t(float x, float y, float width, float height): x(x), y(y), width(width), height(height)
|
||||||
|
{}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct draw_state
|
||||||
|
{
|
||||||
|
// texture to use
|
||||||
|
std::string texture_name;
|
||||||
|
// color to use
|
||||||
|
blt::vec4 color;
|
||||||
|
// how much to blend the texture into the color? note blending is always additive!
|
||||||
|
blt::vec4 blend;
|
||||||
};
|
};
|
||||||
|
|
||||||
class batch_renderer_2d
|
class batch_renderer_2d
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
vertex_array* square_vao;
|
struct vec_hash
|
||||||
shader_t* shader;
|
{
|
||||||
|
std::size_t operator()(const blt::vec4& key) const
|
||||||
|
{
|
||||||
|
using namespace blt::mem;
|
||||||
|
return type_cast<std::int32_t>(key.x()) ^ type_cast<std::int32_t>(key.y()) ^ type_cast<std::int32_t>(key.y()) ^
|
||||||
|
type_cast<std::int32_t>(key.z());
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
private:
|
||||||
|
vertex_array* square_vao = nullptr;
|
||||||
|
shader_t* shader = nullptr;
|
||||||
|
resource_manager& resources;
|
||||||
|
HASHMAP<std::string, HASHMAP<blt::vec4, HASHMAP<blt::vec4, std::vector<rectangle_t>, vec_hash>, vec_hash>> complex_rectangles;
|
||||||
|
size_t draw_count_ = 0;
|
||||||
public:
|
public:
|
||||||
/**
|
explicit batch_renderer_2d(resource_manager& resources): resources(resources)
|
||||||
* @param use_view_matrix should we use the view matrix when rendering? Defaults to false as the assumption is the view matrix is 3d
|
{}
|
||||||
*/
|
|
||||||
void create(bool use_view_matrix = false);
|
void create();
|
||||||
|
|
||||||
|
inline void drawRectangle(std::string_view texture, const rectangle_t& rectangle)
|
||||||
|
{
|
||||||
|
const static blt::vec4 empty {0,0,0,0};
|
||||||
|
const static blt::vec4 full {1,1,1,1};
|
||||||
|
complex_rectangles[texture][empty][full].push_back(rectangle);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void drawRectangle(const blt::vec4& color, const rectangle_t& rectangle)
|
||||||
|
{
|
||||||
|
const static blt::vec4 empty {0,0,0,0};
|
||||||
|
complex_rectangles[""][color][empty].push_back(rectangle);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void drawRectangle(const draw_state& draw_info, const rectangle_t& rectangle)
|
||||||
|
{
|
||||||
|
complex_rectangles[draw_info.texture_name][draw_info.color][draw_info.blend].push_back(rectangle);
|
||||||
|
}
|
||||||
|
|
||||||
|
void render();
|
||||||
|
|
||||||
void cleanup();
|
void cleanup();
|
||||||
|
|
||||||
|
[[nodiscard]] inline size_t draw_count(){
|
||||||
|
return draw_count_;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,8 +21,11 @@
|
||||||
|
|
||||||
#include <blt/std/hashmap.h>
|
#include <blt/std/hashmap.h>
|
||||||
#include <blt/gfx/texture.h>
|
#include <blt/gfx/texture.h>
|
||||||
#include <blt/std/thread.h>
|
#include <mutex>
|
||||||
|
#include <vector>
|
||||||
|
#include <optional>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include "blt/compatibility.h"
|
||||||
|
|
||||||
namespace blt::gfx
|
namespace blt::gfx
|
||||||
{
|
{
|
||||||
|
@ -53,8 +56,10 @@ namespace blt::gfx
|
||||||
|
|
||||||
void load_resources(std::size_t threads = 8);
|
void load_resources(std::size_t threads = 8);
|
||||||
|
|
||||||
inline texture_gl2D* get(const std::string& name)
|
inline std::optional<texture_gl2D*> get(const std::string& name)
|
||||||
{
|
{
|
||||||
|
if (name.empty() || textures_2d.find(name) == textures_2d.end())
|
||||||
|
return {};
|
||||||
return textures_2d[name];
|
return textures_2d[name];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
Subproject commit d882b76d83749273b05e71fb0361d8778cc6ad94
|
Subproject commit 8411810ab5df8f330f9d7cf96a96179375dc4704
|
|
@ -16,6 +16,8 @@
|
||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
#include <blt/gfx/renderer/batch_2d_renderer.h>
|
#include <blt/gfx/renderer/batch_2d_renderer.h>
|
||||||
|
#include <blt/gfx/renderer/2d_textured.vert>
|
||||||
|
#include <blt/gfx/renderer/2d_textured.frag>
|
||||||
|
|
||||||
float square_vertices[20] = {
|
float square_vertices[20] = {
|
||||||
// positions // texture coords
|
// positions // texture coords
|
||||||
|
@ -32,13 +34,64 @@ const unsigned int square_indices[6] = {
|
||||||
namespace blt::gfx
|
namespace blt::gfx
|
||||||
{
|
{
|
||||||
|
|
||||||
void batch_renderer_2d::create(bool use_view_matrix)
|
void batch_renderer_2d::create()
|
||||||
{
|
{
|
||||||
|
vbo_t vertices_vbo;
|
||||||
|
vbo_t indices_vbo;
|
||||||
|
|
||||||
|
vertices_vbo.create();
|
||||||
|
indices_vbo.create(GL_ELEMENT_ARRAY_BUFFER);
|
||||||
|
|
||||||
|
vertices_vbo.allocate(sizeof(square_vertices), square_vertices);
|
||||||
|
indices_vbo.allocate(sizeof(square_indices), square_indices);
|
||||||
|
|
||||||
|
square_vao = new vertex_array();
|
||||||
|
square_vao->bindVBO(vertices_vbo, 0, 3, GL_FLOAT, 5 * sizeof(float), 0);
|
||||||
|
square_vao->bindVBO(vertices_vbo, 1, 2, GL_FLOAT, 5 * sizeof(float), 3 * sizeof(float));
|
||||||
|
square_vao->bindElement(indices_vbo);
|
||||||
|
|
||||||
|
shader = new shader_t(shader_2d_textured_vert, shader_2d_textured_frag);
|
||||||
|
shader->bindAttribute(0, "vertex");
|
||||||
|
shader->bindAttribute(1, "uv_in");
|
||||||
}
|
}
|
||||||
|
|
||||||
void batch_renderer_2d::cleanup()
|
void batch_renderer_2d::cleanup()
|
||||||
{
|
{
|
||||||
|
delete square_vao;
|
||||||
|
delete shader;
|
||||||
|
}
|
||||||
|
|
||||||
|
void batch_renderer_2d::render()
|
||||||
|
{
|
||||||
|
draw_count_ = 0;
|
||||||
|
shader->bind();
|
||||||
|
square_vao->bind();
|
||||||
|
glActiveTexture(GL_TEXTURE0);
|
||||||
|
for (auto& textures : complex_rectangles)
|
||||||
|
{
|
||||||
|
// resource manager handles the check for empty string
|
||||||
|
if (auto val = resources.get(textures.first))
|
||||||
|
val.value()->bind();
|
||||||
|
for (auto& colors : textures.second)
|
||||||
|
{
|
||||||
|
shader->setVec4("color", colors.first);
|
||||||
|
for (auto& blend_factors : colors.second)
|
||||||
|
{
|
||||||
|
shader->setVec4("use_texture", blend_factors.first);
|
||||||
|
for (auto& rect : blend_factors.second)
|
||||||
|
{
|
||||||
|
blt::mat4x4 model;
|
||||||
|
model.translate(rect.x, rect.y, 0.0f);
|
||||||
|
model.scale(rect.width, rect.height, 1);
|
||||||
|
if (rect.rotation != 0)
|
||||||
|
model.rotateZ(blt::toRadians(rect.rotation));
|
||||||
|
shader->setMatrix("model", model);
|
||||||
|
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
|
||||||
|
draw_count_++;
|
||||||
|
}
|
||||||
|
blend_factors.second.clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -17,6 +17,7 @@
|
||||||
*/
|
*/
|
||||||
#include <blt/gfx/renderer/resource_manager.h>
|
#include <blt/gfx/renderer/resource_manager.h>
|
||||||
#include <blt/std/logging.h>
|
#include <blt/std/logging.h>
|
||||||
|
#include <blt/std/thread.h>
|
||||||
|
|
||||||
namespace blt::gfx
|
namespace blt::gfx
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
#include <string>
|
#include <string>
|
||||||
std::string shader_test_frag = R"("
|
const std::string shader_test_frag = R"("
|
||||||
#version 300 es
|
#version 300 es
|
||||||
precision mediump float;
|
precision mediump float;
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
#include <string>
|
#include <string>
|
||||||
std::string shader_test_vert = R"("
|
const std::string shader_test_vert = R"("
|
||||||
#version 300 es
|
#version 300 es
|
||||||
precision mediump float;
|
precision mediump float;
|
||||||
|
|
||||||
|
@ -22,7 +22,6 @@ layout (std140) uniform GlobalMatrices
|
||||||
uniform mat4 model;
|
uniform mat4 model;
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
//gl_Position = projection * view * vec4(vertex.x, vertex.y, vertex.z, 1.0);
|
|
||||||
gl_Position = ortho * model * vec4(vertex, 1.0);
|
gl_Position = ortho * model * vec4(vertex, 1.0);
|
||||||
pos = vertex.xy;
|
pos = vertex.xy;
|
||||||
uv = uv_in;
|
uv = uv_in;
|
||||||
|
|
|
@ -7,15 +7,13 @@
|
||||||
#include <imgui.h>
|
#include <imgui.h>
|
||||||
#include "blt/gfx/imgui/IconsFontAwesome5.h"
|
#include "blt/gfx/imgui/IconsFontAwesome5.h"
|
||||||
|
|
||||||
#include <shaders/test.vert>
|
|
||||||
#include <shaders/test.frag>
|
|
||||||
#include "blt/gfx/renderer/resource_manager.h"
|
#include "blt/gfx/renderer/resource_manager.h"
|
||||||
|
#include "blt/gfx/renderer/batch_2d_renderer.h"
|
||||||
|
|
||||||
|
|
||||||
blt::gfx::vertex_array* vao;
|
|
||||||
blt::gfx::shader_t* shader;
|
|
||||||
blt::gfx::matrix_state_manager global_matrices;
|
blt::gfx::matrix_state_manager global_matrices;
|
||||||
blt::gfx::resource_manager resources;
|
blt::gfx::resource_manager resources;
|
||||||
|
blt::gfx::batch_renderer_2d renderer_2d(resources);
|
||||||
float x = 0, y = 0, z = 0;
|
float x = 0, y = 0, z = 0;
|
||||||
float bx = 500, by = 500;
|
float bx = 500, by = 500;
|
||||||
float mx = 0, my = -9.8;
|
float mx = 0, my = -9.8;
|
||||||
|
@ -46,71 +44,36 @@ void handle_input()
|
||||||
global_matrices.setView(view);
|
global_matrices.setView(view);
|
||||||
}
|
}
|
||||||
|
|
||||||
void draw(float x_, float y_, float width_, float height_, float rot = 0)
|
|
||||||
{
|
|
||||||
blt::mat4x4 model;
|
|
||||||
model.translate(x_, y_, 0.0f);
|
|
||||||
model.scale(width_, height_, 1);
|
|
||||||
model.rotateZ(blt::toRadians(rot));
|
|
||||||
|
|
||||||
shader->setMatrix("model", model);
|
|
||||||
|
|
||||||
vao->bind();
|
|
||||||
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
void init()
|
void init()
|
||||||
{
|
{
|
||||||
using namespace blt::gfx;
|
using namespace blt::gfx;
|
||||||
|
|
||||||
vbo_t vertices_vbo;
|
|
||||||
vbo_t indices_vbo;
|
|
||||||
|
|
||||||
vertices_vbo.create();
|
|
||||||
indices_vbo.create(GL_ELEMENT_ARRAY_BUFFER);
|
|
||||||
|
|
||||||
vertices_vbo.allocate(sizeof(vertices), vertices);
|
|
||||||
indices_vbo.allocate(sizeof(indices), indices);
|
|
||||||
|
|
||||||
vao = new vertex_array();
|
|
||||||
vao->bindVBO(vertices_vbo, 0, 3, GL_FLOAT, 5 * sizeof(float), 0);
|
|
||||||
vao->bindVBO(vertices_vbo, 1, 2, GL_FLOAT, 5 * sizeof(float), 3 * sizeof(float));
|
|
||||||
vao->bindElement(indices_vbo);
|
|
||||||
|
|
||||||
shader = new shader_t(shader_test_vert, shader_test_frag);
|
|
||||||
shader->bindAttribute(0, "vertex");
|
|
||||||
shader->bindAttribute(1, "uv_in");
|
|
||||||
|
|
||||||
resources.enqueue("../resources/textures/cumdollar.jpg", "ibuythat");
|
resources.enqueue("../resources/textures/cumdollar.jpg", "ibuythat");
|
||||||
resources.enqueue("../resources/textures/dfoedbi-28157978-1555-45c3-b2f4-d5e5fe25b253.png", "niko");
|
resources.enqueue("../resources/textures/dfoedbi-28157978-1555-45c3-b2f4-d5e5fe25b253.png", "niko");
|
||||||
|
|
||||||
global_matrices.create_internals();
|
global_matrices.create_internals();
|
||||||
resources.load_resources();
|
resources.load_resources();
|
||||||
|
renderer_2d.create();
|
||||||
}
|
}
|
||||||
|
|
||||||
void update(std::int32_t width, std::int32_t height)
|
void update(std::int32_t width, std::int32_t height)
|
||||||
{
|
{
|
||||||
global_matrices.update_perspectives(width, height);
|
global_matrices.update_perspectives(width, height);
|
||||||
ImGui::ShowDemoWindow();
|
ImGui::ShowDemoWindow();
|
||||||
ImGui::SetNextWindowSize(ImVec2(150, 65));
|
ImGui::SetNextWindowSize(ImVec2(150, 85));
|
||||||
ImGui::Begin("Debug Info Panel", nullptr, ImGuiWindowFlags_NoResize);
|
ImGui::Begin("Debug Info Panel", nullptr, ImGuiWindowFlags_NoResize);
|
||||||
ImGui::Text("%s FPS: %f", ICON_FA_WRENCH, 1.0e9 / static_cast<double>(blt::gfx::getFrameDelta()));
|
ImGui::Text("%s FPS: %f", ICON_FA_WRENCH, 1.0e9 / static_cast<double>(blt::gfx::getFrameDelta()));
|
||||||
|
ImGui::Text("Draw Count: %zu", renderer_2d.draw_count());
|
||||||
ImGui::End();
|
ImGui::End();
|
||||||
|
|
||||||
handle_input();
|
handle_input();
|
||||||
|
|
||||||
global_matrices.update();
|
global_matrices.update();
|
||||||
|
|
||||||
shader->bind();
|
|
||||||
|
|
||||||
const float w = 120, h = 120, cf = 30, rf = 15, crf = 10;
|
const float w = 120, h = 120, cf = 30, rf = 15, crf = 10;
|
||||||
|
|
||||||
glActiveTexture(GL_TEXTURE0);
|
renderer_2d.drawRectangle("ibuythat", blt::gfx::rectangle_t(width/2.0, height/2.0, width, height, 90));
|
||||||
resources.get("ibuythat")->bind();
|
renderer_2d.drawRectangle("niko", {bx, by, w, h});
|
||||||
draw(width / 2.0, height / 2.0, width, height, 90);
|
|
||||||
|
|
||||||
resources.get("niko")->bind();
|
|
||||||
draw(bx, by, w, h, 0);
|
|
||||||
|
|
||||||
bx += mx * blt::gfx::getFrameDeltaSeconds() * cf;
|
bx += mx * blt::gfx::getFrameDeltaSeconds() * cf;
|
||||||
by += my * blt::gfx::getFrameDeltaSeconds() * cf;
|
by += my * blt::gfx::getFrameDeltaSeconds() * cf;
|
||||||
|
@ -131,15 +94,16 @@ void update(std::int32_t width, std::int32_t height)
|
||||||
}
|
}
|
||||||
if (my > 100 || my < -100)
|
if (my > 100 || my < -100)
|
||||||
my = my * 0.2;
|
my = my * 0.2;
|
||||||
|
|
||||||
|
renderer_2d.render();
|
||||||
}
|
}
|
||||||
|
|
||||||
int main()
|
int main()
|
||||||
{
|
{
|
||||||
blt::gfx::init(blt::gfx::window_data{"My Sexy Window", init, update}.setSyncInterval(1));
|
blt::gfx::init(blt::gfx::window_data{"My Sexy Window", init, update}.setSyncInterval(1));
|
||||||
delete vao;
|
|
||||||
delete shader;
|
|
||||||
global_matrices.cleanup();
|
global_matrices.cleanup();
|
||||||
resources.cleanup();
|
resources.cleanup();
|
||||||
|
renderer_2d.cleanup();
|
||||||
blt::gfx::cleanup();
|
blt::gfx::cleanup();
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue