overte/libraries/render-utils/src/taa.slh
2017-08-30 22:42:55 -07:00

276 lines
7.2 KiB
Text

// Generated on <$_SCRIBE_DATE$>
//
// TAA.slh
// Common component needed by TemporalAntialiasing fragment shader
//
// Created by Sam Gateau on 8/17/2017
// Copyright 2017 High Fidelity, Inc.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
<@include DeferredTransform.slh@>
<$declareDeferredFrameTransform()$>
const int SEQUENCE_LENGTH = 16;
struct JitterSequence {
vec4 offsets[(SEQUENCE_LENGTH / 2) + 1];
};
layout(std140) uniform taaJitterBuffer {
JitterSequence sequence;
};
vec2 taa_getJitterSample(int index) {
return vec2((bool(index & 0x01) ? sequence.offsets[index >> 1].zw : sequence.offsets[index >> 1].xy));
}
int taa_getJitterSequenceLength() {
return int(sequence.offsets[(SEQUENCE_LENGTH / 2)].z);
}
int taa_getCurrentJitterIndex() {
return int(sequence.offsets[(SEQUENCE_LENGTH / 2)].w);
}
vec2 taa_getCurrentJitterSample() {
return taa_getJitterSample(taa_getCurrentJitterIndex());
}
<@include gpu/Color.slh@>
uniform sampler2D depthMap;
uniform sampler2D sourceMap;
uniform sampler2D historyMap;
uniform sampler2D velocityMap;
uniform sampler2D nextMap;
struct TAAParams
{
float debugX;
float blend;
float motionScale;
float debugShowVelocityThreshold;
ivec4 debug;
vec4 pixelInfo_orbZoom;
};
layout(std140) uniform taaParamsBuffer {
TAAParams params;
};
#define GET_BIT(bitfield, bitIndex) bool((bitfield) & (1 << (bitIndex)))
bool taa_showDebugCursor() {
return GET_BIT(params.debug.x, 1);
}
bool taa_showJitterSequence() {
return GET_BIT(params.debug.x, 2);
}
bool taa_showClosestFragment() {
return GET_BIT(params.debug.x, 3);
}
bool taa_unjitter() {
return GET_BIT(params.debug.y, 0);
}
bool taa_constrainColor() {
return GET_BIT(params.debug.y, 1);
}
vec2 taa_getDebugCursorTexcoord() {
return params.pixelInfo_orbZoom.xy;
}
float taa_getDebugOrbZoom() {
return params.pixelInfo_orbZoom.z;
}
vec4 taa_fetchColor(sampler2D map, vec2 uv) {
#if USE_YCOCG
vec4 c = texture(map, uv);
return vec4(color_LinearToYCoCg(c.rgb), c.a);
#else
return texture(map, uv);
#endif
}
vec3 taa_resolveColor(vec3 color) {
#if USE_YCOCG
return color_YCoCgToLinear(color);
#else
return color;
#endif
}
vec4 taa_fetchSourceMap(vec2 uv) {
#if USE_YCOCG
vec4 c = texture(sourceMap, uv);
return vec4(color_LinearToYCoCg(c.rgb), c.a);
#else
return texture(sourceMap, uv);
#endif
}
vec4 taa_fetchHistoryMap(vec2 uv) {
#if USE_YCOCG
vec4 c = texture(historyMap, uv);
return vec4(color_LinearToYCoCg(c.rgb), c.a);
#else
return texture(historyMap, uv);
#endif
}
vec4 taa_fetchNextMap(vec2 uv) {
#if USE_YCOCG
vec4 c = texture(nextMap, uv);
return vec4(color_LinearToYCoCg(c.rgb), c.a);
#else
return texture(nextMap, uv);
#endif
}
vec2 taa_fetchVelocityMap(vec2 uv) {
return texture(velocityMap, uv).xy;
}
float taa_fetchDepth(vec2 uv) {
return -texture(depthMap, vec2(uv), 0).x;
}
#define ZCMP_GT(a, b) (a > b)
vec3 taa_findClosestFragment3x3(vec2 uv)
{
vec2 dd = abs(getInvWidthHeight());
vec2 du = vec2(dd.x, 0.0);
vec2 dv = vec2(0.0, dd.y);
vec3 dtl = vec3(-1, -1, taa_fetchDepth(uv - dv - du));
vec3 dtc = vec3( 0, -1, taa_fetchDepth(uv - dv));
vec3 dtr = vec3( 1, -1, taa_fetchDepth(uv - dv + du));
vec3 dml = vec3(-1, 0, taa_fetchDepth(uv - du));
vec3 dmc = vec3( 0, 0, taa_fetchDepth(uv));
vec3 dmr = vec3( 1, 0, taa_fetchDepth(uv + du));
vec3 dbl = vec3(-1, 1, taa_fetchDepth(uv + dv - du));
vec3 dbc = vec3( 0, 1, taa_fetchDepth(uv + dv));
vec3 dbr = vec3( 1, 1, taa_fetchDepth(uv + dv + du));
vec3 dmin = dtl;
if (ZCMP_GT(dmin.z, dtc.z)) dmin = dtc;
if (ZCMP_GT(dmin.z, dtr.z)) dmin = dtr;
if (ZCMP_GT(dmin.z, dml.z)) dmin = dml;
if (ZCMP_GT(dmin.z, dmc.z)) dmin = dmc;
if (ZCMP_GT(dmin.z, dmr.z)) dmin = dmr;
if (ZCMP_GT(dmin.z, dbl.z)) dmin = dbl;
if (ZCMP_GT(dmin.z, dbc.z)) dmin = dbc;
if (ZCMP_GT(dmin.z, dbr.z)) dmin = dbr;
return vec3(uv + dd.xy * dmin.xy, dmin.z);
}
vec2 taa_fetchSourceAndHistory(vec2 fragUV, vec2 fragVelocity, out vec3 sourceColor, out vec3 historyColor) {
sourceColor = taa_fetchSourceMap(fragUV).xyz;
vec2 prevFragUV = fragUV - fragVelocity;
historyColor = sourceColor;
if (!(any(lessThan(prevFragUV, vec2(0.0))) || any(greaterThan(prevFragUV, vec2(1.0))))) {
historyColor = taa_fetchHistoryMap(prevFragUV).xyz;
}
return prevFragUV;
}
float Luminance(vec3 rgb) {
return rgb.x/4.0 + rgb.y/2.0 + rgb.z/4.0;
}
vec3 taa_temporalReprojection(vec3 sourceColor, vec3 historyColor, vec2 fragUV, vec2 fragVelocity, float fragZe, vec2 fragJitterPix)
{
vec4 texel1 = vec4(historyColor, 1.0);
vec4 texel0 = vec4(sourceColor, 1.0);
vec2 imageSize = getWidthHeight(0);
vec2 texelSize = getInvWidthHeight();
/* if (taa_unjitter()) {
fragUV += fragJitterPix * texelSize;
}*/
const float _SubpixelThreshold = 0.5;
const float _GatherBase = 0.5;
const float _GatherSubpixelMotion = 0.1666;
const float _FeedbackMin = 0.1;
const float _FeedbackMax = 0.9;
vec2 texel_vel = fragVelocity * imageSize;
float texel_vel_mag = length(texel_vel) * -fragZe;
float k_subpixel_motion = clamp(_SubpixelThreshold / (0.0001 + texel_vel_mag), 0.0, 1.0);
float k_min_max_support = _GatherBase + _GatherSubpixelMotion * k_subpixel_motion;
vec2 ss_offset01 = k_min_max_support * vec2(-texelSize.x, texelSize.y);
vec2 ss_offset11 = k_min_max_support * vec2(texelSize.x, texelSize.y);
vec4 c00 = taa_fetchSourceMap(fragUV - ss_offset11);
vec4 c10 = taa_fetchSourceMap(fragUV - ss_offset01);
vec4 c01 = taa_fetchSourceMap(fragUV + ss_offset01);
vec4 c11 = taa_fetchSourceMap(fragUV + ss_offset11);
vec4 cmin = min(c00, min(c10, min(c01, c11)));
vec4 cmax = max(c00, max(c10, max(c01, c11)));
#if USE_YCOCG || USE_CLIPPING
vec4 cavg = (c00 + c10 + c01 + c11) / 4.0;
#endif
// shrink chroma min-max
#if USE_YCOCG
vec2 chroma_extent = 0.25 * 0.5 * (cmax.r - cmin.r);
vec2 chroma_center = texel0.gb;
cmin.yz = chroma_center - chroma_extent;
cmax.yz = chroma_center + chroma_extent;
cavg.yz = chroma_center;
#endif
// clamp to neighbourhood of current sample
#if USE_CLIPPING
texel1 = clip_aabb(cmin.xyz, cmax.xyz, clamp(cavg, cmin, cmax), texel1);
#else
texel1 = clamp(texel1, cmin, cmax);
#endif
// feedback weight from unbiased luminance diff (t.lottes)
#if USE_YCOCG
float lum0 = texel0.r;
float lum1 = texel1.r;
#else
float lum0 = Luminance(texel0.rgb);
float lum1 = Luminance(texel1.rgb);
#endif
float unbiased_diff = abs(lum0 - lum1) / max(lum0, max(lum1, 0.2));
float unbiased_weight = 1.0 - unbiased_diff;
float unbiased_weight_sqr = unbiased_weight * unbiased_weight;
float k_feedback = mix(_FeedbackMin, _FeedbackMax, unbiased_weight_sqr);
// output
vec3 nextColor = mix(texel1, texel0, k_feedback).xyz;
return taa_resolveColor(nextColor);
}
<$declareColorWheel()$>
vec3 taa_getVelocityColorRelative(float velocityPixLength) {
return colorRamp(velocityPixLength/params.debugShowVelocityThreshold);
}
vec3 taa_getVelocityColorAboveThreshold(float velocityPixLength) {
return colorRamp((velocityPixLength - params.debugShowVelocityThreshold)/params.debugShowVelocityThreshold);
}