From ac8ab8d60d03e77caf54409bebbe6d926139ec96 Mon Sep 17 00:00:00 2001 From: asrael Date: Mon, 10 Nov 2025 10:24:27 -0600 Subject: [PATCH] enable camera frustum culling for bsp rendering --- demo/mod/bsp_world.fnl | 53 ------------------------------------------ demo/mod/worldgen.fnl | 10 ++++---- src/pxl8_bsp.c | 7 ++++++ src/pxl8_math.c | 48 +++++++++++++++++++------------------- 4 files changed, 36 insertions(+), 82 deletions(-) delete mode 100644 demo/mod/bsp_world.fnl diff --git a/demo/mod/bsp_world.fnl b/demo/mod/bsp_world.fnl deleted file mode 100644 index 8c87791..0000000 --- a/demo/mod/bsp_world.fnl +++ /dev/null @@ -1,53 +0,0 @@ -(local pxl8 (require :pxl8)) - -(var camera-angle 0) -(local camera-height 0) -(local camera-distance 450) -(var fps 0) -(var world nil) - -(fn init [] - (set world (pxl8.world_new)) - (let [result (pxl8.world_load world "res/maps/test.bsp")] - (if (< result 0) - (pxl8.error (.. "Failed to load test.bsp - result: " result)) - (pxl8.info "Loaded world successfully!")))) - -(fn update [dt] - (when (> dt 0) - (set fps (math.floor (/ 1.0 dt)))) - (when (pxl8.world_is_loaded world) - (set camera-angle (+ camera-angle (* dt 0.5))))) - -(fn frame [] - (pxl8.clr 0) - (pxl8.text (.. "FPS: " fps) 10 40 14) - - (if (pxl8.world_is_loaded world) - (let [cam-x (* camera-distance (math.cos camera-angle)) - cam-z (* camera-distance (math.sin camera-angle))] - - (pxl8.text (.. "Camera: " (string.format "%.0f" cam-x) "," - (string.format "%.0f" camera-height) "," - (string.format "%.0f" cam-z)) 10 55 12) - - (pxl8.clear_zbuffer) - (pxl8.set_backface_culling true) - (pxl8.set_wireframe true) - - (let [aspect (/ (pxl8.get_width) (pxl8.get_height)) - fov 1.047] - (pxl8.set_projection (pxl8.mat4_perspective fov aspect 1.0 4096.0))) - - (pxl8.set_view (pxl8.mat4_lookat - [cam-x camera-height cam-z] - [0 0 0] - [0 1 0])) - - (pxl8.set_model (pxl8.mat4_identity)) - - (pxl8.world_render world [cam-x camera-height cam-z])))) - -{:init init - :update update - :frame frame} diff --git a/demo/mod/worldgen.fnl b/demo/mod/worldgen.fnl index 0519d88..ba3d29b 100644 --- a/demo/mod/worldgen.fnl +++ b/demo/mod/worldgen.fnl @@ -114,10 +114,6 @@ target-y (+ eye-y (math.sin cam-pitch)) target-z (+ cam-z forward-z)] - (pxl8.text (.. "Pos: " (string.format "%.0f" cam-x) "," - (string.format "%.0f" cam-y) "," - (string.format "%.0f" cam-z)) 10 25 12) - (pxl8.clear_zbuffer) (pxl8.set_backface_culling true) (pxl8.set_wireframe false) @@ -134,7 +130,11 @@ (pxl8.set_model (pxl8.mat4_identity)) (pxl8.set_affine_textures affine) - (pxl8.world_render world [cam-x eye-y cam-z])) + (pxl8.world_render world [cam-x eye-y cam-z]) + + (pxl8.text (.. "Pos: " (string.format "%.0f" cam-x) "," + (string.format "%.0f" cam-y) "," + (string.format "%.0f" cam-z)) 10 25 12)) (let [new-state (debug-ui.render {:show-debug-ui show-debug-ui :fps fps diff --git a/src/pxl8_bsp.c b/src/pxl8_bsp.c index 7006e3d..e5284fa 100644 --- a/src/pxl8_bsp.c +++ b/src/pxl8_bsp.c @@ -486,6 +486,8 @@ void pxl8_bsp_render_solid( if (rendered_faces[face_id]) continue; rendered_faces[face_id] = 1; + if (!face_in_frustum(bsp, face_id, frustum)) continue; + pxl8_bsp_render_face(gfx, bsp, face_id, texture_id); } } @@ -500,6 +502,9 @@ void pxl8_bsp_render_wireframe( ) { if (!gfx || !bsp) return; + const pxl8_frustum* frustum = pxl8_3d_get_frustum(gfx); + if (!frustum) return; + i32 camera_leaf = pxl8_bsp_find_leaf(bsp, camera_pos); for (u32 leaf_id = 0; leaf_id < bsp->num_leafs; leaf_id++) { @@ -514,6 +519,8 @@ void pxl8_bsp_render_wireframe( u32 face_id = bsp->marksurfaces[surf_idx]; if (face_id >= bsp->num_faces) continue; + if (!face_in_frustum(bsp, face_id, frustum)) continue; + const pxl8_bsp_face* face = &bsp->faces[face_id]; for (u32 e = 0; e < face->num_edges; e++) { diff --git a/src/pxl8_math.c b/src/pxl8_math.c index 4935cf6..f3a2321 100644 --- a/src/pxl8_math.c +++ b/src/pxl8_math.c @@ -255,35 +255,35 @@ pxl8_frustum pxl8_frustum_from_matrix(pxl8_mat4 vp) { pxl8_frustum frustum; const f32* m = vp.m; - frustum.planes[0].normal.x = m[3] - m[0]; - frustum.planes[0].normal.y = m[7] - m[4]; - frustum.planes[0].normal.z = m[11] - m[8]; - frustum.planes[0].distance = m[15] - m[12]; + frustum.planes[0].normal.x = m[12] - m[0]; + frustum.planes[0].normal.y = m[13] - m[1]; + frustum.planes[0].normal.z = m[14] - m[2]; + frustum.planes[0].distance = m[15] - m[3]; - frustum.planes[1].normal.x = m[3] + m[0]; - frustum.planes[1].normal.y = m[7] + m[4]; - frustum.planes[1].normal.z = m[11] + m[8]; - frustum.planes[1].distance = m[15] + m[12]; + frustum.planes[1].normal.x = m[12] + m[0]; + frustum.planes[1].normal.y = m[13] + m[1]; + frustum.planes[1].normal.z = m[14] + m[2]; + frustum.planes[1].distance = m[15] + m[3]; - frustum.planes[2].normal.x = m[3] + m[1]; - frustum.planes[2].normal.y = m[7] + m[5]; - frustum.planes[2].normal.z = m[11] + m[9]; - frustum.planes[2].distance = m[15] + m[13]; + frustum.planes[2].normal.x = m[12] + m[4]; + frustum.planes[2].normal.y = m[13] + m[5]; + frustum.planes[2].normal.z = m[14] + m[6]; + frustum.planes[2].distance = m[15] + m[7]; - frustum.planes[3].normal.x = m[3] - m[1]; - frustum.planes[3].normal.y = m[7] - m[5]; - frustum.planes[3].normal.z = m[11] - m[9]; - frustum.planes[3].distance = m[15] - m[13]; + frustum.planes[3].normal.x = m[12] - m[4]; + frustum.planes[3].normal.y = m[13] - m[5]; + frustum.planes[3].normal.z = m[14] - m[6]; + frustum.planes[3].distance = m[15] - m[7]; - frustum.planes[4].normal.x = m[3] - m[2]; - frustum.planes[4].normal.y = m[7] - m[6]; - frustum.planes[4].normal.z = m[11] - m[10]; - frustum.planes[4].distance = m[15] - m[14]; + frustum.planes[4].normal.x = m[12] - m[8]; + frustum.planes[4].normal.y = m[13] - m[9]; + frustum.planes[4].normal.z = m[14] - m[10]; + frustum.planes[4].distance = m[15] - m[11]; - frustum.planes[5].normal.x = m[3] + m[2]; - frustum.planes[5].normal.y = m[7] + m[6]; - frustum.planes[5].normal.z = m[11] + m[10]; - frustum.planes[5].distance = m[15] + m[14]; + frustum.planes[5].normal.x = m[12] + m[8]; + frustum.planes[5].normal.y = m[13] + m[9]; + frustum.planes[5].normal.z = m[14] + m[10]; + frustum.planes[5].distance = m[15] + m[11]; for (i32 i = 0; i < 6; i++) { f32 len = pxl8_vec3_length(frustum.planes[i].normal);