Refactor mesh handling to use templated vertex structures for improved type safety and flexibility
This commit is contained in:
@@ -8,15 +8,10 @@
|
||||
|
||||
#include <cmath>
|
||||
|
||||
inline constexpr uint B2D_VERTEX_SIZE = 8;
|
||||
|
||||
Batch2D::Batch2D(size_t capacity) : capacity(capacity), color(1.0f){
|
||||
const VertexAttribute attrs[] = {
|
||||
{2}, {2}, {4}, {0}
|
||||
};
|
||||
|
||||
buffer = std::make_unique<float[]>(capacity * B2D_VERTEX_SIZE);
|
||||
mesh = std::make_unique<Mesh>(buffer.get(), 0, attrs);
|
||||
buffer = std::make_unique<Batch2DVertex[]>(capacity );
|
||||
mesh = std::make_unique<Mesh<Batch2DVertex>>(buffer.get(), 0, Batch2DVertex::ATTRIBUTES);
|
||||
index = 0;
|
||||
|
||||
const ubyte pixels[] = {
|
||||
@@ -51,28 +46,20 @@ void Batch2D::vertex(
|
||||
float u, float v,
|
||||
float r, float g, float b, float a
|
||||
) {
|
||||
buffer[index++] = x;
|
||||
buffer[index++] = y;
|
||||
buffer[index++] = u * region.getWidth() + region.u1;
|
||||
buffer[index++] = v * region.getHeight() + region.v1;
|
||||
buffer[index++] = r;
|
||||
buffer[index++] = g;
|
||||
buffer[index++] = b;
|
||||
buffer[index++] = a;
|
||||
buffer[index].position = {x, y};
|
||||
buffer[index].uv = {u * region.getWidth() + region.u1, v * region.getHeight() + region.v1};
|
||||
buffer[index].color = {r, g, b, a};
|
||||
index++;
|
||||
}
|
||||
void Batch2D::vertex(
|
||||
glm::vec2 point,
|
||||
glm::vec2 uvpoint,
|
||||
float r, float g, float b, float a
|
||||
) {
|
||||
buffer[index++] = point.x;
|
||||
buffer[index++] = point.y;
|
||||
buffer[index++] = uvpoint.x * region.getWidth() + region.u1;
|
||||
buffer[index++] = uvpoint.y * region.getHeight() + region.v1;
|
||||
buffer[index++] = r;
|
||||
buffer[index++] = g;
|
||||
buffer[index++] = b;
|
||||
buffer[index++] = a;
|
||||
buffer[index].position = point;
|
||||
buffer[index].uv = {uvpoint.x * region.getWidth() + region.u1, uvpoint.y * region.getHeight() + region.v1};
|
||||
buffer[index].color = {r, g, b, a};
|
||||
index++;
|
||||
}
|
||||
|
||||
void Batch2D::texture(const Texture* new_texture){
|
||||
@@ -99,14 +86,14 @@ void Batch2D::setRegion(UVRegion region) {
|
||||
}
|
||||
|
||||
void Batch2D::point(float x, float y, float r, float g, float b, float a){
|
||||
if (index + 6*B2D_VERTEX_SIZE >= capacity)
|
||||
if (index + 6 >= capacity)
|
||||
flush();
|
||||
setPrimitive(DrawPrimitive::point);
|
||||
vertex(x, y, 0, 0, r,g,b,a);
|
||||
}
|
||||
|
||||
void Batch2D::line(float x1, float y1, float x2, float y2, float r, float g, float b, float a){
|
||||
if (index + 6*B2D_VERTEX_SIZE >= capacity) {
|
||||
if (index + 6 >= capacity) {
|
||||
flush();
|
||||
}
|
||||
setPrimitive(DrawPrimitive::line);
|
||||
@@ -119,7 +106,7 @@ void Batch2D::rect(float x, float y, float w, float h){
|
||||
const float g = color.g;
|
||||
const float b = color.b;
|
||||
const float a = color.a;
|
||||
if (index + 6*B2D_VERTEX_SIZE >= capacity) {
|
||||
if (index + 6 >= capacity) {
|
||||
flush();
|
||||
}
|
||||
setPrimitive(DrawPrimitive::triangle);
|
||||
@@ -142,7 +129,7 @@ void Batch2D::rect(
|
||||
bool flippedY,
|
||||
glm::vec4 tint
|
||||
) {
|
||||
if (index + 6 * B2D_VERTEX_SIZE >= capacity) {
|
||||
if (index + 6 >= capacity) {
|
||||
flush();
|
||||
}
|
||||
setPrimitive(DrawPrimitive::triangle);
|
||||
@@ -230,14 +217,14 @@ void Batch2D::rect(
|
||||
}
|
||||
|
||||
void Batch2D::lineRect(float x, float y, float w, float h) {
|
||||
if (index + 8 * B2D_VERTEX_SIZE >= capacity) {
|
||||
if (index + 8 >= capacity) {
|
||||
flush();
|
||||
}
|
||||
setPrimitive(DrawPrimitive::line);
|
||||
|
||||
vertex(x, y, 0.0f, 0.0f, color.r, color.g, color.b, color.a);
|
||||
vertex(x, y+h, 0.0f, 1.0f, color.r, color.g, color.b, color.a);
|
||||
|
||||
|
||||
vertex(x, y+h, 0.0f, 1.0f, color.r, color.g, color.b, color.a);
|
||||
vertex(x+w, y+h, 1.0f, 1.0f, color.r, color.g, color.b, color.a);
|
||||
|
||||
@@ -253,7 +240,7 @@ void Batch2D::rect(
|
||||
float u, float v, float tx, float ty,
|
||||
float r, float g, float b, float a
|
||||
){
|
||||
if (index + 6*B2D_VERTEX_SIZE >= capacity) {
|
||||
if (index + 6 >= capacity) {
|
||||
flush();
|
||||
}
|
||||
setPrimitive(DrawPrimitive::triangle);
|
||||
@@ -271,7 +258,7 @@ void Batch2D::parallelogram(
|
||||
float u, float v, float tx, float ty,
|
||||
float r, float g, float b, float a
|
||||
){
|
||||
if (index + 6*B2D_VERTEX_SIZE >= capacity) {
|
||||
if (index + 6 >= capacity) {
|
||||
flush();
|
||||
}
|
||||
setPrimitive(DrawPrimitive::triangle);
|
||||
@@ -292,7 +279,7 @@ void Batch2D::rect(
|
||||
float r3, float g3, float b3,
|
||||
float r4, float g4, float b4, int sh
|
||||
){
|
||||
if (index + 30*B2D_VERTEX_SIZE >= capacity) {
|
||||
if (index + 30 >= capacity) {
|
||||
flush();
|
||||
}
|
||||
setPrimitive(DrawPrimitive::triangle);
|
||||
@@ -378,7 +365,7 @@ void Batch2D::sprite(
|
||||
void Batch2D::flush() {
|
||||
if (index == 0)
|
||||
return;
|
||||
mesh->reload(buffer.get(), index / B2D_VERTEX_SIZE);
|
||||
mesh->reload(buffer.get(), index);
|
||||
mesh->draw(gl::to_glenum(primitive));
|
||||
index = 0;
|
||||
}
|
||||
|
||||
@@ -1,19 +1,33 @@
|
||||
#pragma once
|
||||
|
||||
#include <memory>
|
||||
#include <stdlib.h>
|
||||
#include <glm/glm.hpp>
|
||||
|
||||
#include "commons.hpp"
|
||||
#include "maths/UVRegion.hpp"
|
||||
#include "MeshData.hpp"
|
||||
|
||||
template<typename VertexStructure>
|
||||
class Mesh;
|
||||
class Texture;
|
||||
|
||||
struct Batch2DVertex {
|
||||
glm::vec2 position;
|
||||
glm::vec2 uv;
|
||||
glm::vec4 color;
|
||||
|
||||
static constexpr VertexAttribute ATTRIBUTES[] {
|
||||
{GL_FLOAT, false, 2},
|
||||
{GL_FLOAT, false,2},
|
||||
{GL_FLOAT, false, 4},
|
||||
{0}
|
||||
};
|
||||
};
|
||||
|
||||
class Batch2D : public Flushable {
|
||||
std::unique_ptr<float[]> buffer;
|
||||
std::unique_ptr<Batch2DVertex[]> buffer;
|
||||
size_t capacity;
|
||||
std::unique_ptr<Mesh> mesh;
|
||||
std::unique_ptr<Mesh<Batch2DVertex>> mesh;
|
||||
std::unique_ptr<Texture> blank;
|
||||
size_t index;
|
||||
glm::vec4 color;
|
||||
|
||||
@@ -7,17 +7,12 @@
|
||||
#include "typedefs.hpp"
|
||||
#include "maths/UVRegion.hpp"
|
||||
|
||||
/// xyz, uv, rgba
|
||||
inline constexpr uint B3D_VERTEX_SIZE = 9;
|
||||
|
||||
Batch3D::Batch3D(size_t capacity)
|
||||
Batch3D::Batch3D(size_t capacity)
|
||||
: capacity(capacity) {
|
||||
const VertexAttribute attrs[] = {
|
||||
{3}, {2}, {4}, {0}
|
||||
};
|
||||
|
||||
buffer = std::make_unique<float[]>(capacity * B3D_VERTEX_SIZE);
|
||||
mesh = std::make_unique<Mesh>(buffer.get(), 0, attrs);
|
||||
|
||||
buffer = std::make_unique<Batch3DVertex[]>(capacity);
|
||||
mesh = std::make_unique<Mesh<Batch3DVertex>>(buffer.get(), 0, Batch3DVertex::ATTRIBUTES);
|
||||
index = 0;
|
||||
|
||||
const ubyte pixels[] = {
|
||||
@@ -40,69 +35,54 @@ void Batch3D::vertex(
|
||||
float x, float y, float z, float u, float v,
|
||||
float r, float g, float b, float a
|
||||
) {
|
||||
buffer[index++] = x;
|
||||
buffer[index++] = y;
|
||||
buffer[index++] = z;
|
||||
buffer[index++] = u;
|
||||
buffer[index++] = v;
|
||||
buffer[index++] = r;
|
||||
buffer[index++] = g;
|
||||
buffer[index++] = b;
|
||||
buffer[index++] = a;
|
||||
buffer[index].position = {x, y, z};
|
||||
buffer[index].uv = {u, v};
|
||||
buffer[index].color = {r, g, b, a};
|
||||
index++;
|
||||
}
|
||||
void Batch3D::vertex(
|
||||
glm::vec3 coord, float u, float v,
|
||||
float r, float g, float b, float a
|
||||
) {
|
||||
buffer[index++] = coord.x;
|
||||
buffer[index++] = coord.y;
|
||||
buffer[index++] = coord.z;
|
||||
buffer[index++] = u;
|
||||
buffer[index++] = v;
|
||||
buffer[index++] = r;
|
||||
buffer[index++] = g;
|
||||
buffer[index++] = b;
|
||||
buffer[index++] = a;
|
||||
buffer[index].position = coord;
|
||||
buffer[index].uv = {u, v};
|
||||
buffer[index].color = {r, g, b, a};
|
||||
index++;
|
||||
}
|
||||
void Batch3D::vertex(
|
||||
glm::vec3 point,
|
||||
glm::vec2 uvpoint,
|
||||
float r, float g, float b, float a
|
||||
) {
|
||||
buffer[index++] = point.x;
|
||||
buffer[index++] = point.y;
|
||||
buffer[index++] = point.z;
|
||||
buffer[index++] = uvpoint.x;
|
||||
buffer[index++] = uvpoint.y;
|
||||
buffer[index++] = r;
|
||||
buffer[index++] = g;
|
||||
buffer[index++] = b;
|
||||
buffer[index++] = a;
|
||||
buffer[index].position = point;
|
||||
buffer[index].uv = uvpoint;
|
||||
buffer[index].color = {r, g, b, a};
|
||||
index++;
|
||||
}
|
||||
|
||||
void Batch3D::face(
|
||||
const glm::vec3& coord,
|
||||
const glm::vec3& coord,
|
||||
float w, float h,
|
||||
const glm::vec3& axisX,
|
||||
const glm::vec3& axisY,
|
||||
const UVRegion& region,
|
||||
const glm::vec4& tint
|
||||
) {
|
||||
if (index + B3D_VERTEX_SIZE * 6 > capacity) {
|
||||
if (index + 6 >= capacity) {
|
||||
flush();
|
||||
}
|
||||
vertex(coord, region.u1, region.v1,
|
||||
vertex(coord, region.u1, region.v1,
|
||||
tint.r, tint.g, tint.b, tint.a);
|
||||
vertex(coord + axisX * w, region.u2, region.v1,
|
||||
vertex(coord + axisX * w, region.u2, region.v1,
|
||||
tint.r, tint.g, tint.b, tint.a);
|
||||
vertex(coord + axisX * w + axisY * h, region.u2, region.v2,
|
||||
vertex(coord + axisX * w + axisY * h, region.u2, region.v2,
|
||||
tint.r, tint.g, tint.b, tint.a);
|
||||
|
||||
vertex(coord, region.u1, region.v1,
|
||||
vertex(coord, region.u1, region.v1,
|
||||
tint.r, tint.g, tint.b, tint.a);
|
||||
vertex(coord + axisX * w + axisY * h, region.u2, region.v2,
|
||||
tint.r, tint.g, tint.b, tint.a);
|
||||
vertex(coord + axisY * h, region.u1, region.v2,
|
||||
vertex(coord + axisY * h, region.u1, region.v2,
|
||||
tint.r, tint.g, tint.b, tint.a);
|
||||
}
|
||||
|
||||
@@ -134,18 +114,18 @@ void Batch3D::sprite(
|
||||
}
|
||||
|
||||
void Batch3D::sprite(
|
||||
const glm::vec3& pos,
|
||||
const glm::vec3& up,
|
||||
const glm::vec3& right,
|
||||
float w, float h,
|
||||
const UVRegion& uv,
|
||||
const glm::vec3& pos,
|
||||
const glm::vec3& up,
|
||||
const glm::vec3& right,
|
||||
float w, float h,
|
||||
const UVRegion& uv,
|
||||
const glm::vec4& color
|
||||
){
|
||||
const float r = color.r;
|
||||
const float g = color.g;
|
||||
const float b = color.b;
|
||||
const float a = color.a;
|
||||
if (index + 6*B3D_VERTEX_SIZE >= capacity) {
|
||||
if (index + 6 >= capacity) {
|
||||
flush();
|
||||
}
|
||||
|
||||
@@ -194,17 +174,17 @@ void Batch3D::xSprite(
|
||||
float w, float h, const UVRegion& uv, const glm::vec4& tint, bool shading
|
||||
) {
|
||||
face(
|
||||
glm::vec3(-w * 0.25f, 0.0f, -w * 0.25f),
|
||||
w, h,
|
||||
glm::vec3(1, 0, 0),
|
||||
glm::vec3(0, 1, 0),
|
||||
glm::vec3(-w * 0.25f, 0.0f, -w * 0.25f),
|
||||
w, h,
|
||||
glm::vec3(1, 0, 0),
|
||||
glm::vec3(0, 1, 0),
|
||||
uv, (shading ? do_tint(1.0f)*tint : tint)
|
||||
);
|
||||
face(
|
||||
glm::vec3(w * 0.25f, 0.0f, w * 0.5f - w * 0.25f),
|
||||
glm::vec3(w * 0.25f, 0.0f, w * 0.5f - w * 0.25f),
|
||||
w, h,
|
||||
glm::vec3(0, 0, -1),
|
||||
glm::vec3(0, 1, 0),
|
||||
glm::vec3(0, 0, -1),
|
||||
glm::vec3(0, 1, 0),
|
||||
uv, (shading ? do_tint(0.9f)*tint : tint)
|
||||
);
|
||||
}
|
||||
@@ -221,41 +201,41 @@ void Batch3D::cube(
|
||||
const glm::vec3 Z(0.0f, 0.0f, 1.0f);
|
||||
|
||||
face(
|
||||
coord+glm::vec3(0.0f, 0.0f, 0.0f),
|
||||
size.x, size.y, X, Y, texfaces[5],
|
||||
coord+glm::vec3(0.0f, 0.0f, 0.0f),
|
||||
size.x, size.y, X, Y, texfaces[5],
|
||||
(shading ? do_tint(0.8)*tint : tint)
|
||||
);
|
||||
face(
|
||||
coord+glm::vec3(size.x, 0.0f, -size.z),
|
||||
size.x, size.y, -X, Y, texfaces[4],
|
||||
coord+glm::vec3(size.x, 0.0f, -size.z),
|
||||
size.x, size.y, -X, Y, texfaces[4],
|
||||
(shading ? do_tint(0.8f)*tint : tint)
|
||||
);
|
||||
face(
|
||||
coord+glm::vec3(0.0f, size.y, 0.0f),
|
||||
size.x, size.z, X, -Z, texfaces[3],
|
||||
coord+glm::vec3(0.0f, size.y, 0.0f),
|
||||
size.x, size.z, X, -Z, texfaces[3],
|
||||
(shading ? do_tint(1.0f)*tint : tint)
|
||||
);
|
||||
face(
|
||||
coord+glm::vec3(0.0f, 0.0f, -size.z),
|
||||
size.x, size.z, X, Z, texfaces[2],
|
||||
coord+glm::vec3(0.0f, 0.0f, -size.z),
|
||||
size.x, size.z, X, Z, texfaces[2],
|
||||
(shading ? do_tint(0.7f)*tint : tint)
|
||||
);
|
||||
face(
|
||||
coord+glm::vec3(0.0f, 0.0f, -size.z),
|
||||
size.z, size.y, Z, Y, texfaces[0],
|
||||
coord+glm::vec3(0.0f, 0.0f, -size.z),
|
||||
size.z, size.y, Z, Y, texfaces[0],
|
||||
(shading ? do_tint(0.9f)*tint : tint)
|
||||
);
|
||||
face(
|
||||
coord+glm::vec3(size.x, 0.0f, 0.0f),
|
||||
size.z, size.y, -Z, Y, texfaces[1],
|
||||
coord+glm::vec3(size.x, 0.0f, 0.0f),
|
||||
size.z, size.y, -Z, Y, texfaces[1],
|
||||
(shading ? do_tint(0.9f)*tint : tint)
|
||||
);
|
||||
}
|
||||
|
||||
void Batch3D::blockCube(
|
||||
const glm::vec3& size,
|
||||
const UVRegion(&texfaces)[6],
|
||||
const glm::vec4& tint,
|
||||
const glm::vec3& size,
|
||||
const UVRegion(&texfaces)[6],
|
||||
const glm::vec4& tint,
|
||||
bool shading
|
||||
) {
|
||||
cube((1.0f - size) * -0.5f, size, texfaces, tint, shading);
|
||||
@@ -264,27 +244,27 @@ void Batch3D::blockCube(
|
||||
void Batch3D::vertex(
|
||||
const glm::vec3& coord, const glm::vec2& uv, const glm::vec4& tint
|
||||
) {
|
||||
if (index + B3D_VERTEX_SIZE >= capacity) {
|
||||
if (index + 1 >= capacity) {
|
||||
flush();
|
||||
}
|
||||
vertex(coord, uv, tint.r, tint.g, tint.b, tint.a);
|
||||
}
|
||||
|
||||
void Batch3D::point(const glm::vec3& coord, const glm::vec4& tint) {
|
||||
if (index + B3D_VERTEX_SIZE >= capacity) {
|
||||
if (index + 1 >= capacity) {
|
||||
flushPoints();
|
||||
}
|
||||
vertex(coord, {}, tint.r, tint.g, tint.b, tint.a);
|
||||
}
|
||||
|
||||
void Batch3D::flush() {
|
||||
mesh->reload(buffer.get(), index / B3D_VERTEX_SIZE);
|
||||
mesh->reload(buffer.get(), index);
|
||||
mesh->draw();
|
||||
index = 0;
|
||||
}
|
||||
|
||||
void Batch3D::flushPoints() {
|
||||
mesh->reload(buffer.get(), index / B3D_VERTEX_SIZE);
|
||||
mesh->reload(buffer.get(), index);
|
||||
mesh->draw(GL_POINTS);
|
||||
index = 0;
|
||||
}
|
||||
|
||||
@@ -2,19 +2,34 @@
|
||||
|
||||
#include "typedefs.hpp"
|
||||
#include "commons.hpp"
|
||||
#include "MeshData.hpp"
|
||||
|
||||
#include <memory>
|
||||
#include <stdlib.h>
|
||||
#include <cstdlib>
|
||||
#include <glm/glm.hpp>
|
||||
|
||||
class Mesh;
|
||||
template<typename VertexStructure> class Mesh;
|
||||
|
||||
class Texture;
|
||||
struct UVRegion;
|
||||
|
||||
struct Batch3DVertex {
|
||||
glm::vec3 position;
|
||||
glm::vec2 uv;
|
||||
glm::vec4 color;
|
||||
|
||||
static constexpr VertexAttribute ATTRIBUTES[] {
|
||||
{GL_FLOAT, false, 3},
|
||||
{GL_FLOAT, false, 2},
|
||||
{GL_FLOAT, false, 4},
|
||||
{0}
|
||||
};
|
||||
};
|
||||
|
||||
class Batch3D : public Flushable {
|
||||
std::unique_ptr<float[]> buffer;
|
||||
std::unique_ptr<Batch3DVertex[]> buffer;
|
||||
size_t capacity;
|
||||
std::unique_ptr<Mesh> mesh;
|
||||
std::unique_ptr<Mesh<Batch3DVertex>> mesh;
|
||||
std::unique_ptr<Texture> blank;
|
||||
size_t index;
|
||||
glm::vec4 tint {1.0f};
|
||||
|
||||
@@ -3,12 +3,11 @@
|
||||
|
||||
#include <GL/glew.h>
|
||||
|
||||
inline constexpr uint LB_VERTEX_SIZE = (3+4);
|
||||
|
||||
LineBatch::LineBatch(size_t capacity) : capacity(capacity) {
|
||||
const VertexAttribute attrs[] = { {3},{4}, {0} };
|
||||
buffer = std::make_unique<float[]>(capacity * LB_VERTEX_SIZE * 2);
|
||||
mesh = std::make_unique<Mesh>(buffer.get(), 0, attrs);
|
||||
|
||||
buffer = std::make_unique<LineVertex[]>(capacity * 2);
|
||||
mesh = std::make_unique<Mesh<LineVertex>>(buffer.get(), 0, LineVertex::ATTRIBUTES);
|
||||
index = 0;
|
||||
}
|
||||
|
||||
@@ -16,31 +15,21 @@ LineBatch::~LineBatch(){
|
||||
}
|
||||
|
||||
void LineBatch::line(
|
||||
float x1, float y1,
|
||||
float z1, float x2,
|
||||
float x1, float y1,
|
||||
float z1, float x2,
|
||||
float y2, float z2,
|
||||
float r, float g, float b, float a
|
||||
) {
|
||||
if (index + LB_VERTEX_SIZE * 2 >= capacity) {
|
||||
if (index + 2 >= capacity) {
|
||||
flush();
|
||||
}
|
||||
buffer[index] = x1;
|
||||
buffer[index+1] = y1;
|
||||
buffer[index+2] = z1;
|
||||
buffer[index+3] = r;
|
||||
buffer[index+4] = g;
|
||||
buffer[index+5] = b;
|
||||
buffer[index+6] = a;
|
||||
index += LB_VERTEX_SIZE;
|
||||
buffer[index].position = {x1,y1,z1};
|
||||
buffer[index].color = {r,g,b,a};
|
||||
index++;
|
||||
|
||||
buffer[index] = x2;
|
||||
buffer[index+1] = y2;
|
||||
buffer[index+2] = z2;
|
||||
buffer[index+3] = r;
|
||||
buffer[index+4] = g;
|
||||
buffer[index+5] = b;
|
||||
buffer[index+6] = a;
|
||||
index += LB_VERTEX_SIZE;
|
||||
buffer[index].position = {x2,y2,z2};
|
||||
buffer[index].color = {r,g,b,a};
|
||||
index++;
|
||||
}
|
||||
|
||||
void LineBatch::box(float x, float y, float z, float w, float h, float d,
|
||||
@@ -68,7 +57,7 @@ void LineBatch::box(float x, float y, float z, float w, float h, float d,
|
||||
void LineBatch::flush(){
|
||||
if (index == 0)
|
||||
return;
|
||||
mesh->reload(buffer.get(), index / LB_VERTEX_SIZE);
|
||||
mesh->reload(buffer.get(), index);
|
||||
mesh->draw(GL_LINES);
|
||||
index = 0;
|
||||
}
|
||||
|
||||
@@ -5,12 +5,21 @@
|
||||
#include <glm/glm.hpp>
|
||||
|
||||
#include "commons.hpp"
|
||||
#include "MeshData.hpp"
|
||||
|
||||
template<typename VertexStructure>
|
||||
class Mesh;
|
||||
|
||||
struct LineVertex {
|
||||
glm::vec3 position;
|
||||
glm::vec4 color;
|
||||
|
||||
static constexpr VertexAttribute ATTRIBUTES[] { {GL_FLOAT,false,3},{GL_FLOAT,false,4}, {0} };
|
||||
};
|
||||
|
||||
class LineBatch : public Flushable {
|
||||
std::unique_ptr<Mesh> mesh;
|
||||
std::unique_ptr<float[]> buffer;
|
||||
std::unique_ptr<Mesh<LineVertex>> mesh;
|
||||
std::unique_ptr<LineVertex[]> buffer;
|
||||
size_t index;
|
||||
size_t capacity;
|
||||
public:
|
||||
|
||||
@@ -1,93 +1,8 @@
|
||||
#include "Mesh.hpp"
|
||||
#include <assert.h>
|
||||
#include <GL/glew.h>
|
||||
//
|
||||
// Created by RED on 24.03.2025.
|
||||
//
|
||||
|
||||
int Mesh::meshesCount = 0;
|
||||
int Mesh::drawCalls = 0;
|
||||
#include "graphics/core/Mesh.hpp"
|
||||
|
||||
inline size_t calc_vertex_size(const VertexAttribute* attrs) {
|
||||
size_t vertexSize = 0;
|
||||
for (int i = 0; attrs[i].size; i++) {
|
||||
vertexSize += attrs[i].size;
|
||||
}
|
||||
assert(vertexSize != 0);
|
||||
return vertexSize;
|
||||
}
|
||||
|
||||
Mesh::Mesh(const MeshData& data)
|
||||
: Mesh(data.vertices.data(),
|
||||
data.vertices.size() / calc_vertex_size(data.attrs.data()),
|
||||
data.indices.data(),
|
||||
data.indices.size(),
|
||||
data.attrs.data()) {}
|
||||
|
||||
Mesh::Mesh(const float* vertexBuffer, size_t vertices, const int* indexBuffer, size_t indices, const VertexAttribute* attrs) :
|
||||
ibo(0),
|
||||
vertices(0),
|
||||
indices(0)
|
||||
{
|
||||
meshesCount++;
|
||||
vertexSize = 0;
|
||||
for (int i = 0; attrs[i].size; i++) {
|
||||
vertexSize += attrs[i].size;
|
||||
}
|
||||
|
||||
glGenVertexArrays(1, &vao);
|
||||
glGenBuffers(1, &vbo);
|
||||
|
||||
reload(vertexBuffer, vertices, indexBuffer, indices);
|
||||
|
||||
// attributes
|
||||
int offset = 0;
|
||||
for (int i = 0; attrs[i].size; i++) {
|
||||
int size = attrs[i].size;
|
||||
glVertexAttribPointer(i, size, GL_FLOAT, GL_FALSE, vertexSize * sizeof(float), (GLvoid*)(offset * sizeof(float)));
|
||||
glEnableVertexAttribArray(i);
|
||||
offset += size;
|
||||
}
|
||||
|
||||
glBindVertexArray(0);
|
||||
}
|
||||
|
||||
Mesh::~Mesh(){
|
||||
meshesCount--;
|
||||
glDeleteVertexArrays(1, &vao);
|
||||
glDeleteBuffers(1, &vbo);
|
||||
if (ibo != 0) glDeleteBuffers(1, &ibo);
|
||||
}
|
||||
|
||||
void Mesh::reload(const float* vertexBuffer, size_t vertices, const int* indexBuffer, size_t indices){
|
||||
glBindVertexArray(vao);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, vbo);
|
||||
if (vertexBuffer != nullptr && vertices != 0) {
|
||||
glBufferData(GL_ARRAY_BUFFER, sizeof(float) * vertexSize * vertices, vertexBuffer, GL_STREAM_DRAW);
|
||||
} else {
|
||||
glBufferData(GL_ARRAY_BUFFER, 0, {}, GL_STREAM_DRAW);
|
||||
}
|
||||
if (indexBuffer != nullptr && indices != 0) {
|
||||
if (ibo == 0) glGenBuffers(1, &ibo);
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo);
|
||||
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(int) * indices, indexBuffer, GL_STATIC_DRAW);
|
||||
}
|
||||
else if (ibo != 0) {
|
||||
glDeleteBuffers(1, &ibo);
|
||||
}
|
||||
this->vertices = vertices;
|
||||
this->indices = indices;
|
||||
}
|
||||
|
||||
void Mesh::draw(unsigned int primitive) const {
|
||||
drawCalls++;
|
||||
glBindVertexArray(vao);
|
||||
if (ibo != 0) {
|
||||
glDrawElements(primitive, indices, GL_UNSIGNED_INT, 0);
|
||||
}
|
||||
else {
|
||||
glDrawArrays(primitive, 0, vertices);
|
||||
}
|
||||
glBindVertexArray(0);
|
||||
}
|
||||
|
||||
void Mesh::draw() const {
|
||||
draw(GL_TRIANGLES);
|
||||
}
|
||||
int MeshStats::meshesCount = 0;
|
||||
int MeshStats::drawCalls = 0;
|
||||
+27
-15
@@ -1,31 +1,43 @@
|
||||
#pragma once
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "typedefs.hpp"
|
||||
#include "MeshData.hpp"
|
||||
|
||||
|
||||
struct MeshStats {
|
||||
static int meshesCount;
|
||||
static int drawCalls;
|
||||
};
|
||||
|
||||
|
||||
template<typename VertexStructure>
|
||||
class Mesh {
|
||||
unsigned int vao;
|
||||
unsigned int vbo;
|
||||
unsigned int ibo;
|
||||
size_t vertices;
|
||||
size_t indices;
|
||||
size_t vertexCount;
|
||||
size_t indexCount;
|
||||
size_t vertexSize;
|
||||
|
||||
public:
|
||||
Mesh(const MeshData& data);
|
||||
Mesh(const float* vertexBuffer, size_t vertices, const int* indexBuffer, size_t indices, const VertexAttribute* attrs);
|
||||
Mesh(const float* vertexBuffer, size_t vertices, const VertexAttribute* attrs) :
|
||||
Mesh(vertexBuffer, vertices, nullptr, 0, attrs) {};
|
||||
explicit Mesh(const MeshData<VertexStructure> &data);
|
||||
|
||||
Mesh(const VertexStructure *vertexBuffer, size_t vertices, const uint32_t *indexBuffer, size_t indices,
|
||||
const VertexAttribute *attrs);
|
||||
|
||||
Mesh(const VertexStructure *vertexBuffer, size_t vertices, const VertexAttribute *attrs) : Mesh<VertexStructure>(
|
||||
vertexBuffer, vertices, nullptr, 0, attrs) {
|
||||
};
|
||||
|
||||
~Mesh();
|
||||
|
||||
/// @brief Update GL vertex and index buffers data without changing VAO attributes
|
||||
/// @param vertexBuffer vertex data buffer
|
||||
/// @param vertices number of vertices in new buffer
|
||||
/// @param vertexCount number of vertices in new buffer
|
||||
/// @param indexBuffer indices buffer
|
||||
/// @param indices number of values in indices buffer
|
||||
void reload(const float* vertexBuffer, size_t vertices, const int* indexBuffer = nullptr, size_t indices = 0);
|
||||
|
||||
/// @param indexCount number of values in indices buffer
|
||||
void reload(const VertexStructure *vertexBuffer, size_t vertexCount, const uint32_t *indexBuffer = nullptr,
|
||||
size_t indexCount = 0);
|
||||
|
||||
/// @brief Draw mesh with specified primitives type
|
||||
/// @param primitive primitives type
|
||||
void draw(unsigned int primitive) const;
|
||||
@@ -34,6 +46,6 @@ public:
|
||||
void draw() const;
|
||||
|
||||
/// @brief Total numbers of alive mesh objects
|
||||
static int meshesCount;
|
||||
static int drawCalls;
|
||||
};
|
||||
|
||||
#include "graphics/core/Mesh.inl"
|
||||
|
||||
@@ -0,0 +1,92 @@
|
||||
#pragma once
|
||||
|
||||
#include <GL/glew.h>
|
||||
|
||||
#include "MeshData.hpp"
|
||||
|
||||
template<typename VertexStructure>
|
||||
Mesh<VertexStructure>::Mesh(const MeshData<VertexStructure>& data)
|
||||
: Mesh(data.vertices.data(),
|
||||
data.vertices.size(),
|
||||
data.indices.data(),
|
||||
data.indices.size(),
|
||||
data.attrs.data()) {}
|
||||
|
||||
template<typename VertexStructure>
|
||||
Mesh<VertexStructure>::Mesh(const VertexStructure* vertexBuffer, size_t vertices, const uint32_t* indexBuffer, size_t indices, const VertexAttribute* attrs) :
|
||||
ibo(0),
|
||||
vao(0),
|
||||
vbo(0),
|
||||
vertexCount(0),
|
||||
indexCount(0)
|
||||
{
|
||||
MeshStats::meshesCount++;
|
||||
vertexSize = 0;
|
||||
for (int i = 0; attrs[i].count; i++) {
|
||||
vertexSize += attrs[i].size();
|
||||
}
|
||||
size_t tmp = sizeof(VertexStructure);
|
||||
assert(vertexSize==tmp);
|
||||
|
||||
glGenVertexArrays(1, &vao);
|
||||
glGenBuffers(1, &vbo);
|
||||
|
||||
reload(vertexBuffer, vertices, indexBuffer, indices);
|
||||
|
||||
// attributes
|
||||
int offset = 0;
|
||||
for (int i = 0; attrs[i].count; i++) {
|
||||
const VertexAttribute &attr = attrs[i];
|
||||
glVertexAttribPointer(i, attr.count, attr.type, attr.normalized, sizeof(VertexStructure), (GLvoid*)(size_t)offset);
|
||||
glEnableVertexAttribArray(i);
|
||||
offset += attr.size();
|
||||
}
|
||||
|
||||
glBindVertexArray(0);
|
||||
}
|
||||
template<typename VertexStructure>
|
||||
Mesh<VertexStructure>::~Mesh(){
|
||||
MeshStats::meshesCount--;
|
||||
glDeleteVertexArrays(1, &vao);
|
||||
glDeleteBuffers(1, &vbo);
|
||||
if (ibo != 0) glDeleteBuffers(1, &ibo);
|
||||
}
|
||||
template<typename VertexStructure>
|
||||
void Mesh<VertexStructure>::reload(const VertexStructure *vertexBuffer, size_t vertexCount, const uint32_t *indexBuffer, size_t indexCount) {
|
||||
this->vertexCount = vertexCount;
|
||||
this->indexCount = indexCount;
|
||||
glBindVertexArray(vao);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, vbo);
|
||||
if (vertexBuffer != nullptr && vertexCount != 0) {
|
||||
glBufferData(GL_ARRAY_BUFFER, vertexCount * vertexSize, vertexBuffer, GL_STREAM_DRAW);
|
||||
} else {
|
||||
glBufferData(GL_ARRAY_BUFFER, 0, {}, GL_STREAM_DRAW);
|
||||
}
|
||||
|
||||
if (indexBuffer != nullptr && indexCount != 0) {
|
||||
if (ibo == 0)
|
||||
glGenBuffers(1, &ibo);
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo);
|
||||
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(uint32_t) * indexCount, indexBuffer, GL_STATIC_DRAW);
|
||||
} else if (ibo != 0) {
|
||||
glDeleteBuffers(1, &ibo);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
template<typename VertexStructure>
|
||||
void Mesh<VertexStructure>::draw(unsigned int primitive) const {
|
||||
MeshStats::drawCalls++;
|
||||
glBindVertexArray(vao);
|
||||
if (ibo != 0) {
|
||||
glDrawElements(primitive, indexCount, GL_UNSIGNED_INT, nullptr);
|
||||
} else {
|
||||
glDrawArrays(primitive, 0, vertexCount);
|
||||
}
|
||||
glBindVertexArray(0);
|
||||
}
|
||||
|
||||
template<typename VertexStructure>
|
||||
void Mesh<VertexStructure>::draw() const {
|
||||
draw(GL_TRIANGLES);
|
||||
}
|
||||
@@ -1,19 +1,42 @@
|
||||
#pragma once
|
||||
|
||||
#include <vector>
|
||||
#include <stdexcept>
|
||||
#include <GL/glew.h>
|
||||
|
||||
#include "typedefs.hpp"
|
||||
#include "util/Buffer.hpp"
|
||||
|
||||
/// @brief Vertex attribute info
|
||||
struct VertexAttribute {
|
||||
ubyte size;
|
||||
uint32_t type;
|
||||
bool normalized;
|
||||
ubyte count;
|
||||
|
||||
|
||||
[[nodiscard]] uint32_t size() const {
|
||||
switch (type) {
|
||||
case GL_FLOAT:
|
||||
return count * sizeof(float);
|
||||
case GL_UNSIGNED_INT:
|
||||
case GL_INT:
|
||||
return count * sizeof(uint32_t);
|
||||
case GL_UNSIGNED_SHORT:
|
||||
case GL_SHORT:
|
||||
return count * sizeof(uint16_t);
|
||||
case GL_UNSIGNED_BYTE:
|
||||
case GL_BYTE:
|
||||
return count * sizeof(uint8_t);
|
||||
default:
|
||||
throw std::runtime_error("VertexAttribute type is not supported");
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/// @brief Raw mesh data structure
|
||||
template<typename VertexStructure>
|
||||
struct MeshData {
|
||||
util::Buffer<float> vertices;
|
||||
util::Buffer<int> indices;
|
||||
util::Buffer<VertexStructure> vertices;
|
||||
util::Buffer<uint32_t> indices;
|
||||
util::Buffer<VertexAttribute> attrs;
|
||||
|
||||
MeshData() = default;
|
||||
@@ -22,8 +45,8 @@ struct MeshData {
|
||||
/// @param indices nullable indices buffer
|
||||
/// @param attrs vertex attribute sizes (must be null-terminated)
|
||||
MeshData(
|
||||
util::Buffer<float> vertices,
|
||||
util::Buffer<int> indices,
|
||||
util::Buffer<VertexStructure> vertices,
|
||||
util::Buffer<uint32_t> indices,
|
||||
util::Buffer<VertexAttribute> attrs
|
||||
) : vertices(std::move(vertices)),
|
||||
indices(std::move(indices)),
|
||||
|
||||
@@ -12,12 +12,16 @@
|
||||
PostProcessing::PostProcessing(size_t effectSlotsCount)
|
||||
: effectSlots(effectSlotsCount) {
|
||||
// Fullscreen quad mesh bulding
|
||||
float vertices[] {
|
||||
-1.0f, -1.0f, -1.0f, 1.0f, 1.0f, 1.0f,
|
||||
-1.0f, -1.0f, 1.0f, 1.0f, 1.0f, -1.0f
|
||||
PostProcessingVertex meshData[]{
|
||||
{{-1.0f, -1.0f}},
|
||||
{{-1.0f, 1.0f}},
|
||||
{{1.0f, 1.0f}},
|
||||
{{-1.0f, -1.0f}},
|
||||
{{1.0f, 1.0f}},
|
||||
{{1.0f, -1.0f}},
|
||||
};
|
||||
VertexAttribute attrs[] {{2}, {0}};
|
||||
quadMesh = std::make_unique<Mesh>(vertices, 6, attrs);
|
||||
|
||||
quadMesh = std::make_unique<Mesh<PostProcessingVertex>>(meshData, 6, PostProcessingVertex::ATTRIBUTES);
|
||||
}
|
||||
|
||||
PostProcessing::~PostProcessing() = default;
|
||||
|
||||
@@ -2,14 +2,25 @@
|
||||
|
||||
#include <vector>
|
||||
#include <memory>
|
||||
#include <glm/glm.hpp>
|
||||
#include "MeshData.hpp"
|
||||
|
||||
class Mesh;
|
||||
template<typename VertexStructure> class Mesh;
|
||||
class Assets;
|
||||
class Framebuffer;
|
||||
class DrawContext;
|
||||
class ImageData;
|
||||
class PostEffect;
|
||||
|
||||
struct PostProcessingVertex {
|
||||
glm::vec2 position;
|
||||
|
||||
static constexpr VertexAttribute ATTRIBUTES[] {
|
||||
{GL_FLOAT,false,2},
|
||||
{0}
|
||||
};
|
||||
};
|
||||
|
||||
/// @brief Framebuffer with blitting with shaders.
|
||||
/// @attention Current implementation does not support multiple render passes
|
||||
/// for multiple effects. Will be implemented in v0.21
|
||||
@@ -18,7 +29,7 @@ class PostProcessing {
|
||||
std::unique_ptr<Framebuffer> fbo;
|
||||
std::unique_ptr<Framebuffer> fboSecond;
|
||||
/// @brief Fullscreen quad mesh as the post-processing canvas
|
||||
std::unique_ptr<Mesh> quadMesh;
|
||||
std::unique_ptr<Mesh<PostProcessingVertex>> quadMesh;
|
||||
std::vector<std::shared_ptr<PostEffect>> effectSlots;
|
||||
public:
|
||||
PostProcessing(size_t effectSlotsCount);
|
||||
|
||||
Reference in New Issue
Block a user