HDR, Bloom and SSR

This commit is contained in:
Halbear 2026-09-04 00:23:48 +01:00
parent 577836a03f
commit 04befce27d
44 changed files with 1377 additions and 269 deletions

View file

@ -2,13 +2,14 @@
layout(location = 0) in vec2 inTextCoord;
layout(location = 0) out float outAO;
layout(location = 1) out vec4 viewPos;
layout(set = 0, binding = 0) uniform sampler2D posSampler;
layout(set = 0, binding = 1) uniform sampler2D normalSampler;
layout(set = 0, binding = 2) uniform sampler2D noiseSampler;
layout(set = 1, binding = 0) readonly buffer SSAOKernel {
vec4 samples[];
layout(set = 1, binding = 0) uniform SSAOKernel {
vec4 samples[64];
} kernel;
layout(set = 2, binding = 0) uniform SSAOInfo {
@ -17,79 +18,75 @@ layout(set = 2, binding = 0) uniform SSAOInfo {
vec2 screenSize; // 136
float radius; //140
float bias; //144
int kernelSize; //160
int kernelSize; //148
float ResolutionScale; //152;
vec2 Padding; //160;
} ssao;
void main() {
vec2 uv = inTextCoord;
vec3 worldPos = texture(posSampler, uv).xyz;
vec3 worldNormal = normalize(texture(normalSampler, uv).xyz);
vec2 ScreenSize = ssao.screenSize * ssao.ResolutionScale;
vec2 noiseScale = ssao.screenSize / 4.0;
int KERNEL_SIZE = ssao.kernelSize;
vec3 fragPos = texture(posSampler, inTextCoord).xyz;
vec3 worldNorm = normalize(texture(normalSampler, inTextCoord).xyz);
if (length(worldNormal) < 0.001) {
if (dot(worldNorm, worldNorm) < 0.001) {
outAO = 1.0;
return;
}
vec3 fragPos = vec3(ssao.view * vec4(worldPos, 1.0));
vec3 normal = normalize(mat3(ssao.view) * worldNormal);
vec3 normal = normalize(mat3(ssao.view) * worldNorm);
vec3 randomVec = normalize(texture(noiseSampler, inTextCoord * noiseScale).xyz);
viewPos = vec4(fragPos, 1);
vec2 noiseScale = ScreenSize / 4.0;
vec3 randomVec = texture(noiseSampler, inTextCoord * noiseScale).xyz;
vec3 tangent = normalize(randomVec - normal * dot(randomVec, normal));
vec3 bitangent = cross(normal, tangent);
mat3 TBN = mat3(tangent, bitangent, normal);
float fragDepth = -fragPos.z;
float minOptimalDistance = 15;
float maxKernelSize = float(ssao.kernelSize);
// Calculate a dynamic loop limit based on proximity
// If closer than 1.5 units, smoothly scale down the loop count
int dynamicKernelSize = int(KERNEL_SIZE);
if (fragDepth < minOptimalDistance) {
float proximityFactor = clamp(fragDepth / minOptimalDistance, 0.2, 1.0);
dynamicKernelSize = int(maxKernelSize * proximityFactor);
}
// Force a hard minimum baseline of samples so SSAO doesn't completely disappear
dynamicKernelSize = max(dynamicKernelSize, 16);
float occlusion = 0.0;
float validSamples = 0.0;;
for (int i = 0; i < ssao.kernelSize; i++) {
vec3 samplePos = TBN * kernel.samples[i].xyz;
samplePos = fragPos + samplePos * ssao.radius;
float Passes = 0.0f;
vec4 offset = vec4(samplePos, 1.0);
offset = ssao.projection * offset;
for (int i = 0; i < dynamicKernelSize; i++) {
vec3 samplePos = fragPos + (TBN * kernel.samples[i].xyz) * ssao.radius;
vec4 offset = ssao.projection * vec4(samplePos, 1.0);
offset.xyz /= offset.w;
offset.xyz = offset.xyz * 0.5 + 0.5;
vec2 sampleUV = offset.xy;
sampleUV.y = 1 - sampleUV.y;
if (sampleUV.x < 0.0 || sampleUV.x > 1.0 ||
sampleUV.y < 0.0 || sampleUV.y > 1.0) {
vec2 sampleUV = clamp(vec2(offset.x, 1.0 - offset.y), 0.0, 1.0);
vec3 sampleViewPos = texture(posSampler, sampleUV).xyz;
float sampleDepth = -sampleViewPos.z;
float depthDelta = abs(fragDepth - sampleDepth);
if (depthDelta > ssao.radius * 2.0) {
continue;
}
vec3 sampleWorldPos = texture(posSampler, sampleUV).xyz;
vec3 sampleWorldNormal = texture(normalSampler, sampleUV).xyz;
if (length(sampleWorldNormal) < 0.001) {
continue;
}
vec3 sampleViewPos = vec3(ssao.view * vec4(sampleWorldPos, 1.0));
float depthDelta = abs(fragPos.z - sampleViewPos.z);
if (depthDelta > ssao.radius) {
continue;
}
float rangeCheck = 1.0 - depthDelta / ssao.radius;
rangeCheck = rangeCheck * rangeCheck * (3.0 - 2.0 * rangeCheck);
if (sampleViewPos.z >= samplePos.z + ssao.bias) {
occlusion += rangeCheck;
}
validSamples += 1;
float rangeCheck = smoothstep(0.0, 1.0, ssao.radius / depthDelta);
float isOccluded = step(samplePos.z + ssao.bias, sampleViewPos.z);
occlusion += isOccluded * rangeCheck;
Passes += 1.0;
}
if (validSamples <= 0.0) {
outAO = 1.0;
return;
float Subtraction = 0.0;
if(Passes > 0){
Subtraction = (occlusion / Passes);
}
occlusion = 1.0 - occlusion / validSamples;
outAO = occlusion * pow(occlusion, 3.0);
occlusion = 1.0 - Subtraction;
outAO = clamp(pow(occlusion, 3), 0.0, 1.0);
}