81 lines
1.9 KiB
GLSL
81 lines
1.9 KiB
GLSL
#version 450
|
|
|
|
layout(location=0) in vec2 inUV;
|
|
layout(location=0) out vec4 outColor;
|
|
|
|
layout(set=0, binding=0) uniform sampler2D uHdr;
|
|
|
|
layout(push_constant) uniform Push
|
|
{
|
|
float exposure;
|
|
int mode;
|
|
int bloomEnabled;
|
|
float bloomThreshold;
|
|
float bloomIntensity;
|
|
} pc;
|
|
|
|
vec3 reinhard(vec3 x)
|
|
{
|
|
return x / (1.0 + x);
|
|
}
|
|
|
|
// Narkowicz ACES approximation
|
|
vec3 aces_tonemap(vec3 x)
|
|
{
|
|
// https://64.github.io/tonemapping/
|
|
const float a = 2.51;
|
|
const float b = 0.03;
|
|
const float c = 2.43;
|
|
const float d = 0.59;
|
|
const float e = 0.14;
|
|
return clamp((x*(a*x+b))/(x*(c*x+d)+e), 0.0, 1.0);
|
|
}
|
|
|
|
void main()
|
|
{
|
|
vec3 hdr = texture(uHdr, inUV).rgb;
|
|
|
|
// Simple bloom in HDR space: gather bright neighbors and add a small blurred contribution.
|
|
if (pc.bloomEnabled != 0)
|
|
{
|
|
vec2 texel = 1.0 / vec2(textureSize(uHdr, 0));
|
|
vec3 bloom = vec3(0.0);
|
|
int radius = 2;
|
|
int count = 0;
|
|
for (int x = -radius; x <= radius; ++x)
|
|
{
|
|
for (int y = -radius; y <= radius; ++y)
|
|
{
|
|
vec2 offset = vec2(x, y) * texel;
|
|
vec3 c = texture(uHdr, clamp(inUV + offset, vec2(0.0), vec2(1.0))).rgb;
|
|
float bright = max(max(c.r, c.g), c.b) - pc.bloomThreshold;
|
|
if (bright > 0.0)
|
|
{
|
|
bloom += c * bright;
|
|
count++;
|
|
}
|
|
}
|
|
}
|
|
if (count > 0)
|
|
{
|
|
bloom /= float(count);
|
|
}
|
|
hdr += pc.bloomIntensity * bloom;
|
|
}
|
|
|
|
// Simple exposure
|
|
float exposure = max(pc.exposure, 0.0001);
|
|
vec3 mapped = hdr * exposure;
|
|
|
|
if (pc.mode == 1)
|
|
mapped = aces_tonemap(mapped);
|
|
else
|
|
mapped = reinhard(mapped);
|
|
|
|
const float gamma = 2.2;
|
|
mapped = pow(mapped, vec3(1.0 / gamma));
|
|
|
|
outColor = vec4(mapped, 1.0);
|
|
}
|
|
|