2025-05-31 00:27:25 +02:00

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);
}