Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
//
// RenderBatch.hpp
// Disco Rocket Library
//
// ----------------------------------------------------------------------------
//
// Created by Jacob Milligan on 9/12/2016.
// Copyright (c) 2016 Jacob Milligan All rights reserved.
//
#ifndef DISCO_ROCKET_RENDERBATCH_HPP
#define DISCO_ROCKET_RENDERBATCH_HPP
#include <array>
#include "DiscoRocket/Core/Math/Matrix4.hpp"
#include "DiscoRocket/Platform/DiscoGL.hpp"
#include "DiscoRocket/Graphics/Shader.hpp"
#include "DiscoRocket/Graphics/RenderData.hpp"
namespace disco {
struct Rectangle;
struct Color;
class Camera;
class Window;
struct Vertex {
float x;
float y;
float z;
uint8_t r;
uint8_t g;
uint8_t b;
uint8_t a;
};
class RenderBatch {
public:
static constexpr int batch_max = 4096;
RenderBatch(const Window& window);
RenderBatch(const Vector2& view_size);
RenderBatch(const int view_width, const int view_height);
~RenderBatch();
void start();
void finish();
void fill_rectangle(const Rectangle& rect, const Color& color);
private:
int next_, draw_calls_;
static constexpr int num_vertices_ = batch_max * 4;
static constexpr int num_indices_ = batch_max * 6;
Matrix4 projection_;
Matrix4 view_;
// Debug uniforms
GLint projloc_;
// Primitive VAOs
GLuint quad_VAO_;
std::array<GLuint, 2> bufobjs_;
std::array<Vertex, num_vertices_> vertices_;
std::array<GLuint, num_indices_> indices_;
Shader debug_shader_;
};
}
#endif //DISCO_ROCKET_RENDERBATCH_HPP
//
// RenderBatch.cpp
// Disco Rocket Library
//
// ----------------------------------------------------------------------------
//
// Created by Jacob Milligan on 9/12/2016.
// Copyright (c) 2016 Jacob Milligan All rights reserved.
//
#include "DiscoRocket/Graphics/RenderBatch.hpp"
#include "DiscoRocket/Graphics/DebugShaders.hpp"
#include "DiscoRocket/Graphics/Rectangle.hpp"
#include "DiscoRocket/Graphics/Window.hpp"
namespace disco {
RenderBatch::RenderBatch(const int view_width, const int view_height)
: RenderBatch(Vector2(view_width, view_height)) {}
RenderBatch::RenderBatch(const Window& window)
: RenderBatch(window.size()) {}
RenderBatch::RenderBatch(const Vector2& view_size)
: next_(0)
{
GLuint vert = 0, indices_per_vert = 6;
for(GLuint i = 0; i < indices_.size(); i += indices_per_vert)
{
vert = i * 4;
indices_[i] = vert;
indices_[i + 1] = 1 + vert;
indices_[i + 2] = 2 + vert;
indices_[i + 3] = vert;
indices_[i + 4] = 2 + vert;
indices_[i + 5] = 3 + vert;
}
glGenVertexArrays(1, &quad_VAO_);
glGenBuffers(2, bufobjs_.data());
glBindVertexArray(quad_VAO_);
glBindBuffer(GL_ARRAY_BUFFER, bufobjs_[0]);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices_), vertices_.data(),
GL_DYNAMIC_DRAW);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, bufobjs_[1]);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices_), indices_.data(),
GL_DYNAMIC_DRAW);
glEnableVertexAttribArray(0);
glEnableVertexAttribArray(1);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), 0);
glVertexAttribPointer(1, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(Vertex),
(GLvoid*)offsetof(Vertex, r));
glBindVertexArray(0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
// For debugging purposes
projection_ = projection_.ortho(0.0f, view_size.x, view_size.y, 0.0f);
debug_shader_.compile(debug_shader_vert, debug_shader_frag);
projloc_ = glGetUniformLocation(debug_shader_.id, "projection");
viewloc_ = glGetUniformLocation(debug_shader_.id, "view");
debug_shader_.use();
glUniformMatrix4fv(projloc_, 1, GL_FALSE, &projection_[0][0]);
glUniformMatrix4fv(viewloc_, 1, GL_FALSE, &view_[0][0]);
}
RenderBatch::~RenderBatch()
{
glDeleteBuffers(2, bufobjs_.data());
glDeleteVertexArrays(1, &quad_VAO_);
}
void RenderBatch::start()
{
next_ = 0;
draw_calls_ = 0;
glBindVertexArray(quad_VAO_);
glBindBuffer(GL_ARRAY_BUFFER, bufobjs_[0]);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, bufobjs_[1]);
}
void RenderBatch::finish()
{
if ( draw_calls_ <= 0 )
return;
glBufferSubData(GL_ARRAY_BUFFER, 0,
next_ * sizeof(Vertex), vertices_.data());
glDrawElements(GL_TRIANGLES, draw_calls_ * 6, GL_UNSIGNED_INT, nullptr);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
glBindVertexArray(0);
disco_gl_get_error();
}
void RenderBatch::fill_rectangle(const Rectangle& rect, const Color& color)
{
auto scaled_alpha = static_cast<uint8_t>(color.a * 255.0f); // scale from normalized to 0-255 value
// Top left
auto v = &vertices_[next_++];
v->r = color.r;
v->g = color.g;
v->b = color.b;
v->a = scaled_alpha;
v->x = rect.position.x;
v->y = rect.position.y;
v->z = 0.0f;
// Top right
v = &vertices_[next_++];
v->r = color.r;
v->g = color.g;
v->b = color.b;
v->a = scaled_alpha;
v->x = rect.position.x + rect.width;
v->y = rect.position.y;
v->z = 0.0f;
// Bottom right
v = &vertices_[next_++];
v->r = color.r;
v->g = color.g;
v->b = color.b;
v->a = scaled_alpha;
v->x = rect.position.x + rect.width;
v->y = rect.position.y + rect.height;
v->z = 0.0f;
// Bottom left
v = &vertices_[next_++];
v->r = color.r;
v->g = color.g;
v->b = color.b;
v->a = scaled_alpha;
v->x = rect.position.x;
v->y = rect.position.y + rect.height;
v->z = 0.0f;
draw_calls_++;
if ( next_ >= vertices_.size() ) {
finish();
start();
}
}
}
//
// DebugShaders.hpp
// Disco Rocket Library
//
// ----------------------------------------------------------------------------
//
// Created by Jacob Milligan on 9/12/2016.
// Copyright (c) 2016 Jacob Milligan All rights reserved.
//
#ifndef DISCO_ROCKET_DEBUGSHADERS_HPP
#define DISCO_ROCKET_DEBUGSHADERS_HPP
namespace disco {
static const char* debug_shader_vert = R"(
#version 330 core
layout (location = 0) in vec3 position;
layout (location = 1) in vec4 color;
out vec4 frag_color;
uniform mat4 projection;
void main() {
gl_Position = projection * vec4(position, 1.0f);
frag_color = color;
}
)";
static const char* debug_shader_frag = R"(
#version 330 core
out vec4 color;
in vec4 frag_color;
void main() {
color = frag_color;
}
)";
}
#endif //DISCO_ROCKET_DEBUGSHADERS_HPP
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.