add compute shader to auto calculate screen exposure, add SSBO impl
This commit is contained in:
63
Editor/assets/shaders/Exposure.glsl
Normal file
63
Editor/assets/shaders/Exposure.glsl
Normal file
@ -0,0 +1,63 @@
|
||||
#type compute
|
||||
#version 460 core
|
||||
layout(local_size_x = 1, local_size_y = 1) in;
|
||||
|
||||
layout(binding = 0, std430) buffer Histogram {
|
||||
uint bins[64];
|
||||
};
|
||||
layout(binding = 1, std430) buffer Exposure {
|
||||
float exposure;
|
||||
};
|
||||
|
||||
uniform float u_SpeedUp;
|
||||
uniform float u_SpeedDown;
|
||||
uniform float u_Key;
|
||||
uniform float u_LowPercent;
|
||||
uniform float u_HighPercent;
|
||||
uniform float u_MinExposure;
|
||||
uniform float u_MaxExposure;
|
||||
uniform float u_DeltaTime;
|
||||
uniform float u_LogMin;
|
||||
uniform float u_LogMax;
|
||||
|
||||
void main() {
|
||||
float currentExposure = exposure;
|
||||
|
||||
uint total = 0;
|
||||
uint prefix[64];
|
||||
for (int i = 0; i < 64; i++) {
|
||||
total += bins[i];
|
||||
prefix[i] = total;
|
||||
}
|
||||
|
||||
float lowCount = u_LowPercent * 0.01 * total;
|
||||
float highCount = u_HighPercent * 0.01 * total;
|
||||
int lowBin = 0, highBin = 63;
|
||||
for (int i = 0; i < 64; i++) {
|
||||
if (prefix[i] < lowCount) lowBin = i + 1;
|
||||
if (prefix[i] < highCount) highBin = i + 1;
|
||||
}
|
||||
lowBin = clamp(lowBin, 0, 63);
|
||||
highBin = clamp(highBin, 0, 63);
|
||||
|
||||
float sumLum = 0.0;
|
||||
uint count = 0;
|
||||
for (int i = lowBin; i <= highBin; i++) {
|
||||
float t = (float(i) + 0.5) / 64.0;
|
||||
float logLum = u_LogMin + t * (u_LogMax - u_LogMin);
|
||||
float lum = exp2(logLum);
|
||||
sumLum += lum * float(bins[i]);
|
||||
count += bins[i];
|
||||
}
|
||||
float avgLum = count > 0 ? sumLum / count : 0.18;
|
||||
|
||||
float targetExposure = u_Key / max(avgLum, 0.0001);
|
||||
targetExposure = clamp(targetExposure, u_MinExposure, u_MaxExposure);
|
||||
|
||||
float speed = (targetExposure > currentExposure) ? u_SpeedUp : u_SpeedDown;
|
||||
float adaptFactor = 1.0 - exp(-speed * u_DeltaTime);
|
||||
float newExposure = mix(currentExposure, targetExposure, adaptFactor);
|
||||
newExposure = clamp(newExposure, u_MinExposure, u_MaxExposure);
|
||||
|
||||
exposure = newExposure;
|
||||
}
|
||||
26
Editor/assets/shaders/Histogram.glsl
Normal file
26
Editor/assets/shaders/Histogram.glsl
Normal file
@ -0,0 +1,26 @@
|
||||
#type compute
|
||||
#version 460 core
|
||||
layout(local_size_x = 16, local_size_y = 16) in;
|
||||
|
||||
layout(binding = 0) uniform sampler2D u_SceneColor;
|
||||
layout(binding = 1, std430) buffer Histogram {
|
||||
uint bins[64];
|
||||
};
|
||||
|
||||
uniform float u_LogMin;
|
||||
uniform float u_LogMax;
|
||||
|
||||
void main() {
|
||||
ivec2 texel = ivec2(gl_GlobalInvocationID.xy);
|
||||
ivec2 size = textureSize(u_SceneColor, 0);
|
||||
if (texel.x >= size.x || texel.y >= size.y) return;
|
||||
|
||||
vec3 color = texelFetch(u_SceneColor, texel, 0).rgb;
|
||||
float lum = max(dot(color, vec3(0.2126, 0.7152, 0.0722)), 0.0001);
|
||||
float logLum = log2(lum);
|
||||
|
||||
float invLogRange = 1.0 / (u_LogMax - u_LogMin);
|
||||
float t = (logLum - u_LogMin) * invLogRange;
|
||||
int bin = int(clamp(t * 64.0, 0.0, 63.0));
|
||||
atomicAdd(bins[bin], 1u);
|
||||
}
|
||||
@ -23,7 +23,14 @@ in vec2 v_TexCoord;
|
||||
|
||||
uniform sampler2DMS u_Texture;
|
||||
|
||||
uniform float u_Exposure;
|
||||
|
||||
uniform bool u_EnableAutoExposure;
|
||||
uniform float u_ManualExposure;
|
||||
layout(std430, binding = 2) buffer Exposure
|
||||
{
|
||||
float u_Exposure;
|
||||
};
|
||||
|
||||
uniform int u_TextureSamples;
|
||||
|
||||
uniform bool u_EnableBloom;
|
||||
@ -64,7 +71,10 @@ void main()
|
||||
color += bloomColor;
|
||||
}
|
||||
|
||||
color *= u_Exposure;
|
||||
if(u_EnableAutoExposure)
|
||||
color *= u_Exposure;
|
||||
else
|
||||
color *= u_ManualExposure;
|
||||
|
||||
// Reinhard tonemapping operator.
|
||||
// see: "Photographic Tone Reproduction for Digital Images", eq. 4
|
||||
|
||||
Reference in New Issue
Block a user