在网上阅读了几篇文章后,我可以自信地说我对使用光线追踪时的抗锯齿工作一无所知。

我所能理解的是,单个像素/光线被分为4个子像素,是4条射线,而不是1条射线。

请解释一下它是如何完成的(最好是用代码)?

评论

我可以建议您看看“ supersampling” en.wikipedia.org/wiki/Supersampling,也许还可以看看en.wikipedia.org/wiki/Distributed_ray_tracing吗?

我还建议您阅读PBRT的这一章pbrt.org/chapters/pbrt_chapter7.pdf并阅读本文lgdv.cs.fau.de/get/785(它解释了与pbrt中实现的技术不同的技术)。 >
每个像素:p {acc = 0; foreach子样本:s {acc + = sample_scene(s);} store(p,acc);}

#1 楼

我认为可以肯定地说,在光线跟踪中有两种不同的AA方式:

1:如果您拥有最终图像和深度图像,则可以应用几乎所有现有技术在游戏中(FXAA等),它们直接作用于最终图像,与光线追踪无关。

2:第二种方法是考虑每个像素的多条光线,然后取平均结果。对于一个非常简单的版本,可以这样考虑:


,您首先渲染尺寸为1024x1024的图像,每个像素(例如)一个光线
渲染后,您可以缩放将图片缩小为512x512(每个像素平均分为4个像素),您会注意到边缘更加平滑。这样,您就可以有效地为512x512大小的最终图像中的每个像素使用4条射线。

此方法还有其他变化。例如,您可以调整恰好位于几何图形边缘的像素的样本数量,这意味着对于某些像素,您将只有4个样本,而对于其他像素,则只有16个样本。

检查中的链接上面的评论。

评论


$ \ begingroup $
因此,基本上我将图像渲染为大尺寸,然后将其保存为图像时,将其缩小为较小的尺寸?这似乎很简单:)!这是超级采样方法吗?
$ \ endgroup $
– Arjan Singh
16-11-10在14:27



$ \ begingroup $
@Arjan Singh是的,它是en.wikipedia.org/wiki/Supersampling,但这是所有方法中最慢的一种,光线跟踪使您可以轻松地进行自适应超级采样,这可以使性能更好
$ \ endgroup $
– Raxvan
16年11月10日在14:54

#2 楼

Raxvan完全正确地说,“传统”抗锯齿技术将在光线跟踪中起作用,包括那些使用诸如深度之类的信息进行抗锯齿的技术。例如,您甚至可以在光线跟踪中进行时间抗锯齿。

就像朱利安所说,如果您想每个像素进行$ N $个采样像素,您可以将像素分解为均匀分布的$ N $采样点(基本上在网格上),并对这些采样值求平均。

如果这样做,仍然可以得到别名。最好不要执行此操作,因为您可以提高采样率,因此能够处理更高频率的数据(又称较小的细节),但仍可能导致混叠。

$ N $个像素内的随机样本,您实际上是在为噪点使用混叠。噪声比混叠更容易出现在眼睛上,看起来更自然,因此通常是首选结果。我相信这甚至是具有较高样本数量的理想情况,但没有更多有关此信息):

当您仅使用“常规”随机数时,例如从rand()或std :: uniform_int_distribution,称为“白噪声”,因为它包含所有频率,例如白光是由其他所有颜色(频率)的光组成的。

使用白噪声对样本进行随机化一个像素内的像素有时会聚集在一起。例如,如果您平均一个像素中有100个样本,但是它们最终都位于该像素的左上角,那么您将不会获得有关该像素其他部分的任何信息,因此最终得到的像素颜色将缺少有关其应使用的颜色的信息。

一种更好的方法是使用一种仅包含高频成分的蓝噪声(例如蓝光如何成为高频光)。

蓝噪声的好处是您可以获得均匀的覆盖范围在像素上,就像使用均匀的采样网格一样,但是仍然会出现一些随机性,从而将混叠化为噪点并为您提供更好看的图像。

不幸的是,蓝噪会非常昂贵进行计算,最好的方法似乎都已申请专利(到底是什么?!),但是,由pixar发明的一种方法(我认为也是获得专利的,但并非100%可以肯定)是制作均匀的样本点,然后将每个采样点随机偏移少量​​-就像采样网格宽度和高度的正负一半之间的随机量一样。这样,您便可以以相当便宜的价格获得某种蓝噪声采样。蓝噪声:
https://www.jasondavies.com/poisson-disc/

如果您对深入研究感兴趣,您可能还需要检查一下这个问题并回答! br />
在一个像素内使用多个随机样本进行抗锯齿的基本原因是什么?

最后,这些东西开始误入蒙特卡洛路径跟踪的领域,这就是进行逼真的光线追踪的常用方法。如果您有兴趣了解有关此内容的更多信息,请阅读这篇文章!

http://blog.demofox.org/2016/09/21/path-tracing-getting-started-with-diffuse -and-emissive /

评论


$ \ begingroup $
一看到你的名字,我就知道你会在蓝色的噪音中加入一些东西:)
$ \ endgroup $
–哈勃
20 Mar 25 '20在19:39

