C++ 无法实现光子映射

C++ 无法实现光子映射,c++,raytracing,C++,Raytracing,我目前正在开发一个简单的光线跟踪器,到目前为止,我已经成功地实现了几个功能,如抗锯齿、景深和带区域光的软阴影。 代表我作品的图像可以是: (这里没有AA) 下一步是使用一些全局照明算法将真实感添加到渲染中,因此我决定使用光子贴图方法,这似乎是最简单的方法 为此,我阅读了一些在网上找到的论文,比如这篇: 写得很好 现在,我的程序可以在场景中拍摄光子,并在第一次反弹(漫反射或镜面反射)后存储它们,然后将每个光子的功率缩放为灯光功率/光子量。 这些图像显示了这一点的直接可视化,其中我拍摄了1000k

我目前正在开发一个简单的光线跟踪器,到目前为止,我已经成功地实现了几个功能,如抗锯齿、景深和带区域光的软阴影。 代表我作品的图像可以是:


(这里没有AA)

下一步是使用一些全局照明算法将真实感添加到渲染中,因此我决定使用光子贴图方法,这似乎是最简单的方法

为此,我阅读了一些在网上找到的论文,比如这篇:
写得很好

现在,我的程序可以在场景中拍摄光子,并在第一次反弹(漫反射或镜面反射)后存储它们,然后将每个光子的功率缩放为灯光功率/光子量。 这些图像显示了这一点的直接可视化,其中我拍摄了1000k和50k光子,每个光子允许反弹6次,在全球地图中总共有5000k和250k光子:

我认为效果是正确的,所以我转到下一部分,即使用光线跟踪光线交点上一定半径内的光子计算间接照明

在我的光线跟踪器中,我执行以下操作:

  • 对于每个像素,我通过它发送一条光线以与场景相交,并计算直接照明
    (点(N,L)*primitive.color*primitive.diffuseFactor*light.power)
    ,以及镜面反射项

  • 这里是一个棘手的部分:我寻找最近的光子,它们位于交叉点周围的固定半径圆盘中,并以这种方式将每个光子产生的光求和:

    对于半径内的每个光子 使用与直接照明相同的方法计算灯光 (点(-photonDir,N)*primitive.color*photonColor) 总结一下

  • 当每一个感兴趣的光子都经过处理并添加到最终颜色中时,我将其除以定义搜索区域的光盘区域

  • 问题是这样做我没有得到想要的结果,特别是天花板与我在网上找到的图像相比非常暗(如果天花板有直接照明的额外贡献,我不知道天花板怎么会像地板一样亮,如果上面的光子只有红或绿,它怎么会是白色的)

    表示问题的图像如下所示:

    这是使用150k光子渲染的,每个光子有4次反弹,直接照明被PI分割


    另外,如果你知道我如何从角落里移除那些丑陋的文物,请告诉我。

    首先,非常感谢你的帮助

    第二,我在这里宣布,经过一些麻烦,经过一段时间我没有接触代码,我终于得到了它

    我还不明白我做错了什么,也许是得到半球内随机方向的算法,也许是光子聚集过程。。。 关键是,在重新格式化了一点代码之后(在执行了最后的聚集步骤和2.2伽马校正之后),我能够用200k光子、10个漫反射反弹、20个直接照明样本和100个FG样本(以随机余弦加权方向采集)渲染以下内容

    我对此非常满意,因为它看起来几乎和用V射线追踪的c4d路径中场景的再现一样


    我还不清楚存储光子入射方向的实用程序是什么,哈哈哈,但它是有效的,所以没问题


    再次感谢。

    我觉得它很不错。好的,doneThanks,但是正如你所看到的,天花板,这是我的主要问题,是非常非常暗的,如果我增加间接照明,唯一会发生的事情是颜色流失会变得更加明显,这不是我想要的。预计天花板是暗的:它没有直接照明。如果你在网上看到天花板不暗的图像,那是因为添加了一些环境光(即,如果没有任何光源,你甚至会看到天花板)。颜色流血也不是不现实的,只是我们人类太习惯于忽视颜色光,以至于我们通常没有意识到。这就是为什么您经常看到光子灯光变灰,以使渲染图像与预期而非现实相匹配。唯一真实的人工制品是角落处的明亮线条。好吧,天花板肯定要比这更亮,就像在真正的康奈尔盒子网站上:或者在其他来自网络的图像中:或者来自路径跟踪渲染:你真的必须缩小它的范围。这个问题虽然在某些地方很有趣也很有效,但对于编程问答库来说太广泛了。“存储光子入射方向的实用程序是什么”它用于任何比纯漫反射更复杂的BRDF。因为你似乎在使用一个纯朗伯模型,你不需要它。哦,那么当光子反弹时,brdf也应该被计算?(确定其强度)是的,您应该在每次反弹时对BRDF进行采样,并在“聚集”步骤中应用。这对于朗伯曲面来说很简单。嗯,我对此有点困惑。如何找到每个brdf模型的重要性抽样算法?这是一个值得几篇学术论文讨论的问题。以下是其中之一: