Chunks render moved to ChunksLoader

This commit is contained in:
MihailRis 2022-06-29 19:30:23 +03:00 committed by GitHub
parent 15bed4169e
commit f569378b88
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 127 additions and 43 deletions

View File

@ -1,12 +1,12 @@
#include "VoxelRenderer.h" #include "VoxelRenderer.h"
#include <iostream>
#include "Mesh.h" #include "Mesh.h"
#include "../voxels/Chunk.h" #include "../voxels/Chunk.h"
#include "../voxels/voxel.h" #include "../voxels/voxel.h"
#include "../voxels/Block.h" #include "../voxels/Block.h"
#include "../lighting/Lightmap.h" #include "../lighting/Lightmap.h"
#define VERTEX_SIZE (3 + 2 + 4)
#define CDIV(X,A) (((X) < 0) ? ((X) / (A) - 1) : ((X) / (A))) #define CDIV(X,A) (((X) < 0) ? ((X) / (A) - 1) : ((X) / (A)))
#define LOCAL_NEG(X, SIZE) (((X) < 0) ? ((SIZE)+(X)) : (X)) #define LOCAL_NEG(X, SIZE) (((X) < 0) ? ((SIZE)+(X)) : (X))
#define LOCAL(X, SIZE) ((X) >= (SIZE) ? ((X) - (SIZE)) : LOCAL_NEG(X, SIZE)) #define LOCAL(X, SIZE) ((X) >= (SIZE) ? ((X) - (SIZE)) : LOCAL_NEG(X, SIZE))
@ -17,16 +17,16 @@
#define VOXEL(X,Y,Z) (GET_CHUNK(X,Y,Z)->voxels[(LOCAL(Y, CHUNK_H) * CHUNK_D + LOCAL(Z, CHUNK_D)) * CHUNK_W + LOCAL(X, CHUNK_W)]) #define VOXEL(X,Y,Z) (GET_CHUNK(X,Y,Z)->voxels[(LOCAL(Y, CHUNK_H) * CHUNK_D + LOCAL(Z, CHUNK_D)) * CHUNK_W + LOCAL(X, CHUNK_W)])
#define IS_BLOCKED(X,Y,Z,GROUP) ((!IS_CHUNK(X, Y, Z)) || Block::blocks[VOXEL(X, Y, Z).id]->drawGroup == (GROUP)) #define IS_BLOCKED(X,Y,Z,GROUP) ((!IS_CHUNK(X, Y, Z)) || Block::blocks[VOXEL(X, Y, Z).id]->drawGroup == (GROUP))
#define VERTEX(INDEX, X,Y,Z, U,V, R,G,B,S) buffer[INDEX+0] = (X);\ #define VERTEX(INDEX, X,Y,Z, U,V, R,G,B,S) buffer.push_back(X);\
buffer[INDEX+1] = (Y);\ buffer.push_back(Y);\
buffer[INDEX+2] = (Z);\ buffer.push_back(Z);\
buffer[INDEX+3] = (U);\ buffer.push_back(U);\
buffer[INDEX+4] = (V);\ buffer.push_back(V);\
buffer[INDEX+5] = (R);\ buffer.push_back(R);\
buffer[INDEX+6] = (G);\ buffer.push_back(G);\
buffer[INDEX+7] = (B);\ buffer.push_back(B);\
buffer[INDEX+8] = (S);\ buffer.push_back(S);\
INDEX += VERTEX_SIZE; INDEX += CHUNK_VERTEX_SIZE;
#define SETUP_UV(INDEX) float u1 = ((INDEX) % 16) * uvsize;\ #define SETUP_UV(INDEX) float u1 = ((INDEX) % 16) * uvsize;\
@ -36,15 +36,13 @@
int chunk_attrs[] = {3,2,4, 0}; int chunk_attrs[] = {3,2,4, 0};
VoxelRenderer::VoxelRenderer(size_t capacity) : capacity(capacity) { VoxelRenderer::VoxelRenderer() {
buffer = new float[capacity * VERTEX_SIZE * 6];
} }
VoxelRenderer::~VoxelRenderer(){ VoxelRenderer::~VoxelRenderer(){
delete[] buffer;
} }
inline void _renderBlock(float* buffer, int x, int y, int z, const Chunk** chunks, voxel vox, size_t& index){ inline void _renderBlock(std::vector<float>& buffer, int x, int y, int z, const Chunk** chunks, voxel vox, size_t& index){
unsigned int id = vox.id; unsigned int id = vox.id;
if (!id){ if (!id){
@ -289,7 +287,8 @@ inline void _renderBlock(float* buffer, int x, int y, int z, const Chunk** chunk
} }
} }
Mesh* VoxelRenderer::render(Chunk* chunk, const Chunk** chunks){ const float* VoxelRenderer::render(Chunk* chunk, const Chunk** chunks, size_t& size){
buffer.clear();
size_t index = 0; size_t index = 0;
for (int y = 0; y < CHUNK_H; y++){ for (int y = 0; y < CHUNK_H; y++){
for (int z = 0; z < CHUNK_D; z++){ for (int z = 0; z < CHUNK_D; z++){
@ -323,5 +322,6 @@ Mesh* VoxelRenderer::render(Chunk* chunk, const Chunk** chunks){
} }
} }
} }
return new Mesh(buffer, index / VERTEX_SIZE, chunk_attrs); size = buffer.size();
return &buffer[0];
} }

