Chunk Loading
This commit is contained in:
@@ -17,8 +17,11 @@ void main() {
|
||||
if (outColour.w == .0)
|
||||
discard;
|
||||
|
||||
float fogMax = 20000;
|
||||
float fogMax = 60000;
|
||||
|
||||
outColour = vec4(mix(outColour.xyz, SkyColour, min(1.0f, Distance / fogMax)), outColour.w);
|
||||
vec3 colour = mix(outColour.xyz, SkyColour, min(1.0f, Distance / fogMax));
|
||||
|
||||
// Retain fragment transparency
|
||||
outColour = vec4(colour, outColour.w);
|
||||
|
||||
}
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
#ifndef MINECRAFT_COMMON_H_
|
||||
#define MINECRAFT_COMMON_H_
|
||||
|
||||
#include <glm/glm.hpp>
|
||||
#include <glm/gtc/matrix_transform.hpp>
|
||||
#include <glm/gtc/type_ptr.hpp>
|
||||
#include <glm/gtx/hash.hpp>
|
||||
#include <glm/glm.hpp>
|
||||
|
||||
#include <glad/glad.h>
|
||||
#include <KHR/khrplatform.h>
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
#include "game.hpp"
|
||||
|
||||
// For glm::vec2 as the key of a hashmap
|
||||
#define GLM_ENABLE_EXPERIMENTAL
|
||||
|
||||
#define LOGGER_DEFINITION
|
||||
#include <logger.h>
|
||||
|
||||
@@ -81,6 +84,8 @@ void Game::Setup(int w, int h) {
|
||||
|
||||
m_cameras["Default"] = std::make_shared<Camera>(w, h);
|
||||
m_activeCamera = m_cameras["Default"];
|
||||
m_activeCamera->Position = { 0, 40, 0 };
|
||||
m_activeCamera->UpdateView();
|
||||
|
||||
std::shared_ptr<CBlockDictionary> BlockDictionary = CBlockDictionary::GetInstance();
|
||||
|
||||
@@ -92,10 +97,6 @@ void Game::Setup(int w, int h) {
|
||||
m_world->SetTextureMap(texture.LoadTextures(BlockDictionary->Textures));
|
||||
|
||||
m_world->LoadWorld();
|
||||
|
||||
m_world->Shaders["Basic"] = std::make_shared<Shader>();
|
||||
m_world->Shaders["Basic"]->Load(GameConfig.ResourceBase + "shaders/simple");
|
||||
m_world->Shaders["Basic"]->Link();
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -11,12 +11,6 @@ Renderer::Renderer() {
|
||||
// Perform the render passes
|
||||
void Renderer::Render(std::shared_ptr<World> world, std::shared_ptr<Camera> camera) {
|
||||
|
||||
glBindTexture(GL_TEXTURE_2D_ARRAY, world->TextureID);
|
||||
|
||||
for (int i = 0; i < world->Chunks.size(); i++) {
|
||||
|
||||
world->Chunks[i]->Render(camera, world->Shaders["Basic"]);
|
||||
|
||||
}
|
||||
world->Render(camera);
|
||||
|
||||
}
|
||||
|
||||
@@ -11,16 +11,43 @@
|
||||
|
||||
static std::default_random_engine generator;
|
||||
|
||||
Chunk::Chunk() {
|
||||
|
||||
}
|
||||
|
||||
Chunk::Chunk(int x, int z) {
|
||||
|
||||
m_model = glm::translate(glm::mat4(1.0f), { x * CHUNK_WIDTH, 0, z * CHUNK_DEPTH });
|
||||
|
||||
Load();
|
||||
|
||||
}
|
||||
|
||||
Chunk::Chunk(int x, int z, std::vector<uint8_t> voxels) {
|
||||
|
||||
m_model = glm::translate(glm::mat4(1.0f), { x * CHUNK_WIDTH, 0, z * CHUNK_DEPTH });
|
||||
|
||||
Voxels = voxels;
|
||||
|
||||
Load();
|
||||
|
||||
}
|
||||
|
||||
void Chunk::Load() {
|
||||
|
||||
if (Loaded)
|
||||
return;
|
||||
|
||||
if (!Voxels.empty()) {
|
||||
m_mesh();
|
||||
return;
|
||||
}
|
||||
|
||||
// [x + WIDTH * (y + HEIGHT * z)]
|
||||
for (int x = 0; x < CHUNK_WIDTH; x++)
|
||||
for (int y = 0; y < CHUNK_HEIGHT; y++)
|
||||
for (int z = 0; z < CHUNK_DEPTH; z++) {
|
||||
|
||||
|
||||
if (y > 32) {
|
||||
Voxels.push_back((uint8_t)EBlockType::Air);
|
||||
continue;
|
||||
@@ -28,13 +55,12 @@ Chunk::Chunk(int x, int z) {
|
||||
|
||||
std::uniform_real_distribution<float> distribution(0, 1);
|
||||
float r = distribution(generator);
|
||||
|
||||
if (r > 0.8f) {
|
||||
|
||||
if (r > 0.9f) {
|
||||
Voxels.push_back((uint8_t)EBlockType::Air);
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
if (y == 0)
|
||||
Voxels.push_back((uint8_t)EBlockType::Bedrock);
|
||||
else if (y < 28)
|
||||
@@ -47,22 +73,51 @@ Chunk::Chunk(int x, int z) {
|
||||
}
|
||||
|
||||
m_mesh();
|
||||
Loaded = true;
|
||||
|
||||
}
|
||||
|
||||
Chunk::Chunk(int x, int z, std::vector<uint8_t> voxels) {
|
||||
void Chunk::UploadMesh() {
|
||||
|
||||
m_model = glm::translate(glm::mat4(1.0f), { x * CHUNK_WIDTH, 0, z * CHUNK_DEPTH });
|
||||
|
||||
Voxels = voxels;
|
||||
|
||||
m_mesh();
|
||||
if (!MeshReady)
|
||||
return;
|
||||
|
||||
glGenVertexArrays(1, &m_vao);
|
||||
glBindVertexArray(m_vao);
|
||||
|
||||
glGenBuffers(1, &m_vbo);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, m_vbo);
|
||||
|
||||
std::vector<glm::vec3> data;
|
||||
data.insert(data.end(), m_vertices.begin(), m_vertices.end());
|
||||
data.insert(data.end(), m_uvs.begin(), m_uvs.end());
|
||||
|
||||
m_numVerts = m_vertices.size();
|
||||
|
||||
glBufferData(GL_ARRAY_BUFFER, data.size() * sizeof(glm::vec3), &data[0], GL_STATIC_DRAW);
|
||||
|
||||
glEnableVertexAttribArray(0);
|
||||
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, (const void*)0);
|
||||
|
||||
glEnableVertexAttribArray(1);
|
||||
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 0, (const void*)(m_vertices.size() * sizeof(glm::vec3)));
|
||||
|
||||
m_vertices.clear();
|
||||
m_uvs.clear();
|
||||
|
||||
data.clear();
|
||||
|
||||
glBindVertexArray(0);
|
||||
|
||||
MeshReady = !MeshReady;
|
||||
|
||||
}
|
||||
|
||||
|
||||
void Chunk::Render(std::shared_ptr<Camera> camera, std::shared_ptr<Shader> shader) {
|
||||
|
||||
if (!Loaded)
|
||||
return;
|
||||
|
||||
shader->Use();
|
||||
glBindVertexArray(m_vao);
|
||||
|
||||
@@ -79,8 +134,9 @@ void Chunk::Render(std::shared_ptr<Camera> camera, std::shared_ptr<Shader> shade
|
||||
|
||||
}
|
||||
|
||||
void Chunk::Update() {
|
||||
void Chunk::Update(std::vector<uint8_t> voxels) {
|
||||
|
||||
Voxels = voxels;
|
||||
m_mesh();
|
||||
|
||||
}
|
||||
@@ -142,29 +198,10 @@ void Chunk::m_mesh() {
|
||||
|
||||
}
|
||||
|
||||
glGenVertexArrays(1, &m_vao);
|
||||
glBindVertexArray(m_vao);
|
||||
|
||||
glGenBuffers(1, &m_vbo);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, m_vbo);
|
||||
|
||||
std::vector<glm::vec3> data;
|
||||
data.insert(data.end(), m_vertices.begin(), m_vertices.end());
|
||||
data.insert(data.end(), m_uvs.begin(), m_uvs.end());
|
||||
|
||||
m_numVerts = m_vertices.size();
|
||||
|
||||
glBufferData(GL_ARRAY_BUFFER, data.size() * sizeof(glm::vec3), &data[0], GL_STATIC_DRAW);
|
||||
|
||||
glEnableVertexAttribArray(0);
|
||||
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, (const void*)0);
|
||||
|
||||
glEnableVertexAttribArray(1);
|
||||
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 0, (const void*)(m_vertices.size() * sizeof(glm::vec3)));
|
||||
|
||||
m_vertices.clear();
|
||||
m_uvs.clear();
|
||||
|
||||
glBindVertexArray(0);
|
||||
MeshReady = true;
|
||||
|
||||
}
|
||||
|
||||
Chunk::~Chunk() {
|
||||
|
||||
}
|
||||
|
||||
@@ -15,12 +15,19 @@ class Voxel;
|
||||
class Chunk {
|
||||
public:
|
||||
|
||||
Chunk();
|
||||
Chunk(int x, int z);
|
||||
Chunk(int x, int z, std::vector<uint8_t> voxels);
|
||||
|
||||
void Load();
|
||||
|
||||
bool MeshReady = false;
|
||||
void UploadMesh();
|
||||
|
||||
|
||||
void Render(std::shared_ptr<Camera> camera, std::shared_ptr<Shader> shader);
|
||||
|
||||
void Update();
|
||||
void Update(std::vector<uint8_t> voxels);
|
||||
|
||||
//bool Loaded = false;
|
||||
//bool Render = false;
|
||||
@@ -32,6 +39,13 @@ public:
|
||||
// to generate a mesh and send it to the GPU
|
||||
std::vector<uint8_t> Voxels;
|
||||
|
||||
// To only be changed by the class its self
|
||||
bool Loaded = false;
|
||||
// To only be changed by render components
|
||||
bool ShouldRender = false;
|
||||
|
||||
~Chunk();
|
||||
|
||||
private:
|
||||
|
||||
void m_mesh();
|
||||
|
||||
@@ -2,3 +2,4 @@
|
||||
#define MINECRAFT_WORLD_ENTITY_H_
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,22 +1,140 @@
|
||||
#include "world.hpp"
|
||||
|
||||
#include "chunk/chunk.hpp"
|
||||
|
||||
#include "../renderer/shader.hpp"
|
||||
|
||||
#include "../config.hpp"
|
||||
|
||||
World::World() {
|
||||
|
||||
}
|
||||
|
||||
void World::LoadWorld() {
|
||||
|
||||
m_shaders["Basic"] = std::make_shared<Shader>();
|
||||
m_shaders["Basic"]->Load(GameConfig.ResourceBase + "shaders/simple");
|
||||
m_shaders["Basic"]->Link();
|
||||
|
||||
for (int x = -4; x < 4; x++)
|
||||
for (int y = -4; y < 4; y++) {
|
||||
|
||||
m_chunkLoaderQueue.push({ x, y });
|
||||
|
||||
}
|
||||
|
||||
for (int i = 0; i < 7; i++) {
|
||||
|
||||
m_generatorThreads.push_back(std::thread([&]() {
|
||||
|
||||
m_loadChunks();
|
||||
|
||||
}));
|
||||
|
||||
}
|
||||
|
||||
m_generatorRunning = true;
|
||||
|
||||
}
|
||||
|
||||
void World::SetTextureMap(GLuint map) {
|
||||
|
||||
m_textureMapID = map;
|
||||
|
||||
}
|
||||
|
||||
glm::vec2 World::GetChunkCoords(glm::vec3) {
|
||||
glm::vec2 World::GetChunkCoords(glm::vec3 wordCoords) {
|
||||
|
||||
return { wordCoords.x / CHUNK_WIDTH, wordCoords.z / CHUNK_DEPTH };
|
||||
|
||||
}
|
||||
|
||||
std::vector<std::shared_ptr<Chunk>> World::GetRenderableChunks() {
|
||||
|
||||
std::vector<std::shared_ptr<Chunk>> chunks;
|
||||
|
||||
for (auto& chunk : m_chunks) {
|
||||
|
||||
// Should the chunk be rendererd ?
|
||||
if (chunk.second->ShouldRender) {
|
||||
|
||||
m_chunkMutex.lock();
|
||||
|
||||
if (chunk.second->MeshReady)
|
||||
chunk.second->UploadMesh();
|
||||
|
||||
m_chunkMutex.unlock();
|
||||
|
||||
// If not, add it
|
||||
chunks.push_back(chunk.second);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return chunks;
|
||||
|
||||
}
|
||||
|
||||
void World::Render(std::shared_ptr<Camera> camera) {
|
||||
|
||||
glBindTexture(GL_TEXTURE_2D_ARRAY, m_textureMapID);
|
||||
|
||||
std::vector<std::shared_ptr<Chunk>> chunks = GetRenderableChunks();
|
||||
|
||||
|
||||
for (int i = 0; i < chunks.size(); i++) {
|
||||
|
||||
chunks[i]->Render(camera, m_shaders["Basic"]);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
World::~World() {
|
||||
|
||||
m_generatorRunning = false;
|
||||
|
||||
for (int i = 0; i < m_generatorThreads.size(); i++) {
|
||||
|
||||
m_generatorThreads[i].join();
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void World::m_loadChunks() {
|
||||
|
||||
while (m_generatorRunning) {
|
||||
|
||||
m_chunkMutex.lock();
|
||||
|
||||
glm::vec2 coords = m_chunkLoaderQueue.front();
|
||||
m_chunkLoaderQueue.pop();
|
||||
|
||||
m_chunkMutex.unlock();
|
||||
|
||||
|
||||
std::shared_ptr<Chunk> loadingChunk = std::make_shared<Chunk>(coords.x, coords.y);
|
||||
std::cout << "Loaded chunk " << coords.x << ":" << coords.y << std::endl;
|
||||
|
||||
|
||||
m_chunkMutex.lock();
|
||||
|
||||
m_chunks[coords] = loadingChunk;
|
||||
m_chunks[coords]->ShouldRender = true;
|
||||
|
||||
m_chunkMutex.unlock();
|
||||
|
||||
|
||||
while (m_chunkLoaderQueue.empty()) {
|
||||
|
||||
if (!m_generatorRunning) break;
|
||||
static std::chrono::milliseconds dura(1);
|
||||
std::this_thread::sleep_for(dura);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -3,42 +3,67 @@
|
||||
|
||||
#include "../common.hpp"
|
||||
|
||||
#include <unordered_map>
|
||||
#include "../renderer/camera.hpp"
|
||||
|
||||
#include "chunk/chunk.hpp"
|
||||
|
||||
#include <unordered_map>
|
||||
#include <thread>
|
||||
#include <mutex>
|
||||
#include <queue>
|
||||
|
||||
class Shader;
|
||||
class Chunk;
|
||||
|
||||
class World {
|
||||
public:
|
||||
|
||||
// Default constructor
|
||||
World();
|
||||
|
||||
|
||||
// Preps the render threads and loads all of the shaders
|
||||
void LoadWorld();
|
||||
|
||||
void SetTextureMap(GLuint map);
|
||||
|
||||
// Takes world coordinates and gets a chunks coordinates
|
||||
glm::vec2 GetChunkCoords(glm::vec3);
|
||||
glm::vec2 GetChunkCoords(glm::vec3 wordCoords);
|
||||
|
||||
std::vector<std::shared_ptr<Chunk>> GetRenderableChunks();
|
||||
|
||||
|
||||
void Render(std::shared_ptr<Camera> camera);
|
||||
|
||||
~World();
|
||||
|
||||
private:
|
||||
|
||||
// GL stuff
|
||||
|
||||
// Main texture map id
|
||||
GLuint m_textureMapID;
|
||||
|
||||
|
||||
// Shaders indexed by name
|
||||
std::map<std::string, std::shared_ptr<Shader>> m_shaders;
|
||||
|
||||
|
||||
|
||||
// Threads used for chunk generation
|
||||
std::vector<std::thread> m_generatorThreads;
|
||||
bool m_generatorRunning = false;
|
||||
|
||||
|
||||
// Chuks
|
||||
|
||||
std::vector<std::shared_ptr<Chunk>> m_renderableChunks;
|
||||
// Indexed by chunk coorinates
|
||||
std::unordered_map<glm::vec2, std::shared_ptr<Chunk>> m_chunks;
|
||||
|
||||
std::queue<glm::vec2> m_chunkUpdatesQueue;
|
||||
std::queue<glm::vec2> m_chunkLoaderQueue;
|
||||
|
||||
std::mutex m_chunkMutex;
|
||||
|
||||
|
||||
void m_loadChunks();
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user