游戏引擎学习第96天

讨论了优化和速度问题,以便简化调试过程

节目以一个有趣的类比开始,提到就像某些高端餐厅那样,菜单上充满了听起来陌生或不太清楚的描述,需要依靠服务员进一步解释。虽然这听起来有些奇怪,但实际上,它反映了本期的开发过程:没有现成的工具,而是全程手动开发。开发者虽然没有顶楼花园,但他们自己编写的代码和图形纹理就像这些高端餐厅里的自家种植的食材一样,确保质量。

当前阶段,开发者已经编写了自己的纹理映射和渲染器,并且做了许多优化。然而,尽管优化带来了性能提升,但调试时,开启优化后的构建会让代码执行变得过于跳跃,难以通过单步调试来演示。为了解决这一问题,开发者正在考虑是否应该调整优化策略。虽然一部分开发者认为此时不应进行过早的优化,因为可能会在后续开发中发现其他需要改进的地方,另一部分开发者则认为进行优化后即使需要重新优化也无妨,毕竟可以在这个过程中向观众展示优化的步骤和技巧。

总的来说,虽然目前的开发过程存在一些优化和调试的挑战,但通过这种完全自定义的方式,可以让开发者充分控制整个游戏引擎的构建过程,并在此过程中与观众分享经验和技巧。

提出了两种可能的方向:渲染器特性...

在接下来的开发过程中,存在两个主要的方向。第一个方向是为当前的渲染器增加一些新的功能,并思考如何在不优化代码的情况下实现这些功能,以便能够逐步调试并演示。当前的渲染器还缺少两个主要的功能,其中一个是确保像素填充的定义更加严格,以及纹理如何应用到这些像素上的规则。

在最初实现时,代码的设计是为了尽快让功能能够运行,而不是过于纠结于每个细节。这种做法在初期阶段是合理的,因为目的是确保基础功能能快速实现。然而,在开发进一步功能之前,最好先明确像素填充的规则,并对纹理的获取方式进行严格的定义。这包括如何选择纹理、如何应用纹理到像素,以及具体的操作规则。这样可以确保在后续开发时,基础的渲染逻辑是健全的,避免后期修改时出现问题。

...或者是光照控制

目前,已经实现了色调控制、透明度控制、缩放和旋转等功能,这些功能大致上满足了游戏的需求。然而,仍然缺少一个重要的功能------光照控制。具体来说,如果想要根据方向光源或区域光源来改变精灵的像素,目前的渲染系统无法有效地处理这一需求。因此,在优化纹理填充的过程中,考虑增加光照控制功能显得尤为重要。

在现有的基础上,虽然已经实现了平滑旋转和其他基本效果,但要让游戏更加生动和富有动感,增加一些动态光照效果将是一个重要的步骤。这样可以让游戏中的物体在光照下有更多的变化和表现,使其更加细腻和真实。因此,考虑如何在当前系统中加入光照效果,能够提升渲染的质量,为游戏增添更多的视觉效果。

建议关闭除树木之外的所有内容

为了避免性能问题,可以考虑暂时关闭游戏中的其他功能,只渲染一两个主要的元素,比如一个树。这样做可以避免复杂的渲染计算,从而减少性能压力,因为如果只渲染非常小的一部分,性能问题就不大。接着,应该专注于实现光照功能,并确保亚像素计算准确无误,直到这些功能完善且稳定为止。

在确保这些基础功能正确运行之后,再开始对渲染进行优化,这样的步骤相对安全。通过这种方式,可以逐步完成渲染系统的功能,并确保每个部分的稳定性和效果。

审查game_render_group中的内容

在代码中,渲染系统通过分组的方式构建出要渲染的内容,并在执行时逐个渲染。当前的测试项目涉及到旋转和缩放,使用了一个坐标系统来进行测试,允许指定坐标并对矩形进行变换。这个过程进行得很顺利。

然而,问题在于目前的复杂代码都在同一条路径下运行,而其他未进行旋转和缩放处理的代码路径较为简单且速度较慢。后者并没有进行复杂的变换操作,因此执行效率较低。这意味着,虽然现在的代码路径实现了基本的功能,但它们并没有像当前的测试项目那样进行额外的变换处理。

关闭DrawBitmap,修改难看的粉色背景并切换到调试模式编译

如果完全去除DrawBitmap的代码,那么运行程序时,只会看到树和一个令人不悦的粉色背景。如果保留矩形轮廓,仍会看到这些元素。背景色可以调整为灰色或其他颜色,这样就能更灵活地调整显示效果。

如果关闭编译器优化请求,就能得到较慢的版本运行,这对当前的开发来说并不构成问题。因此,认为这样的方法是可行的,可以继续在这个状态下工作几天,添加新特性,等到功能完善后再转向优化。除非有特别的顾虑,否则这种方式似乎是合理的。

停止树木旋转

首先,暂时不再需要旋转功能,所以决定停用旋转功能。现在,树木就直接处于直立位置。停止透明度变化

接下来,想要引入光照的概念。虽然会详细讨论一些内容,但首先需要开始思考要在光照方面实现哪些功能。

黑板:'光照是图形的声音'------Doug Church

讨论了光照的重要性。有一位名叫Doug Church的人曾提到,"光照是图形的声音",这句话虽然在当时可能显得有些奇怪,但现在看起来已成为经典名言。Doug Church当时的意思是,如果没有光照,游戏中的图像会显得非常平坦,就像是颜色的简单排列,缺乏深度和空间感。而引入阴影图等光照效果后,能够大大改变游戏的表现,因为光线如何与空间互动,能让空间看起来更生动、真实,且具有深度。

他通过将光照与声音进行类比,指出如果没有声音,游戏的体验会变得差很多,尽管玩家可能没有意识到这一点。优秀的音效能提升游戏的表现,同样,良好的光照效果能让图像更有生气和层次感。尤其在3D游戏中,光照的作用更加突出,因为它能够为艺术资源带来更大的表现力,使得环境看起来更为真实和有维度。

黑板:动态光照

尽管在2D游戏中,光照效果不像在3D游戏中那么重要,但动态光照仍然能够为游戏增色,带来很多视觉上的强调效果。例如,在一个有许多树木的场景中,如果树木周围有篝火,光照会随着火焰的闪烁在树木上投射,这种效果能大大提升场景的氛围。同样,如果游戏中有一个愤怒的巫师,他施放火球时,火球的光亮照射到周围的树木上,也能让光线在树木间来回变化,从而加强火球的运动感,并让所有元素看起来处于同一个空间中。

此外,光的缺失也能用来讲述故事。比如,当某个庞大的物体的影子笼罩在空间中时,这种暗影变化同样能够传达氛围和情感。这些例子都说明,即便是在2D游戏中,动态光照的控制也是有意义的,它能够提升游戏的表现力和代入感。

黑板:光照本质上是'方向性的'效果

光照本质上是一个方向性的效果,意味着光线沿着直线路径传播,这与现实世界中的光传播方式相符。光线从光源出发,经过反射和折射,最终到达观察者的眼睛。眼睛通过收集这些光子来构建图像。因此,照明效果的关键在于光线的传播方向,这使得实现正确的照明非常复杂。

要进行真实的光照计算,需要处理很多复杂的因素。光线从光源发出,经过多个表面的反射和折射,最终进入眼睛,而这些过程涉及大量的计算。如果要完全准确地模拟光线的行为,照明的实现会变得异常复杂,因为每个表面反射的光线方向和强度都会影响最终图像的呈现。

黑板:波长

在这个简单的照明模型中,光线从太阳发出,照射到一个表面上,然后反射到眼睛,最终在视网膜上形成图像。即使是这种简化的情况,计算照明仍然非常复杂。大多数表面在光照射时会将光线散射到多个方向,因此难以准确计算。

光线的波长决定了我们所看到的颜色。光波是振荡的,就像正弦波一样,光的振荡速度和波长会随着光源的不同而变化。波长的变化决定了我们看到的颜色范围,包括不可见的红外线、紫外线等。虽然我们无法直接看到这些不可见的光线,但它们可以通过与其他物质的相互作用转变为可见光。

光的颜色并不是由红、绿、蓝三种颜色组成的。实际上,光是连续的,可以表示任何颜色,而RGB模式只是为了适应显示技术的需求。每种颜色都有其独特的波长,并且可以通过这些波长来表示不同的颜色。

黑板:RGB颜色感应器

RGB被广泛使用的原因是因为人眼的感光细胞只对红、绿、蓝三个波段的光敏感。在视网膜中,有三种感光细胞分别对红光、绿光和蓝光敏感。每种感光细胞并不是只对某一特定波长的光做出反应,而是对接近其感应波长的光产生较强的反应,离其波长越远的光产生的反应则越弱。大脑通过分析这些感光细胞的活动,来推断光的波长,从而识别不同的颜色。

当不同波长的光照射到视网膜时,感光细胞会根据光的波长产生不同的反应。例如,蓝色和绿色的光会同时刺激蓝色和绿色的感光细胞,而大脑将其识别为一种混合色。当有多种波长的光同时进入眼睛时,感光细胞的反应会结合起来,例如白光就包含了不同波长的光,刺激了红、绿、蓝三种感光细胞。

RGB的颜色表示方法非常有效,因为它能够模拟人眼的感光机制。通过控制红、绿、蓝光的输出,可以让眼睛误以为看到了其他颜色,比如通过同时发出红光和绿光,可以让眼睛感知到黄色,尽管实际发出的并不是黄色光。这种方法是通过刺激不同的感光细胞,使其混合反应,从而产生我们所见的颜色。

有些动物拥有比人类更多种类的感光细胞,因此它们对光的感知方式不同。如果这些动物看我们的显示器,它们可能会觉得显示器上的颜色与现实世界大不相同。

黑板:不要和拥有更多颜色波长传感器的动物交谈

一个重要的教训是,不要和那些拥有更多色觉感光细胞或更广泛光波长感应器的动物交谈。与这些动物交谈可能会带来不必要的麻烦,因此不值得去尝试。至于接下来的内容,尽管这一点是最重要的,但仍然要继续前进,尽量在剩下的时间内深入探讨实际的照明问题。

黑板:我们看到的是所有光源将光散射到我们眼睛中的聚合效果

光的波长从光源入射,碰到表面后会在各个方向上散射,其中一些会朝着眼睛的方向散射。问题在于,这种散射对于任何入射方向都是适用的。如果有第二个光源,比如如果有第二个光源,它也会像第一个光源一样,向表面散射光线。它也会向眼睛散射光。人眼看到的并不是单一光源的光,而是所有光源的光聚合效应。

即使只有一个太阳,周围的物体也会反射光线,许多反射的光会再次回到观察点并散射到眼睛。因此,要计算世界上某一点的正确照明,实际上需要计算从该点发出所有方向的入射光,这是一个极其困难的问题。这也是为什么准确的光照在计算机图形学中是最难实现的任务之一。

黑板:次表面散射

光线不仅仅是反射在表面上,它实际上会穿透表面并进入到物体内部,然后再反弹出来。当光线接触到一个真实的表面时,表面通常是有厚度的,可能像蜡一样复杂。当光子到达表面时,它们会穿透表面,可能在内部发生反射,最终光线会从物体内部出来并散射到眼睛。这种现象被称为"次表面散射"(Subsurface Scattering)。

如果要准确计算光照,不仅需要知道所有可能从外部射向眼睛的光线,还需要了解所有可能从物体内部射向眼睛的光线。虽然很多物体是如此不透明,以至于不需要考虑物体内部的光线,但如果想要准确处理如蜡、水或其他透明或半透明物质的光照,就必须考虑到这些次表面散射的效果。

黑板:是什么让表面看起来不同?

物体表面看起来不同的原因在于它们如何处理光子。不同表面对光线的反射方式有所不同,关键在于光的入射角度(光源发出的光与表面之间的角度)和观察角度(观察者眼睛与表面之间的角度)。每个表面对于不同的光入射角度和观察角度,反射的光的比例也会有所不同,这控制了表面在视觉上的表现。

为了准确描述这一过程,必须使用一个二维函数,来表示每个入射角度和观察角度的光反射百分比。所有光线的反射量加起来通常为100%,但因为表面也会吸收一些光,因此实际反射光的比例会少于100%。这个函数决定了表面的外观,而不同表面可能在处理不同波长的光时有不同的效果,这也是需要考虑的细节。

在实际计算中,由于光线的行为非常复杂,精确的渲染通常会采用更简化的模型。在实时渲染中,不会尝试进行如此复杂的计算,而是使用一些近似方法来在性能上做出妥协。为了处理光线的传播和反射,实际应用中可能会简化为使用RGB等颜色空间来近似光的传播行为,尽管这并不是最精确的方式。

黑板:我们实际上想要的是什么样的表面?

在考虑表面的类型时,通常关注三种表面:漫反射表面、光泽表面和反射表面。

  1. 漫反射表面:这种表面类似于粉笔,它不具有明显的高光。光线射入后,会在所有方向上均匀散射,不会偏向某个特定方向。其特性是光的散射是分布均匀的。

  2. 反射表面:这种表面类似于镜子,当光线照射到它上面时,光线会直接反射回来,几乎没有光线进入或散射到其他方向。反射表面是典型的镜面反射,眼睛看到的图像非常清晰,几乎就像没有表面一样。

  3. 光泽表面:这种表面介于漫反射和反射之间。当光线照射到表面时,大部分光线会反射回去,但仍然有一部分会散射到其他方向。这种表面通常具有一个明显的反射中心(光泽),而四周的反射则较弱,形成一个反射的"光环"。

这些表面是艺术创作中常用的,因为它们能够通过合适的近似效果在游戏中呈现出更真实的视觉效果。

黑板:近似方法

在早期,由于计算机处理能力有限,光照效果通常使用非常简单的近似方法。这些方法没有考虑复杂的光传播过程,而是通过简单的计算来模拟光的反射。最常见的做法是仅考虑一个点光源,光线从光源射向表面,然后反射回来。此时,光照效果主要通过控制反射角度和光线强度来实现,通常会有一个衰减系数来决定光斑的尖锐度。

这种方法看起来就像是有人用手电筒照射物体,表面上只有一个光源,反射光线通常较为尖锐,阴影也很硬。这种简单的模型通过调整反射角度和亮度衰减来呈现表面的光泽感或阴影变化,但它也会带来一些问题,比如表面没有来自其他方向的光照,阴影部分会显得非常黑暗,除非添加一些假的光源来弥补。

然而,对于早期的二维艺术作品来说,这种近似的光照方法是可以接受的。由于艺术已经绘制了很多光照效果,光照系统不需要精确重建整个场景的光照,而是通过覆盖一些高光区域,并让艺术本身的环境光处理其他细节,这样就能够达到较为合适的效果。因此,这种简单的光照方法在当时是可行的。

黑板:'光探针'或间接光采样

随着计算能力的提升,现代光照的近似方法不再仅仅依赖于单一的点光源,而是引入了"光探针"(light probes)技术来解决传统方法的局限性。传统的方法将光源视为单个点,这样无法准确模拟真实世界的光照,因为光线来自各个方向,而不仅仅是某个点或少数几个点。

为了更真实地模拟光照效果,现代方法通过使用间接光采样来捕捉多个方向的光照信息。例如,一种常见的做法是使用六个面向不同方向的立方体贴图来捕捉周围环境的光照信息。这种方法的本质是将周围的光照压缩成一个查找表,方便快速访问和计算。

接下来,通过对这些立方体贴图进行降采样(例如将256x256x256的分辨率降至128x128x128,甚至更低),可以得到不同清晰度的光照图像。较低分辨率的贴图通常表示环境中的平均光照,而高分辨率的贴图则更加精细,适用于反射较强的表面。

通过这种方式,可以模拟不同类型的表面反射。例如,对于一个光滑的表面,可以使用高分辨率的光探针来计算反射光,而对于一个粗糙的表面,则使用低分辨率的光探针来模拟较为平均的光照。这种方法使得在三维环境中能够较为精准地模拟各种光照效果,尤其是在实时渲染中,能够在不进行复杂计算的情况下,实现较为真实的光照效果。

总体来说,光探针技术为光照的近似计算提供了一种有效的解决方案,使得即便在计算资源有限的情况下,依然能够实现较为真实的光照表现。

黑板:我们在2D中如何处理?

在二维渲染中,面临两个主要问题:

首先,在三维中,每个表面都是多边形的,可以明确知道它们的形状、方向和其他重要信息,因此可以方便地计算表面的光照和反射。然而,在二维渲染中,并没有明确的表面定义。即使我们看到一个物体(例如一棵树),也只是看到了不同的颜色变化,而大脑通过颜色的变化推测出树的形状。对于计算机来说,这个过程非常困难,因为它并不能像人类一样自动理解颜色变化代表的形状,它甚至无法识别出这些颜色是树的部分。这使得计算机很难理解这些图像的表面方向或朝向,特别是在没有明确几何数据的情况下。

其次,计算机不知道每个表面的朝向。在三维渲染中,反射计算依赖于已知的表面方向。例如,如果一个墙面朝向不同的方向,反射的光线会有所不同,类似于球击打墙壁的方式也取决于墙面朝向。对于二维渲染来说,计算机无法获取每个表面的方向,因此无法像三维那样进行精确的反射计算。

因此,解决这些问题对于二维渲染的光照计算是一个巨大的挑战,尤其是在没有明确的表面几何信息的情况下。

黑板:法线贴图

解决第一个问题的一种方法是使用法线贴图(Normal Maps)。法线贴图是一种增强颜色贴图的技术,其中每个像素不仅存储颜色信息,还存储一个表示表面朝向的向量(通常是单位向量)。这些向量表示每个像素的表面方向,而不是存储实际的表面能量。通常,这些向量只需要存储x和y(或y和z),而不是存储完整的x、y、z坐标,因为法线的长度通常为1,这样可以简化计算。

法线贴图的使用能够有效解决二维渲染中的表面方向问题。然而,问题在于如何生成这些法线贴图。艺术家通常是绘制颜色贴图的,但他们并不一定能直接绘制法线贴图。虽然可以要求艺术家先绘制凸起贴图,再从中生成法线贴图,但这会增加额外的时间和工作量。此外,市面上也有一些程序可以帮助生成法线贴图,但它们的效果不一定理想。

因此,这个问题虽然是艺术资源的问题,但它并不是计算上的难题。解决方案是尝试实现法线贴图,并希望能够找到一种有效的方法来生成有用的法线贴图。如果无法得到合适的法线贴图,可以考虑采用一种不太理想的方式来处理,至少这样做可以为问题提供一个计算上的解决方案。

黑板:我们不知道光场是什么

第二个问题是关于光照场的问题。在三维渲染中,可以通过设置摄像机的位置并渲染场景,轻松地获取不同方向的光照信息。然而,在二维渲染中,无法通过这种方式获得光照信息。因此,需要找到一种方法来生成可供采样的光照场。

一种可能的解决方案是使用点光源,这种方法是通过将光源设置为点光源并在计算中使用来模拟光照。虽然这种方式简单有效,但可能并不总是足够灵活。

另一种方法是进行预渲染,生成一个类似光照缓存的东西。这个光照缓存是一个位图,可以在渲染前创建,类似一个帧缓冲区。通过这种方式,可以将场景中的光源渲染到这个缓存中,并对其进行扩散处理,如模糊化。然后,在渲染实体时,可以根据法线信息从这个光照缓存中获取光照数据,进行合成,最终计算出光照效果。

这种方法的核心思想是通过在光照缓存中创建"小光照探针"来获取周围的光照信息。每个探针覆盖一个区域,采样时会根据当前位置周围的光照情况进行采样,从而获得相应的光照数据。这种方法相较于传统的渲染方式,可以加速光照查找,提高渲染效率。

然而,光照是一个方向性的问题,涉及到反射等复杂情况。例如,如果在一个场景中有镜面反射,光源远在镜子另一侧,应该能够通过镜面反射看到该光源。如何处理这种情况是一个挑战,因此仍需要深入思考如何实现这种方法。

总的来说,这个问题的解决方案仍在探索阶段,尽管目前没有明确的解决方案,但目标是通过加速光照查询,提升渲染的动态性和场景的一致性。

问:这就是为什么像皮克斯这样的动画工作室需要超级计算机来渲染吗?

动画工作室像皮克斯之所以需要超级计算机来进行渲染,主要是因为光照计算非常复杂,通常涉及到四维或更高维度的采样问题。这些问题需要大量的计算资源才能解决,因此即使我们已经掌握了如何进行较为精确的光照计算,计算量依然非常大,导致需要使用强大的计算机硬件来处理。

为了生成高质量的图像,一种解决方案就是通过增加计算能力,投入更多的计算资源来加速渲染。光照计算尤其需要大量的计算,因为它涉及到复杂的采样过程,而不仅仅是简单的几何计算。虽然几何渲染也需要一定的计算资源,但相比之下,光照计算对计算能力的需求更为庞大。因此,超级计算机主要是用来处理光照等复杂的渲染计算。

问:阴影怎么办?

阴影的有趣之处在于,阴影其实并不是真正独立存在的"东西",它只是由于没有光照的区域产生的效果。因此,光照计算本身就能够处理阴影问题。然而,由于光照技术的近似性,当遇到需要锐利阴影的情况时,效果可能不够理想。例如,当需要像阳光照射在灯柱上的长阴影时,这些技术可能只会生成一种非常模糊的阴影效果,而无法呈现出锐利的阴影边缘。

黑板:阴影贴图

通常,为了实现阴影效果,人们会使用阴影映射技术。阴影映射的原理是,首先计算光源直接贡献的照明(即直接光照),而不是间接光照(通常使用光探针等技术处理)。然后,从光源的视角进行渲染,得到光源看到的场景信息,这样就能判断某些区域是否处于光源的视野范围内,从而产生阴影。当渲染时,如果光源没有看到某个区域,那么该区域就会被认为是阴影区域。

然而,对于本项目而言,阴影映射可能不需要实现,因为游戏中的场景不需要特别锐利的阴影效果。如果确实需要锐利阴影,也许可以通过简单的静态方式实现。这个游戏更关注的是环境光照的效果,例如通过绿色物质照射产生的绿色光,或者被绿色光照遮挡的物体呈现出不同的效果。因此,更适合的方式是采用光照传播技术,而阴影映射可能会浪费计算资源。

问:我在找一个构建设计文档,如果有的话该如何遵循?

在讨论"构建设计文档"时,主要是指为构建过程或开发工作制定的文档,通常涉及到构建流程、工具链、环境设置、依赖项、构建步骤以及可能的部署策略等内容。通过这样的文档,开发团队能够清晰地了解如何从代码到可执行文件的整个过程,并确保一致性和可重复性。

如果没有这样一个文档,可能是因为没有专门制定详细的构建步骤或工作流程,或者当前的开发方式并不需要一个正式的构建文档。在某些情况下,团队可能依赖于简单的脚本或自动化工具来处理构建,而不需要额外的文档支持。

问:我们是否计划实现昼夜循环和动态阴影,阴影会根据太阳位置伸长和消失?

虽然从技术角度来看,动态的昼夜循环和随着太阳位置变化的阴影变化可能是一个有趣的功能,但在这个游戏中,并不会实现昼夜循环。游戏设定在完全的夜晚,整个冒险过程发生在森林的夜晚,所以游戏中没有白天的情节。

不过,当前的阴影处理方法是通过单独的渲染通道来完成的,这样的技术支持实际上可以很容易地实现动态的阴影变化,包括阴影随着太阳的位置变化而拉长或变淡。如果以后有人希望为游戏加入昼夜循环的功能,这项技术支持应该能够很好地应对这一需求,可能只需要做一些小的调整。

问:光羽化,例如在窗户或树木上

关于"光的羽化"问题,是否指的是透明度效果?如果能提供更多具体的细节,将有助于理解所提问题。

问:是否考虑过在未来做一次关于真实3D光照或光线追踪的讨论/课程?

虽然不排除未来讨论三维照明或光线追踪的可能性,但由于当前项目并不涉及这些技术,因此这些内容不太适用。

问:如果镜子反射到另一个镜子里,反射光又反射回来,这种无限反射怎么处理?

在处理无限反射时,如果是在合成环境中,通常会采用一种技巧,比如限制反射的次数,通过设定一定的反射次数来避免无限反射的计算。但在现实世界中,这种情况并不存在。每次光子反射时,都会有一定的几率被吸收或散射,最终不会出现能够无限反射光线的镜子。即使是面对面的镜子反射,最终光线会被吸收,反射会逐渐变暗。实际上,并不存在完全纯粹的反射器,因为反射器会有一些散射和吸收现象,甚至空气中的灰尘也会影响光线的反射。

