Strange artifact with PBR `perceptual_roughness` set to 0
- Dominant language
- Rust
- Stars
- 48.2k
- Forks
- 4.8k
- Avg merge
- 3d 16h
- Merged PRs (30d)
- 171
Description
## Bevy version
Commit 2a66bf0909992b280420442ecda42a38d37de326 (latest main at time of writing).
## Relevant system information
AMD Ryzen 9 7950X3D Integrated Graphics (RDNA 2) on latest Arch Linux
```ignore
INFO bevy_render::renderer: AdapterInfo {
name: "AMD Radeon Graphics (RADV RAPHAEL_MENDOCINO)",
vendor: 4098,
device: 5710,
device_type: IntegratedGpu,
driver: "radv",
driver_info: "Mesa 24.2.7-arch1.1",
backend: Vulkan
}
```
## What you did
Created a PBR material with `perceptual_roughness` 0.0. Here is a small example using a mesh I generated to reproduce, with light moving to make it more obvious.
```rs
use bevy::{
asset::RenderAssetUsages,
color::palettes::css::DEEP_PINK,
pbr::wireframe::{WireframeConfig, WireframePlugin},
prelude::*,
render::mesh::{Indices, PrimitiveTopology},
};
fn main() {
App::new()
.add_plugins((DefaultPlugins, WireframePlugin))
.add_systems(Startup, setup)
.add_systems(Update, light_rotate)
.insert_resource(WireframeConfig {
global: true,
..default()
})
.run();
}
fn setup(
mut commands: Commands,
mut meshes: ResMut>,
mut materials: ResMut>,
) {
let mut mesh = Mesh::new(
PrimitiveTopology::TriangleList,
RenderAssetUsages::RENDER_WORLD,
);
mesh.insert_attribute(
Mesh::ATTRIBUTE_POSITION,
vec![
[0.0, 0.24613905, 0.49612403],
[0.24806201, 0.6153476, 0.74418604],
[0.24806201, 0.3076738, 0.49612403],
[0.49612403, 0.4922781, 0.49612403],
[0.0, 0.9845562, 0.99224806],
[0.0, 0.55381286, 0.74418604],
[0.24806201, 0.123069525, 0.24806201],
[0.0, 0.061534762, 0.24806201],
[0.0, 0.0, 0.0],
[0.49612403, 1.2306952, 0.99224806],
[0.74418604, 1.1076257, 0.74418604],
[0.49612403, 0.7999519, 0.74418604],
[0.99224806, 1.9691124, 0.99224806],
[0.74418604, 1.538369, 0.99224806],
[0.24806201, 1.046091, 0.99224806],
[0.99224806, 1.2306952, 0.49612403],
[0.74418604, 0.6153476, 0.24806201],
[0.74418604, 0.7999519, 0.49612403],
[0.99224806, 0.9845562, 0.0],
[0.99224806, 1.046091, 0.24806201],
[0.99224806, 1.538369, 0.74418604],
[0.49612403, 0.24613905, 0.0],
[0.49612403, 0.3076738, 0.24806201],
[0.24806201, 0.061534762, 0.0],
[0.74418604, 0.55381286, 0.0],
],
);
mesh.insert_attribute(
Mesh::ATTRIBUTE_NORMAL,
vec![
[0.0, 1.0, -0.99224806],
[0.49612114, 1.0, -1.4883711],
[0.49612308, 1.0, -0.99224806],
[0.99224806, 1.0, -0.99224806],
[0.0, 1.0, 0.0],
[0.0, 1.0, -1.4883711],
[0.49612355, 1.0, -0.49612355],
[0.0, 1.0, -0.49612427],
[0.0, 1.0, 0.0],
[0.99224997, 1.0, 0.0],
[1.488375, 1.0, -1.488375],
[0.99224615, 1.0, -1.4883711],
[0.0, 1.0, 0.0],
[1.4883673, 1.0, 0.0],
[0.49612498, 1.0, 0.0],
[0.0, 1.0, -0.99224997],
[1.4883711, 1.0, -0.49612114],
[1.4883711, 1.0, -0.99224615],
[0.0, 1.0, 0.0],
[0.0, 1.0, -0.49612498],
[0.0, 1.0, -1.4883673],
[0.99224806, 1.0, 0.0],
[0.99224806, 1.0, -0.49612308],
[0.49612427, 1.0, 0.0],
[1.4883711, 1.0, 0.0],
],
);
mesh.insert_indices(Indices::U32(vec![
0, 1, 2, 1, 3, 2, 4, 1, 5, 1, 0, 5, 0, 6, 7, 6, 8, 7, 3, 6, 2, 6, 0, 2, 9, 10, 11, 10, 3,
11, 12, 10, 13, 10, 9, 13, 9, 1, 14, 1, 4, 14, 3, 1, 11, 1, 9, 11, 15, 16, 17, 16, 3, 17,
18, 16, 19, 16, 15, 19, 15, 10, 20, 10, 12, 20, 3, 10, 17, 10, 15, 17, 21, 6, 22, 6, 3, 22,
8, 6, 23, 6, 21, 23, 21, 16, 24, 16, 18, 24, 3, 16, 22, 16, 21, 22,
]));
let light_angle = -91f32.to_radians();
commands.spawn((
PointLight::default(),
Transform::from_xyz(light_angle.cos(), 2.0, light_angle.sin()),
));
commands.spawn((
Mesh3d(meshes.add(mesh)),
MeshMaterial3d(materials.add(StandardMaterial {
base_color: DEEP_PINK.into(),
perceptual_roughness: 0.0,
..default()
})),
Transform::from_xyz(0.0, 0.0, 0.0)
.with_rotation(Quat::from_rotation_y(90f32.to_radians()))
.with_scale(Vec3::ONE * 2.0),
));
commands.spawn((
Camera3d::default(),
Transform::from_xyz(0.0, 4.0, 8.0).looking_at(Vec3::ZERO, Vec3::Y),
));
}
fn light_rotate(mut light: Query<&mut Transform, With>, time: Res
## What went wrong
The surface presents black line artifacts. I apologize as this is not made super obvious on this attempt at reproducing minimally, the example below from my project shows it better.

This is a more obvious example from my project, same style of artifact but more pronounced somehow:

Notice that it seems to follow shadows in some way:

And it does not appear to follow triangles:

## Additional information
Is this a case of the 0.0 roughness making the color fall into a pole?
Contributor guide
Research direction
Start with the supplied minimal reproduction, especially the setup function's StandardMaterial using perceptual_roughness: 0.0 and the light_rotate system. Reproduce the black line artifacts while moving the light, then determine whether the behavior is caused by zero roughness and identify the rendering change needed to eliminate it.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- rust
- Domain
- computer-graphics, game-dev
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Needs clarification
- Newbie friendliness
- 35/100