欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 房产 > 建筑 > 游戏引擎学习第173天

游戏引擎学习第173天

2025/3/22 13:18:06 来源:https://blog.csdn.net/TM1695648164/article/details/146429323  浏览:    关键词:游戏引擎学习第173天

今天的总结和计划

今天我们将继续昨天和前几天的工作,基本上已经完成了字体支持的功能,我们成功地把字体功能加入了游戏中,包括字距调整等基本功能。然而,我觉得整体还没有完全完成,感觉还有一些地方没有完全打理好,尤其是在定位和细节方面,代码还有一些“垃圾”需要清理。因此,我计划今天花时间对这些部分进行整理,确保一切都清理干净。

此外,我还想确保我们有一个合理的方案来支持多语言。目前,我们虽然支持任意Unicode代码点,可以在游戏中显示多个字符,但仍然存在一些限制。这些限制其实并不是必需的,我们完全可以去掉它们,不会带来太多麻烦。所以,我计划今天开始着手处理这些问题,花接下来的几天时间逐步清理和完善,直到觉得一切都很顺利。

回顾之前内容

回顾一下我们上次停下的地方,简单来说,我们刚刚完成了整个流程的工作,包括从资源打包器到游戏中的字体元数据的整个过程。现在我们可以做像字距调整(kerning)这样的事情了。

此外,我们还加入了行高设置,现在你会注意到这些行之间的距离是正确的。

第一行应该从屏幕的顶部下一行开始

有几件事我们还没有完成,其中之一是在游戏界面中,第一行的文本显示位置偏离了屏幕的顶部。原因是我们还没有编写正确的代码来处理文本的定位,这与字体本身无关。问题仅仅是我们在调试过程中使用的测试代码没有做得足够智能。我们目前看到的显示有些不正确,这其实与我们想要呈现的内容没有关系。
在这里插入图片描述

我们要做的是确保从Y轴的基线开始正确定位文本,因此第一步是调整代码,将文本的起始位置设置为正确的Y坐标。这将使得文本能够从预期的起始位置开始显示。

接下来,我们还需要考虑一些细节,像是字体缩放等,这些是基础设施部分的一部分。需要在代码中初始化一些参数,确保它们可以合理地开始运行。通过这样做,我们可以确保代码能够按预期工作,而无需在此时做过多调整。

同时,我们还要确保调试功能能够顺利地访问到需要的字体信息。因此,我们需要让调试功能知道游戏资源的位置,这样它才能正确加载字体。

最终,为了适应这种变化,我们可能还需要调整调试代码中的字体ID。为了简化处理,暂时将其命名为“FontID”即可,稍后可以根据需要做进一步的调整。
在这里插入图片描述

我们希望能够在不加载字体的情况下访问行间距信息

我们已经做出了一个决定,之前对于一些问题有过犹豫,但现在似乎得出了答案。我们不希望依赖某种加载时间的机制来获取信息,而是希望这个信息始终可以直接获得。这样做的目的是为了能够方便地进行重置操作等。这也意味着,我们需要确保信息在操作中始终可用,而不是依赖某些临时的状态或延迟加载。

考虑到这一点,我们更倾向于直接获取这些信息,而不是通过传递思考来实现,这样可以避免任何可能的随机性,确保信息的稳定性和可依赖性。通过这种方式,我们可以确保信息在每个阶段始终都是可用的,不会有不确定的情况。

这种方法的一个好处是,它提供了一种更可靠的方式来处理信息,不会因为外部因素的影响而产生波动。因此,决定采取这种直接获取和操作信息的方式,让每次游戏的状态都保持一致、清晰。
在这里插入图片描述

在这里插入图片描述

布局还不正确

目前的状态应该已经有所改善,特别是在替换方面,但实际上似乎并不是完全如此。某些距离的差异显得有些过大,这就说明可能出现了问题。我们决定仔细看看发生了什么。

具体来说,在y轴等于“FontScale”乘以“GetLineAdvanceFor”的位置时,应该是直接反映出“GetLineAdvanceFor”的值。所以这时候,y值应该是用当前的y来计算的。接着,应该从中减去“GetLineAdvanceFor(FontInfo)“ 再乘以一个常数,结果应该只是下移了相应的量。
在这里插入图片描述

问题可能出现在基准线的对齐上,这也许是导致偏差的根源。需要检查是否在这部分出了问题,尤其是基准线的处理方式,因为这种情况看起来有些不对劲。
当前的表现有点不正常,甚至有点不清楚发生了什么。在尝试了设置y为0后,结果却并没有达到预期,显示出了异常。这表明可能在设置过程中出现了不符合预期的情况,需要进一步排查。
在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

Y零坐标应位于屏幕中心,而不是边缘

原来问题出在了坐标系的起点上。零的位置应该是屏幕的中心,而不是角落。实际的目标是从屏幕的顶部开始,然后向下移动一行。
因此,应该从屏幕的顶部开始,而不是从中心开始。零零点应该是在屏幕的中心,而不是角落,这是一个关键的理解差异。所以,调整思路后,我们应该从屏幕的顶部起始,按照一行一行地往下走。
在这里插入图片描述

在这里插入图片描述

测试一个单词中的多个字形大小

现在,经过一番努力,情况终于有所好转,至少没有再犯明显的错误,这已经是个好消息。可以看出,现在即使在句子中间改变元素的大小,所有的计算和逻辑依然可以正常运作,效果是正确的。我们可以放心地说,字体的处理在一定程度上变得更加可靠,至少对于一些复杂的操作来说,现在可以正常工作了。

如果需要进一步调整字体的大小,甚至是频繁地进行更改,这也是可以做到的。比如,我们可以设置不同的字体大小,像是从1变成5,再变成3,再变成9,甚至再变成2、7等。这种操作现在也能正常进行,理论上不应该出问题。

然而,做完这些后,发现了一个有趣的问题。假如我们需要支持这种动态变化的字体大小,可能还需要做进一步的调整和优化。
在这里插入图片描述

在这里插入图片描述

我们没有必要的信息来进行不同大小字符之间的字距调整

我们还需要做一件事,那就是必须将字符的“破坏”分开处理,因为如果两个字母的大小不同,当前的格式可能会发生变化,这样就变得比较复杂了。我们不确定操作系统是否提供了足够的信息来正确处理这种情况。

为了更好地理解这个问题,需要画出当前的情况,因为这件事值得我们深思。通过图示,可以更清晰地看到当前的问题和如何解决它。

(黑板)问题说明

