@@ -12,7 +12,8 @@ use bevy_transform::components::GlobalTransform;
12
12
use bevy_window:: Windows ;
13
13
14
14
use crate :: {
15
- CubeMapFace , CubemapVisibleEntities , ViewClusterBindings , CUBE_MAP_FACES , POINT_LIGHT_NEAR_Z ,
15
+ calculate_cluster_factors, CubeMapFace , CubemapVisibleEntities , ViewClusterBindings ,
16
+ CUBE_MAP_FACES , POINT_LIGHT_NEAR_Z ,
16
17
} ;
17
18
18
19
/// A light that emits light in all directions from a central point.
@@ -265,12 +266,14 @@ fn line_intersection_to_z_plane(origin: Vec3, p: Vec3, z: f32) -> Vec3 {
265
266
origin + t * v
266
267
}
267
268
269
+ #[ allow( clippy:: too_many_arguments) ]
268
270
fn compute_aabb_for_cluster (
269
271
z_near : f32 ,
270
272
z_far : f32 ,
271
273
tile_size : Vec2 ,
272
274
screen_size : Vec2 ,
273
275
inverse_projection : Mat4 ,
276
+ is_orthographic : bool ,
274
277
cluster_dimensions : UVec3 ,
275
278
ijk : UVec3 ,
276
279
) -> Aabb {
@@ -280,25 +283,52 @@ fn compute_aabb_for_cluster(
280
283
let p_min = ijk. xy ( ) * tile_size;
281
284
let p_max = p_min + tile_size;
282
285
283
- // Convert to view space at the near plane
284
- // NOTE: 1.0 is the near plane due to using reverse z projections
285
- let p_min = screen_to_view ( screen_size, inverse_projection, p_min, 1.0 ) ;
286
- let p_max = screen_to_view ( screen_size, inverse_projection, p_max, 1.0 ) ;
287
-
288
- let z_far_over_z_near = -z_far / -z_near;
289
- let cluster_near = -z_near * z_far_over_z_near. powf ( ijk. z / cluster_dimensions. z as f32 ) ;
290
- // NOTE: This could be simplified to:
291
- // let cluster_far = cluster_near * z_far_over_z_near;
292
- let cluster_far = -z_near * z_far_over_z_near. powf ( ( ijk. z + 1.0 ) / cluster_dimensions. z as f32 ) ;
293
-
294
- // Calculate the four intersection points of the min and max points with the cluster near and far planes
295
- let p_min_near = line_intersection_to_z_plane ( Vec3 :: ZERO , p_min. xyz ( ) , cluster_near) ;
296
- let p_min_far = line_intersection_to_z_plane ( Vec3 :: ZERO , p_min. xyz ( ) , cluster_far) ;
297
- let p_max_near = line_intersection_to_z_plane ( Vec3 :: ZERO , p_max. xyz ( ) , cluster_near) ;
298
- let p_max_far = line_intersection_to_z_plane ( Vec3 :: ZERO , p_max. xyz ( ) , cluster_far) ;
299
-
300
- let cluster_min = p_min_near. min ( p_min_far) . min ( p_max_near. min ( p_max_far) ) ;
301
- let cluster_max = p_min_near. max ( p_min_far) . max ( p_max_near. max ( p_max_far) ) ;
286
+ let cluster_min;
287
+ let cluster_max;
288
+ if is_orthographic {
289
+ // Use linear depth slicing for orthographic
290
+
291
+ // Convert to view space at the cluster near and far planes
292
+ // NOTE: 1.0 is the near plane due to using reverse z projections
293
+ let p_min = screen_to_view (
294
+ screen_size,
295
+ inverse_projection,
296
+ p_min,
297
+ 1.0 - ( ijk. z / cluster_dimensions. z as f32 ) ,
298
+ )
299
+ . xyz ( ) ;
300
+ let p_max = screen_to_view (
301
+ screen_size,
302
+ inverse_projection,
303
+ p_max,
304
+ 1.0 - ( ( ijk. z + 1.0 ) / cluster_dimensions. z as f32 ) ,
305
+ )
306
+ . xyz ( ) ;
307
+
308
+ cluster_min = p_min. min ( p_max) ;
309
+ cluster_max = p_min. max ( p_max) ;
310
+ } else {
311
+ // Convert to view space at the near plane
312
+ // NOTE: 1.0 is the near plane due to using reverse z projections
313
+ let p_min = screen_to_view ( screen_size, inverse_projection, p_min, 1.0 ) ;
314
+ let p_max = screen_to_view ( screen_size, inverse_projection, p_max, 1.0 ) ;
315
+
316
+ let z_far_over_z_near = -z_far / -z_near;
317
+ let cluster_near = -z_near * z_far_over_z_near. powf ( ijk. z / cluster_dimensions. z as f32 ) ;
318
+ // NOTE: This could be simplified to:
319
+ // cluster_far = cluster_near * z_far_over_z_near;
320
+ let cluster_far =
321
+ -z_near * z_far_over_z_near. powf ( ( ijk. z + 1.0 ) / cluster_dimensions. z as f32 ) ;
322
+
323
+ // Calculate the four intersection points of the min and max points with the cluster near and far planes
324
+ let p_min_near = line_intersection_to_z_plane ( Vec3 :: ZERO , p_min. xyz ( ) , cluster_near) ;
325
+ let p_min_far = line_intersection_to_z_plane ( Vec3 :: ZERO , p_min. xyz ( ) , cluster_far) ;
326
+ let p_max_near = line_intersection_to_z_plane ( Vec3 :: ZERO , p_max. xyz ( ) , cluster_near) ;
327
+ let p_max_far = line_intersection_to_z_plane ( Vec3 :: ZERO , p_max. xyz ( ) , cluster_far) ;
328
+
329
+ cluster_min = p_min_near. min ( p_min_far) . min ( p_max_near. min ( p_max_far) ) ;
330
+ cluster_max = p_min_near. max ( p_min_far) . max ( p_max_near. max ( p_max_far) ) ;
331
+ }
302
332
303
333
Aabb :: from_min_max ( cluster_min, cluster_max)
304
334
}
@@ -322,6 +352,7 @@ pub fn add_clusters(
322
352
323
353
pub fn update_clusters ( windows : Res < Windows > , mut views : Query < ( & Camera , & mut Clusters ) > ) {
324
354
for ( camera, mut clusters) in views. iter_mut ( ) {
355
+ let is_orthographic = camera. projection_matrix . w_axis . w == 1.0 ;
325
356
let inverse_projection = camera. projection_matrix . inverse ( ) ;
326
357
let window = windows. get ( camera. window ) . unwrap ( ) ;
327
358
let screen_size_u32 = UVec2 :: new ( window. physical_width ( ) , window. physical_height ( ) ) ;
@@ -348,6 +379,7 @@ pub fn update_clusters(windows: Res<Windows>, mut views: Query<(&Camera, &mut Cl
348
379
tile_size,
349
380
screen_size,
350
381
inverse_projection,
382
+ is_orthographic,
351
383
clusters. axis_slices ,
352
384
UVec3 :: new ( x, y, z) ,
353
385
) ) ;
@@ -383,22 +415,28 @@ impl VisiblePointLights {
383
415
}
384
416
}
385
417
386
- fn view_z_to_z_slice ( cluster_factors : Vec2 , view_z : f32 ) -> u32 {
387
- // NOTE: had to use -view_z to make it positive else log(negative) is nan
388
- ( ( -view_z) . ln ( ) * cluster_factors. x - cluster_factors. y ) . floor ( ) as u32
418
+ fn view_z_to_z_slice ( cluster_factors : Vec2 , view_z : f32 , is_orthographic : bool ) -> u32 {
419
+ if is_orthographic {
420
+ // NOTE: view_z is correct in the orthographic case
421
+ ( ( view_z - cluster_factors. x ) * cluster_factors. y ) . floor ( ) as u32
422
+ } else {
423
+ // NOTE: had to use -view_z to make it positive else log(negative) is nan
424
+ ( ( -view_z) . ln ( ) * cluster_factors. x - cluster_factors. y ) . floor ( ) as u32
425
+ }
389
426
}
390
427
391
428
fn ndc_position_to_cluster (
392
429
cluster_dimensions : UVec3 ,
393
430
cluster_factors : Vec2 ,
431
+ is_orthographic : bool ,
394
432
ndc_p : Vec3 ,
395
433
view_z : f32 ,
396
434
) -> UVec3 {
397
435
let cluster_dimensions_f32 = cluster_dimensions. as_vec3 ( ) ;
398
436
let frag_coord =
399
437
( ndc_p. xy ( ) * Vec2 :: new ( 0.5 , -0.5 ) + Vec2 :: splat ( 0.5 ) ) . clamp ( Vec2 :: ZERO , Vec2 :: ONE ) ;
400
438
let xy = ( frag_coord * cluster_dimensions_f32. xy ( ) ) . floor ( ) ;
401
- let z_slice = view_z_to_z_slice ( cluster_factors, view_z) ;
439
+ let z_slice = view_z_to_z_slice ( cluster_factors, view_z, is_orthographic ) ;
402
440
xy. as_uvec2 ( )
403
441
. extend ( z_slice)
404
442
. clamp ( UVec3 :: ZERO , cluster_dimensions - UVec3 :: ONE )
@@ -421,11 +459,12 @@ pub fn assign_lights_to_clusters(
421
459
let view_transform = view_transform. compute_matrix ( ) ;
422
460
let inverse_view_transform = view_transform. inverse ( ) ;
423
461
let cluster_count = clusters. aabbs . len ( ) ;
424
- let z_slices_of_ln_zfar_over_znear =
425
- clusters. axis_slices . z as f32 / ( camera. far / camera. near ) . ln ( ) ;
426
- let cluster_factors = Vec2 :: new (
427
- z_slices_of_ln_zfar_over_znear,
428
- camera. near . ln ( ) * z_slices_of_ln_zfar_over_znear,
462
+ let is_orthographic = camera. projection_matrix . w_axis . w == 1.0 ;
463
+ let cluster_factors = calculate_cluster_factors (
464
+ camera. near ,
465
+ camera. far ,
466
+ clusters. axis_slices . z as f32 ,
467
+ is_orthographic,
429
468
) ;
430
469
431
470
let mut clusters_lights =
@@ -501,12 +540,14 @@ pub fn assign_lights_to_clusters(
501
540
let min_cluster = ndc_position_to_cluster (
502
541
clusters. axis_slices ,
503
542
cluster_factors,
543
+ is_orthographic,
504
544
light_aabb_ndc_min,
505
545
light_aabb_view_min. z ,
506
546
) ;
507
547
let max_cluster = ndc_position_to_cluster (
508
548
clusters. axis_slices ,
509
549
cluster_factors,
550
+ is_orthographic,
510
551
light_aabb_ndc_max,
511
552
light_aabb_view_max. z ,
512
553
) ;
0 commit comments