$ \ begingroup $
由于再次弹出该窗口:要解释为什么是这种情况-蓝噪声采样模式擅长将功能与大多数能量集中在低频进行积分。因此,通过使用蓝色噪声模式,您可以有效地假设信号大部分是平滑的/由低频主导。对于高频信号,这实际上可能适得其反。幸运的是,自然图像的能量集中在低频。有关更多详细信息,请参阅:sample.mpi-inf.mpg.de/2019-singh-fourier.html
$ \ endgroup $
–lightxbulb
20 Mar 26 '15:39



#3 楼

让我们假设一个相当典型的光线跟踪主循环:

 struct Ray
{
    vec3 origin;
    vec3 direction;
};

RGBColor* image = CreateImageBuffer(width, height);

for (int j=0; j < height; ++i)
{
    for (int i=0; i < width; ++i)
    {
        float x = 2.0 * (float)i / (float)max(width, height) - 1.0;
        float y = 2.0 * (float)j / (float)max(width, height) - 1.0;

        vec3 dir = normalize(vec3(x, y, -tanHalfFov));
        Ray r = { cameraPosition, dir };

        image[width * j + i] = ComputeColor(r);
    }
}
 


它可能要做的一种修改SSAA的4个样本为:

 float jitterMatrix[4 * 2] = {
    -1.0/4.0,  3.0/4.0,
     3.0/4.0,  1.0/3.0,
    -3.0/4.0, -1.0/4.0,
     1.0/4.0, -3.0/4.0,
};

for (int j=0; j < height; ++i)
{
    for (int i=0; i < width; ++i)
    {
        // Init the pixel to 100% black (no light).
        image[width * j + i] = RGBColor(0.0);

        // Accumulate light for N samples.
        for (int sample = 0; sample < 4; ++sample)
        {
            float x = 2.0 * (i + jitterMatrix[2*sample]) / (float)max(width, height) - 1.0;
            float y = 2.0 * (i + jitterMatrix[2*sample+1]) / (float)max(width, height) - 1.0;

            vec3 dir = normalize(vec3(x, y, -tanHalfFov) + jitter);
            Ray r = { cameraPosition, dir };

            image[width * j + i] += ComputeColor(r);
        }

        // Get the average.
        image[width * j + i] /= 4.0;
    }
}
 


另一种可能性是进行随机抖动(代替,但您很快就会进入信号处理领域,需要大量阅读才能知道如何选择良好的噪声函数。考虑像素代表一个很小的正方形区域,而不是只发射一条穿过像素中心的射线,而是发射许多覆盖整个像素区域的射线。射线分布越密集,得到的信号越好。

P.S .:我在上面即时编写了代码,所以我希望其中有一些错误。这只是为了展示基本思想。

评论


$ \ begingroup $
好答案!与@Raxvan使用的方法相比,使用此方法有什么好处?通过渲染成较大的尺寸然后缩小为较小的尺寸,是否可以获得相同的结果?
$ \ endgroup $
– Arjan Singh
16年11月10日在15:28

$ \ begingroup $
从根本上讲,使用光线跟踪,您无需渲染较大的图像,然后将其缩小。这意味着您具有更大的灵活性:您可以拥有很多样本,可以根据区域来改变样本数量,并且简单地,您不必添加重新缩放步骤。
$ \ endgroup $
–朱利安·盖尔特(Julien Guertault)
16年11月10日在15:36

$ \ begingroup $
关于抖动的问题,事实证明这是一个相当复杂的话题。这是一篇很棒的论文,分析了几年前的图形技术。pixar.com/ library / MultiJitteredSampling / paper.pdf
$ \ endgroup $
– Mikkel Gjoel
16年10月10日在15:44

$ \ begingroup $
上面的代码示例使用4样本MSAA,如果我想做8倍MSAA,矩阵将是什么样?我需要改变上面显示的抖动矩阵吗?
$ \ endgroup $
– Arjan Singh
16 Dec 3'在15:59

$ \ begingroup $
@SimonF感谢您指出它。固定。
$ \ endgroup $
–朱利安·盖尔特(Julien Guertault)
20-3-28在17:53

#4 楼

只需添加以上答案即可:

分布式射线跟踪(库克,波特和木匠)。使您可以同时进行空间AA,时间AA(即运动模糊)和景深/景深。最好阅读论文,但基本上每个像素发射的N射线也可以分配伪随机时间(用于运动模糊)和镜头上的位置(以获得聚焦效果)。

自适应超级采样:您最初会在每个像素上发射一定数量的射线。但是,如果本地附近的光线返回的结果明显不同,则可以在本地增加采样率(例如2倍)以改善结果。您可以选择重复此过程。
这并不完美,因为对象仍然可以“落在样本之间”,但是它可能比以更高的速率均匀采样更便宜。

带有锥体的射线追踪(变形):而不是使用无限细的射线,而是将每个射线都近似为一个圆锥体,例如,其直径可以覆盖所有像素(和少量邻域),从而可以评估部分覆盖率。它还对纹理采样/抗锯齿,柔和阴影以及潜在的模型LOD有好处。我很多年前做了一个实现-确实做起来比较困难,但是确实避免了很多额外的光线。
IIRC还提供了一种称为笔迹跟踪的方案(但是我最初的搜索没有找到与纸)