Skip to content

Commit e5e02e7

Browse files
committed
Add support for flat shading with indiced meshes
Use the partial derivative (dFdx, dFdy) for computing facet normals in the fragment shader. I made this as an alternative for bevyengine#1808 when for example making procedually generated terrain.
1 parent 6a8a8c9 commit e5e02e7

File tree

5 files changed

+79
-0
lines changed

5 files changed

+79
-0
lines changed

Cargo.toml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -181,6 +181,10 @@ path = "examples/3d/wireframe.rs"
181181
name = "z_sort_debug"
182182
path = "examples/3d/z_sort_debug.rs"
183183

184+
[[example]]
185+
name = "flat_shading"
186+
path = "examples/3d/flat_shading.rs"
187+
184188
# Application
185189
[[example]]
186190
name = "custom_loop"

crates/bevy_pbr/src/material.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,10 @@ pub struct StandardMaterial {
4242
#[render_resources(ignore)]
4343
#[shader_def]
4444
pub unlit: bool,
45+
/// This allows for flat shading even with indiced meshes.
46+
#[render_resources(ignore)]
47+
#[shader_def]
48+
pub flat_shading: bool,
4549
}
4650

4751
impl Default for StandardMaterial {
@@ -69,6 +73,7 @@ impl Default for StandardMaterial {
6973
emissive: Color::BLACK,
7074
emissive_texture: None,
7175
unlit: false,
76+
flat_shading: false,
7277
}
7378
}
7479
}

crates/bevy_pbr/src/render_graph/pbr_pipeline/pbr.frag

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,10 @@ struct DirectionalLight {
5050
};
5151

5252
layout(location = 0) in vec3 v_WorldPosition;
53+
54+
#ifndef STANDARDMATERIAL_FLAT_SHADING
5355
layout(location = 1) in vec3 v_WorldNormal;
56+
#endif
5457
layout(location = 2) in vec2 v_Uv;
5558

5659
#ifdef STANDARDMATERIAL_NORMAL_MAP

crates/bevy_pbr/src/render_graph/pbr_pipeline/pbr.vert

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,9 @@ layout(location = 3) in vec4 Vertex_Tangent;
99
#endif
1010

1111
layout(location = 0) out vec3 v_WorldPosition;
12+
#ifndef STANDARDMATERIAL_FLAT_SHADING
1213
layout(location = 1) out vec3 v_WorldNormal;
14+
#endif
1315
layout(location = 2) out vec2 v_Uv;
1416

1517
layout(set = 0, binding = 0) uniform CameraViewProj {
@@ -27,7 +29,9 @@ layout(set = 2, binding = 0) uniform Transform {
2729
void main() {
2830
vec4 world_position = Model * vec4(Vertex_Position, 1.0);
2931
v_WorldPosition = world_position.xyz;
32+
#ifndef STANDARDMATERIAL_FLAT_SHADING
3033
v_WorldNormal = mat3(Model) * Vertex_Normal;
34+
#endif
3135
v_Uv = Vertex_Uv;
3236
#ifdef STANDARDMATERIAL_NORMAL_MAP
3337
v_WorldTangent = vec4(mat3(Model) * Vertex_Tangent.xyz, Vertex_Tangent.w);

examples/3d/flat_shading.rs

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
use bevy::{
2+
prelude::*,
3+
render::{
4+
mesh::{Indices, VertexAttributeValues},
5+
pipeline::PrimitiveTopology,
6+
},
7+
};
8+
9+
fn main() {
10+
App::new()
11+
.insert_resource(Msaa { samples: 4 })
12+
.add_plugins(DefaultPlugins)
13+
.add_startup_system(setup)
14+
.run();
15+
}
16+
17+
/// set up a simple 3D scene
18+
fn setup(
19+
mut commands: Commands,
20+
mut meshes: ResMut<Assets<Mesh>>,
21+
mut materials: ResMut<Assets<StandardMaterial>>,
22+
) {
23+
// flat
24+
commands.spawn_bundle(PbrBundle {
25+
mesh: meshes.add(Mesh::from(shape::Icosphere {
26+
radius: 0.5,
27+
subdivisions: 4,
28+
})),
29+
material: materials.add(StandardMaterial {
30+
base_color: Color::rgb(0.8, 0.7, 0.6),
31+
flat_shading: true,
32+
..Default::default()
33+
}),
34+
transform: Transform::from_xyz(-0.55, 0.5, 0.0),
35+
..Default::default()
36+
});
37+
// smooth
38+
commands.spawn_bundle(PbrBundle {
39+
mesh: meshes.add(Mesh::from(shape::Icosphere {
40+
radius: 0.5,
41+
subdivisions: 4,
42+
})),
43+
material: materials.add(Color::rgb(0.8, 0.7, 0.6).into()),
44+
transform: Transform::from_xyz(0.55, 0.5, 0.0),
45+
..Default::default()
46+
});
47+
// plane
48+
commands.spawn_bundle(PbrBundle {
49+
mesh: meshes.add(Mesh::from(shape::Plane { size: 5.0 })),
50+
material: materials.add(Color::rgb(0.3, 0.5, 0.3).into()),
51+
..Default::default()
52+
});
53+
// light
54+
commands.spawn_bundle(PointLightBundle {
55+
transform: Transform::from_xyz(5.0, 5.0, 5.0),
56+
..Default::default()
57+
});
58+
// camera
59+
commands.spawn_bundle(PerspectiveCameraBundle {
60+
transform: Transform::from_xyz(1.0, 3.0, 4.0).looking_at(Vec3::ZERO, Vec3::Y),
61+
..Default::default()
62+
});
63+
}

0 commit comments

Comments
 (0)