如果我们开始时使用一个很小的字母,然后切换到一个很大的字母,那么在这种情况下,我们应该使用哪个字母的字形?如果按照字母本身的形状来决定,因为记住当前我们获得的值是相同的,但由于字母的大小不同,这个值应该如何解释呢?我们是否应该按第一个字母的比例来解释,还是按照第二个字母的比例来解释?

如果按第一个字母的比例来解释,结果会导致字母之间重叠过多,因为间距会太小;如果按第二个字母的比例来解释,又会导致字母之间有一个巨大的空隙。所以,这里就出现了一个问题:我们缺乏必要的信息来正确处理这种情况。

在这种情况下,字形的调整应该变得更加程序化,特别是当考虑到字母的对齐问题时。例如,如果我们把一个小写字母“c”和一个大写字母“t”放在一起,假如把“t”缩小到与“c”的顶部对齐,那么它们之间的距离就会变得更远,因为它们不能重叠,否则会相互碰撞。

这意味着,某些情况下,我们可能不能在一个单词内自由地改变字符的对齐,因为我们没有足够的信息来确保它们之间的正确间距。虽然我们可以尝试自己编写一个训练系统来支持这种情况,但使用当前操作系统提供的信息,我们发现并没有办法做到这一点。任何相邻的两个字母必须使用相同的字体对齐方式。

因此,尽管希望能够实现这种复杂的字形调整,但从目前的角度来看,我们无法做到这一点,至少无法做到既可靠又精准。这个限制来自于字体渲染系统,特别是Windows的字形处理方式,我们无法对其进行更改。虽然有些人可能会尝试编写自己的字体渲染系统,但这显然需要投入大量的工作,并且超出了目前的范围。

然而,虽然在这个问题上无法做出改进,但还有一些方面是我们可以改进的。这些问题虽然有限,但至少我们可以从中找到可操作的解决方案。

我们的字距调整表格没有指定在没有前导字符时的初始水平偏移量

首先,出现的这个巨大的空白到底是怎么来的呢?这个问题的原因在于,当前的间距表没有被初始化好,无法正确处理当一个字母后面没有其他字母时的情况。默认情况下,当字母后面没有其他字母时,系统会使用一个通用的宽度,这就是导致空白出现的原因。

为了解决这个问题,我们需要对间距表进行调整,确保当前一个字符是“零字符”时(即没有其他字符跟随时),我们不进行任何的前进间距。这是因为,初始化时,字符间的对齐从“零字符”开始,因此需要特别处理这个情况。

在调试时,我们会发现,如果删除了这种初始化的设置,程序就会从屏幕的左边缘开始,并且按计划继续执行。但问题出在,当程序请求计算当前字符与前一个字符之间的水平间距时,由于没有前一个字符,相关的间距信息为零。此时,程序会查找间距表,但表中没有有意义的值,因为我们没有对该值进行初始化。

因此,这个空白问题实际上是由于没有正确处理初始化导致的,需要对间距表进行适当的设置,确保在没有前一个字符的情况下不会错误地使用默认的间距。
在这里插入图片描述

在资产打包器中对空字符进行特殊处理

回过头来看,比如我们检查一下测试资源打包器,当我们处理字符间距表时,可以做一些调整。具体来说,在处理当前字符对时,可以开始特别处理第一个字符对,尤其是当第一个字符是空字符(null)时。初始化这些间距表时,如果遇到第一个字符对是空字符,我们就要做一些特别处理。

一种做法是,在开始时对空字符做特殊处理,比如设定初始宽度为零。如果字符的索引大于零,或者不等于零时,则可以用实际的宽度来填充。这将确保在处理这种特殊情况时,能够正确初始化并避免空字符导致的错误。

这种方法是相对简单且有效的解决方案,可以确保字符间距表能正确初始化,从而避免出现不期望的空白或不正确的间距。这样做可以很好地解决之前出现的问题。

然而,实际运行时并没有达到预期的效果,可能是存在其他未发现的潜在问题。
在这里插入图片描述

在这里插入图片描述

字符仍然无法对齐左边和上边缘

现在的情况已经接近预期了,字符对在左边缘对齐,至少在很大程度上是对齐的。不过,仍然有一点空白存在,而这个空白并不理想。如果我们明确告诉系统希望字符能直接与左边缘对齐,那么应该实现这一目标。

虽然如果我们并不特别关心排版细节,可能不会太在意这种微小的偏差,但为了讨论这个问题,至少需要理解为什么会发生这种情况。实际上,这种空白的存在是可以理解的,背后有一些原因需要考虑。在讨论这个问题时,了解发生的原因有助于找到合适的解决方案。

通过查看字体的升降头对齐顶部边缘

接下来需要解决的一个问题是大间隙的问题。这个问题的根源在于当前的行进距离(line advance)是基于基线到基线的距离计算的,但这并没有告诉我们字体的顶部位置在哪里。如果希望字体的顶部对齐,那么就会遇到困难。

为了解决这个问题,需要存储额外的元数据,特别是关于字体实际高度的信息。这些信息已经存在,但我们之前选择没有存储。通过存储这些数据,可以让我们在需要时使用字体的实际高度,而不是行进距离(line advance)。这会让问题变得更简单,能够更精确地处理对齐问题。

具体来说,需要将字体的高度(包括上升高度和下降高度)存储为两个单独的值,并且在计算时分别使用。这样,系统就可以更灵活地处理垂直定位问题。通过这种方式,可以将基线、字体总高度、或者其他感兴趣的位置精确对齐。

另外,还需要添加一些额外的功能来获取基线的位置,这样就可以根据需要调整基线或其他位置。具体实现时,应该避免使用之前的行进距离,而是基于新的高度数据进行定位。这样就能更灵活地处理字体排版,避免出现不一致或不准确的对齐问题。

在修改时,发现了一个问题,原本存储数据的位置不对,应该将其存储在正确的位置。经过调整后,问题得到了解决,测试结果也变得更加理想了。
在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

字符仍然没有对齐顶部边缘,但这是因为字体包含比我们正在显示的字形更高的字形

现在看起来情况有所改善,尽管字体并没有完全对齐,这一点有些奇怪。可能这就是正确的情况,原因是目前并不清楚字符映射是否包括了这个空间。例如,假设字符映射中包含了字体上方的空白区域,可能会导致这种看似不对齐的现象。

具体来说,观察到的字体可能是一个带有额外空白的字母形状,像是字母 “a” 和带有上方附加空间的字母 “a” 看起来几乎一样。因此,推测这个空白区域是为了放置附加符号(如重音符号等)而预留的空间。

从技术角度来说,这种情况可能是正确的,但并不确定。如果要更加精确地对齐,可能需要手动测量所有字符的高度,然后调整值,确保字符的顶部与基线对齐,底部也符合要求。这种方法虽然可以做到精确对齐,但它并不完全使用字体的原始数据,而是基于我们观察到的内容来调整。

不过,目前决定暂时保留现状,意识到这个问题的存在并在以后决定是否调整。如果后续觉得不合适,移除这个设置也并不难。因此,暂时将此视为一个已知问题,留待后续可能的调整。

将文本与左边缘对齐,处理行距空间并合并到字距调整中

另一个需要考虑的问题是字符的对齐方式。即使我们要求字符直接对齐到屏幕的左边缘,实际情况是它们并没有完全对齐。出现这种情况的原因是由于之前提到的字形宽度(a, b, c 宽度)问题。我们选择将字符的偏移量作为这些宽度的一部分,这样做的结果就是当我们尝试把字符放置在左边缘时,它实际上被偏移了这部分宽度。

因此,考虑到这一点,我认为我们可能需要将这个偏移量重新纳入到字符间距表(kerning table)中,而不是现在的做法。我们可以选择在字符间距表中处理这一问题,这样字符在显示时会始终与左边缘对齐,而字形的宽度(a, b, c 宽度)则会以不同的方式处理。

具体来说,现在我们在计算时使用了一个偏移值,但我们更倾向于把这个偏移值放入字符间距表里。这样做的挑战在于,我们需要先处理所有字符,而当前我们并没有在处理字符之前就进行这种调整。不过,我觉得有一个相对简单的办法可以绕过这个问题,那就是先对所有字符进行处理,再进行其他操作。

在处理字体之前先处理字符,以便获取必要的信息

通过确保字体列表总是在字体渲染之前,这样就能解决当前的问题。原因是现在的水平推进表在某个资产类型中,顺序在字体字形之前,因此它可能不会按照我们想要的顺序处理。这是因为我们添加它们的方式,导致它们以这样的顺序被写入。
在这里插入图片描述

如果我们查看水平推进的部分,假设我们希望调整它的顺序,其实可以将这个顺序调换,这样问题就能解决。不过,这样做有点不太优雅,因为必须确保每次处理时都要保持顺序正确。

如果我们决定按照这种方式进行调整,那么这意味着字形的最小x值和偏移量将不再被固定在对齐过程中,而是从对齐中分离出来,直接移入到字符间距(kerning)处理里。如果查看字符间距的部分,它会变成这样,水平推进的计算就会包括这个偏移量,我们可以对整个字符表进行处理,遍历每个字符的代码点,并根据调整后的值进行修正。

为此,我们首先需要计算出所需的调整量,这样我们就能够移动字形的正确位置。这个计算过程需要考虑到字符的最小x值和偏移量。如果我们需要将字形从前一个字符的末尾位置移动到正确的位置,应该根据这些调整来进行修正。

尽管一开始这个过程看起来有点复杂,但调整后的结果会更精确,字形能够正确地与左边缘对齐,看起来几乎完全准确。接下来可以查看字符间距的效果,确保它符合预期,并且可能还需要与其他标准进行比较,确保没有遗漏任何细节。

最终,通过调整字符间距和处理顺序,字形和字符的对齐得到了有效的修正,显示效果接近完美,虽然仍有一些细节可以进一步优化。
在这里插入图片描述

在这里插入图片描述

比较字距调整

通过将字符对齐后,发现字形的大小不对,看起来比预期的要大,这表明字符间距(kerning)存在问题。问题的原因可能是字符位置被错误地偏移了,这表明之前对字符间距的理解是错误的。经过检查,确认之前假设需要反转字符间距的推测是正确的,所以现在打算尝试调整,看看能否修正。

不过,在调整后,仍然发现字形的位置看起来不对,意味着还有其他问题没有解决。因为存在额外的错误,这反而让我松了一口气,因为这说明之前的困惑并非完全源自错误的推测,而是另一个问题导致的错误。

现在最重要的是确认并解决这个新发现的问题。虽然调整字符间距的过程有些曲折,但最终如果能够解决所有问题,那么就可以继续进行进一步的优化,甚至可能会进一步调查这个问题的根源。如果发现问题的原因并非自己之前的推测错误,而是由于其他代码bug,反而能更好地进行修复和优化。

ABC字形的“A”已经包含在水平字形推进中

通过检查水平间距时,发现了问题。原本应该包含的This->abcA(即某个宽度值)不再需要包括,因为它已经在其他步骤中被移除了。因此,初始化这个表格时,应该只包括字形的bc宽度,而不是宽度的整体值。

现在应该将宽度从其他步骤中提取出来,而不是在这里直接使用,这样做更加合理。

同时,注意到一个问题,就是资产构建(asset builds)没有自动更新,这可能导致一些不便。虽然目前这样做是可行的,但考虑到未来可能需要进行频繁更新,应该思考是否需要实现自动更新的机制,尤其是在完成项目时,自动更新的功能将会更为便捷。
在这里插入图片描述

字距调整仍然不完全正确

目前来看,情况仍然有些不对,虽然空间变得更加宽敞,但相比参考值,字符排列还是不完全正确。到目前为止,整体的效果已经有了很大的改进,看起来差不多了,但是当遇到某些特定字符(例如a)时,问题依然存在。这些字符有些细节没有正确对齐,因此需要进一步调整。

目前的状况已经比之前有所好转,但显然仍然存在一些细节问题,特别是在处理字符时,依然有一些误差。因此,还需要继续调整,逐步完善,直到能准确对齐并与参考效果一致。

使用我们自己的字符宽度测量,而不是ABC字形的“B”

考虑到当前的情况,可能的一个解决方案是放弃使用ABC宽度,而仅仅使用C宽度来进行调整。具体来说,可以从实际字符的宽度中计算B宽度,这样就能在构建字形表时更加精确。在这种情况下,可以将最大X坐标减去前置步长,计算出字符需要移动的距离,从而精确地调整字符的位置。

目前的想法是,可能通过仅使用C宽度来处理,而将总宽度作为前进步长。这种做法可能比Windows的字形处理方式要好,尽管Windows的字形对齐并不是很理想,因此对于能够超越Windows的处理方式并不太担心。

另外,有点奇怪的是,Windows在字形中给定的C宽度与实际字形内容之间的差异非常大,特别是在B宽度部分,这显得非常不合常理,导致目前的字形处理方式需要进一步改进和调整。

在这里插入图片描述

在这里插入图片描述

继续调试

在当前的调试过程中,发现了一些问题,特别是字形的对齐没有完全符合预期。考虑到这一点,决定回退到之前的方式,通过检查最小X坐标减去前置步长来计算需要移动的距离,然后更新当前的字符信息。此外,还计划在资产构建器中重新查看和调整字符宽度,以确保这些调整得到正确应用。

