载入中...
搜索中...
未找到
DisplayOutputEncoding.h
浏览该文件的文档.
1#pragma once
2
3#include "graphics/Color.h"
4
5#include <algorithm>
6#include <cmath>
7#include <cstdint>
8
10
12enum class ActiveColorSpace : uint8_t { Sdr = 0, ScRgb = 1, Hdr10 = 2 };
13
15enum class OutputMode : uint8_t { Sdr = 0, Auto = 1, Hdr10 = 2, ScRgb = 3 };
16
18struct Support {
19 bool sdr = true;
20 bool hdr10 = false;
21 bool scRgb = false;
22};
23
24inline constexpr float kDefaultPaperWhiteNits = 200.f;
25inline constexpr float kDefaultPeakNits = 1000.f;
26
28inline void clampCalibration(float &paperWhiteNits, float &peakNits) noexcept {
29 paperWhiteNits = std::clamp(paperWhiteNits, 80.f, 400.f);
30 peakNits = std::clamp(peakNits, std::max(paperWhiteNits, 200.f), 10000.f);
31}
32
34inline float packNits(float paperWhiteNits, float peakNits) noexcept {
36 clampCalibration(paperWhiteNits, peakNits);
37 const float paperQ = std::round(paperWhiteNits * 10.f);
38 const float peakQ = std::round(peakNits / 10.f);
39 return paperQ + peakQ * 65536.f;
40}
41
43inline void unpackNits(float packed, float &paperWhiteNits, float &peakNits) noexcept {
44 const float rounded = std::round(packed);
45 paperWhiteNits = std::fmod(rounded, 65536.f) * 0.1f;
46 peakNits = std::floor(rounded / 65536.f) * 10.f;
48 clampCalibration(paperWhiteNits, peakNits);
49}
50
53inline float packActiveMode(ActiveColorSpace space) noexcept {
54 switch (space) {
56 return 1.f;
58 return 2.f;
60 default:
61 return 0.f;
62 }
63}
64
66inline float packComposeLinearMode() noexcept { return 3.f; }
67
69inline ActiveColorSpace unpackActiveMode(float packed) noexcept {
70 const int mode = int(std::round(packed));
71 if (mode == 1) return ActiveColorSpace::ScRgb;
72 if (mode == 2) return ActiveColorSpace::Hdr10;
74}
75
77inline bool isComposeLinearMode(float packed) noexcept {
79 return int(std::round(packed)) == 3;
80}
81
83inline Color sceneResolveTint(bool aces, ActiveColorSpace space, bool attachmentEncodesSrgb,
84 float paperWhiteNits, float peakNits) noexcept {
85 const float encodeSrgb = (!attachmentEncodesSrgb && space == ActiveColorSpace::Sdr) ? 65536.f : 0.f;
87 return Color(aces ? 1.f : 0.f, packActiveMode(space), packNits(paperWhiteNits, peakNits), encodeSrgb);
88}
89
94inline Color sceneComposeTint(bool aces, float paperWhiteNits, float peakNits) noexcept {
96 return Color(aces ? 1.f : 0.f, packComposeLinearMode(), packNits(paperWhiteNits, peakNits), 0.f);
97}
98
100inline Color uiResolveTint(ActiveColorSpace space, float paperWhiteNits, float peakNits) noexcept {
101 // r < 0 selects the UI passthrough+encode path in scene_tonemap.frag.
103 return Color(-1.f, packActiveMode(space), packNits(paperWhiteNits, peakNits), 0.f);
104}
105
107inline float luminanceRec709(float r, float g, float b) noexcept {
108 return 0.2126f * r + 0.7152f * g + 0.0722f * b;
109}
110
112inline void rec709ToRec2020(float &r, float &g, float &b) noexcept {
113 const float nr = 0.6274040f * r + 0.3292820f * g + 0.0433136f * b;
114 const float ng = 0.0690970f * r + 0.9195400f * g + 0.0113612f * b;
115 const float nb = 0.0163916f * r + 0.0880132f * g + 0.8955950f * b;
116 r = nr;
117 g = ng;
118 b = nb;
119}
120
122inline float linearToPq(float v) noexcept {
123 v = std::max(v, 0.f);
124 constexpr float m1 = 2610.f / 4096.f / 4.f;
125 constexpr float m2 = 2523.f / 4096.f * 128.f;
126 constexpr float c1 = 3424.f / 4096.f;
127 constexpr float c2 = 2413.f / 4096.f * 32.f;
128 constexpr float c3 = 2392.f / 4096.f * 32.f;
129 const float cp = std::pow(v, m1);
131 return std::pow((c1 + c2 * cp) / (1.f + c3 * cp), m2);
132}
133
138inline void encodeHdr10(float &r, float &g, float &b, float paperWhiteNits, float peakNits) noexcept {
140 clampCalibration(paperWhiteNits, peakNits);
141 const float peakRatio = peakNits / paperWhiteNits;
142 r = std::clamp(r, 0.f, peakRatio);
143 g = std::clamp(g, 0.f, peakRatio);
144 b = std::clamp(b, 0.f, peakRatio);
146 rec709ToRec2020(r, g, b);
147 constexpr float st2084Max = 10000.f;
148 r = linearToPq(r * paperWhiteNits / st2084Max);
149 g = linearToPq(g * paperWhiteNits / st2084Max);
150 b = linearToPq(b * paperWhiteNits / st2084Max);
151}
152
157inline void acesToDisplayLinear(float &r, float &g, float &b, float paperWhiteNits,
158 float peakNits) noexcept {
160 clampCalibration(paperWhiteNits, peakNits);
161 const float peakRatio = peakNits / paperWhiteNits;
162 const float inv = 1.f / peakRatio;
163 auto aces = [](float c) {
164 c = std::max(c, 0.f);
165 constexpr float a = 2.51f, b = 0.03f, c0 = 2.43f, d = 0.59f, e = 0.14f;
167 return std::clamp((c * (a * c + b)) / (c * (c0 * c + d) + e), 0.f, 1.f);
168 };
169 r = aces(r * inv) * peakRatio;
170 g = aces(g * inv) * peakRatio;
171 b = aces(b * inv) * peakRatio;
172}
173
178inline void encodeScRgb(float &r, float &g, float &b, float paperWhiteNits, float peakNits) noexcept {
180 clampCalibration(paperWhiteNits, peakNits);
181 const float peakRatio = peakNits / paperWhiteNits;
182 const float scale = paperWhiteNits / 80.f;
183 r = std::clamp(r, 0.f, peakRatio) * scale;
184 g = std::clamp(g, 0.f, peakRatio) * scale;
185 b = std::clamp(b, 0.f, peakRatio) * scale;
186}
187
188} // namespace eve::graphics::display
tensor::Graph g
Definition GpuGraph.cpp:7
double r
float v
std::int32_t c
std::array< float, 3 > scale
MeleePoint3 b
Definition MeleeHit.cpp:41
MeleePoint3 a
Definition MeleeHit.cpp:40
float d
float luminanceRec709(float r, float g, float b) noexcept
Luminance rec 709.
bool isComposeLinearMode(float packed) noexcept
True when the tint G channel requests compose-linear (mode 3).
ActiveColorSpace unpackActiveMode(float packed) noexcept
Decode the present mode from the resolve tint G channel.
float linearToPq(float v) noexcept
Apply the ST.2084 PQ OETF to a [0,1] normalized luminance sample.
void encodeHdr10(float &r, float &g, float &b, float paperWhiteNits, float peakNits) noexcept
Map filmic display-linear RGB (1 = paper white) into HDR10 PQ codes.
Color uiResolveTint(ActiveColorSpace space, float paperWhiteNits, float peakNits) noexcept
Build the Color tint used when compositing SDR UI onto an HDR swapchain.
float packComposeLinearMode() noexcept
Tint G value for compose-linear output (paper-white-relative, no OETF).
Color sceneResolveTint(bool aces, ActiveColorSpace space, bool attachmentEncodesSrgb, float paperWhiteNits, float peakNits) noexcept
Build the Color tint used by the final scene present resolve.
float packNits(float paperWhiteNits, float peakNits) noexcept
Pack paper-white and peak nits into one float for the present resolve tint.
void clampCalibration(float &paperWhiteNits, float &peakNits) noexcept
Clamp paper-white / peak luminance into the engine-supported range.
void rec709ToRec2020(float &r, float &g, float &b) noexcept
Convert display-linear Rec.709 RGB into Rec.2020.
constexpr float kDefaultPaperWhiteNits
OutputMode
Requested present preference; Auto picks Hdr10 then ScRgb then Sdr.
ActiveColorSpace
Active present color encoding after swapchain selection.
void unpackNits(float packed, float &paperWhiteNits, float &peakNits) noexcept
Unpack paper-white and peak nits from the present resolve tint channel.
Color sceneComposeTint(bool aces, float paperWhiteNits, float peakNits) noexcept
Build the Color tint for tonemapping into a linear HDR compose target.
float packActiveMode(ActiveColorSpace space) noexcept
Encode the active present mode into the resolve tint G channel.
void acesToDisplayLinear(float &r, float &g, float &b, float paperWhiteNits, float peakNits) noexcept
Expand ACES [0,1] output into display-linear relative to paper white.
void encodeScRgb(float &r, float &g, float &b, float paperWhiteNits, float peakNits) noexcept
Map paper-white-relative display-linear RGB into scRGB (1.0 = 80 nits).
eve::Color Color
RGBA color used by every graphics draw call. Lives inside eve::graphics so including a graphics heade...
Definition Color.h:13