游戏引擎学习第81天
仓库:https://gitee.com/mrxiao_com/2d_game_2
或许我们应该尝试在地面上添加一些绘图
在这段时间的工作中,讨论了如何改进地面渲染的问题。虽然之前并没有专注于渲染部分,因为当时主要的工作重心不在这里,但在实现过程中,发现地面没有明确的可视化表示,这导致玩家无法直观地看到地面或楼层的变化。虽然房间的边界通过树木做了简要的绘制,但地面本身并没有明确的图形,玩家在上下楼层时,缺乏对地面位置的视觉提示,所看到的只是一些代表性元素。
因此,提出了一个想法,考虑增加一些简单的地面绘制,以便玩家能够清楚地看到楼层的边界。这种改进将使地面更加可视化,提升用户体验。目标是寻找一个既简单又能有效体现这一需求的解决方案,并且不会偏离目前的工作方向。
在GIMP中查看艺术资源
在这一段讨论中,提出了通过使用纹理贴图来构建地面的一些想法。之前已经有了一些测试图像文件,存放在项目的“data”目录中。这些图像被用作地面纹理,可以通过图片查看工具查看,尽管在某些程序中可能显示不完全。通过GIMP等图像处理软件,这些纹理可以加载到一个图像查看器中,看到的是一些石质或草地的纹理片段,带有一定的透明度。
这些纹理片段设计成可以拼接起来,形成一个连续的地面区域。例如,石质地面纹理可以通过将不同的片段组合在一起,创建一个类似石头或土壤的地面。草地纹理的使用方式类似,可以用来覆盖地面的一部分,形成更自然的外观。
通过在图像编辑软件中复制粘贴这些纹理,可以创建出更大的地面区域,看起来像是草地的延伸。使用不同的图层和纹理,可以让地面看起来更加多样化,并避免过于重复的效果。尽管这种方法简单,但通过多次调整、重新排列和使用更多的纹理,可以构建出更复杂、更自然的地面。
这种方式模拟了使用“克隆工具或者“画笔”的技术,通过不断地复制和调整这些纹理块,逐步填充一个更大的地面区域。尽管效果并不完美,但它为构建虚拟世界提供了一个直观、灵活的起点。
总的来说,这种方法可以有效地创造出一种有机、非重复的地面效果,适用于一些基础的地面建模工作,尤其是在早期开发阶段。
对艺术的构想
目标是为游戏创造一个较为有机且不重复的地面纹理,避免像传统的瓷砖地图那样的僵硬边界和重复感。为了实现这一点,计划通过利用Clone技术(类似于使用“画笔”)来创建自然感觉的地面图案,能够拼接成更为流畅、无缝的地面效果。最终的目标是通过这种方法,让艺术家能够以较低的成本和时间,制作出看起来更具手绘感的图像,而不是依赖传统的拼接瓷砖地图。
目前,已经实现了Alpha混合精灵的支持,这使得可以开始尝试在游戏中使用这些地面元素,但这也可能影响帧率,因尚未优化相关代码。尽管如此,仍希望能通过这种方式尝试构建更自然的地面纹理,并为后续的艺术设计和代码架构做准备。
这些地面元素可能会通过实体系统处理,尤其是像草丛、树木等有互动的背景物体。某些元素(例如草丛)可能需要进入同一区域并且与玩家互动,比如随风摇曳,而其他背景元素则可以独立于玩家互动,作为单纯的艺术效果进行管理。
因此,需要考虑如何合理地将这些元素引入游戏的不同区域,以及如何处理它们的行为和交互效果。提前进行这些设计和实验,将有助于在未来做出更合适的架构决策,并优化游戏的表现和可玩性。
加载地面纹理
为了实现地面纹理的加载和展示,计划首先将一些纹理资源加载进来。目标是将这些纹理分为几组,包括草地纹理、石头纹理和草丛纹理等。具体步骤包括加载草地和草丛纹理,并暂时跳过大石块纹理,专注于草和草丛效果。
目前并不关注资源流式加载等复杂功能,只是通过简单的方式加载纹理图像。这些代码的实现是为了快速验证加载的效果,未来会有一个更完整、优化的方式来处理资源加载。
此外,还通过直接的复制粘贴操作将纹理加载到对应的数组中,确保每个纹理正确地加载并呈现出预期的效果。最终目标是为后续的地面效果设计做准备,虽然这部分代码目前还不会在实际开发中使用,但通过简单的实现来确保可以顺利加载和展示资源。
引入DrawTestGround来合成纹理
首先,决定跳过引入不必要的内容,专注于实现合成(compositing)功能。在处理过程中,首先会清除屏幕并设置为灰色背景。接着,在背景清除后,简单地实现一个绘制测试的功能,即创建一个“DrawTestGround”函数。这个函数的目的是为接下来的合成操作做准备,确保在开始其他工作之前,可以看到合成的效果。
接下来,绘制功能的实现重点是测试合成效果,特别是如何将不同的元素进行组合。为了做到这一点,随机选择一些草图元素(如草地),并在随机位置上绘制这些草元素。为了简化操作,使用一个随机数表来生成位置,并且决定先绘制草地图形。
为了更系统地处理随机数,考虑到可能需要改善随机数生成的方式,将其设计成更系统的方式,以便在以后可以重复使用。一个可能的改进是将当前的随机数生成方式转化为更结构化的机制,计划在当日完成这一任务。
为了实现绘制,需要确保合适的缓冲区被传递给绘图函数,特别是需要将屏幕缓冲区传递给“DrawTestGround”函数。接着,选择一个草地纹理并在屏幕上的(100,100)位置绘制它,确保绘制时能显示完整的透明度效果。为了正确提取位图的像素,检查了加载的位图是否包含宽度和高度,并确认了如何通过指针传递图像数据。
总体来说,当前的重点是实现一个简单的测试框架,以便能够有效地调试和查看合成效果。
在游戏中查看结果
当前目标是确保草地图形能够正确显示,并且能够在屏幕上看到草地元素的效果。虽然草地已经显示出来,但它仍然处于屏幕空间中,这意味着它会随着相机的移动而一起移动,始终保持在同一屏幕位置。当前的实现没有考虑这些元素如何被拉入世界中或它们的实际位置,这些都暂时不在计划之内。
接下来的计划是尝试在屏幕上随机放置多个草地元素,看看如果放置十个这样的元素会是什么效果。目标是测试将多个草地元素堆叠在一起后的视觉效果,并评估这种做法是否符合预期。
随机地喷溅大量草地纹理
目前使用的随机数生成器并不是一个真正的生成器,而是简单地通过一个随机数表来驱动生成随机数。随机数生成的实现还在待办事项列表中,未来会考虑如何实现一个真正的随机数生成器。
接下来,目标是让草地元素的位置不再基于像素空间,而是转换为米单位。为了做到这一点,决定使用“米到像素”的转换方法,使得坐标能够更加符合实际游戏世界的尺寸。在初始化草地元素的位置时,计划选择屏幕上的随机点进行绘制,范围大致为-16米到16米之间,这样可以确保草地元素的位置不会过于局限。
查看RandomNumberTable
目前使用的随机数生成器产生的随机数并不在完整的32位无符号整数范围内,实际上,它们的最大值较小。使用的是从一个随机数网站(如random.org)获取的随机数,虽然这些数是随机的,但它们并没有覆盖所有可能的32位范围。例如,生成的随机数最高只有0x5xxxxxxx,而不是32位无符号整数的最大值0xFFFFFFFF。因此,当前的随机数表生成的值范围较小,无法充分利用32位整数的全部可能性,这可能影响生成更大范围随机数的能力。
计算RandomNumberTable的最大值
目前不知道随机数表中的最大值,但可以通过遍历随机数表来找出最大值。首先将最大值初始化为0,然后遍历整个表,逐个检查每个值。如果当前值大于已记录的最大值,就更新最大值。通过这种方式,可以确定随机数表中能产生的最大值。
一旦确定了最大值,就可以将其作为最大可能随机数值,更新到随机数生成器中。这使得我们可以更准确地理解随机数生成器所能产生的范围,并进一步决定如何使用这些值来生成浮动值(如浮点数)。
计算RandomNumberTable的最小值
为了找出随机数表中的最小值,可以将最小值初始设为最大值,这样在遍历过程中每次遇到小于当前值的项时,就会更新最小值。这是一个常见的编程模式,用于跟踪一组值中的最小或最大值。
通过这种方法,可以确保无论表中的值如何,最终都会找出最小值和最大值。在这个过程中,最小值和最大值已经计算出来了。如果需要,可以将最小值当作零来处理,但既然已经计算出来,就可以保留它。
在RandomNumberTable的范围内生成一个0到1之间的浮动数字
通过将随机数表中的整数除以最大值,可以将其转换为一个介于0和1之间的浮动点数。这是将32位整数转换为浮动点数值的常见方法。当得到一个随机点后,通常需要将其映射到一个范围,例如如果假设屏幕中心是坐标(0,0),那么为了在该中心周围分布草地,需要将数值映射到-1到1之间。然后,可以根据所需的半径乘以该数值,来决定草地的位置。
Blackboard: 将数字从0到1之间转换为-1到1之间
为了将0到1之间的数字转换为-1到1之间的数字,可以使用简单的范围缩放和偏移。首先,将数字乘以2,使得其范围变为0到2。然后,通过减去1,将范围平移到-1到1之间。这种方法对于程序员来说是直观且常用的,因为这种类型的操作非常常见。如果觉得更复杂的数学操作难以理解,可以明确地推导出数学公式。假设有一个函数f(x),其输入在0到1之间,可以通过2x-1将其映射到-1到1的范围。
Blackboard: 两个点之间会发生什么?
在确定如何将0到1之间的数字转换为-1到1之间的数字时,可以通过定义一个数学函数来实现转换。通过设置两个样本点,分别表示输入值为0时输出为-1,输入值为1时输出为1,可以构建这个函数。然而,问题在于如何处理两个样本点之间的值。需要确定函数的形状,例如是线性进展,抛物线,还是其他形式。根据这些信息,函数的具体形状会有所不同,因此需要更多的细节来明确函数在区间中的行为。
Blackboard: 多项式的次数
在数学中,定义一个函数时,通常会涉及到多项式的次数(degree)。多项式的次数决定了函数的复杂度,即曲线的形状。例如,线性函数(一次多项式)只是一个简单的直线,而二次多项式(抛物线)则会形成一个弯曲的形状。对于简单的线性映射,可以通过解一个简单的线性方程来找到所需的函数。
在定义了两个样本点之后,可以通过代入这些点来求解线性函数。以两个点(0, -1)和(1, 1)为例,可以设定一个简单的线性方程 f ( x ) = a x + b f(x) = ax + b f(x)=ax+b,然后通过代入这些点来求解常数 a a a 和 b b b。解得结果是 f ( x ) = x − 1 f(x) = x - 1 f(x)=x−1。
如果希望使用更高阶的多项式,例如二次多项式,可以增加一个额外的点来使得函数可以通过更多的点进行拟合。这时,方程的形状将变得更加复杂,可能需要求解更多的参数。对于高阶多项式,增加更多的约束条件(例如更多的样本点)可以帮助确定函数的形状。
当我们面对过多或冗余的约束时,例如给定了不适合的点,可能会导致方程无法解出。这种情况可以通过其他数学技术(如最小二乘法)来解决,从而找到一个最优的近似解。这些方法可以在无法完全满足所有约束条件时,寻找一个“最接近”的解,依然能够提供有用的结果。
实现方程f(x)=2x-1并喷溅多个草地纹理
在程序实现过程中,首先设定了一个基本的输入映射公式:输入值乘以2再减去1。这样就能确保输入的值被正确地转换为所需的范围。接下来,计算过程中使用了一些变量,如屏幕的中心位置和“米到像素”的比例,将图形的位置与屏幕上的像素位置关联起来。
为了确保图形正确地显示在屏幕上,首先通过计算屏幕的宽度和高度的一半来确定屏幕的中心。接着,将屏幕中心作为参考点,通过适当的缩放和偏移量,计算出图形的实际位置。通过这种方式,可以将一个点(比如草地)随机地放置在屏幕上的不同位置。
为了测试这个位置计算,首先设置了一个较小的值(例如1)来确保初步的图形显示正常。然后通过增加显示数量(例如增加到10),可以在屏幕上看到更多的草地随机分布。如果草地的分布出现问题,则需要进一步调整“米到像素”的缩放比例和其他参数,确保图形正确显示。
最后,考虑到当前使用的是屏幕中心作为参考位置,实际上更合理的做法是使用世界坐标系的中心来进行计算,这样可以更准确地将图形定位到实际的游戏世界坐标中,而不仅仅是屏幕坐标。
考虑位图的中心
在这段内容中,首先讨论了绘制草地时,草图标的位置偏离了预期。问题的根源在于,绘制的坐标没有正确考虑到位图的中心点,导致草图标的位置偏离了世界的中心点。因此,决定添加位图中心的偏移量来进行调整。
具体步骤如下:
-
考虑位图中心:为了确保草图标正确居中,首先获取位图的宽度和高度,计算出位图的中心。这里的位图是“Grass[0]”,它的宽度和高度被用来确定位图的中心位置。
-
调整绘制位置:接着,根据位图的中心点,调整草图标的位置,使其正确对齐到屏幕的中心。这个调整是为了确保草图标绘制在屏幕上的正确位置。
最终,通过这些调整,草图标的绘制位置得到了修正,确保了它能够更准确地显示在屏幕的中心,尽管调整是通过目测的方式进行的。
设置偏移喷溅的半径
首先,考虑到草地的半径,需要确定它的大小。假设设定半径为10米,进行测试。为了生成随机位置,当前使用的是一个方形区域,但是为了使草地更加自然,需要使用一个圆形区域来随机生成位置。因此,当前生成的是一个方形的草地分布。为了将随机生成的草地点改为圆形,需要额外的计算步骤。
在实际的草地生成过程中,草地会被随机地分布在区域内,但随着草地数量的增加,绘制性能会受到影响,导致帧率下降。这是因为目前的绘制方法没有优化,直接绘制的效率较低。
虽然草地开始显示出来并接近预期效果,但在数量增多时,性能下降明显。此时,帧率变慢,尽管对于当前的测试目的,性能下降是可以接受的。
为了进一步优化,需要增加草地点的多样性,以避免出现重复的明显模式,使草地看起来更加自然。虽然草地的分布开始有了效果,但为了提升质量,仍需要更多的随机性。
为了演示效果,可以先将草地的半径设为较小,草地的数量也减少,这样可以更直观地观察草地的分布效果,最终得到一个小范围的草地分布。
提供一个函数将整数转化为v2
在进行代码清理时,遇到一个常见的模式:当进行两次操作时,通常会使用系数和两个整数值进行计算。为减少重复输入,可以创建一个构造函数(或类似的函数)来简化这个过程,特别是当涉及到创建向量时。这个函数的作用是接受两个整数(例如 x
和 y
)并自动进行类型转换,从而生成一个 v2
类型的向量。这样可以避免手动输入并减少代码中的冗余。
通过这种方式,可以使代码更加简洁,提升可读性。代码的表达方式也会变得更加清晰,使得变量的使用和理解更加直观。这个小的便利函数可以有效减少代码量,并且避免在编码过程中进行过多的复制和粘贴操作。
参数化加载的位图
在这段过程中,目标是通过引入随机化来生成不同的草和石头纹理。首先,通过从随机数表中获取一个值,使用取模操作选择一个加载的位图(比如草图)。然后,通过调用相应的函数绘制该图案。这个过程通过参数化的方式使得可以加载多个不同的纹理,如草和石头,并根据随机数的不同选择性加载。
在进行这一过程中,有时遇到一些小问题。比如,在调试时发现,加载石头纹理时,屏幕上没有显示任何石头图案。经过排查,发现是由于石头图案的加载函数未能正确调用,导致没有正确加载对应的位图。通过确认加载时的位图名称和路径,以及是否正确调用了相关函数,逐步解决了这些问题。
此外,为了提高代码的简洁性和可维护性,提出了将纹理加载过程进一步参数化,避免冗余的代码,并尝试通过随机数来选择不同的纹理,增强场景中的多样性。这一过程在调试时也会遇到一些细节问题,但通过逐步排查和调整,最终实现了目标。
总结来说,这一段过程的关键在于通过随机数生成不同的纹理,增加了图形的多样性,但也面临了一些调试中的挑战,如加载函数调用不当等问题。
重新修饰
在此阶段,加载的石头纹理成功显示出来。接着,进行了进一步的改进,决定使用“tufts”(草丛或草丛的顶部)来增强纹理的细节,这种小改动可以让场景更加生动。尽管目前的地面效果还不是最精美的,但可以看到,随着开发的推进,加入更多的精细元素和图形效果后,地面会显得更加自然和有机,而不是单纯的平铺图块。
这种做法的目标是让场景看起来更加有机,避免单调的图块效果。预计随着项目的进一步发展,使用更多复杂和精致的精灵图形,场景将呈现出更具视觉吸引力的效果,从而提升整体游戏的外观和体验。
Q&A
关于自动加载dll的内容
在这一阶段,讨论了如何改进DebugLoadBMP,并提到了一些当前存在的不足,例如初始化代码没有重新执行,不能直接使用函数指针或硬编码字符串等问题。这些问题虽然存在,但并不严重,解决起来也很快。提到,当前DebugLoadBMP的问题主要是因为缺少完整的资源加载代码,导致加载过程不完全。实际上,当实现了完整的资源流加载(asset streaming)系统后,这些问题会得到解决,因为系统会自动处理资源缺失并重新加载。
最大的随机数应该设置为固定的数字100000[…],因为在第35集时你访问了random.org并选择生成从0到该数字的随机数
在讨论最大值的设定时,有人建议将最大值设置为固定数字(如1000000000)。对于这一点,有两种不同的观点。如果目标是实现一个均匀随机数生成器,那么确实应该使用随机生成范围的最大值。然而,如果目标是填充空间,那么有时可能希望随机数生成的最大值能够达到极限值。虽然在某些情况下,随机数生成器可能无法达到这个最大值,但为了能够填充空间,使用实际的最大值可能更合适。
你会实际使用更高阶的多项式插值吗?不是有更稳定的插值曲线方法吗?
在插值过程中,使用高阶多项式插值的情况取决于具体的目标。如果目标是生成一个“均匀的”插值函数,通常会使用低阶的多项式,例如三次或四次多项式,因为这些插值函数能提供平滑的过渡。然而,实际的插值问题中,常见的多项式插值方法,特别是高阶多项式插值,可能会导致不希望出现的波动(例如振荡)。
插值过程中的一个关键问题是,通过简单的高阶多项式插值来强制通过所有给定的点,可能会得到非常不稳定的结果。例如,当一个三次多项式被强行通过四个点时,得到的插值曲线可能会出现不必要的波动,导致结果不如预期的平滑曲线。
为了避免这种情况,通常需要采用更复杂的求解方法,通过加入额外的约束条件或自由度,来确保插值曲线不会出现这些不希望的波动。例如,可以使用最小二乘法等更先进的技术来近似曲线,而不是直接通过高阶多项式来解问题。这些方法能更好地保证插值的平滑性,并且能够根据预期的需求生成符合条件的插值曲线。
简而言之,虽然高阶多项式插值在某些情况下是必需的,但通常需要通过更复杂的求解方法来避免其带来的不稳定性或不规则的结果。
问:你会对地面 stamping 做什么样的优化?
对于地面印刷的优化,可以采取两种不同的策略,取决于是否运行在高性能的硬件上。在没有高加速硬件的情况下,计划使用合成缓冲区(compositing buffer)来避免每次重新进行全地面印刷。这样,只有在特定区域进入视野时才进行地面印刷,而当它们离开视野时,会丢弃不再需要的部分。具体来说,这是一个类似于平铺更新的方案,即只在需要的地方进行更新,而不是每一帧都重新印刷整个地面区域。
此外,可能会将这一过程分配到额外的线程中,以加速处理。在硬件性能更强的情况下,可以充分利用GPU的计算能力。仍然可能使用类似的合成缓冲区方案,但这次是将地面印刷操作交给GPU进行,直接渲染到一个可以重用的纹理上,避免每次都进行繁琐的计算。而一些小细节,例如地面上的小草与风的互动等,可能会在每帧中动态更新,而不进行预处理。
总的来说,会根据硬件的性能来优化地面印刷的方式,在软件渲染方案中学习并改进,同时也利用硬件的优势来实现更复杂的效果。
问:你没有对随机数的两端进行相同的处理。当前系统下你可以得到1,但永远得不到0,因为你没有考虑最小值…
在当前的随机数生成系统中,虽然可以生成最大值,但不能生成零,因为设定中已经排除了最小值。然而,针对这一点,并没有过于严格的要求。系统的目标只是让随机数生成大致有效,而不要求完美。在实际使用中,可能会实现一个更精确的随机数生成器,该生成器不会有这些限制。
为了确保能够生成包括零在内的随机数,可以调整现有的公式。具体方法是:将生成的随机数减去最小值,从而确保数值范围从零开始,然后再根据新的范围进行归一化。这种方法简单有效,但当前并不特别关注这一点,因为目前的随机数生成器只是用来避免讨论如何生成随机数的问题。
未来将讨论如何生成更为严谨的随机数,并确保生成器能够返回从零到一之间的所有浮动数值。
问:你是否计划加入像泥土小径这样的东西?
在设计地面元素时,可能会使用模板和(stamps)来绘制简单的路径,如泥土小道。不过,某些地面元素需要更复杂的逻辑处理,尤其是具有规律图案的路径(例如石板路)。简单地随机放置印章可能无法达到理想效果,因此需要更加小心地处理地面元素的绘制。
虽然最初可能会选择快速实现基本的地面效果,但如果目标是创建更精致的石板路等图案,必须更加谨慎地设计印章的使用和排列方式。在某些情况下,可能会放弃某些细节设计,专注于其他内容。
最终,虽然仍会考虑使用程序化生成方法,但可能会避免过于自由的stamps排列,而是采用更加结构化和有目的的方式来生成地面路径。
问:你的地面纹理设计本质上是MegaTexture吗?
地面纹理设计并不算是“MegaTexture”。虽然如果参考id Tech 5中的MegaTexture,它有许多特定的元素和技术,而当前的设计并没有使用这些技术。解释为什么不使用MegaTexture可能对某些人来说并不太有意义,因为MegaTexture作为一种由John Carmack提出的特殊技术,其细节并不适用于目前的需求。因此,当前的地面纹理设计与MegaTexture是不同的,尽管在某些方面可能存在相似之处。
Blackboard: MegaTexture
总结内容
讨论中提到了一种纹理管理和渲染的方案,计划与 MegaTexture 技术做对比,指出自己的方案相对简单。以下是总结的要点:
-
简单的纹理管理方案:
- 该方案使用了类似 MegaTexture 的想法,但实现方式更简单。游戏世界被划分为多个小块(可以理解为瓦片),每个小块对应一个纹理。
- 当玩家视野内的纹理块需要渲染时,首先检查这些纹理是否已经存在于缓存中。如果缓存中有,直接使用;如果没有,则生成并缓存这些纹理以便未来使用。
-
缓存管理:
- 类似于空间分区的概念,每次渲染时,首先绘制之前已经填充的区域,然后渲染新的部分。这种方式类似“脏区域”更新(dirty rect update),避免每次都重新渲染所有内容。
- 这种方法的核心思想是动态生成和填充可视区域的纹理,而无需预先生成和加载整个游戏世界的纹理。
-
与 MegaTexture 的对比:
- MegaTexture 技术采用了一个单一的巨大纹理图像覆盖整个游戏世界,通过分块(Tile)来管理这些纹理。在 MegaTexture 中,所有纹理都是存储在一个大纹理中,系统会在渲染时根据需要加载不同的区域。
- 在 MegaTexture 中,首先进行预渲染,生成一个包含所有可能纹理区域的 ID(类似标识符)图像,然后在渲染过程中根据这些 ID 查找并使用缓存中的纹理。
- 不同于上述的简单方法,MegaTexture 会使用多分辨率的缓存,即不同分辨率的纹理可以存储在缓存中,并在需要时动态加载。
-
MegaTexture 的复杂性:
- 由于 MegaTexture 是针对三维游戏设计的,它需要处理极为复杂的场景,包括远近景深、不同视角的细节层级(LOD)。因此,它能根据视距和细节需求动态调整纹理分辨率。
- 而在二维游戏中,纹理的需求较为简单,因为不会有复杂的视角切换和动态远近调整。通常游戏中的纹理分辨率是已知的,且不需要动态调整。因此,二维游戏不需要像 MegaTexture 那样复杂的多分辨率纹理缓存。
-
MegaTexture 的缺点:
- 不适合二维游戏:由于二维游戏的纹理需求较为固定,且不会像三维游戏那样需要处理不同的细节层级,因此使用 MegaTexture 的多分辨率设计显得不必要且过于复杂。
- 性能与存储问题:虽然 MegaTexture 适用于大规模的三维游戏世界,但在处理简单的二维纹理时,它的缓存和分辨率管理方式反而可能造成不必要的性能消耗。
-
结论:
- 尽管 MegaTexture 是一个强大的技术,尤其在处理复杂的三维游戏环境时具有优势,但对于二维游戏,使用类似 MegaTexture 的复杂设计方案并不合适。二维游戏的纹理管理方式可以更简单且高效,避免过度的复杂化。
相关文章:
游戏引擎学习第81天
仓库:https://gitee.com/mrxiao_com/2d_game_2 或许我们应该尝试在地面上添加一些绘图 在这段时间的工作中,讨论了如何改进地面渲染的问题。虽然之前并没有专注于渲染部分,因为当时主要的工作重心不在这里,但在实现过程中,发现地…...
网络安全 | 什么是正向代理和反向代理?
关注:CodingTechWork 引言 在现代网络架构中,代理服务器扮演着重要的角色。它们在客户端和服务器之间充当中介,帮助管理、保护和优化数据流。根据代理的工作方向和用途,代理服务器可分为正向代理和反向代理。本文将深入探讨这两种…...
前缀和——模板 二维前缀和
一.题目描述 【模板】二维前缀和_牛客题霸_牛客网 二.题目解析 这道题和上一道题有点异曲同工之妙。输入一个m行n列的矩阵,然后进行q次操作,每次操作输入4个数,作为两个点的坐标,计算这两个点为对角线的矩阵的和。 三.算法原理 …...
oracle使用case when报错ORA-12704字符集不匹配原因分析及解决方法
问题概述 使用oracle的case when函数时,报错提示ORA-12704字符集不匹配,如下图,接下来分析报错原因并提出解决方法。 样例演示 现在有一个TESTTABLE表,本表包含的字段如下图所示,COL01字段是NVARCHAR2类型࿰…...
高等数学学习笔记 ☞ 定积分与积分公式
1. 定积分的基本概念 1.1 定积分的定义 1. 定义:设函数在闭区间上有界。在闭区间上任意插入若干个分点,即, 此时每个小区间的长度记作(不一定是等分的)。然后在每个小区间上任意取,对应的函数值为。 为保证每段的值(即矩形面积)无…...
MLMs之Agent:Phidata的简介、安装和使用方法、案例应用之详细攻略
MLMs之Agent:Phidata的简介、安装和使用方法、案例应用之详细攻略 目录 Phidata简介 Phidata安装和使用方法 1、安装 2、使用方法 (1)、认证 (2)、创建 Agent (3)、运行 Agent (4)、Agent Playground Phidata 案例应用 1、多工具 Agent 2、多模态 Agent …...
如何在不暴露MinIO地址的情况下,用Spring Boot与KKFileView实现文件预览
在现代Web应用中,文件预览是一项常见且重要的功能。它允许用户在不上传或下载文件的情况下,直接在浏览器中查看文件内容。然而,直接将文件存储服务(如MinIO)暴露给前端可能会带来安全风险。本文将介绍如何在不暴露MinI…...
ESP8266固件烧录
一、烧录原理 1、引脚布局 2、引脚定义 3、尺寸封装 4、环境要求 5、接线方式 ESP8266系列模块集成了高速GPI0和外围接口,这可能会导致严重的开关噪声。如果某些应用需要高功率和EMI特性,建议在数字I/0线上串联10到100欧姆。这可以在切换电源时抑制过冲…...
Python 模拟真人鼠标轨迹算法 - 防止游戏检测
一.简介 鼠标轨迹算法是一种模拟人类鼠标操作的程序,它能够模拟出自然而真实的鼠标移动路径。 鼠标轨迹算法的底层实现采用C/C语言,原因在于C/C提供了高性能的执行能力和直接访问操作系统底层资源的能力。 鼠标轨迹算法具有以下优势: 模拟…...
三天急速通关Java基础知识:Day1 基本语法
三天急速通关JAVA基础知识:Day1 基本语法 0 文章说明1 关键字 Keywords2 注释 Comments2.1 单行注释2.2 多行注释2.3 文档注释 3 数据类型 Data Types3.1 基本数据类型3.2 引用数据类型 4 变量与常量 Variables and Constant5 运算符 Operators6 字符串 String7 输入…...
免费使用 Adobe 和 JetBrains 软件的秘密
今天想和大家聊聊如何利用 Edu 教育邮箱免费使用 Photoshop、Illustrator 等 Adobe 系列软件,以及 JetBrains 开发工具。 首先,Adobe 的软件是设计师的必备工具。无论是处理图像的 Photoshop,还是进行矢量设计的 Illustrator,它们…...
Pytorch 自学笔记(三):利用自定义文本数据集构建Dataset和DataLoader
Pytorch 自学笔记(三) 1. Dataset与DataLoader1.1 torch.utils.data.Dataset1.2 torch.utils.data.DataLoader Pytorch 自学笔记系列的第三篇。针对Pytorch的Dataset和DataLoader进行简单的介绍,同时,介绍如何使用自定义文本数据集…...
gradle项目的创建和基本结构简介
文章目录 创建gradle项目(命令行)创建gradle项目(IDEA)项目基本结构和功能Gradle 构建流程测试类体验 创建gradle项目(命令行) yangMacdeMac-mini gradleStudy % gradle init Starting a Gradle Daemon (s…...
wow-agent---Day3 Zigent 智能代理开发框架
这个框架是课程讲解的,但资料比较少,觉得框架比较小众,所以这里只分析代码,打算把更多的精力放在metagpt的学习上,毕竟还是要学教为主流的框架,这对后续维护升级都有帮助,当然感兴趣作为研究&am…...
python 入门
1. Python 概述 1.1 简介 python 是一种面向对象的解释型编程语言,由吉多范罗苏姆开发; 1991 年,公开发行版发布; 因其可以将其他语言制作的模块轻松联接在一起,又被称作胶水语言; 1.2 优点 简单易学&…...
sentinel微服务保护
学习链接 SpringCloudRabbitMQDockerRedis搜索分布式 文章目录 学习链接1.初识Sentinel1.1.雪崩问题及解决方案1.1.1.雪崩问题1.1.2.超时处理1.1.3.仓壁模式1.1.4.断路器1.1.5.限流1.1.6.总结 1.2.服务保护技术对比1.3.Sentinel介绍和安装1.3.1.初识Sentinel官网地址github地址…...
接口测试Day10-封装IHRM登录
-登录接口 普通方式实现 登录接口对象层 思路: 动态变化的,写入参数固定不变,直接写到方法实现内响应结果,通过返回值 return 分析: 封装实现: 登录接口测试用例层 封装断言方法 1、创建 文件 assert_uti…...
什么是IP地址、子网掩码、网关、DNS
简单解释 IP地址在网络中用于标识一个节点(或者网络设备的接口) IP地址用于IP报文在网络中的寻址 一个IPv4地址有32 bit。 IPv4地址通常采用“点分十进制”表示。 IPv4地址范围:0.0.0.0~255.255.255.255 网络部分:用来标识一个网络,代表IP地址所属网络。 主机部分:…...
python编程-OpenCV(图像读写-图像处理-图像滤波-角点检测-边缘检测)角点检测
角点检测(Corner Detection)是计算机视觉和图像处理中重要的步骤,主要用于提取图像中的关键特征,以便进行后续的任务,比如图像匹配、物体识别、运动跟踪等。下面介绍几种常用的角点检测方法及其应用。 1. Harris角点检…...
软路由系统iStoreOS 一键安装 docker compose
一键安装命令 大家好!今天我来分享一个快速安装 docker-compose 的方法。以下是我常用的命令,当前版本是 V2.32.4。如果你需要最新版本,可以查看获取docker compose最新版本号 部分,获取最新版本号后替换命令中的版本号即可。 w…...
Invicti-Professional-V25.1
01 更新介绍 此更新包括对内部代理的更改。内部扫描代理的当前版本为 25.1.0。内部身份验证验证程序代理的当前版本为 25.1.0。#新功能现在,单击扫描摘要屏幕中的预设扫描图标会将您重定向到具有过滤视图的 “最近扫描” 页面,从而改进导航和对相关扫描…...
【QT】: 初识 QWidget 控件 | QWidget 核心属性(API) | qrc 文件
🔥 目录 1. 控件概述 控件体系的发展阶段 2. QWidget 核心属性 2.1 核心属性概览2.2 用件可用(Enabled) 2.3 坐标系(Geometry) **实例 1: 控制按钮的位置**实例 2: 表白 程序 2.4 窗口标题(windowTiltle&a…...
Spring WebFlux
文章目录 一、概述1、Spring体系定位2、Spring MVC和WebFlux差异 二、入门1、依赖2、ReactorHttpHandlerAdapter(main启动)3、DispatcherHandler(SpringWebFlux启动)4、WebFilter 三、DispatcherHandler理解1、handle 前置知识&am…...
【AI | pytorch】torch.polar的使用
一、torch.polar的使用 torch.polar 是 PyTorch 中用来生成复数张量的一个函数,但它与数学中的复数表达式 ( z re^{i\theta} ) 是等价的。 具体来说,torch.polar(abs, angle) 接受两个实数张量参数: abs:表示复数的模长&#…...
AWTK fscript 中的 输入/出流 扩展函数
fscript 是 AWTK 内置的脚本引擎,开发者可以在 UI XML 文件中直接嵌入 fscript 脚本,提高开发效率。本文介绍一下 fscript 中的 iostream 扩展函数 1.iostream_get_istream 获取输入流对象。 原型 iostream_get_istream(iostream) > object示例 va…...
【多线程】线程池
一、什么是线程池 线程池(Thread Pool)是一种多线程并发执行的设计模式,它通过维护一个线程集合来执行多个任务,避免频繁地创建和销毁线程,提高系统性能和响应速度。 就好比如你经营了一家餐饮店,你名下有…...
小结:路由器配置和管理 RIP协议
华为路由器中配置和管理 RIP(Routing Information Protocol)的相关指令主要分为以下几个部分:基础配置指令、接口配置指令、路由控制指令和调试指令。以下是总结: 1. 启用 RIP 协议 [Huawei] rip 1rip 1:表示创建并启…...
基于海思soc的智能产品开发(高、中、低soc、以及和fpga的搭配)
【 声明:版权所有,欢迎转载,请勿用于商业用途。 联系信箱:feixiaoxing 163.com】 市场上关于图像、音频的soc其实非常多,这里面有高、中、低档,开发方式也不相同。之所以会这样,有价格的因素&am…...
于灵动的变量变幻间:函数与计算逻辑的浪漫交织(下)
大家好啊,我是小象٩(๑ω๑)۶ 我的博客:Xiao Xiangζั͡ޓއއ 很高兴见到大家,希望能够和大家一起交流学习,共同进步。 这一节我们主要来学习单个函数的声明与定义,static和extern… 这里写目录标题 一、单个函数…...
偷偷的学Java
序章:为何要偷偷学Java? • Java,不仅仅是一种编程语言 • 偷偷学Java,快速提升你的竞争力 •Java学习秘籍 第一章:Java的神秘面纱 •Java的起源与发展历程 •Java的生态系统与应用场景 • Java与其他编程语言的…...
以单用户模式启动 Linux 的方法
注:本文为 “Linux 启动单用户模式” 相关文章合辑。 未整理去重。 以单用户模式启动 linux 的三种方法 作者: Magesh Maruthamuthu 译者: LCTT Xiaobin.Liu 2020-05-03 23:01 单用户模式,也被称为维护模式,超级用户…...
【AI论文】生成式视频模型是否通过观看视频学习物理原理?
摘要:AI视频生成领域正经历一场革命,其质量和真实感在迅速提升。这些进步引发了一场激烈的科学辩论:视频模型是否学习了能够发现物理定律的“世界模型”,或者,它们仅仅是复杂的像素预测器,能够在不理解现实…...
【有啥问啥】Contrastive Captioners(CoCa):对比式图像描述模型——图像-文本基础模型的新范式
Contrastive Captioners(CoCa):对比式图像描述模型——图像-文本基础模型的新范式 引言 随着深度学习技术的发展,多模态模型在处理视觉和语言任务方面的能力逐渐增强。特别是大规模预训练模型的兴起,使得这些模型可以快速迁移到许多下游任务…...
Python(十七)excel指定列自动翻译成英文
前言 本章主要讲述在excel的指定列后面添加一列,并翻译成英文 一、效果图 二、代码 实际需求: # -*- codeing utf-8 -*- # time: 2025/1/16 16:32 # Author : Mikasa # # Aim:自动将客户发的货物清单里的商品名称,翻译成英文…...
【论文投稿】探秘计算机视觉算法:开启智能视觉新时代
目录 引言 一、计算机视觉算法基石:图像基础与预处理 二、特征提取:视觉信息的精华萃取 三、目标检测:从图像中精准定位目标 四、图像分类:识别图像所属类别 五、语义分割:理解图像的像素级语义 六、计算机视觉…...
【机器学习实战入门】使用LSTM机器学习预测股票价格
机器学习在股票价格预测中有重要的应用。在这个机器学习项目中,我们将讨论如何预测股票的收益。这是一个非常复杂的任务,充满了不确定性。我们将会把这个项目分成两部分进行开发: 首先,我们将学习如何使用 LSTM 神经网络预测股票…...
(一)相机标定——四大坐标系的介绍、对应转换、畸变原理以及OpenCV完整代码实战(C++版)
一、四大坐标系介绍 1,世界坐标系 从这个世界(world)的视角来看物体 世界坐标系是3D空间坐标,每个点的位置用 ( X w , Y w , Z w ) (X_w,Y_w,Z_w) (Xw,Yw,Zw)表示 2,相机坐标系 相机本身具有一个坐标系&…...
Bootstrap 下拉菜单
Bootstrap 下拉菜单 Bootstrap 是一个流行的前端框架,它提供了许多预构建的组件,其中之一就是下拉菜单。下拉菜单是一个交互式元素,允许用户从一系列选项中选择一个。在本篇文章中,我们将详细介绍如何在 Bootstrap 中创建和使用下…...
WinHttp API接口辅助类实现GET POST网络通讯
1、简述 近期需要在MFC基础上开发网络Http通讯,开始使用的WinINet进行通讯,后面发现WinINet对连接超时这块不支持设置,在网上搜索了几种方式效果都不太好,于是决定用WinHttp API接口进行通讯,分别对GET、POST进行了封装。 2、使用到接口 2.1、WinHttpOpen WinHttpOpen 是…...
Elasticsearch实战应用
嘿,小伙伴们,今天咱们来唠唠Elasticsearch,这可是个超厉害的搜索引擎,能帮你在海量数据里快速找到想要的东西,就像给你的数据装上了“放大镜”。 一、啥是Elasticsearch 简单来说,Elasticsearch就是一个基…...
MySQL存储过程
存储过程: 事先经过编译并存储在数据库中的一段sql语句的集合,调用存储过程可以简化应用开发人员的很多工作,减少数据在数据库和应用服务器之间的传输,对于提高数据处理的效率是有好处的,思想上就是sql语言层面的代码封装与重用 …...
安路FPGA开发工具TD:问题解决办法 及 Tips 总结
安路科技(Anlogic)是一家专注于高性能、低功耗可编程逻辑器件(FPGA)设计和生产的公司。其提供的开发工具TD(TangDynasty)是专门为安路FPGA系列产品设计的集成开发环境(IDE)。以下是对…...
高精度阶乘C++实现
高精度计算,实际上就是模拟竖式计算,代码如下,请慢慢消化,如有不足或建议,请在评论区留言 这个阶乘操作实际上就是高精度乘法的运用,可以非常容易的在考场上写出来 #include <bits/stdc.h> using na…...
PageHelper快速使用
依赖 <!--分页插件PageHelper--> <dependency><groupId>com.github.pagehelper</groupId><artifactId>pagehelper-spring-boot-starter</artifactId><version>1.4.7</version> </dependency>示例 /** * 封装分页结果…...
“AI 辅助决策系统:决策路上的智慧领航员
在当今瞬息万变的时代,无论是企业的运营管理,还是个人在生活中的重大抉择,都需要精准、高效的决策。然而,信息的繁杂和未来的不确定性,常常让决策变得困难重重。这时,AI 辅助决策系统宛如一位智慧的领航员&…...
[Linux] linux 系统中如何添加自动启动程序
背景:在嵌入式系统中,需要开机自动启动所编写的程序【可执行文件】。 解决方法:原理就是Linux开机会自动执行一些文件。在/etc/profile中添加执行程序的脚本。/etc/profile 是一个系统级的配置文件,在用户登录Linux系统时自动执行…...
Linux之网络套接字
Linux之网络套接字 一.IP地址和端口号二.TCP和UDP协议2.1网络字节序 三.socket编程的常见API四.模拟实现UDP服务器和客户端五.模拟实现TCP服务器和客户端 一.IP地址和端口号 在了解了网络相关的基础知识之后我们知道了数据在计算机中传输的流程并且发现IP地址在其中占据了确定…...
LeetCode 2266.统计打字方案数:排列组合
【LetMeFly】2266.统计打字方案数:排列组合 力扣题目链接:https://leetcode.cn/problems/count-number-of-texts/ Alice 在给 Bob 用手机打字。数字到字母的 对应 如下图所示。 为了 打出 一个字母,Alice 需要 按 对应字母 i 次,…...
Jmeter 动态参数压力测试时间段预定接口
🎯 本文档详细介绍了如何使用Apache JMeter进行压力测试,以评估预定接口在高并发场景下的性能表现。通过创建线程组模拟不同数量的用户并发请求,利用CSV文件动态配置时间段ID和用户token,确保了测试数据的真实性和有效性。文档中还…...
Learning Prompt
说明:这是我的学习笔记,很多内容转自网络,请查阅文章末尾的参考资料。 目录 基本要求(C.R.E.A.T.E)总结文章(Summarise)改写文章(Rewrite)根据参考资料回答问题(Question & Answer)参考资料 基本要求(C.R.E.A.T.E) Character This is th…...