然而,问题出现在Windows的字符处理方式上,Windows不允许直接获得字符的左边界,这使得在使用Windows的字形数据时,无法简单地对齐字符。因此,打算尝试其他方法,将所有的字符数据同时处理,并重新考虑如何根据当前的字符宽度和预定的对齐方式进行调整。

为了更好地控制字形对齐,考虑先将所有水平数组清零,然后将已知的字符按照其当前的标准填充到数组中,再进行进一步的调整。这个过程需要使用已知的字符宽度(如ABC宽度)来帮助计算。

尝试了将ABC宽度应用到当前的计算中,但发现结果依然不符合预期。特别是在计算时,发现可能忽略了某些空白区域,导致宽度计算不准确。这一系列问题导致字形的间距仍然异常,无法正确对齐。

接下来,计划简化操作,暂时不更新字形表,仅仅将所有字符对齐在一起,以确认是否存在更基础的错误。在排除复杂的调整步骤后,字形依然显示出不合理的小间距,意味着计算中可能仍然存在某些未发现的bug。

综上所述,当前主要问题在于字形间距计算的不一致,可能是由于忽略了某些空白区域或字符的预定宽度计算不准确,导致字符位置没有正确对齐。
在这里插入图片描述

在这里插入图片描述

检查ABC字形的文档

在当前的分析过程中,我们开始怀疑对ABC宽度(ABC Width)的理解可能存在偏差。本应是总的前进宽度,但现在不太确定是否正确地应用了这个值。关键问题在于,字距调整(kerning)数值是相对于什么进行计算的,并且文档并未清晰说明这一点,这使得推测变得困难。

为了确认这一点,查阅了相关文档,寻找是否有关于字距调整的参考基准。然而,文档往往遗漏了关键细节,导致无法确定字距调整的确切计算方式。在进一步检索后,发现了一些关于字体嵌入和度量的描述,但仍然没有明确说明字距调整的参考点。

在检查字体API时,发现有函数可以获取字体的设计度量数据,包括字形的放置位置和字符宽度。此外,还有一个与GetCharABCWidths类似的函数GetCharABCWidthsFloat,其作用基本相同,但返回的是浮点数格式的数据,可能会提高精度。然而,尽管可以使用浮点数进行计算,这个问题的核心仍然是如何正确解释ABC宽度以及它在字距调整计算中的作用。

根据文档说明,字符的总宽度应该是A、B和C三个部分的总和(ABC Width = A + B + C)。然而,在当前的计算过程中,字形的对齐仍然存在问题,因此推测可能是某些偏移量未被正确考虑。

为了进一步验证,将尝试重新梳理计算逻辑,并确保在处理字距调整时正确应用了ABC宽度的各个部分。接下来的步骤是继续分析字体度量数据,确认计算方法,并找出导致当前对齐误差的根本原因。

(黑板)对问题的进一步思考

为了尽可能逆向工程这个过程,我们选取了一个问题较多的字母——大写“N”。当我们请求绘制该字母时,发现它的实际绘制位置比预期位置向后偏移了一些。这表明在某个阶段,Windows 进行了额外的调整,但具体调整逻辑尚不清楚。

我们知道,Windows 选择了某个参考位置进行绘制,而我们原先的假设是,该位置的计算方式为 ABC宽度的总和(A + B + C)。然后,在这个计算出的定位上,Windows 还会应用字距调整(kerning)值,使字符进一步偏移。

但目前我们并不完全清楚如何解释这整个偏移过程,特别是从我们给出的绘制位置,到Windows实际渲染字符的最终位置之间的关系。按照常规逻辑,假设我们希望在某个位置绘制字符,Windows 应该在此基础上再偏移 ABC宽度 以确定下一个字符的起始位置。

然而,我们观察到的问题是,在实际绘制时,字符的位置似乎相对于这个参考位置有所偏移。因此,我们推测,在绘制字符之前,可能需要进行额外的回退(回调某个固定的偏移量),或者调整kerning的应用方式。目前,我们的做法是尝试将这个回退值合并到kerning计算中,以确保最终字符能够正确对齐。

接下来的步骤是进一步拆解这个过程,确认Windows是如何计算字符的最终位置的,并验证我们调整的kerning逻辑是否能够正确反映这一机制。

为了能够将所有字符都左对齐,当前字符的预处理步骤应该应用到下一个字符!

我们发现,字距调整(kerning)实际上是针对下一个字符进行的。这意味着如果希望所有字符能够对齐,就需要将 A宽度(A width)部分放入下一个字符的计算中。然而,Windows 提供的数据并没有直接包含我们需要的信息,因为它将这些宽度值拆分得比较零散,使得 ABC宽度(A、B、C widths)的数据并不完全符合预期。

在应用字距调整时,实际发生偏移的并不是当前字符,而是下一个字符的位置。也就是说,在当前字符绘制完毕后,实际调整的部分是下一个代码点的起始位置。因此,在计算偏移量时,应该调整的是下一个字符的起点,而不是当前字符的位置。

在 Windows 计算字符前进距离(advance)时,使用的是 B 和 C 这两个宽度部分,而 A 部分实际上是额外的空白区域。由于我们在对齐字符时会吸收掉部分空白,这意味着字距调整应当发生在正在绘制的字符上,而不是已经绘制的字符上。这种方式使得调整更加准确。

经过这一修改后,我们发现整体的字距调整比之前更加准确。尽管仍然存在一些小的间距误差,例如某些字符之间的间隔可能略微偏大,但总体而言结果已经非常接近理想状态。不过,仍然存在一个问题:Windows 提供的 ABC宽度 是否准确?如果这些数据本身存在偏差,那无论如何调整计算方式,都无法完全精确复现 Windows 的排版结果。

接下来的关键是确认 ABC宽度(ABC widths)是否被正确报告。如果这些宽度值不准确,就需要找到一种方式来修正它们,以确保最终的字符对齐效果完全符合预期。
在这里插入图片描述

从前一个字符中减去字距调整

我们找到了一种可能的方法来进一步调整字距。具体来说,我们可以利用 Windows 计算出的总位移量(即字符的总前进距离),然后减去字距调整的影响量,以确保计算更精确。

应用这一方法后,我们发现字母的对齐度明显提高。例如,“R” 变得更加接近预期,并且整体效果比 Windows 的渲染更佳,尽管某些特定字母(如 “b”、“p” 和 “d”)仍然存在问题,间距显得不太合理。这种现象表明,调整在某些情况下可以优化字形排列,但在其他情况下仍然有偏差。

观察整体结果,我们发现某些字母的间距比 Windows 版本更紧密,整体趋于更加均匀。然而,仍然有部分字符的间距显得略微紧凑,可能需要额外调整。

因此,接下来的工作重点是:

  1. 进一步微调字距计算方式,使其在所有情况下都表现良好。
  2. 确保所有字母的对齐方式与 Windows 保持一致,特别是那些当前表现仍不佳的字母。
  3. 可能需要重新审视 Windows 提供的字距调整数据,以确认是否存在系统级误差,并找到更稳定的解决方案。

总的来说,当前的调整方法已经在大多数情况下提升了渲染效果,但仍需要进一步优化,使所有字符的间距保持一致性并符合排版预期。
在这里插入图片描述

在这里插入图片描述

对于紧接空字符的字符没有字距调整

我们发现了一个关键问题,即**字距调整(kerning)**不应该对首字符(即代码点为 0 的字符)生效。否则,会导致整体对齐出现偏差。例如,在当前实现中,首字符的偏移量被错误地增加,进而影响整体文本的排列。

为了解决这个问题,我们修改了代码逻辑,使得字距调整仅适用于非零代码点。具体来说:

  • 如果首字符是代码点 0,那么不应该应用字距调整。
  • 只有当当前字符的前一个字符不是代码点 0 时,才执行字距调整

经过这项调整后:

  1. 文本的左对齐恢复正常,不会因为额外的字距调整导致错位。
  2. 整体的字距调整更加符合预期,匹配 Windows 版本的渲染效果,虽然仍有一些微小的差异。

当前来看,这一修改基本解决了首字符对齐错误的问题,使得整个文本的字距调整更加稳定,视觉效果也得到了提升。接下来可能还需要继续微调,以确保所有字符的字距都符合排版要求。

在这里插入图片描述

在这里插入图片描述

是否有可能精确匹配Windows的字距调整?

目前的调整已经基本解决了主要问题,但仍然存在一些难以精准对齐的情况。主要的困扰在于,我们无法完全确定 A、B、C 宽度(ABC Widths) 如何对应到具体的对齐方式。这使得完全匹配 Windows 的渲染结果变得非常困难,甚至可能无法做到 100% 还原。

尽管如此,我们的实现已经相当接近理想状态:

  • 大部分关键的字距调整问题都已经得到处理,整体对齐效果良好。
  • 当前的调整方案涵盖了大多数需要考虑的因素,包括 字距调整、字符宽度计算和对齐方式
  • 整体的渲染结果已经足够接近 Windows 的实现,虽然可能仍有一些微小的误差,但整体已经相当不错。

当前的结果已经令人满意,至少在大多数情况下,它的表现与预期非常接近。后续可能仍需要进一步微调,但目前来看,我们的实现已经足够可靠,并且能够处理大多数实际应用场景。

To 的间隙很大

减少该字符对的间距,确保字形间距调整正确。
在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

我们需要压缩字体范围,以支持其他语言的字距调整

目前正在考虑如何支持其他语言,特别是非拉丁字母的字符集,以便让母语不是拉丁字母的人也能够翻译游戏中的文本。例如,物品名称等内容可能需要被翻译,尽管游戏本身的文本量可能不会太多,但至少某些部分会涉及多语言支持。

字符集扩展与存储挑战

在当前的实现中,字符的字距调整(kerning)是通过平铺数组查找(flat array lookup)来完成的。这种方式对于小字符集来说非常高效,例如:

  • 60、120 或 250 个字符,存储需求较小,性能较高。
  • 即便使用浮点数存储,每 256 个字符也仅占用 256 KB,对于常见的字母表字符集(如英语)问题不大。

然而,当考虑支持更大字符集时,例如:

  • 日语字符集,可能包含 700-1000 个字符
  • Unicode 代码点较高的字符(例如 0x4EAC,即 “京” 字),其代码点可能达到 20,140
  • 如果仍然采用当前方法,会导致存储需求大幅增加。例如:
    • 20,000×20,000 的字距调整表,即 1.5GB 内存占用,显然不现实

优化存储方案

目标是优化存储方式,让高代码点的字符仍然能被高效查询,同时避免占用过多存储空间。因此,需要压缩字体数据,减少大范围空白数据的存储开销。

  • 由于游戏通常不会使用完整的 Unicode 字符集,而是某个特定语言的一部分字符,因此可以仅存储实际使用到的字符
  • 例如,日语可能只会用到 700-1000 个字符,这意味着:
    • 1.9MB 内存(使用浮点存储)是可以接受的。
    • 压缩成 1 字节存储(uint8)后,仅需约 0.5MB,更加高效。

下一步计划

为了避免维护一个庞大的、几乎空置的大规模字符表,接下来的目标是:

  1. 设计一种方法,只存储实际使用到的字符,而不浪费空间存储未用字符。
  2. 压缩字距调整(kerning)数据,保证查询高效的同时节省内存。
  3. 确保未来支持多种语言,例如日语、韩语、中文等,而不会导致系统资源消耗过大。

这些优化方案将在之后的开发中进一步探讨和实施。
https://unicode.scarfboy.com/?s=U%2B4EAC
在这里插入图片描述

看到Notepad中的字距调整,与你们的相比,简直让人觉得它很糟糕

相比之下,在记事本中查看字距调整(kerning)效果会让整体排版显得更糟糕。事实上,当前的字距调整效果本身就很差,主要问题出在字体上。
字距调整一直是一个令人头疼的问题,几乎没有人能把它做得完美,这让人非常恼火。

我意识到这是未知领域,但对我来说,字体渲染占用了比渲染器其他部分更多的时间。这正常吗?

字体渲染所花费的时间似乎比整个渲染过程的其他部分都要长,但实际上并非如此。回顾之前的开发过程,字体渲染大约花费了七天,而渲染整体至少花费了二十天,甚至可能更多。之前曾制作过一份信息图来展示各部分的开发时间分配,理论上可以通过查看那份图表来验证这一点。

尽管如此,字体渲染确实是一个复杂的过程。与普通的位图不同,字体涉及到许多额外的信息,如对齐、基线、字距调整(kerning)、字符对(pairwise interaction)等,而普通的位图(例如精灵图)通常只有一个或两个参考点,并不会涉及这些复杂的排版规则。因此,相较于一般的渲染任务,字体渲染通常更具挑战性,占用更多的处理时间。

日本文字不是均匀间隔的吗?

在字体渲染的过程中,有一个问题是,字体设计和排版规则并不总是符合所有语言的需求。例如,日语和中文的字符间距问题与其他语言不同。日语和中文的字符通常不需要进行像英文那样复杂的字距调整,主要依赖简单的间距规则。

