Skip to content

Commit

Permalink
Fix banding artifacts of 3D space view's skybox (#5279)
Browse files Browse the repository at this point in the history
### What

Add simple algebraic (doesn't need a texture lookup) dithering to 3D
generic skybox in order to fix banding artifacts.
Depending on your screen and screen calibration you may or may not have
been annoyed by this in the past (on most of the setups I use it's quite
glaring)

Before:

![image](https://github.com/rerun-io/rerun/assets/1220815/7d2384f9-a956-49a3-9b2f-0f2b7091126d)


After:

![image](https://github.com/rerun-io/rerun/assets/1220815/918c5e46-baaa-4a9f-8242-541c64088ebe)


Note the ring artifacts which are mostly gone on the second screenshot -
if you can't spot the difference, make sure to look at the screenshots
without any scaling with your screen at high brightness relative to your
surroundings

### Checklist
* [x] I have read and agree to [Contributor
Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and
the [Code of
Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md)
* [x] I've included a screenshot or gif (if applicable)
* [x] I have tested the web demo (if applicable):
* Using newly built examples:
[app.rerun.io](https://app.rerun.io/pr/5279/index.html)
* Using examples from latest `main` build:
[app.rerun.io](https://app.rerun.io/pr/5279/index.html?manifest_url=https://app.rerun.io/version/main/examples_manifest.json)
* Using full set of examples from `nightly` build:
[app.rerun.io](https://app.rerun.io/pr/5279/index.html?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json)
* [x] The PR title and labels are set such as to maximize their
usefulness for the next release's CHANGELOG
* [x] If applicable, add a new check to the [release
checklist](https://github.com/rerun-io/rerun/blob/main/tests/python/release_checklist)!

- [PR Build Summary](https://build.rerun.io/pr/5279)
- [Docs
preview](https://rerun.io/preview/1d32c18f1ccf2c8c9d6e76c6a80a5f90d1d2d33e/docs)
<!--DOCS-PREVIEW-->
- [Examples
preview](https://rerun.io/preview/1d32c18f1ccf2c8c9d6e76c6a80a5f90d1d2d33e/examples)
<!--EXAMPLES-PREVIEW-->
- [Recent benchmark results](https://build.rerun.io/graphs/crates.html)
- [Wasm size tracking](https://build.rerun.io/graphs/sizes.html)

---------

Co-authored-by: Emil Ernerfeldt <emil.ernerfeldt@gmail.com>
  • Loading branch information
Wumpf and emilk authored Feb 26, 2024
1 parent f47f41e commit c123c59
Showing 1 changed file with 31 additions and 2 deletions.
33 changes: 31 additions & 2 deletions crates/re_renderer/shader/generic_skybox.wgsl
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,40 @@ fn skybox_light_srgb(dir: vec3f) -> vec3f {
return vec3f(0.85) + 0.15 * rgb;
}

// -----------------------------------------------
// Adapted from
// https://www.shadertoy.com/view/llVGzG
// Originally presented in:
// Jimenez 2014, "Next Generation Post-Processing in Call of Duty"
//
// A good overview can be found in
// https://blog.demofox.org/2022/01/01/interleaved-gradient-noise-a-different-kind-of-low-discrepancy-sequence/

fn interleaved_gradient_noise(n: vec2f) -> f32 {
let f = 0.06711056 * n.x + 0.00583715 * n.y;
return fract(52.9829189 * fract(f));
}

fn dither_interleaved(rgb: vec3f, levels: f32, frag_coord: vec4<f32>) -> vec3f {
var noise = interleaved_gradient_noise(frag_coord.xy);
noise = noise - 0.5;
return rgb + noise / (levels - 1.0);
}

// -----------------------------------------------

@fragment
fn main(in: FragmentInput) -> @location(0) vec4f {
fn main(in: FragmentInput, @builtin(position) frag_coord: vec4<f32>) -> @location(0) vec4f {
let camera_dir = camera_ray_direction_from_screenuv(in.texcoord);
// Messing with direction a bit so it looks like in our old three-d based renderer (for easier comparison)
let rgb = skybox_dark_srgb(camera_dir); // TODO(andreas): Allow switching to skybox_light
return vec4f(linear_from_srgb(rgb), 1.0);

// Apply dithering in gamma space.
// TODO(andreas): Once we switch to HDR outputs, this can be removed.
// As of writing, the render target itself is (s)RGB8, so we need to dither while we still have maximum precision.
let rgb_dithered = dither_interleaved(rgb, 256.0, frag_coord);

return vec4f(linear_from_srgb(rgb_dithered), 1.0);
//return vec4f(linear_from_srgb(rgb), 1.0); // Without dithering
//return vec4f(camera_dir, 1.0);
}

0 comments on commit c123c59

Please sign in to comment.