最近在模拟2D像素阴影时,遇到了一个问题,对于任意形状的凸四边形,要如何计算其UV才能让最终的效果看起来正常?(想知道不正常的效果是什么样子?您也可以在下文中的连接中找到对应的图片。)
一番搜索之下,找到了如下链接:
https://www.reedbeta.com/blog/quadrilateral-interpolation-part-1/
这里作者提供了一个通用的公式用于计算UV值,但是作者并没有解释这个公式是如何得来的。本文将试着证明该公式。
首先,我们先看一下作者提供的公式:
注意,这里
同时,让我们看一下作者在这篇博客中提到的:
It’s well-known that to do perspective-correct interpolation for a triangle, you must calculate
, , and at each vertex, interpolate those linearly in screen space, then calculate and at each pixel. GPU rasterizers do this automatically, behind the scenes, for every interpolated attribute.
若您对这段话仍有疑问,建议参考此篇文章:
https://www.cnblogs.com/straywriter/articles/15889273.html
由此,我们可以推断出,这里的
那么,这个z究竟是个什么?
首先我们需要知道我们面临的问题是什么。
首先,我们有一个在图像平面(image plane)的四边形形状,而我们的目标就是找到一个平行四边形,使其投影到图像平面的形状恰好和我们要求的四边形重合。
(为什么是平行四边形?因为我们的Texture是矩形,从矩形到平行四边形是仿射变换,仿射变换不会影响我们对uv进行线性插值,具体请参考第一个链接的开头部分。为什么不是矩形?因为平行四边形已经足够我们实现我们的效果?同时使用矩形还需要额外证明一些不必要的东西,同时我们也无法保证真的存在这样的矩形(笔者并未尝试过证明该矩形是否一定存在)。)
而这个z,就是这个平行四边形的四个顶点距离摄像机的距离。
下面,我们就来证明为何这样的Z定义的平行四边形能够在图像平面恰好形成我们需要的四边形。
首先,这个平行四边形的四个点肯定都在从摄像机到图像平面四个点所确定的四条直线上。不然这个平行四边形在图像平面上的投影不会是我们所需要的四边形。
现在,我们设这个平行四边形的四个点为
现在我们取其中一条对角线
我们设A的坐标为
可以看出,点A的z坐标
同时,我们有:
这里的
这里需要证明一下
(什么是保持共线性?根据这篇文章的说法,保持共线性指的是变换后,原本在一条直线上的点仍然保持在同一条直线上。(Points on a line remain aligned post-transformation))
点Q的坐标可以表示为
因为点A’、点B’和点Q’都位于图像平面上,它们的
又因为
同理
所以我们有
同理,我们也可以得到
至此,我们得到了对角线两边的点的z值和它到对角线交点长度的关系。我们可以试一下,如果按照原博客的公式,
那么,
首先,我们有:
我们设
同理
又因为
所以
由此,我们得出了
可以注意到,这里我们给出的是比例关系,实际上这样的平行四边形是有无穷多个的,这也是符合我们的直觉的,只需要沿着z轴等比放大,我们生成的平行四边形总是可以在图像平面上投影成一样的形状。
笔者对于图形学来说也只是略懂皮毛,以上的证明可能包含错误或不准确的地方,如有问题请联系 wlzqkwd#Gmail.com。
最后,让我们以一张笔者目前正在尝试的像素光照的效果作为结尾吧: