Skip to content

Commit d68093b

Browse files
committed
Update to bevy 0.10, rust-gpu-bridge 0.3, permutate-macro 0.4
1 parent de4864c commit d68093b

17 files changed

+1271
-108
lines changed

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,4 +10,4 @@ crate_type = ["dylib", "rlib"]
1010
bitflags = "1.3.2"
1111
spirv-std = { version = "0.5.0", features = ["glam"] }
1212
permutate-macro = { git = "https://github.com/Bevy-Rust-GPU/permutate-macro", tag = "v0.4.0" }
13-
rust-gpu-bridge = { git = "https://github.com/Bevy-Rust-GPU/rust-gpu-bridge", tag = "v0.2.0", features = ["spirv-std"] }
13+
rust-gpu-bridge = { git = "https://github.com/Bevy-Rust-GPU/rust-gpu-bridge", tag = "v0.3.0", features = ["spirv-std"] }

src/clustered_forward.rs

Lines changed: 25 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,11 @@ pub const CLUSTER_COUNT_SIZE: u32 = 9;
1313

1414
// Cluster allocation debug (using 'over' alpha blending)
1515
pub trait ClusterDebugVisualization {
16-
fn cluster_debug_visualization(
17-
lights: &Lights,
16+
fn cluster_debug_visualization<
17+
const MAX_DIRECTIONAL_LIGHTS: usize,
18+
const MAX_CASCADES_PER_LIGHT: usize,
19+
>(
20+
lights: &Lights<MAX_DIRECTIONAL_LIGHTS, MAX_CASCADES_PER_LIGHT>,
1821
output_color: Vec4,
1922
view_z: f32,
2023
is_orthographic: bool,
@@ -24,8 +27,11 @@ pub trait ClusterDebugVisualization {
2427
}
2528

2629
impl ClusterDebugVisualization for () {
27-
fn cluster_debug_visualization(
28-
_: &Lights,
30+
fn cluster_debug_visualization<
31+
const MAX_DIRECTIONAL_LIGHTS: usize,
32+
const MAX_CASCADES_PER_LIGHT: usize,
33+
>(
34+
_: &Lights<MAX_DIRECTIONAL_LIGHTS, MAX_CASCADES_PER_LIGHT>,
2935
output_color: Vec4,
3036
_: f32,
3137
_: bool,
@@ -39,8 +45,11 @@ impl ClusterDebugVisualization for () {
3945
pub enum DebugZSlices {}
4046

4147
impl ClusterDebugVisualization for DebugZSlices {
42-
fn cluster_debug_visualization(
43-
lights: &Lights,
48+
fn cluster_debug_visualization<
49+
const MAX_DIRECTIONAL_LIGHTS: usize,
50+
const MAX_CASCADES_PER_LIGHT: usize,
51+
>(
52+
lights: &Lights<MAX_DIRECTIONAL_LIGHTS, MAX_CASCADES_PER_LIGHT>,
4453
output_color: Vec4,
4554
view_z: f32,
4655
is_orthographic: bool,
@@ -69,8 +78,11 @@ impl ClusterDebugVisualization for DebugZSlices {
6978
pub enum DebugClusterLightComplexity {}
7079

7180
impl ClusterDebugVisualization for DebugClusterLightComplexity {
72-
fn cluster_debug_visualization(
73-
_: &Lights,
81+
fn cluster_debug_visualization<
82+
const MAX_DIRECTIONAL_LIGHTS: usize,
83+
const MAX_CASCADES_PER_LIGHT: usize,
84+
>(
85+
_: &Lights<MAX_DIRECTIONAL_LIGHTS, MAX_CASCADES_PER_LIGHT>,
7486
mut output_color: Vec4,
7587
_: f32,
7688
_: bool,
@@ -100,8 +112,11 @@ impl ClusterDebugVisualization for DebugClusterLightComplexity {
100112
pub enum DebugClusterCoherency {}
101113

102114
impl ClusterDebugVisualization for DebugClusterCoherency {
103-
fn cluster_debug_visualization(
104-
_: &Lights,
115+
fn cluster_debug_visualization<
116+
const MAX_DIRECTIONAL_LIGHTS: usize,
117+
const MAX_CASCADES_PER_LIGHT: usize,
118+
>(
119+
_: &Lights<MAX_DIRECTIONAL_LIGHTS, MAX_CASCADES_PER_LIGHT>,
105120
output_color: Vec4,
106121
_: f32,
107122
_: bool,

src/environment_map.rs

Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
use rust_gpu_bridge::{
2+
glam::{Vec2, Vec3, Vec4},
3+
pow::Pow,
4+
};
5+
use spirv_std::Sampler;
6+
7+
use crate::prelude::{Lights, TextureCube};
8+
9+
pub trait EnvironmentMap {
10+
fn environment_map_light<
11+
const MAX_DIRECTIONAL_LIGHTS: usize,
12+
const MAX_CASCADES_PER_LIGHT: usize,
13+
>(
14+
lights: &Lights<MAX_DIRECTIONAL_LIGHTS, MAX_CASCADES_PER_LIGHT>,
15+
environment_map_diffuse: &TextureCube,
16+
environment_map_specular: &TextureCube,
17+
environment_map_sampler: &Sampler,
18+
perceptual_roughness: f32,
19+
roughness: f32,
20+
diffuse_color: Vec3,
21+
n_dot_v: f32,
22+
f_ab: Vec2,
23+
n: Vec3,
24+
r: Vec3,
25+
f0: Vec3,
26+
) -> EnvironmentMapLight;
27+
}
28+
29+
impl EnvironmentMap for () {
30+
fn environment_map_light<
31+
const MAX_DIRECTIONAL_LIGHTS: usize,
32+
const MAX_CASCADES_PER_LIGHT: usize,
33+
>(
34+
lights: &Lights<MAX_DIRECTIONAL_LIGHTS, MAX_CASCADES_PER_LIGHT>,
35+
environment_map_diffuse: &TextureCube,
36+
environment_map_specular: &TextureCube,
37+
environment_map_sampler: &Sampler,
38+
perceptual_roughness: f32,
39+
roughness: f32,
40+
diffuse_color: Vec3,
41+
n_dot_v: f32,
42+
f_ab: Vec2,
43+
n: Vec3,
44+
r: Vec3,
45+
f0: Vec3,
46+
) -> EnvironmentMapLight {
47+
Default::default()
48+
}
49+
}
50+
51+
#[derive(Default, Copy, Clone, PartialEq)]
52+
pub struct EnvironmentMapLight {
53+
pub diffuse: Vec3,
54+
pub specular: Vec3,
55+
}
56+
57+
impl EnvironmentMap for EnvironmentMapLight {
58+
fn environment_map_light<
59+
const MAX_DIRECTIONAL_LIGHTS: usize,
60+
const MAX_CASCADES_PER_LIGHT: usize,
61+
>(
62+
lights: &Lights<MAX_DIRECTIONAL_LIGHTS, MAX_CASCADES_PER_LIGHT>,
63+
environment_map_diffuse: &TextureCube,
64+
environment_map_specular: &TextureCube,
65+
environment_map_sampler: &Sampler,
66+
perceptual_roughness: f32,
67+
roughness: f32,
68+
diffuse_color: Vec3,
69+
n_dot_v: f32,
70+
f_ab: Vec2,
71+
n: Vec3,
72+
r: Vec3,
73+
f0: Vec3,
74+
) -> EnvironmentMapLight {
75+
// Split-sum approximation for image based lighting: https://cdn2.unrealengine.com/Resources/files/2013SiggraphPresentationsNotes-26915738.pdf
76+
// Technically we could use textureNumLevels(environment_map_specular) - 1 here, but we use a uniform
77+
// because textureNumLevels() does not work on WebGL2
78+
let radiance_level =
79+
perceptual_roughness * (lights.environment_map_smallest_specular_mip_level) as f32;
80+
let irradiance = environment_map_diffuse
81+
.sample::<f32, Vec4>(*environment_map_sampler, n)
82+
.truncate();
83+
let radiance = environment_map_specular
84+
.sample_by_lod::<f32, Vec4>(*environment_map_sampler, r, radiance_level)
85+
.truncate();
86+
87+
// Multiscattering approximation: https://www.jcgt.org/published/0008/01/03/paper.pdf
88+
// Useful reference: https://bruop.github.io/ibl
89+
let fr = Vec3::splat(1.0 - roughness).max(f0) - f0;
90+
let ks = f0 + fr * (1.0 - n_dot_v).pow(5.0);
91+
let fss_ess = ks * f_ab.x + f_ab.y;
92+
let ess = f_ab.x + f_ab.y;
93+
let ems = 1.0 - ess;
94+
let favg = f0 + (1.0 - f0) / 21.0;
95+
let fms = fss_ess * favg / (1.0 - ems * favg);
96+
let fms_ems = fms * ems;
97+
let edss = 1.0 - (fss_ess + fms_ems);
98+
let kd = diffuse_color * edss;
99+
100+
EnvironmentMapLight {
101+
diffuse: (fms_ems + kd) * irradiance,
102+
specular: fss_ess * radiance,
103+
}
104+
}
105+
}

src/fog.rs

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
// Fog formulas adapted from:
2+
// https://learn.microsoft.com/en-us/windows/win32/direct3d9/fog-formulas
3+
// https://catlikecoding.com/unity/tutorials/rendering/part-14/
4+
// https://iquilezles.org/articles/fog/ (Atmospheric Fog and Scattering)
5+
6+
use rust_gpu_bridge::glam::{Vec3, Vec4};
7+
use spirv_std::num_traits::Float;
8+
9+
// Important: These must be kept in sync with `fog.rs`
10+
pub const FOG_MODE_OFF: u32 = 0;
11+
pub const FOG_MODE_LINEAR: u32 = 1;
12+
pub const FOG_MODE_EXPONENTIAL: u32 = 2;
13+
pub const FOG_MODE_EXPONENTIAL_SQUARED: u32 = 3;
14+
pub const FOG_MODE_ATMOSPHERIC: u32 = 4;
15+
16+
#[repr(C, packed(4))]
17+
pub struct Fog {
18+
pub base_color: Vec4,
19+
pub directional_light_color: Vec4,
20+
// `be` and `bi` are allocated differently depending on the fog mode
21+
//
22+
// For Linear Fog:
23+
// be.x = start, be.y = end
24+
// For Exponential and ExponentialSquared Fog:
25+
// be.x = density
26+
// For Atmospheric Fog:
27+
// be = per-channel extinction density
28+
// bi = per-channel inscattering density
29+
//pub be: Vec3,
30+
pub be_x: f32,
31+
pub be_y: f32,
32+
pub be_z: f32,
33+
pub directional_light_exponent: f32,
34+
//pub bi: Vec3,
35+
pub bi_x: f32,
36+
pub bi_y: f32,
37+
pub bi_z: f32,
38+
pub mode: u32,
39+
}
40+
41+
impl Fog {
42+
pub fn scattering_adjusted_fog_color(&self, scattering: Vec3) -> Vec4 {
43+
if self.directional_light_color.w > 0.0 {
44+
return (self.base_color.truncate()
45+
+ scattering
46+
* self.directional_light_color.truncate()
47+
* self.directional_light_color.w)
48+
.extend(self.base_color.w);
49+
} else {
50+
return self.base_color;
51+
}
52+
}
53+
54+
pub fn linear_fog(&self, input_color: Vec4, distance: f32, scattering: Vec3) -> Vec4 {
55+
let mut fog_color = self.scattering_adjusted_fog_color(scattering);
56+
let start = self.be_x;
57+
let end = self.be_y;
58+
fog_color.w *= 1.0 - ((end - distance) / (end - start)).clamp(0.0, 1.0);
59+
return input_color
60+
.truncate()
61+
.lerp(fog_color.truncate(), fog_color.w)
62+
.extend(input_color.w);
63+
}
64+
65+
pub fn exponential_fog(&self, input_color: Vec4, distance: f32, scattering: Vec3) -> Vec4 {
66+
let mut fog_color = self.scattering_adjusted_fog_color(scattering);
67+
let density = self.be_x;
68+
fog_color.w *= 1.0 - 1.0 / (distance * density).exp();
69+
return input_color
70+
.truncate()
71+
.lerp(fog_color.truncate(), fog_color.w)
72+
.extend(input_color.w);
73+
}
74+
75+
pub fn exponential_squared_fog(&self, input_color: Vec4, distance: f32, scattering: Vec3) -> Vec4 {
76+
let mut fog_color = self.scattering_adjusted_fog_color(scattering);
77+
let distance_times_density = distance * self.be_x;
78+
fog_color.w *= 1.0 - 1.0 / (distance_times_density * distance_times_density).exp();
79+
return input_color
80+
.truncate()
81+
.lerp(fog_color.truncate(), fog_color.w)
82+
.extend(input_color.w);
83+
}
84+
85+
pub fn atmospheric_fog(&self, input_color: Vec4, distance: f32, scattering: Vec3) -> Vec4 {
86+
let fog_color = self.scattering_adjusted_fog_color(scattering);
87+
let extinction_factor = 1.0 - 1.0 / (distance * Vec3::new(self.be_x, self.be_y, self.be_z)).exp();
88+
let inscattering_factor = 1.0 - 1.0 / (distance * Vec3::new(self.bi_x, self.bi_y, self.bi_z)).exp();
89+
return (input_color.truncate() * (1.0 - extinction_factor * fog_color.w)
90+
+ fog_color.truncate() * inscattering_factor * fog_color.w)
91+
.extend(input_color.w);
92+
}
93+
}

src/lib.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,12 @@
33
use rust_gpu_bridge::glam;
44

55
pub mod clustered_forward;
6+
pub mod fog;
67
pub mod mesh;
78
pub mod mesh_view;
89
pub mod pbr;
910
pub mod prelude;
1011
pub mod shadows;
1112
pub mod skinning;
1213
pub mod tonemapping_shared;
13-
14+
pub mod environment_map;

src/mesh/entry_points.rs

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,9 +20,25 @@ use super::mesh_position_local_to_world;
2020
color: some | none,
2121
skinned: some | none
2222
},
23+
constants = {},
2324
permutations = [
24-
(none, none, none),
25-
(some, some, some),
25+
{
26+
parameters = [
27+
none,
28+
none,
29+
none
30+
],
31+
constants = {}
32+
},
33+
{
34+
parameters = [
35+
some,
36+
some,
37+
some
38+
],
39+
constants = {
40+
}
41+
},
2642
file("../../entry_points.json", "mesh::entry_points"),
2743
env("BEVY_PBR_RUST_MESH_VERTEX_PERMUTATIONS", "mesh::entry_points")
2844
]

src/mesh_view/bindings.rs

Lines changed: 57 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,64 @@
1-
use spirv_std::Image;
1+
use spirv_std::{spirv, Image, Sampler};
22

3+
use crate::{
4+
fog::Fog,
5+
prelude::{
6+
ClusterLightIndexLists, ClusterOffsetsAndCounts, DirectionalShadowTextures, Globals,
7+
Lights, PointLights, PointShadowTextures, View,
8+
},
9+
};
10+
11+
pub type Texture2d = Image!(2D, type = f32, sampled = true);
12+
pub type Texture3d = Image!(3D, type = f32, sampled = true);
13+
pub type TextureCube = Image!(cube, type = f32, sampled = true);
314
pub type TextureDepthCube = Image!(cube, type = f32, sampled = true, depth = true);
415
pub type TextureDepthCubeArray =
516
Image!(cube, type = f32, sampled = true, depth = true, arrayed = true);
617

718
pub type TextureDepth2d = Image!(2D, type = f32, sampled = true, depth = true);
819
pub type TextureDepth2dArray = Image!(2D, type = f32, sampled = true, depth = true, arrayed = true);
20+
21+
pub type TextureMultisampled2d = Image!(2D, type = f32, sampled = true, multisampled = true);
22+
pub type TextureDepthMultisampled2d =
23+
Image!(2D, type = f32, sampled = true, multisampled = true, depth = true);
24+
25+
pub trait DepthPrepassTexture {}
26+
27+
impl DepthPrepassTexture for TextureDepthMultisampled2d {}
28+
impl DepthPrepassTexture for TextureDepth2d {}
29+
30+
pub trait NormalPrepassTexture {}
31+
32+
impl NormalPrepassTexture for TextureMultisampled2d {}
33+
impl NormalPrepassTexture for Texture2d {}
34+
35+
#[allow(unused_variables)]
36+
#[spirv(fragment)]
37+
pub fn mesh_view_bindings<
38+
const MAX_DIRECTIONAL_LIGHTS: usize,
39+
const MAX_CASCADES_PER_LIGHT: usize,
40+
>(
41+
#[spirv(uniform, descriptor_set = 0, binding = 0)] view: &View,
42+
#[spirv(descriptor_set = 0, binding = 1)] lights: &Lights<
43+
MAX_DIRECTIONAL_LIGHTS,
44+
MAX_CASCADES_PER_LIGHT,
45+
>,
46+
#[spirv(descriptor_set = 0, binding = 2)] point_shadow_textures: &impl PointShadowTextures,
47+
#[spirv(descriptor_set = 0, binding = 3)] point_shadow_textures_sampler: &Sampler,
48+
#[spirv(descriptor_set = 0, binding = 4)]
49+
directional_shadow_textures: &impl DirectionalShadowTextures,
50+
#[spirv(descriptor_set = 0, binding = 5)] directional_shadow_textures_sampler: &Sampler,
51+
#[spirv(descriptor_set = 0, binding = 6)] point_lights: &impl PointLights,
52+
#[spirv(descriptor_set = 0, binding = 7)] cluster_light_index_lists: &impl ClusterLightIndexLists,
53+
#[spirv(descriptor_set = 0, binding = 8)] cluster_offsets_and_counts: &impl ClusterOffsetsAndCounts,
54+
#[spirv(descriptor_set = 0, binding = 9)] globals: &Globals,
55+
#[spirv(descriptor_set = 0, binding = 10)] fog: &Fog,
56+
#[spirv(descriptor_set = 0, binding = 11)] environment_map_diffuse: &TextureCube,
57+
#[spirv(descriptor_set = 0, binding = 12)] environment_map_specular: &TextureCube,
58+
#[spirv(descriptor_set = 0, binding = 13)] environment_map_sampler: &Sampler,
59+
#[spirv(descriptor_set = 0, binding = 14)] dt_lut_texture: &Texture3d,
60+
#[spirv(descriptor_set = 0, binding = 15)] dt_lut_sampler: &Sampler,
61+
#[spirv(descriptor_set = 0, binding = 16)] depth_prepass_texture: &impl DepthPrepassTexture,
62+
#[spirv(descriptor_set = 0, binding = 17)] normal_prepass_texture: &impl NormalPrepassTexture,
63+
) {
64+
}

0 commit comments

Comments
 (0)