Correct frustum culling, finally!
This commit is contained in:
parent
78eebc1e17
commit
1633957d07
@ -405,23 +405,15 @@ pub fn finish(self: *Render) void {
|
|||||||
gl.useProgram(self.assetman.resolveShaderProgram(a.ShaderPrograms.shaders.mesh).program);
|
gl.useProgram(self.assetman.resolveShaderProgram(a.ShaderPrograms.shaders.mesh).program);
|
||||||
gl.bindVertexArray(self.mesh_vao);
|
gl.bindVertexArray(self.mesh_vao);
|
||||||
|
|
||||||
//const inv_view_mat = self.camera.view_mat.inv();
|
|
||||||
// const world_camera_frustum = math.Frustum.perspective(
|
|
||||||
// self.camera.fovy,
|
|
||||||
// self.camera.aspect,
|
|
||||||
// self.camera.near,
|
|
||||||
// self.camera.far,
|
|
||||||
// ).transform(&inv_view_mat);
|
|
||||||
|
|
||||||
const view_proj = projection.mul(self.camera.view_mat);
|
const view_proj = projection.mul(self.camera.view_mat);
|
||||||
|
const world_camera_frustum = math.Frustum.new(view_proj);
|
||||||
|
|
||||||
var rendered_count: usize = 0;
|
var rendered_count: usize = 0;
|
||||||
for (self.command_buffer[0..self.command_count]) |*cmd| {
|
for (self.command_buffer[0..self.command_count]) |*cmd| {
|
||||||
const mesh = self.assetman.resolveMesh(cmd.mesh);
|
const mesh = self.assetman.resolveMesh(cmd.mesh);
|
||||||
const aabb = math.AABB.fromMinMax(mesh.aabb.min, mesh.aabb.max);
|
const aabb = math.AABB.fromMinMax(mesh.aabb.min, mesh.aabb.max);
|
||||||
|
|
||||||
const mvp = view_proj.mul(cmd.transform);
|
if (!world_camera_frustum.intersectAABB(aabb.transform(cmd.transform))) {
|
||||||
if (!math.checkAABBIntersectionNDC(&aabb, &mvp)) {
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
rendered_count += 1;
|
rendered_count += 1;
|
||||||
|
@ -65,14 +65,13 @@ pub const FreeLookCamera = struct {
|
|||||||
self.yaw += look.x();
|
self.yaw += look.x();
|
||||||
self.pitch += look.y();
|
self.pitch += look.y();
|
||||||
// First rotate pitch, then yaw
|
// First rotate pitch, then yaw
|
||||||
const rot = Mat4.fromRotation(self.pitch, Vec3.left()).mul(Mat4.fromRotation(self.yaw, Vec3.up()));
|
const rot = Mat4.fromRotation(self.pitch, Vec3.right()).mul(Mat4.fromRotation(self.yaw, Vec3.up()));
|
||||||
|
|
||||||
// First 3 of transform matrix are: right, up, forward
|
const right = Vec3.new(rot.data[0][0], rot.data[1][0], rot.data[2][0]);
|
||||||
const left = Vec3.new(rot.data[0][0], rot.data[1][0], rot.data[2][0]);
|
|
||||||
const up = Vec3.new(rot.data[0][1], rot.data[1][1], rot.data[2][1]);
|
const up = Vec3.new(rot.data[0][1], rot.data[1][1], rot.data[2][1]);
|
||||||
const forward = Vec3.new(rot.data[0][2], rot.data[1][2], rot.data[2][2]);
|
const forward = Vec3.new(-rot.data[0][2], -rot.data[1][2], -rot.data[2][2]);
|
||||||
|
|
||||||
const movement = left.scale(-move.x()).add(forward.scale(move.y())).add(up.scale(move.z()));
|
const movement = right.scale(move.x()).add(forward.scale(move.y())).add(up.scale(move.z()));
|
||||||
|
|
||||||
self.pos = self.pos.add(movement.scale(self.move_speed * dt));
|
self.pos = self.pos.add(movement.scale(self.move_speed * dt));
|
||||||
|
|
||||||
|
66
src/math.zig
66
src/math.zig
@ -22,8 +22,9 @@ pub const Plane = struct {
|
|||||||
// x, y, z - normal, w - distance
|
// x, y, z - normal, w - distance
|
||||||
nd: Vec4 = Vec4.up(),
|
nd: Vec4 = Vec4.up(),
|
||||||
|
|
||||||
pub fn new(normal: Vec3, distance: f32) Plane {
|
pub fn new(normal_d: Vec4) Plane {
|
||||||
return .{ .nd = normal.norm().toVec4(distance) };
|
const scale = 1.0 / normal_d.toVec3().length();
|
||||||
|
return .{ .nd = normal_d.scale(scale) };
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn transform(self: *const Plane, matrix: *const Mat4) Plane {
|
pub fn transform(self: *const Plane, matrix: *const Mat4) Plane {
|
||||||
@ -80,30 +81,30 @@ pub const Frustum = struct {
|
|||||||
near: Plane,
|
near: Plane,
|
||||||
far: Plane,
|
far: Plane,
|
||||||
|
|
||||||
// Returns a frustum in view space
|
/// Extracts frustum planes from matrices using Gribb-Hartmann method
|
||||||
pub fn perspective(fovy: f32, aspect: f32, z_near: f32, z_far: f32) Frustum {
|
/// If you pass in a projection matrix planes will be in view space.
|
||||||
const half_height = @tan(za.toRadians(fovy) * 0.5);
|
/// If you pass in a view-projection matrix planes will be in world space.
|
||||||
const half_width = half_height * aspect;
|
/// If you pass in a model-view-projection matrix planes will be in model space.
|
||||||
|
pub fn new(mat: Mat4) Frustum {
|
||||||
|
const row1 = Vec4.new(mat.data[0][0], mat.data[1][0], mat.data[2][0], mat.data[3][0]);
|
||||||
|
const row2 = Vec4.new(mat.data[0][1], mat.data[1][1], mat.data[2][1], mat.data[3][1]);
|
||||||
|
const row3 = Vec4.new(mat.data[0][2], mat.data[1][2], mat.data[2][2], mat.data[3][2]);
|
||||||
|
const row4 = Vec4.new(mat.data[0][3], mat.data[1][3], mat.data[2][3], mat.data[3][3]);
|
||||||
|
|
||||||
const nw = Vec3.new(-half_width, half_height, 1).norm();
|
const left = row4.add(row1);
|
||||||
const ne = Vec3.new(half_width, half_height, 1).norm();
|
const right = row4.sub(row1);
|
||||||
const se = Vec3.new(half_width, -half_height, 1).norm();
|
const bottom = row4.add(row2);
|
||||||
const sw = Vec3.new(-half_width, -half_height, 1).norm();
|
const top = row4.sub(row2);
|
||||||
|
const near = row4.add(row3);
|
||||||
const top = nw.cross(ne);
|
const far = row4.sub(row3);
|
||||||
const right = ne.cross(se);
|
|
||||||
const bottom = se.cross(sw);
|
|
||||||
const left = sw.cross(nw);
|
|
||||||
const near = Vec3.new(0, 0, -1);
|
|
||||||
const far = Vec3.new(0, 0, 1);
|
|
||||||
|
|
||||||
return .{
|
return .{
|
||||||
.top = Plane.new(top, 0),
|
.top = Plane.new(top),
|
||||||
.right = Plane.new(right, 0),
|
.right = Plane.new(right),
|
||||||
.bottom = Plane.new(bottom, 0),
|
.bottom = Plane.new(bottom),
|
||||||
.left = Plane.new(left, 0),
|
.left = Plane.new(left),
|
||||||
.near = Plane.new(near, z_near),
|
.near = Plane.new(near),
|
||||||
.far = Plane.new(far, -z_far),
|
.far = Plane.new(far),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -123,13 +124,24 @@ pub const Frustum = struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn intersectAABB(self: *const Frustum, aabb: AABB) bool {
|
pub fn intersectAABB(self: *const Frustum, aabb: AABB) bool {
|
||||||
|
var outside_top_plane = true;
|
||||||
|
var outside_bottom_plane = true;
|
||||||
|
var outside_left_plane = true;
|
||||||
|
var outside_right_plane = true;
|
||||||
|
var outside_near_plane = true;
|
||||||
|
var outside_far_plane = true;
|
||||||
inline for (box_corners) |corner| {
|
inline for (box_corners) |corner| {
|
||||||
if (self.intersectPoint(aabb.origin.add(aabb.extents.mul(corner)))) {
|
const p = aabb.origin.add(aabb.extents.mul(corner));
|
||||||
return true;
|
|
||||||
}
|
outside_top_plane = outside_top_plane and self.top.isUnder(p);
|
||||||
|
outside_bottom_plane = outside_bottom_plane and self.bottom.isUnder(p);
|
||||||
|
outside_left_plane = outside_left_plane and self.left.isUnder(p);
|
||||||
|
outside_right_plane = outside_right_plane and self.right.isUnder(p);
|
||||||
|
outside_near_plane = outside_near_plane and self.near.isUnder(p);
|
||||||
|
outside_far_plane = outside_far_plane and self.far.isUnder(p);
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return !(outside_left_plane or outside_right_plane or outside_bottom_plane or outside_top_plane or outside_near_plane or outside_far_plane);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user