Photographic Standards for Real-Time Rendering¶
Comprehensive guide to values and photographic concepts used in modern game engines and tone mapping.
📸 The 18% Middle Gray - The Cornerstone¶
Photographic Origin¶
18% gray (0.18 in linear space) has been the universal standard of photometry since the 1940s.
Why 18%?¶
- Human Perception: Our eye perceives 18% reflectance as a neutral "middle tone".
- Statistical Average: The majority of real-world scenes have an average reflectance of ~12-20%.
- Ansel Adams' Zone System: Zone V (middle of the 0-X scale) = 18%.
Applications¶
- Gray cards for camera calibration.
- Light meters calibrated to 18% to calculate correct exposure.
- Lightroom/Photoshop: Target for auto-exposure.
- Unreal Engine, Unity: Default Key value for eye adaptation.
🎚️ Photographic Values Scale¶
Exposure Values (EV)¶
The EV scale measures the quantity of light:
| EV | Condition | Luminance (cd/m²) | Rendering Usage |
|---|---|---|---|
| -6 | Moonlight | 0.001 | Very dark scenes |
| -4 | Dimly lit interior | 0.01 | Dungeons, caves |
| 0 | Lit interior | 1.0 | Standard rooms |
| +4 | Outdoor shadow | 16 | Shaded outdoor scenes |
| +10 | Full sunlight | 1,000 | Sunny day |
| +15 | Snow in sunlight | 32,000 | Very bright environments |
| +20 | Direct Sun (surface) | 1,000,000 | Extreme HDR |
Visual EV Scale¶
Auto-Exposure Formula¶
Examples (with keyValue = 0.18):
- Dark scene (0.01 cd/m²) → Exposure = 18.0 (boost ×18)
- Middle gray (0.18 cd/m²) → Exposure = 1.0 (neutral)
- Bright scene (10 cd/m²) → Exposure = 0.018 (attenuation)
🌈 Material Reflectance Values¶
Standard Albedos (Physically Based)¶
| Material | Reflectance | Linear | sRGB (8-bit) |
|---|---|---|---|
| Charcoal | 4% | 0.04 | 61 |
| Dark Skin | 12% | 0.12 | 105 |
| 18% Gray Card | 18% | 0.18 | 119 |
| Light Skin | 35% | 0.35 | 160 |
| Concrete | 50% | 0.50 | 186 |
| Fresh Snow | 90% | 0.90 | 241 |
| Maximum (Physical) | 100% | 1.0 | 255 |
⚠️ In PBR, albedos exceeding 0.90 are non-physical (except for special materials).
📊 Tone Mapping - Standard Curves¶
1. Linear (Naive)¶
Problem: Brutal clipping at 1.0, loss of HDR details.
2. Reinhard (Simple)¶
Pros: Soft compression, never clips. Cons: Desaturates colors too much.
3. Uncharted 2 / Hable (Filmic)¶
// Reproduces film response
vec3 FilmicToneMapping(vec3 x) {
float A = 0.15; // Shoulder strength
float B = 0.50; // Linear strength
float C = 0.10; // Linear angle
float D = 0.20; // Toe strength
float E = 0.02; // Toe numerator
float F = 0.30; // Toe denominator
return ((x * (A * x + C * B) + D * E) /
(x * (A * x + B) + D * F)) - E / F;
}
Features: - Toe: Lifts shadows. - Shoulder: Compresses highlights. - Linear section: Preserves mid-tones.
4. ACES (Academy Color Encoding System)¶
THE Hollywood Standard (default in Unreal Engine).
vec3 ACESFilm(vec3 x) {
float a = 2.51;
float b = 0.03;
float c = 2.43;
float d = 0.59;
float e = 0.14;
return clamp((x * (a * x + b)) / (x * (c * x + d) + e), 0.0, 1.0);
}
Pros: - Preserves saturated colors. - Smooth transition to white. - Industry standard (Movies, AAA Games).
🎮 Recommended Values for Games¶
Auto-Exposure Settings¶
| Parameter | Conservative Value | Dynamic Value | Usage |
|---|---|---|---|
| keyValue | 0.18 | 0.14 - 0.20 | Standard / Fast FPS |
| minLuminance | 1.0 | 0.5 - 2.0 | No boost / Dungeons |
| maxLuminance | 5000 | 1000 - 10000 | Daylight / Extreme HDR |
| speedUp | 2.0 | 1.0 - 3.0 | Slow / Fast Adaptation |
| speedDown | 1.0 | 0.5 - 2.0 | Pupil Adaptation |
Examples by Genre¶
Realistic FPS (like Call of Duty)
keyValue = 0.15 // Slightly darker (tactical)
minLuminance = 0.8
maxLuminance = 8000
speedUp = 3.0 // Fast adaptation (gameplay)
speedDown = 1.5
Fantasy RPG (like Skyrim)
keyValue = 0.20 // Brighter (exploration)
minLuminance = 0.5 // Boost for dungeons
maxLuminance = 10000 // Magic HDR sky
speedUp = 1.5 // Soft adaptation
speedDown = 1.0
Horror (like Resident Evil)
keyValue = 0.12 // Very dark (atmosphere)
minLuminance = 2.0 // No boost (oppressive)
maxLuminance = 1000
speedUp = 0.5 // Very slow adaptation
speedDown = 2.0 // Fast return to black
🔧 Interesting Alternative Values¶
Key Value Alternatives¶
| Value | Name | Effect | Usage |
|---|---|---|---|
| 0.18 | Photographic Standard | Neutral, balanced | Universal default |
| 0.14 | Unreal Engine (UE⅘) | Slightly darker | AAA Games |
| 0.12 | Low-Key | Dark, dramatic | Cinematic, Horror |
| 0.25 | High-Key | Bright, airy | Cartoon, Light Fantasy |
| 0.50 | Very High-Key | Very bright | Artistic overexposure |
Middle Gray in sRGB¶
Warning: 18% linear ≠ 18% sRGB!
Common Trap: Using 0.18 directly in sRGB results in a gray that is too dark!
📐 Useful Formulas¶
Luminance Conversion¶
// Rec. 709 (HD TV standard)
float luminance_709 = dot(color.rgb, vec3(0.2126, 0.7152, 0.0722));
// Alternative (Rec. 601 - SD TV)
float luminance_601 = dot(color.rgb, vec3(0.299, 0.587, 0.114));
EV ↔ Luminance Conversion¶
Temporal Adaptation¶
float adaptationSpeed = (target > current) ? speedUp : speedDown;
float factor = 1.0 - exp(-deltaTime * adaptationSpeed);
float newExposure = mix(current, target, factor);
🎨 Practical Workflow¶
1. Initial Calibration¶
2. Test with Type Scenes¶
- Dark Interior: Check boost isn't excessive.
- Outdoor Day: Check for no over-exposure.
- Rapid Transition: Adjust adaptation speeds.
3. Artistic Tweaking¶
- Too bright → Reduce keyValue (0.14 - 0.16)
- Too dark → Increase keyValue (0.20 - 0.25)
- Flashy/Unstable → Reduce speedUp/Down
- Too slow → Increase speedUp
📚 Recommended Resources¶
- Film Lighting Simulator (Unreal Engine docs)
- "Physically Based Rendering" - Matt Pharr, Greg Humphreys
- Tone Mapping Comparison - John Hable (Filmic Worlds blog)
- ACES Documentation - Academy of Motion Picture Arts
- "Real Shading in Unreal Engine 4" - Brian Karis (SIGGRAPH 2013)
✨ Bonus: Exotic Values¶
Lunar Scenes¶
Underwater¶
Space¶
🎨 Gamut Mapping & 3D LUTs¶
Color Spaces & Gamuts¶
Modern cinema cameras capture light in wide-gamut log spaces to preserve maximum dynamic range.
| Standard | Dynamic Range | Primary Usage |
|---|---|---|
| Rec.709 | ~6 stops | Standard TV / Web |
| DCI-P3 | ~12 stops | Digital Cinema / HDR |
| S-Gamut3.Cine | ~15 stops | Sony Cinema Cameras (A7S III, Venice) |
| Arri LogC | ~14+ stops | Arri Alexa Standard |
3D LUT (Look-Up Table)¶
A 3D LUT is a \(N^3\) cube of colors used to transform a source gamut (e.g., S-Log3) into a target "look" or standard (e.g., Rec.709).
- Technical LUT: Exact mathematical conversion between color spaces.
- Creative LUT: Artistic grading (Teal & Orange, Film Emulation).
Sony S-Log3 / S-Gamut3.Cine¶
Used in our Sony A7S III profile. It maps linear light to a logarithmic curve to optimize data distribution in deep shadows and bright highlights.
// Simplified S-Log3 decoding (emulated by LUT)
if (x < 0.01125) {
y = (x - 0.01) / 3.5;
} else {
y = (log10((x + 0.01) / 0.1) + 0.1) / 1.0;
}
suckless-ogl, we use Hardware-Accelerated 3D LUTs (GL_TEXTURE_3D) for near-zero cost gamut mapping.


