optimize demo3d bsp render by sorting faces based on material
This commit is contained in:
parent
cf43538518
commit
728b393a8e
3 changed files with 109 additions and 78 deletions
|
|
@ -104,10 +104,18 @@ demo3d_bsp_render_state* demo3d_bsp_render_state_create(u32 num_faces) {
|
||||||
pxl8_free(state);
|
pxl8_free(state);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
state->visible_faces = pxl8_malloc(num_faces * sizeof(u32));
|
||||||
|
if (!state->visible_faces) {
|
||||||
|
pxl8_free(state->render_face_flags);
|
||||||
|
pxl8_free(state);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
state->mesh = pxl8_mesh_create(8192, 16384);
|
state->mesh = pxl8_mesh_create(8192, 16384);
|
||||||
if (!state->mesh) {
|
if (!state->mesh) {
|
||||||
|
pxl8_free(state->visible_faces);
|
||||||
pxl8_free(state->render_face_flags);
|
pxl8_free(state->render_face_flags);
|
||||||
pxl8_free(state);
|
pxl8_free(state);
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
@ -120,6 +128,9 @@ void demo3d_bsp_render_state_destroy(demo3d_bsp_render_state* state) {
|
||||||
if (!state) return;
|
if (!state) return;
|
||||||
pxl8_free(state->materials);
|
pxl8_free(state->materials);
|
||||||
pxl8_mesh_destroy(state->mesh);
|
pxl8_mesh_destroy(state->mesh);
|
||||||
|
pxl8_free(state->mat_write_pos);
|
||||||
|
pxl8_free(state->mat_offsets);
|
||||||
|
pxl8_free(state->visible_faces);
|
||||||
pxl8_free(state->render_face_flags);
|
pxl8_free(state->render_face_flags);
|
||||||
pxl8_free(state);
|
pxl8_free(state);
|
||||||
}
|
}
|
||||||
|
|
@ -140,18 +151,38 @@ void demo3d_bsp_render(pxl8_gfx* gfx, const demo3d_bsp* bsp,
|
||||||
u8 ambient = pxl8_gfx_get_ambient(gfx);
|
u8 ambient = pxl8_gfx_get_ambient(gfx);
|
||||||
pxl8_mat4 identity = pxl8_mat4_identity();
|
pxl8_mat4 identity = pxl8_mat4_identity();
|
||||||
|
|
||||||
u8 mat_has_faces[256] = {0};
|
u32 mat_count = state->num_materials;
|
||||||
for (u32 face_id = 0; face_id < bsp->num_faces; face_id++) {
|
if (!state->mat_offsets || !state->mat_write_pos) return;
|
||||||
|
|
||||||
|
memset(state->mat_offsets, 0, (mat_count + 1) * sizeof(u32));
|
||||||
|
|
||||||
|
for (u32 face_id = 0; face_id < bsp->num_faces && face_id < state->num_faces; face_id++) {
|
||||||
if (!state->render_face_flags[face_id]) continue;
|
if (!state->render_face_flags[face_id]) continue;
|
||||||
u16 mid = bsp->faces[face_id].material_id;
|
u16 mid = bsp->faces[face_id].material_id;
|
||||||
if (mid < state->num_materials) mat_has_faces[mid] = 1;
|
if (mid < mat_count) state->mat_offsets[mid]++;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (u32 mat = 0; mat < state->num_materials; mat++) {
|
u32 running = 0;
|
||||||
if (!mat_has_faces[mat]) continue;
|
for (u32 i = 0; i < mat_count; i++) {
|
||||||
for (u32 face_id = 0; face_id < bsp->num_faces; face_id++) {
|
u32 c = state->mat_offsets[i];
|
||||||
if (!state->render_face_flags[face_id]) continue;
|
state->mat_offsets[i] = running;
|
||||||
if (bsp->faces[face_id].material_id != mat) continue;
|
running += c;
|
||||||
|
}
|
||||||
|
state->mat_offsets[mat_count] = running;
|
||||||
|
|
||||||
|
memcpy(state->mat_write_pos, state->mat_offsets, mat_count * sizeof(u32));
|
||||||
|
|
||||||
|
for (u32 face_id = 0; face_id < bsp->num_faces && face_id < state->num_faces; face_id++) {
|
||||||
|
if (!state->render_face_flags[face_id]) continue;
|
||||||
|
u16 mid = bsp->faces[face_id].material_id;
|
||||||
|
if (mid < mat_count) {
|
||||||
|
state->visible_faces[state->mat_write_pos[mid]++] = face_id;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (u32 mat = 0; mat < mat_count; mat++) {
|
||||||
|
for (u32 i = state->mat_offsets[mat]; i < state->mat_offsets[mat + 1]; i++) {
|
||||||
|
u32 face_id = state->visible_faces[i];
|
||||||
if (!face_in_frustum(bsp, face_id, frustum)) continue;
|
if (!face_in_frustum(bsp, face_id, frustum)) continue;
|
||||||
collect_face_to_mesh(bsp, state, face_id, mesh, ambient);
|
collect_face_to_mesh(bsp, state, face_id, mesh, ambient);
|
||||||
}
|
}
|
||||||
|
|
@ -184,6 +215,9 @@ void demo3d_bsp_set_material(demo3d_bsp_render_state* state, u16 material_id, co
|
||||||
|
|
||||||
state->materials = new_materials;
|
state->materials = new_materials;
|
||||||
state->num_materials = new_count;
|
state->num_materials = new_count;
|
||||||
|
|
||||||
|
state->mat_offsets = pxl8_realloc(state->mat_offsets, (new_count + 1) * sizeof(u32));
|
||||||
|
state->mat_write_pos = pxl8_realloc(state->mat_write_pos, new_count * sizeof(u32));
|
||||||
}
|
}
|
||||||
|
|
||||||
pxl8_vec3 u_axis = state->materials[material_id].u_axis;
|
pxl8_vec3 u_axis = state->materials[material_id].u_axis;
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,9 @@ typedef struct demo3d_bsp_render_state {
|
||||||
pxl8_gfx_material* materials;
|
pxl8_gfx_material* materials;
|
||||||
pxl8_mesh* mesh;
|
pxl8_mesh* mesh;
|
||||||
u8* render_face_flags;
|
u8* render_face_flags;
|
||||||
|
u32* visible_faces;
|
||||||
|
u32* mat_offsets;
|
||||||
|
u32* mat_write_pos;
|
||||||
u32 num_materials;
|
u32 num_materials;
|
||||||
u32 num_faces;
|
u32 num_faces;
|
||||||
bool exterior;
|
bool exterior;
|
||||||
|
|
|
||||||
|
|
@ -64,12 +64,7 @@ void pxl8_particles_destroy(pxl8_particles* ps) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void pxl8_particles_clear(pxl8_particles* ps) {
|
void pxl8_particles_clear(pxl8_particles* ps) {
|
||||||
if (!ps || !ps->particles) return;
|
if (!ps) return;
|
||||||
|
|
||||||
for (u32 i = 0; i < ps->max_count; i++) {
|
|
||||||
ps->particles[i].life = 0;
|
|
||||||
ps->particles[i].flags = 0;
|
|
||||||
}
|
|
||||||
ps->alive_count = 0;
|
ps->alive_count = 0;
|
||||||
ps->spawn_timer = 0;
|
ps->spawn_timer = 0;
|
||||||
}
|
}
|
||||||
|
|
@ -78,63 +73,56 @@ void pxl8_particles_emit(pxl8_particles* ps, u32 count) {
|
||||||
if (!ps || !ps->particles) return;
|
if (!ps || !ps->particles) return;
|
||||||
|
|
||||||
for (u32 i = 0; i < count && ps->alive_count < ps->max_count; i++) {
|
for (u32 i = 0; i < count && ps->alive_count < ps->max_count; i++) {
|
||||||
for (u32 j = 0; j < ps->max_count; j++) {
|
pxl8_particle* p = &ps->particles[ps->alive_count];
|
||||||
if (ps->particles[j].life <= 0) {
|
|
||||||
pxl8_particle* p = &ps->particles[j];
|
|
||||||
|
|
||||||
f32 life = ps->life_min + pxl8_rng_f32(ps->rng) * (ps->life_max - ps->life_min);
|
f32 life = ps->life_min + pxl8_rng_f32(ps->rng) * (ps->life_max - ps->life_min);
|
||||||
p->life = life;
|
p->life = life;
|
||||||
p->max_life = life;
|
p->max_life = life;
|
||||||
|
|
||||||
p->x = ps->x + (pxl8_rng_f32(ps->rng) - 0.5f) * ps->spread_x;
|
p->x = ps->x + (pxl8_rng_f32(ps->rng) - 0.5f) * ps->spread_x;
|
||||||
p->y = ps->y + (pxl8_rng_f32(ps->rng) - 0.5f) * ps->spread_y;
|
p->y = ps->y + (pxl8_rng_f32(ps->rng) - 0.5f) * ps->spread_y;
|
||||||
p->z = 0;
|
p->z = 0;
|
||||||
|
|
||||||
p->vx = ps->vx_min + pxl8_rng_f32(ps->rng) * (ps->vx_max - ps->vx_min);
|
p->vx = ps->vx_min + pxl8_rng_f32(ps->rng) * (ps->vx_max - ps->vx_min);
|
||||||
p->vy = ps->vy_min + pxl8_rng_f32(ps->rng) * (ps->vy_max - ps->vy_min);
|
p->vy = ps->vy_min + pxl8_rng_f32(ps->rng) * (ps->vy_max - ps->vy_min);
|
||||||
p->vz = 0;
|
p->vz = 0;
|
||||||
|
|
||||||
p->ax = ps->gravity_x;
|
p->ax = ps->gravity_x;
|
||||||
p->ay = ps->gravity_y;
|
p->ay = ps->gravity_y;
|
||||||
p->az = 0;
|
p->az = 0;
|
||||||
|
|
||||||
u8 ramp_range = ps->color_max - ps->color_min + 1;
|
u8 ramp_range = ps->color_max - ps->color_min + 1;
|
||||||
u8 ramp_pos = ps->color_min + (pxl8_rng_next(ps->rng) % ramp_range);
|
u8 ramp_pos = ps->color_min + (pxl8_rng_next(ps->rng) % ramp_range);
|
||||||
u8 color = ps->palette
|
u8 color = ps->palette
|
||||||
? pxl8_palette_ramp_index(ps->palette, ramp_pos)
|
? pxl8_palette_ramp_index(ps->palette, ramp_pos)
|
||||||
: ramp_pos;
|
: ramp_pos;
|
||||||
p->color = p->start_color = p->end_color = color;
|
p->color = p->start_color = p->end_color = color;
|
||||||
|
|
||||||
p->size = ps->size_min + pxl8_rng_f32(ps->rng) * (ps->size_max - ps->size_min);
|
p->size = ps->size_min + pxl8_rng_f32(ps->rng) * (ps->size_max - ps->size_min);
|
||||||
p->angle = 0;
|
p->angle = 0;
|
||||||
p->spin = 0;
|
p->spin = 0;
|
||||||
p->flags = 1;
|
p->flags = 1;
|
||||||
|
|
||||||
if (ps->spawn_fn) {
|
if (ps->spawn_fn) {
|
||||||
ps->spawn_fn(ps, p);
|
ps->spawn_fn(ps, p);
|
||||||
}
|
|
||||||
|
|
||||||
ps->alive_count++;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ps->alive_count++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void pxl8_particles_render(pxl8_particles* ps, pxl8_gfx* gfx) {
|
void pxl8_particles_render(pxl8_particles* ps, pxl8_gfx* gfx) {
|
||||||
if (!ps || !ps->particles || !gfx) return;
|
if (!ps || !ps->particles || !gfx) return;
|
||||||
|
|
||||||
for (u32 i = 0; i < ps->max_count; i++) {
|
for (u32 i = 0; i < ps->alive_count; i++) {
|
||||||
pxl8_particle* p = &ps->particles[i];
|
pxl8_particle* p = &ps->particles[i];
|
||||||
if (p->life > 0 && p->flags) {
|
if (ps->render_fn) {
|
||||||
if (ps->render_fn) {
|
ps->render_fn(gfx, p, ps->userdata);
|
||||||
ps->render_fn(gfx, p, ps->userdata);
|
} else {
|
||||||
} else {
|
i32 x = (i32)p->x;
|
||||||
i32 x = (i32)p->x;
|
i32 y = (i32)p->y;
|
||||||
i32 y = (i32)p->y;
|
if (x >= 0 && x < pxl8_gfx_get_width(gfx) && y >= 0 && y < pxl8_gfx_get_height(gfx)) {
|
||||||
if (x >= 0 && x < pxl8_gfx_get_width(gfx) && y >= 0 && y < pxl8_gfx_get_height(gfx)) {
|
pxl8_2d_pixel(gfx, x, y, p->color);
|
||||||
pxl8_2d_pixel(gfx, x, y, p->color);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -150,38 +138,44 @@ void pxl8_particles_update(pxl8_particles* ps, f32 dt) {
|
||||||
if (max_spawns_per_frame < 1) max_spawns_per_frame = 1;
|
if (max_spawns_per_frame < 1) max_spawns_per_frame = 1;
|
||||||
u32 spawn_count = 0;
|
u32 spawn_count = 0;
|
||||||
while (ps->spawn_timer >= spawn_interval && spawn_count < max_spawns_per_frame) {
|
while (ps->spawn_timer >= spawn_interval && spawn_count < max_spawns_per_frame) {
|
||||||
pxl8_particles_emit(ps, 1);
|
|
||||||
ps->spawn_timer -= spawn_interval;
|
ps->spawn_timer -= spawn_interval;
|
||||||
spawn_count++;
|
spawn_count++;
|
||||||
}
|
}
|
||||||
|
if (spawn_count > 0) {
|
||||||
|
pxl8_particles_emit(ps, spawn_count);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (u32 i = 0; i < ps->max_count; i++) {
|
u32 i = 0;
|
||||||
|
while (i < ps->alive_count) {
|
||||||
pxl8_particle* p = &ps->particles[i];
|
pxl8_particle* p = &ps->particles[i];
|
||||||
if (p->life > 0) {
|
|
||||||
if (ps->update_fn) {
|
|
||||||
ps->update_fn(p, dt, ps->userdata);
|
|
||||||
} else {
|
|
||||||
p->vx += p->ax * dt;
|
|
||||||
p->vy += p->ay * dt;
|
|
||||||
p->vz += p->az * dt;
|
|
||||||
|
|
||||||
p->vx *= ps->drag;
|
if (ps->update_fn) {
|
||||||
p->vy *= ps->drag;
|
ps->update_fn(p, dt, ps->userdata);
|
||||||
p->vz *= ps->drag;
|
} else {
|
||||||
|
p->vx += p->ax * dt;
|
||||||
|
p->vy += p->ay * dt;
|
||||||
|
p->vz += p->az * dt;
|
||||||
|
|
||||||
p->x += p->vx * dt;
|
p->vx *= ps->drag;
|
||||||
p->y += p->vy * dt;
|
p->vy *= ps->drag;
|
||||||
p->z += p->vz * dt;
|
p->vz *= ps->drag;
|
||||||
|
|
||||||
p->angle += p->spin * dt;
|
p->x += p->vx * dt;
|
||||||
}
|
p->y += p->vy * dt;
|
||||||
|
p->z += p->vz * dt;
|
||||||
p->life -= dt / p->max_life;
|
|
||||||
if (p->life <= 0) {
|
p->angle += p->spin * dt;
|
||||||
p->flags = 0;
|
}
|
||||||
ps->alive_count--;
|
|
||||||
|
p->life -= dt / p->max_life;
|
||||||
|
if (p->life <= 0) {
|
||||||
|
ps->alive_count--;
|
||||||
|
if (i < ps->alive_count) {
|
||||||
|
ps->particles[i] = ps->particles[ps->alive_count];
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
i++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue