牛顿入门协议:可以容纳4 KB

图片

我最近在PC 4k简介类别中参加了Revision 2019演示场景,我的简介赢得了第一名。 我进行编码和图形处理,然后由狄克森作曲。 竞赛的基本规则是创建一个大小仅为4096字节的可执行文件或网站。 这意味着必须使用数学和算法来生成所有内容。 我无法将图像,视频和音频压缩到如此少量的内存中。 在本文中,我将讨论Newton简介影片的渲染流程。 在下面,您可以查看完成的结果,或单击此处查看在Revision上的实时效果,或转到pouet进行评论并下载参加比赛的简介。 您可以在此处阅读有关竞争对手的工作和更正的信息


光线行进距离场技术在4k入门学科中非常流行,因为它允许您仅用几行代码指定复杂的形式。 但是,这种方法的缺点是执行速度快。 要渲染场景,您需要找到光线与场景的交点,首先确定所看到的东西,例如,来自相机的光线,然后确定从对象到光源的后续光线,以计算照明。 使用光线行进时,无法一步找到这些交点,您需要沿着光束采取许多小步骤,并评估每个点上的所有对象。 另一方面,使用射线追踪时,可以通过仅检查每个对象一次来找到确切的相交,但是可以使用的形状集非常有限:每种类型都需要有一个公式才能计算与射线的相交。

在本简介中,我想模拟非常精确的照明。 由于必须反射场景中的数百万条光线,因此光线追踪似乎是实现此效果的合理选择。 我将自己限制在一个单一的图形-球体上,因为光线和球体的交点非常简单。 甚至介绍中的墙实际上都是很大的球体。 此外,它简化了物理模拟。 仅考虑领域之间的冲突就足够了。

为了说明适合4096字节的代码量,下面提供了完整的介绍的完整源代码。 除HTML末尾以外的所有部分均编码为PNG图像,以将其压缩为较小的尺寸。 如果不进行这种压缩,则该代码将占用几乎8900个字节。 名为Synth的部分是SoundBox的精简版本。 为了以这种最小化格式打包代码,我使用了Google Closure CompilerShader Minifier 。 最后,几乎所有内容都使用JsExe压缩为PNG。 在我之前的4k简介Core Critical的源代码中可以看到完整的编译管道,因为它完全与此处介绍的匹配。


音乐和合成器完全用Javascript实现。 WebGL上的这一部分分为两部分(代码中以绿色突出显示);另一部分则为WebGL。 她设置了渲染管道。 物理和光线跟踪器元素是GLSL着色器。 其余代码被编码为PNG图像,HTML不变地添加到结果图像的末尾。 浏览器将忽略图像数据,仅执行HTML代码,然后将PNG解码回javascript并执行。

渲染管线


下图显示了渲染管道。 它由两部分组成。 管道的第一部分是物理模拟器。 简介场景包含50个球体,它们在房间内相互碰撞。 房间本身由六个球体组成,其中一些比其他球体小一些,以创建更多弯曲的墙。 拐角处的两个垂直照明光源也是球体,即场景中共有58个球体。 流水线的第二部分是光线跟踪器,用于渲染场景。 下图显示了在时间t处一帧的渲染。 物理模拟采用前一帧(t-1)并模拟当前状态。 光线跟踪器获取当前位置和前一帧的位置(对于速度通道),并渲染场景。 然后,后处理将先前的5帧和当前的帧进行组合以减少失真和噪点,然后创建最终结果。


在时间t渲染一帧。

物理部分非常简单,在Internet上可以找到许多有关创建球体原始模拟的教程。 位置,半径,速度和质量存储在分辨率为1 x 58的两个纹理中。我使用了Webgl 2功能,该功能允许渲染到多个渲染目标,因此可以同时记录两个纹理的数据。 光线跟踪器使用相同的功能来创建三个纹理。 Webgl不提供对NVidia RTX或DirectX光线跟踪(DXR)光线跟踪API的任何访问权限,因此一切都从头开始。

光线追踪器


光线跟踪本身是一种相当原始的技术。 我们将光线释放到场景中,被反射4次,如果光线进入光源,则反射的颜色会累积。 否则,我们会变黑。 在4096字节(包括音乐,合成器,物理和渲染)中,没有空间创建复杂的加速射线跟踪结构。 因此,我们使用粗略搜索方法,即,针对每条射线检查所有57个球体(不包括前壁),而没有进行任何优化以排除部分球体。 这意味着要以每秒1080p的分辨率提供60帧,您只能发射2-6射线或每个像素样本。 这足够接近以创建平滑的照明。


每个像素1个样本。


每个像素6个样本。

如何应对呢? 最初,我研究了光线跟踪算法,但是已经简化到了这一点。 通过消除射线在球体内部开始的情况,我设法稍微提高了性能,因为这种情况仅在存在透明效果的情况下适用,并且场景中仅存在不透明的对象。 之后,我将每个if条件组合到一个单独的语句中,以避免不必要的分支:尽管进行了“冗余”计算,但这种方法仍然比一堆条件语句要快。 您还可以改善采样模式:我们可以随机地将光线分布在整个场景中,而不是随机发出光线。 不幸的是,这无济于事,并且在我尝试的每种算法中都产生了波浪状的假象。 但是,这种方法为静止图像创造了良好的效果。 结果,我返回使用完全随机分布。

