Skip to content

Commit b7ca6ec

Browse files
committed
Parametrize MAX_STEPS, fix iteration count
1 parent 6863000 commit b7ca6ec

File tree

6 files changed

+38
-10
lines changed

6 files changed

+38
-10
lines changed

crates/bevy_pbr/src/parallax.rs

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use bevy_reflect::{FromReflect, Reflect};
22

3-
/// The parallax mapping method to use to compute a displacement based on the
3+
/// The parallax mapping method to use to compute depth based on the
44
/// material's [`depth_map`].
55
///
66
/// See the `parallax_mapping.wgsl` shader code for implementation details
@@ -12,9 +12,25 @@ pub enum ParallaxMappingMethod {
1212
/// A simple linear interpolation, using a single texture sample.
1313
#[default]
1414
ParallaxOcclusionMapping,
15-
/// A discovery of 5 iterations of the best displacement
16-
/// value. Each iteration incurs a texture sample.
15+
/// Discovers the best depth value based on binary search.
1716
///
17+
/// Each iteration incurs a texture sample.
1818
/// The result has fewer visual artifacts than `ParallaxOcclusionMapping`.
19-
ReliefMapping { n_steps: u32 },
19+
ReliefMapping {
20+
/// How many additional steps to use at most to find the depth value.
21+
max_steps: u32,
22+
},
23+
}
24+
impl ParallaxMappingMethod {
25+
/// [`ReliefMapping`] with a 5 steps, a reasonable default.
26+
///
27+
/// [`ReliefMapping`]: Self::ReliefMapping
28+
pub const DEFAULT_RELIEF_MAPPING: Self = ParallaxMappingMethod::ReliefMapping { max_steps: 5 };
29+
30+
pub(crate) fn max_steps(&self) -> u32 {
31+
match self {
32+
ParallaxMappingMethod::ParallaxOcclusionMapping => 0,
33+
ParallaxMappingMethod::ReliefMapping { max_steps } => *max_steps,
34+
}
35+
}
2036
}

crates/bevy_pbr/src/pbr_material.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -431,6 +431,9 @@ pub struct StandardMaterialUniform {
431431
/// If your `parallax_depth` is >0.1 and you are seeing jaggy edges,
432432
/// increase this value. However, this incurs a performance cost.
433433
pub max_parallax_layer_count: f32,
434+
/// Using [`ParallaxMappingMethod::ReliefMapping`], how many additional
435+
/// steps to use at most to find the depth value.
436+
pub max_relief_mapping_search_steps: u32,
434437
}
435438

436439
impl AsBindGroupShaderType<StandardMaterialUniform> for StandardMaterial {
@@ -502,6 +505,7 @@ impl AsBindGroupShaderType<StandardMaterialUniform> for StandardMaterial {
502505
alpha_cutoff,
503506
parallax_depth: self.parallax_depth,
504507
max_parallax_layer_count: self.max_parallax_layer_count,
508+
max_relief_mapping_search_steps: self.parallax_mapping_method.max_steps(),
505509
}
506510
}
507511
}

crates/bevy_pbr/src/render/parallax_mapping.wgsl

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ fn sample_depth_map(uv: vec2<f32>) -> f32 {
99
fn parallaxed_uv(
1010
depth: f32,
1111
max_layer_count: f32,
12+
max_steps: u32,
1213
// The original uv
1314
uv: vec2<f32>,
1415
// The vector from camera to the surface of material
@@ -42,7 +43,7 @@ fn parallaxed_uv(
4243
var current_height = sample_depth_map(uv);
4344

4445
// This at most runs layer_count times
45-
for (var i: i32 = 0; current_height > current_layer_height && i < i32(layer_count); i++) {
46+
for (var i: i32 = 0; current_height > current_layer_height && i <= i32(layer_count); i++) {
4647
current_layer_height += layer_height;
4748
uv -= delta_uv;
4849
current_height = sample_depth_map(uv);
@@ -55,13 +56,12 @@ fn parallaxed_uv(
5556
// with a binary search between the layer selected by steep parallax
5657
// and the next one to find a point closer to the depth map surface.
5758
// This reduces the jaggy step artifacts from steep parallax mapping.
58-
let MAX_STEPS: i32 = 5;
5959

6060
delta_uv *= 0.5;
6161
var delta_height = 0.5 * layer_height;
6262
uv += delta_uv;
6363
current_layer_height -= delta_height;
64-
for (var i: i32 = 0; i < MAX_STEPS; i++) {
64+
for (var i: u32 = 0u; i < max_steps; i++) {
6565
// Sample depth at current offset
6666
current_height = sample_depth_map(uv);
6767

crates/bevy_pbr/src/render/pbr.wgsl

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,13 @@ fn fragment(in: FragmentInput) -> @location(0) vec4<f32> {
3232
dot(V, -cross(in.world_normal, in.world_tangent.xyz) * sign(in.world_tangent.w)),
3333
dot(V, in.world_normal),
3434
);
35-
uv = parallaxed_uv(material.parallax_depth, material.max_parallax_layer_count, uv, tangent_V);
35+
uv = parallaxed_uv(
36+
material.parallax_depth,
37+
material.max_parallax_layer_count,
38+
material.max_relief_mapping_search_steps,
39+
uv,
40+
tangent_V,
41+
);
3642
}
3743
#endif
3844
#endif

crates/bevy_pbr/src/render/pbr_types.wgsl

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ struct StandardMaterial {
1111
alpha_cutoff: f32,
1212
parallax_depth: f32,
1313
max_parallax_layer_count: f32,
14+
max_relief_mapping_search_steps: u32,
1415
};
1516

1617
const STANDARD_MATERIAL_FLAGS_BASE_COLOR_TEXTURE_BIT: u32 = 1u;
@@ -47,6 +48,7 @@ fn standard_material_new() -> StandardMaterial {
4748
material.alpha_cutoff = 0.5;
4849
material.parallax_depth = 0.1;
4950
material.max_parallax_layer_count = 16.0;
51+
material.max_relief_mapping_search_steps = 5u;
5052

5153
return material;
5254
}

examples/3d/parallax_mapping.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,7 @@ fn switch_algo(
9090
if input.just_pressed(KeyCode::Space) {
9191
*current = match *current {
9292
ReliefMapping { .. } => ParallaxOcclusionMapping,
93-
ParallaxOcclusionMapping => ReliefMapping { n_steps: 5 },
93+
ParallaxOcclusionMapping => ReliefMapping { max_steps: 5 },
9494
}
9595
} else {
9696
return;
@@ -258,7 +258,7 @@ fn setup(
258258
// white the lowest.
259259
depth_map: Some(asset_server.load("textures/parallax_example/cube_depth.jpg")),
260260
parallax_depth,
261-
parallax_mapping_method: ParallaxMappingMethod::ReliefMapping { n_steps: 5 },
261+
parallax_mapping_method: ParallaxMappingMethod::DEFAULT_RELIEF_MAPPING,
262262
max_parallax_layer_count,
263263
..default()
264264
});

0 commit comments

Comments
 (0)