Unity TAA Jittering公式推导

        关于Jittering的公式,很多地方只是大概提了一下公式,这是Unity中的实现,使用的公式是:

matrix[0, 2] += offset.x * 2 / horizontal;
matrix[1, 2] += offset.y * 2 / vertical;

        具体参考代码(话说这函数定义horizontal,vertical意义不明,可能是为了提高计算精度?)

public static Matrix4x4 GetJitteredPerspectiveProjectionMatrix(Camera camera, Vector2 offset)
{
    float near = camera.nearClipPlane;
    float far = camera.farClipPlane;

    float vertical = Mathf.Tan(0.5f * Mathf.Deg2Rad * camera.fieldOfView) * near;
    float horizontal = vertical * camera.aspect;

    offset.x *= horizontal / (0.5f * camera.pixelWidth);
    offset.y *= vertical / (0.5f * camera.pixelHeight);

    var matrix = camera.projectionMatrix;

    matrix[0, 2] += offset.x / horizontal;
    matrix[1, 2] += offset.y / vertical;

    return matrix;
}

        现在来分析一下原理:

        先不管Jitter的数值是多少,我们把Jitter带入到投影矩阵中

\begin{pmatrix} \frac{n}{r} & 0 & Jitter_{x} & 0\\ 0 & \frac{n}{t} & Jitter_{y} & 0\\ 0 & 0 & -\frac{f+n}{f-n} & -\frac{2fn}{f-n}\\ 0 & 0 & -1 & 0\\ \end{pmatrix}

        然后计算clip space坐标的差值  

        {P_{clip}}' = {}{M_{proj}}'* P_{view} = P_{clip}+ \begin{pmatrix} Jitter_{x} * Z_{view}\\ Jitter_{y} * Z_{view}\\ 0\\ 0 \end{pmatrix}

        因为坐标值只涉及到xy的修改,所以后面都只看xy,下一步是到NDC空间

        {P_{ndc}}' = {\frac{P_{clip}}{w}}'= \frac{​{P_{clip}'}}{-Z_{view}} = P_{ndc} + \frac{Jitter_{xy} * Z_{view}}{-Z_{view}} = P_{ndc} - Jitter_{xy}

        以及屏幕空间

{P_{screen}}' = \frac{​{P_{ndc}}' + 1}{2} = P_{screen} - \frac{Jitter_{xy}}{2}

        现在把最初的Jitter数值带入进去

Jitter_{xy} = \frac{2*Offset_{xy}}{Resolution}

        得到最终的差异:

 {P_{screen}}' = P_{screen} - \frac{Offset_{xy}}{Resolution}

        其中Offset的xy介于[-0.5, 0.5]之间,到这一步作用已经很明显了,1除以屏幕分辨率得到的是每个像素的长宽,乘以Offset代表偏移的长度,表示往像素在水平和垂直分别偏移最多0.5个像素。

        在很多实现当中,比如https://zhuanlan.zhihu.com/p/138866533,会使用这样的公式

var jitteredProjection = camera.projectionMatrix;
jitteredProjection.m02 += (offset.x * 2 - 1) / camera.pixelWidth;
jitteredProjection.m12 += (offset.x * 2 - 1) / camera.pixelHeight;

        区别只是这里的分母多减了1,结果变成了

{P_{screen}}' = P_{screen} + \frac{0.5 - Offset_{xy}}{Resolution}

        实际上没有区别,只是这里Offset值域不一样,这里的是[0, 1]

猜你喜欢

转载自blog.csdn.net/paserity/article/details/129638442