相邻像素应该具有非常相似的照明,那么为什么在计算单个像素的照明时不使用它们呢? 我们不想仅使照明模糊,而是需要在单独的通道中渲染它们。 我们也不想模糊对象,因此我们需要考虑对象的标识符,以便知道哪些像素可以轻松地模糊。 因为我们有反光物体,并且需要清晰的反射,所以仅找出光束与之碰撞的第一个物体的ID是不够的。 对于纯反射材料,我使用了一种特殊情况,即在对象标识符通道的反射中也包含第一和第二个对象的ID。 在这种情况下,模糊可以使反射中物体的照明变得平滑,同时保持物体的边界。


纹理通道,我们不需要对其进行模糊处理。


红色通道中包含第一个对象的ID,绿色(第二个)和蓝色(第三个)。 实际上,它们全部被编码为浮点格式的单个值,其中整数部分存储对象的标识符,而小数部分表示粗糙度:332211.RR。

由于场景中的物体具有不同的粗糙度(某些区域是粗糙的,光线会散射在其他区域,在第三区域中会产生镜面反射),因此我存储该粗糙度以控制模糊半径。 场景中没有很小的细节,因此我使用了一个较大的50 x 50核心,其权重采用反平方的形式来模糊。 它没有考虑世界空间(可以实现以获得更精确的结果),因为在某些方向上以一定角度倾斜的表面会侵蚀较大的区域。 这种模糊会产生相当平滑的图像,但是伪影清晰可见,尤其是在运动中。


照明通道具有模糊和明显的伪影。 在此图像中,可以看到后壁上的模糊点,这是由带有第二个反射物体的标识符的小错误(光线离开场景)引起的。 在完成的图像上,这不是很明显,因为从纹理通道获得了清晰的反射。 光源也变得模糊,但是我喜欢这种效果,所以我离开了。 如果需要,可以通过根据材料更改对象的标识符来防止这种情况。

当物体在场景中并且拍摄场景的相机移动缓慢时,每帧中的照明应保持恒定。 因此,我们不仅可以在屏幕的XY坐标上执行模糊;还可以在屏幕上执行模糊。 我们可以及时模糊。 如果我们假设光照在100毫秒内变化不大,则可以将其平均6帧。 但是在此时间范围内,物体和相机之间仍会相隔一段距离,因此简单计算6帧的平均值将创建非常模糊的图像。 但是,我们知道所有对象和摄影机在上一张地图中的位置,因此我们可以计算屏幕空间中的速度矢量。 这称为临时重投影。 如果我在时间t处有一个像素,那么我可以以该像素的速度计算在时间t-1处的像素,然后计算在时间t-1处的像素在时间t-2处,依此类推。后5帧。 与屏幕空间模糊不同,我对每一帧使用相同的权重,即 只是对所有帧之间的颜色进行平均以得到临时的“模糊”。


像素速度通道根据对象和摄像机的运动报告像素在最后一帧中的位置。


为了避免对象的联合模糊,我们将再次使用对象标识符的通道。 在这种情况下,我们仅考虑光束碰撞的第一个对象。 这提供了对象内的抗锯齿,即 在思考。

当然,在前一帧中可能看不到该像素。 它可能被其他物体隐藏或不在相机的视野范围内。 在这种情况下,我们无法使用以前的信息。 此检查是针对每个帧分别执行的,因此我们每个像素获得1到6个样本或帧,并使用可能的样本或帧。 下图显示了对于慢速物体这不是一个非常严重的问题。


当对象移动并打开场景的新部分时,我们没有6帧信息可以对这些部分取平均。 此图像显示具有6帧的区域(白色),以及缺少6帧的区域(逐渐变暗的阴影)。 轮廓的出现是由于每一帧中像素的采样位置的随机化以及我们从第一个样本中获取对象的标识符这一事实造成的。


模糊照明平均超过六帧。 伪影几乎是不可见的,并且随着时间的推移,结果是稳定的,因为在每帧中,只有六帧中考虑照明的变化中的一帧。

结合所有这些,我们得到一个完整的图像。 照明模糊到相邻像素,而纹理和反射保持清晰。 然后,将所有这些数据平均在六个帧之间,以随时间推移创建更平滑,更稳定的图像。


完成的图像。

阻尼伪影仍然很明显,因为我平均每个像素有几个样本,尽管我选择了第一个交叉点的对象标识和速度通道。 您可以尝试解决此问题,并通过丢弃样本(如果样本与第一个样本不重合)或至少在第一次碰撞的顺序不重合上获得平滑化。 在实践中,痕迹几乎是看不见的,因此我没有费心去消除它们。 对象的边界也会失真,因为无法平滑速度和对象标识符的通道。 我曾考虑过以2160p渲染整个图像的可能性,并进一步缩小到1080p,但是我的NVidia GTX 980ti无法以60fps的分辨率处理这样的分辨率,因此我决定放弃这个想法。

总的来说,我对介绍的结果感到非常满意。 我设法将所有想法牢记在心,尽管有一些小错误,但最终结果还是很高的质量。 将来,您可以尝试修复错误并改进抗锯齿功能。 还值得尝试使用诸如透明度,运动模糊,各种形状和对象变换之类的功能。

Source: https://habr.com/ru/post/zh-CN450612/


All Articles