Refactor mesh handling to use templated vertex structures for improved type safety and flexibility
This commit is contained in:
@@ -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)};
|
||||
}
|
||||
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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 ®ion) {
|
||||
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]
|
||||
);
|
||||
}
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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},
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user