Skip to content

Commit

Permalink
dithering in fullscreen tonemap
Browse files Browse the repository at this point in the history
  • Loading branch information
aevyrie committed Nov 10, 2022
1 parent 1914a3f commit b3d7830
Show file tree
Hide file tree
Showing 4 changed files with 86 additions and 1 deletion.
10 changes: 10 additions & 0 deletions Cargo.toml
Expand Up @@ -1349,6 +1349,16 @@ description = "Various test cases for hierarchy and transform propagation perfor
category = "Stress Tests"
wasm = true

[[example]]
name = "color_banding"
path = "examples/stress_tests/color_banding.rs"

[package.metadata.example.color_banding]
name = "Color Banding"
description = "Test cases for extreme color banding"
category = "Stress Tests"
wasm = false

# Tools
[[example]]
name = "scene_viewer"
Expand Down
8 changes: 7 additions & 1 deletion crates/bevy_core_pipeline/src/tonemapping/tonemapping.wgsl
Expand Up @@ -10,5 +10,11 @@ var hdr_sampler: sampler;
fn fragment(in: FullscreenVertexOutput) -> @location(0) vec4<f32> {
let hdr_color = textureSample(hdr_texture, hdr_sampler, in.uv);

return vec4<f32>(reinhard_luminance(hdr_color.rgb), hdr_color.a);
var output_rgb = vec3<f32>(reinhard_luminance(hdr_color.rgb));
output_rgb = pow(output_rgb.rgb, vec3<f32>(1.0 / 2.2));
output_rgb = output_rgb + screen_space_dither(in.position.xy);
// This conversion back to linear space is required because our output texture format is
// SRGB; the GPU will assume our output is linear and will apply an SRGB conversion.
output_rgb = pow(output_rgb.rgb, vec3<f32>(2.2));
return vec4<f32>(output_rgb, hdr_color.a);
}
Expand Up @@ -27,3 +27,11 @@ fn reinhard_luminance(color: vec3<f32>) -> vec3<f32> {
let l_new = l_old / (1.0 + l_old);
return tonemapping_change_luminance(color, l_new);
}

// Source: Advanced VR Rendering, GDC 2015, Alex Vlachos, Valve, Slide 49
// https://media.steampowered.com/apps/valve/2015/Alex_Vlachos_Advanced_VR_Rendering_GDC2015.pdf
fn screen_space_dither(frag_coord: vec2<f32>) -> vec3<f32> {
var dither = vec3<f32>(dot(vec2<f32>(171.0, 231.0), frag_coord)).xxx;
dither = fract(dither.rgb / vec3<f32>(103.0, 71.0, 97.0));
return dither / 255.0;
}
61 changes: 61 additions & 0 deletions examples/stress_tests/color_banding.rs
@@ -0,0 +1,61 @@
//! Useful for stress-testing rendering cases that exhibit extreme color banding.

use bevy::prelude::*;

fn main() {
App::new()
.add_plugins(DefaultPlugins)
.insert_resource(AmbientLight {
color: Color::BLACK,
brightness: 0.0,
})
.add_startup_system(setup)
.run();
}

/// set up a simple 3D scene
fn setup(
mut commands: Commands,
mut meshes: ResMut<Assets<Mesh>>,
mut materials: ResMut<Assets<StandardMaterial>>,
) {
let colors = [Color::WHITE, Color::RED, Color::GREEN, Color::BLUE];
let x = [-5.0, 5.0, -5.0, 5.0];
let z = [-5.0, -5.0, 5.0, 5.0];
let mesh = meshes.add(Mesh::from(shape::Plane { size: 10.0 }));

for i in 0..4 {
// plane
commands.spawn_bundle(PbrBundle {
mesh: mesh.clone(),
material: materials.add(custom_material(colors[i])),
transform: Transform::from_xyz(x[i], 0.0, z[i]),
..default()
});
}
// light
commands.spawn_bundle(PointLightBundle {
point_light: PointLight {
intensity: 50.0,
shadows_enabled: false,
..default()
},
transform: Transform::from_xyz(0.0, 5.0, 0.0),
..default()
});
// camera
commands.spawn_bundle(Camera3dBundle {
transform: Transform::from_xyz(0.0, 6.0, 0.0).looking_at(Vec3::default(), -Vec3::Z),
..default()
});
}

fn custom_material(color: Color) -> StandardMaterial {
StandardMaterial {
base_color: color,
perceptual_roughness: 1.0,
metallic: 0.0,
reflectance: 0.0,
..default()
}
}

0 comments on commit b3d7830

Please sign in to comment.