NVIDIA TXAA 3.0 creates a smoother, clearer image than any other anti-aliasing solution by combining high-quality MSAA multisample anti-aliasing, post process, and NVIDIA designed temporal filters. This release provides a temporal super-sampling solution that is known to work with the deferred engines without incurring the high cost of shading at every sample, large G-buffers and the associated bandwidth. The central idea in temporal super sampling is to shade the geometry at different sample locations within a pixel every frame and then average the color values over the last few frames. Shading at different sample locations is achieved by jittering the projection matrix (thus effectively changing sample locations for all pixels). Exponential average instead of a simple average requires only the last frame instead of multiple frames. The last frame’s color includes the contributions from its previous frames and so on. However, when the objects are in relative motion with respect to camera, pixel’s history is found at some other location - the pixel’s position in its previous frame. In such a case, the motion vector at each pixel is used to find where the current pixel was in the previous frame. Application needs to generate the motion vector at each sample location. If the color of the corresponding pixel in the previous frame is very different from the current color, a closest approximation is made using the color space bounding box of its neighborhood and clipping the previous color against that bounding box. This release introduces a newer way of calculating the bounding box using the statistical metrics. This newer way tends to produce tighter bounding boxes resulting in less ghosting but can potentially cause flicker when the camera is not moving. We provide additional knobs to control the flicker.
For more details on temporal super-sampling and statistics based color space bounding box calculations, please follow the references linked in the Features section.
doc/—this documentation page.
extensions/—extra utilities and libraries for use with TXAA.
external/—external dependencies needed for TXAA and samples.
include/—C/C++ header files to include into your project.
lib/—TXAA import libraries and dlls.
samples/—TXAA sample program.
Temporal Re-projection Modes
MSAA Modes
The TXAA resolve takes a debug render target that can aid debugging.
View MSAA
View Motion Vectors
Mode: NV_TXAA_DEBUGCHANNEL_MOTIONVECTORS
View Difference Between MSAA and Temporal Re-projection
Mode: NV_TXAA_DEBUGCHANNEL_TEMPORALDIFFS
View Temporal Re-projection
View Control
TXAA Replaces the MSAA resolve step with this custom resolve pipeline
AxB sized MSAA RGBA color ---------> T --> AxB sized RGBA resolved color
AxB sized motion vector ---------> X |
AxB sized RGBA feedback ---------> A |
AXB sized depth ---------> A |
| |
+----------------------------------------------------------------+
TXAA needs two AxB sized resolve surfaces (because of the feedback).
NOTE, if the AxB sized RGBA resolved color surface is going to be modified after TXAA, then it needs to be copied, and the unmodified copy needs to be feed back into the next TXAA frame.
NOTE, resolved depth is best resolved for TXAA with the minimum depth of all samples in the pixel. If required one can write min depth for TXAA and max depth for particles in the same resolve pass (if the game needs max depth for something else).
Starting with this release, users can apply jitter offsets of less than one pixel to the projection matrix. This has the same effect as that of moving the visibility and shading samples by the same offsets in the opposite directions. The offsets can be from a low discrepancy sequence e.g. Sobol, and repeat after some number of frames e.g. 16. During the spatial resolve phase, we need to filter the results and the filter weights must be adjusted for these offsets. As a result, these offsets need to be conveyed along with the other resolve parameters.
TXAA is a temporal approach to anti-aliasing; as such, it introduces an inter frame dependency on the RGBA feedback surface, which could hinder SLI scaling in AFR mode. An approach for removing the inter frame dependency is to use the NvAPI to manage a separate feedback buffer for each GPU. The TXAA11 sample application that is included with the TXAA library uses the technique to remove the inter frame dependency, improving SLI scaling.
TXAA requires linear RGB color input.
Use DXGI_FORMAT_R16G16B16A16_FLOAT for HDR.
Tone-mapping the linear HDR data to low-dynamic-range is done in TXAA and TXAA will preserve the linear color space when finishes its pass. For example, after post-processing at the time of color-grading. The hack to tone-map prior to resolve, to workaround the artifacts of the traditional MSAA box filter resolve, is not needed with TXAA. Tone-map prior to resolve will result on wrong colors on thin features.
There is support for compressing some or all of the dynamic range before the resolve using the NvTxaaCompressionRange struct. With TXAA dynamic range compression enabled, the resolved frame will be decompressed back to linear HDR automatically; the application should always supply linear HDR data, and should expect linear HDR results back from TXAA.
The motion vector field input is FP16, where:
Suggestions for integration:
Best case have proper motion vectors.
May need to move the motion vector generation to before the MSAA resolve.
This library does not save and restore GPU state. All modified GPU state is noted in the API documentation and in the function prototype comments.
Suggested way of TXAA 3.0 integration. Per-pixel motion vector is needed for this method. Value in each pixel is a 2d direction pointing to the previous projected coordinate by the corresponding vertex.
Initialize Context
// DX11
#define __GFSDK_DX11__
#include <GFSDK_TXAA.h>
NvTxaaContextDX11 txaaCtx;
ID3D11Device *dev;
if (NV_TXAA_STATUS_OK != GFSDK_TXAA_DX11_InitializeContext(&txaaCtx, dev)) // No TXAA.
// GL
#define __GFSDK_GL__
#include <GFSDK_TXAA.h>
TxaaCtx txaaCtx;
if (NV_TXAA_STATUS_OK != GFSDK_TXAA_GL_InitializeContext(&txaaCtx)) // No TXAA.
// GL
// This feature is not yet supported in Open GL version of TXAA 3.0.
Replace the MSAA Resolve Step with the TXAA Resolve
Custom Motion Vector
// DX11
NvTxaaContextDX11 *ctx; // TXAA context.
ID3D11DeviceContext *dxCtx; // DX11 device context.
ID3D11RenderTargetView *dstRtv; // Destination texture.
ID3D11ShaderResourceView *msaaSrv; // Source MSAA texture shader resource view.
ID3D11ShaderResourceView *mvSrv; // Source motion vector texture SRV.
ID3D11ShaderResourceView *dstSrv; // SRV to feedback resolve results from prior frame.
ID3D11ShaderResourceView *ctrlSrv; // Per pixel control, can be null.
NvTxaaFeedbackParameters fb; // Feedback parameters
NvTxaaResolveParametersDX11 resolveParameters;
memset(&resolveParameters, 0, sizeof(resolveParameters));
resolveParameters.txaaContext = &m_txaaContext;
resolveParameters.deviceContext = deviceContext;
resolveParameters.resolveTarget = m_resolveTarget.pRTV;
resolveParameters.msaaSource = srv;
resolveParameters.msaaDepth = (m_presetMode == PRESETMODE_0xTXAA) ? m_TXAASceneDepthResolved.pSRV : m_TXAASceneDepth.pSRV;
resolveParameters.feedbackSource = feedback.m_txaaFeedback.pSRV;
resolveParameters.alphaResolveMode = NV_TXAA_ALPHARESOLVEMODE_RESOLVESRCALPHA;
resolveParameters.feedback = &m_feedback;
m_txaaPerFrameConstants.xJitter = pJitter[0];
m_txaaPerFrameConstants.yJitter = pJitter[1];
m_txaaPerFrameConstants.mvScale = m_MVScale;
m_txaaPerFrameConstants.motionVecSelection = NV_TXAA_USEMV_NEAREST; // This can be configured differently.
m_txaaPerFrameConstants.useRGB = 0;
m_txaaPerFrameConstants.frameBlendFactor = GetBlendFactor(); // Manual override of the blend factor.
m_txaaPerFrameConstants.dbg1 = GetDbg1(); // Debugging. Do not modify the default values.
m_txaaPerFrameConstants.bbScale = GetBBScale(); // Scales the bounding box tightness. Default value 1.f
m_txaaPerFrameConstants.enableClipping = GetEnableClipping(); // Disable clipping for debugging.
// GL
NvTxaaContextGL *ctx; // TXAA context.
GLuint *dst; // Destination texture.
GLuint msaaSrc; // Source MSAA texture.
GLuint mv; // Source motion vector texture.
GLuint ctrl; // Per pixel control, can be null.
NvTxaaFeedbackParameters fb; // Feedback parameters
gfsdk_U32 frameCounter; // Increment every frame, notice the ping pong of dst.
NvTxaaResolveParametersGL resolveParameters;
memset(&resolveParameters, 0, sizeof(resolveParameters));
resolveParameters.txaaContext = ctx;
resolveParameters.resolveTarget = dst[(frameCounter + 1) & 1;
resolveParameters.msaaSource = msaaSrc;
resolveParameters.feedbackSource = dst[frameCounter & 1];
resolveParameters.controlSource = ctrl;
resolveParameters.alphaResolveMode = NV_TXAA_ALPHARESOLVEMODE_RESOLVESRCALPHA;
resolveParameters.feedback = &fb;
NvTxaaMotionDX11 motion;
memset(&motion, 0, sizeof(motion));
motion.motionVectors = mv;
GFSDK_TXAA_GL_ResolveFromMotionVectors(&resolveParameters, &motion);
Release Context
// DX11
#define __GFSDK_DX11__
#include <GFSDK_TXAA.h>
NvTxaaContextDX11 txaaCtx;
GFSDK_TXAA_DX11_ReleaseContext(&txaaCtx);
// GL
#define __GFSDK_GL__
#include <GFSDK_TXAA.h>
NvTxaaContextGL txaaCtx;
GFSDK_TXAA_GL_ReleaseContext(&txaaCtx);
Besides the TXAA core library, there is also an utility library which provides some stand-alone features that may be helpful in TXAA 3.0 integration.
Get the debug pass-through modes working, for instance NV_TXAA_DEBUGCHANNEL_MSAA.
Get the TXAA resolve working on the frames without the camera and the scene motion.
2a. Verify motion vector field sign is correct using NV_TXAA_DEBUGCHANNEL_MOTIONVECTORS. Output should be:
Light Blue-Purple -> no movement
Pink -> objects moving left
Blue -> objects moving up
If this is wrong, try the transpose of mvpCurrent and mvpPrior.
2b. Verify motion vector field scale is correct using NV_TXAA_DEBUGCHANNEL_TEMPORALDIFFS. Should see:
No Motion -> edges
Small Motion -> edges maintaining brightness and thickness
If seeing edges increase in size with a simple camera rotation, then motion vector input or mvpCurrent and/or mvpPrior is incorrect.
Also when clipping is disabled, one should see smearing at the locations where there is change in the occlusion. If one sees blurring or other image artifacts, motion vectors can be assumed to be incorrectly used.
2c. Once the motion field is verified, the TXAA resolve should work with motion.