1#version 450 core 2#extension GL_ARB_separate_shader_objects : enable 3#extension GL_ARB_shading_language_420pack : enable 4 5// includes 6 7#include "render/shaders/common/render_color_conversion_common.h" 8#include "render/shaders/common/render_post_process_common.h" 9#include "render/shaders/common/render_tonemap_common.h" 10 11// sets 12 13#include "render/shaders/common/render_post_process_layout_common.h" 14 15layout(set = 1, binding = 0) uniform texture2D uDepth; 16layout(set = 1, binding = 1) uniform texture2D uColor; 17layout(set = 1, binding = 2) uniform texture2D uVelocity; 18layout(set = 1, binding = 3) uniform texture2D uHistory; 19layout(set = 1, binding = 4) uniform sampler uSampler; 20 21// in / out 22 23layout(location = 0) in vec2 inUv; 24 25layout(location = 0) out vec4 outColor; 26 27// NOTE: cannot be used (remove if not used for any input) 28#define ENABLE_INPUT_ATTACHMENTS 0 29 30#define QUALITY_LOW 0 31#define QUALITY_MED 1 32#define QUALITY_HIGH 2 33 34float GetUnpackDepthBuffer(const vec2 uv) 35{ 36#if (ENABLE_INPUT_ATTACHMENTS == 1) 37 return subpassLoad(uDepth).x; 38#else 39 return textureLod(sampler2D(uDepth, uSampler), uv, 0).x; 40#endif 41} 42 43vec2 GetUnpackVelocity(const vec2 uv, const vec2 invSize) 44{ 45#if (ENABLE_INPUT_ATTACHMENTS == 1) 46 return subpassLoad(uVelocity).xy; 47#else 48 return textureLod(sampler2D(uVelocity, uSampler), uv, 0).xy * invSize; 49#endif 50} 51 52vec2 GetVelocity() 53{ 54 const uint quality = uint(uPc.factor.x + 0.5); 55 vec2 velUv = inUv; 56 if (quality >= QUALITY_MED) { 57 const uint offsetCount = 5; 58 const ivec2 offsets[offsetCount] = { 59 ivec2(-1, -1), 60 ivec2(1, -1), 61 ivec2(0, 0), 62 ivec2(-1, 1), 63 ivec2(1, 1), 64 }; 65 66 // NOTE: needs compile time constant offset and does not compile if e.g. passed to function 67 vec2 batch1 = vec2(1.0, textureLodOffset(sampler2D(uDepth, uSampler), inUv.xy, 0.0, offsets[0]).x); 68 vec2 batch2 = vec2(textureLodOffset(sampler2D(uDepth, uSampler), inUv.xy, 0.0, offsets[1]).x, textureLodOffset(sampler2D(uDepth, uSampler), inUv.xy, 0.0, offsets[2]).x); 69 ivec2 index = mix(ivec2(2, 0), ivec2(1, 2), lessThan(batch1, batch2)); 70 batch1 = mix(batch1, batch2, lessThan(batch1, batch2)); 71 72 vec2 batch3 = vec2(textureLodOffset(sampler2D(uDepth, uSampler), inUv.xy, 0.0, offsets[3]).x, textureLodOffset(sampler2D(uDepth, uSampler), inUv.xy, 0.0, offsets[4]).x); 73 index = mix(index, ivec2(3, 4), lessThan(batch1, batch3)); 74 batch1 = mix(batch1, batch3, lessThan(batch1, batch3)); 75 76 ivec2 offset = offsets[batch1.x < batch1.y?index.x:index.y]; 77 float depth = batch1.x <batch1.y ? batch1.x : batch1.y; 78 79 velUv += offset * (uPc.viewportSizeInvSize.zw); 80 } 81 // multiply velocity to correct uv offsets 82 return textureLod(sampler2D(uVelocity, uSampler), velUv, 0).xy * uPc.viewportSizeInvSize.zw; 83} 84 85// clip towards aabb center 86// e.g. "temporal reprojection anti-aliasing in inside" 87vec4 ClipAabb(const vec3 aabbMin, const vec3 aabbMax, const vec4 color, const vec4 history) 88{ 89 const vec3 pClip = 0.5 * (aabbMax + aabbMin); 90 const vec3 eClip = 0.5 * (aabbMax - aabbMin); 91 92 const vec4 vClip = history - vec4(pClip, color.w); 93 const vec3 vUnit = vClip.xyz - eClip; 94 const vec3 aUnit = abs(vUnit); 95 const float maUnit = max(aUnit.x, max(aUnit.y, aUnit.z)); 96 // if maUnit <= 1.0 the point is inside the aabb 97 const vec4 res = (maUnit > 1.0) ? (vec4(pClip, color.w) + vClip / maUnit) : color; 98 return res; 99} 100 101void main(void) 102{ 103 // NOTE: could use closest depth 3x3 velocity 104 const vec2 velocity = GetVelocity(); 105 const vec2 historyUv = inUv.xy - velocity; 106 107 const vec4 colorSample = textureLod(sampler2D(uColor, uSampler), inUv.xy, 0.0); 108 const float frameAlpha = colorSample.a; 109 vec4 currColor = colorSample; 110 111 // NOTE: add filtered option for less blurred history 112 vec4 history = textureLod(sampler2D(uHistory, uSampler), historyUv, 0.0); 113 // sample 3x3 grid 114 // 0 1 2 115 // 3 4 5 116 // 6 7 8 117 118 // Box filter for history 119 // diamond shape 120 vec3 bc1 = textureLodOffset(sampler2D(uColor, uSampler), inUv.xy, 0.0, ivec2(0, -1)).rgb; 121 vec3 bc3 = textureLodOffset(sampler2D(uColor, uSampler), inUv.xy, 0.0, ivec2(-1, 0)).rgb; 122 // center sample 123 vec3 bc4 = currColor.rgb; 124 vec3 min13 = min(min(bc1, bc3), bc4); 125 vec3 max13 = max(max(bc1, bc3), bc4); 126 127 vec3 bc5 = textureLodOffset(sampler2D(uColor, uSampler), inUv.xy, 0.0, ivec2(1, 0)).rgb; 128 vec3 bc7 = textureLodOffset(sampler2D(uColor, uSampler), inUv.xy, 0.0, ivec2(0, 1)).rgb; 129 vec3 min57 = min(bc5, bc7); 130 vec3 max57 = max(bc5, bc7); 131 vec3 boxMin = min(min13, min57); 132 vec3 boxMax = max(max13, max57); 133 134 // 135 vec3 bc0 = textureLodOffset(sampler2D(uColor, uSampler), inUv.xy, 0.0, ivec2(-1, -1)).rgb; 136 vec3 bc2 = textureLodOffset(sampler2D(uColor, uSampler), inUv.xy, 0.0, ivec2(1, -1)).rgb; 137 vec3 min02 = min(boxMin, min(bc0, bc2)); 138 vec3 max02 = max(boxMax, max(bc0, bc2)); 139 140 vec3 bc6 = textureLodOffset(sampler2D(uColor, uSampler), inUv.xy, 0.0, ivec2(-1, 1)).rgb; 141 vec3 bc8 = textureLodOffset(sampler2D(uColor, uSampler), inUv.xy, 0.0, ivec2(1, 1)).rgb; 142 vec3 min68 = min(bc6, bc8); 143 vec3 max68 = max(bc6, bc8); 144 145 // corners 146 const vec3 boxMinCorner = min(min02, min68); 147 const vec3 boxMaxCorner = max(max02, max68); 148 149 // NOTE: add 150 // filter with tonemapping and yCoCG 151 152 boxMin = (boxMin + boxMinCorner) * 0.5; 153 boxMax = (boxMax + boxMaxCorner) * 0.5; 154 155 // NOTE: add option to use clipping 156 history.rgb = clamp(history.rgb, boxMin, boxMax); 157 158 // luma based tonemapping as suggested by Karis 159 const float historyLuma = CalcLuma(history.rgb); 160 const float colorLuma = CalcLuma(currColor.rgb); 161 162 history.rgb *= 1.0 / (1.0 + historyLuma); 163 currColor.rgb *= 1.0 / (1.0 + colorLuma); 164 165 const float taaAlpha = uPc.factor.a; 166 vec4 color = mix(history, currColor, taaAlpha); 167 168 // inverse tonemap 169 color.rgb *= 1.0 / (1.0 - CalcLuma(color.rgb)); 170 171 // safety for removing negative values 172 outColor = max(color, vec4(0.0)); 173} 174