Add night adaptation control to ColorGrading (#4559)

In low-light conditions, peak luminance sensitivity of the eye shifts
toward the blue end of the visible spectrum. This effect called the
Purkinje effect occurs during the transition from photopic (cone-based)
vision to scotopic (rod-based) vision. Because the rods and cones use the
same neural pathways, a color shift is introduced as the rods take over to
improve low-light perception.

This function aims to (somewhat) replicate this color shift and peak
luminance sensitivity increase to more faithfully reproduce scenes in
low-light conditions as they would be perceived by a human observer
(as opposed to an artificial observer such as a camera sensor).

The night adaptation can be controlled using a 0..1 factor for artistic
reasons: `ColorGrading::Builder::nightAdaptation()`.
This commit is contained in:
Romain Guy
2021-08-30 17:19:56 -07:00
committed by GitHub
parent dcfc27857f
commit 0e574f3fce
13 changed files with 1563 additions and 9 deletions

View File

@@ -314,6 +314,8 @@ static int parse(jsmntok_t const* tokens, int i, const char* jsonChunk, ColorGra
i = parse(tokens, i + 1, jsonChunk, &out->gamutMapping);
} else if (compare(tok, jsonChunk, "exposure") == 0) {
i = parse(tokens, i + 1, jsonChunk, &out->exposure);
} else if (compare(tok, jsonChunk, "nightAdaptation") == 0) {
i = parse(tokens, i + 1, jsonChunk, &out->nightAdaptation);
} else if (compare(tok, jsonChunk, "temperature") == 0) {
i = parse(tokens, i + 1, jsonChunk, &out->temperature);
} else if (compare(tok, jsonChunk, "tint") == 0) {
@@ -1021,6 +1023,7 @@ ColorGrading* createColorGrading(const ColorGradingSettings& settings, Engine* e
ColorGrading *colorGrading = ColorGrading::Builder()
.quality(settings.quality)
.exposure(settings.exposure)
.nightAdaptation(settings.nightAdaptation)
.whiteBalance(settings.temperature, settings.tint)
.channelMixer(settings.outRed, settings.outGreen, settings.outBlue)
.shadowsMidtonesHighlights(
@@ -1161,6 +1164,7 @@ static std::ostream& operator<<(std::ostream& out, const ColorGradingSettings& i
<< "\"luminanceScaling\": " << to_string(in.luminanceScaling) << ",\n"
<< "\"gamutMapping\": " << to_string(in.gamutMapping) << ",\n"
<< "\"exposure\": " << (in.exposure) << ",\n"
<< "\"nightAdaptation\": " << (in.nightAdaptation) << ",\n"
<< "\"temperature\": " << (in.temperature) << ",\n"
<< "\"tint\": " << (in.tint) << ",\n"
<< "\"outRed\": " << (in.outRed) << ",\n"
@@ -1425,7 +1429,7 @@ bool GenericToneMapperSettings::operator==(const GenericToneMapperSettings &rhs)
bool ColorGradingSettings::operator==(const ColorGradingSettings &rhs) const {
// If you had to fix the following codeline, then you likely also need to update the
// implementation of operator==.
static_assert(sizeof(ColorGradingSettings) == 228, "Please update Settings.cpp");
static_assert(sizeof(ColorGradingSettings) == 232, "Please update Settings.cpp");
return enabled == rhs.enabled &&
quality == rhs.quality &&
toneMapping == rhs.toneMapping &&
@@ -1433,6 +1437,7 @@ bool ColorGradingSettings::operator==(const ColorGradingSettings &rhs) const {
luminanceScaling == rhs.luminanceScaling &&
gamutMapping == rhs.gamutMapping &&
exposure == rhs.exposure &&
nightAdaptation == rhs.nightAdaptation &&
temperature == rhs.temperature &&
tint == rhs.tint &&
outRed == rhs.outRed &&