1
0
Fork 0

VertexData packing

This commit is contained in:
May B. 2020-08-12 21:09:01 +02:00
parent b98a791fc4
commit bfba0544d6
13 changed files with 98 additions and 75 deletions

View File

@ -38,13 +38,14 @@ namespace contouring {
#if TRACY_ENABLE
tracy::SetThreadName("Contouring");
#endif
std::vector<buffer::VertexData> tmp;
while (running) {
std::pair<area_<chunk_pos>, surrounding::corners> ctx;
loadQueue.wait();
if (loadQueue.pop(ctx)) {
ZoneScopedN("ProcessContouring");
buffer::LodShortIndexed::LodData data;
render(ctx.second, data);
render(ctx.second, data, tmp);
loadedQueue.emplace(ctx.first, data);
}
}
@ -184,7 +185,7 @@ namespace contouring {
}
}
void FlatDualMC::render(const surrounding::corners &surrounding, buffer::LodShortIndexed::LodData &out) const {
void FlatDualMC::render(const surrounding::corners &surrounding, buffer::LodShortIndexed::LodData &out, std::vector<buffer::VertexData> &tmp) const {
const int SIZE = CHUNK_LENGTH + 3;
std::array<dualmc::DualMC<float>::Point, SIZE * SIZE * SIZE> grid;
{
@ -207,15 +208,18 @@ namespace contouring {
builder.buildTris(&grid.front(), SIZE, SIZE, SIZE, iso, world::materials::roughness.cbegin(), manifold, dmc_vertices, dmc_tris);
auto &data = out.first;
data.vertices.reserve(dmc_vertices.size());
std::transform(dmc_vertices.begin(), dmc_vertices.end(), std::back_inserter(data.vertices), [](const dualmc::Vertex &v) {
return buffer::VertexData(glm::vec3(v.x, v.y, v.z), v.w, glm::vec3(0));
tmp.clear();
tmp.reserve(dmc_vertices.size());
constexpr auto HALF_MANTISSA = 10;
std::transform(dmc_vertices.begin(), dmc_vertices.end(), std::back_inserter(tmp), [](const dualmc::Vertex &v) {
return buffer::VertexData(glm::vec3(meshopt_quantizeFloat(v.x, HALF_MANTISSA),meshopt_quantizeFloat(v.y, HALF_MANTISSA),
meshopt_quantizeFloat(v.z, HALF_MANTISSA)), v.w, glm::vec3(0));
});
data.indices.reserve(dmc_tris.size() * 3);
for (const auto& t: dmc_tris) {
glm::vec3 edge1 = data.vertices[t.i1].Position - data.vertices[t.i0].Position;
glm::vec3 edge2 = data.vertices[t.i2].Position - data.vertices[t.i0].Position;
glm::vec3 edge1 = tmp[t.i1].Position - tmp[t.i0].Position;
glm::vec3 edge2 = tmp[t.i2].Position - tmp[t.i0].Position;
glm::vec3 normal = glm::normalize(glm::cross(edge1, edge2));
if(!reordering || glm::length2(edge1) > glm::length2(edge2)) {
@ -228,16 +232,22 @@ namespace contouring {
data.indices.push_back(t.i1);
}
data.vertices[t.i0].Normal += normal;
data.vertices[t.i1].Normal += normal;
data.vertices[t.i2].Normal += normal;
tmp[t.i0].Normal += normal;
tmp[t.i1].Normal += normal;
tmp[t.i2].Normal += normal;
}
for(auto& v: data.vertices) {
for(auto& v: tmp) {
v.Normal = glm::normalize(v.Normal);
}
out.second = simplify_lod(data.indices, dmc_vertices, loadedLevels);
out.second = simplify_lod(data.indices, tmp, loadedLevels);
std::transform(tmp.begin(), tmp.end(), std::back_inserter(data.vertices), [](const buffer::VertexData &v) {
return buffer::PackedVertexData(meshopt_quantizeHalf(v.Position.x), meshopt_quantizeHalf(v.Position.y),
meshopt_quantizeHalf(v.Position.z), v.Material,
meshopt_quantizeHalf(v.Normal.x), meshopt_quantizeHalf(v.Normal.y),
meshopt_quantizeHalf(v.Normal.z));
});
optimize_fetch(data);
}
}

View File

@ -47,6 +47,6 @@ namespace contouring {
std::vector<std::pair<float, float>> loadedLevels;
void render(const surrounding::corners &surrounding, buffer::LodShortIndexed::LodData& out) const;
void render(const surrounding::corners &surrounding, buffer::LodShortIndexed::LodData& out, std::vector<buffer::VertexData>& tmp) const;
};
}

View File

@ -13,7 +13,7 @@ namespace contouring {
std::pair<area_<chunk_pos>, surrounding::faces> ctx;
loadQueue.wait();
if (loadQueue.pop(ctx)) {
std::vector<buffer::VertexData> vertices;
std::vector<buffer::PackedVertexData> vertices;
render(ctx.second, vertices);
{
loadedQueue.emplace(ctx.first, vertices);
@ -93,7 +93,7 @@ namespace contouring {
return !surrounding[idx.first]->get(idx.second).is_full(); // MAYBE: materials::transparent
}
void FlatSurroundingBox::render(const surrounding::faces &surrounding, std::vector<buffer::VertexData> &vertices) {
void FlatSurroundingBox::render(const surrounding::faces &surrounding, std::vector<buffer::PackedVertexData> &vertices) {
const auto center = surrounding[surrounding::CENTER];
vertices.clear();
for (ushort i = 0; i < world::CHUNK_SIZE; i++) {

View File

@ -36,6 +36,6 @@ namespace contouring {
private:
static inline bool isTransparent(const surrounding::faces &surrounding, const std::pair<ushort, ushort> &idx);
static void render(const surrounding::faces &surrounding, std::vector<buffer::VertexData> &vertices);
static void render(const surrounding::faces &surrounding, std::vector<buffer::PackedVertexData> &vertices);
};
} // namespace contouring

View File

@ -2,6 +2,7 @@
#include <vector>
#include <glm/gtc/matrix_transform.hpp>
#include <meshoptimizer.h>
#include "../data/geometry/Faces.hpp"
#include "../render/buffer/VertexData.hpp"
@ -25,13 +26,18 @@ namespace contouring::box {
glm::rotate<float>(glm::mat4(1), glm::half_pi<float>(), glm::vec3(0, 1, 0)),
};
static void addQuad(std::vector<buffer::VertexData> & out, glm::vec3 position, ushort material, Face face, glm::vec3 size) {
static void addQuad(std::vector<buffer::PackedVertexData> & out, glm::vec3 position, ushort material, Face face, glm::vec3 size) {
constexpr auto HALF_MANTISSA = 10;
for (auto vertex : g_quad_vertices) {
out.emplace_back(glm::vec3(g_cube_rotate[static_cast<int>(face)] * glm::vec4(vertex, 1)) * size + position, material, g_cube_normals[static_cast<int>(face)]);
const auto p = glm::vec3(g_cube_rotate[static_cast<int>(face)] * glm::vec4(vertex, 1)) * size + position;
out.emplace_back(meshopt_quantizeHalf(p.x), meshopt_quantizeHalf(p.y),
meshopt_quantizeHalf(p.z), material,
meshopt_quantizeHalf(g_cube_normals[static_cast<int>(face)].x), meshopt_quantizeHalf(g_cube_normals[static_cast<int>(face)].y),
meshopt_quantizeHalf(g_cube_normals[static_cast<int>(face)].z));
}
}
static void addCube(std::vector<buffer::VertexData>& out, glm::vec3 position, uint material, Faces faces = Faces::All, glm::vec3 size = glm::vec3(1)) {
static void addCube(std::vector<buffer::PackedVertexData>& out, glm::vec3 position, uint material, Faces faces = Faces::All, glm::vec3 size = glm::vec3(1)) {
if (faces && Faces::Right)
addQuad(out, position, material, Face::Right, size);

View File

@ -391,7 +391,7 @@ void DualMC<T>::calculateDualPoint(int32_t const cx, int32_t const cy, int32_t c
p.y = 0;
p.z = 0;
int points = 0;
float max = 0;
T max = 0;
// sum edge intersection vertices using the point code
if (pointCode & EDGE0) {

View File

@ -4,31 +4,21 @@
inline void optimize_fetch(buffer::ShortIndexed::Data& out) {
ZoneScopedN("Optimize");
std::vector<unsigned int> remap(out.indices.size());
size_t vertex_count = meshopt_optimizeVertexFetch(out.vertices.data(), out.indices.data(), out.indices.size(), out.vertices.data(), out.vertices.size(), sizeof(buffer::VertexData));
out.vertices.resize(vertex_count, buffer::VertexData(glm::vec3(0), 0, glm::vec3(0)));
}
inline void optimize_buffer(buffer::ShortIndexed::Data& out) {
meshopt_optimizeVertexCache(out.indices.data(), out.indices.data(), out.indices.size(), out.vertices.size()); //NOTE: pretty minimal gain
// reorder indices for overdraw, balancing overdraw and vertex cache efficiency
const float kThreshold = 1.01f; // allow up to 1% worse ACMR to get more reordering opportunities for overdraw
meshopt_optimizeOverdraw(out.indices.data(), out.indices.data(), out.indices.size(), &out.vertices.front().Position[0], out.vertices.size(), sizeof(buffer::VertexData), kThreshold);
// optimize_fetch(out);
size_t vertex_count = meshopt_optimizeVertexFetch(out.vertices.data(), out.indices.data(), out.indices.size(), out.vertices.data(), out.vertices.size(), sizeof(buffer::PackedVertexData));
out.vertices.resize(vertex_count, buffer::PackedVertexData(0, 0, 0, 0, 0, 0, 0));
}
//TODO: quantize half-float / 8-10 int
//MAYBE: when networking meshopt_encodeVertexBuffer
template<typename I>
inline void simplify_buffer(std::vector<I> &out, const std::vector<I> &indices, const std::vector<dualmc::Vertex>& vertices, float threshold = .2f, float target_error = 1e-2f) {
inline void simplify_buffer(std::vector<I> &out, const std::vector<I> &indices, const std::vector<buffer::VertexData>& vertices, float threshold = .2f, float target_error = 1e-2f) {
out.resize(indices.size());
out.resize(meshopt_simplify(out.data(), indices.data(), indices.size(), &vertices.front().x, vertices.size(), sizeof(dualmc::Vertex), indices.size() * threshold, target_error));
out.resize(meshopt_simplify(out.data(), indices.data(), indices.size(), &vertices.front().Position.x, vertices.size(), sizeof(buffer::VertexData), indices.size() * threshold, target_error));
}
#include <iostream>
template <typename I>
inline std::vector<size_t> simplify_lod(std::vector<I> &indices, const std::vector<dualmc::Vertex> &vertices, const std::vector<std::pair<float, float>> &levels)
inline std::vector<size_t> simplify_lod(std::vector<I> &indices, const std::vector<buffer::VertexData> &vertices, const std::vector<std::pair<float, float>> &levels)
{
ZoneScopedN("LOD");
typename std::vector<I> full(indices);

View File

@ -5,15 +5,15 @@
using namespace buffer;
ShortIndexed::Data::Data(const std::vector<VertexData> &vs, const std::vector<GLushort> &indices): indices(indices), vertices(vs) { }
void ShortIndexed::Data::index(const std::vector<VertexData>& vs) {
ShortIndexed::Data::Data(const std::vector<PackedVertexData> &vs, const std::vector<GLushort> &indices): indices(indices), vertices(vs) { }
void ShortIndexed::Data::index(const std::vector<PackedVertexData>& vs) {
indexVBO(vs, indices, vertices);
}
ShortIndexed::ShortIndexed(GLenum shape, const std::vector<VertexData> &vertices): Abstract(shape) {
ShortIndexed::ShortIndexed(GLenum shape, const std::vector<PackedVertexData> &vertices): Abstract(shape) {
setData(ShortIndexed::Data(vertices));
}
ShortIndexed::ShortIndexed(GLenum shape, const std::vector<VertexData> &vertices, const std::vector<GLushort>& indices): Abstract(shape) {
ShortIndexed::ShortIndexed(GLenum shape, const std::vector<PackedVertexData> &vertices, const std::vector<GLushort>& indices): Abstract(shape) {
setData(ShortIndexed::Data(vertices, indices));
}
ShortIndexed::ShortIndexed(GLenum shape, const ShortIndexed::Data &data): Abstract(shape) {
@ -30,10 +30,10 @@ void ShortIndexed::enableVertexAttrib() {
glVertexAttribPointer(
0, // attribute
3, // size
GL_FLOAT, // type
GL_HALF_FLOAT, // type
GL_FALSE, // normalized?
sizeof(VertexData), // stride
reinterpret_cast<void *>(offsetof(VertexData, Position)) // array buffer offset
sizeof(PackedVertexData), // stride
reinterpret_cast<void *>(offsetof(PackedVertexData, PosMat[0])) // array buffer offset
);
}
@ -42,21 +42,21 @@ void ShortIndexed::enableAllAttribs() {
glEnableVertexAttribArray(1);
glVertexAttribIPointer(
1, // attribute
1, // size
GL_UNSIGNED_SHORT, // type
sizeof(VertexData), // stride
reinterpret_cast<void *>(offsetof(VertexData, Material)) // array buffer offset
1, // attribute
1, // size
GL_UNSIGNED_SHORT, // type
sizeof(PackedVertexData), // stride
reinterpret_cast<void *>(offsetof(PackedVertexData, PosMat[3])) // array buffer offset
);
glEnableVertexAttribArray(2);
glVertexAttribPointer(
2, // attribute
3, // size
GL_FLOAT, // type
GL_FALSE, // normalized?
sizeof(VertexData), // stride
reinterpret_cast<void *>(offsetof(VertexData, Normal)) // array buffer offset
2, // attribute
3, // size
GL_HALF_FLOAT, // type
GL_FALSE, // normalized?
sizeof(PackedVertexData), // stride
reinterpret_cast<void *>(offsetof(PackedVertexData, Nrm)) // array buffer offset
);
}
void ShortIndexed::disableAllAttribs() {
@ -96,7 +96,7 @@ void ShortIndexed::setData(const ShortIndexed::Data& data) {
LOG_E("ShortBuffer overflow: " << data.indices.size());
}
setIndicies(IndexSize * sizeof(GLushort), data.indices.data());
setVertices(data.vertices.size() * sizeof(VertexData), data.vertices.data());
setVertices(data.vertices.size() * sizeof(PackedVertexData), data.vertices.data());
}
void ShortIndexed::setIndicies(const unsigned long size, const void *data) {

View File

@ -14,13 +14,13 @@ namespace buffer {
/// Preindexed buffer data
struct Data {
std::vector<GLushort> indices;
std::vector<VertexData> vertices;
std::vector<PackedVertexData> vertices;
Data() { }
Data(const std::vector<VertexData> &vertices, const std::vector<GLushort> &indices);
Data(const std::vector<VertexData> &vertices) { index(vertices); }
Data(const std::vector<PackedVertexData> &vertices, const std::vector<GLushort> &indices);
Data(const std::vector<PackedVertexData> &vertices) { index(vertices); }
void index(const std::vector<VertexData> &vertices);
void index(const std::vector<PackedVertexData> &vertices);
bool empty() const {
return indices.empty();
}
@ -30,8 +30,8 @@ namespace buffer {
}
};
ShortIndexed(GLenum shape, const typename std::vector<VertexData> &vertices);
ShortIndexed(GLenum shape, const typename std::vector<VertexData> &vertices, const typename std::vector<GLushort> &indices);
ShortIndexed(GLenum shape, const typename std::vector<PackedVertexData> &vertices);
ShortIndexed(GLenum shape, const typename std::vector<PackedVertexData> &vertices, const typename std::vector<GLushort> &indices);
ShortIndexed(GLenum shape, const typename ShortIndexed::Data &data);
virtual ~ShortIndexed();

View File

@ -12,8 +12,24 @@ namespace buffer {
glm::vec3 Position;
GLushort Material;
glm::vec3 Normal;
bool operator<(const VertexData that) const {
return memcmp((void *)this, (void *)&that, sizeof(VertexData)) > 0;
};
/// Quantized vertex properties
struct PackedVertexData {
PackedVertexData(GLushort x, GLushort y, GLushort z, GLushort mat, GLushort nx, GLushort ny, GLushort nz, GLushort nw = 0) {
PosMat[0] = x;
PosMat[1] = y;
PosMat[2] = z;
PosMat[3] = mat;
Nrm[0] = nx;
Nrm[1] = ny;
Nrm[2] = nz;
Nrm[3] = nw;
}
GLushort PosMat[4];
GLushort Nrm[4];
bool operator<(const PackedVertexData that) const {
return memcmp((void *)this, (void *)&that, sizeof(PackedVertexData)) > 0;
};
};
}

View File

@ -6,11 +6,11 @@
#include "vboindexer.hpp"
bool getSimilarVertexIndex_fast(
const buffer::VertexData &packed,
std::map<buffer::VertexData, GLushort> &VertexToOutIndex,
const buffer::PackedVertexData &packed,
std::map<buffer::PackedVertexData, GLushort> &VertexToOutIndex,
GLushort &result)
{
std::map<buffer::VertexData, GLushort>::iterator it = VertexToOutIndex.find(packed);
std::map<buffer::PackedVertexData, GLushort>::iterator it = VertexToOutIndex.find(packed);
if ( it == VertexToOutIndex.end() ){
return false;
}else{
@ -19,11 +19,11 @@ bool getSimilarVertexIndex_fast(
}
}
bool getSimilarVertexIndex_fast(
const buffer::VertexData &packed,
std::map<buffer::VertexData, unsigned int> &VertexToOutIndex,
const buffer::PackedVertexData &packed,
std::map<buffer::PackedVertexData, unsigned int> &VertexToOutIndex,
unsigned int &result)
{
std::map<buffer::VertexData, unsigned int>::iterator it = VertexToOutIndex.find(packed);
std::map<buffer::PackedVertexData, unsigned int>::iterator it = VertexToOutIndex.find(packed);
if ( it == VertexToOutIndex.end() ){
return false;
}else{
@ -33,12 +33,12 @@ bool getSimilarVertexIndex_fast(
}
void indexVBO(
const std::vector<buffer::VertexData> &in_vertices,
const std::vector<buffer::PackedVertexData> &in_vertices,
std::vector<GLushort> &out_indices,
std::vector<buffer::VertexData> &out_vertices)
std::vector<buffer::PackedVertexData> &out_vertices)
{
std::map<buffer::VertexData, GLushort> VertexToOutIndex;
std::map<buffer::PackedVertexData, GLushort> VertexToOutIndex;
out_indices.reserve(in_vertices.size());
// For each input vertex

View File

@ -7,9 +7,9 @@
#include <GL/glew.h>
void indexVBO(
const std::vector<buffer::VertexData> &in_vertices,
const std::vector<buffer::PackedVertexData> &in_vertices,
std::vector<GLushort> &out_indices,
std::vector<buffer::VertexData> &out_vertices);
std::vector<buffer::PackedVertexData> &out_vertices);
#endif

View File

@ -48,8 +48,9 @@ Universe::Universe(const Universe::options &options): dicts("content/zstd.dict"
} else {
LOG_E("No index file!!! Probably a new world...");
//TODO: generate universe
const auto radius = 1 << 4;
far_areas.emplace(Area::params{glm::multiply(voxel_pos(radius)), radius, Generator::Properties(radius * CHUNK_LENGTH * 3 / 4, 42)});
/*const auto radius = 1 << 4;
far_areas.emplace(Area::params{glm::multiply(voxel_pos(radius)), radius, Generator::Properties(radius * CHUNK_LENGTH * 3 / 4, 42)});*/
far_areas.emplace(Area::params{voxel_pos(0), 1 << 20, Generator::Properties(42)});
}
index.close();
}