Refactor mesh handling to use templated vertex structures for improved type safety and flexibility

This commit is contained in:
REDxEYE 2025-03-29 22:20:54 +03:00
parent bba647db5c
commit 1ffbeb8148
28 changed files with 591 additions and 521 deletions

View File

@ -49,3 +49,11 @@ if(VOXELENGINE_BUILD_TESTS)
endif()
add_subdirectory(vctest)
add_custom_target(copy_resources ALL
COMMAND ${CMAKE_COMMAND} -E copy_directory
${CMAKE_CURRENT_SOURCE_DIR}/res
${CMAKE_CURRENT_BINARY_DIR}/res
COMMENT "Copying resource directory to the build directory"
)
add_dependencies(${PROJECT_NAME} copy_resources)

View File

@ -46,10 +46,15 @@
],
"buildPresets": [
{
"name": "default-vs-msvc-windows",
"name": "Debug build",
"configurePreset": "default-vs-msvc-windows",
"configuration": "Debug"
},
{
"name": "Release build",
"configurePreset": "default-vs-msvc-windows",
"configuration": "Release"
},
{
"name": "default-ninja-gnu-linux",
"configurePreset": "default-ninja-gnu-linux",

View File

@ -3,7 +3,7 @@
layout (location = 0) in vec3 v_position;
layout (location = 1) in vec2 v_texCoord;
layout (location = 2) in vec3 v_color;
layout (location = 3) in float v_light;
layout (location = 3) in vec4 v_light;
out vec4 a_color;
out vec2 a_texCoord;
@ -31,7 +31,7 @@ void main() {
vec3 pos3d = modelpos.xyz - u_cameraPos;
modelpos.xyz = apply_planet_curvature(modelpos.xyz, pos3d);
vec4 decomp_light = decompress_light(v_light);
vec4 decomp_light = v_light;
vec3 light = decomp_light.rgb;
float torchlight = max(0.0, 1.0-distance(u_cameraPos, modelpos.xyz) /
u_torchlightDistance);

View File

@ -1,28 +1,17 @@
#ifndef COMMONS_GLSL_
#define COMMONS_GLSL_
#include <constants>
vec4 decompress_light(float compressed_light) {
vec4 result;
int compressed = floatBitsToInt(compressed_light);
result.r = ((compressed >> 24) & 0xFF) / 255.f;
result.g = ((compressed >> 16) & 0xFF) / 255.f;
result.b = ((compressed >> 8) & 0xFF) / 255.f;
result.a = (compressed & 0xFF) / 255.f;
return result;
}
vec3 pick_sky_color(samplerCube cubemap) {
vec3 skyLightColor = texture(cubemap, vec3(0.4f, 0.0f, 0.4f)).rgb;
skyLightColor *= SKY_LIGHT_TINT;
skyLightColor = min(vec3(1.0), skyLightColor*SKY_LIGHT_MUL);
skyLightColor = min(vec3(1.0f), skyLightColor * SKY_LIGHT_MUL);
skyLightColor = max(MIN_SKY_LIGHT, skyLightColor);
return skyLightColor;
}
vec3 apply_planet_curvature(vec3 modelPos, vec3 pos3d) {
modelPos.y -= pow(length(pos3d.xz)*CURVATURE_FACTOR, 3.0);
modelPos.y -= pow(length(pos3d.xz) * CURVATURE_FACTOR, 3.0f);
return modelPos;
}

View File

@ -2,7 +2,7 @@
layout (location = 0) in vec3 v_position;
layout (location = 1) in vec2 v_texCoord;
layout (location = 2) in float v_light;
layout (location = 2) in vec4 v_light;
out vec4 a_color;
out vec2 a_texCoord;
@ -27,13 +27,13 @@ uniform vec3 u_torchlightColor;
uniform float u_torchlightDistance;
void main() {
vec4 modelpos = u_model * vec4(v_position, 1.0);
vec4 modelpos = u_model * vec4(v_position, 1.0f);
vec3 pos3d = modelpos.xyz-u_cameraPos;
modelpos.xyz = apply_planet_curvature(modelpos.xyz, pos3d);
vec4 decomp_light = decompress_light(v_light);
vec4 decomp_light = v_light;
vec3 light = decomp_light.rgb;
float torchlight = max(0.0, 1.0-distance(u_cameraPos, modelpos.xyz) /
float torchlight = max(0.0, 1.0-distance(u_cameraPos, modelpos.xyz) /
u_torchlightDistance);
light += torchlight * u_torchlightColor;
a_color = vec4(pow(light, vec3(u_gamma)),1.0f);

View File

@ -93,11 +93,11 @@ std::shared_ptr<UINode> create_debug_panel(
panel->add(create_label(gui, []() { return L"fps: "+fpsString;}));
panel->add(create_label(gui, []() {
return L"meshes: " + std::to_wstring(Mesh::meshesCount);
return L"meshes: " + std::to_wstring(MeshStats::meshesCount);
}));
panel->add(create_label(gui, []() {
int drawCalls = Mesh::drawCalls;
Mesh::drawCalls = 0;
int drawCalls = MeshStats::drawCalls;
MeshStats::drawCalls = 0;
return L"draw-calls: " + std::to_wstring(drawCalls);
}));
panel->add(create_label(gui, []() {

View File

@ -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;
}

View File

@ -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;

View File

@ -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;
}

View File

@ -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};

View File

@ -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;
}

View File

@ -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:

View File

@ -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;

View File

@ -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"

View File

@ -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);
}

View File

@ -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)),

View File

@ -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;

View File

@ -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);

View File

