per-instance frustum culling
parent
aec753e2c4
commit
9bfb5b47fd
|
@ -1493,6 +1493,7 @@ typedef struct model_t {
|
|||
vec3 *meshcenters;
|
||||
aabb *meshbounds;
|
||||
float *meshradii;
|
||||
bool *mesh_visible;
|
||||
int num_tris;
|
||||
handle vao, ibo, vbo, vao_instanced;
|
||||
int* lod_collapse_map;
|
||||
|
|
|
@ -17783,6 +17783,7 @@ typedef struct model_t {
|
|||
vec3 *meshcenters;
|
||||
aabb *meshbounds;
|
||||
float *meshradii;
|
||||
bool *mesh_visible;
|
||||
int num_tris;
|
||||
handle vao, ibo, vbo, vao_instanced;
|
||||
|
||||
|
@ -386398,6 +386399,7 @@ bool model_load_meshes(iqm_t *q, const struct iqmheader *hdr, model_t *m) {
|
|||
m->meshcenters = CALLOC(hdr->num_meshes, sizeof(vec3));
|
||||
m->meshbounds = CALLOC(hdr->num_meshes, sizeof(aabb));
|
||||
m->meshradii = CALLOC(hdr->num_meshes, sizeof(float));
|
||||
m->mesh_visible = CALLOC(hdr->num_meshes, sizeof(bool));
|
||||
|
||||
for(int i = 0; i < (int)hdr->num_meshes; i++) {
|
||||
int invalid = texture_checker().id;
|
||||
|
@ -387195,7 +387197,7 @@ bool model_is_visible(model_t m, int mesh, mat44 model_mat, mat44 proj, mat44 vi
|
|||
mat44 proj_modified;
|
||||
copy44(proj_modified, proj);
|
||||
|
||||
// Increase FOV by 1.5
|
||||
// Increase FOV by GLOBAL_FRUSTUM_FOV_MULTIPLIER
|
||||
float fov_scale = 1.0f / GLOBAL_FRUSTUM_FOV_MULTIPLIER;
|
||||
proj_modified[0] *= fov_scale;
|
||||
proj_modified[5] *= fov_scale;
|
||||
|
@ -387265,13 +387267,13 @@ void model_draw_call(model_t m, int shader, int pass, vec3 cam_pos, mat44 model_
|
|||
|
||||
if (rs_idx > RENDER_PASS_OVERRIDES_BEGIN) {
|
||||
for(int i = 0; i < q->nummeshes; i++) {
|
||||
if (!model_is_visible(m, i, model_mat, proj, view)) continue;
|
||||
if (!m.mesh_visible[i]) continue;
|
||||
array_push(drawcalls, (drawcall_t){i, -1});
|
||||
}
|
||||
} else {
|
||||
if(pass == -1 || pass == RENDER_PASS_OPAQUE) {
|
||||
for(int i = 0; i < q->nummeshes; i++) {
|
||||
if (!model_is_visible(m, i, model_mat, proj, view)) continue;
|
||||
if (!m.mesh_visible[i]) continue;
|
||||
|
||||
// collect opaque drawcalls
|
||||
if (required_rs[i] == RENDER_PASS_OPAQUE) {
|
||||
|
@ -387288,7 +387290,7 @@ void model_draw_call(model_t m, int shader, int pass, vec3 cam_pos, mat44 model_
|
|||
|
||||
if(pass == -1 || pass == RENDER_PASS_TRANSPARENT) {
|
||||
for(int i = 0; i < q->nummeshes; i++) {
|
||||
if (!model_is_visible(m, i, model_mat, proj, view)) continue;
|
||||
if (!m.mesh_visible[i]) continue;
|
||||
|
||||
// collect transparent drawcalls
|
||||
if (required_rs[i] == RENDER_PASS_TRANSPARENT) {
|
||||
|
@ -387364,28 +387366,52 @@ void model_draw_call(model_t m, int shader, int pass, vec3 cam_pos, mat44 model_
|
|||
shader_bind(old_shader);
|
||||
}
|
||||
|
||||
void model_render_instanced_pass(model_t m, mat44 proj, mat44 view, mat44* models, int shader, unsigned count, int pass) {
|
||||
if(!m.iqm) return;
|
||||
iqm_t *q = m.iqm;
|
||||
static mat44 *pass_model_matrices = NULL;
|
||||
|
||||
void model_render_instanced_pass(model_t mdl, mat44 proj, mat44 view, mat44* models, int shader, unsigned count, int pass) {
|
||||
if(!mdl.iqm) return;
|
||||
iqm_t *q = mdl.iqm;
|
||||
|
||||
if (active_shadowmap && active_shadowmap->skip_render) {
|
||||
return;
|
||||
}
|
||||
|
||||
mat44 mv; multiply44x2(mv, view, models[0]);
|
||||
pass_model_matrices = array_resize(pass_model_matrices, count); //@leak
|
||||
memcpy(pass_model_matrices, models, count * sizeof(mat44));
|
||||
memset(mdl.mesh_visible, 0, q->nummeshes * sizeof(bool));
|
||||
|
||||
if( count != m.num_instances ) {
|
||||
m.num_instances = count;
|
||||
m.instanced_matrices = (float*)models;
|
||||
model_set_state(m);
|
||||
for (int i = 0; i < count; i++) {
|
||||
bool any_visible = false;
|
||||
for (int m = 0; m < q->nummeshes; m++) {
|
||||
bool visible = model_is_visible(mdl, m, pass_model_matrices[i], proj, view);
|
||||
mdl.mesh_visible[m] |= visible;
|
||||
any_visible |= visible;
|
||||
}
|
||||
if (!any_visible) {
|
||||
array_erase_fast(pass_model_matrices, i);
|
||||
i--;
|
||||
count--;
|
||||
}
|
||||
}
|
||||
|
||||
if (count == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
mat44 mv; multiply44x2(mv, view, pass_model_matrices[0]);
|
||||
|
||||
if( count != mdl.num_instances ) {
|
||||
mdl.num_instances = count;
|
||||
mdl.instanced_matrices = (float*)pass_model_matrices;
|
||||
model_set_state(mdl);
|
||||
}
|
||||
|
||||
if (model_getpass() > RENDER_PASS_SHADOW_BEGIN && model_getpass() < RENDER_PASS_SHADOW_END) {
|
||||
shader = m.shadow_program;
|
||||
shader = mdl.shadow_program;
|
||||
}
|
||||
|
||||
model_set_uniforms(m, shader > 0 ? shader : m.program, mv, proj, view, models[0]);
|
||||
model_draw_call(m, shader > 0 ? shader : m.program, pass, pos44(view), models[0], proj, view);
|
||||
model_set_uniforms(mdl, shader > 0 ? shader : mdl.program, mv, proj, view, pass_model_matrices[0]);
|
||||
model_draw_call(mdl, shader > 0 ? shader : mdl.program, pass, pos44(view), pass_model_matrices[0], proj, view);
|
||||
}
|
||||
|
||||
void model_render_instanced(model_t m, mat44 proj, mat44 view, mat44* models, int shader, unsigned count) {
|
||||
|
@ -387796,6 +387822,7 @@ void model_destroy(model_t m) {
|
|||
FREE(m.meshcenters);
|
||||
FREE(m.meshbounds);
|
||||
FREE(m.meshradii);
|
||||
FREE(m.mesh_visible);
|
||||
|
||||
iqm_t *q = m.iqm;
|
||||
// if(m.mesh) mesh_destroy(m.mesh);
|
||||
|
|
|
@ -4575,6 +4575,7 @@ bool model_load_meshes(iqm_t *q, const struct iqmheader *hdr, model_t *m) {
|
|||
m->meshcenters = CALLOC(hdr->num_meshes, sizeof(vec3));
|
||||
m->meshbounds = CALLOC(hdr->num_meshes, sizeof(aabb));
|
||||
m->meshradii = CALLOC(hdr->num_meshes, sizeof(float));
|
||||
m->mesh_visible = CALLOC(hdr->num_meshes, sizeof(bool));
|
||||
|
||||
for(int i = 0; i < (int)hdr->num_meshes; i++) {
|
||||
int invalid = texture_checker().id;
|
||||
|
@ -5372,7 +5373,7 @@ bool model_is_visible(model_t m, int mesh, mat44 model_mat, mat44 proj, mat44 vi
|
|||
mat44 proj_modified;
|
||||
copy44(proj_modified, proj);
|
||||
|
||||
// Increase FOV by 1.5
|
||||
// Increase FOV by GLOBAL_FRUSTUM_FOV_MULTIPLIER
|
||||
float fov_scale = 1.0f / GLOBAL_FRUSTUM_FOV_MULTIPLIER;
|
||||
proj_modified[0] *= fov_scale;
|
||||
proj_modified[5] *= fov_scale;
|
||||
|
@ -5442,13 +5443,13 @@ void model_draw_call(model_t m, int shader, int pass, vec3 cam_pos, mat44 model_
|
|||
|
||||
if (rs_idx > RENDER_PASS_OVERRIDES_BEGIN) {
|
||||
for(int i = 0; i < q->nummeshes; i++) {
|
||||
if (!model_is_visible(m, i, model_mat, proj, view)) continue;
|
||||
if (!m.mesh_visible[i]) continue;
|
||||
array_push(drawcalls, (drawcall_t){i, -1});
|
||||
}
|
||||
} else {
|
||||
if(pass == -1 || pass == RENDER_PASS_OPAQUE) {
|
||||
for(int i = 0; i < q->nummeshes; i++) {
|
||||
if (!model_is_visible(m, i, model_mat, proj, view)) continue;
|
||||
if (!m.mesh_visible[i]) continue;
|
||||
|
||||
// collect opaque drawcalls
|
||||
if (required_rs[i] == RENDER_PASS_OPAQUE) {
|
||||
|
@ -5465,7 +5466,7 @@ void model_draw_call(model_t m, int shader, int pass, vec3 cam_pos, mat44 model_
|
|||
|
||||
if(pass == -1 || pass == RENDER_PASS_TRANSPARENT) {
|
||||
for(int i = 0; i < q->nummeshes; i++) {
|
||||
if (!model_is_visible(m, i, model_mat, proj, view)) continue;
|
||||
if (!m.mesh_visible[i]) continue;
|
||||
|
||||
// collect transparent drawcalls
|
||||
if (required_rs[i] == RENDER_PASS_TRANSPARENT) {
|
||||
|
@ -5541,28 +5542,52 @@ void model_draw_call(model_t m, int shader, int pass, vec3 cam_pos, mat44 model_
|
|||
shader_bind(old_shader);
|
||||
}
|
||||
|
||||
void model_render_instanced_pass(model_t m, mat44 proj, mat44 view, mat44* models, int shader, unsigned count, int pass) {
|
||||
if(!m.iqm) return;
|
||||
iqm_t *q = m.iqm;
|
||||
static mat44 *pass_model_matrices = NULL;
|
||||
|
||||
void model_render_instanced_pass(model_t mdl, mat44 proj, mat44 view, mat44* models, int shader, unsigned count, int pass) {
|
||||
if(!mdl.iqm) return;
|
||||
iqm_t *q = mdl.iqm;
|
||||
|
||||
if (active_shadowmap && active_shadowmap->skip_render) {
|
||||
return;
|
||||
}
|
||||
|
||||
mat44 mv; multiply44x2(mv, view, models[0]);
|
||||
pass_model_matrices = array_resize(pass_model_matrices, count); //@leak
|
||||
memcpy(pass_model_matrices, models, count * sizeof(mat44));
|
||||
memset(mdl.mesh_visible, 0, q->nummeshes * sizeof(bool));
|
||||
|
||||
if( count != m.num_instances ) {
|
||||
m.num_instances = count;
|
||||
m.instanced_matrices = (float*)models;
|
||||
model_set_state(m);
|
||||
for (int i = 0; i < count; i++) {
|
||||
bool any_visible = false;
|
||||
for (int m = 0; m < q->nummeshes; m++) {
|
||||
bool visible = model_is_visible(mdl, m, pass_model_matrices[i], proj, view);
|
||||
mdl.mesh_visible[m] |= visible;
|
||||
any_visible |= visible;
|
||||
}
|
||||
if (!any_visible) {
|
||||
array_erase_fast(pass_model_matrices, i);
|
||||
i--;
|
||||
count--;
|
||||
}
|
||||
}
|
||||
|
||||
if (count == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
mat44 mv; multiply44x2(mv, view, pass_model_matrices[0]);
|
||||
|
||||
if( count != mdl.num_instances ) {
|
||||
mdl.num_instances = count;
|
||||
mdl.instanced_matrices = (float*)pass_model_matrices;
|
||||
model_set_state(mdl);
|
||||
}
|
||||
|
||||
if (model_getpass() > RENDER_PASS_SHADOW_BEGIN && model_getpass() < RENDER_PASS_SHADOW_END) {
|
||||
shader = m.shadow_program;
|
||||
shader = mdl.shadow_program;
|
||||
}
|
||||
|
||||
model_set_uniforms(m, shader > 0 ? shader : m.program, mv, proj, view, models[0]);
|
||||
model_draw_call(m, shader > 0 ? shader : m.program, pass, pos44(view), models[0], proj, view);
|
||||
model_set_uniforms(mdl, shader > 0 ? shader : mdl.program, mv, proj, view, pass_model_matrices[0]);
|
||||
model_draw_call(mdl, shader > 0 ? shader : mdl.program, pass, pos44(view), pass_model_matrices[0], proj, view);
|
||||
}
|
||||
|
||||
void model_render_instanced(model_t m, mat44 proj, mat44 view, mat44* models, int shader, unsigned count) {
|
||||
|
@ -5973,6 +5998,7 @@ void model_destroy(model_t m) {
|
|||
FREE(m.meshcenters);
|
||||
FREE(m.meshbounds);
|
||||
FREE(m.meshradii);
|
||||
FREE(m.mesh_visible);
|
||||
|
||||
iqm_t *q = m.iqm;
|
||||
// if(m.mesh) mesh_destroy(m.mesh);
|
||||
|
|
|
@ -815,6 +815,7 @@ typedef struct model_t {
|
|||
vec3 *meshcenters;
|
||||
aabb *meshbounds;
|
||||
float *meshradii;
|
||||
bool *mesh_visible;
|
||||
int num_tris;
|
||||
handle vao, ibo, vbo, vao_instanced;
|
||||
|
||||
|
|
56
engine/v4k.c
56
engine/v4k.c
|
@ -21429,6 +21429,7 @@ bool model_load_meshes(iqm_t *q, const struct iqmheader *hdr, model_t *m) {
|
|||
m->meshcenters = CALLOC(hdr->num_meshes, sizeof(vec3));
|
||||
m->meshbounds = CALLOC(hdr->num_meshes, sizeof(aabb));
|
||||
m->meshradii = CALLOC(hdr->num_meshes, sizeof(float));
|
||||
m->mesh_visible = CALLOC(hdr->num_meshes, sizeof(bool));
|
||||
|
||||
for(int i = 0; i < (int)hdr->num_meshes; i++) {
|
||||
int invalid = texture_checker().id;
|
||||
|
@ -22226,7 +22227,7 @@ bool model_is_visible(model_t m, int mesh, mat44 model_mat, mat44 proj, mat44 vi
|
|||
mat44 proj_modified;
|
||||
copy44(proj_modified, proj);
|
||||
|
||||
// Increase FOV by 1.5
|
||||
// Increase FOV by GLOBAL_FRUSTUM_FOV_MULTIPLIER
|
||||
float fov_scale = 1.0f / GLOBAL_FRUSTUM_FOV_MULTIPLIER;
|
||||
proj_modified[0] *= fov_scale;
|
||||
proj_modified[5] *= fov_scale;
|
||||
|
@ -22296,13 +22297,13 @@ void model_draw_call(model_t m, int shader, int pass, vec3 cam_pos, mat44 model_
|
|||
|
||||
if (rs_idx > RENDER_PASS_OVERRIDES_BEGIN) {
|
||||
for(int i = 0; i < q->nummeshes; i++) {
|
||||
if (!model_is_visible(m, i, model_mat, proj, view)) continue;
|
||||
if (!m.mesh_visible[i]) continue;
|
||||
array_push(drawcalls, (drawcall_t){i, -1});
|
||||
}
|
||||
} else {
|
||||
if(pass == -1 || pass == RENDER_PASS_OPAQUE) {
|
||||
for(int i = 0; i < q->nummeshes; i++) {
|
||||
if (!model_is_visible(m, i, model_mat, proj, view)) continue;
|
||||
if (!m.mesh_visible[i]) continue;
|
||||
|
||||
// collect opaque drawcalls
|
||||
if (required_rs[i] == RENDER_PASS_OPAQUE) {
|
||||
|
@ -22319,7 +22320,7 @@ void model_draw_call(model_t m, int shader, int pass, vec3 cam_pos, mat44 model_
|
|||
|
||||
if(pass == -1 || pass == RENDER_PASS_TRANSPARENT) {
|
||||
for(int i = 0; i < q->nummeshes; i++) {
|
||||
if (!model_is_visible(m, i, model_mat, proj, view)) continue;
|
||||
if (!m.mesh_visible[i]) continue;
|
||||
|
||||
// collect transparent drawcalls
|
||||
if (required_rs[i] == RENDER_PASS_TRANSPARENT) {
|
||||
|
@ -22395,28 +22396,52 @@ void model_draw_call(model_t m, int shader, int pass, vec3 cam_pos, mat44 model_
|
|||
shader_bind(old_shader);
|
||||
}
|
||||
|
||||
void model_render_instanced_pass(model_t m, mat44 proj, mat44 view, mat44* models, int shader, unsigned count, int pass) {
|
||||
if(!m.iqm) return;
|
||||
iqm_t *q = m.iqm;
|
||||
static mat44 *pass_model_matrices = NULL;
|
||||
|
||||
void model_render_instanced_pass(model_t mdl, mat44 proj, mat44 view, mat44* models, int shader, unsigned count, int pass) {
|
||||
if(!mdl.iqm) return;
|
||||
iqm_t *q = mdl.iqm;
|
||||
|
||||
if (active_shadowmap && active_shadowmap->skip_render) {
|
||||
return;
|
||||
}
|
||||
|
||||
mat44 mv; multiply44x2(mv, view, models[0]);
|
||||
pass_model_matrices = array_resize(pass_model_matrices, count); //@leak
|
||||
memcpy(pass_model_matrices, models, count * sizeof(mat44));
|
||||
memset(mdl.mesh_visible, 0, q->nummeshes * sizeof(bool));
|
||||
|
||||
if( count != m.num_instances ) {
|
||||
m.num_instances = count;
|
||||
m.instanced_matrices = (float*)models;
|
||||
model_set_state(m);
|
||||
for (int i = 0; i < count; i++) {
|
||||
bool any_visible = false;
|
||||
for (int m = 0; m < q->nummeshes; m++) {
|
||||
bool visible = model_is_visible(mdl, m, pass_model_matrices[i], proj, view);
|
||||
mdl.mesh_visible[m] |= visible;
|
||||
any_visible |= visible;
|
||||
}
|
||||
if (!any_visible) {
|
||||
array_erase_fast(pass_model_matrices, i);
|
||||
i--;
|
||||
count--;
|
||||
}
|
||||
}
|
||||
|
||||
if (count == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
mat44 mv; multiply44x2(mv, view, pass_model_matrices[0]);
|
||||
|
||||
if( count != mdl.num_instances ) {
|
||||
mdl.num_instances = count;
|
||||
mdl.instanced_matrices = (float*)pass_model_matrices;
|
||||
model_set_state(mdl);
|
||||
}
|
||||
|
||||
if (model_getpass() > RENDER_PASS_SHADOW_BEGIN && model_getpass() < RENDER_PASS_SHADOW_END) {
|
||||
shader = m.shadow_program;
|
||||
shader = mdl.shadow_program;
|
||||
}
|
||||
|
||||
model_set_uniforms(m, shader > 0 ? shader : m.program, mv, proj, view, models[0]);
|
||||
model_draw_call(m, shader > 0 ? shader : m.program, pass, pos44(view), models[0], proj, view);
|
||||
model_set_uniforms(mdl, shader > 0 ? shader : mdl.program, mv, proj, view, pass_model_matrices[0]);
|
||||
model_draw_call(mdl, shader > 0 ? shader : mdl.program, pass, pos44(view), pass_model_matrices[0], proj, view);
|
||||
}
|
||||
|
||||
void model_render_instanced(model_t m, mat44 proj, mat44 view, mat44* models, int shader, unsigned count) {
|
||||
|
@ -22827,6 +22852,7 @@ void model_destroy(model_t m) {
|
|||
FREE(m.meshcenters);
|
||||
FREE(m.meshbounds);
|
||||
FREE(m.meshradii);
|
||||
FREE(m.mesh_visible);
|
||||
|
||||
iqm_t *q = m.iqm;
|
||||
// if(m.mesh) mesh_destroy(m.mesh);
|
||||
|
|
|
@ -3850,6 +3850,7 @@ typedef struct model_t {
|
|||
vec3 *meshcenters;
|
||||
aabb *meshbounds;
|
||||
float *meshradii;
|
||||
bool *mesh_visible;
|
||||
int num_tris;
|
||||
handle vao, ibo, vbo, vao_instanced;
|
||||
|
||||
|
|
Loading…
Reference in New Issue