[工作积累] UE4 TAA ReProjection的精度处理
先贴一个UE4 TAA的slide
https://de45xmedrsdbp.cloudfront.net/Resources/files/TemporalAA_small-59732822.pdf
里面细节问题很多,先记录一下目前想到和遇到的问题,便于备忘,后面有空的话再记录。
TAA用到的Velocity和抖动对精度要求比较高, 特别是大场景下误差容易比较大,UE4做了一系列的处理来保持精度。
投影矩阵的精度
static const FMatrix InvertProjectionMatrix( const FMatrix& M )
{
if( M.M[][] == 0.0f &&
M.M[][] == 0.0f &&
M.M[][] == 0.0f &&
M.M[][] == 0.0f &&
M.M[][] == 0.0f &&
M.M[][] == 0.0f &&
M.M[][] == 0.0f &&
M.M[][] == 0.0f &&
M.M[][] == 1.0f &&
M.M[][] == 0.0f )
{
// Solve the common case directly with very high precision.
/*
M =
| a | 0 | 0 | 0 |
| 0 | b | 0 | 0 |
| s | t | c | 1 |
| 0 | 0 | d | 0 |
*/ double a = M.M[][];
double b = M.M[][];
double c = M.M[][];
double d = M.M[][];
double s = M.M[][];
double t = M.M[][]; return FMatrix(
FPlane( 1.0 / a, 0.0f, 0.0f, 0.0f ),
FPlane( 0.0f, 1.0 / b, 0.0f, 0.0f ),
FPlane( 0.0f, 0.0f, 0.0f, 1.0 / d ),
FPlane( -s/a, -t/b, 1.0f, -c/d )
);
}
else
{
return M.Inverse();
}
}
可以看到对投影矩阵的取反做了特殊处理,来提高浮点计算精度。
视图矩阵的精度
FVector DeltaTranslation = InPrevViewMatrices.GetPreViewTranslation() - InViewMatrices.GetPreViewTranslation();
FMatrix InvViewProj = InViewMatrices.ComputeInvProjectionNoAAMatrix() * InViewMatrices.GetTranslatedViewMatrix().GetTransposed();
FMatrix PrevViewProj = FTranslationMatrix(DeltaTranslation) * InPrevViewMatrices.GetTranslatedViewMatrix() * InPrevViewMatrices.ComputeProjectionNoAAMatrix(); ViewUniformShaderParameters.ClipToPrevClip = InvViewProj * PrevViewProj;
将视图矩阵的位移和旋转拆开来(T*R),以避免大地图上,相机位置过大造成的误差。
Reprojection是把当前帧Clip space或NDC space的点重新投影到上一帧的位置
Reprojection = (V*P)-1 * (PrevV*PrevP)
= P-1 * V-1 * PrevV * PrevP
其中V为视图矩阵,P为投影矩阵。
而UE4的视图矩阵实际使用TR的方式 (类似变换矩阵的TRS和RTS的顺序,区别是试图矩阵没有缩放, https://docs.microsoft.com/en-us/dotnet/framework/winforms/advanced/why-transformation-order-is-significant
注意如果是相同的T和R, T*R和R*T结果是不一样的,这里的TR,是在ViewMatrix结果一样的前提上,拆解出的另外两个矩阵,从几何分析的角度也可以得出)
Reprojection = P-1 * (T*R)-1 * (PrevT*PrevR) * prevP
= P-1 * R-1 * T-1 * PrevT * PrevR * PrevP
= P-1 * R-1 * (T-1 * PrevT) * PrevR * PrevP
其中:
Reprojection是UE4代码里的ViewUniformShaderParameters.ClipToPrevClip,
R是ViewMatrix的旋转部分(UE4代码中的GetTranslatedViewMatrix),
T是ViewMatrix的位移部分,
T-1*PrevT 就是UE4代码中的 FTranslationMatrix(DeltaTranslation) 。
这样做的好处是,把两个绝对位置转换为一个相对位移, 从而避免绝对位置过大而导致的矩阵Inverse的精度问题。
同时,视图矩阵的旋转部分 R 是正交矩阵,所以Transpose等价于Inverse,这样不仅是效率的提高,更重要的是避免了Inverse导致的浮点误差。
VelocityBuffer的精度
// for velocity rendering, motionblur and temporal AA
// velocity needs to support -2..2 screen space range for x and y
// texture is 16bit 0..1 range per channel
float2 EncodeVelocityToTexture(float2 In)
{
// 0.499f is a value smaller than 0.5f to avoid using the full range to use the clear color (0,0) as special value
// 0.5f to allow for a range of -2..2 instead of -1..1 for really fast motions for temporal AA
return In * (0.499f * 0.5f) + 32767.0f / 65535.0f;
}
// see EncodeVelocityToTexture()
float2 DecodeVelocityFromTexture(float2 In)
{
const float InvDiv = 1.0f / (0.499f * 0.5f);
// reference
// return (In - 32767.0f / 65535.0f ) / (0.499f * 0.5f);
// MAD layout to help compiler
return In * InvDiv - 32767.0f / 65535.0f * InvDiv;
}
VelocityBuffer在TAA里用来reproject移动的物体,包括蒙皮动画和位移旋转动画等。
为了提高精度,VelocityBuffer可以使用Float32。Unity使用的是Float16x2 (R16G16F), 不同的是,UE4使用的是INT16x2 (R16G16_INT)。
对于Float16,最小精度是2-10。 如果映射到Int16,去掉等价的符号位,精度是2-15。 这样在占用同样显存大小的情况下,提高了精度。
[工作积累] UE4 TAA ReProjection的精度处理的更多相关文章
- [工作积累] UE4 并行渲染的同步 - Sync between FParallelCommandListSet & FRHICommandListImmediate calls
UE4 的渲染分为两个模式1.编辑器是同步绘制的 2.游戏里是FParallelCommandListSet并行派发的. mesh渲染也分两类,static mesh 使用TStaticMeshDra ...
- [工作积累] TAA Ghosting 的相关问题
因为TAA要使用上一帧的历史结果,那么在相机移动的时候,颜色就会有残留,出现ghosting(残影). 由于上一帧历史是累积的,是由上一帧的直接渲染结果和上上帧的结果做了合并,所以ghosting并不 ...
- [工作积累] Tricks with UE4 PerInstanceRandom
最近在用UE4的Instancing, 发现限制很多. Unity有instancing的attribute array (uniform/constant buffer),通过InstanceID来 ...
- [工作积累] D3D10+ 中 Pixel Shader 的input semantic和参数顺序
由于semantic的使用,我们有理由相信 vertex shader的output 和 pixel shader的input是按照semantic来匹配的,而跟传入顺序无关.印象dx9时代是这样. ...
- [工作积累] shadow map问题汇总
1.基本问题和相关 Common Techniques to Improve Shadow Depth Maps: https://msdn.microsoft.com/en-us/library/w ...
- [工作积累] Google/Amazon平台的各种坑
所谓坑, 就是文档中没有标明的特别需要处理的细节, 工作中会被无故的卡住各种令人恼火的问题. 包括系统级的bug和没有文档化的限制. 继Android的各种坑后, 现在做Amazon平台, 遇到的坑很 ...
- [工作积累] 32bit to 64bit: array index underflow
先贴一段C++标准(ISO/IEC 14882:2003): 5.2.1 Subscripting: 1 A postfix expression followed by an expression ...
- [工作积累] bitfield
ISO/IEC 14882:2003: 9.6 Bit-fields [class.bit] A member-declarator of the form identifieropt : const ...
- [工作积累] GCC 4.6 new[] operator内存对齐的BUG
对于用户没有定义dctor(包括其所有成员)的类来说, new CLASS[n] 可能会直接请求sizeof(CLASS)*n的空间. 而带有dctor的 类, 因为delete[]的时候要逐个调用析 ...
随机推荐
- 三元运算和bytes数据类型笔记
三元运算 result = 值1 if条件 else 值2 如果条件为真:result = 值1 如果条件为假:result = 值2 bytes数据类型 字符串可以编码成字节包,字节包也可以解码成 ...
- Android四大组件之 --- Service入门
在前面了解了什么是多线程和异步消息处理机制后,我们来看一下到底什么是Service. 1. 什么是service(service的作用)一个服务是一个具有较长生命周期但没有用户界面的程序,例如:一个正 ...
- Filebeat占用内存和CPU过高问题排查
经反馈,新部署的服务器上filebeat占用的cpu过高,且内存只增不减. 而据我了解filebeat非常轻量级,正常情况下占用的资源几乎都能忽略不计,所以怀疑是filebeat本身出了问题. 第一时 ...
- 没有与这些操作数匹配的 "<<" 运算符 操作数类型为: std::ostream << std::string
错误显示:没有与这些操作数匹配的 "<<" 运算符 操作数类型为: std::ostream << std::string 错误改正:要在头文 ...
- CSS中的颜色问题
css颜色: CSS 颜色 颜色是通过对红.绿和蓝光的组合来显示的 颜色值 CSS 颜色使用组合了红绿蓝颜色值 (RGB) 的十六进制 (hex) 表示法进行定义.对光源进行设置的最低值可以是 0(十 ...
- 网易云课堂----java视频教程
http://study.163.com/course/introduction.htm?courseId=1003203062#/courseDetail?tab=1
- 4--TestNG测试报告
第一:自带测试报告(略) 第二:Reportng测试报告(略) 第三:ExtentReport--extentreports.com (1) pom.xml:不是总的pom,是文件夹下的pom < ...
- 2018-软工机试-A-西班牙馅饼
A. 西班牙馅饼 单点时限: 1.0 sec 内存限制: 256 MB 港岛妹妹,你献给我的西班牙馅饼 甜蜜地融化了我,天空之城在哭泣 港岛妹妹,我们曾拥有的甜蜜的爱情 疯狂地撕裂了我,天空之城在哭泣 ...
- ios 传递JSON串过去 前面多了个等号
先说下我的问题 后台让我这边把请求的参数弄成一个实体转化成 json 串放body里传给他,当然header也有设置,提前设置好了, 但是后来了解 所谓的把实体转成json串的本质就是先把实体用run ...
- flex 布局 实现电商页面商品展示floor
有了上一篇,对flex的初次使用,心里痒痒的试着,实现了电商首页,商品展示的floor,先看下效果: 要实现首先是对组件构件的拆解,拆解如下: 页面布局如下: <div class=" ...