然而,现有的系统可能没有考虑到这些语言的特殊需求。一个可能的解决方案是为日语和中文提供特殊的排版规则,仅需要处理简单的字符间距调整,而不需要完全遵循其他语言复杂的排版和字距调整要求。这可以作为一个例外的处理方式,但问题是现有的系统可能并未内置这些语言的特殊需求。

我在Notepad、Word、Wordpad中测试字距调整… 但那里没有字距调整?你们在哪看到了Windows中的字距调整?

在测试过程中,注意到记事本和Word中没有进行字距调整。字距调整通常是由系统提供的,尤其是在Windows操作系统中,字距调整功能是内置的,并且在系统字体处理中是自动启用的。Windows的字体渲染系统会根据字符对之间的关系,自动调整字距,以确保文本的可读性和美观性。

约翰·卡马克做了低级图形编程并买了辆法拉利,字体渲染人员啥都没得到。什么时候能回到编程那些酷炫的明星项目上?

在游戏编程领域,许多人像 Elon Musk 一样,投身于低级图形编程,但与之相比,字体渲染领域的John Warnock则成就了更多,尤其是在商业软件的盈利能力上远超游戏软件。Warnock是Adobe的创始人,而Adobe作为一个数十亿美元的公司,其在字体渲染领域的贡献要远大于Carmack在游戏图形方面的影响力。事实上,商业软件的盈利要比游戏软件高出一个或两个数量级,因此,字体渲染领域的影响力和收益也大大超过了游戏渲染。

我现在在大学学编程,已经学了两年了,但有些事情还是不太理解。我的问题是,你们需要多久才能对编程有更深入的理解?

在大学二年级学习编程时,仍然遇到一些简单问题是很正常的。对于掌握编程的一般理解,通常需要大约十年的时间。这是一个渐进的过程,不同的人可能会有不同的学习进度,但大致上,十年左右的时间可以达到对编程的较好理解。

说得好,也许只是看起来“进展”慢了点

进展可能看起来很慢,但如果将处理 Windows 的时间排除在外,进展会显得更快。Windows 操作系统就像一个黑盒子,处理它需要额外的时间。在渲染错误中,很多时间被花费在编写自己的代码上,这样节省了不少时间。因此,如果要进行公平的比较,应该把渲染和 Windows 平台代码的时间加在一起。

我有点困惑,为什么字体渲染如此依赖Windows?这些信息不都保存在字体文件里吗?没有Windows的文本度量不行吗?或者换句话说,如果我们使用stb_truetype,今天做的事会有什么不同吗?

关于字体渲染依赖于 Windows 的问题,其实字体文件本身并不会完全存储所有字体渲染所需的数据。Windows 使用的是文本度量(text metrics)数据,这些信息是从字体文件中提取的,尤其是 TrueType 文件。然而,尽管可以从 TrueType 文件中提取这些数据,问题在于,字体的对齐方式可能仍然不正确。因此,即使不依赖 Windows,问题依然存在,因为 TrueType 文件本身可能会存在对齐不正确的情况,导致最终渲染出的字符仍然存在偏差。所以,根本问题还是出在 TrueType 文件的格式,而非操作系统本身。

在MSDN条目“Uniscribe Glossary”中,ABC值如何被Windows理解有更好的解释

根据MSDN的术语解释,字符的宽度(advance width)是字体渲染中的一个重要概念。当多个字形(glyphs)组成一个字符串时,通常只有最左边的字形会贡献该串的宽度,而最右边的字形会贡献该串的宽度。然而,这并不是严格的规则。如果字符串中的第一个字形是一个窄字符,而第二个字符有上标或下标的附加符号(比如重音符号),则附加符号可能会扩展超出字符本身。

在计算字符的“advance width”(即字符前进宽度)时,关键是考虑字形的左右两侧空白区域的宽度,这被称为“白空间”或“padding”。在字体渲染中,advance width 是字符在显示过程中从一个字符到下一个字符的间隔,它需要考虑符号、附加符号等因素。

实际应用中,可以通过特定的函数(比如 Windows API)获取每个字符的advance width,这是一个整数值,表示字符的宽度。在某些情况下,尤其是在有多个字符和符号的组合时,实际的字符宽度和它们的排版方式可能会有所不同。
https://learn.microsoft.com/en-us/windows/win32/intl/uniscribe-glossary
在这里插入图片描述

忽略文档,直接使用GetCharWidth32

在这个实验中,尝试忽略文档中的定义,直接操作字符的“advance width”。首先,原本应该获取字符宽度的函数 GetCharWidth32 被认为是一个获取字符宽度的函数,但在这里被直接修改或忽略了标准实现。操作的步骤包括将字符宽度相加,并通过 hdc(全球字体设备上下文)来处理,但并没有按照文档的标准流程。

意图是通过不参考文档规定,直接操作 GetCharWidth32,看看是否会有任何不同的结果。实际上,尝试之后并没有得到预期的效果,反而系统发生了崩溃。这表明如果忽略了正确的文档定义或不遵循标准实现,可能会导致程序无法正常工作。
在这里插入图片描述

在这里插入图片描述

看看字距调整效果如何

经过尝试,结果看起来好像是有效的,因此认为文档中的定义可能是错误的,这是一个单独的问题。接着,检查字体的字距调整效果,看起来与之前的效果差不多,尽管仍然有些地方看起来不完全正确。例如,某些地方的字距比其他地方要近,看起来很接近,但仍然不完全对齐。

经过进一步观察,觉得效果已经非常接近预期,虽然某些部分仍有细微差别,仍未完全达到理想状态。整体来说,调整后的效果非常接近正确,但还是感觉有一点点差距,某些地方的字距还是不太对。

你在渲染时是否使用了显卡?

目前,在渲染时并没有使用显卡,所有的渲染工作都是自己处理的。

你用的C++有什么特性让你不使用普通的C?

目前,问题的核心是为何不使用一些更现代的编程特性,比如运算符重载和函数重载,或者在任何地方声明变量。实际上,C++98 版本就已经允许在任何地方声明变量,因此对于像运算符重载和函数重载这类功能的使用,可能存在一些限制或偏好。

当你说Windows使用字距调整时,为什么每个字母从不与后面的字母重叠?在你的代码中,我看到字母有重叠。难道我理解错了字距调整吗?

