Skip to content

Commit

Permalink
Merge branch 'feat-taa-translation'
Browse files Browse the repository at this point in the history
  • Loading branch information
yvt committed Jan 17, 2021
2 parents 03a8b97 + debf3aa commit 99f3f79
Show file tree
Hide file tree
Showing 4 changed files with 89 additions and 19 deletions.
38 changes: 34 additions & 4 deletions Resources/Shaders/PostFilters/TemporalAA.fs
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,13 @@


uniform sampler2D inputTexture;
uniform sampler2D depthTexture;
uniform sampler2D previousTexture;
uniform sampler2D processedInputTexture;
uniform vec2 inverseVP;
uniform mat4 reprojectionMatrix;

varying vec2 texCoord;
varying vec3 reprojectedTexCoord;
/* UE4-style temporal AA. Implementation is based on my ShaderToy submission */

// YUV-RGB conversion routine from Hyper3D
Expand All @@ -49,12 +50,41 @@ vec3 decodePalYuv(vec3 yuv)


void main() {
vec4 lastColor = texture2D(previousTexture, reprojectedTexCoord.xy / reprojectedTexCoord.z);

// ------------------------------------------------------------------------
// Reprojection
//
// Calulate the Z position of the current pixel. Take the minimum Z value
// of the neighboring pixels to preserve the antialiasing of foreground
// objects.
vec2 off = inverseVP;
float inputZ0 = texture2D(depthTexture, texCoord).x;
float inputZ1 = texture2D(depthTexture, texCoord + vec2(+off.x, 0.0)).x;
float inputZ2 = texture2D(depthTexture, texCoord + vec2(-off.x, 0.0)).x;
float inputZ3 = texture2D(depthTexture, texCoord + vec2(0.0, +off.y)).x;
float inputZ4 = texture2D(depthTexture, texCoord + vec2(0.0, -off.y)).x;
float inputZ5 = texture2D(depthTexture, texCoord + vec2(+off.x, +off.y)).x;
float inputZ6 = texture2D(depthTexture, texCoord + vec2(-off.x, +off.y)).x;
float inputZ7 = texture2D(depthTexture, texCoord + vec2(+off.x, -off.y)).x;
float inputZ8 = texture2D(depthTexture, texCoord + vec2(-off.x, -off.y)).x;
float inputZ = min(min(min(inputZ0, inputZ1), min(inputZ2, inputZ3)),
min(min(inputZ4, inputZ5), min(inputZ6, min(inputZ7, inputZ8))));

// Predict where the point was in the previous frame. The Z range [0, 0.1]
// is for a view weapon, so assume no movement in this range.
vec4 reprojectedTexCoord;
if (inputZ < 0.1) {
reprojectedTexCoord.xy = texCoord.xy;
} else {
reprojectedTexCoord = reprojectionMatrix * vec4(texCoord, inputZ, 1.0);
reprojectedTexCoord.xy /= reprojectedTexCoord.w;
}

vec4 lastColor = texture2D(previousTexture, reprojectedTexCoord.xy);

// ------------------------------------------------------------------------
vec3 antialiased = lastColor.xyz;
float mixRate = min(lastColor.w, 0.5);

vec2 off = inverseVP;
vec3 in0 = texture2D(processedInputTexture, texCoord).xyz;

antialiased = mix(antialiased, in0, mixRate);
Expand Down
6 changes: 0 additions & 6 deletions Resources/Shaders/PostFilters/TemporalAA.vs
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,6 @@
attribute vec2 positionAttribute;

varying vec2 texCoord;
varying vec3 reprojectedTexCoord;
uniform mat4 reprojectionMatrix;

void main() {
vec2 pos = positionAttribute;
Expand All @@ -34,9 +32,5 @@ void main() {
gl_Position = vec4(scrPos, 0.5, 1.);

texCoord = pos;

reprojectedTexCoord = (reprojectionMatrix * vec4(scrPos, 1., 0.)).xyz;
reprojectedTexCoord.xy *= 0.5;
reprojectedTexCoord.xy += vec2(reprojectedTexCoord.z) * .5;
}

63 changes: 54 additions & 9 deletions Sources/Draw/GLTemporalAAFilter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ namespace spades {
namespace draw {
GLTemporalAAFilter::GLTemporalAAFilter(GLRenderer *renderer) : renderer(renderer) {
prevMatrix = Matrix4::Identity();
prevViewOrigin = Vector3(0.0f, 0.0f, 0.0f);
program = renderer->RegisterProgram("Shaders/PostFilters/TemporalAA.program");

// Preload
Expand All @@ -62,25 +63,65 @@ namespace spades {
IGLDevice *dev = renderer->GetGLDevice();
GLQuadRenderer qr(dev);

// Compute the reprojection matrix
// Calculate the current view-projection matrix.
const client::SceneDefinition &def = renderer->GetSceneDef();
Matrix4 newMatrix = Matrix4::Identity();
Vector3 axes[] = {def.viewAxis[0], def.viewAxis[1], def.viewAxis[2]};
axes[0] /= std::tan(def.fovX * 0.5f);
axes[1] /= std::tan(def.fovY * 0.5f);
newMatrix.m[0] = axes[0].x;
newMatrix.m[1] = axes[1].x;
newMatrix.m[2] = axes[2].x;
newMatrix.m[2] = -axes[2].x;
newMatrix.m[4] = axes[0].y;
newMatrix.m[5] = axes[1].y;
newMatrix.m[6] = axes[2].y;
newMatrix.m[6] = -axes[2].y;
newMatrix.m[8] = axes[0].z;
newMatrix.m[9] = axes[1].z;
newMatrix.m[10] = axes[2].z;
newMatrix.m[10] = -axes[2].z;

Matrix4 projectionMatrix;
{
// From `GLRenderer::BuildProjectionMatrix`
float near = def.zNear;
float far = def.zFar;
float t = near * std::tan(def.fovY * .5f);
float r = near * std::tan(def.fovX * .5f);
float a = r * 2.f, b = t * 2.f, c = far - near;
Matrix4 &mat = projectionMatrix;
mat.m[0] = near * 2.f / a;
mat.m[1] = 0.f;
mat.m[2] = 0.f;
mat.m[3] = 0.f;
mat.m[4] = 0.f;
mat.m[5] = near * 2.f / b;
mat.m[6] = 0.f;
mat.m[7] = 0.f;
mat.m[8] = 0.f;
mat.m[9] = 0.f;
mat.m[10] = -(far + near) / c;
mat.m[11] = -1.f;
mat.m[12] = 0.f;
mat.m[13] = 0.f;
mat.m[14] = -(far * near * 2.f) / c;
mat.m[15] = 0.f;
}

newMatrix = projectionMatrix * newMatrix;

// In `y = newMatrix * x`, the coordinate space `y` belongs to must
// cover the clip region by range `[0, 1]` (like texture coordinates)
// instead of `[-1, 1]` (like OpenGL clip coordinates)
newMatrix = Matrix4::Translate(1.0f, 1.0f, 1.0f) * newMatrix;
newMatrix = Matrix4::Scale(0.5f, 0.5f, 0.5f) * newMatrix;

// Camera translation must be incorporated into the calculation
// separately to avoid numerical errors. (You'd be suprised to see
// how visible the visual artifacts can be.)
Matrix4 translationMatrix = Matrix4::Translate(def.viewOrigin - prevViewOrigin);

// Compute the reprojection matrix
Matrix4 inverseNewMatrix = newMatrix.Inversed();
Matrix4 diffMatrix = prevMatrix * inverseNewMatrix;
Matrix4 diffMatrix = prevMatrix * translationMatrix * inverseNewMatrix;
prevMatrix = newMatrix;
prevViewOrigin = def.viewOrigin;

if (!historyBuffer.valid || historyBuffer.width != input.GetWidth() ||
historyBuffer.height != input.GetHeight()) {
Expand Down Expand Up @@ -155,10 +196,9 @@ namespace spades {
return GLFXAAFilter{renderer}.Filter(input);
}() : input; */

// TODO: take camera translation (not just rotation) into account during reprojection

static GLProgramAttribute positionAttribute("positionAttribute");
static GLProgramUniform inputTexture("inputTexture");
static GLProgramUniform depthTexture("depthTexture");
static GLProgramUniform previousTexture("previousTexture");
static GLProgramUniform processedInputTexture("processedInputTexture");
static GLProgramUniform reprojectionMatrix("reprojectionMatrix");
Expand All @@ -168,6 +208,7 @@ namespace spades {

positionAttribute(program);
inputTexture(program);
depthTexture(program);
previousTexture(program);
processedInputTexture(program);
reprojectionMatrix(program);
Expand All @@ -178,6 +219,7 @@ namespace spades {
inputTexture.SetValue(0);
previousTexture.SetValue(1);
processedInputTexture.SetValue(2);
depthTexture.SetValue(3);
reprojectionMatrix.SetValue(diffMatrix);
inverseVP.SetValue(1.f / input.GetWidth(), 1.f / input.GetHeight());

Expand All @@ -190,6 +232,9 @@ namespace spades {
dev->BindTexture(IGLDevice::Texture2D, historyBuffer.texture);
dev->ActiveTexture(2);
dev->BindTexture(IGLDevice::Texture2D, processedInput.GetTexture());
dev->ActiveTexture(3);
dev->BindTexture(IGLDevice::Texture2D,
renderer->GetFramebufferManager()->GetDepthTexture());
dev->ActiveTexture(0);
dev->BindFramebuffer(IGLDevice::Framebuffer, output.GetFramebuffer());
dev->Viewport(0, 0, output.GetWidth(), output.GetHeight());
Expand Down
1 change: 1 addition & 0 deletions Sources/Draw/GLTemporalAAFilter.h
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ namespace spades {
} historyBuffer;

Matrix4 prevMatrix;
Vector3 prevViewOrigin;
std::size_t jitterTableIndex = 0;

void DeleteHistoryBuffer();
Expand Down

0 comments on commit 99f3f79

Please sign in to comment.