Working on voxels
This commit is contained in:
parent
041853a4a0
commit
5d0741635c
92
Deer/Include/DeerCore/Voxel.h
Normal file
92
Deer/Include/DeerCore/Voxel.h
Normal file
@ -0,0 +1,92 @@
|
|||||||
|
#pragma once
|
||||||
|
#include "DeerCore/Tools/Memory.h"
|
||||||
|
#include "DeerCore/Tools/TypeDefs.h"
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <unordered_map>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#define CHUNK_VOXEL_SIZE 16
|
||||||
|
|
||||||
|
#ifdef DEER_RENDER
|
||||||
|
#include "DeerRender/Resource.h"
|
||||||
|
namespace Deer {
|
||||||
|
class VoxelBuilder;
|
||||||
|
class GPUMesh;
|
||||||
|
} // namespace Deer
|
||||||
|
#endif
|
||||||
|
|
||||||
|
namespace Deer {
|
||||||
|
struct VoxelType {
|
||||||
|
std::string id;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Chunk {
|
||||||
|
Chunk() {
|
||||||
|
Voxel voxel = {.voxelTypeId = 0};
|
||||||
|
voxels_list.push_back(voxel);
|
||||||
|
voxels_reference_map[voxel] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Voxel {
|
||||||
|
uint32_t voxelTypeId;
|
||||||
|
|
||||||
|
bool operator==(const Voxel& other) const noexcept {
|
||||||
|
return voxelTypeId == other.voxelTypeId;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct VoxelHasher {
|
||||||
|
std::size_t operator()(const Voxel& v) const noexcept {
|
||||||
|
return std::hash<uint32_t>{}(v.voxelTypeId);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
std::vector<Chunk::Voxel> voxels_list;
|
||||||
|
std::unordered_map<Chunk::Voxel, uint16_t, VoxelHasher> voxels_reference_map;
|
||||||
|
uint16_t reference_matrix[CHUNK_VOXEL_SIZE][CHUNK_VOXEL_SIZE][CHUNK_VOXEL_SIZE];
|
||||||
|
|
||||||
|
uint16_t getOrCreateVoxelReference(const Voxel& voxel);
|
||||||
|
Voxel getVoxel(uint16_t voxelReference);
|
||||||
|
};
|
||||||
|
|
||||||
|
class VoxelEnvironment {
|
||||||
|
public:
|
||||||
|
VoxelEnvironment();
|
||||||
|
|
||||||
|
void modifyVoxel(uint32_t voxelId, int x, int y, int z);
|
||||||
|
uint32_t getVoxel(int x, int y, int z);
|
||||||
|
|
||||||
|
#ifdef DEER_RENDER
|
||||||
|
public:
|
||||||
|
Resource<GPUMesh> buildChunk(int x, int y, int z);
|
||||||
|
Scope<VoxelBuilder> voxelBuilder;
|
||||||
|
#endif
|
||||||
|
private:
|
||||||
|
struct ChunkID {
|
||||||
|
int x, y, z;
|
||||||
|
|
||||||
|
bool operator==(const ChunkID& other) const noexcept {
|
||||||
|
return x == other.x &&
|
||||||
|
y == other.y &&
|
||||||
|
z == other.z;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ChunkIDHasher {
|
||||||
|
std::size_t operator()(const ChunkID& c) const noexcept {
|
||||||
|
std::size_t h = 0;
|
||||||
|
h ^= std::hash<int>{}(c.x) + 0x9e3779b9 + (h << 6) + (h >> 2);
|
||||||
|
h ^= std::hash<int>{}(c.y) + 0x9e3779b9 + (h << 6) + (h >> 2);
|
||||||
|
h ^= std::hash<int>{}(c.z) + 0x9e3779b9 + (h << 6) + (h >> 2);
|
||||||
|
return h;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
Chunk* getOrCreateChunk(int x, int y, int z);
|
||||||
|
Chunk* tryGetChunk(int x, int y, int z);
|
||||||
|
|
||||||
|
std::vector<Scope<Chunk>> chunk_list;
|
||||||
|
std::unordered_map<ChunkID, Chunk*, ChunkIDHasher> chunk_map;
|
||||||
|
};
|
||||||
|
} // namespace Deer
|
||||||
@ -24,6 +24,12 @@ namespace Deer {
|
|||||||
VertexUV(float _u, float _v) : u(_u), v(_v) {}
|
VertexUV(float _u, float _v) : u(_u), v(_v) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct VertexLight {
|
||||||
|
uint8_t light;
|
||||||
|
|
||||||
|
VertexLight() = default;
|
||||||
|
VertexLight(int8_t _u) : light(_u) {}
|
||||||
|
};
|
||||||
// Vertex normal is represented with a number fromn [-64,64], and then its
|
// Vertex normal is represented with a number fromn [-64,64], and then its
|
||||||
// divided by 64 to know the decimal number
|
// divided by 64 to know the decimal number
|
||||||
struct VertexNormal {
|
struct VertexNormal {
|
||||||
@ -43,6 +49,7 @@ namespace Deer {
|
|||||||
vertexCount = count;
|
vertexCount = count;
|
||||||
}
|
}
|
||||||
void createUVData() { vertexUVData = MakeScope<VertexUV[]>(vertexCount); }
|
void createUVData() { vertexUVData = MakeScope<VertexUV[]>(vertexCount); }
|
||||||
|
void createLightData() { vertexLightData = MakeScope<VertexLight[]>(vertexCount); }
|
||||||
void createIndices(uint32_t count) {
|
void createIndices(uint32_t count) {
|
||||||
indexData = MakeScope<uint32_t[]>(count);
|
indexData = MakeScope<uint32_t[]>(count);
|
||||||
indexCount = count;
|
indexCount = count;
|
||||||
@ -51,6 +58,7 @@ namespace Deer {
|
|||||||
inline VertexPosition* getVertexPosition() const { return vertexPositionsData.get(); }
|
inline VertexPosition* getVertexPosition() const { return vertexPositionsData.get(); }
|
||||||
inline VertexNormal* getVertexNormal() const { return vertexNormalData.get(); }
|
inline VertexNormal* getVertexNormal() const { return vertexNormalData.get(); }
|
||||||
inline VertexUV* getVertexUV() const { return vertexUVData.get(); }
|
inline VertexUV* getVertexUV() const { return vertexUVData.get(); }
|
||||||
|
inline VertexLight* getVertexLight() const { return vertexLightData.get(); }
|
||||||
inline uint32_t* getIndexData() const { return indexData.get(); }
|
inline uint32_t* getIndexData() const { return indexData.get(); }
|
||||||
|
|
||||||
inline uint32_t getVertexCount() const { return vertexCount; }
|
inline uint32_t getVertexCount() const { return vertexCount; }
|
||||||
@ -61,6 +69,7 @@ namespace Deer {
|
|||||||
Scope<VertexPosition[]> vertexPositionsData;
|
Scope<VertexPosition[]> vertexPositionsData;
|
||||||
Scope<VertexNormal[]> vertexNormalData;
|
Scope<VertexNormal[]> vertexNormalData;
|
||||||
Scope<VertexUV[]> vertexUVData;
|
Scope<VertexUV[]> vertexUVData;
|
||||||
|
Scope<VertexLight[]> vertexLightData;
|
||||||
|
|
||||||
uint32_t indexCount = 0;
|
uint32_t indexCount = 0;
|
||||||
Scope<uint32_t[]> indexData;
|
Scope<uint32_t[]> indexData;
|
||||||
|
|||||||
@ -1,23 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
#include "DeerRender/EntityEnviroment.h"
|
|
||||||
#include "DeerRender/Render/FrameBuffer.h"
|
|
||||||
#include "DeerRender/Tools/Memory.h"
|
|
||||||
|
|
||||||
namespace Deer {
|
|
||||||
class RenderPiperline {
|
|
||||||
public:
|
|
||||||
RenderPiperline(RenderPiperline&) = delete;
|
|
||||||
RenderPiperline(PiperlineOptions);
|
|
||||||
|
|
||||||
void render(const EntityEnvironment&);
|
|
||||||
|
|
||||||
private:
|
|
||||||
Scope<FrameBuffer> resultImage;
|
|
||||||
PiperlineOptions options;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct PiperlineOptions {
|
|
||||||
int width = 100;
|
|
||||||
int height = 100;
|
|
||||||
};
|
|
||||||
} // namespace Deer
|
|
||||||
78
Deer/Include/DeerRender/Voxel.h
Normal file
78
Deer/Include/DeerRender/Voxel.h
Normal file
@ -0,0 +1,78 @@
|
|||||||
|
#pragma once
|
||||||
|
#include "DeerCore/Voxel.h"
|
||||||
|
|
||||||
|
#include "DeerRender/Mesh.h"
|
||||||
|
#include "glm/glm.hpp"
|
||||||
|
|
||||||
|
#include <array>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
namespace Deer {
|
||||||
|
struct VoxelVertex {
|
||||||
|
VoxelVertex() = default;
|
||||||
|
VoxelVertex(glm::vec3 _position) : position(_position) {}
|
||||||
|
|
||||||
|
glm::vec3 position;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct VoxelFaceData {
|
||||||
|
// Basic construction
|
||||||
|
std::vector<VoxelVertex> vertices;
|
||||||
|
std::vector<uint32_t> triangles;
|
||||||
|
|
||||||
|
std::array<std::vector<uint32_t>, 4> connections;
|
||||||
|
std::array<uint32_t, 4> edges;
|
||||||
|
};
|
||||||
|
|
||||||
|
class VoxelBuilder {
|
||||||
|
public:
|
||||||
|
Resource<GPUMesh> buildChunk(int x, int y, int z);
|
||||||
|
|
||||||
|
VoxelBuilder(VoxelEnvironment* env) : environment(env) {}
|
||||||
|
|
||||||
|
private:
|
||||||
|
struct VoxelData {
|
||||||
|
int16_t vertexIndexFace[6] = {-1, -1, -1, -1, -1, -1};
|
||||||
|
};
|
||||||
|
|
||||||
|
struct VertexData {
|
||||||
|
glm::vec3 position;
|
||||||
|
glm::vec3 normal;
|
||||||
|
float extrussion;
|
||||||
|
float light;
|
||||||
|
};
|
||||||
|
|
||||||
|
private:
|
||||||
|
void addFace(VoxelFaceData& data, glm::vec3 origin, glm::vec3 up, glm::vec3 right);
|
||||||
|
void calculateNormals();
|
||||||
|
|
||||||
|
void buildVertices();
|
||||||
|
void buildFaceVertices(int x, int y, int z, int face);
|
||||||
|
|
||||||
|
void buildConnections();
|
||||||
|
void buildAxisConnections(int x, int y, int z);
|
||||||
|
void connectVertices(VoxelFaceData& face1, int edgeIndex1, int face1VertexOffset, VoxelFaceData& face2, int edgeIndex2, int face2VertexOffset);
|
||||||
|
|
||||||
|
void buildMarchingCubesCorners();
|
||||||
|
void buildMarchingVoxel(int x, int y, int z, uint8_t marchingCubeId);
|
||||||
|
int getVertexIdCorner(int x, int y, int z, int edge);
|
||||||
|
|
||||||
|
VoxelData& getVoxelData(int x, int y, int z);
|
||||||
|
void clearVoxelData();
|
||||||
|
|
||||||
|
bool hasBlock(int x, int y, int z);
|
||||||
|
float calculateVertexSunLight(int x, int y, int z);
|
||||||
|
|
||||||
|
std::vector<VertexData> vertices;
|
||||||
|
std::vector<u_int32_t> indices;
|
||||||
|
|
||||||
|
int voxelXOffset;
|
||||||
|
int voxelYOffset;
|
||||||
|
int voxelZOffset;
|
||||||
|
|
||||||
|
VoxelEnvironment* environment;
|
||||||
|
VoxelData voxelData[CHUNK_VOXEL_SIZE + 2][CHUNK_VOXEL_SIZE + 2][CHUNK_VOXEL_SIZE + 2];
|
||||||
|
|
||||||
|
friend VoxelEnvironment;
|
||||||
|
};
|
||||||
|
} // namespace Deer
|
||||||
16
Deer/src/DeerCore/Voxel/Chunk.cpp
Normal file
16
Deer/src/DeerCore/Voxel/Chunk.cpp
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
#include "DeerCore/Voxel.h"
|
||||||
|
|
||||||
|
namespace Deer {
|
||||||
|
uint16_t Chunk::getOrCreateVoxelReference(const Voxel& voxel) {
|
||||||
|
if (voxels_reference_map.contains(voxel))
|
||||||
|
return voxels_reference_map[voxel];
|
||||||
|
|
||||||
|
voxels_list.push_back(voxel);
|
||||||
|
voxels_reference_map[voxel] = voxels_list.size() - 1;
|
||||||
|
return voxels_list.size() - 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
Chunk::Voxel Chunk::getVoxel(uint16_t voxelReference) {
|
||||||
|
return voxels_list[voxelReference];
|
||||||
|
}
|
||||||
|
} // namespace Deer
|
||||||
91
Deer/src/DeerCore/Voxel/VoxelEnvironment.cpp
Normal file
91
Deer/src/DeerCore/Voxel/VoxelEnvironment.cpp
Normal file
@ -0,0 +1,91 @@
|
|||||||
|
#include "DeerCore/Voxel.h"
|
||||||
|
|
||||||
|
namespace Deer {
|
||||||
|
namespace Voxel {
|
||||||
|
int getChunk(int id) {
|
||||||
|
int chunk = id / CHUNK_VOXEL_SIZE;
|
||||||
|
|
||||||
|
// Fix truncation toward zero for negatives
|
||||||
|
if (id < 0 && id % CHUNK_VOXEL_SIZE != 0)
|
||||||
|
--chunk;
|
||||||
|
|
||||||
|
return chunk;
|
||||||
|
}
|
||||||
|
|
||||||
|
int getBlock(int id) {
|
||||||
|
int block = id % CHUNK_VOXEL_SIZE;
|
||||||
|
|
||||||
|
// Make remainder positive
|
||||||
|
if (block < 0)
|
||||||
|
block += CHUNK_VOXEL_SIZE;
|
||||||
|
|
||||||
|
return block;
|
||||||
|
}
|
||||||
|
} // namespace Voxel
|
||||||
|
|
||||||
|
Chunk* VoxelEnvironment::getOrCreateChunk(int x, int y, int z) {
|
||||||
|
ChunkID chunkId = {
|
||||||
|
.x = Voxel::getChunk(x),
|
||||||
|
.y = Voxel::getChunk(y),
|
||||||
|
.z = Voxel::getChunk(z)};
|
||||||
|
|
||||||
|
if (chunk_map.contains(chunkId))
|
||||||
|
return chunk_map[chunkId];
|
||||||
|
|
||||||
|
// Should do stuff but we relax for the moment
|
||||||
|
chunk_list.push_back(MakeScope<Chunk>());
|
||||||
|
Chunk* chunk = chunk_list.back().get();
|
||||||
|
chunk_map[chunkId] = chunk;
|
||||||
|
|
||||||
|
for (int x = 0; x < CHUNK_VOXEL_SIZE; x++) {
|
||||||
|
for (int y = 0; y < CHUNK_VOXEL_SIZE; y++) {
|
||||||
|
for (int z = 0; z < CHUNK_VOXEL_SIZE; z++) {
|
||||||
|
chunk->reference_matrix[x][y][z] = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return chunk;
|
||||||
|
}
|
||||||
|
|
||||||
|
Chunk* VoxelEnvironment::tryGetChunk(int x, int y, int z) {
|
||||||
|
ChunkID chunkId = {
|
||||||
|
.x = Voxel::getChunk(x),
|
||||||
|
.y = Voxel::getChunk(y),
|
||||||
|
.z = Voxel::getChunk(z)};
|
||||||
|
|
||||||
|
if (chunk_map.contains(chunkId))
|
||||||
|
return chunk_map[chunkId];
|
||||||
|
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
void VoxelEnvironment::modifyVoxel(uint32_t voxelId, int x, int y, int z) {
|
||||||
|
Chunk* chunk = getOrCreateChunk(x, y, z);
|
||||||
|
|
||||||
|
Chunk::Voxel voxel = {.voxelTypeId = voxelId};
|
||||||
|
|
||||||
|
uint16_t voxelRef = chunk->getOrCreateVoxelReference(voxel);
|
||||||
|
|
||||||
|
int posX = Voxel::getBlock(x);
|
||||||
|
int posY = Voxel::getBlock(y);
|
||||||
|
int posZ = Voxel::getBlock(z);
|
||||||
|
|
||||||
|
chunk->reference_matrix[posX][posY][posZ] = voxelRef;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t VoxelEnvironment::getVoxel(int x, int y, int z) {
|
||||||
|
Chunk* chunk = tryGetChunk(x, y, z);
|
||||||
|
|
||||||
|
if (!chunk)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
int posX = Voxel::getBlock(x);
|
||||||
|
int posY = Voxel::getBlock(y);
|
||||||
|
int posZ = Voxel::getBlock(z);
|
||||||
|
|
||||||
|
uint16_t voxelRef = chunk->reference_matrix[posX][posY][posZ];
|
||||||
|
return chunk->getVoxel(voxelRef).voxelTypeId;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Deer
|
||||||
@ -34,7 +34,15 @@ namespace Deer {
|
|||||||
vertexNormalBuffer->setLayout(normalLayout);
|
vertexNormalBuffer->setLayout(normalLayout);
|
||||||
vertexArray->addVertexBuffer(vertexNormalBuffer);
|
vertexArray->addVertexBuffer(vertexNormalBuffer);
|
||||||
|
|
||||||
if (data.getVertexPosition()) {
|
if (data.getVertexLight()) {
|
||||||
|
BufferLayout lightLayout({{"v_Light", DataType::Unsigned_Byte, ShaderDataType::FloatingPoint}}, sizeof(VertexLight));
|
||||||
|
Ref<VertexBuffer> vertexLightBuffer = VertexBuffer::create(data.getVertexLight(), data.getVertexCount() * sizeof(VertexLight));
|
||||||
|
vertexLightBuffer->bind();
|
||||||
|
vertexLightBuffer->setLayout(lightLayout);
|
||||||
|
vertexArray->addVertexBuffer(vertexLightBuffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (data.getVertexUV()) {
|
||||||
BufferLayout uvLayout({{"v_UV", DataType::Float2, ShaderDataType::FloatingPoint}}, sizeof(VertexUV));
|
BufferLayout uvLayout({{"v_UV", DataType::Float2, ShaderDataType::FloatingPoint}}, sizeof(VertexUV));
|
||||||
Ref<VertexBuffer> vertexUVBuffer = VertexBuffer::create(data.getVertexUV(), data.getVertexCount() * sizeof(VertexUV));
|
Ref<VertexBuffer> vertexUVBuffer = VertexBuffer::create(data.getVertexUV(), data.getVertexCount() * sizeof(VertexUV));
|
||||||
vertexUVBuffer->bind();
|
vertexUVBuffer->bind();
|
||||||
|
|||||||
428
Deer/src/DeerRender/Voxel/VoxelBuilder.cpp
Normal file
428
Deer/src/DeerRender/Voxel/VoxelBuilder.cpp
Normal file
@ -0,0 +1,428 @@
|
|||||||
|
#include "DeerCore/Log.h"
|
||||||
|
#include "DeerRender/Voxel.h"
|
||||||
|
#include "DeerRender/Voxel/VoxelData.h"
|
||||||
|
#include <random>
|
||||||
|
|
||||||
|
namespace Deer {
|
||||||
|
|
||||||
|
VoxelFaceData testFaceData = {
|
||||||
|
.vertices = {
|
||||||
|
VoxelVertex(glm::vec3(0.1f, 0.90f, 0.1f)), // 0
|
||||||
|
VoxelVertex(glm::vec3(0.5f, 0.90f, 0.1f)), // 1
|
||||||
|
VoxelVertex(glm::vec3(0.9f, 0.90f, 0.1f)), // 2
|
||||||
|
VoxelVertex(glm::vec3(0.1f, 0.6f, 0.2f)), // 3
|
||||||
|
VoxelVertex(glm::vec3(0.5f, 0.35f, 0.2f)), // 4
|
||||||
|
VoxelVertex(glm::vec3(0.9f, 0.6f, 0.2f)), // 5
|
||||||
|
VoxelVertex(glm::vec3(0.1f, 0.55f, 0)), // 3
|
||||||
|
VoxelVertex(glm::vec3(0.5f, 0.3f, 0)), // 4
|
||||||
|
VoxelVertex(glm::vec3(0.9f, 0.55f, 0)), // 5
|
||||||
|
VoxelVertex(glm::vec3(0.1f, 0.1f, 0)), // 6
|
||||||
|
VoxelVertex(glm::vec3(0.5f, 0.1f, 0)), // 7
|
||||||
|
VoxelVertex(glm::vec3(0.9f, 0.1f, 0)), // 8
|
||||||
|
},
|
||||||
|
.triangles = {0, 1, 3, 3, 1, 4, 5, 1, 2, 1, 5, 4, 3, 4, 7, 3, 7, 6, 5, 8, 4, 4, 8, 7, 6, 7, 9, 7, 10, 9, 8, 11, 7, 7, 11, 10},
|
||||||
|
.connections = {
|
||||||
|
std::vector<uint32_t>{9, 6, 3, 0}, // [0]
|
||||||
|
std::vector<uint32_t>{2, 5, 8, 11}, // [1]
|
||||||
|
std::vector<uint32_t>{11, 10, 9}, // [2]
|
||||||
|
std::vector<uint32_t>{0, 1, 2} // [3]
|
||||||
|
},
|
||||||
|
.edges = {9, 11, 0, 2}};
|
||||||
|
|
||||||
|
VoxelFaceData flatFaceData = {
|
||||||
|
.vertices = {
|
||||||
|
VoxelVertex(glm::vec3(0.3f, 0.3f, 0)),
|
||||||
|
VoxelVertex(glm::vec3(0.7f, 0.3f, 0)),
|
||||||
|
VoxelVertex(glm::vec3(0.3f, 0.7f, 0)),
|
||||||
|
VoxelVertex(glm::vec3(0.7f, 0.7f, 0)),
|
||||||
|
},
|
||||||
|
.triangles = {0, 2, 1, 1, 2, 3},
|
||||||
|
.connections = {
|
||||||
|
std::vector<uint32_t>{0, 2}, // [0]
|
||||||
|
std::vector<uint32_t>{3, 1}, // [1]
|
||||||
|
std::vector<uint32_t>{1, 0}, // [2]
|
||||||
|
std::vector<uint32_t>{2, 3} // [3]
|
||||||
|
},
|
||||||
|
.edges = {0, 1, 2, 3}};
|
||||||
|
/*
|
||||||
|
VoxelFaceData testFaceData = {
|
||||||
|
.vertices = {
|
||||||
|
VoxelVertex(glm::vec2(0.1f, 0.95f)), // 0
|
||||||
|
VoxelVertex(glm::vec2(0.4f, 0.8f)), // 1
|
||||||
|
VoxelVertex(glm::vec2(0.9f, 0.95f)), // 2
|
||||||
|
VoxelVertex(glm::vec2(0.2f, 0.5f)), // 3
|
||||||
|
VoxelVertex(glm::vec2(0.5f, 0.6f)), // 4
|
||||||
|
VoxelVertex(glm::vec2(0.8f, 0.4f)), // 5
|
||||||
|
VoxelVertex(glm::vec2(0.1f, 0.1f)), // 6
|
||||||
|
VoxelVertex(glm::vec2(0.6f, 0.1f)), // 7
|
||||||
|
VoxelVertex(glm::vec2(0.9f, 0.1f)), // 8
|
||||||
|
},
|
||||||
|
.triangles = {0, 1, 3, 1, 4, 3, 1, 2, 5, 1, 5, 4, 6, 3, 4, 6, 4, 7, 4, 5, 7, 7, 5, 8},
|
||||||
|
.connections = {
|
||||||
|
std::vector<uint32_t>{6, 3, 0}, // [0]
|
||||||
|
std::vector<uint32_t>{2, 5, 8}, // [1]
|
||||||
|
std::vector<uint32_t>{8, 7, 6}, // [2]
|
||||||
|
std::vector<uint32_t>{0, 1, 2} // [3]
|
||||||
|
},
|
||||||
|
.edges = {6, 8, 0, 2}};
|
||||||
|
|
||||||
|
VoxelFaceData testFaceData = {
|
||||||
|
.vertices = {
|
||||||
|
VoxelVertex(glm::vec2(0.1f, 0.1f)),
|
||||||
|
VoxelVertex(glm::vec2(0.9f, 0.1f)),
|
||||||
|
VoxelVertex(glm::vec2(0.1f, 0.9f)),
|
||||||
|
VoxelVertex(glm::vec2(0.9f, 0.9f)),
|
||||||
|
},
|
||||||
|
.triangles = {0, 2, 1, 1, 2, 3},
|
||||||
|
.connections = {
|
||||||
|
std::vector<uint32_t>{0, 2}, // [0]
|
||||||
|
std::vector<uint32_t>{3, 1}, // [1]
|
||||||
|
std::vector<uint32_t>{1, 0}, // [2]
|
||||||
|
std::vector<uint32_t>{2, 3} // [3]
|
||||||
|
},
|
||||||
|
.edges = {0, 1, 2, 3}};
|
||||||
|
*/
|
||||||
|
|
||||||
|
void VoxelBuilder::calculateNormals() {
|
||||||
|
for (uint32_t indexId = 0; indexId < indices.size(); indexId += 3) {
|
||||||
|
glm::vec3 startIndex = vertices[indices[indexId + 0]].position;
|
||||||
|
glm::vec3 direction1 = vertices[indices[indexId + 1]].position - startIndex;
|
||||||
|
glm::vec3 direction2 = vertices[indices[indexId + 2]].position - startIndex;
|
||||||
|
|
||||||
|
glm::vec3 normal = glm::cross(direction1, direction2);
|
||||||
|
vertices[indices[indexId + 0]].normal += normal;
|
||||||
|
vertices[indices[indexId + 1]].normal += normal;
|
||||||
|
vertices[indices[indexId + 2]].normal += normal;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Resource<GPUMesh> VoxelBuilder::buildChunk(int x, int y, int z) {
|
||||||
|
voxelXOffset = x;
|
||||||
|
voxelYOffset = y;
|
||||||
|
voxelZOffset = z;
|
||||||
|
|
||||||
|
vertices.clear();
|
||||||
|
indices.clear();
|
||||||
|
clearVoxelData();
|
||||||
|
|
||||||
|
buildVertices();
|
||||||
|
buildConnections();
|
||||||
|
buildMarchingCubesCorners();
|
||||||
|
|
||||||
|
calculateNormals();
|
||||||
|
|
||||||
|
for (size_t i = 0; i < vertices.size(); i++) {
|
||||||
|
float randomValue = (float)(rand() % 1000) / 10000.0f - 0.05f;
|
||||||
|
randomValue = 0;
|
||||||
|
glm::vec3 normal = glm::normalize(vertices[i].normal);
|
||||||
|
vertices[i].position += normal * randomValue + normal * vertices[i].extrussion;
|
||||||
|
}
|
||||||
|
|
||||||
|
calculateNormals();
|
||||||
|
|
||||||
|
MeshData meshData;
|
||||||
|
meshData.createVertices(vertices.size());
|
||||||
|
meshData.createIndices(indices.size());
|
||||||
|
meshData.createLightData();
|
||||||
|
|
||||||
|
DEER_CORE_TRACE("{} , {}", meshData.getVertexCount(), meshData.getIndexCount());
|
||||||
|
for (size_t i = 0; i < meshData.getVertexCount(); i++) {
|
||||||
|
meshData.getVertexPosition()[i].x = vertices[i].position.x;
|
||||||
|
meshData.getVertexPosition()[i].y = vertices[i].position.y;
|
||||||
|
meshData.getVertexPosition()[i].z = vertices[i].position.z;
|
||||||
|
|
||||||
|
glm::vec3 normal = glm::normalize(vertices[i].normal);
|
||||||
|
meshData.getVertexNormal()[i].x = (uint8_t)(normal.x * 64);
|
||||||
|
meshData.getVertexNormal()[i].y = (uint8_t)(normal.y * 64);
|
||||||
|
meshData.getVertexNormal()[i].z = (uint8_t)(normal.z * 64);
|
||||||
|
|
||||||
|
meshData.getVertexLight()[i].light = (uint8_t)(vertices[i].light * 255.0f);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (size_t i = 0; i < meshData.getIndexCount(); i++) {
|
||||||
|
meshData.getIndexData()[i] = indices[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
return ResourceManager<GPUMesh>::loadResourceFromData(meshData, "tmp&&");
|
||||||
|
}
|
||||||
|
|
||||||
|
VoxelBuilder::VoxelData& VoxelBuilder::getVoxelData(int x, int y, int z) {
|
||||||
|
return voxelData[x + 1][y + 1][z + 1];
|
||||||
|
}
|
||||||
|
|
||||||
|
void VoxelBuilder::clearVoxelData() {
|
||||||
|
for (int x = 0; x < CHUNK_VOXEL_SIZE + 2; x++) {
|
||||||
|
for (int y = 0; y < CHUNK_VOXEL_SIZE + 2; y++) {
|
||||||
|
for (int z = 0; z < CHUNK_VOXEL_SIZE + 2; z++) {
|
||||||
|
voxelData[x][y][z] = VoxelData();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool VoxelBuilder::hasBlock(int x, int y, int z) {
|
||||||
|
uint32_t voxelId = environment->getVoxel(x, y, z);
|
||||||
|
return voxelId > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
float VoxelBuilder::calculateVertexSunLight(int x, int y, int z) {
|
||||||
|
float acumulatedLight = 0;
|
||||||
|
for (int i = 0; i < 8; i++) {
|
||||||
|
if (!hasBlock(x + Voxel::voxelCheckOrder[i][0],
|
||||||
|
y + Voxel::voxelCheckOrder[i][1],
|
||||||
|
z + Voxel::voxelCheckOrder[i][2]))
|
||||||
|
acumulatedLight += 1.0f / 4.0f;
|
||||||
|
}
|
||||||
|
if (acumulatedLight < 1)
|
||||||
|
return acumulatedLight;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void VoxelBuilder::buildVertices() {
|
||||||
|
for (int x = 0; x < CHUNK_VOXEL_SIZE; x++) {
|
||||||
|
for (int y = 0; y < CHUNK_VOXEL_SIZE; y++) {
|
||||||
|
for (int z = 0; z < CHUNK_VOXEL_SIZE; z++) {
|
||||||
|
if (!hasBlock(x, y, z))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
for (int i = 0; i < 6; i++) {
|
||||||
|
if (!hasBlock(
|
||||||
|
x + Voxel::faceNeighborOffset[i][0],
|
||||||
|
y + Voxel::faceNeighborOffset[i][1],
|
||||||
|
z + Voxel::faceNeighborOffset[i][2])) {
|
||||||
|
buildFaceVertices(x, y, z, i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void VoxelBuilder::buildFaceVertices(int x, int y, int z, int face) {
|
||||||
|
uint32_t startIndex = vertices.size();
|
||||||
|
getVoxelData(x, y, z).vertexIndexFace[face] = startIndex;
|
||||||
|
|
||||||
|
VoxelFaceData* faceData = &testFaceData;
|
||||||
|
if (face == 2 || face == 3)
|
||||||
|
faceData = &flatFaceData;
|
||||||
|
|
||||||
|
float cornersLight[4];
|
||||||
|
cornersLight[0] = calculateVertexSunLight(x + Voxel::faceOriginVectorInt[face][0],
|
||||||
|
y + Voxel::faceOriginVectorInt[face][1],
|
||||||
|
z + Voxel::faceOriginVectorInt[face][2]);
|
||||||
|
cornersLight[1] = calculateVertexSunLight(x + Voxel::faceOriginVectorInt[face][0] + Voxel::faceRightVector[face][0],
|
||||||
|
y + Voxel::faceOriginVectorInt[face][1] + Voxel::faceRightVector[face][1],
|
||||||
|
z + Voxel::faceOriginVectorInt[face][2] + Voxel::faceRightVector[face][2]);
|
||||||
|
cornersLight[2] = calculateVertexSunLight(x + Voxel::faceOriginVectorInt[face][0] + Voxel::faceUpVectorInt[face][0],
|
||||||
|
y + Voxel::faceOriginVectorInt[face][1] + Voxel::faceUpVectorInt[face][1],
|
||||||
|
z + Voxel::faceOriginVectorInt[face][2] + Voxel::faceUpVectorInt[face][2]);
|
||||||
|
cornersLight[3] = calculateVertexSunLight(x + Voxel::faceOriginVectorInt[face][0] + Voxel::faceUpVectorInt[face][0] + Voxel::faceRightVector[face][0],
|
||||||
|
y + Voxel::faceOriginVectorInt[face][1] + Voxel::faceUpVectorInt[face][1] + Voxel::faceRightVector[face][1],
|
||||||
|
z + Voxel::faceOriginVectorInt[face][2] + Voxel::faceUpVectorInt[face][2] + Voxel::faceRightVector[face][2]);
|
||||||
|
|
||||||
|
for (VoxelVertex& voxelVertex : faceData->vertices) {
|
||||||
|
glm::vec3 vertexPosition = glm::vec3(x, y, z) + Voxel::faceOriginVector[face];
|
||||||
|
glm::vec3 up = Voxel::faceUpVector[face];
|
||||||
|
glm::vec3 right = Voxel::faceRightVector[face];
|
||||||
|
|
||||||
|
vertexPosition += up * voxelVertex.position.y;
|
||||||
|
vertexPosition += right * voxelVertex.position.x;
|
||||||
|
|
||||||
|
glm::vec3 perpendicular = glm::cross(up, right);
|
||||||
|
|
||||||
|
float topLight = Voxel::lerp(voxelVertex.position.x, cornersLight[3], cornersLight[2]);
|
||||||
|
float bottomLight = Voxel::lerp(voxelVertex.position.x, cornersLight[1], cornersLight[0]);
|
||||||
|
|
||||||
|
vertices.push_back({});
|
||||||
|
VertexData& vv = vertices.back();
|
||||||
|
vv.position = vertexPosition;
|
||||||
|
vv.extrussion = voxelVertex.position.z;
|
||||||
|
vv.light = Voxel::lerp(voxelVertex.position.y, topLight, bottomLight);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (uint32_t index : faceData->triangles) {
|
||||||
|
indices.push_back(index + startIndex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// This function goes foreach edge, from (0, 0, 0) to (33, 33, 33) then check each edge
|
||||||
|
void VoxelBuilder::buildConnections() {
|
||||||
|
for (int x = 0; x < CHUNK_VOXEL_SIZE + 1; x++) {
|
||||||
|
for (int y = 0; y < CHUNK_VOXEL_SIZE + 1; y++) {
|
||||||
|
for (int z = 0; z < CHUNK_VOXEL_SIZE + 1; z++) {
|
||||||
|
buildAxisConnections(x, y, z);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void VoxelBuilder::buildAxisConnections(int x, int y, int z) {
|
||||||
|
for (int axis = 0; axis < AXIS_NUMBER; axis++) {
|
||||||
|
uint8_t edgeCheckBitmask = 0;
|
||||||
|
for (int edge = 0; edge < EDGE_PER_AXIS; edge++) {
|
||||||
|
uint8_t currentEdgeBitmask = 1 << edge;
|
||||||
|
if (edgeCheckBitmask & currentEdgeBitmask)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
Voxel::VoxelEdge& voxelEdge = Voxel::edgesPerAxis[axis][edge];
|
||||||
|
VoxelData& voxel = getVoxelData(x + voxelEdge.voxelOffset[0],
|
||||||
|
y + voxelEdge.voxelOffset[1],
|
||||||
|
z + voxelEdge.voxelOffset[2]);
|
||||||
|
bool existsFace = voxel.vertexIndexFace[voxelEdge.faceIndex] >= 0;
|
||||||
|
|
||||||
|
edgeCheckBitmask |= currentEdgeBitmask;
|
||||||
|
if (!existsFace)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
int edgeCheckIndex = edge;
|
||||||
|
for (int safeCheck = 0; safeCheck < EDGE_PER_AXIS - 1; safeCheck++) {
|
||||||
|
edgeCheckIndex += voxelEdge.isClockwiseOrder ? 1 : -1;
|
||||||
|
|
||||||
|
if (edgeCheckIndex >= EDGE_PER_AXIS)
|
||||||
|
edgeCheckIndex -= EDGE_PER_AXIS;
|
||||||
|
|
||||||
|
if (edgeCheckIndex < 0)
|
||||||
|
edgeCheckIndex += EDGE_PER_AXIS;
|
||||||
|
|
||||||
|
uint8_t nextEdgeBitmask = 1 << edgeCheckIndex;
|
||||||
|
if (nextEdgeBitmask & edgeCheckBitmask)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
edgeCheckBitmask |= nextEdgeBitmask;
|
||||||
|
|
||||||
|
Voxel::VoxelEdge& nextVoxelEdge = Voxel::edgesPerAxis[axis][edgeCheckIndex];
|
||||||
|
VoxelData& nextVoxel = getVoxelData(x + nextVoxelEdge.voxelOffset[0],
|
||||||
|
y + nextVoxelEdge.voxelOffset[1],
|
||||||
|
z + nextVoxelEdge.voxelOffset[2]);
|
||||||
|
|
||||||
|
bool nextEdgeExist = nextVoxel.vertexIndexFace[nextVoxelEdge.faceIndex] >= 0;
|
||||||
|
if (nextEdgeExist) {
|
||||||
|
|
||||||
|
VoxelFaceData* faceData1 = &testFaceData;
|
||||||
|
if (voxelEdge.faceIndex == 2 || voxelEdge.faceIndex == 3)
|
||||||
|
faceData1 = &flatFaceData;
|
||||||
|
|
||||||
|
VoxelFaceData* faceData2 = &testFaceData;
|
||||||
|
if (nextVoxelEdge.faceIndex == 2 || nextVoxelEdge.faceIndex == 3)
|
||||||
|
faceData2 = &flatFaceData;
|
||||||
|
|
||||||
|
connectVertices(*faceData1, voxelEdge.edgeIndex, voxel.vertexIndexFace[voxelEdge.faceIndex],
|
||||||
|
*faceData2, nextVoxelEdge.edgeIndex, nextVoxel.vertexIndexFace[nextVoxelEdge.faceIndex]);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void VoxelBuilder::connectVertices(VoxelFaceData& face1, int edgeIndex1, int face1VertexOffset, VoxelFaceData& face2, int edgeIndex2, int face2VertexOffset) {
|
||||||
|
int edge1Index = 0;
|
||||||
|
int edge2Index = face2.connections[edgeIndex2].size() - 1;
|
||||||
|
|
||||||
|
int triangleCount = 0;
|
||||||
|
while (edge1Index < face1.connections[edgeIndex1].size() - 1 || edge2Index > 0) {
|
||||||
|
triangleCount++;
|
||||||
|
if (edge1Index == face1.connections[edgeIndex1].size() - 1) {
|
||||||
|
indices.push_back(face1VertexOffset + face1.connections[edgeIndex1][edge1Index]);
|
||||||
|
indices.push_back(face2VertexOffset + face2.connections[edgeIndex2][edge2Index]);
|
||||||
|
indices.push_back(face2VertexOffset + face2.connections[edgeIndex2][edge2Index - 1]);
|
||||||
|
|
||||||
|
edge2Index--;
|
||||||
|
} else if (edge2Index == 0) {
|
||||||
|
indices.push_back(face2VertexOffset + face2.connections[edgeIndex2][edge2Index]);
|
||||||
|
indices.push_back(face1VertexOffset + face1.connections[edgeIndex1][edge1Index + 1]);
|
||||||
|
indices.push_back(face1VertexOffset + face1.connections[edgeIndex1][edge1Index]);
|
||||||
|
|
||||||
|
edge1Index++;
|
||||||
|
} else {
|
||||||
|
glm::vec3 firstEdgeVertex = vertices[face1.connections[edgeIndex1][edge1Index] + face1VertexOffset].position;
|
||||||
|
glm::vec3 secondEdgeVertex = vertices[face2.connections[edgeIndex2][edge2Index] + face2VertexOffset].position;
|
||||||
|
|
||||||
|
glm::vec3 midPoint = (firstEdgeVertex + secondEdgeVertex) * 0.5f;
|
||||||
|
|
||||||
|
glm::vec3 FED = vertices[face1.connections[edgeIndex1][edge1Index + 1] + face1VertexOffset].position - midPoint;
|
||||||
|
glm::vec3 SED = vertices[face2.connections[edgeIndex2][edge2Index - 1] + face2VertexOffset].position - midPoint;
|
||||||
|
|
||||||
|
float firstDistanceNext = FED.x * FED.x + FED.y * FED.y + FED.z * FED.z;
|
||||||
|
float secondDistanceNext = SED.x * SED.x + SED.y * SED.y + SED.z * SED.z;
|
||||||
|
|
||||||
|
if (firstDistanceNext > secondDistanceNext) {
|
||||||
|
indices.push_back(face1VertexOffset + face1.connections[edgeIndex1][edge1Index]);
|
||||||
|
indices.push_back(face2VertexOffset + face2.connections[edgeIndex2][edge2Index]);
|
||||||
|
indices.push_back(face2VertexOffset + face2.connections[edgeIndex2][edge2Index - 1]);
|
||||||
|
|
||||||
|
edge2Index--;
|
||||||
|
} else {
|
||||||
|
indices.push_back(face1VertexOffset + face1.connections[edgeIndex1][edge1Index]);
|
||||||
|
indices.push_back(face2VertexOffset + face2.connections[edgeIndex2][edge2Index]);
|
||||||
|
indices.push_back(face1VertexOffset + face1.connections[edgeIndex1][edge1Index + 1]);
|
||||||
|
|
||||||
|
edge1Index++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void VoxelBuilder::buildMarchingCubesCorners() {
|
||||||
|
for (int x = 0; x < CHUNK_VOXEL_SIZE + 1; x++) {
|
||||||
|
for (int y = 0; y < CHUNK_VOXEL_SIZE + 1; y++) {
|
||||||
|
for (int z = 0; z < CHUNK_VOXEL_SIZE + 1; z++) {
|
||||||
|
uint8_t marchingCubeId = 0;
|
||||||
|
for (int side = 0; side < CUBE_SIDES; side++) {
|
||||||
|
bool hasVoxel = hasBlock(x + Voxel::voxelCheckOrder[side][0],
|
||||||
|
y + Voxel::voxelCheckOrder[side][1],
|
||||||
|
z + Voxel::voxelCheckOrder[side][2]);
|
||||||
|
|
||||||
|
if (hasVoxel)
|
||||||
|
marchingCubeId |= 1 << side;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (marchingCubeId == 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
buildMarchingVoxel(x, y, z, marchingCubeId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void VoxelBuilder::buildMarchingVoxel(int x, int y, int z, uint8_t marchingCubeId) {
|
||||||
|
for (int safeStop = 0; safeStop < 16; safeStop += 3) {
|
||||||
|
int nextMarchingCubesedgeIndex = Voxel::marchingCubesTriTable[marchingCubeId][safeStop];
|
||||||
|
if (nextMarchingCubesedgeIndex == -1)
|
||||||
|
return;
|
||||||
|
|
||||||
|
int vertices[3] = {
|
||||||
|
getVertexIdCorner(x, y, z, nextMarchingCubesedgeIndex),
|
||||||
|
getVertexIdCorner(x, y, z, Voxel::marchingCubesTriTable[marchingCubeId][safeStop + 1]),
|
||||||
|
getVertexIdCorner(x, y, z, Voxel::marchingCubesTriTable[marchingCubeId][safeStop + 2]),
|
||||||
|
};
|
||||||
|
|
||||||
|
if (vertices[0] != -1 && vertices[1] != -1 && vertices[2] != -1) {
|
||||||
|
indices.push_back(vertices[0]);
|
||||||
|
indices.push_back(vertices[1]);
|
||||||
|
indices.push_back(vertices[2]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int VoxelBuilder::getVertexIdCorner(int x, int y, int z, int edge) {
|
||||||
|
for (int i = 0; i < 2; i++) {
|
||||||
|
Voxel::VoxelCorner& option = Voxel::marchingCubesEdgeCornerPairs[edge][i];
|
||||||
|
|
||||||
|
VoxelData& _voxelData = getVoxelData(x + option.voxelOffset[0],
|
||||||
|
y + option.voxelOffset[1],
|
||||||
|
z + option.voxelOffset[2]);
|
||||||
|
|
||||||
|
VoxelFaceData* faceData = &testFaceData;
|
||||||
|
if (option.faceIndex == 2 || option.faceIndex == 3)
|
||||||
|
faceData = &flatFaceData;
|
||||||
|
|
||||||
|
int voxelDataFaceOffset = _voxelData.vertexIndexFace[option.faceIndex];
|
||||||
|
if (voxelDataFaceOffset >= 0)
|
||||||
|
return faceData->edges[option.localCornerIndex] + voxelDataFaceOffset;
|
||||||
|
}
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
} // namespace Deer
|
||||||
50
Deer/src/DeerRender/Voxel/VoxelData.h
Normal file
50
Deer/src/DeerRender/Voxel/VoxelData.h
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
#pragma once
|
||||||
|
#include "glm/glm.hpp"
|
||||||
|
|
||||||
|
#define EDGE_PER_AXIS 8
|
||||||
|
#define AXIS_NUMBER 3
|
||||||
|
#define CUBE_SIDES 8
|
||||||
|
|
||||||
|
namespace Deer {
|
||||||
|
namespace Voxel {
|
||||||
|
// Represents an edge of a voxel along a specific axis
|
||||||
|
struct VoxelEdge {
|
||||||
|
int voxelOffset[3];
|
||||||
|
int faceIndex;
|
||||||
|
int edgeIndex;
|
||||||
|
bool isClockwiseOrder;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct VoxelCorner {
|
||||||
|
int voxelOffset[3];
|
||||||
|
int faceIndex;
|
||||||
|
int localCornerIndex;
|
||||||
|
};
|
||||||
|
|
||||||
|
inline float lerp(float v, float a, float b) {
|
||||||
|
return b + (a - b) * v;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Direction vectors for checking neighboring voxels along each face
|
||||||
|
extern int faceNeighborOffset[6][3];
|
||||||
|
|
||||||
|
// Local "up" vector for each face of the voxel
|
||||||
|
extern glm::vec3 faceUpVector[6];
|
||||||
|
extern int faceUpVectorInt[6][3];
|
||||||
|
|
||||||
|
// Local "right" vector for each face of the voxel
|
||||||
|
extern glm::vec3 faceRightVector[6];
|
||||||
|
extern int faceRightVectorInt[6][3];
|
||||||
|
|
||||||
|
// Offset to the voxel face position relative to voxel center
|
||||||
|
extern glm::vec3 faceOriginVector[6];
|
||||||
|
extern int faceOriginVectorInt[6][3];
|
||||||
|
|
||||||
|
extern VoxelEdge edgesPerAxis[AXIS_NUMBER][EDGE_PER_AXIS];
|
||||||
|
extern int marchingCubesTriTable[256][16];
|
||||||
|
|
||||||
|
extern VoxelCorner marchingCubesEdgeCornerPairs[12][2];
|
||||||
|
|
||||||
|
extern int voxelCheckOrder[CUBE_SIDES][3];
|
||||||
|
} // namespace Voxel
|
||||||
|
} // namespace Deer
|
||||||
7
Deer/src/DeerRender/Voxel/VoxelEnvironment.cpp
Normal file
7
Deer/src/DeerRender/Voxel/VoxelEnvironment.cpp
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
#include "DeerRender/Voxel.h"
|
||||||
|
|
||||||
|
namespace Deer {
|
||||||
|
VoxelEnvironment::VoxelEnvironment() {
|
||||||
|
voxelBuilder = MakeScope<VoxelBuilder>(this);
|
||||||
|
}
|
||||||
|
} // namespace Deer
|
||||||
534
Deer/src/DeerRender/Voxel/VoxelGenerationData.cpp
Normal file
534
Deer/src/DeerRender/Voxel/VoxelGenerationData.cpp
Normal file
@ -0,0 +1,534 @@
|
|||||||
|
#include "DeerRender/Voxel/VoxelData.h"
|
||||||
|
|
||||||
|
namespace Deer {
|
||||||
|
namespace Voxel {
|
||||||
|
// Direction vectors for checking neighboring voxels along each face
|
||||||
|
int faceNeighborOffset[6][3] = {
|
||||||
|
{-1, 0, 0}, // Left
|
||||||
|
{1, 0, 0}, // Right
|
||||||
|
{0, -1, 0}, // Bottom
|
||||||
|
{0, 1, 0}, // Top
|
||||||
|
{0, 0, -1}, // Back
|
||||||
|
{0, 0, 1} // Front
|
||||||
|
};
|
||||||
|
|
||||||
|
// Local "up" vector for each face of the voxel
|
||||||
|
glm::vec3 faceUpVector[6] = {
|
||||||
|
glm::vec3(0, 1, 0), // Left
|
||||||
|
glm::vec3(0, 1, 0), // Right
|
||||||
|
glm::vec3(0, 0, -1), // Bottom
|
||||||
|
glm::vec3(0, 0, 1), // Top
|
||||||
|
glm::vec3(0, 1, 0), // Back
|
||||||
|
glm::vec3(0, 1, 0) // Front
|
||||||
|
};
|
||||||
|
int faceUpVectorInt[6][3] = {
|
||||||
|
{0, 1, 0},
|
||||||
|
{0, 1, 0}, // Right
|
||||||
|
{0, 0, -1}, // Bottom
|
||||||
|
{0, 0, 1}, // Top
|
||||||
|
{0, 1, 0}, // Back
|
||||||
|
{0, 1, 0} // Front
|
||||||
|
};
|
||||||
|
|
||||||
|
// Local "right" vector for each face of the voxel
|
||||||
|
glm::vec3 faceRightVector[6] = {
|
||||||
|
glm::vec3(0, 0, -1), // Left
|
||||||
|
glm::vec3(0, 0, 1), // Right
|
||||||
|
glm::vec3(1, 0, 0), // Bottom
|
||||||
|
glm::vec3(1, 0, 0), // Top
|
||||||
|
glm::vec3(1, 0, 0), // Back
|
||||||
|
glm::vec3(-1, 0, 0) // Front
|
||||||
|
};
|
||||||
|
int faceRightVectorInt[6][3] = {
|
||||||
|
{0, 0, -1}, // Left
|
||||||
|
{0, 0, 1}, // Right
|
||||||
|
{1, 0, 0}, // Bottom
|
||||||
|
{1, 0, 0}, // Top
|
||||||
|
{1, 0, 0}, // Back
|
||||||
|
{-1, 0, 0} // Front
|
||||||
|
};
|
||||||
|
|
||||||
|
// Offset to the voxel face position relative to voxel center
|
||||||
|
glm::vec3 faceOriginVector[6] = {
|
||||||
|
glm::vec3(-0.5f, -0.5f, 0.5f), // Left
|
||||||
|
glm::vec3(0.5f, -0.5f, -0.5f), // Right
|
||||||
|
glm::vec3(-0.5f, -0.5f, 0.5f), // Bottom
|
||||||
|
glm::vec3(-0.5f, 0.5f, -0.5f), // Top
|
||||||
|
glm::vec3(-0.5f, -0.5f, -0.5f), // Back
|
||||||
|
glm::vec3(0.5f, -0.5f, 0.5f) // Front
|
||||||
|
};
|
||||||
|
|
||||||
|
extern int faceOriginVectorInt[6][3] = {
|
||||||
|
{0, 0, 1}, // Left
|
||||||
|
{1, 0, 0}, // Right
|
||||||
|
{0, 0, 1}, // Bottom
|
||||||
|
{0, 1, 0}, // Top
|
||||||
|
{0, 0, 0}, // Back
|
||||||
|
{1, 0, 1} // Front
|
||||||
|
};
|
||||||
|
|
||||||
|
int voxelCheckOrder[CUBE_SIDES][3]{
|
||||||
|
{-1, -1, -1},
|
||||||
|
{0, -1, -1},
|
||||||
|
{-1, 0, -1},
|
||||||
|
{0, 0, -1},
|
||||||
|
{-1, -1, 0},
|
||||||
|
{0, -1, 0},
|
||||||
|
{-1, 0, 0},
|
||||||
|
{0, 0, 0}};
|
||||||
|
|
||||||
|
// For each MC case, a list of triangles, specified as triples of edge indices, terminated by -1
|
||||||
|
int marchingCubesTriTable[256][16] = {
|
||||||
|
{-1},
|
||||||
|
{0, 3, 8, -1},
|
||||||
|
{0, 9, 1, -1},
|
||||||
|
{3, 8, 1, 1, 8, 9, -1},
|
||||||
|
{2, 11, 3, -1},
|
||||||
|
{8, 0, 11, 11, 0, 2, -1},
|
||||||
|
{3, 2, 11, 1, 0, 9, -1},
|
||||||
|
{11, 1, 2, 11, 9, 1, 11, 8, 9, -1},
|
||||||
|
{1, 10, 2, -1},
|
||||||
|
{0, 3, 8, 2, 1, 10, -1},
|
||||||
|
{10, 2, 9, 9, 2, 0, -1},
|
||||||
|
{8, 2, 3, 8, 10, 2, 8, 9, 10, -1},
|
||||||
|
{11, 3, 10, 10, 3, 1, -1},
|
||||||
|
{10, 0, 1, 10, 8, 0, 10, 11, 8, -1},
|
||||||
|
{9, 3, 0, 9, 11, 3, 9, 10, 11, -1},
|
||||||
|
{8, 9, 11, 11, 9, 10, -1},
|
||||||
|
{4, 8, 7, -1},
|
||||||
|
{7, 4, 3, 3, 4, 0, -1},
|
||||||
|
{4, 8, 7, 0, 9, 1, -1},
|
||||||
|
{1, 4, 9, 1, 7, 4, 1, 3, 7, -1},
|
||||||
|
{8, 7, 4, 11, 3, 2, -1},
|
||||||
|
{4, 11, 7, 4, 2, 11, 4, 0, 2, -1},
|
||||||
|
{0, 9, 1, 8, 7, 4, 11, 3, 2, -1},
|
||||||
|
{7, 4, 11, 11, 4, 2, 2, 4, 9, 2, 9, 1, -1},
|
||||||
|
{4, 8, 7, 2, 1, 10, -1},
|
||||||
|
{7, 4, 3, 3, 4, 0, 10, 2, 1, -1},
|
||||||
|
{10, 2, 9, 9, 2, 0, 7, 4, 8, -1},
|
||||||
|
{10, 2, 3, 10, 3, 4, 3, 7, 4, 9, 10, 4, -1},
|
||||||
|
{1, 10, 3, 3, 10, 11, 4, 8, 7, -1},
|
||||||
|
{10, 11, 1, 11, 7, 4, 1, 11, 4, 1, 4, 0, -1},
|
||||||
|
{7, 4, 8, 9, 3, 0, 9, 11, 3, 9, 10, 11, -1},
|
||||||
|
{7, 4, 11, 4, 9, 11, 9, 10, 11, -1},
|
||||||
|
{9, 4, 5, -1},
|
||||||
|
{9, 4, 5, 8, 0, 3, -1},
|
||||||
|
{4, 5, 0, 0, 5, 1, -1},
|
||||||
|
{5, 8, 4, 5, 3, 8, 5, 1, 3, -1},
|
||||||
|
{9, 4, 5, 11, 3, 2, -1},
|
||||||
|
{2, 11, 0, 0, 11, 8, 5, 9, 4, -1},
|
||||||
|
{4, 5, 0, 0, 5, 1, 11, 3, 2, -1},
|
||||||
|
{5, 1, 4, 1, 2, 11, 4, 1, 11, 4, 11, 8, -1},
|
||||||
|
{1, 10, 2, 5, 9, 4, -1},
|
||||||
|
{9, 4, 5, 0, 3, 8, 2, 1, 10, -1},
|
||||||
|
{2, 5, 10, 2, 4, 5, 2, 0, 4, -1},
|
||||||
|
{10, 2, 5, 5, 2, 4, 4, 2, 3, 4, 3, 8, -1},
|
||||||
|
{11, 3, 10, 10, 3, 1, 4, 5, 9, -1},
|
||||||
|
{4, 5, 9, 10, 0, 1, 10, 8, 0, 10, 11, 8, -1},
|
||||||
|
{11, 3, 0, 11, 0, 5, 0, 4, 5, 10, 11, 5, -1},
|
||||||
|
{4, 5, 8, 5, 10, 8, 10, 11, 8, -1},
|
||||||
|
{8, 7, 9, 9, 7, 5, -1},
|
||||||
|
{3, 9, 0, 3, 5, 9, 3, 7, 5, -1},
|
||||||
|
{7, 0, 8, 7, 1, 0, 7, 5, 1, -1},
|
||||||
|
{7, 5, 3, 3, 5, 1, -1},
|
||||||
|
{5, 9, 7, 7, 9, 8, 2, 11, 3, -1},
|
||||||
|
{2, 11, 7, 2, 7, 9, 7, 5, 9, 0, 2, 9, -1},
|
||||||
|
{2, 11, 3, 7, 0, 8, 7, 1, 0, 7, 5, 1, -1},
|
||||||
|
{2, 11, 1, 11, 7, 1, 7, 5, 1, -1},
|
||||||
|
{8, 7, 9, 9, 7, 5, 2, 1, 10, -1},
|
||||||
|
{10, 2, 1, 3, 9, 0, 3, 5, 9, 3, 7, 5, -1},
|
||||||
|
{7, 5, 8, 5, 10, 2, 8, 5, 2, 8, 2, 0, -1},
|
||||||
|
{10, 2, 5, 2, 3, 5, 3, 7, 5, -1},
|
||||||
|
{8, 7, 5, 8, 5, 9, 11, 3, 10, 3, 1, 10, -1},
|
||||||
|
{5, 11, 7, 10, 11, 5, 1, 9, 0, -1},
|
||||||
|
{11, 5, 10, 7, 5, 11, 8, 3, 0, -1},
|
||||||
|
{5, 11, 7, 10, 11, 5, -1},
|
||||||
|
{6, 7, 11, -1},
|
||||||
|
{7, 11, 6, 3, 8, 0, -1},
|
||||||
|
{6, 7, 11, 0, 9, 1, -1},
|
||||||
|
{9, 1, 8, 8, 1, 3, 6, 7, 11, -1},
|
||||||
|
{3, 2, 7, 7, 2, 6, -1},
|
||||||
|
{0, 7, 8, 0, 6, 7, 0, 2, 6, -1},
|
||||||
|
{6, 7, 2, 2, 7, 3, 9, 1, 0, -1},
|
||||||
|
{6, 7, 8, 6, 8, 1, 8, 9, 1, 2, 6, 1, -1},
|
||||||
|
{11, 6, 7, 10, 2, 1, -1},
|
||||||
|
{3, 8, 0, 11, 6, 7, 10, 2, 1, -1},
|
||||||
|
{0, 9, 2, 2, 9, 10, 7, 11, 6, -1},
|
||||||
|
{6, 7, 11, 8, 2, 3, 8, 10, 2, 8, 9, 10, -1},
|
||||||
|
{7, 10, 6, 7, 1, 10, 7, 3, 1, -1},
|
||||||
|
{8, 0, 7, 7, 0, 6, 6, 0, 1, 6, 1, 10, -1},
|
||||||
|
{7, 3, 6, 3, 0, 9, 6, 3, 9, 6, 9, 10, -1},
|
||||||
|
{6, 7, 10, 7, 8, 10, 8, 9, 10, -1},
|
||||||
|
{11, 6, 8, 8, 6, 4, -1},
|
||||||
|
{6, 3, 11, 6, 0, 3, 6, 4, 0, -1},
|
||||||
|
{11, 6, 8, 8, 6, 4, 1, 0, 9, -1},
|
||||||
|
{1, 3, 9, 3, 11, 6, 9, 3, 6, 9, 6, 4, -1},
|
||||||
|
{2, 8, 3, 2, 4, 8, 2, 6, 4, -1},
|
||||||
|
{4, 0, 6, 6, 0, 2, -1},
|
||||||
|
{9, 1, 0, 2, 8, 3, 2, 4, 8, 2, 6, 4, -1},
|
||||||
|
{9, 1, 4, 1, 2, 4, 2, 6, 4, -1},
|
||||||
|
{4, 8, 6, 6, 8, 11, 1, 10, 2, -1},
|
||||||
|
{1, 10, 2, 6, 3, 11, 6, 0, 3, 6, 4, 0, -1},
|
||||||
|
{11, 6, 4, 11, 4, 8, 10, 2, 9, 2, 0, 9, -1},
|
||||||
|
{10, 4, 9, 6, 4, 10, 11, 2, 3, -1},
|
||||||
|
{4, 8, 3, 4, 3, 10, 3, 1, 10, 6, 4, 10, -1},
|
||||||
|
{1, 10, 0, 10, 6, 0, 6, 4, 0, -1},
|
||||||
|
{4, 10, 6, 9, 10, 4, 0, 8, 3, -1},
|
||||||
|
{4, 10, 6, 9, 10, 4, -1},
|
||||||
|
{6, 7, 11, 4, 5, 9, -1},
|
||||||
|
{4, 5, 9, 7, 11, 6, 3, 8, 0, -1},
|
||||||
|
{1, 0, 5, 5, 0, 4, 11, 6, 7, -1},
|
||||||
|
{11, 6, 7, 5, 8, 4, 5, 3, 8, 5, 1, 3, -1},
|
||||||
|
{3, 2, 7, 7, 2, 6, 9, 4, 5, -1},
|
||||||
|
{5, 9, 4, 0, 7, 8, 0, 6, 7, 0, 2, 6, -1},
|
||||||
|
{3, 2, 6, 3, 6, 7, 1, 0, 5, 0, 4, 5, -1},
|
||||||
|
{6, 1, 2, 5, 1, 6, 4, 7, 8, -1},
|
||||||
|
{10, 2, 1, 6, 7, 11, 4, 5, 9, -1},
|
||||||
|
{0, 3, 8, 4, 5, 9, 11, 6, 7, 10, 2, 1, -1},
|
||||||
|
{7, 11, 6, 2, 5, 10, 2, 4, 5, 2, 0, 4, -1},
|
||||||
|
{8, 4, 7, 5, 10, 6, 3, 11, 2, -1},
|
||||||
|
{9, 4, 5, 7, 10, 6, 7, 1, 10, 7, 3, 1, -1},
|
||||||
|
{10, 6, 5, 7, 8, 4, 1, 9, 0, -1},
|
||||||
|
{4, 3, 0, 7, 3, 4, 6, 5, 10, -1},
|
||||||
|
{10, 6, 5, 8, 4, 7, -1},
|
||||||
|
{9, 6, 5, 9, 11, 6, 9, 8, 11, -1},
|
||||||
|
{11, 6, 3, 3, 6, 0, 0, 6, 5, 0, 5, 9, -1},
|
||||||
|
{11, 6, 5, 11, 5, 0, 5, 1, 0, 8, 11, 0, -1},
|
||||||
|
{11, 6, 3, 6, 5, 3, 5, 1, 3, -1},
|
||||||
|
{9, 8, 5, 8, 3, 2, 5, 8, 2, 5, 2, 6, -1},
|
||||||
|
{5, 9, 6, 9, 0, 6, 0, 2, 6, -1},
|
||||||
|
{1, 6, 5, 2, 6, 1, 3, 0, 8, -1},
|
||||||
|
{1, 6, 5, 2, 6, 1, -1},
|
||||||
|
{2, 1, 10, 9, 6, 5, 9, 11, 6, 9, 8, 11, -1},
|
||||||
|
{9, 0, 1, 3, 11, 2, 5, 10, 6, -1},
|
||||||
|
{11, 0, 8, 2, 0, 11, 10, 6, 5, -1},
|
||||||
|
{3, 11, 2, 5, 10, 6, 2, 11, 6, 6, 10, 2, -1},
|
||||||
|
{1, 8, 3, 9, 8, 1, 5, 10, 6, -1},
|
||||||
|
{6, 5, 10, 0, 1, 9, -1},
|
||||||
|
{8, 3, 0, 5, 10, 6, -1},
|
||||||
|
{6, 5, 10, -1},
|
||||||
|
{10, 5, 6, -1},
|
||||||
|
{0, 3, 8, 6, 10, 5, -1},
|
||||||
|
{10, 5, 6, 9, 1, 0, -1},
|
||||||
|
{3, 8, 1, 1, 8, 9, 6, 10, 5, -1},
|
||||||
|
{2, 11, 3, 6, 10, 5, -1},
|
||||||
|
{8, 0, 11, 11, 0, 2, 5, 6, 10, -1},
|
||||||
|
{1, 0, 9, 2, 11, 3, 6, 10, 5, -1},
|
||||||
|
{5, 6, 10, 11, 1, 2, 11, 9, 1, 11, 8, 9, -1},
|
||||||
|
{5, 6, 1, 1, 6, 2, -1},
|
||||||
|
{5, 6, 1, 1, 6, 2, 8, 0, 3, -1},
|
||||||
|
{6, 9, 5, 6, 0, 9, 6, 2, 0, -1},
|
||||||
|
{6, 2, 5, 2, 3, 8, 5, 2, 8, 5, 8, 9, -1},
|
||||||
|
{3, 6, 11, 3, 5, 6, 3, 1, 5, -1},
|
||||||
|
{8, 0, 1, 8, 1, 6, 1, 5, 6, 11, 8, 6, -1},
|
||||||
|
{11, 3, 6, 6, 3, 5, 5, 3, 0, 5, 0, 9, -1},
|
||||||
|
{5, 6, 9, 6, 11, 9, 11, 8, 9, -1},
|
||||||
|
{5, 6, 10, 7, 4, 8, -1},
|
||||||
|
{0, 3, 4, 4, 3, 7, 10, 5, 6, -1},
|
||||||
|
{5, 6, 10, 4, 8, 7, 0, 9, 1, -1},
|
||||||
|
{6, 10, 5, 1, 4, 9, 1, 7, 4, 1, 3, 7, -1},
|
||||||
|
{7, 4, 8, 6, 10, 5, 2, 11, 3, -1},
|
||||||
|
{10, 5, 6, 4, 11, 7, 4, 2, 11, 4, 0, 2, -1},
|
||||||
|
{4, 8, 7, 6, 10, 5, 3, 2, 11, 1, 0, 9, -1},
|
||||||
|
{1, 2, 10, 11, 7, 6, 9, 5, 4, -1},
|
||||||
|
{2, 1, 6, 6, 1, 5, 8, 7, 4, -1},
|
||||||
|
{0, 3, 7, 0, 7, 4, 2, 1, 6, 1, 5, 6, -1},
|
||||||
|
{8, 7, 4, 6, 9, 5, 6, 0, 9, 6, 2, 0, -1},
|
||||||
|
{7, 2, 3, 6, 2, 7, 5, 4, 9, -1},
|
||||||
|
{4, 8, 7, 3, 6, 11, 3, 5, 6, 3, 1, 5, -1},
|
||||||
|
{5, 0, 1, 4, 0, 5, 7, 6, 11, -1},
|
||||||
|
{9, 5, 4, 6, 11, 7, 0, 8, 3, -1},
|
||||||
|
{11, 7, 6, 9, 5, 4, -1},
|
||||||
|
{6, 10, 4, 4, 10, 9, -1},
|
||||||
|
{6, 10, 4, 4, 10, 9, 3, 8, 0, -1},
|
||||||
|
{0, 10, 1, 0, 6, 10, 0, 4, 6, -1},
|
||||||
|
{6, 10, 1, 6, 1, 8, 1, 3, 8, 4, 6, 8, -1},
|
||||||
|
{9, 4, 10, 10, 4, 6, 3, 2, 11, -1},
|
||||||
|
{2, 11, 8, 2, 8, 0, 6, 10, 4, 10, 9, 4, -1},
|
||||||
|
{11, 3, 2, 0, 10, 1, 0, 6, 10, 0, 4, 6, -1},
|
||||||
|
{6, 8, 4, 11, 8, 6, 2, 10, 1, -1},
|
||||||
|
{4, 1, 9, 4, 2, 1, 4, 6, 2, -1},
|
||||||
|
{3, 8, 0, 4, 1, 9, 4, 2, 1, 4, 6, 2, -1},
|
||||||
|
{6, 2, 4, 4, 2, 0, -1},
|
||||||
|
{3, 8, 2, 8, 4, 2, 4, 6, 2, -1},
|
||||||
|
{4, 6, 9, 6, 11, 3, 9, 6, 3, 9, 3, 1, -1},
|
||||||
|
{8, 6, 11, 4, 6, 8, 9, 0, 1, -1},
|
||||||
|
{11, 3, 6, 3, 0, 6, 0, 4, 6, -1},
|
||||||
|
{8, 6, 11, 4, 6, 8, -1},
|
||||||
|
{10, 7, 6, 10, 8, 7, 10, 9, 8, -1},
|
||||||
|
{3, 7, 0, 7, 6, 10, 0, 7, 10, 0, 10, 9, -1},
|
||||||
|
{6, 10, 7, 7, 10, 8, 8, 10, 1, 8, 1, 0, -1},
|
||||||
|
{6, 10, 7, 10, 1, 7, 1, 3, 7, -1},
|
||||||
|
{3, 2, 11, 10, 7, 6, 10, 8, 7, 10, 9, 8, -1},
|
||||||
|
{2, 9, 0, 10, 9, 2, 6, 11, 7, -1},
|
||||||
|
{0, 8, 3, 7, 6, 11, 1, 2, 10, -1},
|
||||||
|
{7, 6, 11, 1, 2, 10, 11, 6, 2, 2, 6, 10, -1},
|
||||||
|
{2, 1, 9, 2, 9, 7, 9, 8, 7, 6, 2, 7, -1},
|
||||||
|
{2, 7, 6, 3, 7, 2, 0, 1, 9, -1},
|
||||||
|
{8, 7, 0, 7, 6, 0, 6, 2, 0, -1},
|
||||||
|
{7, 2, 3, 6, 2, 7, -1},
|
||||||
|
{8, 1, 9, 3, 1, 8, 11, 7, 6, -1},
|
||||||
|
{11, 7, 6, 1, 9, 0, -1},
|
||||||
|
{6, 11, 7, 0, 8, 3, -1},
|
||||||
|
{11, 7, 6, -1},
|
||||||
|
{7, 11, 5, 5, 11, 10, -1},
|
||||||
|
{10, 5, 11, 11, 5, 7, 0, 3, 8, -1},
|
||||||
|
{7, 11, 5, 5, 11, 10, 0, 9, 1, -1},
|
||||||
|
{7, 11, 10, 7, 10, 5, 3, 8, 1, 8, 9, 1, -1},
|
||||||
|
{5, 2, 10, 5, 3, 2, 5, 7, 3, -1},
|
||||||
|
{5, 7, 10, 7, 8, 0, 10, 7, 0, 10, 0, 2, -1},
|
||||||
|
{0, 9, 1, 5, 2, 10, 5, 3, 2, 5, 7, 3, -1},
|
||||||
|
{9, 7, 8, 5, 7, 9, 10, 1, 2, -1},
|
||||||
|
{1, 11, 2, 1, 7, 11, 1, 5, 7, -1},
|
||||||
|
{8, 0, 3, 1, 11, 2, 1, 7, 11, 1, 5, 7, -1},
|
||||||
|
{7, 11, 2, 7, 2, 9, 2, 0, 9, 5, 7, 9, -1},
|
||||||
|
{7, 9, 5, 8, 9, 7, 3, 11, 2, -1},
|
||||||
|
{3, 1, 7, 7, 1, 5, -1},
|
||||||
|
{8, 0, 7, 0, 1, 7, 1, 5, 7, -1},
|
||||||
|
{0, 9, 3, 9, 5, 3, 5, 7, 3, -1},
|
||||||
|
{9, 7, 8, 5, 7, 9, -1},
|
||||||
|
{8, 5, 4, 8, 10, 5, 8, 11, 10, -1},
|
||||||
|
{0, 3, 11, 0, 11, 5, 11, 10, 5, 4, 0, 5, -1},
|
||||||
|
{1, 0, 9, 8, 5, 4, 8, 10, 5, 8, 11, 10, -1},
|
||||||
|
{10, 3, 11, 1, 3, 10, 9, 5, 4, -1},
|
||||||
|
{3, 2, 8, 8, 2, 4, 4, 2, 10, 4, 10, 5, -1},
|
||||||
|
{10, 5, 2, 5, 4, 2, 4, 0, 2, -1},
|
||||||
|
{5, 4, 9, 8, 3, 0, 10, 1, 2, -1},
|
||||||
|
{2, 10, 1, 4, 9, 5, -1},
|
||||||
|
{8, 11, 4, 11, 2, 1, 4, 11, 1, 4, 1, 5, -1},
|
||||||
|
{0, 5, 4, 1, 5, 0, 2, 3, 11, -1},
|
||||||
|
{0, 11, 2, 8, 11, 0, 4, 9, 5, -1},
|
||||||
|
{5, 4, 9, 2, 3, 11, -1},
|
||||||
|
{4, 8, 5, 8, 3, 5, 3, 1, 5, -1},
|
||||||
|
{0, 5, 4, 1, 5, 0, -1},
|
||||||
|
{5, 4, 9, 3, 0, 8, -1},
|
||||||
|
{5, 4, 9, -1},
|
||||||
|
{11, 4, 7, 11, 9, 4, 11, 10, 9, -1},
|
||||||
|
{0, 3, 8, 11, 4, 7, 11, 9, 4, 11, 10, 9, -1},
|
||||||
|
{11, 10, 7, 10, 1, 0, 7, 10, 0, 7, 0, 4, -1},
|
||||||
|
{3, 10, 1, 11, 10, 3, 7, 8, 4, -1},
|
||||||
|
{3, 2, 10, 3, 10, 4, 10, 9, 4, 7, 3, 4, -1},
|
||||||
|
{9, 2, 10, 0, 2, 9, 8, 4, 7, -1},
|
||||||
|
{3, 4, 7, 0, 4, 3, 1, 2, 10, -1},
|
||||||
|
{7, 8, 4, 10, 1, 2, -1},
|
||||||
|
{7, 11, 4, 4, 11, 9, 9, 11, 2, 9, 2, 1, -1},
|
||||||
|
{1, 9, 0, 4, 7, 8, 2, 3, 11, -1},
|
||||||
|
{7, 11, 4, 11, 2, 4, 2, 0, 4, -1},
|
||||||
|
{4, 7, 8, 2, 3, 11, -1},
|
||||||
|
{9, 4, 1, 4, 7, 1, 7, 3, 1, -1},
|
||||||
|
{7, 8, 4, 1, 9, 0, -1},
|
||||||
|
{3, 4, 7, 0, 4, 3, -1},
|
||||||
|
{7, 8, 4, -1},
|
||||||
|
{11, 10, 8, 8, 10, 9, -1},
|
||||||
|
{0, 3, 9, 3, 11, 9, 11, 10, 9, -1},
|
||||||
|
{1, 0, 10, 0, 8, 10, 8, 11, 10, -1},
|
||||||
|
{10, 3, 11, 1, 3, 10, -1},
|
||||||
|
{3, 2, 8, 2, 10, 8, 10, 9, 8, -1},
|
||||||
|
{9, 2, 10, 0, 2, 9, -1},
|
||||||
|
{8, 3, 0, 10, 1, 2, -1},
|
||||||
|
{2, 10, 1, -1},
|
||||||
|
{2, 1, 11, 1, 9, 11, 9, 8, 11, -1},
|
||||||
|
{11, 2, 3, 9, 0, 1, -1},
|
||||||
|
{11, 0, 8, 2, 0, 11, -1},
|
||||||
|
{3, 11, 2, -1},
|
||||||
|
{1, 8, 3, 9, 8, 1, -1},
|
||||||
|
{1, 9, 0, -1},
|
||||||
|
{8, 3, 0, -1},
|
||||||
|
{-1},
|
||||||
|
};
|
||||||
|
|
||||||
|
extern VoxelCorner marchingCubesEdgeCornerPairs[12][2] = {
|
||||||
|
{// 0
|
||||||
|
{.voxelOffset = {-1, -1, -1},
|
||||||
|
.faceIndex = 1,
|
||||||
|
.localCornerIndex = 3},
|
||||||
|
{.voxelOffset = {0, -1, -1},
|
||||||
|
.faceIndex = 0,
|
||||||
|
.localCornerIndex = 2}},
|
||||||
|
{// 1
|
||||||
|
{.voxelOffset = {0, -1, -1},
|
||||||
|
.faceIndex = 3,
|
||||||
|
.localCornerIndex = 2},
|
||||||
|
{.voxelOffset = {0, 0, -1},
|
||||||
|
.faceIndex = 2,
|
||||||
|
.localCornerIndex = 0}},
|
||||||
|
{// 2
|
||||||
|
{.voxelOffset = {0, 0, -1},
|
||||||
|
.faceIndex = 0,
|
||||||
|
.localCornerIndex = 0},
|
||||||
|
{.voxelOffset = {-1, 0, -1},
|
||||||
|
.faceIndex = 1,
|
||||||
|
.localCornerIndex = 1}},
|
||||||
|
{// 3
|
||||||
|
{.voxelOffset = {-1, 0, -1},
|
||||||
|
.faceIndex = 2,
|
||||||
|
.localCornerIndex = 1},
|
||||||
|
{.voxelOffset = {-1, -1, -1},
|
||||||
|
.faceIndex = 3,
|
||||||
|
.localCornerIndex = 3}},
|
||||||
|
{// 4
|
||||||
|
{.voxelOffset = {-1, -1, 0},
|
||||||
|
.faceIndex = 1,
|
||||||
|
.localCornerIndex = 2},
|
||||||
|
{.voxelOffset = {0, -1, 0},
|
||||||
|
.faceIndex = 0,
|
||||||
|
.localCornerIndex = 3}},
|
||||||
|
{// 5
|
||||||
|
{.voxelOffset = {0, -1, 0},
|
||||||
|
.faceIndex = 3,
|
||||||
|
.localCornerIndex = 0},
|
||||||
|
{.voxelOffset = {0, 0, 0},
|
||||||
|
.faceIndex = 2,
|
||||||
|
.localCornerIndex = 2}},
|
||||||
|
{// 6
|
||||||
|
{.voxelOffset = {0, 0, 0},
|
||||||
|
.faceIndex = 0,
|
||||||
|
.localCornerIndex = 1},
|
||||||
|
{.voxelOffset = {-1, 0, 0},
|
||||||
|
.faceIndex = 1,
|
||||||
|
.localCornerIndex = 0}},
|
||||||
|
{// 7
|
||||||
|
{.voxelOffset = {-1, 0, 0},
|
||||||
|
.faceIndex = 2,
|
||||||
|
.localCornerIndex = 3},
|
||||||
|
{.voxelOffset = {-1, -1, 0},
|
||||||
|
.faceIndex = 3,
|
||||||
|
.localCornerIndex = 1}},
|
||||||
|
{// 8
|
||||||
|
{.voxelOffset = {-1, -1, -1},
|
||||||
|
.faceIndex = 5,
|
||||||
|
.localCornerIndex = 2},
|
||||||
|
{.voxelOffset = {-1, -1, 0},
|
||||||
|
.faceIndex = 4,
|
||||||
|
.localCornerIndex = 3}},
|
||||||
|
{// 9
|
||||||
|
{.voxelOffset = {0, -1, -1},
|
||||||
|
.faceIndex = 5,
|
||||||
|
.localCornerIndex = 3},
|
||||||
|
{.voxelOffset = {0, -1, 0},
|
||||||
|
.faceIndex = 4,
|
||||||
|
.localCornerIndex = 2}},
|
||||||
|
{// 10
|
||||||
|
{.voxelOffset = {0, 0, -1},
|
||||||
|
.faceIndex = 5,
|
||||||
|
.localCornerIndex = 1},
|
||||||
|
{.voxelOffset = {0, 0, 0},
|
||||||
|
.faceIndex = 4,
|
||||||
|
.localCornerIndex = 0}},
|
||||||
|
{// 11
|
||||||
|
{.voxelOffset = {-1, 0, -1},
|
||||||
|
.faceIndex = 5,
|
||||||
|
.localCornerIndex = 0},
|
||||||
|
{.voxelOffset = {-1, 0, 0},
|
||||||
|
.faceIndex = 4,
|
||||||
|
.localCornerIndex = 1}}};
|
||||||
|
|
||||||
|
// Represents the 8 edges along each of the 3 axes for a voxel, axis : (X, Y, Z)
|
||||||
|
VoxelEdge edgesPerAxis[AXIS_NUMBER][EDGE_PER_AXIS] = {
|
||||||
|
{
|
||||||
|
{.voxelOffset = {0, 0, 0},
|
||||||
|
.isClockwiseOrder = true,
|
||||||
|
.faceIndex = 4,
|
||||||
|
.edgeIndex = 2},
|
||||||
|
{.voxelOffset = {0, 0, 0},
|
||||||
|
.isClockwiseOrder = false,
|
||||||
|
.faceIndex = 2,
|
||||||
|
.edgeIndex = 3},
|
||||||
|
|
||||||
|
{.voxelOffset = {0, -1, 0},
|
||||||
|
.isClockwiseOrder = true,
|
||||||
|
.faceIndex = 3,
|
||||||
|
.edgeIndex = 2},
|
||||||
|
{.voxelOffset = {0, -1, 0},
|
||||||
|
.isClockwiseOrder = false,
|
||||||
|
.faceIndex = 4,
|
||||||
|
.edgeIndex = 3},
|
||||||
|
|
||||||
|
{.voxelOffset = {0, -1, -1},
|
||||||
|
.isClockwiseOrder = true,
|
||||||
|
.faceIndex = 5,
|
||||||
|
.edgeIndex = 3},
|
||||||
|
{.voxelOffset = {0, -1, -1},
|
||||||
|
.isClockwiseOrder = false,
|
||||||
|
.faceIndex = 3,
|
||||||
|
.edgeIndex = 3},
|
||||||
|
|
||||||
|
{.voxelOffset = {0, 0, -1},
|
||||||
|
.isClockwiseOrder = true,
|
||||||
|
.faceIndex = 2,
|
||||||
|
.edgeIndex = 2},
|
||||||
|
{.voxelOffset = {0, 0, -1},
|
||||||
|
.isClockwiseOrder = false,
|
||||||
|
.faceIndex = 5,
|
||||||
|
.edgeIndex = 2},
|
||||||
|
}, // X axis
|
||||||
|
{
|
||||||
|
{.voxelOffset = {0, 0, 0},
|
||||||
|
.isClockwiseOrder = true,
|
||||||
|
.faceIndex = 0,
|
||||||
|
.edgeIndex = 1},
|
||||||
|
{.voxelOffset = {0, 0, 0},
|
||||||
|
.isClockwiseOrder = false,
|
||||||
|
.faceIndex = 4,
|
||||||
|
.edgeIndex = 0},
|
||||||
|
{.voxelOffset = {0, 0, -1},
|
||||||
|
.isClockwiseOrder = true,
|
||||||
|
.faceIndex = 5,
|
||||||
|
.edgeIndex = 1},
|
||||||
|
{.voxelOffset = {0, 0, -1},
|
||||||
|
.isClockwiseOrder = false,
|
||||||
|
.faceIndex = 0,
|
||||||
|
.edgeIndex = 0},
|
||||||
|
{.voxelOffset = {-1, 0, -1},
|
||||||
|
.isClockwiseOrder = true,
|
||||||
|
.faceIndex = 1,
|
||||||
|
.edgeIndex = 1},
|
||||||
|
{.voxelOffset = {-1, 0, -1},
|
||||||
|
.isClockwiseOrder = false,
|
||||||
|
.faceIndex = 5,
|
||||||
|
.edgeIndex = 0},
|
||||||
|
{.voxelOffset = {-1, 0, 0},
|
||||||
|
.isClockwiseOrder = true,
|
||||||
|
.faceIndex = 4,
|
||||||
|
.edgeIndex = 1},
|
||||||
|
{.voxelOffset = {-1, 0, 0},
|
||||||
|
.isClockwiseOrder = false,
|
||||||
|
.faceIndex = 1,
|
||||||
|
.edgeIndex = 0}}, // Y axis
|
||||||
|
{
|
||||||
|
{.voxelOffset = {0, 0, 0},
|
||||||
|
.isClockwiseOrder = true,
|
||||||
|
.faceIndex = 0,
|
||||||
|
.edgeIndex = 2},
|
||||||
|
{.voxelOffset = {0, 0, 0},
|
||||||
|
.isClockwiseOrder = false,
|
||||||
|
.faceIndex = 2,
|
||||||
|
.edgeIndex = 0},
|
||||||
|
{.voxelOffset = {0, -1, 0},
|
||||||
|
.isClockwiseOrder = true,
|
||||||
|
.faceIndex = 3,
|
||||||
|
.edgeIndex = 0},
|
||||||
|
{.voxelOffset = {0, -1, 0},
|
||||||
|
.isClockwiseOrder = false,
|
||||||
|
.faceIndex = 0,
|
||||||
|
.edgeIndex = 3},
|
||||||
|
{.voxelOffset = {-1, -1, 0},
|
||||||
|
.isClockwiseOrder = true,
|
||||||
|
.faceIndex = 1,
|
||||||
|
.edgeIndex = 3},
|
||||||
|
{.voxelOffset = {-1, -1, 0},
|
||||||
|
.isClockwiseOrder = false,
|
||||||
|
.faceIndex = 3,
|
||||||
|
.edgeIndex = 1},
|
||||||
|
{.voxelOffset = {-1, 0, 0},
|
||||||
|
.isClockwiseOrder = true,
|
||||||
|
.faceIndex = 2,
|
||||||
|
.edgeIndex = 1},
|
||||||
|
{.voxelOffset = {-1, 0, 0},
|
||||||
|
.isClockwiseOrder = false,
|
||||||
|
.faceIndex = 1,
|
||||||
|
.edgeIndex = 2},
|
||||||
|
} // Z axis
|
||||||
|
};
|
||||||
|
} // namespace Voxel
|
||||||
|
} // namespace Deer
|
||||||
@ -40,7 +40,7 @@ namespace Deer {
|
|||||||
if (targetRenderTime > 0 && accumulatedRenderTime >= targetRenderTime) {
|
if (targetRenderTime > 0 && accumulatedRenderTime >= targetRenderTime) {
|
||||||
renderDeltaTime = accumulatedRenderTime;
|
renderDeltaTime = accumulatedRenderTime;
|
||||||
worldSettings.renderCallback(*this);
|
worldSettings.renderCallback(*this);
|
||||||
accumulatedRenderTime = 0;
|
accumulatedRenderTime -= targetRenderTime;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::this_thread::sleep_for(std::chrono::microseconds(1));
|
std::this_thread::sleep_for(std::chrono::microseconds(1));
|
||||||
|
|||||||
@ -8,6 +8,8 @@
|
|||||||
#include "DeerRender/World.h"
|
#include "DeerRender/World.h"
|
||||||
|
|
||||||
// TMP
|
// TMP
|
||||||
|
#include "DeerCore/EntityEnviroment.h"
|
||||||
|
#include "DeerRender/Voxel.h"
|
||||||
#include "DeerStudio/Fonts.h"
|
#include "DeerStudio/Fonts.h"
|
||||||
#include "DeerStudio/Style.h"
|
#include "DeerStudio/Style.h"
|
||||||
// TMP
|
// TMP
|
||||||
@ -17,6 +19,7 @@ namespace Deer {
|
|||||||
|
|
||||||
namespace DeerStudio {
|
namespace DeerStudio {
|
||||||
World* world;
|
World* world;
|
||||||
|
VoxelEnvironment env;
|
||||||
|
|
||||||
void onUpdate();
|
void onUpdate();
|
||||||
void onRender();
|
void onRender();
|
||||||
@ -46,6 +49,53 @@ namespace Deer {
|
|||||||
|
|
||||||
while (world) {
|
while (world) {
|
||||||
StudioPanel::setWorld(world);
|
StudioPanel::setWorld(world);
|
||||||
|
|
||||||
|
Entity& entity = world->entityEnvironment->createEntity();
|
||||||
|
MeshComponent& mesh = entity.addComponent<MeshComponent>();
|
||||||
|
ShaderComponent& shader = entity.addComponent<ShaderComponent>();
|
||||||
|
|
||||||
|
/*
|
||||||
|
env.modifyVoxel(1, 0, 1, 0);
|
||||||
|
env.modifyVoxel(1, 1, 2, 0);
|
||||||
|
|
||||||
|
env.modifyVoxel(1, 5, 1, 1);
|
||||||
|
env.modifyVoxel(1, 5, 2, 2);
|
||||||
|
env.modifyVoxel(1, 5, 1, 3);
|
||||||
|
|
||||||
|
env.modifyVoxel(1, 15, 1, 15);
|
||||||
|
env.modifyVoxel(1, 14, 1, 16);
|
||||||
|
|
||||||
|
env.modifyVoxel(1, 5, 1, 8);
|
||||||
|
env.modifyVoxel(1, 5, 1, 9);
|
||||||
|
env.modifyVoxel(1, 5, 2, 9);
|
||||||
|
env.modifyVoxel(1, 6, 1, 9);
|
||||||
|
|
||||||
|
env.modifyVoxel(1, 0, 1, 5);
|
||||||
|
env.modifyVoxel(1, 1, 2, 6);
|
||||||
|
|
||||||
|
env.modifyVoxel(1, 4, 1, 5);
|
||||||
|
|
||||||
|
env.modifyVoxel(1, 9, 1, 9);
|
||||||
|
env.modifyVoxel(1, 10, 1, 10);
|
||||||
|
*/
|
||||||
|
for (int x = 0; x < 20; x++)
|
||||||
|
for (int y = 0; y < 20; y++)
|
||||||
|
env.modifyVoxel(1, x, 0, y);
|
||||||
|
|
||||||
|
env.modifyVoxel(1, 5, 1, 5);
|
||||||
|
env.modifyVoxel(1, 5, 2, 5);
|
||||||
|
env.modifyVoxel(1, 4, 2, 5);
|
||||||
|
env.modifyVoxel(1, 4, 2, 4);
|
||||||
|
|
||||||
|
env.modifyVoxel(1, 7, 1, 5);
|
||||||
|
env.modifyVoxel(1, 6, 1, 5);
|
||||||
|
env.modifyVoxel(1, 6, 1, 4);
|
||||||
|
|
||||||
|
DEER_CORE_INFO("{}", env.getVoxel(0, 0, 0));
|
||||||
|
|
||||||
|
shader.shader = Builtin::simpleShader();
|
||||||
|
mesh.mesh = env.voxelBuilder->buildChunk(0, 0, 0);
|
||||||
|
|
||||||
world->execute();
|
world->execute();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,11 +0,0 @@
|
|||||||
#include "DeerStudio/DeerStudio.h"
|
|
||||||
|
|
||||||
#include "imgui.h"
|
|
||||||
|
|
||||||
namespace Deer {
|
|
||||||
namespace DeerStudio {
|
|
||||||
void onPanelMenuBar() {
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace DeerStudio
|
|
||||||
} // namespace Deer
|
|
||||||
@ -5,10 +5,22 @@ class ViewportPanel : Panel {
|
|||||||
float pitch = 0;
|
float pitch = 0;
|
||||||
float yaw = 0;
|
float yaw = 0;
|
||||||
|
|
||||||
|
int frameCounter = 0;
|
||||||
|
float deltaAcomulated = 0;
|
||||||
|
float latestFrameRate;
|
||||||
|
|
||||||
void onImGui() {
|
void onImGui() {
|
||||||
if (!frameBuffer.isValid())
|
if (!frameBuffer.isValid())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
frameCounter++;
|
||||||
|
deltaAcomulated += World::getRenderDeltaTime();
|
||||||
|
if (frameCounter == 50) {
|
||||||
|
latestFrameRate = 50 / deltaAcomulated;
|
||||||
|
frameCounter = 0;
|
||||||
|
deltaAcomulated = 0;
|
||||||
|
}
|
||||||
|
|
||||||
float vel = World::getRenderDeltaTime() * 3;
|
float vel = World::getRenderDeltaTime() * 3;
|
||||||
|
|
||||||
if (ImGui::isKeyDown(key::LeftShift))
|
if (ImGui::isKeyDown(key::LeftShift))
|
||||||
@ -104,7 +116,7 @@ class ViewportPanel : Panel {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ImGui::simplePopup("ViewportCameraProps", SimpleFunction(this.viewportCameraProps));
|
ImGui::simplePopup("ViewportCameraProps", SimpleFunction(this.viewportCameraProps));
|
||||||
ImGui::textColor(0, 0.5f, 0,"" + ceil(1 / World::getRenderDeltaTime()));
|
ImGui::textColor(0, 0.5f, 0,"" + latestFrameRate);
|
||||||
}
|
}
|
||||||
|
|
||||||
void viewportCameraProps() {
|
void viewportCameraProps() {
|
||||||
|
|||||||
12
Editor/Scripts/VoxelEditor/VoxelEditor.as
Normal file
12
Editor/Scripts/VoxelEditor/VoxelEditor.as
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
class VoxelEditor : Panel {
|
||||||
|
FrameBuffer editorBuffer;
|
||||||
|
|
||||||
|
void onInit() {
|
||||||
|
editorBuffer = Resource::createFrameBuffer("VoxelEditor", 620, 620);
|
||||||
|
}
|
||||||
|
|
||||||
|
void onImGui() {
|
||||||
|
editorBuffer.clearRGBA(60, 120, 100, 255);
|
||||||
|
ImGui::drawFrameBufferCentered(editorBuffer, 620, 620);
|
||||||
|
}
|
||||||
|
}
|
||||||
83
Resources/normal.glsl
Normal file
83
Resources/normal.glsl
Normal file
@ -0,0 +1,83 @@
|
|||||||
|
#type vertex
|
||||||
|
#version 410 core
|
||||||
|
|
||||||
|
// Vertex attributes
|
||||||
|
layout(location = 0) in vec3 v_position;
|
||||||
|
layout(location = 1) in vec3 v_normal;
|
||||||
|
layout(location = 2) in vec2 v_UV;
|
||||||
|
|
||||||
|
// Outputs to fragment shader
|
||||||
|
out vec3 normalWS;
|
||||||
|
out vec3 normalVS;
|
||||||
|
out vec3 positionVS;
|
||||||
|
|
||||||
|
// Uniforms
|
||||||
|
uniform mat4 u_worldMatrix;
|
||||||
|
uniform mat4 u_viewMatrix;
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
gl_Position = u_viewMatrix * u_worldMatrix * vec4(v_position, 1.0);
|
||||||
|
positionVS = gl_Position.xyz;
|
||||||
|
|
||||||
|
mat3 normalMatrix = transpose(inverse(mat3(u_worldMatrix)));
|
||||||
|
normalWS = normalize(normalMatrix * v_normal);
|
||||||
|
|
||||||
|
mat3 normalMatrixView = transpose(inverse(mat3(u_viewMatrix * u_worldMatrix)));
|
||||||
|
normalVS = normalize(normalMatrixView * v_normal);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#type fragment
|
||||||
|
#version 410 core
|
||||||
|
|
||||||
|
// Fragment outputs
|
||||||
|
layout(location = 0) out vec4 fragColor;
|
||||||
|
layout(location = 1) out int objectID;
|
||||||
|
|
||||||
|
// Inputs from vertex shader
|
||||||
|
in vec3 normalWS;
|
||||||
|
in vec3 normalVS;
|
||||||
|
in vec3 positionVS;
|
||||||
|
|
||||||
|
// Uniforms
|
||||||
|
uniform int u_objectID;
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
// Directional light
|
||||||
|
vec3 lightDir = normalize(vec3(1.0, 7.0, 3.0));
|
||||||
|
|
||||||
|
// Base light intensity
|
||||||
|
float light = clamp(dot(normalize(normalWS), lightDir) * 0.8 + 0.2, 0.0, 1.0);
|
||||||
|
|
||||||
|
// Gradient from purple (dark) to cyan (lit)
|
||||||
|
vec3 gradientColor = mix(
|
||||||
|
vec3(0.9412, 0.4471, 0.7137),
|
||||||
|
vec3(1.0, 0.9725, 0.5255),
|
||||||
|
light
|
||||||
|
);
|
||||||
|
|
||||||
|
// Rim/fresnel effect
|
||||||
|
float rim = 0.5 - dot(normalize(normalWS), normalize(lightDir)) * 0.5;
|
||||||
|
float rimValue = rim * rim * rim * rim;
|
||||||
|
vec3 rimColor = vec3(1.0, 0.8, 0.5) * (rim * rim * rim * rim);
|
||||||
|
|
||||||
|
vec3 mixedColor = mix(
|
||||||
|
gradientColor,
|
||||||
|
vec3(1, 1, 1) ,
|
||||||
|
rimValue
|
||||||
|
);
|
||||||
|
|
||||||
|
//float fresnel = dot(, vec3(0, 0, -1));
|
||||||
|
//fresnel = fresnel * fresnel;
|
||||||
|
|
||||||
|
float fresnel = 1 + dot(normalize(positionVS), normalize(normalVS));
|
||||||
|
fresnel = fresnel * fresnel * fresnel * fresnel;
|
||||||
|
|
||||||
|
// Combine everything
|
||||||
|
fragColor = vec4(normalize(normalWS) * 0.5 + vec3(0.5, 0.5, 0.5), 1.0);
|
||||||
|
|
||||||
|
// Object ID output
|
||||||
|
objectID = u_objectID;
|
||||||
|
}
|
||||||
87
Resources/shad.glsl
Normal file
87
Resources/shad.glsl
Normal file
@ -0,0 +1,87 @@
|
|||||||
|
#type vertex
|
||||||
|
#version 410 core
|
||||||
|
|
||||||
|
// Vertex attributes
|
||||||
|
layout(location = 0) in vec3 v_position;
|
||||||
|
layout(location = 1) in vec3 v_normal;
|
||||||
|
layout(location = 2) in float v_light;
|
||||||
|
|
||||||
|
// Outputs to fragment shader
|
||||||
|
out vec3 normalWS;
|
||||||
|
out vec3 normalVS;
|
||||||
|
out vec3 positionVS;
|
||||||
|
out float shadow;
|
||||||
|
|
||||||
|
// Uniforms
|
||||||
|
uniform mat4 u_worldMatrix;
|
||||||
|
uniform mat4 u_viewMatrix;
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
gl_Position = u_viewMatrix * u_worldMatrix * vec4(v_position, 1.0);
|
||||||
|
positionVS = gl_Position.xyz;
|
||||||
|
|
||||||
|
mat3 normalMatrix = transpose(inverse(mat3(u_worldMatrix)));
|
||||||
|
normalWS = normalize(normalMatrix * v_normal);
|
||||||
|
|
||||||
|
mat3 normalMatrixView = transpose(inverse(mat3(u_viewMatrix * u_worldMatrix)));
|
||||||
|
normalVS = normalize(normalMatrixView * v_normal);
|
||||||
|
|
||||||
|
shadow = v_light;
|
||||||
|
}
|
||||||
|
|
||||||
|
#type fragment
|
||||||
|
#version 410 core
|
||||||
|
|
||||||
|
// Fragment outputs
|
||||||
|
layout(location = 0) out vec4 fragColor;
|
||||||
|
layout(location = 1) out int objectID;
|
||||||
|
|
||||||
|
// Inputs from vertex shader
|
||||||
|
in vec3 normalWS;
|
||||||
|
in vec3 normalVS;
|
||||||
|
in vec3 positionVS;
|
||||||
|
in float shadow;
|
||||||
|
|
||||||
|
// Uniforms
|
||||||
|
uniform int u_objectID;
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
// Directional light
|
||||||
|
vec3 lightDir = normalize(vec3(1.0, 7.0, 3.0));
|
||||||
|
|
||||||
|
// Base light intensity
|
||||||
|
float light = clamp(dot(normalize(normalWS), lightDir) * 0.8 + 0.2, 0.0, 1.0);
|
||||||
|
|
||||||
|
// Gradient from purple (dark) to cyan (lit)
|
||||||
|
vec3 gradientColor = mix(
|
||||||
|
vec3(0.9412, 0.4471, 0.7137),
|
||||||
|
vec3(1.0, 0.9725, 0.5255),
|
||||||
|
light
|
||||||
|
);
|
||||||
|
|
||||||
|
// Rim/fresnel effect
|
||||||
|
float rim = 0.5 - dot(normalize(normalWS), normalize(lightDir)) * 0.5;
|
||||||
|
float rimValue = rim * rim * rim * rim;
|
||||||
|
vec3 rimColor = vec3(1.0, 0.8, 0.5) * (rim * rim * rim * rim);
|
||||||
|
|
||||||
|
vec3 mixedColor = mix(
|
||||||
|
gradientColor,
|
||||||
|
vec3(1, 1, 1) ,
|
||||||
|
rimValue
|
||||||
|
);
|
||||||
|
|
||||||
|
//float fresnel = dot(, vec3(0, 0, -1));
|
||||||
|
//fresnel = fresnel * fresnel;
|
||||||
|
|
||||||
|
float fresnel = 1 + dot(normalize(positionVS), normalize(normalVS));
|
||||||
|
fresnel = fresnel * fresnel * fresnel * fresnel;
|
||||||
|
|
||||||
|
// Combine everything
|
||||||
|
fragColor = vec4(normalize(normalWS) * 0.5 + vec3(0.5, 0.5, 0.5), 1.0);
|
||||||
|
fragColor = vec4(shadow / 255, shadow / 255, shadow / 255, 1);
|
||||||
|
|
||||||
|
// Object ID output
|
||||||
|
objectID = u_objectID;
|
||||||
|
}
|
||||||
26
imgui.ini
26
imgui.ini
@ -10,34 +10,40 @@ Collapsed=0
|
|||||||
|
|
||||||
[Window][ViewportPanel]
|
[Window][ViewportPanel]
|
||||||
Pos=561,26
|
Pos=561,26
|
||||||
Size=1500,853
|
Size=1348,870
|
||||||
Collapsed=0
|
Collapsed=0
|
||||||
DockId=0x00000005,0
|
DockId=0x00000005,0
|
||||||
|
|
||||||
[Window][PropertiesPanel]
|
[Window][PropertiesPanel]
|
||||||
Pos=2063,26
|
Pos=1911,26
|
||||||
Size=497,853
|
Size=649,870
|
||||||
Collapsed=0
|
Collapsed=0
|
||||||
DockId=0x00000006,0
|
DockId=0x00000006,0
|
||||||
|
|
||||||
[Window][ResourceExplorer]
|
[Window][ResourceExplorer]
|
||||||
Pos=0,881
|
Pos=0,898
|
||||||
Size=2560,490
|
Size=2560,473
|
||||||
Collapsed=0
|
Collapsed=0
|
||||||
DockId=0x00000004,0
|
DockId=0x00000004,0
|
||||||
|
|
||||||
[Window][TreePanel]
|
[Window][TreePanel]
|
||||||
Pos=0,26
|
Pos=0,26
|
||||||
Size=559,853
|
Size=559,870
|
||||||
Collapsed=0
|
Collapsed=0
|
||||||
DockId=0x00000001,0
|
DockId=0x00000001,0
|
||||||
|
|
||||||
|
[Window][VoxelEditor]
|
||||||
|
Pos=1911,26
|
||||||
|
Size=649,870
|
||||||
|
Collapsed=0
|
||||||
|
DockId=0x00000006,1
|
||||||
|
|
||||||
[Docking][Data]
|
[Docking][Data]
|
||||||
DockSpace ID=0x0AC2E849 Window=0xD0388BC8 Pos=0,26 Size=2560,1345 Split=Y
|
DockSpace ID=0x0AC2E849 Window=0xD0388BC8 Pos=0,26 Size=2560,1345 Split=Y
|
||||||
DockNode ID=0x00000003 Parent=0x0AC2E849 SizeRef=1920,493 Split=X
|
DockNode ID=0x00000003 Parent=0x0AC2E849 SizeRef=1920,870 Split=X
|
||||||
DockNode ID=0x00000001 Parent=0x00000003 SizeRef=559,985 Selected=0x16E3C1E7
|
DockNode ID=0x00000001 Parent=0x00000003 SizeRef=559,985 Selected=0x16E3C1E7
|
||||||
DockNode ID=0x00000002 Parent=0x00000003 SizeRef=1359,985 Split=X
|
DockNode ID=0x00000002 Parent=0x00000003 SizeRef=1359,985 Split=X
|
||||||
DockNode ID=0x00000005 Parent=0x00000002 SizeRef=1500,493 CentralNode=1 Selected=0x0F5FFC8C
|
DockNode ID=0x00000005 Parent=0x00000002 SizeRef=1348,493 CentralNode=1 Selected=0x0F5FFC8C
|
||||||
DockNode ID=0x00000006 Parent=0x00000002 SizeRef=497,493 Selected=0x9876A79B
|
DockNode ID=0x00000006 Parent=0x00000002 SizeRef=649,493 Selected=0x9876A79B
|
||||||
DockNode ID=0x00000004 Parent=0x0AC2E849 SizeRef=1920,490 Selected=0x018A0F9B
|
DockNode ID=0x00000004 Parent=0x0AC2E849 SizeRef=1920,473 Selected=0x018A0F9B
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user