黑板:体积散射(Volumetric Scattering)

在现实世界中,光线的反射不会无限循环,因为空气中的粒子会导致散射现象。当光线在大气中传播时,它可能会与空气中的粒子碰撞并发生散射,这就是为何远处的物体看起来更加模糊或被洗淡的原因。实际上,光线通过空气时会损失一些能量,因为散射现象在不断发生。即使是在两个面对面的镜子之间,光线每次穿过空气时都会因为空气分子造成散射而损失一部分能量。因此,在现实世界中,不可能存在光线无限反射的情况,因为每次反射都会有部分光线被散射或吸收。

问:关于新手为何要经历你们正在经历的这些讨论。#JustUseUnity

在讨论是否使用Unity时,提到有些新人可能认为直接使用Unity会更省事,快速开发一个游戏。然而,这个讨论并不是关于如何快速上手Unity或其他游戏引擎,而是深入了解游戏开发的核心技术。在这场讨论中,强调的是如何深入理解这些引擎背后的原理,以及如何在现有引擎基础上进行拓展和定制。对于那些只想使用引擎完成基础开发的人来说,Unity和其他引擎已经提供了足够的工具和教程。但如果目标是突破引擎的限制,掌握更深层次的技术,甚至自己开发引擎或插件,那么这就是与众不同的地方。学习这些技术可以使得开发者能够实现别人做不到的效果,并且为自己提供更多的开发自由,甚至在未来有能力创造全新的游戏引擎或插件。这个过程就像是想要了解汽车构造的工程师,而不仅仅是买一辆车开。

问:当2D变得比3D更复杂时,值得继续做2D吗?

虽然表面上看,2D可能看起来更复杂,但实际上,3D涉及的复杂性要高得多。对于3D,存在许多看不见的挑战,如如何实现表面反射函数,如何处理透明度和排序问题,如何正确渲染立体图像等。3D渲染需要解决更复杂的数学问题,比如如何处理光线通过透明物体的折射,如何管理光照贴图,如何计算多重光照探针等,这些都比2D要困难得多。尽管在一些现代引擎中,3D图形的实现已经变得更加实时且精确,但要实现高质量的3D光照仍然需要大量的工作和计算。这也是为什么开始时选择2D作为入门是明智的,因为3D涉及的内容过于复杂,且许多技术和方法需要在后期进一步学习和掌握。如果要在3D中处理光照,涉及的问题和技术的深度远超2D,需要对HDR等技术有很高的理解和应用能力。

问:你的'光照立方体'概念和立方贴图是一样的吗?

在讨论光照时,所提到的"光照立方体"实际上就是"立方体贴图"(cube maps)。立方体贴图通常是通过在场景中不同位置渲染多个立方体图像来进行的,这些图像用来插值计算间接光照。间接光照指的是光线反射或散射后的路径,而不仅仅是直接照射到物体上的光线。直接光照相对简单,因为它只涉及光源直接照射到物体表面,再进入观察者眼睛的部分。间接光照则复杂得多,因为它来自各个方向,且光线会反射或折射多次。立方体贴图是计算间接光照的一种常见方案,但也存在其他方案。

问:如何让光穿过窗户或树木的羽化效果

在讨论间接光照时,提到的复杂性源于光线的多方向传播。与直接光照相比,间接光照涉及更多的计算,因为它不是来自单一方向,而是来自各个反射或散射后的方向。这使得计算更加复杂,尤其是在尝试模拟光线穿过窗户或树木等场景时。

黑板:半透明

在讨论半透明时,举了一个典型的例子:日式屏风(Shoji屏风)。这种屏风由木制框架和纸张构成,具有半透明的特性。当光线从屏风的另一侧照射过来时,屏风会发出柔和的光线,而人影会投射到其上,但不能看到人本身。这种现象被称为半透明,而不是透明,因为光可以透过,但无法清晰地看到物体的形状。

另外,提到了通过树叶看到阳光的例子,光线通过叶子时,也只能看到光的存在,却看不到叶子的具体形状,这也是半透明的表现。

半透明的处理方法实际上是间接光照的一种扩展。对于半透明物体,光从背面进入,通过物体内部散射后再从前面出来。这种光线的散射行为需要在计算中处理,考虑到光线如何从物体的一面传播到另一面。因此,半透明的表面实际上是通过间接光照方程来处理的,光线通过物体的背面传播,而不仅仅是从正面入射。

问:为什么不直接在精灵上模拟光照?

将光照直接预先渲染到精灵上是不可行的,因为无法提前确定光源的方向。如果想让物体(如树木)能够根据光源的不同位置而显示不同的光照效果,无法将这些效果固定在精灵上。为了实现这种效果,需要动态计算光照。这样,光照可以随着光源的移动而变化,而不是静态的。因此,需要在渲染时动态计算物体周围的光照,尤其是当光源围绕物体移动时,才能正确表现光照的变化。

问:关于第二帧缓冲区的提议,是否可以让光源有预计算的距离衰减,并让图形对象有一个类似透明度的通道表示反射率?这样会很快,或许足够适用于2D游戏

使用第二帧缓冲区与光源的预先计算的距离衰减和图形对象的额外反射率通道(类似于透明度通道)是一种加速并能够为2D渲染提供足够效果的方法。然而,这种方法依然面临挑战。尽管距离衰减可以通过模糊处理实现,但光照的处理依然复杂,因为光照系统涉及多种因素,远比流体动力学或其他体积效应更具挑战性。

黑板:光照在一条线上的分布是恒定的

光照的本质问题在于,光并不会因为它传播的距离而变暗。实际上,光沿直线传播,如果没有任何物体阻挡,光的强度在传播过程中是不会衰减的。只有当光照射到物体时,它的强度才会变化。现实中,空气的密度太低,所以在游戏中,光源与远处物体(比如镜面球体)之间的反射光,实际上并不会发生显著衰减。

尽管如此,光照在现实中并不会像游戏中的计算那样准确地衰减,因此为了在游戏中实现更合理的效果,可能会使用一些近似方法,比如使用假设的衰减来模拟光的效果。因为游戏需要实时计算,无法像物理模拟那样精确,所以下近似处理是不可避免的,可能会通过点光源来处理衰减效果,而漫反射光的衰减则可能并不被考虑,因为远距离的光照衰减对视觉效果影响较小。

问:由于光照的复杂性,系统资源在着色引擎中的使用是一个重要因素吗?

由于光照的复杂性,系统资源确实是游戏引擎中的一个重要考虑因素。在游戏设置中,通常会提供选项来调整如阴影细节等内容,这些设置直接影响光照的计算和渲染效果。更强大的计算机硬件意味着能够处理更复杂的光照计算,因此高性能的机器可以实现更精细的光照效果。

问:如果使用2D光照缓冲区,是否需要先生成G缓冲区或Z缓冲区?

在使用 A 到 D 的光照缓冲区时,通常不需要生成 Z 缓冲区,但需要一种方式来控制光的传播。因此,可能会使用 G 缓冲区。在这种情况下,需要能够阻止光在有实物的方向上传播,以减少光的量。具体如何实现这一点尚不确定,但可以通过某种方式处理这一问题。

问:关于光晕效应怎么办?

不清楚"光晕效应"指的是什么。

问:这个系统是否适用于软件渲染,或者会因为计算开销过大而无法实现?

该方法会在软件渲染中实现,如果发现运行速度不够快,就会在软件渲染中关闭。如果性能不够理想,且无法优化到足够快,就只会在GPU路径上运行。首先会确保软件路径能够正确工作,然后根据需要依赖GPU的运算能力来实现实时渲染,以支持游戏的表现。

问:你提到过如何计算一个光源接收来自多个源的光。我们应该如何计算这些值?我猜测是基于相邻像素的值。我有点难以构思这个方法

计算来自多个光源的单一光源接收的光值的方法是通过逐步下采样的方式进行的。首先,从较高分辨率(如156x128)开始,逐步将其下采样为128x64、64x32、32x16、16x8、4x4、4x2、2x1和1x1。这样,在需要模糊光照时,可以通过对这些下采样版本进行采样来实现。具体操作仍然在探索中,未来可能会进行调整和尝试。在解决问题时,会尝试处理之前从未遇到过的问题,因为这有助于学习如何处理新问题,而不仅仅是展示已经掌握的知识。

问:在大多数情况下,使用现有的图形/渲染引擎来开发游戏,而专注于游戏本身/玩法会不会更聪明?

在游戏开发中,选择是否使用现有的图形引擎来专注于游戏玩法是一个带有假设性的问题。如果目标只是快速实现游戏玩法,那么使用现有的图形引擎是更聪明的选择。然而,游戏开发不仅仅是关于实现游戏玩法。游戏开发是一门完整的学科,包含了许多方面。每个开发者对开发的乐趣来源不同,不能仅仅假设每个人的唯一目标是尽快将游戏玩法呈现出来。实际上,很多开发者享受的是整个开发过程,包括与游戏玩法无关的部分。

使用现有技术或引擎的选择,正是因为有一些人不只关注于快速实现游戏玩法,而是享受制作游戏各个部分的过程。游戏开发不仅仅是为了实现一个具体目标,而是艺术性的创作,涉及多个层面的工作。因此,如果只追求简单的游戏呈现,可以使用更简单的工具,但如果想要了解如何从零开始构建整个游戏,就需要了解所有的开发方面。

问:什么是环境遮蔽,为什么我的显卡在运行带有环境遮蔽的游戏时会变慢?为什么会丢失FPS?

环境光遮蔽(Ambient Occlusion,简称AO)是一种模拟光线与物体表面相互作用的技术,旨在增强图像的真实感。它通过在场景中的暗区域添加更多的阴影来模拟光线如何被遮挡,这样可以使得物体看起来更加立体和真实。具体来说,AO模拟的是物体表面在与周围环境互动时的遮挡效果,例如物体之间的缝隙、角落和紧密区域,通常这些地方会比开放区域更暗。

关于为何启用环境光遮蔽时,某些视频卡运行游戏会变慢,可能的原因有多个。AO是一种计算密集型的渲染技术,它需要处理大量的光线信息,特别是在场景复杂或动态光照条件下。较低端或老旧的视频卡可能没有足够的处理能力来快速计算这些额外的光影效果,从而导致游戏性能下降。

黑板:环境遮蔽

环境光遮蔽(Ambient Occlusion, AO)是一种技术,旨在通过模拟光线与物体表面相互作用来增强图像的真实感。它并不是一个真实的物理现象,而是通过近似计算来再现光线在物体表面传播时的遮挡效应。简单来说,AO通过在物体表面和物体之间添加阴影,模拟光线在小空间或物体表面细节中的遮挡现象,从而让物体看起来更有层次感。

具体来说,AO通常有两种实现方式:

  1. 烘焙环境光遮蔽(Baked AO):这种方法是在离线渲染过程中计算物体表面某些区域的遮挡程度,并将结果存储为纹理图。通过分析每个纹理的视野范围,即它能够看到的光线来源的半球区域,计算其受遮挡的程度,然后将这个信息写入纹理映射中,最终在渲染时直接应用这些预计算的值。

  2. 屏幕空间环境光遮蔽(SSAO):这种方法利用场景的Z缓冲区,即在渲染过程中每个像素的深度值信息。通过分析每个像素周围的深度值,确定是否有其他物体会遮挡光线,进而模拟阴影效果。尽管这种方法常常产生不太真实的效果,但它能够在实时渲染中动态计算遮挡,减少了计算开销。

值得注意的是,环境光遮蔽并不是真正的物理光照计算,而是一种近似的技巧,目的是增加图像的真实感。它并不像全局光照或其他复杂的光照计算那样精确,因此被视为一种"修补"或"黑客式"的方法,用来弥补常规光照模型无法捕捉到的自阴影效应。

问:你有计划实现精灵的不透明度吗?如果有,是否可以在光照贴图计算中考虑它?即不透明物体会阻挡更多的光?

