Skip to content

Commit 65aa6a4

Browse files
pcwaltonknutsoned
authored andcommitted
Implement PBR anisotropy per KHR_materials_anisotropy. (bevyengine#13450)
This commit implements support for physically-based anisotropy in Bevy's `StandardMaterial`, following the specification for the [`KHR_materials_anisotropy`] glTF extension. [*Anisotropy*] (not to be confused with [anisotropic filtering]) is a PBR feature that allows roughness to vary along the tangent and bitangent directions of a mesh. In effect, this causes the specular light to stretch out into lines instead of a round lobe. This is useful for modeling brushed metal, hair, and similar surfaces. Support for anisotropy is a common feature in major game and graphics engines; Unity, Unreal, Godot, three.js, and Blender all support it to varying degrees. Two new parameters have been added to `StandardMaterial`: `anisotropy_strength` and `anisotropy_rotation`. Anisotropy strength, which ranges from 0 to 1, represents how much the roughness differs between the tangent and the bitangent of the mesh. In effect, it controls how stretched the specular highlight is. Anisotropy rotation allows the roughness direction to differ from the tangent of the model. In addition to these two fixed parameters, an *anisotropy texture* can be supplied. Such a texture should be a 3-channel RGB texture, where the red and green values specify a direction vector using the same conventions as a normal map ([0, 1] color values map to [-1, 1] vector values), and the the blue value represents the strength. This matches the format that the [`KHR_materials_anisotropy`] specification requires. Such textures should be loaded as linear and not sRGB. Note that this texture does consume one additional texture binding in the standard material shader. The glTF loader has been updated to properly parse the `KHR_materials_anisotropy` extension. A new example, `anisotropy`, has been added. This example loads and displays the barn lamp example from the [`glTF-Sample-Assets`] repository. Note that the textures were rather large, so I shrunk them down and converted them to a mixture of JPEG and KTX2 format, in the interests of saving space in the Bevy repository. [*Anisotropy*]: https://google.github.io/filament/Filament.md.html#materialsystem/anisotropicmodel [anisotropic filtering]: https://en.wikipedia.org/wiki/Anisotropic_filtering [`KHR_materials_anisotropy`]: https://github.com/KhronosGroup/glTF/blob/main/extensions/2.0/Khronos/KHR_materials_anisotropy/README.md [`glTF-Sample-Assets`]: https://github.com/KhronosGroup/glTF-Sample-Assets/ * Physically-based anisotropy is now available for materials, which enhances the look of surfaces such as brushed metal or hair. glTF scenes can use the new feature with the `KHR_materials_anisotropy` extension. With anisotropy: ![Screenshot 2024-05-20 233414](https://github.com/bevyengine/bevy/assets/157897/379f1e42-24e9-40b6-a430-f7d1479d0335) Without anisotropy: ![Screenshot 2024-05-20 233420](https://github.com/bevyengine/bevy/assets/157897/aa220f05-b8e7-417c-9671-b242d4bf9fc4)
1 parent 1e81fc4 commit 65aa6a4

File tree

2 files changed

+26
-3
lines changed

2 files changed

+26
-3
lines changed

crates/bevy_pbr/src/render/pbr_functions.wgsl

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -181,6 +181,7 @@ fn apply_normal_mapping(
181181
double_sided: bool,
182182
is_front: bool,
183183
in_Nt: vec3<f32>,
184+
mip_bias: f32,
184185
) -> vec3<f32> {
185186
// Unpack the TBN vectors.
186187
var T = TBN[0];

examples/3d/anisotropy.rs

Lines changed: 25 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -78,14 +78,14 @@ fn setup(mut commands: Commands, asset_server: Res<AssetServer>, app_status: Res
7878
..default()
7979
});
8080

81-
spawn_text(&mut commands, &app_status);
81+
spawn_text(&mut commands, &asset_server, &app_status);
8282
}
8383

8484
/// Spawns the help text.
85-
fn spawn_text(commands: &mut Commands, app_status: &AppStatus) {
85+
fn spawn_text(commands: &mut Commands, asset_server: &AssetServer, app_status: &AppStatus) {
8686
commands.spawn(
8787
TextBundle {
88-
text: app_status.create_help_text(),
88+
text: app_status.create_help_text(asset_server),
8989
..default()
9090
}
9191
.with_style(Style {
@@ -223,9 +223,19 @@ fn handle_input(
223223
}
224224

225225
/// A system that updates the help text based on the current app status.
226+
<<<<<<< HEAD
226227
fn update_help_text(mut text_query: Query<&mut Text>, app_status: Res<AppStatus>) {
227228
for mut text in text_query.iter_mut() {
228229
*text = app_status.create_help_text();
230+
=======
231+
fn update_help_text(
232+
mut text_query: Query<&mut Text>,
233+
app_status: Res<AppStatus>,
234+
asset_server: Res<AssetServer>,
235+
) {
236+
for mut text in text_query.iter_mut() {
237+
*text = app_status.create_help_text(&asset_server);
238+
>>>>>>> ef156ebb0 (Implement PBR anisotropy per `KHR_materials_anisotropy`. (#13450))
229239
}
230240
}
231241

@@ -274,7 +284,11 @@ fn spawn_point_light(commands: &mut Commands) {
274284

275285
impl AppStatus {
276286
/// Creates the help text as appropriate for the current app status.
287+
<<<<<<< HEAD
277288
fn create_help_text(&self) -> Text {
289+
=======
290+
fn create_help_text(&self, asset_server: &AssetServer) -> Text {
291+
>>>>>>> ef156ebb0 (Implement PBR anisotropy per `KHR_materials_anisotropy`. (#13450))
278292
// Choose the appropriate help text for the anisotropy toggle.
279293
let material_variant_help_text = if self.anisotropy_enabled {
280294
"Press Enter to disable anisotropy"
@@ -292,7 +306,15 @@ impl AppStatus {
292306
// Build the `Text` object.
293307
Text::from_section(
294308
format!("{}\n{}", material_variant_help_text, light_help_text),
309+
<<<<<<< HEAD
295310
TextStyle::default(),
311+
=======
312+
TextStyle {
313+
font: asset_server.load("fonts/FiraMono-Medium.ttf"),
314+
font_size: 24.0,
315+
..default()
316+
},
317+
>>>>>>> ef156ebb0 (Implement PBR anisotropy per `KHR_materials_anisotropy`. (#13450))
296318
)
297319
}
298320
}

0 commit comments

Comments
 (0)