Fry3DX/engine/shaders/adapt.frag
Nexoniarz f3e8eca87b Fry3DX 0.4: an easy 3D modeller
Shapes with live settings, shape editing, knife and hole tools, drawing
shapes onto other objects, combining objects (add / subtract / overlap),
copies, thickness, painting with stickers and layers, a Layout tab, a
Print tab with checks, packed .fry files with autosave, export to GLB,
glTF, FBX, OBJ, 3MF, STL and PLY, folders in Layers, its own crash
screen, and a website for GitHub Pages in docs/.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NMSrd5oe1GpUD7E6d825KP
2026-10-19 21:18:35 +02:00

32 lines
1.4 KiB
GLSL
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#version 460
// Eye adaptation (1×1): the scene's average brightness (geometric mean of 16 taps of the
// smallest bloom level), turned into an exposure that keeps a mid grey where it should be,
// eased towards (0.6x to 1.8x, so nothing burns out) from last frame's at `speed` per second (faster into the dark is slower,
// as eyes are). The tonemap multiplies its exposure by it.
#define KEEL_POST // screen-space: render targets, sampled clamped
#include "backend.glsl"
PUSH_BLOCK {
uint src; // the smallest bloom level
uint prev; // last frame's (0 = start fresh)
float dt;
float speed;
float key; // the brightness to aim for
float minE, maxE;
float pad;
} pc;
layout(location = 0) out vec4 o_exposure;
void main() {
float sum = 0.0;
for (int y = 0; y < 4; ++y)
for (int x = 0; x < 4; ++x) {
vec3 c = sampleTexLod(pc.src, (vec2(x, y) + 0.5) / 4.0, 0.0).rgb;
sum += log(max(dot(c, vec3(0.2126, 0.7152, 0.0722)), 1e-4));
}
float average = exp(sum / 16.0);
float target = clamp(pc.key / average, pc.minE, pc.maxE);
if (pc.prev == 0u) { o_exposure = vec4(target); return; }
float last = sampleTexLod(pc.prev, vec2(0.5), 0.0).r;
float rate = target > last ? pc.speed * 0.6 : pc.speed; // brightening (into the dark) is slower
o_exposure = vec4(last + (target - last) * (1.0 - exp(-pc.dt * rate)));
}