implement global frustum culling
parent
dfcb0877ca
commit
aec753e2c4
|
@ -1195,6 +1195,7 @@ typedef struct shadowmap_t {
|
||||||
int cascade_index;
|
int cascade_index;
|
||||||
unsigned shadow_technique;
|
unsigned shadow_technique;
|
||||||
float cascade_splits[4];
|
float cascade_splits[4];
|
||||||
|
frustum shadow_frustum;
|
||||||
bool skip_render;
|
bool skip_render;
|
||||||
int lights_pushed;
|
int lights_pushed;
|
||||||
handle fbo;
|
handle fbo;
|
||||||
|
@ -1641,6 +1642,7 @@ typedef struct camera_t {
|
||||||
float yaw, pitch, roll;
|
float yaw, pitch, roll;
|
||||||
float speed, fov;
|
float speed, fov;
|
||||||
float near_clip, far_clip;
|
float near_clip, far_clip;
|
||||||
|
float frustum_fov_multiplier;
|
||||||
float move_friction, move_damping;
|
float move_friction, move_damping;
|
||||||
float look_friction, look_damping;
|
float look_friction, look_damping;
|
||||||
vec3 last_look; vec3 last_move;
|
vec3 last_look; vec3 last_move;
|
||||||
|
@ -1657,6 +1659,7 @@ typedef struct camera_t {
|
||||||
void camera_orbit(camera_t *cam, float yaw, float pitch, float inc_distance);
|
void camera_orbit(camera_t *cam, float yaw, float pitch, float inc_distance);
|
||||||
void camera_lookat(camera_t *cam, vec3 target);
|
void camera_lookat(camera_t *cam, vec3 target);
|
||||||
void camera_enable(camera_t *cam);
|
void camera_enable(camera_t *cam);
|
||||||
|
frustum camera_frustum_build(camera_t *cam);
|
||||||
camera_t *camera_get_active();
|
camera_t *camera_get_active();
|
||||||
int ui_camera(camera_t *cam);
|
int ui_camera(camera_t *cam);
|
||||||
void ddraw_camera(camera_t *cam);
|
void ddraw_camera(camera_t *cam);
|
||||||
|
|
|
@ -19,7 +19,7 @@ const char *OBJ_MDLS[] = {
|
||||||
|
|
||||||
int main(int argc, char** argv) {
|
int main(int argc, char** argv) {
|
||||||
window_create(85, WINDOW_MSAA8);
|
window_create(85, WINDOW_MSAA8);
|
||||||
// window_fps_unlock();
|
window_fps_unlock();
|
||||||
|
|
||||||
camera_t cam = camera(); {
|
camera_t cam = camera(); {
|
||||||
cam.position = vec3(0, 7.5, 15);
|
cam.position = vec3(0, 7.5, 15);
|
||||||
|
@ -103,7 +103,7 @@ int main(int argc, char** argv) {
|
||||||
if( active ) cam.speed = clampf(cam.speed + input_diff(MOUSE_W) / 10, 0.05f, 5.0f);
|
if( active ) cam.speed = clampf(cam.speed + input_diff(MOUSE_W) / 10, 0.05f, 5.0f);
|
||||||
vec2 mouse = scale2(vec2(input_diff(MOUSE_X), -input_diff(MOUSE_Y)), 0.2f * active);
|
vec2 mouse = scale2(vec2(input_diff(MOUSE_X), -input_diff(MOUSE_Y)), 0.2f * active);
|
||||||
vec3 wasdec = scale3(vec3(input(KEY_D)-input(KEY_A),input(KEY_E)-input(KEY_C),input(KEY_W)-input(KEY_S)), cam.speed);
|
vec3 wasdec = scale3(vec3(input(KEY_D)-input(KEY_A),input(KEY_E)-input(KEY_C),input(KEY_W)-input(KEY_S)), cam.speed);
|
||||||
camera_moveby(&cam, wasdec);
|
camera_moveby(&cam, scale3(wasdec, window_delta() * 60));
|
||||||
camera_fps(&cam, mouse.x,mouse.y);
|
camera_fps(&cam, mouse.x,mouse.y);
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
2
depot
2
depot
|
@ -1 +1 @@
|
||||||
Subproject commit 132e0cc46f06576f580ea1202aea75fbf64ff13d
|
Subproject commit 9d9b137bf427e9144c6a47de017058d884636a27
|
|
@ -17330,6 +17330,7 @@ typedef struct shadowmap_t {
|
||||||
int cascade_index;
|
int cascade_index;
|
||||||
unsigned shadow_technique;
|
unsigned shadow_technique;
|
||||||
float cascade_splits[NUM_SHADOW_CASCADES];
|
float cascade_splits[NUM_SHADOW_CASCADES];
|
||||||
|
frustum shadow_frustum;
|
||||||
|
|
||||||
// signals
|
// signals
|
||||||
bool skip_render;
|
bool skip_render;
|
||||||
|
@ -17994,6 +17995,7 @@ typedef struct camera_t {
|
||||||
float yaw, pitch, roll; // mirror of (x,y) lookdir in deg;
|
float yaw, pitch, roll; // mirror of (x,y) lookdir in deg;
|
||||||
float speed, fov; // fov in deg(45)
|
float speed, fov; // fov in deg(45)
|
||||||
float near_clip, far_clip;
|
float near_clip, far_clip;
|
||||||
|
float frustum_fov_multiplier;
|
||||||
|
|
||||||
float move_friction, move_damping;
|
float move_friction, move_damping;
|
||||||
float look_friction, look_damping;
|
float look_friction, look_damping;
|
||||||
|
@ -18015,6 +18017,7 @@ API void camera_fps2(camera_t *cam, float yaw, float pitch, float roll);
|
||||||
API void camera_orbit(camera_t *cam, float yaw, float pitch, float inc_distance);
|
API void camera_orbit(camera_t *cam, float yaw, float pitch, float inc_distance);
|
||||||
API void camera_lookat(camera_t *cam, vec3 target);
|
API void camera_lookat(camera_t *cam, vec3 target);
|
||||||
API void camera_enable(camera_t *cam);
|
API void camera_enable(camera_t *cam);
|
||||||
|
API frustum camera_frustum_build(camera_t *cam);
|
||||||
API camera_t *camera_get_active();
|
API camera_t *camera_get_active();
|
||||||
|
|
||||||
API int ui_camera(camera_t *cam);
|
API int ui_camera(camera_t *cam);
|
||||||
|
@ -383893,6 +383896,8 @@ void shadowmap_light(shadowmap_t *s, light_t *l, mat44 cam_proj, mat44 cam_view)
|
||||||
|
|
||||||
unsigned texture_width = s->shadow_technique == SHADOW_VSM ? s->vsm_texture_width : s->csm_texture_width;
|
unsigned texture_width = s->shadow_technique == SHADOW_VSM ? s->vsm_texture_width : s->csm_texture_width;
|
||||||
glViewport(0, 0, texture_width, texture_width);
|
glViewport(0, 0, texture_width, texture_width);
|
||||||
|
|
||||||
|
s->shadow_frustum = frustum_build(s->PV);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -387163,14 +387168,50 @@ void model_clear_frustum(model_t *m) {
|
||||||
m->frustum_enabled = 0;
|
m->frustum_enabled = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define GLOBAL_FRUSTUM_ENABLED 1
|
||||||
|
#define GLOBAL_FRUSTUM_FOV_MULTIPLIER 1.5f
|
||||||
|
static frustum global_frustum;
|
||||||
|
static mat44 global_frustum_stored_mat_proj;
|
||||||
|
static mat44 global_frustum_stored_mat_view;
|
||||||
|
|
||||||
static inline
|
static inline
|
||||||
bool model_is_visible(model_t m, int mesh, mat44 model_mat) {
|
bool model_is_visible(model_t m, int mesh, mat44 model_mat, mat44 proj, mat44 view) {
|
||||||
if(!m.iqm) return false;
|
if(!m.iqm) return false;
|
||||||
if(!m.frustum_enabled) return true;
|
|
||||||
|
bool is_enabled = m.frustum_enabled;
|
||||||
|
frustum fr = m.frustum_state;
|
||||||
|
|
||||||
|
if (active_shadowmap) {
|
||||||
|
is_enabled = true;
|
||||||
|
fr = active_shadowmap->shadow_frustum;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if GLOBAL_FRUSTUM_ENABLED
|
||||||
|
if (!is_enabled) { /* custom frustum not provided, let's compute one from input call */
|
||||||
|
if (memcmp(global_frustum_stored_mat_proj, proj, sizeof(mat44)) != 0 ||
|
||||||
|
memcmp(global_frustum_stored_mat_view, view, sizeof(mat44)) != 0) {
|
||||||
|
copy44(global_frustum_stored_mat_proj, proj);
|
||||||
|
copy44(global_frustum_stored_mat_view, view);
|
||||||
|
mat44 proj_modified;
|
||||||
|
copy44(proj_modified, proj);
|
||||||
|
|
||||||
|
// Increase FOV by 1.5
|
||||||
|
float fov_scale = 1.0f / GLOBAL_FRUSTUM_FOV_MULTIPLIER;
|
||||||
|
proj_modified[0] *= fov_scale;
|
||||||
|
proj_modified[5] *= fov_scale;
|
||||||
|
mat44 projview; multiply44x2(projview, proj_modified, view);
|
||||||
|
global_frustum = frustum_build(projview);
|
||||||
|
}
|
||||||
|
fr = global_frustum;
|
||||||
|
is_enabled = true;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if(!is_enabled) return true;
|
||||||
|
|
||||||
sphere s; s.c = transform344(model_mat, m.meshcenters[mesh]); s.r = m.meshradii[mesh];
|
sphere s; s.c = transform344(model_mat, m.meshcenters[mesh]); s.r = m.meshradii[mesh];
|
||||||
|
|
||||||
if (!frustum_test_sphere(m.frustum_state, s)) {
|
if (!frustum_test_sphere(fr, s)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -387184,7 +387225,7 @@ bool model_is_visible(model_t m, int mesh, mat44 model_mat) {
|
||||||
ddraw_position(s.c, 3.0f);
|
ddraw_position(s.c, 3.0f);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (!frustum_test_aabb(m.frustum_state, box)) {
|
if (!frustum_test_aabb(fr, box)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -387192,7 +387233,7 @@ bool model_is_visible(model_t m, int mesh, mat44 model_mat) {
|
||||||
}
|
}
|
||||||
|
|
||||||
static
|
static
|
||||||
void model_draw_call(model_t m, int shader, int pass, vec3 cam_pos, mat44 model_mat) {
|
void model_draw_call(model_t m, int shader, int pass, vec3 cam_pos, mat44 model_mat, mat44 proj, mat44 view) {
|
||||||
if(!m.iqm) return;
|
if(!m.iqm) return;
|
||||||
iqm_t *q = m.iqm;
|
iqm_t *q = m.iqm;
|
||||||
|
|
||||||
|
@ -387224,13 +387265,13 @@ void model_draw_call(model_t m, int shader, int pass, vec3 cam_pos, mat44 model_
|
||||||
|
|
||||||
if (rs_idx > RENDER_PASS_OVERRIDES_BEGIN) {
|
if (rs_idx > RENDER_PASS_OVERRIDES_BEGIN) {
|
||||||
for(int i = 0; i < q->nummeshes; i++) {
|
for(int i = 0; i < q->nummeshes; i++) {
|
||||||
if (!model_is_visible(m, i, model_mat)) continue;
|
if (!model_is_visible(m, i, model_mat, proj, view)) continue;
|
||||||
array_push(drawcalls, (drawcall_t){i, -1});
|
array_push(drawcalls, (drawcall_t){i, -1});
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if(pass == -1 || pass == RENDER_PASS_OPAQUE) {
|
if(pass == -1 || pass == RENDER_PASS_OPAQUE) {
|
||||||
for(int i = 0; i < q->nummeshes; i++) {
|
for(int i = 0; i < q->nummeshes; i++) {
|
||||||
if (!model_is_visible(m, i, model_mat)) continue;
|
if (!model_is_visible(m, i, model_mat, proj, view)) continue;
|
||||||
|
|
||||||
// collect opaque drawcalls
|
// collect opaque drawcalls
|
||||||
if (required_rs[i] == RENDER_PASS_OPAQUE) {
|
if (required_rs[i] == RENDER_PASS_OPAQUE) {
|
||||||
|
@ -387247,7 +387288,7 @@ void model_draw_call(model_t m, int shader, int pass, vec3 cam_pos, mat44 model_
|
||||||
|
|
||||||
if(pass == -1 || pass == RENDER_PASS_TRANSPARENT) {
|
if(pass == -1 || pass == RENDER_PASS_TRANSPARENT) {
|
||||||
for(int i = 0; i < q->nummeshes; i++) {
|
for(int i = 0; i < q->nummeshes; i++) {
|
||||||
if (!model_is_visible(m, i, model_mat)) continue;
|
if (!model_is_visible(m, i, model_mat, proj, view)) continue;
|
||||||
|
|
||||||
// collect transparent drawcalls
|
// collect transparent drawcalls
|
||||||
if (required_rs[i] == RENDER_PASS_TRANSPARENT) {
|
if (required_rs[i] == RENDER_PASS_TRANSPARENT) {
|
||||||
|
@ -387344,7 +387385,7 @@ void model_render_instanced_pass(model_t m, mat44 proj, mat44 view, mat44* model
|
||||||
}
|
}
|
||||||
|
|
||||||
model_set_uniforms(m, shader > 0 ? shader : m.program, mv, proj, view, models[0]);
|
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]);
|
model_draw_call(m, shader > 0 ? shader : m.program, pass, pos44(view), models[0], proj, view);
|
||||||
}
|
}
|
||||||
|
|
||||||
void model_render_instanced(model_t m, mat44 proj, mat44 view, mat44* models, int shader, unsigned count) {
|
void model_render_instanced(model_t m, mat44 proj, mat44 view, mat44* models, int shader, unsigned count) {
|
||||||
|
@ -388910,6 +388951,7 @@ camera_t camera() {
|
||||||
cam.position = vec3(10,10,10);
|
cam.position = vec3(10,10,10);
|
||||||
cam.updir = vec3(0,1,0);
|
cam.updir = vec3(0,1,0);
|
||||||
cam.fov = 45;
|
cam.fov = 45;
|
||||||
|
cam.frustum_fov_multiplier = 1.5f;
|
||||||
cam.orthographic = false;
|
cam.orthographic = false;
|
||||||
cam.distance = 3; // len3(cam.position);
|
cam.distance = 3; // len3(cam.position);
|
||||||
cam.near_clip = 0.1f;
|
cam.near_clip = 0.1f;
|
||||||
|
@ -389002,6 +389044,19 @@ void camera_enable(camera_t *cam) {
|
||||||
camera_fps(cam, 0, 0);
|
camera_fps(cam, 0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
frustum camera_frustum_build(camera_t *cam) {
|
||||||
|
float aspect = window_width() / ((float)window_height()+!window_height());
|
||||||
|
float fov = cam->fov * cam->frustum_fov_multiplier;
|
||||||
|
mat44 proj;
|
||||||
|
if( cam->orthographic ) {
|
||||||
|
ortho44(proj, -fov * aspect, fov * aspect, -fov, fov, cam->near_clip, cam->far_clip);
|
||||||
|
} else {
|
||||||
|
perspective44(proj, fov, aspect, cam->near_clip, cam->far_clip);
|
||||||
|
}
|
||||||
|
mat44 projview; multiply44x2(projview, proj, cam->view);
|
||||||
|
return frustum_build(projview);
|
||||||
|
}
|
||||||
|
|
||||||
void camera_fov(camera_t *cam, float fov) {
|
void camera_fov(camera_t *cam, float fov) {
|
||||||
last_camera = cam;
|
last_camera = cam;
|
||||||
|
|
||||||
|
@ -389335,21 +389390,7 @@ void scene_render(int flags) {
|
||||||
sm = NULL;
|
sm = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if 1
|
frustum frustum_state = camera_frustum_build(cam);
|
||||||
mat44 projview; multiply44x2(projview, cam->proj, cam->view);
|
|
||||||
frustum frustum_state = frustum_build(projview);
|
|
||||||
#else
|
|
||||||
static frustum frustum_state;
|
|
||||||
do_once {
|
|
||||||
mat44 projview; multiply44x2(projview, cam->proj, cam->view);
|
|
||||||
frustum_state = frustum_build(projview);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (input_down(KEY_T)) {
|
|
||||||
mat44 projview; multiply44x2(projview, cam->proj, cam->view);
|
|
||||||
frustum_state = frustum_build(projview);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if(flags & SCENE_BACKGROUND) {
|
if(flags & SCENE_BACKGROUND) {
|
||||||
if(last_scene->skybox.program) {
|
if(last_scene->skybox.program) {
|
||||||
|
|
|
@ -2073,6 +2073,8 @@ void shadowmap_light(shadowmap_t *s, light_t *l, mat44 cam_proj, mat44 cam_view)
|
||||||
|
|
||||||
unsigned texture_width = s->shadow_technique == SHADOW_VSM ? s->vsm_texture_width : s->csm_texture_width;
|
unsigned texture_width = s->shadow_technique == SHADOW_VSM ? s->vsm_texture_width : s->csm_texture_width;
|
||||||
glViewport(0, 0, texture_width, texture_width);
|
glViewport(0, 0, texture_width, texture_width);
|
||||||
|
|
||||||
|
s->shadow_frustum = frustum_build(s->PV);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5343,14 +5345,50 @@ void model_clear_frustum(model_t *m) {
|
||||||
m->frustum_enabled = 0;
|
m->frustum_enabled = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define GLOBAL_FRUSTUM_ENABLED 1
|
||||||
|
#define GLOBAL_FRUSTUM_FOV_MULTIPLIER 1.5f
|
||||||
|
static frustum global_frustum;
|
||||||
|
static mat44 global_frustum_stored_mat_proj;
|
||||||
|
static mat44 global_frustum_stored_mat_view;
|
||||||
|
|
||||||
static inline
|
static inline
|
||||||
bool model_is_visible(model_t m, int mesh, mat44 model_mat) {
|
bool model_is_visible(model_t m, int mesh, mat44 model_mat, mat44 proj, mat44 view) {
|
||||||
if(!m.iqm) return false;
|
if(!m.iqm) return false;
|
||||||
if(!m.frustum_enabled) return true;
|
|
||||||
|
bool is_enabled = m.frustum_enabled;
|
||||||
|
frustum fr = m.frustum_state;
|
||||||
|
|
||||||
|
if (active_shadowmap) {
|
||||||
|
is_enabled = true;
|
||||||
|
fr = active_shadowmap->shadow_frustum;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if GLOBAL_FRUSTUM_ENABLED
|
||||||
|
if (!is_enabled) { /* custom frustum not provided, let's compute one from input call */
|
||||||
|
if (memcmp(global_frustum_stored_mat_proj, proj, sizeof(mat44)) != 0 ||
|
||||||
|
memcmp(global_frustum_stored_mat_view, view, sizeof(mat44)) != 0) {
|
||||||
|
copy44(global_frustum_stored_mat_proj, proj);
|
||||||
|
copy44(global_frustum_stored_mat_view, view);
|
||||||
|
mat44 proj_modified;
|
||||||
|
copy44(proj_modified, proj);
|
||||||
|
|
||||||
|
// Increase FOV by 1.5
|
||||||
|
float fov_scale = 1.0f / GLOBAL_FRUSTUM_FOV_MULTIPLIER;
|
||||||
|
proj_modified[0] *= fov_scale;
|
||||||
|
proj_modified[5] *= fov_scale;
|
||||||
|
mat44 projview; multiply44x2(projview, proj_modified, view);
|
||||||
|
global_frustum = frustum_build(projview);
|
||||||
|
}
|
||||||
|
fr = global_frustum;
|
||||||
|
is_enabled = true;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if(!is_enabled) return true;
|
||||||
|
|
||||||
sphere s; s.c = transform344(model_mat, m.meshcenters[mesh]); s.r = m.meshradii[mesh];
|
sphere s; s.c = transform344(model_mat, m.meshcenters[mesh]); s.r = m.meshradii[mesh];
|
||||||
|
|
||||||
if (!frustum_test_sphere(m.frustum_state, s)) {
|
if (!frustum_test_sphere(fr, s)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5364,7 +5402,7 @@ bool model_is_visible(model_t m, int mesh, mat44 model_mat) {
|
||||||
ddraw_position(s.c, 3.0f);
|
ddraw_position(s.c, 3.0f);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (!frustum_test_aabb(m.frustum_state, box)) {
|
if (!frustum_test_aabb(fr, box)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5372,7 +5410,7 @@ bool model_is_visible(model_t m, int mesh, mat44 model_mat) {
|
||||||
}
|
}
|
||||||
|
|
||||||
static
|
static
|
||||||
void model_draw_call(model_t m, int shader, int pass, vec3 cam_pos, mat44 model_mat) {
|
void model_draw_call(model_t m, int shader, int pass, vec3 cam_pos, mat44 model_mat, mat44 proj, mat44 view) {
|
||||||
if(!m.iqm) return;
|
if(!m.iqm) return;
|
||||||
iqm_t *q = m.iqm;
|
iqm_t *q = m.iqm;
|
||||||
|
|
||||||
|
@ -5404,13 +5442,13 @@ void model_draw_call(model_t m, int shader, int pass, vec3 cam_pos, mat44 model_
|
||||||
|
|
||||||
if (rs_idx > RENDER_PASS_OVERRIDES_BEGIN) {
|
if (rs_idx > RENDER_PASS_OVERRIDES_BEGIN) {
|
||||||
for(int i = 0; i < q->nummeshes; i++) {
|
for(int i = 0; i < q->nummeshes; i++) {
|
||||||
if (!model_is_visible(m, i, model_mat)) continue;
|
if (!model_is_visible(m, i, model_mat, proj, view)) continue;
|
||||||
array_push(drawcalls, (drawcall_t){i, -1});
|
array_push(drawcalls, (drawcall_t){i, -1});
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if(pass == -1 || pass == RENDER_PASS_OPAQUE) {
|
if(pass == -1 || pass == RENDER_PASS_OPAQUE) {
|
||||||
for(int i = 0; i < q->nummeshes; i++) {
|
for(int i = 0; i < q->nummeshes; i++) {
|
||||||
if (!model_is_visible(m, i, model_mat)) continue;
|
if (!model_is_visible(m, i, model_mat, proj, view)) continue;
|
||||||
|
|
||||||
// collect opaque drawcalls
|
// collect opaque drawcalls
|
||||||
if (required_rs[i] == RENDER_PASS_OPAQUE) {
|
if (required_rs[i] == RENDER_PASS_OPAQUE) {
|
||||||
|
@ -5427,7 +5465,7 @@ void model_draw_call(model_t m, int shader, int pass, vec3 cam_pos, mat44 model_
|
||||||
|
|
||||||
if(pass == -1 || pass == RENDER_PASS_TRANSPARENT) {
|
if(pass == -1 || pass == RENDER_PASS_TRANSPARENT) {
|
||||||
for(int i = 0; i < q->nummeshes; i++) {
|
for(int i = 0; i < q->nummeshes; i++) {
|
||||||
if (!model_is_visible(m, i, model_mat)) continue;
|
if (!model_is_visible(m, i, model_mat, proj, view)) continue;
|
||||||
|
|
||||||
// collect transparent drawcalls
|
// collect transparent drawcalls
|
||||||
if (required_rs[i] == RENDER_PASS_TRANSPARENT) {
|
if (required_rs[i] == RENDER_PASS_TRANSPARENT) {
|
||||||
|
@ -5524,7 +5562,7 @@ void model_render_instanced_pass(model_t m, mat44 proj, mat44 view, mat44* model
|
||||||
}
|
}
|
||||||
|
|
||||||
model_set_uniforms(m, shader > 0 ? shader : m.program, mv, proj, view, models[0]);
|
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]);
|
model_draw_call(m, shader > 0 ? shader : m.program, pass, pos44(view), models[0], proj, view);
|
||||||
}
|
}
|
||||||
|
|
||||||
void model_render_instanced(model_t m, mat44 proj, mat44 view, mat44* models, int shader, unsigned count) {
|
void model_render_instanced(model_t m, mat44 proj, mat44 view, mat44* models, int shader, unsigned count) {
|
||||||
|
|
|
@ -362,6 +362,7 @@ typedef struct shadowmap_t {
|
||||||
int cascade_index;
|
int cascade_index;
|
||||||
unsigned shadow_technique;
|
unsigned shadow_technique;
|
||||||
float cascade_splits[NUM_SHADOW_CASCADES];
|
float cascade_splits[NUM_SHADOW_CASCADES];
|
||||||
|
frustum shadow_frustum;
|
||||||
|
|
||||||
// signals
|
// signals
|
||||||
bool skip_render;
|
bool skip_render;
|
||||||
|
|
|
@ -12,6 +12,7 @@ camera_t camera() {
|
||||||
cam.position = vec3(10,10,10);
|
cam.position = vec3(10,10,10);
|
||||||
cam.updir = vec3(0,1,0);
|
cam.updir = vec3(0,1,0);
|
||||||
cam.fov = 45;
|
cam.fov = 45;
|
||||||
|
cam.frustum_fov_multiplier = 1.5f;
|
||||||
cam.orthographic = false;
|
cam.orthographic = false;
|
||||||
cam.distance = 3; // len3(cam.position);
|
cam.distance = 3; // len3(cam.position);
|
||||||
cam.near_clip = 0.1f;
|
cam.near_clip = 0.1f;
|
||||||
|
@ -104,6 +105,19 @@ void camera_enable(camera_t *cam) {
|
||||||
camera_fps(cam, 0, 0);
|
camera_fps(cam, 0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
frustum camera_frustum_build(camera_t *cam) {
|
||||||
|
float aspect = window_width() / ((float)window_height()+!window_height());
|
||||||
|
float fov = cam->fov * cam->frustum_fov_multiplier;
|
||||||
|
mat44 proj;
|
||||||
|
if( cam->orthographic ) {
|
||||||
|
ortho44(proj, -fov * aspect, fov * aspect, -fov, fov, cam->near_clip, cam->far_clip);
|
||||||
|
} else {
|
||||||
|
perspective44(proj, fov, aspect, cam->near_clip, cam->far_clip);
|
||||||
|
}
|
||||||
|
mat44 projview; multiply44x2(projview, proj, cam->view);
|
||||||
|
return frustum_build(projview);
|
||||||
|
}
|
||||||
|
|
||||||
void camera_fov(camera_t *cam, float fov) {
|
void camera_fov(camera_t *cam, float fov) {
|
||||||
last_camera = cam;
|
last_camera = cam;
|
||||||
|
|
||||||
|
@ -437,21 +451,7 @@ void scene_render(int flags) {
|
||||||
sm = NULL;
|
sm = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if 1
|
frustum frustum_state = camera_frustum_build(cam);
|
||||||
mat44 projview; multiply44x2(projview, cam->proj, cam->view);
|
|
||||||
frustum frustum_state = frustum_build(projview);
|
|
||||||
#else
|
|
||||||
static frustum frustum_state;
|
|
||||||
do_once {
|
|
||||||
mat44 projview; multiply44x2(projview, cam->proj, cam->view);
|
|
||||||
frustum_state = frustum_build(projview);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (input_down(KEY_T)) {
|
|
||||||
mat44 projview; multiply44x2(projview, cam->proj, cam->view);
|
|
||||||
frustum_state = frustum_build(projview);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if(flags & SCENE_BACKGROUND) {
|
if(flags & SCENE_BACKGROUND) {
|
||||||
if(last_scene->skybox.program) {
|
if(last_scene->skybox.program) {
|
||||||
|
|
|
@ -10,6 +10,7 @@ typedef struct camera_t {
|
||||||
float yaw, pitch, roll; // mirror of (x,y) lookdir in deg;
|
float yaw, pitch, roll; // mirror of (x,y) lookdir in deg;
|
||||||
float speed, fov; // fov in deg(45)
|
float speed, fov; // fov in deg(45)
|
||||||
float near_clip, far_clip;
|
float near_clip, far_clip;
|
||||||
|
float frustum_fov_multiplier;
|
||||||
|
|
||||||
float move_friction, move_damping;
|
float move_friction, move_damping;
|
||||||
float look_friction, look_damping;
|
float look_friction, look_damping;
|
||||||
|
@ -31,6 +32,7 @@ API void camera_fps2(camera_t *cam, float yaw, float pitch, float roll);
|
||||||
API void camera_orbit(camera_t *cam, float yaw, float pitch, float inc_distance);
|
API void camera_orbit(camera_t *cam, float yaw, float pitch, float inc_distance);
|
||||||
API void camera_lookat(camera_t *cam, vec3 target);
|
API void camera_lookat(camera_t *cam, vec3 target);
|
||||||
API void camera_enable(camera_t *cam);
|
API void camera_enable(camera_t *cam);
|
||||||
|
API frustum camera_frustum_build(camera_t *cam);
|
||||||
API camera_t *camera_get_active();
|
API camera_t *camera_get_active();
|
||||||
|
|
||||||
API int ui_camera(camera_t *cam);
|
API int ui_camera(camera_t *cam);
|
||||||
|
|
86
engine/v4k.c
86
engine/v4k.c
|
@ -18927,6 +18927,8 @@ void shadowmap_light(shadowmap_t *s, light_t *l, mat44 cam_proj, mat44 cam_view)
|
||||||
|
|
||||||
unsigned texture_width = s->shadow_technique == SHADOW_VSM ? s->vsm_texture_width : s->csm_texture_width;
|
unsigned texture_width = s->shadow_technique == SHADOW_VSM ? s->vsm_texture_width : s->csm_texture_width;
|
||||||
glViewport(0, 0, texture_width, texture_width);
|
glViewport(0, 0, texture_width, texture_width);
|
||||||
|
|
||||||
|
s->shadow_frustum = frustum_build(s->PV);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -22197,14 +22199,50 @@ void model_clear_frustum(model_t *m) {
|
||||||
m->frustum_enabled = 0;
|
m->frustum_enabled = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define GLOBAL_FRUSTUM_ENABLED 1
|
||||||
|
#define GLOBAL_FRUSTUM_FOV_MULTIPLIER 1.5f
|
||||||
|
static frustum global_frustum;
|
||||||
|
static mat44 global_frustum_stored_mat_proj;
|
||||||
|
static mat44 global_frustum_stored_mat_view;
|
||||||
|
|
||||||
static inline
|
static inline
|
||||||
bool model_is_visible(model_t m, int mesh, mat44 model_mat) {
|
bool model_is_visible(model_t m, int mesh, mat44 model_mat, mat44 proj, mat44 view) {
|
||||||
if(!m.iqm) return false;
|
if(!m.iqm) return false;
|
||||||
if(!m.frustum_enabled) return true;
|
|
||||||
|
bool is_enabled = m.frustum_enabled;
|
||||||
|
frustum fr = m.frustum_state;
|
||||||
|
|
||||||
|
if (active_shadowmap) {
|
||||||
|
is_enabled = true;
|
||||||
|
fr = active_shadowmap->shadow_frustum;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if GLOBAL_FRUSTUM_ENABLED
|
||||||
|
if (!is_enabled) { /* custom frustum not provided, let's compute one from input call */
|
||||||
|
if (memcmp(global_frustum_stored_mat_proj, proj, sizeof(mat44)) != 0 ||
|
||||||
|
memcmp(global_frustum_stored_mat_view, view, sizeof(mat44)) != 0) {
|
||||||
|
copy44(global_frustum_stored_mat_proj, proj);
|
||||||
|
copy44(global_frustum_stored_mat_view, view);
|
||||||
|
mat44 proj_modified;
|
||||||
|
copy44(proj_modified, proj);
|
||||||
|
|
||||||
|
// Increase FOV by 1.5
|
||||||
|
float fov_scale = 1.0f / GLOBAL_FRUSTUM_FOV_MULTIPLIER;
|
||||||
|
proj_modified[0] *= fov_scale;
|
||||||
|
proj_modified[5] *= fov_scale;
|
||||||
|
mat44 projview; multiply44x2(projview, proj_modified, view);
|
||||||
|
global_frustum = frustum_build(projview);
|
||||||
|
}
|
||||||
|
fr = global_frustum;
|
||||||
|
is_enabled = true;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if(!is_enabled) return true;
|
||||||
|
|
||||||
sphere s; s.c = transform344(model_mat, m.meshcenters[mesh]); s.r = m.meshradii[mesh];
|
sphere s; s.c = transform344(model_mat, m.meshcenters[mesh]); s.r = m.meshradii[mesh];
|
||||||
|
|
||||||
if (!frustum_test_sphere(m.frustum_state, s)) {
|
if (!frustum_test_sphere(fr, s)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -22218,7 +22256,7 @@ bool model_is_visible(model_t m, int mesh, mat44 model_mat) {
|
||||||
ddraw_position(s.c, 3.0f);
|
ddraw_position(s.c, 3.0f);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (!frustum_test_aabb(m.frustum_state, box)) {
|
if (!frustum_test_aabb(fr, box)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -22226,7 +22264,7 @@ bool model_is_visible(model_t m, int mesh, mat44 model_mat) {
|
||||||
}
|
}
|
||||||
|
|
||||||
static
|
static
|
||||||
void model_draw_call(model_t m, int shader, int pass, vec3 cam_pos, mat44 model_mat) {
|
void model_draw_call(model_t m, int shader, int pass, vec3 cam_pos, mat44 model_mat, mat44 proj, mat44 view) {
|
||||||
if(!m.iqm) return;
|
if(!m.iqm) return;
|
||||||
iqm_t *q = m.iqm;
|
iqm_t *q = m.iqm;
|
||||||
|
|
||||||
|
@ -22258,13 +22296,13 @@ void model_draw_call(model_t m, int shader, int pass, vec3 cam_pos, mat44 model_
|
||||||
|
|
||||||
if (rs_idx > RENDER_PASS_OVERRIDES_BEGIN) {
|
if (rs_idx > RENDER_PASS_OVERRIDES_BEGIN) {
|
||||||
for(int i = 0; i < q->nummeshes; i++) {
|
for(int i = 0; i < q->nummeshes; i++) {
|
||||||
if (!model_is_visible(m, i, model_mat)) continue;
|
if (!model_is_visible(m, i, model_mat, proj, view)) continue;
|
||||||
array_push(drawcalls, (drawcall_t){i, -1});
|
array_push(drawcalls, (drawcall_t){i, -1});
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if(pass == -1 || pass == RENDER_PASS_OPAQUE) {
|
if(pass == -1 || pass == RENDER_PASS_OPAQUE) {
|
||||||
for(int i = 0; i < q->nummeshes; i++) {
|
for(int i = 0; i < q->nummeshes; i++) {
|
||||||
if (!model_is_visible(m, i, model_mat)) continue;
|
if (!model_is_visible(m, i, model_mat, proj, view)) continue;
|
||||||
|
|
||||||
// collect opaque drawcalls
|
// collect opaque drawcalls
|
||||||
if (required_rs[i] == RENDER_PASS_OPAQUE) {
|
if (required_rs[i] == RENDER_PASS_OPAQUE) {
|
||||||
|
@ -22281,7 +22319,7 @@ void model_draw_call(model_t m, int shader, int pass, vec3 cam_pos, mat44 model_
|
||||||
|
|
||||||
if(pass == -1 || pass == RENDER_PASS_TRANSPARENT) {
|
if(pass == -1 || pass == RENDER_PASS_TRANSPARENT) {
|
||||||
for(int i = 0; i < q->nummeshes; i++) {
|
for(int i = 0; i < q->nummeshes; i++) {
|
||||||
if (!model_is_visible(m, i, model_mat)) continue;
|
if (!model_is_visible(m, i, model_mat, proj, view)) continue;
|
||||||
|
|
||||||
// collect transparent drawcalls
|
// collect transparent drawcalls
|
||||||
if (required_rs[i] == RENDER_PASS_TRANSPARENT) {
|
if (required_rs[i] == RENDER_PASS_TRANSPARENT) {
|
||||||
|
@ -22378,7 +22416,7 @@ void model_render_instanced_pass(model_t m, mat44 proj, mat44 view, mat44* model
|
||||||
}
|
}
|
||||||
|
|
||||||
model_set_uniforms(m, shader > 0 ? shader : m.program, mv, proj, view, models[0]);
|
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]);
|
model_draw_call(m, shader > 0 ? shader : m.program, pass, pos44(view), models[0], proj, view);
|
||||||
}
|
}
|
||||||
|
|
||||||
void model_render_instanced(model_t m, mat44 proj, mat44 view, mat44* models, int shader, unsigned count) {
|
void model_render_instanced(model_t m, mat44 proj, mat44 view, mat44* models, int shader, unsigned count) {
|
||||||
|
@ -23944,6 +23982,7 @@ camera_t camera() {
|
||||||
cam.position = vec3(10,10,10);
|
cam.position = vec3(10,10,10);
|
||||||
cam.updir = vec3(0,1,0);
|
cam.updir = vec3(0,1,0);
|
||||||
cam.fov = 45;
|
cam.fov = 45;
|
||||||
|
cam.frustum_fov_multiplier = 1.5f;
|
||||||
cam.orthographic = false;
|
cam.orthographic = false;
|
||||||
cam.distance = 3; // len3(cam.position);
|
cam.distance = 3; // len3(cam.position);
|
||||||
cam.near_clip = 0.1f;
|
cam.near_clip = 0.1f;
|
||||||
|
@ -24036,6 +24075,19 @@ void camera_enable(camera_t *cam) {
|
||||||
camera_fps(cam, 0, 0);
|
camera_fps(cam, 0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
frustum camera_frustum_build(camera_t *cam) {
|
||||||
|
float aspect = window_width() / ((float)window_height()+!window_height());
|
||||||
|
float fov = cam->fov * cam->frustum_fov_multiplier;
|
||||||
|
mat44 proj;
|
||||||
|
if( cam->orthographic ) {
|
||||||
|
ortho44(proj, -fov * aspect, fov * aspect, -fov, fov, cam->near_clip, cam->far_clip);
|
||||||
|
} else {
|
||||||
|
perspective44(proj, fov, aspect, cam->near_clip, cam->far_clip);
|
||||||
|
}
|
||||||
|
mat44 projview; multiply44x2(projview, proj, cam->view);
|
||||||
|
return frustum_build(projview);
|
||||||
|
}
|
||||||
|
|
||||||
void camera_fov(camera_t *cam, float fov) {
|
void camera_fov(camera_t *cam, float fov) {
|
||||||
last_camera = cam;
|
last_camera = cam;
|
||||||
|
|
||||||
|
@ -24369,21 +24421,7 @@ void scene_render(int flags) {
|
||||||
sm = NULL;
|
sm = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if 1
|
frustum frustum_state = camera_frustum_build(cam);
|
||||||
mat44 projview; multiply44x2(projview, cam->proj, cam->view);
|
|
||||||
frustum frustum_state = frustum_build(projview);
|
|
||||||
#else
|
|
||||||
static frustum frustum_state;
|
|
||||||
do_once {
|
|
||||||
mat44 projview; multiply44x2(projview, cam->proj, cam->view);
|
|
||||||
frustum_state = frustum_build(projview);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (input_down(KEY_T)) {
|
|
||||||
mat44 projview; multiply44x2(projview, cam->proj, cam->view);
|
|
||||||
frustum_state = frustum_build(projview);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if(flags & SCENE_BACKGROUND) {
|
if(flags & SCENE_BACKGROUND) {
|
||||||
if(last_scene->skybox.program) {
|
if(last_scene->skybox.program) {
|
||||||
|
|
|
@ -3397,6 +3397,7 @@ typedef struct shadowmap_t {
|
||||||
int cascade_index;
|
int cascade_index;
|
||||||
unsigned shadow_technique;
|
unsigned shadow_technique;
|
||||||
float cascade_splits[NUM_SHADOW_CASCADES];
|
float cascade_splits[NUM_SHADOW_CASCADES];
|
||||||
|
frustum shadow_frustum;
|
||||||
|
|
||||||
// signals
|
// signals
|
||||||
bool skip_render;
|
bool skip_render;
|
||||||
|
@ -4061,6 +4062,7 @@ typedef struct camera_t {
|
||||||
float yaw, pitch, roll; // mirror of (x,y) lookdir in deg;
|
float yaw, pitch, roll; // mirror of (x,y) lookdir in deg;
|
||||||
float speed, fov; // fov in deg(45)
|
float speed, fov; // fov in deg(45)
|
||||||
float near_clip, far_clip;
|
float near_clip, far_clip;
|
||||||
|
float frustum_fov_multiplier;
|
||||||
|
|
||||||
float move_friction, move_damping;
|
float move_friction, move_damping;
|
||||||
float look_friction, look_damping;
|
float look_friction, look_damping;
|
||||||
|
@ -4082,6 +4084,7 @@ API void camera_fps2(camera_t *cam, float yaw, float pitch, float roll);
|
||||||
API void camera_orbit(camera_t *cam, float yaw, float pitch, float inc_distance);
|
API void camera_orbit(camera_t *cam, float yaw, float pitch, float inc_distance);
|
||||||
API void camera_lookat(camera_t *cam, vec3 target);
|
API void camera_lookat(camera_t *cam, vec3 target);
|
||||||
API void camera_enable(camera_t *cam);
|
API void camera_enable(camera_t *cam);
|
||||||
|
API frustum camera_frustum_build(camera_t *cam);
|
||||||
API camera_t *camera_get_active();
|
API camera_t *camera_get_active();
|
||||||
|
|
||||||
API int ui_camera(camera_t *cam);
|
API int ui_camera(camera_t *cam);
|
||||||
|
|
Loading…
Reference in New Issue