已经实现了精灵的透明度控制,精灵可以根据需要进行过渡。对于透明物体的处理,确实可以在光照贴图计算时考虑透明度,较不透明的物体会阻挡更多的光线。还可以尝试让半透明物体表现为透明,但同时保留颜色传递的效果。对于这些处理,可能会做一些实验,看看最终效果如何。开发自己的图形引擎的有趣之处就在于,可以尝试一些新的技术,虽然这些技术可能没有人做过,也可能效果不佳,但通过实验可以探索出一些有趣的想法。

问:是否有任何关于光照或游戏引擎创建的书籍或资源推荐?

有一本关于光照的书籍被很多人推荐,书名是《Physically Based Rendering》,作者是Matt Fair。虽然本人没有读过这本书,但它是很多人推荐的资源,尤其适合想要了解光照背后的数学原理和如何模拟光照的人。如果想要获得一个全面的概述,这本书被认为是一个不错的选择。

2023版

-zlibrary 外网才行 Physically Based Rendering

-本地 Physically Based Rendering

问:游戏设计文档,比如游戏的路线图?

在这项工作中,并没有涉及游戏设计文档或类似的路线图。设计和实现是分开的,重点是编程游戏引擎和开发游戏玩法,但并不讨论设计方面的内容。因为并不从事游戏设计,所以也不打算讲解游戏设计的相关知识,避免提供不恰当的指导。因此,游戏设计文档或类似的设计工作并不在当前的工作范围内。

问:如果游戏在完全黑暗中,是否最容易编写光照系统?

确实,如果游戏完全处于漆黑的环境中,编程一个简单的照明系统会相对容易。曾经有一款游戏,名为《黑暗之中》(Alone in the Dark),最初的设想是完全在黑暗中进行,游戏主要依靠音频来进行交互。最初的计划是让游戏完全依赖音频,而没有视觉元素,但最终发布商要求他们修改,所以游戏最终还是加入了位图和简单的视觉元素。不过,即便如此,这款游戏依然非常成功。虽然设计最初是要保持完全黑暗的游戏环境,但由于后来的改变,最终并没有实现这一点。

问:能不能回到过去,15年前就开始这个系列?

如果能够回到十五年前,肯定会很愿意开始那个系列。十五年前没有现在的Twitch和YouTube等平台,所以需要想办法传输内容。不过,相信最终还是能够找到解决方法的。

问:我的意思是,如何让光束穿过渲染对象?

问题是在追踪如何让光束穿过渲染的物体,似乎是想弄清楚如何实现这种效果。可能是指光辉(god rays)效果,而不是通常的光晕(bloom)。

黑板:光辉(god rays)

"God rays"实际上是体积散射的现象。它的原理是,没有所谓的"光束",光是以光子形式穿过空气,散射的效果发生在空气中充满颗粒物的情况下,特别是在明亮的光线下。比如,阳光在雾气中照射,这时光子会与空气中的颗粒物碰撞并发生散射,从而形成可见的"光束"效果。

例如,如果有一个彩色玻璃窗,光通过窗户时,玻璃会吸收某些颜色的光,允许其他颜色通过。假如是红色的玻璃,红色光会透过,而其他颜色会被吸收。然后这些红色光通过空气中的颗粒物散射,部分光线会回到观察者眼中,形成散射效果。

在实现上,如果是在光线追踪中,需要计算光在通过体积时的散射概率,并在命中时进行光的散射。而在游戏中,由于体积散射的复杂性,需要进行近似处理。目前可能会采用屏幕空间技术来实现这种效果,通过在渲染时检查是否存在需要体积效果的像素,然后对这些像素进行处理。

因此,当前可能的技术是利用屏幕空间进行处理,利用屏幕空间的渲染信息来模拟这些体积散射效应,而不需要复杂的物理计算。

问:你不应该从眼睛发射光线,而是从太阳发射光线,以减少计算量,然后检查从眼睛发射的光线是否击中太阳?

在光线追踪中,通常是从眼睛出发射线,而不是从光源发射,以减少计算量。这样做是因为大多数光线追踪算法(尤其是蒙特卡罗方法)会从观察者的视角出发,追踪光线如何与场景中的物体交互,最终返回到眼睛。因此,光线追踪的核心是从眼睛出发的。

在一些更复杂的实现中,像双向路径追踪(Bidirectional Path Tracing)这样的算法,会同时从眼睛和光源发射光线,结合这两者的结果来计算最终的照明效果。这些算法可以提高某些场景下的计算效率,但它们的实现会更加复杂。

所以,是否从眼睛或光源发射光线,取决于具体的实现和所用的算法。在游戏中,通常使用的是较为简单的光照技术,如阴影贴图等,而不直接使用光线追踪。

问:你可以使用3D叠加层来模拟3D环境的切片吗?例如,平台的z值是1,x值表示左右,y值表示上下。这样你可以在x=33, y=50, z=1的位置有一个光源,所有小于x=33的物体会在右侧投下阴影,而大于x=33的物体则会在左侧投下阴影?

可以使用三维重叠的方式来模拟一个三维环境的切片。例如,平台可以表示为 Z 轴,而 X 轴则表示横向,Y 轴表示上下。在这种设定下,可以有一个光源,所有 X 坐标小于某个值的物体会被照亮到右边,而大于该值的物体则会被照亮到左边。

这种方法实际上是在通过三维空间的分割来模拟光照和物体的关系。然而,这样的设定可能会变得非常复杂,因此还需要进一步探索和实验,才能决定如何实现这个过程。

问:在早期的剧集里,你们曾经讨论过多重z层次。那是否意味着你们需要在渲染中加入3D墙面,这样就会引入一些3D的计算到渲染和光照中?

在早期的讨论中,涉及到多个海拔层次的问题,这可能会意味着需要渲染墙壁并引入三维渲染和光照计算。不过,可能会选择通过分割的方法来处理,而不是完全采用三维渲染。可能的做法是,在不同的平面上进行光照计算,或者只在某些平面上应用光照,而其他平面不做光照处理。

问:你认为我们能实时完成所有这些工作吗?还是我们必须在生成地图时预先计算一些光照信息?

目前还无法确定是否能够实时完成所有的工作,可能需要在生成地图时预测一些光照信息。目前这一切还只是猜测。

问:难道不能直接做一个3D游戏,然后用擀面杖把它压扁?