在谈到 Windows 用户的字距调整时,问题的核心在于为什么每个字母之间的间距看起来从不重叠,而在代码中看到字母是重叠的。对于这个问题,解释是,实际上,字母确实是有重叠的,即字母之间的空间是相互重叠的。字距调整的目的是调整字母之间的间隔,避免它们完全重叠,但在某些情况下,字母之间确实会有重叠。这是字距调整的一个常见现象。

Elon Musk 还做了火箭发射器,所以他赢了

提到字体渲染和编程时,尽管某些人如 Elon Musk 获得了很多成就,比如制作火箭,但也有观点认为相较于字体编程,银行代码可能更加枯燥。而且,事实上,像 Elon Musk 这样的人,虽然同样涉及技术领域,但目前他已经有了一个真正可用的火箭,而相比之下, Elon Musk 目前的火箭仍然没有完全投入使用。因此,虽然 Elon Musk 有很多成就,但在某些方面,他并未完全“取胜”。

你是说Adobe的程序员比Id的更优秀吗?

在讨论程序员的水平时,有人提到是否 Adobe 的程序员比某些低级图形编程领域的程序员更优秀。实际上,可能并非如此,Adobe 的程序员可能比某些图形编程的程序员差。但问题在于市场领域的不同,游戏并不是最具利润的市场,相比之下,字体编程等领域能带来更多的财富。

如果看一下那些专注于文档布局的老牌图形公司,它们的财富要远远超过大多数游戏公司。虽然从技术角度看,某些公司可能有更优秀的程序员,但这与赚多少钱并没有直接关系。赚多少钱和程序员的技术水平并没有太大关系,市场的需求和领域才是关键因素。

为什么我们不使用位图字体而选择了TTF字体?位图字体不是跨平台的吗?

为什么不使用位图字体,而选择 TrueType 字体呢?位图字体确实是跨平台的,因为我们只需要提取一次,它们就变成了位图字体。在使用字体打包工具时,实际上是将三种不同类型的字体转化为位图字体。

我们不使用位图字体的原因是,大多数位图字体的质量并不理想。而 TrueType 字体通常质量非常好。因此,通常来说,从 TrueType 字体中提取字体,再将其转化为位图字体,或者根据需要使用其他类型的字体,都是更好的选择。

当我在GPU上渲染时,是否有办法在不将渲染结果复制回RAM的情况下显示结果?

在渲染时,问题是是否可以在不将渲染结果复制回内存(RAM)的情况下进行渲染。也就是在渲染过程中,是否有办法直接操作,而不需要将渲染的结果再复制回内存。这是一个关于渲染优化的问题,涉及如何减少数据传输,以提高渲染效率。

日文不是均匀间隔的。有些字符像「」依赖字距调整

在讨论日文时,提到日文字符并不是均匀间隔的,一些字符(如上括号和下括号)依赖于字符间距调整(kerning)。但要明确的是,日文字符的间距并不是均匀的,只是没有经过字符间距调整。日文中并不需要进行字符对间距调整(pairwise kerning),因为日文字符要么是全宽字符,要么是半宽字符,或者是标点符号。这些字符的间距可以通过简单处理来实现,而不需要担心像字母和假名之间的间距问题。

此外,不会特别针对日文或其他语言进行特殊处理。目的是确保在不同语言中都能够通过查询表来处理字符间距,即使某些语言不需要这种特殊处理,也要确保系统能够正常工作,保持通用性。

你是如何渲染到GPU上的?

渲染到GPU的过程是通过使用编程API来完成的。这些API由GPU制造商提供,并且有相应的驱动程序来支持。常见的API包括OpenGL、DirectX、Vulkan、Metal等。过去,也使用过一些老旧的API,如Glide、OpenCL等。这些API允许程序直接与GPU交互,从而进行图形渲染和其他计算任务。

阅读时最喜欢的字体是什么?

对于最喜欢的字体渲染,暂时没有明确的答案。因为并没有花费很多时间在这方面,所以还没有特别明确的偏好。

为了显示结果

当渲染结果时,确实可以将其直接显示在显示器上,但这需要将渲染结果传输到GPU。换句话说,如果没有GPU,就无法显示渲染结果。一般来说,在离散显卡(独立显卡)的情况下,渲染结果会被复制到GPU上。如果使用的是集成显卡,那么它们通常共享内存,因此没有额外的复制步骤。因此,是否需要将渲染结果复制回RAM取决于具体的显卡类型和配置。

你说对齐不是字距调整时,我几乎头痛了,请详细说明一下

对齐(alignment)和字间距调整(kerning)是两个不同的概念。对齐是指文本在某一行或段落中的位置安排,比如左对齐、右对齐、居中对齐等,它主要关注整个文本块的排列方式。对齐的目的是确保文字在视觉上有序、整齐,给人一种规范的感觉。

而字间距调整(kerning)是指在字符之间调整间距的过程,目的是确保某些字母对之间的间距更加均匀或适当。比如字母“AV”之间的间距可能会小一些,以避免视觉上看起来过于松散。字间距调整更多关注的是字符之间的细节,而不是文本的整体布局。

因此,虽然两者都与文字的显示方式相关,但它们的关注点不同:对齐是关于文本块的整体位置,而字间距调整是对单个字符间距的精细调整。

黑板:间距与字距调整

在某些语言中,字符的排布方式被正式化,例如日语就是其中之一。日语有两种字符:全宽字符(full-width)和半宽字符(half-width)。这两种字符的区别在于它们所占的空间。全宽字符占用一个完整的字符框,而半宽字符则占用一半的字符框。

在日语中,字符之间的间距只取决于字符本身是全宽还是半宽。无论它们相邻的字符是什么,间距的调整仅仅基于字符的宽度。例如,如果遇到全宽字符,光标会按全宽字符的宽度向前移动;而对于半宽字符,光标只会按半宽字符的宽度向前移动。

对于这种情况,排版时不需要考虑字符对之间的配对对齐(kerning)。配对对齐通常是指需要依赖两个字符的关系来确定它们之间的间距,但在日语中,字符的宽度就能决定间距,而不需要考虑后续字符的类型。这样,日语的排版就不需要使用“字符对”查找表,只需要知道当前字符的类型就可以决定光标的移动。

这和配对对齐(kerning)不同,后者涉及到查找字符对之间的精确间距,需要使用二维的查找表(即需要考虑字符对的组合)。而在日语的情况下,可以通过一维查找表来处理字符间距,因为每个字符的宽度是固定的。

然而,有些字符(例如标点符号)可能会使用配对对齐的方式,特别是在需要让这些字符正确重叠时。在这种情况下,仍然需要考虑配对对齐,但这种情况相对少见。所以,尽管日语中大部分情况不需要配对对齐,但对于少数特殊字符,还是可以通过查找表来处理。