@ -11,24 +11,25 @@
const glm::vec3 BlocksRenderer::SUN_VECTOR (0.2275f,0.9388f,-0.1005f);
BlocksRenderer::BlocksRenderer(
size_t capacity,
const Content& content,
const ContentGfxCache& cache,
const EngineSettings& settings
) : content(content),
vertexBuffer(std::make_unique<float[]>(capacity * CHUNK_VERTEX_SIZE)),
indexBuffer(std::make_unique<int[]>(capacity)),
vertexBuffer(std::make_unique<ChunkVertex[]>(capacity)),
indexBuffer(std::make_unique<uint32_t[]>(capacity)),
vertexCount(0),
vertexOffset(0),
indexOffset(0),
indexSize(0),
indexCount(0),
capacity(capacity),
cache(cache),
settings(settings)
settings(settings)
{
voxelsBuffer = std::make_unique<VoxelsVolume>(
CHUNK_W + voxelBufferPadding*2,
CHUNK_H,
CHUNK_W + voxelBufferPadding*2,
CHUNK_H,
CHUNK_D + voxelBufferPadding*2);
blockDefsCache = content.getIndices()->blocks.getDefs();
}
@ -40,39 +41,31 @@ BlocksRenderer::~BlocksRenderer() {
void BlocksRenderer::vertex(
const glm::vec3& coord, float u, float v, const glm::vec4& light
) {
vertexBuffer[vertexOffset++] = coord.x;
vertexBuffer[vertexOffset++] = coord.y;
vertexBuffer[vertexOffset++] = coord.z;
vertexBuffer[vertexOffset++] = u;
vertexBuffer[vertexOffset++] = v;
vertexBuffer[vertexCount].position = coord;
union {
float floating;
uint32_t integer;
} compressed;
vertexBuffer[vertexCount].uv = {u,v};
compressed.integer = (static_cast<uint32_t>(light.r * 255) & 0xff) << 24;
compressed.integer |= (static_cast<uint32_t>(light.g * 255) & 0xff) << 16;
compressed.integer |= (static_cast<uint32_t>(light.b * 255) & 0xff) << 8;
compressed.integer |= (static_cast<uint32_t>(light.a * 255) & 0xff);
vertexBuffer[vertexOffset++] = compressed.floating;
vertexBuffer[vertexCount].color[0] = static_cast<uint8_t>(light.r * 255);
vertexBuffer[vertexCount].color[1] = static_cast<uint8_t>(light.g * 255);
vertexBuffer[vertexCount].color[2] = static_cast<uint8_t>(light.b * 255);
vertexBuffer[vertexCount].color[3] = static_cast<uint8_t>(light.a * 255);
vertexCount++;
}
void BlocksRenderer::index(int a, int b, int c, int d, int e, int f) {
indexBuffer[indexSize++] = indexOffset + a;
indexBuffer[indexSize++] = indexOffset + b;
indexBuffer[indexSize++] = indexOffset + c;
indexBuffer[indexSize++] = indexOffset + d;
indexBuffer[indexSize++] = indexOffset + e;
indexBuffer[indexSize++] = indexOffset + f;
indexOffset += 4;
void BlocksRenderer::index(uint32_t a, uint32_t b, uint32_t c, uint32_t d, uint32_t e, uint32_t f) {
indexBuffer[indexCount++] = static_cast<uint32_t>(vertexOffset + a);
indexBuffer[indexCount++] = static_cast<uint32_t>(vertexOffset + b);
indexBuffer[indexCount++] = static_cast<uint32_t>(vertexOffset + c);
indexBuffer[indexCount++] = static_cast<uint32_t>(vertexOffset + d);
indexBuffer[indexCount++] = static_cast<uint32_t>(vertexOffset + e);
indexBuffer[indexCount++] = static_cast<uint32_t>(vertexOffset + f);
vertexOffset += 4;
}
/// @brief Add face with precalculated lights
void BlocksRenderer::face(
const glm::vec3& coord,
const glm::vec3& coord,
float w, float h, float d,
const glm::vec3& axisX,
const glm::vec3& axisY,
@ -81,7 +74,7 @@ void BlocksRenderer::face(
const glm::vec4(&lights)[4],
const glm::vec4& tint
) {
if (vertexOffset + CHUNK_VERTEX_SIZE * 4 > capacity) {
if (vertexCount + 4 >= capacity) {
overflow = true;
return;
}
@ -97,7 +90,7 @@ void BlocksRenderer::face(
}
void BlocksRenderer::vertexAO(
const glm::vec3& coord,
const glm::vec3& coord,
float u, float v,
const glm::vec4& tint,
const glm::vec3& axisX,
@ -121,7 +114,7 @@ void BlocksRenderer::faceAO(
const UVRegion& region,
bool lights
) {
if (vertexOffset + CHUNK_VERTEX_SIZE * 4 > capacity) {
if (vertexCount + 4 >= capacity) {
overflow = true;
return;
}
@ -159,7 +152,7 @@ void BlocksRenderer::face(
glm::vec4 tint,
bool lights
) {
if (vertexOffset + CHUNK_VERTEX_SIZE * 4 > capacity) {
if (vertexCount + 4 >= capacity) {
overflow = true;
return;
}
@ -178,10 +171,10 @@ void BlocksRenderer::face(
}
void BlocksRenderer::blockXSprite(
int x, int y, int z,
const glm::vec3& size,
const UVRegion& texface1,
const UVRegion& texface2,
int x, int y, int z,
const glm::vec3& size,
const UVRegion& texface1,
const UVRegion& texface2,
float spread
) {
glm::vec4 lights1[] {
@ -207,12 +200,12 @@ void BlocksRenderer::blockXSprite(
face({x + xs, y, z + zs}, w, size.y, 0, {-1, 0, 1}, {0, 1, 0}, glm::vec3(),
texface1, lights2, tint);
face({x + xs, y, z + zs}, w, size.y, 0, {1, 0, 1}, {0, 1, 0}, glm::vec3(),
face({x + xs, y, z + zs}, w, size.y, 0, {1, 0, 1}, {0, 1, 0}, glm::vec3(),
texface1, lights1, tint);
face({x + xs, y, z + zs}, w, size.y, 0, {-1, 0, -1}, {0, 1, 0}, glm::vec3(),
face({x + xs, y, z + zs}, w, size.y, 0, {-1, 0, -1}, {0, 1, 0}, glm::vec3(),
texface2, lights2, tint);
face({x + xs, y, z + zs}, w, size.y, 0, {1, 0, -1}, {0, 1, 0}, glm::vec3(),
face({x + xs, y, z + zs}, w, size.y, 0, {1, 0, -1}, {0, 1, 0}, glm::vec3(),
texface2, lights1, tint);
}
@ -221,8 +214,8 @@ void BlocksRenderer::blockXSprite(
/// @brief AABB blocks render method
void BlocksRenderer::blockAABB(
const glm::ivec3& icoord,
const UVRegion(&texfaces)[6],
const Block* block,
const UVRegion(&texfaces)[6],
const Block* block,
ubyte rotation,
bool lights,
bool ao
@ -249,7 +242,7 @@ void BlocksRenderer::blockAABB(
orient.transform(hitbox);
}
coord -= glm::vec3(0.5f) - hitbox.center();
if (ao) {
faceAO(coord, X*size.x, Y*size.y, Z*size.z, texfaces[5], lights); // north
faceAO(coord, -X*size.x, Y*size.y, -Z*size.z, texfaces[4], lights); // south
@ -289,7 +282,7 @@ void BlocksRenderer::blockCustomModel(
const auto& model = cache.getModel(block->rt.id);
for (const auto& mesh : model.meshes) {
if (vertexOffset + CHUNK_VERTEX_SIZE * mesh.vertices.size() > capacity) {
if (vertexCount + mesh.vertices.size() >= capacity) {
overflow = true;
return;
}
@ -314,7 +307,7 @@ void BlocksRenderer::blockCustomModel(
r,
n
);
indexBuffer[indexSize++] = indexOffset++;
indexBuffer[indexCount++] = vertexOffset++;
}
}
}
@ -322,9 +315,9 @@ void BlocksRenderer::blockCustomModel(
/* Fastest solid shaded blocks render method */
void BlocksRenderer::blockCube(
const glm::ivec3& coord,
const UVRegion(&texfaces)[6],
const Block& block,
const glm::ivec3& coord,
const UVRegion(&texfaces)[6],
const Block& block,
blockstate states,
bool lights,
bool ao
@ -340,7 +333,7 @@ void BlocksRenderer::blockCube(
Y = orient.axes[1];
Z = orient.axes[2];
}
if (ao) {
if (isOpen(coord + Z, block)) {
faceAO(coord, X, Y, Z, texfaces[5], lights);
@ -383,8 +376,8 @@ void BlocksRenderer::blockCube(
}
bool BlocksRenderer::isOpenForLight(int x, int y, int z) const {
blockid_t id = voxelsBuffer->pickBlockId(chunk->x * CHUNK_W + x,
y,
blockid_t id = voxelsBuffer->pickBlockId(chunk->x * CHUNK_W + x,
y,
chunk->z * CHUNK_D + z);
if (id == BLOCK_VOID) {
return false;
@ -398,7 +391,7 @@ bool BlocksRenderer::isOpenForLight(int x, int y, int z) const {
glm::vec4 BlocksRenderer::pickLight(int x, int y, int z) const {
if (isOpenForLight(x, y, z)) {
light_t light = voxelsBuffer->pickLight(chunk->x * CHUNK_W + x, y,
light_t light = voxelsBuffer->pickLight(chunk->x * CHUNK_W + x, y,
chunk->z * CHUNK_D + z);
return glm::vec4(Lightmap::extract(light, 0),
Lightmap::extract(light, 1),
@ -426,8 +419,8 @@ glm::vec4 BlocksRenderer::pickSoftLight(
float x, float y, float z, const glm::ivec3& right, const glm::ivec3& up
) const {
return pickSoftLight({
static_cast<int>(std::round(x)),
static_cast<int>(std::round(y)),
static_cast<int>(std::round(x)),
static_cast<int>(std::round(y)),
static_cast<int>(std::round(z))},
right, up);
}
@ -466,17 +459,17 @@ void BlocksRenderer::render(
def.ambientOcclusion);
break;
case BlockModel::xsprite: {
blockXSprite(x, y, z, glm::vec3(1.0f),
blockXSprite(x, y, z, glm::vec3(1.0f),
texfaces[FACE_MX], texfaces[FACE_MZ], 1.0f);
break;
}
case BlockModel::aabb: {
blockAABB({x, y, z}, texfaces, &def, vox.state.rotation,
blockAABB({x, y, z}, texfaces, &def, vox.state.rotation,
!def.shadeless, def.ambientOcclusion);
break;
}
case BlockModel::custom: {
blockCustomModel({x, y, z}, &def, vox.state.rotation,
blockCustomModel({x, y, z}, &def, vox.state.rotation,
!def.shadeless, def.ambientOcclusion);
break;
}
@ -529,24 +522,24 @@ SortingMeshData BlocksRenderer::renderTranslucent(
def.ambientOcclusion);
break;
case BlockModel::xsprite: {
blockXSprite(x, y, z, glm::vec3(1.0f),
blockXSprite(x, y, z, glm::vec3(1.0f),
texfaces[FACE_MX], texfaces[FACE_MZ], 1.0f);
break;
}
case BlockModel::aabb: {
blockAABB({x, y, z}, texfaces, &def, vox.state.rotation,
blockAABB({x, y, z}, texfaces, &def, vox.state.rotation,
!def.shadeless, def.ambientOcclusion);
break;
}
case BlockModel::custom: {
blockCustomModel({x, y, z}, &def, vox.state.rotation,
blockCustomModel({x, y, z}, &def, vox.state.rotation,
!def.shadeless, def.ambientOcclusion);
break;
}
default:
break;
}
if (vertexOffset == 0) {
if (vertexCount == 0) {
continue;
}
SortingMeshEntry entry {
@ -555,50 +548,50 @@ SortingMeshData BlocksRenderer::renderTranslucent(
y + 0.5f,
z + chunk->z * CHUNK_D + 0.5f
),
util::Buffer<float>(indexSize * CHUNK_VERTEX_SIZE), 0};
util::Buffer<ChunkVertex>(indexCount), 0};
totalSize += entry.vertexData.size();
for (int j = 0; j < indexSize; j++) {
for (int j = 0; j < indexCount; j++) {
std::memcpy(
entry.vertexData.data() + j * CHUNK_VERTEX_SIZE,
vertexBuffer.get() + indexBuffer[j] * CHUNK_VERTEX_SIZE,
sizeof(float) * CHUNK_VERTEX_SIZE
entry.vertexData.data() + j,
vertexBuffer.get() + indexBuffer[j],
sizeof(ChunkVertex)
);
float& vx = entry.vertexData[j * CHUNK_VERTEX_SIZE + 0];
float& vy = entry.vertexData[j * CHUNK_VERTEX_SIZE + 1];
float& vz = entry.vertexData[j * CHUNK_VERTEX_SIZE + 2];
ChunkVertex& vertex = entry.vertexData[j];
if (!aabbInit) {
aabbInit = true;
aabb.a = aabb.b = {vx, vy, vz};
aabb.a = aabb.b = vertex.position;
} else {
aabb.addPoint(glm::vec3(vx, vy, vz));
aabb.addPoint(vertex.position);
}
vx += chunk->x * CHUNK_W + 0.5f;
vy += 0.5f;
vz += chunk->z * CHUNK_D + 0.5f;
vertex.position.x += chunk->x * CHUNK_W + 0.5f;
vertex.position.y += 0.5f;
vertex.position.z += chunk->z * CHUNK_D + 0.5f;
}
sortingMesh.entries.push_back(std::move(entry));
vertexOffset = 0;
indexOffset = indexSize = 0;
vertexCount = 0;
vertexOffset = indexCount = 0;
}
}
// additional powerful optimization
auto size = aabb.size();
if ((size.y < 0.01f || size.x < 0.01f || size.z < 0.01f) &&
if ((size.y < 0.01f || size.x < 0.01f || size.z < 0.01f) &&
sortingMesh.entries.size() > 1) {
SortingMeshEntry newEntry {
sortingMesh.entries[0].position,
util::Buffer<float>(totalSize),
util::Buffer<ChunkVertex>(totalSize),
0
};
size_t offset = 0;
for (const auto& entry : sortingMesh.entries) {
std::memcpy(
newEntry.vertexData.data() + offset,
entry.vertexData.data(), entry.vertexData.size() * sizeof(float)
entry.vertexData.data(),
entry.vertexData.size() * sizeof(ChunkVertex)
);
offset += entry.vertexData.size();
}
@ -630,7 +623,7 @@ void BlocksRenderer::build(const Chunk* chunk, const Chunks* chunks) {
const voxel& vox = voxels[i];
blockid_t id = vox.id;
const auto& def = *blockDefsCache[id];
if (beginEnds[def.drawGroup][0] == 0) {
beginEnds[def.drawGroup][0] = i+1;
}
@ -639,36 +632,37 @@ void BlocksRenderer::build(const Chunk* chunk, const Chunks* chunks) {
cancelled = false;
overflow = false;
vertexOffset = 0;
indexOffset = indexSize = 0;
vertexCount = 0;
vertexOffset = indexCount = 0;
sortingMesh = renderTranslucent(voxels, beginEnds);
overflow = false;
vertexCount = 0;
vertexOffset = 0;
indexOffset = indexSize = 0;
indexCount = 0;
render(voxels, beginEnds);
}
ChunkMeshData BlocksRenderer::createMesh() {
return ChunkMeshData {
return ChunkMeshData{
MeshData(
util::Buffer<float>(vertexBuffer.get(), vertexOffset),
util::Buffer<int>(indexBuffer.get(), indexSize),
util::Buffer<VertexAttribute>(
CHUNK_VATTRS, sizeof(CHUNK_VATTRS) / sizeof(VertexAttribute)
util::Buffer(vertexBuffer.get(), vertexCount),
util::Buffer(indexBuffer.get(), indexCount),
util::Buffer(
ChunkVertex::ATTRIBUTES, sizeof(ChunkVertex::ATTRIBUTES) / sizeof(VertexAttribute)
)
),
std::move(sortingMesh)};
std::move(sortingMesh)
};
}
ChunkMesh BlocksRenderer::render(const Chunk* chunk, const Chunks* chunks) {
ChunkMesh BlocksRenderer::render(const Chunk *chunk, const Chunks *chunks) {
build(chunk, chunks);
size_t vcount = vertexOffset / CHUNK_VERTEX_SIZE;
return ChunkMesh{std::make_unique<Mesh>(
vertexBuffer.get(), vcount, indexBuffer.get(), indexSize, CHUNK_VATTRS
return ChunkMesh{std::make_unique<Mesh<ChunkVertex>>(
vertexBuffer.get(), vertexCount, indexBuffer.get(), indexCount, ChunkVertex::ATTRIBUTES
), std::move(sortingMesh)};
}

View File

@ -1,7 +1,5 @@
#pragma once
#include <stdlib.h>
#include <vector>
#include <memory>
#include <glm/glm.hpp>
#include "voxels/voxel.hpp"
@ -10,28 +8,27 @@
#include "voxels/Block.hpp"
#include "voxels/Chunk.hpp"
#include "voxels/VoxelsVolume.hpp"
#include "graphics/core/MeshData.hpp"
#include "maths/util.hpp"
#include "commons.hpp"
#include "settings.hpp"
template<typename VertexStructure> class Mesh;
class Content;
class Mesh;
class Block;
class Chunk;
class Chunks;
class VoxelsVolume;
class Chunks;
class ContentGfxCache;
struct UVRegion;
class BlocksRenderer {
static const glm::vec3 SUN_VECTOR;
const Content& content;
std::unique_ptr<float[]> vertexBuffer;
std::unique_ptr<int[]> indexBuffer;
std::unique_ptr<ChunkVertex[]> vertexBuffer;
std::unique_ptr<uint32_t[]> indexBuffer;
size_t vertexCount;
size_t vertexOffset;
size_t indexOffset, indexSize;
size_t indexCount;
size_t capacity;
int voxelBufferPadding = 2;
bool overflow = false;
@ -48,7 +45,7 @@ class BlocksRenderer {
SortingMeshData sortingMesh;
void vertex(const glm::vec3& coord, float u, float v, const glm::vec4& light);
void index(int a, int b, int c, int d, int e, int f);
void index(uint32_t a, uint32_t b, uint32_t c, uint32_t d, uint32_t e, uint32_t f);
void vertexAO(
const glm::vec3& coord, float u, float v,

View File

@ -74,7 +74,7 @@ ChunksRenderer::ChunksRenderer(
if (!result.cancelled) {
auto meshData = std::move(result.meshData);
meshes[result.key] = ChunkMesh {
std::make_unique<Mesh>(meshData.mesh),
std::make_unique<Mesh<ChunkVertex>>(meshData.mesh),
std::move(meshData.sortingMesh)};
}
inwork.erase(result.key);
@ -92,7 +92,7 @@ ChunksRenderer::ChunksRenderer(
ChunksRenderer::~ChunksRenderer() {
}
const Mesh* ChunksRenderer::render(
const Mesh<ChunkVertex>* ChunksRenderer::render(
const std::shared_ptr<Chunk>& chunk, bool important
) {
chunk->flags.modified = false;
@ -125,7 +125,7 @@ void ChunksRenderer::clear() {
threadPool.clearQueue();
}
const Mesh* ChunksRenderer::getOrRender(
const Mesh<ChunkVertex>* ChunksRenderer::getOrRender(
const std::shared_ptr<Chunk>& chunk, bool important
) {
auto found = meshes.find(glm::ivec2(chunk->x, chunk->z));
@ -142,7 +142,7 @@ void ChunksRenderer::update() {
threadPool.update();
}
const Mesh* ChunksRenderer::retrieveChunk(
const Mesh<ChunkVertex>* ChunksRenderer::retrieveChunk(
size_t index, const Camera& camera, Shader& shader, bool culling
) {
auto chunk = chunks.getChunks()[index];
@ -234,14 +234,14 @@ void ChunksRenderer::drawChunks(
}
static inline void write_sorting_mesh_entries(
float* buffer, const std::vector<SortingMeshEntry>& chunkEntries
ChunkVertex* buffer, const std::vector<SortingMeshEntry>& chunkEntries
) {
for (const auto& entry : chunkEntries) {
const auto& vertexData = entry.vertexData;
std::memcpy(
buffer,
vertexData.data(),
vertexData.size() * sizeof(float)
vertexData.size() * sizeof(ChunkVertex)
);
buffer += vertexData.size();
}
@ -288,10 +288,10 @@ void ChunksRenderer::drawSortedMeshes(const Camera& camera, Shader& shader) {
if (chunkEntries.size() == 1) {
auto& entry = chunkEntries.at(0);
if (found->second.sortedMesh == nullptr) {
found->second.sortedMesh = std::make_unique<Mesh>(
found->second.sortedMesh = std::make_unique<Mesh<ChunkVertex>>(
entry.vertexData.data(),
entry.vertexData.size() / CHUNK_VERTEX_SIZE,
CHUNK_VATTRS
entry.vertexData.size(),
ChunkVertex::ATTRIBUTES
);
}
found->second.sortedMesh->draw();
@ -310,13 +310,13 @@ void ChunksRenderer::drawSortedMeshes(const Camera& camera, Shader& shader) {
size += entry.vertexData.size();
}
static util::Buffer<float> buffer;
static util::Buffer<ChunkVertex> buffer;
if (buffer.size() < size) {
buffer = util::Buffer<float>(size);
buffer = util::Buffer<ChunkVertex>(size);
}
write_sorting_mesh_entries(buffer.data(), chunkEntries);
found->second.sortedMesh = std::make_unique<Mesh>(
buffer.data(), size / CHUNK_VERTEX_SIZE, CHUNK_VATTRS
found->second.sortedMesh = std::make_unique<Mesh<ChunkVertex>>(
buffer.data(), size, ChunkVertex::ATTRIBUTES
);
}
found->second.sortedMesh->draw();

View File

@ -1,6 +1,5 @@
#pragma once
#include <queue>
#include <memory>
#include <vector>
#include <unordered_map>
@ -9,12 +8,10 @@
#define GLM_ENABLE_EXPERIMENTAL
#include <glm/gtx/hash.hpp>
#include "voxels/Block.hpp"
#include "util/ThreadPool.hpp"
#include "graphics/core/MeshData.hpp"
#include "commons.hpp"
class Mesh;
template<typename VertexStructure> class Mesh;
class Chunk;
class Level;
class Camera;
@ -52,7 +49,7 @@ class ChunksRenderer {
std::unordered_map<glm::ivec2, bool> inwork;
std::vector<ChunksSortEntry> indices;
util::ThreadPool<std::shared_ptr<Chunk>, RendererResult> threadPool;
const Mesh* retrieveChunk(
const Mesh<ChunkVertex>* retrieveChunk(
size_t index, const Camera& camera, Shader& shader, bool culling
);
public:
@ -66,13 +63,13 @@ public:
);
virtual ~ChunksRenderer();
const Mesh* render(
const Mesh<ChunkVertex>* render(
const std::shared_ptr<Chunk>& chunk, bool important
);
void unload(const Chunk* chunk);
void clear();
const Mesh* getOrRender(
const Mesh<ChunkVertex>* getOrRender(
const std::shared_ptr<Chunk>& chunk, bool important
);
void drawChunks(const Camera& camera, Shader& shader);

View File

@ -6,18 +6,15 @@
#include "voxels/Chunks.hpp"
#include "voxels/Chunk.hpp"
static const VertexAttribute attrs[] = {
{3}, {2}, {3}, {1}, {0}
};
MainBatch::MainBatch(size_t capacity)
: buffer(std::make_unique<float[]>(capacity * VERTEX_SIZE)),
capacity(capacity),
index(0),
mesh(std::make_unique<Mesh>(buffer.get(), 0, attrs)) {
: buffer(std::make_unique<MainBatchVertex[]>(capacity)),
capacity(capacity),
index(0),
mesh(std::make_unique<Mesh<MainBatchVertex>>(buffer.get(), 0, MainBatchVertex::ATTRIBUTES)) {
const ubyte pixels[] = {
255, 255, 255, 255,
255, 255, 255, 255,
};
ImageData image(ImageFormat::rgba8888, 1, 1, pixels);
blank = Texture::from(&image);
@ -25,7 +22,7 @@ MainBatch::MainBatch(size_t capacity)
MainBatch::~MainBatch() = default;
void MainBatch::setTexture(const Texture* texture) {
void MainBatch::setTexture(const Texture *texture) {
if (texture == nullptr) {
texture = blank.get();
}
@ -33,10 +30,10 @@ void MainBatch::setTexture(const Texture* texture) {
flush();
}
this->texture = texture;
region = UVRegion {0.0f, 0.0f, 1.0f, 1.0f};
region = UVRegion{0.0f, 0.0f, 1.0f, 1.0f};
}
void MainBatch::setTexture(const Texture* texture, const UVRegion& region) {
void MainBatch::setTexture(const Texture *texture, const UVRegion &region) {
setTexture(texture);
this->region = region;
}
@ -49,7 +46,7 @@ void MainBatch::flush() {
texture = blank.get();
}
texture->bind();
mesh->reload(buffer.get(), index / VERTEX_SIZE);
mesh->reload(buffer.get(), index);
mesh->draw();
index = 0;
}
@ -60,76 +57,76 @@ void MainBatch::begin() {
}
void MainBatch::prepare(int vertices) {
if (index + VERTEX_SIZE * vertices > capacity * VERTEX_SIZE) {
if (index * vertices > capacity) {
flush();
}
}
glm::vec4 MainBatch::sampleLight(
const glm::vec3& pos, const Chunks& chunks, bool backlight
const glm::vec3 &pos, const Chunks &chunks, bool backlight
) {
light_t light = chunks.getLight(
std::floor(pos.x),
std::floor(std::min(CHUNK_H-1.0f, pos.y)),
std::floor(pos.z));
std::floor(pos.x),
std::floor(std::min(CHUNK_H - 1.0f, pos.y)),
std::floor(pos.z));
light_t minIntensity = backlight ? 1 : 0;
return glm::vec4(
glm::max(Lightmap::extract(light, 0), minIntensity) / 15.0f,
glm::max(Lightmap::extract(light, 1), minIntensity) / 15.0f,
glm::max(Lightmap::extract(light, 2), minIntensity) / 15.0f,
glm::max(Lightmap::extract(light, 3), minIntensity) / 15.0f
);
return {
(float) glm::max(Lightmap::extract(light, 0), minIntensity) / 15.0f,
(float) glm::max(Lightmap::extract(light, 1), minIntensity) / 15.0f,
(float) glm::max(Lightmap::extract(light, 2), minIntensity) / 15.0f,
(float) glm::max(Lightmap::extract(light, 3), minIntensity) / 15.0f
};
}
inline glm::vec4 do_tint(float value) {
return glm::vec4(value, value, value, 1.0f);
return {value, value, value, 1.0f};
}
void MainBatch::cube(
const glm::vec3& coord,
const glm::vec3& size,
const UVRegion(&texfaces)[6],
const glm::vec4& tint,
bool shading
const glm::vec3 &coord,
const glm::vec3 &size,
const UVRegion(&texfaces)[6],
const glm::vec4 &tint,
bool shading
) {
const glm::vec3 X(1.0f, 0.0f, 0.0f);
const glm::vec3 Y(0.0f, 1.0f, 0.0f);
const glm::vec3 Z(0.0f, 0.0f, 1.0f);
quad(
coord + Z * size.z * 0.5f,
X, Y, glm::vec2(size.x, size.y),
(shading ? do_tint(0.8) * tint : tint),
glm::vec3(1.0f), texfaces[5]
coord + Z * size.z * 0.5f,
X, Y, glm::vec2(size.x, size.y),
(shading ? do_tint(0.8) * tint : tint),
glm::vec3(1.0f), texfaces[5]
);
quad(
coord - Z * size.z * 0.5f,
-X, Y, glm::vec2(size.x, size.y),
(shading ? do_tint(0.9f) * tint : tint),
glm::vec3(1.0f), texfaces[4]
coord - Z * size.z * 0.5f,
-X, Y, glm::vec2(size.x, size.y),
(shading ? do_tint(0.9f) * tint : tint),
glm::vec3(1.0f), texfaces[4]
);
quad(
coord + Y * size.y * 0.5f,
-X, Z, glm::vec2(size.x, size.z),
(shading ? do_tint(1.0f) * tint : tint),
glm::vec3(1.0f), texfaces[3]
coord + Y * size.y * 0.5f,
-X, Z, glm::vec2(size.x, size.z),
(shading ? do_tint(1.0f) * tint : tint),
glm::vec3(1.0f), texfaces[3]
);
quad(
coord - Y * size.y * 0.5f,
X, Z, glm::vec2(size.x, size.z),
(shading ? do_tint(0.7f) * tint : tint),
glm::vec3(1.0f), texfaces[2]
coord - Y * size.y * 0.5f,
X, Z, glm::vec2(size.x, size.z),
(shading ? do_tint(0.7f) * tint : tint),
glm::vec3(1.0f), texfaces[2]
);
quad(
coord + X * size.x * 0.5f,
-Z, Y, glm::vec2(size.z, size.y),
(shading ? do_tint(0.8f) * tint : tint),
glm::vec3(1.0f), texfaces[1]
coord + X * size.x * 0.5f,
-Z, Y, glm::vec2(size.z, size.y),
(shading ? do_tint(0.8f) * tint : tint),
glm::vec3(1.0f), texfaces[1]
);
quad(
coord - X * size.x * 0.5f,
Z, Y, glm::vec2(size.z, size.y),
(shading ? do_tint(0.9f) * tint : tint),
glm::vec3(1.0f), texfaces[1]
coord - X * size.x * 0.5f,
Z, Y, glm::vec2(size.z, size.y),
(shading ? do_tint(0.9f) * tint : tint),
glm::vec3(1.0f), texfaces[1]
);
}

View File

@ -1,30 +1,47 @@
#pragma once
#include <array>
#include <memory>
#include <stdint.h>
#include <cstdint>
#include <glm/glm.hpp>
#include "typedefs.hpp"
#include "maths/UVRegion.hpp"
#include "graphics/core/MeshData.hpp"
template<typename VertexStructure>
class Mesh;
class Texture;
class Chunks;
struct MainBatchVertex {
glm::vec3 position;
glm::vec2 uv;
glm::vec3 tint;
std::array<uint8_t,4> color;
static constexpr VertexAttribute ATTRIBUTES[] = {
{GL_FLOAT, false, 3},
{GL_FLOAT, false, 2},
{GL_FLOAT, false, 3},
{GL_UNSIGNED_BYTE, true, 4},
{0}
};
};
class MainBatch {
std::unique_ptr<float[]> const buffer;
std::unique_ptr<MainBatchVertex[]> const buffer;
size_t const capacity;
size_t index;
UVRegion region {0.0f, 0.0f, 1.0f, 1.0f};
std::unique_ptr<Mesh> mesh;
std::unique_ptr<Mesh<MainBatchVertex>> mesh;
std::unique_ptr<Texture> blank;
const Texture* texture = nullptr;
public:
/// xyz, uv, color, compressed lights
static inline constexpr uint VERTEX_SIZE = 9;
MainBatch(size_t capacity);
@ -47,27 +64,16 @@ public:
const glm::vec4& light,
const 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;
MainBatchVertex* buffer = this->buffer.get();
buffer[index].position = pos;
buffer[index].uv = {uv.x * region.getWidth() + region.u1,uv.y * region.getHeight() + region.v1};
buffer[index].tint = tint;
union {
float floating;
uint32_t integer;
} compressed;
compressed.integer = (static_cast<uint32_t>(light.r * 255) & 0xff) << 24;
compressed.integer |= (static_cast<uint32_t>(light.g * 255) & 0xff) << 16;
compressed.integer |= (static_cast<uint32_t>(light.b * 255) & 0xff) << 8;
compressed.integer |= (static_cast<uint32_t>(light.a * 255) & 0xff);
buffer[index++] = compressed.floating;
buffer[index].color[0] = static_cast<uint8_t>(light.r * 255);
buffer[index].color[1] = static_cast<uint8_t>(light.g * 255);
buffer[index].color[2] = static_cast<uint8_t>(light.b * 255);
buffer[index].color[3] = static_cast<uint8_t>(light.a * 255);
index++;
}
inline void quad(

View File

@ -1,14 +1,12 @@
#pragma once
#include "maths/UVRegion.hpp"
#include <memory>
#include <vector>
#include <string>
#include <glm/glm.hpp>
#include <unordered_map>
class Mesh;
template<typename VertexStructure> class Mesh;
class Texture;
class Chunks;
class Assets;

View File

@ -24,10 +24,10 @@
const int STARS_COUNT = 3000;
const int STARS_SEED = 632;
Skybox::Skybox(uint size, Shader& shader)
: size(size),
shader(shader),
batch3d(std::make_unique<Batch3D>(4096))
Skybox::Skybox(uint size, Shader& shader)
: size(size),
shader(shader),
batch3d(std::make_unique<Batch3D>(4096))
{
auto cubemap = std::make_unique<Cubemap>(size, size, ImageFormat::rgb888);
@ -35,12 +35,16 @@ Skybox::Skybox(uint size, Shader& shader)
glGenFramebuffers(1, &fboid);
fbo = std::make_unique<Framebuffer>(fboid, 0, std::move(cubemap));
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
SkyboxVertex 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}}
};
VertexAttribute attrs[] {{2}, {0}};
mesh = std::make_unique<Mesh>(vertices, 6, attrs);
mesh = std::make_unique<Mesh<SkyboxVertex>>(vertices, 6, SkyboxVertex::ATTRIBUTES);
sprites.push_back(skysprite {
"misc/moon",
@ -95,11 +99,11 @@ void Skybox::drawStars(float angle, float opacity) {
}
void Skybox::draw(
const DrawContext& pctx,
const Camera& camera,
const Assets& assets,
const DrawContext& pctx,
const Camera& camera,
const Assets& assets,
float daytime,
float fog)
float fog)
{
const glm::uvec2& viewport = pctx.getViewport();
@ -116,7 +120,7 @@ void Skybox::draw(
float angle = daytime * glm::pi<float>() * 2.0f;
float opacity = glm::pow(1.0f-fog, 7.0f);
for (auto& sprite : sprites) {
batch3d->texture(assets.get<Texture>(sprite.texture));
@ -129,7 +133,7 @@ void Skybox::draw(
if (!sprite.emissive) {
tint *= 0.6f+std::cos(angle)*0.4;
}
batch3d->sprite(pos, glm::vec3(0, 0, 1),
batch3d->sprite(pos, glm::vec3(0, 0, 1),
up, 1, 1, UVRegion(), tint);
}
@ -153,7 +157,7 @@ void Skybox::refresh(const DrawContext& pctx, float t, float mie, uint quality)
cubemap->bind();
shader.use();
t *= glm::pi<float>()*2.0f;
lightDir = glm::normalize(glm::vec3(sin(t), -cos(t), 0.0f));
shader.uniform1i("u_quality", quality);
shader.uniform1f("u_mie", mie);
@ -171,7 +175,7 @@ void Skybox::refresh(const DrawContext& pctx, float t, float mie, uint quality)
}
prevMie = mie;
prevT = t;
cubemap->unbind();
glActiveTexture(GL_TEXTURE0);
}
@ -190,7 +194,7 @@ void Skybox::refreshFace(uint face, Cubemap* cubemap) {
{0.0f, 1.0f, 0.0f},
{0.0f, 1.0f, 0.0f},
{0.0f, 0.0f, -1.0f},
{0.0f, 0.0f, 1.0f},
{0.0f, 1.0f, 0.0f},
{0.0f, 1.0f, 0.0f},
@ -200,7 +204,7 @@ void Skybox::refreshFace(uint face, Cubemap* cubemap) {
{1.0f, 0.0f, 0.0f},
{-1.0f, 0.0f, 0.0f},
{0.0f, -1.0f, 0.0f},
{0.0f, 1.0f, 0.0f},
{0.0f, 0.0f, -1.0f},
{0.0f, 0.0f, 1.0f},

View File

@ -6,17 +6,23 @@
#include <glm/glm.hpp>
#include "typedefs.hpp"
#include "maths/fastmaths.hpp"
#include "graphics/core/MeshData.hpp"
class Mesh;
template<typename VertexStructure> class Mesh;
class Shader;
class Assets;
class Camera;
class Batch3D;
class Shader;
class Cubemap;
class Framebuffer;
class DrawContext;
struct SkyboxVertex {
glm::vec2 position;
static constexpr VertexAttribute ATTRIBUTES[] {{GL_FLOAT,false,2}, {0}};
};
struct skysprite {
std::string texture;
float phase;
@ -32,7 +38,7 @@ class Skybox {
FastRandom random;
glm::vec3 lightDir;
std::unique_ptr<Mesh> mesh;
std::unique_ptr<Mesh<SkyboxVertex>> mesh;
std::unique_ptr<Batch3D> batch3d;
std::vector<skysprite> sprites;
int frameid = 0;

View File

@ -1,25 +1,43 @@
#pragma once
#include <vector>
#include <array>
#include <memory>
#include <GL/glew.h>
#include <glm/vec3.hpp>
#include "graphics/core/MeshData.hpp"
#include "util/Buffer.hpp"
/// @brief Chunk mesh vertex attributes
inline const VertexAttribute CHUNK_VATTRS[]{ {3}, {2}, {1}, {0} };
/// @brief Chunk mesh vertex size divided by sizeof(float)
inline constexpr int CHUNK_VERTEX_SIZE = 6;
/// @brief Chunk mesh vertex format
#pragma pack(push, 2)
struct ChunkVertex {
glm::vec3 position;
glm::vec2 uv;
std::array<uint8_t, 4> color;
static constexpr VertexAttribute ATTRIBUTES[] = {
{GL_FLOAT, false, 3},
{GL_FLOAT, false, 2},
{GL_UNSIGNED_BYTE, true, 4},
{0}
};
};
#pragma pack(pop)
/// @brief Chunk mesh vertex attributes
template<typename VertexStructure>
class Mesh;
struct SortingMeshEntry {
glm::vec3 position;
util::Buffer<float> vertexData;
util::Buffer<ChunkVertex> vertexData;
long long distance;
inline bool operator<(const SortingMeshEntry& o) const noexcept {
inline bool operator<(const SortingMeshEntry &o) const noexcept {
return distance > o.distance;
}
};
@ -29,12 +47,12 @@ struct SortingMeshData {
};
struct ChunkMeshData {
MeshData mesh;
MeshData<ChunkVertex> mesh;
SortingMeshData sortingMesh;
};
struct ChunkMesh {
std::unique_ptr<Mesh> mesh;
std::unique_ptr<Mesh<ChunkVertex> > mesh;
SortingMeshData sortingMeshData;
std::unique_ptr<Mesh> sortedMesh = nullptr;
std::unique_ptr<Mesh<ChunkVertex> > sortedMesh = nullptr;
};