Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

TAA fixes and improvements #8318

Merged
merged 1 commit into from
Dec 18, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion filament/include/filament/Options.h
Original file line number Diff line number Diff line change
Expand Up @@ -438,7 +438,7 @@ struct MultiSampleAntiAliasingOptions {
* @see setTemporalAntiAliasingOptions()
*/
struct TemporalAntiAliasingOptions {
float filterWidth = 1.0f; //!< reconstruction filter width typically between 0.2 (sharper, aliased) and 1.5 (smoother)
float filterWidth = 1.0f; //!< reconstruction filter width typically between 1 (sharper) and 2 (smoother)
float feedback = 0.12f; //!< history feedback, between 0 (maximum temporal AA) and 1 (no temporal AA).
float lodBias = -1.0f; //!< texturing lod bias (typically -1 or -2)
float sharpness = 0.0f; //!< post-TAA sharpen, especially useful when upscaling is true.
Expand Down
35 changes: 25 additions & 10 deletions filament/src/PostProcessManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2622,7 +2622,7 @@ void PostProcessManager::TaaJitterCamera(
current.projection = inoutCameraInfo->projection * inoutCameraInfo->getUserViewMatrix();
current.frameId = previous.frameId + 1;

auto jitterPosition = [pattern = taaOptions.jitterPattern](size_t frameIndex){
auto jitterPosition = [pattern = taaOptions.jitterPattern](size_t frameIndex) -> float2 {
using JitterPattern = TemporalAntiAliasingOptions::JitterPattern;
switch (pattern) {
case JitterPattern::RGSS_X4:
Expand All @@ -2636,6 +2636,7 @@ void PostProcessManager::TaaJitterCamera(
case JitterPattern::HALTON_23_X32:
return sHaltonSamples(frameIndex);
}
return { 0.0f, 0.0f };
};

// sample position within a pixel [-0.5, 0.5]
Expand Down Expand Up @@ -2759,15 +2760,31 @@ FrameGraphId<FrameGraphTexture> PostProcessManager::taa(FrameGraph& fg,
}};

constexpr float2 sampleOffsets[9] = {
{ -1.0f, -1.0f }, { 0.0f, -1.0f }, { 1.0f, -1.0f },
{ -1.0f, 0.0f }, { 0.0f, 0.0f }, { 1.0f, 0.0f },
{ -1.0f, 1.0f }, { 0.0f, 1.0f }, { 1.0f, 1.0f },
{ -1.0f, -1.0f }, { 0.0f, -1.0f }, { 1.0f, -1.0f }, { -1.0f, 0.0f },
{ 0.0f, 0.0f },
{ 1.0f, 0.0f }, { -1.0f, 1.0f }, { 0.0f, 1.0f }, { 1.0f, 1.0f },
};

constexpr float2 subSampleOffsets[4] = {
{ -0.25f, 0.25f }, { 0.25f, 0.25f }, { 0.25f, -0.25f }, { -0.25f, -0.25f }
{ -0.25f, 0.25f },
{ 0.25f, 0.25f },
{ 0.25f, -0.25f },
{ -0.25f, -0.25f }
};

UTILS_UNUSED
auto const lanczos = [](float x, float a) -> float {
if (x <= std::numeric_limits<float>::epsilon()) {
return 1.0f;
}
if (std::abs(x) <= a) {
return (a * std::sin(f::PI * x) * std::sin(f::PI * x / a))
/ ((f::PI * f::PI) * (x * x));
}
return 0.0f;
};

float const filterWidth = std::clamp(taaOptions.filterWidth, 1.0f, 2.0f);
float4 sum = 0.0;
float4 weights[9];

Expand All @@ -2777,11 +2794,9 @@ FrameGraphId<FrameGraphTexture> PostProcessManager::taa(FrameGraph& fg,
for (size_t i = 0; i < 9; i++) {
float2 const o = sampleOffsets[i];
for (size_t j = 0; j < 4; j++) {
float2 const s = taaOptions.upscaling ? subSampleOffsets[j] : float2{ 0 };
float2 const d = (o - current.jitter - s) / taaOptions.filterWidth;
// This is a gaussian fit of a 3.3-wide Blackman-Harris window
// see: "High Quality Temporal Supersampling" by Brian Karis
weights[i][j] = std::exp(-2.29f * (d.x * d.x + d.y * d.y));
float2 const subPixelOffset = taaOptions.upscaling ? subSampleOffsets[j] : float2{ 0 };
float2 const d = (o - (current.jitter - subPixelOffset)) / filterWidth;
weights[i][j] = lanczos(length(d), filterWidth);
}
sum += weights[i];
}
Expand Down
2 changes: 1 addition & 1 deletion filament/src/PostProcessManager.h
Original file line number Diff line number Diff line change
Expand Up @@ -428,7 +428,7 @@ class PostProcessManager {

template<size_t SIZE>
struct JitterSequence {
auto operator()(size_t i) const noexcept { return positions[i % SIZE] - 0.5f; }
math::float2 operator()(size_t i) const noexcept { return positions[i % SIZE] - 0.5f; }
const std::array<math::float2, SIZE> positions;
};

Expand Down
78 changes: 38 additions & 40 deletions filament/src/materials/antiAliasing/taa.mat
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,8 @@ float lumaYCoCg(const vec3 c) {
}

float luma(const vec3 c) {
return materialConstants_useYCoCg ? lumaYCoCg(c) : lumaRGB(c);
return (materialConstants_useYCoCg && materialConstants_boxClipping != BOX_CLIPPING_NONE) ?
lumaYCoCg(c) : lumaRGB(c);
}

vec3 tonemap(const vec3 c) {
Expand Down Expand Up @@ -278,10 +279,6 @@ void postProcess(inout PostProcessInputs postProcess) {
history = textureLod(materialParams_history, uv.zw, 0.0);
}

if (materialConstants_useYCoCg) {
history.rgb = RGB_YCoCg(history.rgb);
}

highp vec2 size = vec2(textureSize(materialParams_color, 0));
highp vec2 p = (floor(uv.xy * size) + 0.5) / size;
vec4 filtered = textureLod(materialParams_color, p, 0.0);
Expand All @@ -297,47 +294,46 @@ void postProcess(inout PostProcessInputs postProcess) {
s[6] = textureLodOffset(materialParams_color, p, 0.0, ivec2(-1, 1)).rgb;
s[7] = textureLodOffset(materialParams_color, p, 0.0, ivec2( 0, 1)).rgb;
s[8] = textureLodOffset(materialParams_color, p, 0.0, ivec2( 1, 1)).rgb;
if (materialConstants_useYCoCg) {
for (int i = 0; i < 9; i++) {
s[i] = RGB_YCoCg(s[i]);
}
}
}

vec2 subPixelOffset = p - uv.xy; // +/- [0.25, 0.25]
float confidence = materialConstants_upscaling ? 0.0 : 1.0;
int j = 0;
float confidence = 1.0;
if (materialConstants_upscaling) {
highp vec2 subPixelOffset = (p - uv.xy) * size; // +/- [0.25, 0.25]

// we reduce the contribution of a sample based on the distance
// to the high resolution pixel center
const float cutoff = 0.5;
highp float l = length(materialParams.jitter - subPixelOffset) / cutoff;
confidence = saturate(1.0 - l * l);

if (materialConstants_filterInput) {
int jxp = subPixelOffset.y > 0.0 ? 1 : 2;
int jxn = subPixelOffset.y > 0.0 ? 0 : 3;
j = subPixelOffset.x > 0.0 ? jxp : jxn;
}
}

if (materialConstants_filterInput) {
// unjitter/filter input
// figure out which set of coeficients to use
filtered = vec4(0, 0, 0, filtered.a);
if (materialConstants_upscaling) {
int jxp = subPixelOffset.y > 0.0 ? 3 : 0;
int jxn = subPixelOffset.y > 0.0 ? 2 : 1;
int j = subPixelOffset.x > 0.0 ? jxp : jxn;
for (int i = 0; i < 9; i++) {
float w = materialParams.filterWeights[i][j];
filtered.rgb += s[i] * w;
confidence = max(confidence, w);
}
} else {
for (int i = 0; i < 9; i++) {
float w = materialParams.filterWeights[i][0];
filtered.rgb += s[i] * w;
}
}
} else {
if (materialConstants_useYCoCg) {
filtered.rgb = RGB_YCoCg(filtered.rgb);
}
if (materialConstants_upscaling) {
confidence = float(materialParams.jitter.x * subPixelOffset.x > 0.0 &&
materialParams.jitter.y * subPixelOffset.y > 0.0);
filtered = vec4(vec3(0), filtered.a);
for (int i = 0; i < 9; i++) {
float w = materialParams.filterWeights[i][j];
filtered.rgb += s[i] * w;
}
filtered.rgb = max(filtered.rgb, vec3(0));
}

// build the history clamping box
if (materialConstants_boxClipping != BOX_CLIPPING_NONE) {
if (materialConstants_useYCoCg) {
history.rgb = RGB_YCoCg(history.rgb);
filtered.rgb = RGB_YCoCg(filtered.rgb);
for (int i = 0; i < 9; i++) {
s[i] = RGB_YCoCg(s[i]);
}
}

vec3 boxmin;
vec3 boxmax;
if (materialConstants_boxType == BOX_TYPE_AABB ||
Expand All @@ -346,7 +342,7 @@ void postProcess(inout PostProcessInputs postProcess) {
boxmax = max(s[4], max(max(s[1], s[3]), max(s[5], s[7])));
vec3 box9min = min(boxmin, min(min(s[0], s[2]), min(s[6], s[8])));
vec3 box9max = max(boxmax, max(max(s[0], s[2]), max(s[6], s[8])));
// round the corners of the 3x3 box
// round the corners of the 3x3 box, giving less importance to the corner samples
boxmin = (boxmin + box9min) * 0.5;
boxmax = (boxmax + box9max) * 0.5;
}
Expand Down Expand Up @@ -388,9 +384,11 @@ void postProcess(inout PostProcessInputs postProcess) {
}

// go back to RGB space before tonemapping
if (materialConstants_useYCoCg) {
filtered.rgb = YCoCg_RGB(filtered.rgb);
history.rgb = YCoCg_RGB(history.rgb);
if (materialConstants_boxClipping != BOX_CLIPPING_NONE) {
if (materialConstants_useYCoCg) {
filtered.rgb = YCoCg_RGB(filtered.rgb);
history.rgb = YCoCg_RGB(history.rgb);
}
}

// tonemap before mixing
Expand Down
Loading