View File

@ -2,18 +2,20 @@
#define GRAPHICS_VOXELRENDERER_H_ #define GRAPHICS_VOXELRENDERER_H_
#include <stdlib.h> #include <stdlib.h>
#include <vector>
class Mesh; class Mesh;
class Chunk; class Chunk;
#define CHUNK_VERTEX_SIZE (3 + 2 + 4)
class VoxelRenderer { class VoxelRenderer {
float* buffer;
size_t capacity;
public: public:
VoxelRenderer(size_t capacity); std::vector<float> buffer;
VoxelRenderer();
~VoxelRenderer(); ~VoxelRenderer();
Mesh* render(Chunk* chunk, const Chunk** chunks); const float* render(Chunk* chunk, const Chunk** chunks, size_t& size);
}; };
#endif /* GRAPHICS_VOXELRENDERER_H_ */ #endif /* GRAPHICS_VOXELRENDERER_H_ */

View File

@ -25,7 +25,7 @@
#define CAMERA_SHAKING_OFFSET_Y 0.031f #define CAMERA_SHAKING_OFFSET_Y 0.031f
#define CAMERA_SHAKING_SPEED 1.6f #define CAMERA_SHAKING_SPEED 1.6f
#define CAMERA_SHAKING_DELTA_K 10.0f #define CAMERA_SHAKING_DELTA_K 10.0f
#define FLIGHT_SPEED_MUL 5.0f #define FLIGHT_SPEED_MUL 8.0f
#define JUMP_FORCE 7.0f #define JUMP_FORCE 7.0f
void update_controls(PhysicsSolver* physics, void update_controls(PhysicsSolver* physics,

View File

@ -81,10 +81,12 @@ void update_level(World* world, Level* level, vec3 position, float delta, long f
update_controls(level->physics, level->chunks, level->player, delta); update_controls(level->physics, level->chunks, level->player, delta);
update_interaction(level, lineBatch); update_interaction(level, lineBatch);
level->chunks->setCenter(world->wfile, position.x,0,position.z); level->chunks->setCenter(world->wfile, position.x, 0, position.z);
level->chunksController->_buildMeshes(renderer, frame);
int freeLoaders = level->chunksController->countFreeLoaders(); int freeLoaders = level->chunksController->countFreeLoaders();
for (int i = 0; i < freeLoaders; i++)
level->chunksController->_buildMeshes(renderer, frame);
freeLoaders = level->chunksController->countFreeLoaders();
for (int i = 0; i < freeLoaders; i++) for (int i = 0; i < freeLoaders; i++)
level->chunksController->loadVisible(world->wfile); level->chunksController->loadVisible(world->wfile);
} }
@ -140,7 +142,7 @@ int main() {
bool occlusion = false; bool occlusion = false;
bool devdata = false; bool devdata = false;
glfwSwapInterval(0); Window::swapInterval(0);
std::cout << "-- initializing finished" << std::endl; std::cout << "-- initializing finished" << std::endl;
while (!Window::isShouldClose()){ while (!Window::isShouldClose()){

View File

@ -8,6 +8,7 @@ Chunk::Chunk(int xpos, int ypos, int zpos) : x(xpos), y(ypos), z(zpos){
for (unsigned int i = 0; i < CHUNK_VOL; i++) for (unsigned int i = 0; i < CHUNK_VOL; i++)
voxels[i].id = 1; voxels[i].id = 1;
lightmap = new Lightmap(); lightmap = new Lightmap();
renderData.vertices = nullptr;
} }
Chunk::~Chunk(){ Chunk::~Chunk(){

View File

@ -1,6 +1,8 @@
#ifndef VOXELS_CHUNK_H_ #ifndef VOXELS_CHUNK_H_
#define VOXELS_CHUNK_H_ #define VOXELS_CHUNK_H_
#include <stdlib.h>
#define CHUNK_W 16 #define CHUNK_W 16
#define CHUNK_H 256 #define CHUNK_H 256
#define CHUNK_D 16 #define CHUNK_D 16
@ -9,6 +11,11 @@
class voxel; class voxel;
class Lightmap; class Lightmap;
struct RenderData {
float* vertices;
size_t size;
};
class Chunk { class Chunk {
public: public:
int x,y,z; int x,y,z;
@ -19,6 +26,8 @@ public:
bool loaded = false; bool loaded = false;
int surrounding = 0; int surrounding = 0;
int references = 1; int references = 1;
RenderData renderData;
Chunk(int x, int y, int z); Chunk(int x, int y, int z);
~Chunk(); ~Chunk();

View File

@ -20,7 +20,7 @@
ChunksController::ChunksController(Chunks* chunks, Lighting* lighting) : chunks(chunks), lighting(lighting){ ChunksController::ChunksController(Chunks* chunks, Lighting* lighting) : chunks(chunks), lighting(lighting){
loadersCount = std::thread::hardware_concurrency() - 1; loadersCount = std::thread::hardware_concurrency() * 2 - 1;
if (loadersCount <= 0) if (loadersCount <= 0)
loadersCount = 1; loadersCount = 1;
loaders = new ChunksLoader*[loadersCount]; loaders = new ChunksLoader*[loadersCount];
@ -130,7 +130,7 @@ bool ChunksController::loadVisible(WorldFiles* worldFiles){
oz += 1; oz += 1;
closes[(oy * 3 + oz) * 3 + ox] = other; closes[(oy * 3 + oz) * 3 + ox] = other;
} }
freeLoader->perform(chunk, (Chunk**)closes); freeLoader->load(chunk, (Chunk**)closes);
return true; return true;
} }
@ -139,6 +139,35 @@ bool ChunksController::_buildMeshes(VoxelRenderer* renderer, int tick) {
const int h = chunks->h; const int h = chunks->h;
const int d = chunks->d; const int d = chunks->d;
for (int y = 0; y < h; y++){
for (int z = 1; z < d-1; z++){
for (int x = 1; x < w-1; x++){
int index = (y * d + z) * w + x;
Chunk* chunk = chunks->chunks[index];
if (chunk == nullptr)
continue;
if (chunk->renderData.vertices > (void*)1){
const int chunk_attrs[] = {3,2,4, 0};
Mesh* mesh = new Mesh(chunk->renderData.vertices, chunk->renderData.size / CHUNK_VERTEX_SIZE, chunk_attrs);
chunks->meshes[index] = mesh;
delete[] chunk->renderData.vertices;
chunk->renderData.vertices = nullptr;
}
}
}
}
ChunksLoader* freeLoader = nullptr;
for (int i = 0; i < loadersCount; i++){
ChunksLoader* loader = loaders[i];
if (loader->isBusy()){
continue;
}
freeLoader = loader;
break;
}
if (freeLoader == nullptr)
return false;
int nearX = 0; int nearX = 0;
int nearY = 0; int nearY = 0;
int nearZ = 0; int nearZ = 0;
@ -208,9 +237,15 @@ bool ChunksController::_buildMeshes(VoxelRenderer* renderer, int tick) {
oz += 1; oz += 1;
closes[(oy * 3 + oz) * 3 + ox] = other; closes[(oy * 3 + oz) * 3 + ox] = other;
} }
mesh = renderer->render(chunk, (const Chunk**)closes); if (chunk->renderData.vertices == nullptr){
chunks->meshes[index] = mesh; chunk->renderData.vertices = (float*)1;
return true; freeLoader->render(chunk, (Chunk**)closes);
return true;
}
//mesh = renderer->render(chunk, (const Chunk**)closes);
//chunks->meshes[index] = mesh;
} }
return false; return false;
} }

View File

@ -5,6 +5,7 @@
#include "Chunks.h" #include "Chunks.h"
#include "WorldGenerator.h" #include "WorldGenerator.h"
#include "../lighting/Lighting.h" #include "../lighting/Lighting.h"
#include "../graphics/VoxelRenderer.h"
#include <iostream> #include <iostream>
@ -13,7 +14,8 @@
void ChunksLoader::_thread(){ void ChunksLoader::_thread(){
Chunks chunks(3,3,3, -1,-1,-1); Chunks chunks(3,3,3, -1,-1,-1);
Lighting lighting(&chunks); Lighting lighting(&chunks);
while (working){ VoxelRenderer renderer;
while (state != OFF){
if (current == nullptr){ if (current == nullptr){
std::this_thread::sleep_for(std::chrono::milliseconds(1)); std::this_thread::sleep_for(std::chrono::milliseconds(1));
continue; continue;
@ -27,12 +29,24 @@ void ChunksLoader::_thread(){
} }
} }
if (!chunk->loaded){ if (state == LOAD){
WorldGenerator::generate(chunk->voxels, chunk->x, chunk->y, chunk->z); chunks.putChunk(chunk);
if (!chunk->loaded){
WorldGenerator::generate(chunk->voxels, chunk->x, chunk->y, chunk->z);
}
lighting.onChunkLoaded(chunk->x, chunk->y, chunk->z, true);
}
else if (state == RENDER){
size_t size;
renderer.render(chunk, (const Chunk**)(closes.load()), size);
float* vertices = new float[size];
for (size_t i = 0; i < size; i++)
vertices[i] = renderer.buffer[i];
chunk->renderData.vertices = vertices;
chunk->renderData.size = size;
} }
chunks.putChunk(chunk);
lighting.onChunkLoaded(chunk->x, chunk->y, chunk->z, true);
chunks.clear(false); chunks.clear(false);
for (int i = 0; i < CLOSES_C; i++){ for (int i = 0; i < CLOSES_C; i++){
Chunk* other = closes[i]; Chunk* other = closes[i];
@ -45,7 +59,7 @@ void ChunksLoader::_thread(){
} }
} }
void ChunksLoader::perform(Chunk* chunk, Chunk** closes_passed){ void ChunksLoader::perform(Chunk* chunk, Chunk** closes_passed, LoaderMode mode){
if (isBusy()){ if (isBusy()){
std::cerr << "performing while busy" << std::endl; std::cerr << "performing while busy" << std::endl;
return; return;
@ -64,4 +78,13 @@ void ChunksLoader::perform(Chunk* chunk, Chunk** closes_passed){
} }
} }
current = chunk; current = chunk;
state = mode;
}
void ChunksLoader::load(Chunk* chunk, Chunk** closes_passed){
perform(chunk, closes_passed, LOAD);
}
void ChunksLoader::render(Chunk* chunk, Chunk** closes_passed){
perform(chunk, closes_passed, RENDER);
} }

View File

@ -12,19 +12,25 @@
class Chunk; class Chunk;
enum LoaderMode {
OFF, IDLE, LOAD, RENDER,
};
class ChunksLoader final { class ChunksLoader final {
private: private:
std::thread loaderThread; std::thread loaderThread;
void _thread(); void _thread();
std::atomic<Chunk*> current {nullptr}; std::atomic<Chunk*> current {nullptr};
std::atomic<Chunk**> closes {nullptr}; std::atomic<Chunk**> closes {nullptr};
std::atomic<bool> working {true}; std::atomic<LoaderMode> state {IDLE};
void perform(Chunk* chunk, Chunk** closes_passed, LoaderMode mode);
public: public:
ChunksLoader() : loaderThread{} { ChunksLoader() : loaderThread{} {
loaderThread = std::thread{&ChunksLoader::_thread, this}; loaderThread = std::thread{&ChunksLoader::_thread, this};
} }
~ChunksLoader(){ ~ChunksLoader(){
working = false; state = OFF;
loaderThread.join(); loaderThread.join();
} }
@ -32,10 +38,11 @@ public:
return current != nullptr; return current != nullptr;
} }
void perform(Chunk* chunk, Chunk** closes_passed); void load(Chunk* chunk, Chunk** closes_passed);
void render(Chunk* chunk, Chunk** closes_passed);
void stop(){ void stop(){
working = false; state = OFF;
} }
}; };

View File

@ -57,6 +57,10 @@ void Window::setShouldClose(bool flag){
glfwSetWindowShouldClose(window, flag); glfwSetWindowShouldClose(window, flag);
} }
void Window::swapInterval(int interval){
glfwSwapInterval(interval);
}
void Window::swapBuffers(){ void Window::swapBuffers(){
glfwSwapBuffers(window); glfwSwapBuffers(window);
} }

View File

@ -15,6 +15,7 @@ public:
static bool isShouldClose(); static bool isShouldClose();
static void setShouldClose(bool flag); static void setShouldClose(bool flag);
static void swapBuffers(); static void swapBuffers();
static void swapInterval(int interval);
}; };
#endif /* WINDOW_WINDOW_H_ */ #endif /* WINDOW_WINDOW_H_ */

View File

@ -57,7 +57,7 @@ void init_renderer(){
uicamera->perspective = false; uicamera->perspective = false;
uicamera->flipped = true; uicamera->flipped = true;
renderer = new VoxelRenderer(1024*1024); renderer = new VoxelRenderer();
} }