总结来说,如果只处理像日语这样的语言,就不需要复杂的配对对齐表格。只需要简单地判断每个字符是全宽还是半宽,并据此决定光标的移动即可。

举个例子:

在日语中,字符的宽度可以是全宽(full-width)或半宽(half-width)。例如:

  1. 全宽字符:日语中的汉字(如「日」)是全宽字符,表示它占据一个完整的字符框。假设当前光标位于字符「日」的起始位置,它会向右移动一个字符框的宽度,才能到达下一个字符位置。

  2. 半宽字符:日语中的英文字母或阿拉伯数字(如「A」、「1」)是半宽字符,表示它占据的空间只有全宽字符的一半。如果当前光标位于字符「A」的起始位置,光标只会向右移动半个字符框的宽度,才能到达下一个字符位置。

示例:

假设我们有如下日文文本:

  • 「私はAIが好きです。」

其中,「私」、「は」、「AI」、「が」、「好き」和「です」都是日语词语。假设「私」是全宽字符,而「A」、「I」是半宽字符。

光标移动:

  • 光标从「私」开始,它是全宽字符,所以下一个字符(「は」)的起始位置在「私」之后一个完整的字符框。
  • 光标到达「A」时,它是半宽字符,所以光标会向右移动一半的字符框宽度,跳到「I」的位置。
  • 光标在「I」后继续前进,移动到「が」,「好き」,最后到「です」,每次都会根据字符的类型(全宽或半宽)决定光标的移动量。

在这个例子中,不需要考虑字符间的配对对齐(kerning),因为字符间的间距只与它们是全宽还是半宽有关。你不需要知道「A」和「I」之间是否会重叠或其他细节,只需要按照它们的宽度来移动光标。

为什么不需要配对对齐:

在其他一些语言(例如英语)中,某些字符组合可能需要特殊的间距调整,比如“AV”这种字符组合可能需要缩小间距,以避免它们之间的空隙过大。而在日语中,由于字符的宽度已经明确规定,光标移动是基于每个字符本身的宽度,而不需要依赖相邻字符的配对信息。因此,大部分日语文本的排版不需要使用复杂的配对对齐查找表。

特殊字符:

虽然大部分日语字符不需要配对对齐,但标点符号(如「。」或「、」)可能会根据情况需要调整。例如,某些标点符号的间距可能需要依赖相邻字符,尤其是在全宽和半宽字符之间混用时。

通过这种方式,日语的排版可以简化,不需要考虑每一对字符之间的具体关系,从而减少了排版复杂度。

你是愿意拥有更多核心的CPU而不是GPU,还是愿意拥有足够的时钟周期以通过软件渲染超越GPU?

这个问题是在询问,是否更倾向于拥有一个核心数比GPU多的CPU,还是一个拥有足够时钟周期的CPU,它的性能可以超越GPU的软渲染能力。

简单来说,这个问题是问:

  1. 是更希望拥有一个多核心的CPU,而它的性能比GPU差?
  2. 还是希望有一个CPU,尽管它的核心数不如GPU,但时钟频率足够高,能够在软件渲染上超过GPU的性能?

这两者其实是在探讨CPU和GPU之间的权衡。CPU的核心数和时钟频率,通常会影响计算任务的处理能力,但GPU在图形渲染上的优势通常与其架构和专门化有关。在这两个选择之间,问题就是要在更多的核心和更高的时钟频率之间做出选择,具体选择取决于任务的性质,比如任务是否可以并行化,或者需要处理的图形工作量是否特别大。

你可以在这里查看1,3. Tsumegumi用于日文字距调整

在讨论日本语言排版需求时,提到可以参考W3C的相关文档,进一步了解更多信息。根据这些文档的内容,日本文字排版非常规律,并且在处理时通常不需要考虑字符间的对齐。日本文字通常使用全角字符和半角字符,字符间的间距是固定的,不需要通过配对字符的方式来调整。

然而,也有提到一些情况下,特定的日文字体可能会使用字符间的微调(kerning),尽管这种情况并不常见。这个微调通常用于一些更具表现力的日文排版字体。如果需要支持这种字体,也许可以考虑为这类字体提供微调支持,但这种需求相对较少。总的来说,大多数日文排版不需要复杂的字符对齐系统。

当想到Adobe的市值超过400亿美元时,为什么没有优秀的程序员想做出更好的Photoshop?

在讨论为什么没有程序员愿意开发比Photoshop更好的图像编辑软件时,有人提出了几个关键观点。首先,Photoshop作为行业标准,已经被广泛接受和使用。几乎每个艺术家都使用Photoshop,且其文件格式PSD也已经成为行业的标准。因此,要打破这个市场非常困难,因为需要面对强大的市场认知和用户基础。

其次,虽然Photoshop本身的市场价值很大,但开发一款真正超越Photoshop的图像编辑软件面临着巨大的挑战。相比之下,许多新的创业项目倾向于选择一些更简单且容易实现的想法,例如开发像Instagram这样的应用,它虽然功能简单,但却能迅速吸引大量用户,并且最终获得高额收购。因此,如果只是为了赚钱,开发一个像Photoshop这样的复杂软件就显得不太有吸引力。

此外,开发像Photoshop这样的程序需要大量的技术投入和时间,而有些创业者可能更倾向于通过开发一些较简单的应用来快速获得资金支持或被大公司收购。总的来说,面对“更加容易赚钱”的选择,挑战Photoshop这样的市场标准显得过于复杂且耗时,因此许多程序员选择了更简单、更快捷的商业模式。

实际上,有很多人正在与Photoshop竞争,你现在在流媒体上用的就是其中一款产品…

事实上,确实有很多产品在与Photoshop竞争,但它们并不完全是Photoshop的替代品。比如Mischief,它与Photoshop功能差异很大,虽然也能用于绘图和设计,但它并没有达到与Photoshop相同的效果和广泛的应用。

对于与Photoshop竞争的产品,有一些类似GIMP和Krita的免费软件,它们在某些方面与Photoshop有相似功能,尤其是在图像编辑领域,但它们并不能完全替代Photoshop。商业市场中,并没有出现明显能与Photoshop直接竞争的产品。

曾经一些软件如CorelDRAW和Fractal Painter也在市场上与Photoshop争夺用户,但这些软件现在几乎已经消失,要么被收购,要么没有继续发展,变得不再重要。而一些针对3D设计的软件,如Maya和Mudbox,也并非Photoshop的直接竞争者。

总结来说,虽然有许多软件可用于图像处理和设计,但它们大多属于不同的市场细分,并没有一个完全能够取代Photoshop的产品出现。

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

热搜词