|
|
@@ -328,7 +328,8 @@ vec3 tonemap_agx(vec3 color) {
|
|
|
}
|
|
|
|
|
|
vec3 linear_to_srgb(vec3 color) {
|
|
|
- //if going to srgb, clamp from 0 to 1.
|
|
|
+ // Clamping is not strictly necessary for floating point nonlinear sRGB encoding,
|
|
|
+ // but many cases that call this function need the result clamped.
|
|
|
color = clamp(color, vec3(0.0), vec3(1.0));
|
|
|
const vec3 a = vec3(0.055f);
|
|
|
return mix((vec3(1.0f) + a) * pow(color.rgb, vec3(1.0f / 2.4f)) - a, 12.92f * color.rgb, lessThan(color.rgb, vec3(0.0031308f)));
|
|
|
@@ -816,12 +817,17 @@ vec3 do_fxaa(vec3 color, float exposure, vec2 uv_interp) {
|
|
|
// From https://alex.vlachos.com/graphics/Alex_Vlachos_Advanced_VR_Rendering_GDC2015.pdf
|
|
|
// and https://www.shadertoy.com/view/MslGR8 (5th one starting from the bottom)
|
|
|
// NOTE: `frag_coord` is in pixels (i.e. not normalized UV).
|
|
|
+// This dithering must be applied after encoding changes (linear/nonlinear) have been applied
|
|
|
+// as the final step before quantization from floating point to integer values.
|
|
|
vec3 screen_space_dither(vec2 frag_coord) {
|
|
|
// Iestyn's RGB dither (7 asm instructions) from Portal 2 X360, slightly modified for VR.
|
|
|
+ // Removed the time component to avoid passing time into this shader.
|
|
|
vec3 dither = vec3(dot(vec2(171.0, 231.0), frag_coord));
|
|
|
dither.rgb = fract(dither.rgb / vec3(103.0, 71.0, 97.0));
|
|
|
|
|
|
// Subtract 0.5 to avoid slightly brightening the whole viewport.
|
|
|
+ // Use a dither strength of 100% rather than the 37.5% suggested by the original source.
|
|
|
+ // Divide by 255 to align to 8-bit quantization.
|
|
|
return (dither.rgb - 0.5) / 255.0;
|
|
|
}
|
|
|
|
|
|
@@ -866,7 +872,8 @@ void main() {
|
|
|
|
|
|
color.rgb = apply_tonemapping(color.rgb, params.white);
|
|
|
|
|
|
- if (bool(params.flags & FLAG_CONVERT_TO_SRGB)) {
|
|
|
+ bool convert_to_srgb = bool(params.flags & FLAG_CONVERT_TO_SRGB);
|
|
|
+ if (convert_to_srgb) {
|
|
|
color.rgb = linear_to_srgb(color.rgb); // Regular linear -> SRGB conversion.
|
|
|
}
|
|
|
#ifndef SUBPASS
|
|
|
@@ -879,7 +886,7 @@ void main() {
|
|
|
|
|
|
// high dynamic range -> SRGB
|
|
|
glow = apply_tonemapping(glow, params.white);
|
|
|
- if (bool(params.flags & FLAG_CONVERT_TO_SRGB)) {
|
|
|
+ if (convert_to_srgb) {
|
|
|
glow = linear_to_srgb(glow);
|
|
|
}
|
|
|
|
|
|
@@ -894,7 +901,13 @@ void main() {
|
|
|
}
|
|
|
|
|
|
if (bool(params.flags & FLAG_USE_COLOR_CORRECTION)) {
|
|
|
+ // apply_color_correction requires nonlinear sRGB encoding
|
|
|
+ if (!convert_to_srgb) {
|
|
|
+ color.rgb = linear_to_srgb(color.rgb);
|
|
|
+ }
|
|
|
color.rgb = apply_color_correction(color.rgb);
|
|
|
+ // When convert_to_srgb is false, there is no need to convert back to
|
|
|
+ // linear because the color correction texture sampling does this for us.
|
|
|
}
|
|
|
|
|
|
if (bool(params.flags & FLAG_USE_DEBANDING)) {
|