Skip to content

Commit

Permalink
vulkan: rework eotf functions to be much clearer
Browse files Browse the repository at this point in the history
  • Loading branch information
Ryp committed Mar 21, 2024
1 parent 12d7ab3 commit 8701650
Show file tree
Hide file tree
Showing 4 changed files with 103 additions and 105 deletions.
6 changes: 3 additions & 3 deletions src/renderer/shader/gbuffer/gbuffer.hlsl
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
#include "lib/format/unorm.hlsl"
#include "lib/format/octahedral.hlsl"
#include "lib/format/bitfield.hlsl"
#include "lib/eotf.hlsl"
#include "lib/tranfer_functions.hlsl"

#include "material/standard.hlsl"

Expand Down Expand Up @@ -59,7 +59,7 @@ GBufferRaw encode_gbuffer(GBuffer gbuffer)
{
GBufferRaw gbuffer_raw;

gbuffer_raw.rt0 = rgba32_float_to_rgba8_unorm(float4(srgb_eotf_fast(gbuffer.albedo), gbuffer.roughness));
gbuffer_raw.rt0 = rgba32_float_to_rgba8_unorm(float4(linear_to_srgb_fast(gbuffer.albedo), gbuffer.roughness));

gbuffer_raw.rt1 = encode_normal_hemi_octahedral(gbuffer.normal_vs, RT1_Normal_Bits / 2) << RT1_Normal_Offset |
r32_float_to_unorm_generic(gbuffer.f0, RT1_FZero_Bits) << RT1_FZero_Offset |
Expand All @@ -74,7 +74,7 @@ GBuffer decode_gbuffer(GBufferRaw gbuffer_raw)

const float4 packed_albedo_roughness = rgba8_unorm_to_rgba32_float(gbuffer_raw.rt0);

gbuffer.albedo = srgb_eotf_inverse_fast(packed_albedo_roughness.xyz);
gbuffer.albedo = srgb_to_linear_fast(packed_albedo_roughness.xyz);
gbuffer.roughness = packed_albedo_roughness.w;

const uint packed_normal_f0_ao = gbuffer_raw.rt1;
Expand Down
98 changes: 0 additions & 98 deletions src/renderer/shader/lib/eotf.hlsl

This file was deleted.

96 changes: 96 additions & 0 deletions src/renderer/shader/lib/tranfer_functions.hlsl
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
////////////////////////////////////////////////////////////////////////////////
/// Reaper
///
/// Copyright (c) 2015-2022 Thibault Schueller
/// This file is distributed under the MIT License
////////////////////////////////////////////////////////////////////////////////

#ifndef LIB_TRANSFER_FUNCTIONS_INCLUDED
#define LIB_TRANSFER_FUNCTIONS_INCLUDED

// -----------------------------------------------------------------------------
// sRGB

float3 linear_to_srgb(float3 color_linear)
{
return (color_linear < 0.0031308) ? 12.92 * color_linear : 1.055 * pow(color_linear, 1.0 / 2.4) - 0.055;
}

float3 srgb_to_linear(float3 color_srgb)
{
return (color_srgb < 0.04045) ? color_srgb / 12.92 : pow((color_srgb + 0.055) / 1.055, 2.4);
}

// Replaces pow() with cheaper sqrt()
// Error < 0.4%
float3 linear_to_srgb_fast(float3 color_linear)
{
return (color_linear < 0.0031308) ? 12.92 * color_linear : 1.13005 * sqrt(color_linear - 0.00228) - 0.13448 * color_linear + 0.005719;
}

float3 srgb_to_linear_fast(float3 color_srgb)
{
return (color_srgb < 0.04045) ? color_srgb / 12.92 : -7.43605 * color_srgb - 31.24297 * sqrt(-0.53792 * color_srgb + 1.279924) + 35.34864;
}

// -----------------------------------------------------------------------------
// Rec.709

float3 linear_to_rec709(float3 color_linear)
{
return (color_linear < 0.0181) ? 4.5 * color_linear : 1.0993 * pow(color_linear, 0.45) - 0.0993;
}

float3 rec709_to_linear(float3 color_rec709)
{
return (color_rec709 < 0.08145) ? color_rec709 / 4.5 : pow((color_rec709 + 0.0993) / 1.0993, 1.0 / 0.45);
}

// -----------------------------------------------------------------------------
// ST.2084 (or PQ)

static const float PQ_MAX_NITS = 10000.0;
static const float PQ_M1 = 2610.0 / 4096.0 / 4.0;
static const float PQ_M2 = 2523.0 / 4096.0 * 128.0;
static const float PQ_C1 = 3424.0 / 4096.0;
static const float PQ_C2 = 2413.0 / 4096.0 * 32.0;
static const float PQ_C3 = 2392.0 / 4096.0 * 32.0;

float3 linear_to_pq(float3 color_linear)
{
float3 Lp = pow(color_linear, PQ_M1);
return pow((PQ_C1 + PQ_C2 * Lp) / (1.0 + PQ_C3 * Lp), PQ_M2);
}

float3 pq_to_linear(float3 color_pq)
{
float3 Np = pow(color_pq, 1.0 / PQ_M2);
return pow(max(Np - PQ_C1, 0.0) / (PQ_C2 - PQ_C3 * Np), 1.0 / PQ_M1);
}

// -----------------------------------------------------------------------------
// Miscellaneous

float3 linear_to_gamma22(float3 color_linear)
{
return pow(color_linear, 1.0 / 2.2);
}

float3 gamma22_to_linear(float3 color_g22)
{
return pow(color_g22, 2.2);
}

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

float3 linear_to_gamma24(float3 color_linear)
{
return pow(color_linear, 1.0 / 2.4);
}

float3 gamma24_to_linear(float3 color_g24)
{
return pow(color_g24, 2.4);
}

#endif
8 changes: 4 additions & 4 deletions src/renderer/shader/swapchain_write.frag.hlsl
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
#include "lib/base.hlsl"

#include "lib/color_space.hlsl"
#include "lib/eotf.hlsl"
#include "lib/tranfer_functions.hlsl"
#include "lib/tonemapping.hlsl"

#include "swapchain_write.share.hlsl"
Expand Down Expand Up @@ -70,17 +70,17 @@ float3 apply_sdr_transfer_func(float3 color_normalized, uint transfer_function)
if (transfer_function == TRANSFER_FUNC_LINEAR)
return color_normalized;
else if (transfer_function == TRANSFER_FUNC_SRGB)
return srgb_eotf(color_normalized);
return linear_to_srgb(color_normalized);
else if (transfer_function == TRANSFER_FUNC_REC709)
return rec709_eotf(color_normalized);
return linear_to_rec709(color_normalized);
else
return 0.42; // Invalid
}

float3 apply_hdr_transfer_func(float3 color_linear_nits, uint transfer_function)
{
if (transfer_function == TRANSFER_FUNC_PQ)
return pq_eotf(color_linear_nits / PQ_MAX_NITS);
return linear_to_pq(color_linear_nits / PQ_MAX_NITS);
else if (transfer_function == TRANSFER_FUNC_WINDOWS_SCRGB)
return color_linear_nits / 80.f;
else
Expand Down

0 comments on commit 8701650

Please sign in to comment.