VertexData packing
This commit is contained in:
parent
b98a791fc4
commit
bfba0544d6
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
}
|
||||
|
|
|
@ -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++) {
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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();
|
||||
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
};
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
|
@ -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();
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue