167 lines
5.7 KiB
C
167 lines
5.7 KiB
C
#include "voxel.h"
|
|
|
|
static const float quad_vertices[] = {
|
|
0.0f, 0.0f, 0.0f,
|
|
0.5f, 0.0f, 0.0f,
|
|
0.0f, 0.5f, 0.0f,
|
|
0.5f, 0.5f, 0.0f,
|
|
};
|
|
|
|
static const uint32_t quad_indices[] = {
|
|
0, 1, 2, 3,
|
|
};
|
|
|
|
uint32_t voxel_mesh_pack_face(uint8_t face, uint8_t x, uint8_t y, uint8_t z, uint8_t height, uint8_t width) {
|
|
return (((face & 0x7F) << 25) | // 7 bits for face (0-127) for marching cube
|
|
((width & 0x1F) << 20) | // 5 bits for width (0-31)
|
|
((height & 0x1F) << 15) | // 5 bits for height (0-31)
|
|
((z & 0x1F) << 10) | // 5 bits for Z (0-31)
|
|
((y & 0x1F) << 5) | // 5 bits for Y (0-31)
|
|
(x & 0x1F)); // 5 bits for X (0-31)
|
|
}
|
|
|
|
uint64_t voxel_mesh_pack_tex(uint16_t tex_id, uint16_t material, uint32_t data) {
|
|
return ((tex_id << 48) | (material << 32) | data);
|
|
}
|
|
|
|
void voxel_update_render_data(voxel_chunk_render_queue *rqueue) {
|
|
if (rqueue->draw_cmd) {
|
|
free(rqueue->draw_cmd);
|
|
}
|
|
rqueue->draw_cmd = calloc(rqueue->chunk_count, sizeof(DrawElementsIndirectCommand));
|
|
assert(rqueue->draw_cmd);
|
|
|
|
if (rqueue->global_data) {
|
|
free(rqueue->global_data);
|
|
}
|
|
rqueue->global_data = calloc(rqueue->face_count, sizeof(uint64_t));
|
|
assert(rqueue->global_data);
|
|
|
|
uint32_t offset = 0;
|
|
|
|
for (int i = 0; i < rqueue->chunk_count; i++) {
|
|
rqueue->draw_cmd[i] = (DrawElementsIndirectCommand){
|
|
.count = 4,
|
|
.instanceCount = rqueue->meshes[i].face_count,
|
|
.firstIndex = 0,
|
|
.baseVertex = 0,
|
|
.baseInstance = rqueue->face_count,
|
|
};
|
|
memcpy(rqueue->global_data[offset], rqueue->meshes[i].faces_buffer, sizeof(uint64_t) * rqueue->meshes[i].face_count);
|
|
offset += rqueue->meshes[i].face_count;
|
|
rqueue->face_count = offset;
|
|
}
|
|
|
|
glBindBuffer(GL_DRAW_INDIRECT_BUFFER, rqueue->ibo);
|
|
glBufferData(GL_DRAW_INDIRECT_BUFFER, rqueue->chunk_count * sizeof(DrawElementsIndirectCommand), rqueue->draw_cmd, GL_DYNAMIC_DRAW);
|
|
|
|
glBindBuffer(GL_ARRAY_BUFFER, rqueue->global_vbo);
|
|
glBufferData(GL_ARRAY_BUFFER, sizeof(uint64_t) * rqueue->face_count, rqueue->global_data, GL_DYNAMIC_DRAW);
|
|
|
|
glBindBuffer(GL_DRAW_INDIRECT_BUFFER, 0);
|
|
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
|
}
|
|
|
|
//need to sort chunk for transparency,
|
|
//also need to not upload face that are oposite to player pos from chunk relative pos (unless player is in chunk)
|
|
voxel_chunk_render_queue* voxel_render_queue_create() {
|
|
voxel_chunk_render_queue* rqueue = malloc(sizeof(voxel_chunk_render_queue));
|
|
assert(rqueue);
|
|
|
|
rqueue->ssbo_data = 0x00;
|
|
rqueue->meshes = 0x00;
|
|
rqueue->global_data = 0x00;
|
|
rqueue->face_count = 0;
|
|
rqueue->chunk_count = 0;
|
|
rqueue->draw_cmd = 0;
|
|
|
|
rqueue->vao = rlLoadVertexArray();
|
|
rlEnableVertexArray(rqueue->vao);
|
|
|
|
rqueue->vbo = rlLoadVertexBuffer(quad_vertices, sizeof(quad_vertices), false);
|
|
rlSetVertexAttribute(0, 3, RL_FLOAT, false, 3 *sizeof(float), 0);
|
|
rlEnableVertexAttribute(0);
|
|
|
|
rqueue->ebo = rlLoadVertexBufferElement(quad_indices, sizeof(quad_indices), false);
|
|
|
|
rqueue->ibo = rlLoadVertexBuffer(rqueue->draw_cmd, rqueue->chunk_count, true);
|
|
|
|
rqueue->global_vbo = rlLoadVertexBuffer(rqueue->global_data, rqueue->face_count, true);
|
|
|
|
rlSetVertexAttribute(1, 1, RL_FLOAT, false, sizeof(int64_t), 0);
|
|
rlEnableVertexAttribute(1);
|
|
rlSetVertexAttributeDivisor(1, 1);
|
|
|
|
rlDisableVertexArray();
|
|
// rlEnableShader();
|
|
|
|
glGenBuffers(1, &rqueue->ssbo);
|
|
assert(rqueue->ssbo);
|
|
glBindBuffer(GL_SHADER_STORAGE_BUFFER, rqueue->ssbo);
|
|
glBufferData(GL_SHADER_STORAGE_BUFFER, rqueue->chunk_count, rqueue->ssbo_data, RL_STREAM_COPY);
|
|
glClearBufferData(GL_SHADER_STORAGE_BUFFER, GL_R8UI, GL_RED_INTEGER, GL_UNSIGNED_BYTE, NULL);// Clear buffer data to 0
|
|
|
|
glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0);
|
|
|
|
return (rqueue);
|
|
}
|
|
|
|
bool voxel_render_queue_update(voxel_chunk_render_queue* rqueue) {
|
|
//load all face if update into rqueue->ibo_data
|
|
|
|
rlEnableVertexArray(rqueue->vao);
|
|
|
|
rlUpdateVertexBuffer(rqueue->global_vbo, rqueue->global_data, sizeof(uint64_t) * rqueue->face_count, 0);
|
|
|
|
rlDisableVertexArray();
|
|
|
|
glBindBuffer(GL_SHADER_STORAGE_BUFFER, rqueue->ssbo);
|
|
glBufferData(GL_SHADER_STORAGE_BUFFER, rqueue->chunk_count, rqueue->ssbo_data, RL_STREAM_COPY);
|
|
glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0);
|
|
|
|
}
|
|
|
|
voxel_mesh* voxel_mesh_create(void) {
|
|
voxel_mesh* mesh = malloc(sizeof(voxel_mesh));
|
|
assert(mesh);
|
|
|
|
mesh->face_count = 0;
|
|
mesh->faces_buffer = 0;
|
|
return (mesh);
|
|
}
|
|
|
|
void voxel_render_chunks(const voxel_chunk_render_queue rqueue, Shader shader, Matrix transform) {
|
|
Matrix matModel = MatrixIdentity();
|
|
Matrix matView = rlGetMatrixModelview();
|
|
Matrix matProjection = rlGetMatrixProjection();
|
|
rlEnableShader(shader.id ); {
|
|
matModel = MatrixMultiply(transform, rlGetMatrixTransform());
|
|
if (shader.locs[SHADER_LOC_MATRIX_MODEL] != -1) {
|
|
rlSetUniformMatrix(shader.locs[SHADER_LOC_MATRIX_MODEL], matModel);
|
|
}
|
|
if (shader.locs[SHADER_LOC_MATRIX_VIEW] != -1) {
|
|
rlSetUniformMatrix(shader.locs[SHADER_LOC_MATRIX_VIEW], matView);
|
|
}
|
|
if (shader.locs[SHADER_LOC_MATRIX_PROJECTION] != -1) {
|
|
rlSetUniformMatrix(shader.locs[SHADER_LOC_MATRIX_PROJECTION], matProjection);
|
|
}
|
|
if (shader.locs[SHADER_LOC_MATRIX_NORMAL] != -1) {
|
|
rlSetUniformMatrix(shader.locs[SHADER_LOC_MATRIX_NORMAL], MatrixTranspose(MatrixInvert(matModel)));
|
|
}
|
|
rlSetUniformMatrix(shader.locs[SHADER_LOC_MATRIX_MVP], MatrixMultiply(MatrixMultiply(matModel, matView), matProjection));
|
|
// rlBindShaderBuffer();
|
|
|
|
// rlBindShaderBuffer();
|
|
glBindBuffer(GL_SHADER_STORAGE_BUFFER, rqueue.ssbo);
|
|
glMultiDrawElementsIndirect(GL_TRIANGLE_STRIP, GL_UNSIGNED_INT, rqueue.draw_cmd, rqueue.chunk_count, 0);
|
|
// glMultiDrawElements(,);
|
|
// for (int i = 0; i < 0; i++) {
|
|
// rlEnableVertexArray(rqueue.meshes[i].vao);
|
|
// glDrawElementsInstanced(GL_TRIANGLE_STRIP, 4, GL_UNSIGNED_INT, 0, rqueue.meshes[i].face_count);
|
|
// }
|
|
// rlDisableVertexArray();
|
|
} rlDisableShader();
|
|
rlSetMatrixModelview(matView);
|
|
rlSetMatrixProjection(matProjection);
|
|
}
|