将一个三维游戏做成二维的想法其实不错,这样可以轻松地从三维资源中创建二维资产。不过,担心用"擀面杖"压平之后,可能会有太多细节被压缩掉,因此需要找到解决这个问题的方法。

问:实时辐射度在游戏中有多常见?它容易实现吗?你们使用过吗?为什么或者为什么不?有什么提示吗?

实时辐射传输技术(radiography)在游戏中并不常见,因为辐射传输主要是处理热传递问题,而游戏中使用的实时光照技术通常是不同的。虽然一些引擎如Frostbite可能使用了辐射传输引擎,但许多游戏引擎现在已经不再使用这种方法,而是采用其他方式处理间接光照。例如,Unreal Engine 4就包含了很多实时间接光照的处理方法,而CryEngine则使用了体积光传播方案(Voxels)。总的来说,实时光照中包括间接光照的技术已变得更加普遍,但辐射传输技术并不是主流。

问:我看到有个游戏在精灵上使用了法线贴图

使用法线贴图(normal maps)在精灵(sprites)中的确并不常见,但也不算特别罕见。有些游戏确实会使用法线贴图来增强精灵的视觉效果。关键问题在于如何生成这些法线贴图。如果从3D模型渲染到2D,生成法线贴图是相对简单的。但如果精灵是手绘的,问题则在于谁来制作这些法线贴图以及如何制作。

问:光的衰减不是平方反比定律吗?当你远离光源时,每一束光线与邻近的光线之间的距离增大

光的衰减确实遵循反平方定律,即随着距离光源越来越远,每条光线之间的距离也会增大。这是两个不同的概念,其中一个是光的衰减方式,另一个则是光线之间的空间分布。

黑板:平方反比定律

反平方定律只会影响部分光线。在讨论光的传播时,直接光和间接光的影响有所不同。当考虑到反射光时,反平方定律并不会直接影响单个光子的路径。例如,在反射光源时,如果光源距离镜面较远,镜面上光源的大小会变小,但光源的亮度并不会随之衰减。实际上,反平方定律影响的是光源的大小,特别是在反射光源的情况下,而不是其亮度。

当光源距离物体越来越远时,反射光源的大小会变得更小,且光线会更分散,因此到达物体的光量会减少。然而,纯反射部分的亮度并不会受到反平方定律的影响,反而是光源的大小会根据距离变化。这意味着,尽管光源的亮度可能会因光的散射变得更稀疏,但对于反射部分的计算,亮度本身并不会按照反平方定律变化。

问:你会考虑像《小小大星球2》那样体素化场景吗?

考虑到光源的处理方式,类似《Little Big Planet》的照明系统就是一种可行的思路。在这个系统中,首先将光源放入场景并进行扩散,然后根据物体的位置来调整光的传播,避免光线穿过物体。这种方式与Vauxhall的光照方案相似,虽然没有完全采用类似的盒子结构,但整体的思路是相同的。可以通过这种方式实现类似《Little Big Planet》风格的照明效果,并根据实际情况进行调整。

问:我需要登录,希望这还不算太晚。当集光源时,是否会有衰减效应,因为光线从源头扩展出去时,衰减会影响表面?

关于光源的衰减问题,光源的衰减并不是简单地遵循逆平方定律。对于环境光和间接光,衰减会受到逆平方定律的影响,但对于直接光源,逆平方定律并不适用。常见的误解是,所有光线都遵循逆平方定律,实际上并非如此。光线沿着一条直线传播时,并不会因为距离远近而衰减,只有当考虑到面积时,才会涉及到衰减的效果。

因此,光的亮度并不会沿着直线衰减,而是取决于反射计算的哪一部分。如果计算的是反射光的大小,逆平方定律会影响光源在物体上的投射尺寸;而如果计算的是反射光的亮度,逆平方定律则不再起作用。这表明,逆平方定律主要影响的是散射光的亮度变化,而对纯反射光的亮度没有影响。

问:为什么在3D程序中用光子而不是粒子来表示光会更容易?

在三维程序中,将光表示为光子而非粒子并不一定更容易。实际上,光子本身也是一种粒子。问题的关键在于,三维程序中通常不会直接模拟光子的行为,而是通过物理模型来处理光的传播和反射等效果。光作为光子是量子物理中的概念,而在计算机图形学中,更多的是通过光线追踪等方法来模拟光的路径和与物体的交互。这样的方法虽然基于粒子理论,但更多的是关注光的宏观行为,比如传播方向、强度等,而非光子级别的细节。因此,将光表示为光子并不总是与程序的实际需求相符。

问:如何在接近光速的环境中渲染光和事件?

在渲染光与接近光速的环境和事件时,处理这类问题非常复杂,涉及到相对论的理论。在这种情况下,考虑到光速的限制和光在不同参考系下的表现,可能需要采用特殊的技术或算法来模拟光的传播。这是一个高级的物理问题,可能需要专门的领域知识和技术,通常不在常规渲染方法的范围内。

问:PBR光照?简要介绍一下它是如何工作的? (Physically based rendering )

本集到此结束

接下来将开始涉及法线贴图的内容,预计会作为接下来的一个部分进行处理

相关推荐
s_little_monster14 分钟前
【Linux】进程地址空间
linux·运维·服务器·经验分享·笔记·学习·学习方法
Orange30151124 分钟前
ES6~ES11新特性全解析
java·前端·javascript·es6
drebander41 分钟前
[特殊字符] 基于 FastAPI 和 React 构建车牌号识别网站
前端·react.js·fastapi
Lanwarf-前端开发1 小时前
gis风场加载
开发语言·前端·javascript
Merlin-Ice1 小时前
Unity Shader Feature
服务器·前端·unity
吃蛋糕的居居1 小时前
疯狂前端面试题(四)
前端·javascript·chrome·ajax·正则表达式·firefox·html5
程序员林北北1 小时前
【Golang学习之旅】gRPC 与 REST API 的对比及应用
java·开发语言·后端·学习·云原生·golang
蝈蝈ly2 小时前
WPF学习
学习·wpf
一川晚照人闲立2 小时前
JEECGBOOT前端VUE3版本浏览器兼容支持chrome>=76版本方法
java·前端·vue.js·chrome·anti-design-vue·jeecgboot·jeecg
前端加油站2 小时前
高级前端成长之路必看前端请求
前端·vue.js·react.js