initial update/mesh/render thread communication refactor
Quirks to iron out: - Some stuff is rendered wrong/not rendered (chunks missing) - Still no way to delete stuff from ChunksToRenderfix-multithread
parent
a05d019c69
commit
ca44c0f284
|
@ -25,14 +25,11 @@ namespace Chunk
|
|||
|
||||
constexpr uint16_t CHUNK_STATE_GENERATED = 1;
|
||||
constexpr uint16_t CHUNK_STATE_MESHED = 2;
|
||||
constexpr uint16_t CHUNK_STATE_MESH_LOADED = 4;
|
||||
constexpr uint16_t CHUNK_STATE_LOADED = 8;
|
||||
constexpr uint16_t CHUNK_STATE_OUTOFVISION = 16;
|
||||
constexpr uint16_t CHUNK_STATE_UNLOADED = 32;
|
||||
constexpr uint16_t CHUNK_STATE_EMPTY = 64;
|
||||
constexpr uint16_t CHUNK_STATE_IN_GENERATION_QUEUE = 128;
|
||||
constexpr uint16_t CHUNK_STATE_IN_MESHING_QUEUE = 256;
|
||||
constexpr uint16_t CHUNK_STATE_IN_RENDERING_QUEUE = 512;
|
||||
|
||||
int coord3DTo1D(int x, int y, int z);
|
||||
|
||||
|
@ -61,12 +58,14 @@ namespace Chunk
|
|||
|
||||
public:
|
||||
GLuint VAO{0}, VBO{0}, extentsBuffer{0}, texinfoBuffer{0}, numVertices{0};
|
||||
int32_t getIndex(){ return index; }
|
||||
std::atomic<float> unload_timer{0};
|
||||
|
||||
private:
|
||||
glm::vec3 position{};
|
||||
IntervalMap<Block> blocks{};
|
||||
|
||||
int32_t index;
|
||||
std::atomic_uint16_t state{0};
|
||||
};
|
||||
};
|
||||
|
|
|
@ -21,7 +21,7 @@
|
|||
|
||||
namespace chunkmanager
|
||||
{
|
||||
typedef oneapi::tbb::concurrent_hash_map<uint32_t, Chunk::Chunk*> ChunkTable;
|
||||
typedef oneapi::tbb::concurrent_hash_map<int32_t, Chunk::Chunk*> ChunkTable;
|
||||
typedef oneapi::tbb::concurrent_queue<int> IntQueue;
|
||||
|
||||
//typedef std::unordered_map<int32_t, Chunk::Chunk*> ChunkTable;
|
||||
|
@ -37,6 +37,8 @@ namespace chunkmanager
|
|||
void init();
|
||||
void blockpick(bool place);
|
||||
int32_t calculateIndex(int16_t i, int16_t j, int16_t k);
|
||||
int32_t calculateIndex(Chunk::Chunk* c);
|
||||
int32_t calculateIndex(glm::vec3 position);
|
||||
|
||||
void stop();
|
||||
void destroy();
|
||||
|
|
|
@ -0,0 +1,32 @@
|
|||
#ifndef CHUNK_MESH_DATA_H
|
||||
#define CHUNK_MESH_DATA_H
|
||||
|
||||
enum class ChunkMeshDataType{
|
||||
MESH_UPDATE
|
||||
};
|
||||
|
||||
typedef struct ChunkMeshData{
|
||||
int32_t index;
|
||||
glm::vec3 position;
|
||||
int num_vertices = 0;
|
||||
|
||||
std::vector<GLfloat> vertices;
|
||||
std::vector<GLfloat> extents;
|
||||
std::vector<GLfloat> texinfo;
|
||||
|
||||
ChunkMeshDataType message_type;
|
||||
|
||||
void clear(){
|
||||
vertices.clear();
|
||||
texinfo.clear();
|
||||
extents.clear();
|
||||
index = 0;
|
||||
position = glm::vec3(0);
|
||||
num_vertices = 0;
|
||||
}
|
||||
|
||||
}ChunkMeshData;
|
||||
typedef oneapi::tbb::concurrent_queue<ChunkMeshData*> ChunkMeshDataQueue;
|
||||
|
||||
|
||||
#endif
|
|
@ -5,28 +5,19 @@
|
|||
#include <vector>
|
||||
|
||||
#include <glad/glad.h>
|
||||
#include <glm/glm.hpp>
|
||||
#include <GLFW/glfw3.h>
|
||||
#include <oneapi/tbb/concurrent_queue.h>
|
||||
|
||||
#include "chunk.hpp"
|
||||
#include "chunkmeshdata.hpp"
|
||||
#include "globals.hpp"
|
||||
#include "shader.hpp"
|
||||
|
||||
namespace chunkmesher{
|
||||
struct MeshData{
|
||||
Chunk::Chunk* chunk;
|
||||
GLuint numVertices{0};
|
||||
|
||||
std::vector<GLfloat> vertices;
|
||||
std::vector<GLfloat> extents;
|
||||
std::vector<GLfloat> texinfo;
|
||||
};
|
||||
oneapi::tbb::concurrent_queue<MeshData*>& getMeshDataQueue();
|
||||
|
||||
ChunkMeshDataQueue& getMeshDataQueue();
|
||||
void init();
|
||||
void mesh(Chunk::Chunk* chunk);
|
||||
void sendtogpu(MeshData* mesh_data);
|
||||
void quad(MeshData* mesh_data, glm::vec3 bottomLeft, glm::vec3 topLeft, glm::vec3 topRight,
|
||||
glm::vec3 bottomRight, glm::vec3 normal, Block block, int dim, bool backFace);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -1,18 +1,35 @@
|
|||
#ifndef RENDERER_H
|
||||
#define RENDERER_H
|
||||
|
||||
#include <oneapi/tbb/concurrent_unordered_set.h>
|
||||
#include <oneapi/tbb/concurrent_queue.h>
|
||||
#include <glm/glm.hpp>
|
||||
|
||||
#include "chunk.hpp"
|
||||
#include "chunkmesher.hpp"
|
||||
#include "chunkmeshdata.hpp"
|
||||
#include "shader.hpp"
|
||||
|
||||
namespace renderer{
|
||||
//typedef oneapi::tbb::concurrent_unordered_set<Chunk::Chunk*> RenderSet;
|
||||
typedef oneapi::tbb::concurrent_queue<Chunk::Chunk*> RenderQueue;
|
||||
typedef struct RenderInfo {
|
||||
int32_t index;
|
||||
int num_vertices;
|
||||
glm::vec3 position;
|
||||
bool buffers_allocated=false;
|
||||
|
||||
GLuint VAO, VBO, extentsBuffer, texinfoBuffer;
|
||||
|
||||
void allocateBuffers(){
|
||||
// Allocate buffers
|
||||
glGenVertexArrays(1, &VAO);
|
||||
glGenBuffers(1, &VBO);
|
||||
glGenBuffers(1, &extentsBuffer);
|
||||
glGenBuffers(1, &texinfoBuffer);
|
||||
|
||||
buffers_allocated=true;
|
||||
}
|
||||
} RenderInfo;
|
||||
|
||||
void init(GLFWwindow* window);
|
||||
void send_chunk_to_gpu(ChunkMeshData* mesh_data, RenderInfo* render_info);
|
||||
void render();
|
||||
void resize_framebuffer(int width, int height);
|
||||
void framebuffer_size_callback(GLFWwindow *window, int width, int height);
|
||||
|
@ -21,8 +38,7 @@ namespace renderer{
|
|||
void saveScreenshot(bool forceFullHD=false);
|
||||
|
||||
Shader* getRenderShader();
|
||||
RenderQueue& getChunksToRender();
|
||||
oneapi::tbb::concurrent_queue<chunkmesher::MeshData*>& getMeshDataQueue();
|
||||
ChunkMeshDataQueue& getMeshDataQueue();
|
||||
|
||||
};
|
||||
|
||||
|
|
|
@ -20,21 +20,11 @@ namespace Chunk
|
|||
this->position = pos;
|
||||
this->setState(CHUNK_STATE_EMPTY, true);
|
||||
this->setBlocks(0, CHUNK_MAX_INDEX, Block::AIR);
|
||||
}
|
||||
|
||||
void Chunk::createBuffers(){
|
||||
glGenVertexArrays(1, &(this->VAO));
|
||||
glGenBuffers(1, &(this->VBO));
|
||||
glGenBuffers(1, &(this->extentsBuffer));
|
||||
glGenBuffers(1, &(this->texinfoBuffer));
|
||||
|
||||
}
|
||||
|
||||
void Chunk::deleteBuffers(){
|
||||
glDeleteBuffers(1, &(this->VBO));
|
||||
glDeleteBuffers(1, &(this->extentsBuffer));
|
||||
glDeleteBuffers(1, &(this->texinfoBuffer));
|
||||
glDeleteVertexArrays(1, &(this->VAO));
|
||||
int16_t i = static_cast<int16_t>(pos.x);
|
||||
int16_t j = static_cast<int16_t>(pos.y);
|
||||
int16_t k = static_cast<int16_t>(pos.z);
|
||||
index = i | (j << 10) | (k << 20);
|
||||
}
|
||||
|
||||
Block Chunk::getBlock(int x, int y, int z)
|
||||
|
|
|
@ -59,10 +59,6 @@ namespace chunkmanager
|
|||
index++;
|
||||
}
|
||||
|
||||
// Also init mesh data queue
|
||||
for(int i = 0; i < 10; i++)
|
||||
chunkmesher::getMeshDataQueue().push(new chunkmesher::MeshData());
|
||||
|
||||
should_run = true;
|
||||
update_thread = std::thread(update);
|
||||
gen_thread = std::thread(generate);
|
||||
|
@ -80,7 +76,7 @@ namespace chunkmanager
|
|||
entry.first->setState(Chunk::CHUNK_STATE_IN_GENERATION_QUEUE, false);
|
||||
}
|
||||
}
|
||||
chunks_to_generate_queue.clear();
|
||||
//chunks_to_generate_queue.clear();
|
||||
}
|
||||
|
||||
// Method for chunk meshing thread(s)
|
||||
|
@ -93,7 +89,7 @@ namespace chunkmanager
|
|||
chunk->setState(Chunk::CHUNK_STATE_IN_MESHING_QUEUE, false);
|
||||
}
|
||||
}
|
||||
chunks_to_mesh_queue.clear();
|
||||
//chunks_to_mesh_queue.clear();
|
||||
}
|
||||
|
||||
void update(){
|
||||
|
@ -177,10 +173,6 @@ namespace chunkmanager
|
|||
}else{
|
||||
mesh++;
|
||||
// If generated & meshed, render
|
||||
/*if(!c->getState(Chunk::CHUNK_STATE_IN_RENDERING_QUEUE)){
|
||||
renderer::getChunksToRender().push(c);
|
||||
c->setState(Chunk::CHUNK_STATE_IN_RENDERING_QUEUE, true);
|
||||
}*/
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -189,7 +181,7 @@ namespace chunkmanager
|
|||
if(c->getState(Chunk::CHUNK_STATE_OUTOFVISION)){
|
||||
// If enough time has passed, set to be deleted
|
||||
if(c->isFree() && glfwGetTime() - c->unload_timer >= UNLOAD_TIMEOUT){
|
||||
chunks_todelete.push(calculateIndex(x,y,z));
|
||||
chunks_todelete.push(c->getIndex());
|
||||
unload++;
|
||||
}
|
||||
}else{
|
||||
|
@ -230,6 +222,13 @@ namespace chunkmanager
|
|||
}
|
||||
|
||||
// uint32_t is fine, since i'm limiting the coordinate to only use up to ten bits (1023). There's actually two spare bits
|
||||
int32_t calculateIndex(Chunk::Chunk* c){
|
||||
return calculateIndex(c->getPosition());
|
||||
}
|
||||
int32_t calculateIndex(glm::vec3 position){
|
||||
return calculateIndex(static_cast<int16_t>(position.x), static_cast<int16_t>(position.y),
|
||||
static_cast<int16_t>(position.z));
|
||||
}
|
||||
int32_t calculateIndex(int16_t i, int16_t j, int16_t k){
|
||||
return i | (j << 10) | (k << 20);
|
||||
}
|
||||
|
|
|
@ -13,13 +13,17 @@
|
|||
|
||||
namespace chunkmesher{
|
||||
|
||||
oneapi::tbb::concurrent_queue<MeshData*> MeshDataQueue;
|
||||
ChunkMeshDataQueue MeshDataQueue;
|
||||
ChunkMeshDataQueue& getMeshDataQueue(){ return MeshDataQueue; }
|
||||
|
||||
oneapi::tbb::concurrent_queue<MeshData*>& getMeshDataQueue(){ return MeshDataQueue; }
|
||||
void init(){
|
||||
for(int i = 0; i < 10; i++)
|
||||
MeshDataQueue.push(new ChunkMeshData{});
|
||||
}
|
||||
|
||||
void mesh(Chunk::Chunk* chunk)
|
||||
{
|
||||
MeshData* mesh_data;
|
||||
ChunkMeshData* mesh_data;
|
||||
if(!MeshDataQueue.try_pop(mesh_data)) return;
|
||||
|
||||
/*
|
||||
|
@ -38,28 +42,13 @@ void mesh(Chunk::Chunk* chunk)
|
|||
*/
|
||||
|
||||
// Cleanup previous data
|
||||
mesh_data->numVertices = 0;
|
||||
mesh_data->chunk = chunk;
|
||||
mesh_data->vertices.clear();
|
||||
mesh_data->extents.clear();
|
||||
mesh_data->texinfo.clear();
|
||||
mesh_data->clear();
|
||||
mesh_data->message_type = ChunkMeshDataType::MESH_UPDATE;
|
||||
mesh_data->index = chunk->getIndex();
|
||||
mesh_data->position = chunk->getPosition();
|
||||
|
||||
// Abort if chunk is empty
|
||||
if(chunk->getState(Chunk::CHUNK_STATE_EMPTY)){
|
||||
chunk->setState(Chunk::CHUNK_STATE_MESHED, true);
|
||||
renderer::getMeshDataQueue().push(mesh_data);
|
||||
return;
|
||||
}
|
||||
|
||||
// convert tree to array since it is easier to work with it
|
||||
std::unique_ptr<Block[]> blocks;
|
||||
int length{0};
|
||||
std::unique_ptr<Block[]> blocks = chunk->getBlocksArray(&length);
|
||||
if(length == 0) {
|
||||
chunk->setState(Chunk::CHUNK_STATE_MESHED, true);
|
||||
renderer::getMeshDataQueue().push(mesh_data);
|
||||
return;
|
||||
}
|
||||
|
||||
int k, l, u, v, w, h, n, j, i;
|
||||
int x[]{0, 0, 0};
|
||||
int q[]{0, 0, 0};
|
||||
|
@ -67,6 +56,14 @@ void mesh(Chunk::Chunk* chunk)
|
|||
int dv[]{0, 0, 0};
|
||||
|
||||
std::array<Block, CHUNK_SIZE * CHUNK_SIZE> mask;
|
||||
|
||||
// Abort if chunk is empty
|
||||
if(chunk->getState(Chunk::CHUNK_STATE_EMPTY)) goto end;
|
||||
|
||||
// convert tree to array since it is easier to work with it
|
||||
blocks = chunk->getBlocksArray(&length);
|
||||
if(length == 0) goto end;
|
||||
|
||||
for (bool backFace = true, b = false; b != backFace; backFace = backFace && b, b = !b)
|
||||
{
|
||||
// iterate over 3 dimensions
|
||||
|
@ -188,14 +185,15 @@ void mesh(Chunk::Chunk* chunk)
|
|||
mesh_data->vertices.push_back(x[1]); //bottomLeft.y
|
||||
mesh_data->vertices.push_back(x[2]); //bottomLeft.z
|
||||
|
||||
// extents, use normals for now
|
||||
// extents
|
||||
mesh_data->extents.push_back(du[0] + dv[0]);
|
||||
mesh_data->extents.push_back(du[1] + dv[1]);
|
||||
mesh_data->extents.push_back(du[2] + dv[2]);
|
||||
|
||||
// texture info (block type, backFace)
|
||||
mesh_data->texinfo.push_back(backFace ? 0.0 : 1.0);
|
||||
mesh_data->texinfo.push_back((int)(mask[n]) - 2);
|
||||
mesh_data->numVertices++;
|
||||
mesh_data->num_vertices++;
|
||||
}
|
||||
|
||||
for (l = 0; l < h; ++l)
|
||||
|
@ -224,49 +222,8 @@ void mesh(Chunk::Chunk* chunk)
|
|||
}
|
||||
}
|
||||
|
||||
end:
|
||||
chunk->setState(Chunk::CHUNK_STATE_MESHED, true);
|
||||
renderer::getMeshDataQueue().push(mesh_data);
|
||||
}
|
||||
|
||||
void sendtogpu(MeshData* mesh_data)
|
||||
{
|
||||
if (mesh_data->numVertices > 0)
|
||||
{
|
||||
if(mesh_data->chunk->VAO == 0) mesh_data->chunk->createBuffers();
|
||||
|
||||
// bind the Vertex Array Object first, then bind and set vertex buffer(s), and then configure vertex attributes(s).
|
||||
glBindVertexArray(mesh_data->chunk->VAO);
|
||||
|
||||
// position attribute
|
||||
glBindBuffer(GL_ARRAY_BUFFER, mesh_data->chunk->VBO);
|
||||
glBufferData(GL_ARRAY_BUFFER, mesh_data->vertices.size() * sizeof(GLfloat), &(mesh_data->vertices[0]), GL_STATIC_DRAW);
|
||||
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void *)0);
|
||||
glEnableVertexAttribArray(0);
|
||||
|
||||
// normal attribute
|
||||
glBindBuffer(GL_ARRAY_BUFFER, mesh_data->chunk->extentsBuffer);
|
||||
glBufferData(GL_ARRAY_BUFFER, mesh_data->extents.size() * sizeof(GLfloat), &(mesh_data->extents[0]), GL_STATIC_DRAW);
|
||||
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void *)(0));
|
||||
glEnableVertexAttribArray(1);
|
||||
|
||||
// texcoords attribute
|
||||
glBindBuffer(GL_ARRAY_BUFFER, mesh_data->chunk->texinfoBuffer);
|
||||
glBufferData(GL_ARRAY_BUFFER, mesh_data->texinfo.size() * sizeof(GLfloat), &(mesh_data->texinfo[0]), GL_STATIC_DRAW);
|
||||
glEnableVertexAttribArray(2);
|
||||
glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 2 * sizeof(float), (void *)0);
|
||||
|
||||
glBindVertexArray(0);
|
||||
|
||||
// save the number of indices of the mesh, it is needed later for drawing
|
||||
mesh_data->chunk->numVertices = (GLuint)(mesh_data->numVertices);
|
||||
|
||||
// once data has been sent to the GPU, it can be cleared from system RAM
|
||||
mesh_data->vertices.clear();
|
||||
mesh_data->extents.clear();
|
||||
mesh_data->texinfo.clear();
|
||||
}
|
||||
|
||||
// mark the chunk mesh has loaded on GPU
|
||||
mesh_data->chunk->setState(Chunk::CHUNK_STATE_MESH_LOADED, true);
|
||||
}
|
||||
};
|
||||
|
|
|
@ -70,8 +70,9 @@ int main()
|
|||
}
|
||||
|
||||
SpaceFilling::initLUT();
|
||||
chunkmanager::init();
|
||||
debug::window::init(window);
|
||||
chunkmanager::init();
|
||||
chunkmesher::init();
|
||||
renderer::init(window);
|
||||
|
||||
while (!glfwWindowShouldClose(window))
|
||||
|
|
|
@ -3,8 +3,7 @@
|
|||
#include <glm/ext.hpp>
|
||||
#include <glm/gtx/string_cast.hpp>
|
||||
|
||||
#include <oneapi/tbb/concurrent_vector.h>
|
||||
#include <oneapi/tbb/concurrent_queue.h>
|
||||
#include <oneapi/tbb/concurrent_hash_map.h>
|
||||
|
||||
#include "chunkmanager.hpp"
|
||||
#include "chunkmesher.hpp"
|
||||
|
@ -15,22 +14,23 @@
|
|||
#include "stb_image_write.h"
|
||||
|
||||
namespace renderer{
|
||||
RenderQueue chunks_torender;
|
||||
oneapi::tbb::concurrent_queue<chunkmesher::MeshData*> MeshDataQueue;
|
||||
typedef oneapi::tbb::concurrent_hash_map<int32_t, RenderInfo*> RenderTable;
|
||||
|
||||
RenderTable ChunksToRender;
|
||||
ChunkMeshDataQueue MeshDataQueue;
|
||||
|
||||
Shader* theShader, *quadShader;
|
||||
GLuint chunkTexture;
|
||||
|
||||
Shader* getRenderShader() { return theShader; }
|
||||
RenderQueue& getChunksToRender(){ return chunks_torender; }
|
||||
oneapi::tbb::concurrent_queue<chunkmesher::MeshData*>& getMeshDataQueue(){ return MeshDataQueue; }
|
||||
|
||||
GLuint renderTexFrameBuffer, renderTex, renderTexDepthBuffer, quadVAO, quadVBO;
|
||||
int screenWidth, screenHeight;
|
||||
|
||||
int crosshair_type{0};
|
||||
bool wireframe{false};
|
||||
|
||||
Shader* getRenderShader() { return theShader; }
|
||||
ChunkMeshDataQueue& getMeshDataQueue(){ return MeshDataQueue; }
|
||||
|
||||
void init(GLFWwindow* window){
|
||||
// Setup rendering
|
||||
// We will render the image to a texture, then display the texture on a quad that fills the
|
||||
|
@ -140,26 +140,49 @@ namespace renderer{
|
|||
theShader->use();
|
||||
theShader->setVec3("viewPos", cameraPos);
|
||||
|
||||
chunkmesher::MeshData* m;
|
||||
// TODO: works but some stuff is rendered wrong (trees floating or inside the terrain,
|
||||
// missing or malformed chunks)
|
||||
ChunkMeshData* m;
|
||||
while(MeshDataQueue.try_pop(m)){
|
||||
chunkmesher::sendtogpu(m);
|
||||
RenderTable::accessor a;
|
||||
RenderInfo* render_info;
|
||||
|
||||
if(ChunksToRender.find(a, m->index)){
|
||||
render_info = a->second;
|
||||
render_info->position = m->position;
|
||||
render_info->num_vertices = m->num_vertices;
|
||||
std::cout << "index collision on " << render_info->index << std::endl;
|
||||
}else{
|
||||
render_info = new RenderInfo();
|
||||
render_info->index = m->index;
|
||||
render_info->position = m->position;
|
||||
render_info->num_vertices = m->num_vertices;
|
||||
|
||||
ChunksToRender.emplace(a, std::make_pair(render_info->index, render_info));
|
||||
}
|
||||
|
||||
send_chunk_to_gpu(m, render_info);
|
||||
chunkmesher::getMeshDataQueue().push(m);
|
||||
}
|
||||
|
||||
Chunk::Chunk* c;
|
||||
while(chunks_torender.try_pop(c)){
|
||||
if(!c->getState(Chunk::CHUNK_STATE_MESH_LOADED)) goto end;
|
||||
// TODO: implement removal of chunks from rendering
|
||||
std::cout << "chunks to render: " << ChunksToRender.size();
|
||||
|
||||
|
||||
// Render the chunks
|
||||
// parallel_for cannot be used since all the rendering needs to happen in a single thread
|
||||
for(RenderTable::iterator i = ChunksToRender.begin(); i != ChunksToRender.end(); i++){
|
||||
RenderInfo* render_info = i->second;
|
||||
|
||||
total++;
|
||||
|
||||
if(c->numVertices > 0)
|
||||
if(render_info->num_vertices > 0)
|
||||
{
|
||||
|
||||
// Increase total vertex count
|
||||
vertices += c->numVertices;
|
||||
vertices += render_info->num_vertices;
|
||||
|
||||
// Perform frustum culling and eventually render
|
||||
glm::vec3 chunk = c->getPosition();
|
||||
glm::vec3 chunk = render_info->position;
|
||||
glm::vec4 chunkW = glm::vec4(chunk.x*static_cast<float>(CHUNK_SIZE), chunk.y*static_cast<float>(CHUNK_SIZE), chunk.z*static_cast<float>(CHUNK_SIZE),1.0);
|
||||
glm::mat4 model = glm::translate(glm::mat4(1.0), ((float)CHUNK_SIZE) * chunk);
|
||||
|
||||
|
@ -185,16 +208,13 @@ namespace renderer{
|
|||
theShader->setMat4("view", theCamera.getView());
|
||||
theShader->setMat4("projection", theCamera.getProjection());
|
||||
|
||||
glBindVertexArray(c->VAO);
|
||||
glDrawArrays(GL_POINTS, 0, c->numVertices);
|
||||
glBindVertexArray(render_info->VAO);
|
||||
glDrawArrays(GL_POINTS, 0, render_info->num_vertices);
|
||||
glBindVertexArray(0);
|
||||
|
||||
toGpu++;
|
||||
}
|
||||
}
|
||||
|
||||
end:
|
||||
c->setState(Chunk::CHUNK_STATE_IN_RENDERING_QUEUE, false);
|
||||
}
|
||||
|
||||
debug::window::set_parameter("render_chunks_total", total);
|
||||
|
@ -223,6 +243,39 @@ end:
|
|||
debug::window::render();
|
||||
}
|
||||
|
||||
void send_chunk_to_gpu(ChunkMeshData* mesh_data, RenderInfo* render_info)
|
||||
{
|
||||
if (render_info->num_vertices > 0)
|
||||
{
|
||||
if(!render_info->buffers_allocated) render_info->allocateBuffers();
|
||||
|
||||
// bind the Vertex Array Object first, then bind and set vertex buffer(s), and then configure vertex attributes(s).
|
||||
glBindVertexArray(render_info->VAO);
|
||||
|
||||
// TODO: change GL_STATIC_DRAW to the one that means "few redraws and further in between"
|
||||
|
||||
// position attribute
|
||||
glBindBuffer(GL_ARRAY_BUFFER, render_info->VBO);
|
||||
glBufferData(GL_ARRAY_BUFFER, mesh_data->vertices.size() * sizeof(GLfloat), &(mesh_data->vertices[0]), GL_STATIC_DRAW);
|
||||
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void *)0);
|
||||
glEnableVertexAttribArray(0);
|
||||
|
||||
// normal attribute
|
||||
glBindBuffer(GL_ARRAY_BUFFER, render_info->extentsBuffer);
|
||||
glBufferData(GL_ARRAY_BUFFER, mesh_data->extents.size() * sizeof(GLfloat), &(mesh_data->extents[0]), GL_STATIC_DRAW);
|
||||
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void *)(0));
|
||||
glEnableVertexAttribArray(1);
|
||||
|
||||
// texcoords attribute
|
||||
glBindBuffer(GL_ARRAY_BUFFER, render_info->texinfoBuffer);
|
||||
glBufferData(GL_ARRAY_BUFFER, mesh_data->texinfo.size() * sizeof(GLfloat), &(mesh_data->texinfo[0]), GL_STATIC_DRAW);
|
||||
glEnableVertexAttribArray(2);
|
||||
glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 2 * sizeof(float), (void *)0);
|
||||
|
||||
glBindVertexArray(0);
|
||||
}
|
||||
}
|
||||
|
||||
void framebuffer_size_callback(GLFWwindow *window, int width, int height){
|
||||
resize_framebuffer(width, height);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue