使用Graphics.DrawString(而不是SpriteBatch.DrawString)在Monogame中呈现文本

14
使用 Graphics.DrawString 渲染静态文本至离屏位图,转换为一个 Texture2D ,然后简单调用 SpriteBatch.Draw 以代替使用内容管道和 SpriteFont 渲染文本,是否存在任何不利影响?这基本上是在“纸张”上绘制一整页文本,但用户也可以选择调整字体大小,这意味着我需要包含不同尺寸的 spritefonts。
由于这是仅限 Windows 应用程序(不打算移植),我将可以像在普通的 WinForms 应用程序中那样访问所有字体,并且我相信使用 Graphics.DrawString (甚至是 TextRenderer )进行渲染时,渲染质量会比使用精灵字体更好。
此外,性能似乎可能更好,因为 SpriteBatch.DrawString 需要在每次迭代中“渲染”整个文本(即为每个字母单独发送顶点),而通过使用位图,我只需执行一次,因此在 CPU 方面应该稍微减轻了一些工作量。
1. 是否有我没有注意到的问题或不利影响?
2. 是否可以使用精灵字体获得 alpha 混合文本?我看到 Nuclex 框架被提到过,但据我所知,它还没有被移植到 Monogame。
更新:
从技术方面来看,它似乎完美运行,比通过精灵字体渲染文本要好得多。如果它们水平渲染,我甚至可以获得 ClearType。可能存在的一个问题是,字体的精灵表(spritesheets)在纹理内存方面更有效率,而不是为每一页文本创建单独的纹理。
2个回答

2

没有问题

实际上,您似乎正在遵循标准的文本渲染方法。
事实上,“正确”地呈现文本比呈现纹理化四边形要慢得多,即使SpriteFonts削减了所有的曲线字形,如果您呈现一整页的文本,则仍然可以积累大量三角形。

每当我在寻找不同的GL/XNA文本呈现解决方案时,人们倾向于推荐您的方法。将您的长篇文字绘制一次并转换为可重复使用的纹理,然后呈现该纹理。

您还可以考虑RenderTarget2D作为可能的解决方案,这是一种便携式解决方案。
以下是一个示例:

// Render the new text on the texture
LoadPageText(int pageNum) {
    string[] text = this.book[pageNum];
    GraphicsDevice.SetRenderTarget(pageTarget);
    // TODO: draw page background

    this.spriteBatchCache.Begin();
    for (int i = 0; i < text.Length; i++) {
         this.spriteBatchCache.DrawText(this.font, 
             new Vector2(10, 10 + this.fontHeight * i), 
             text[i], 
             this.color);
    }
    this.spriteBatchCache.End();
    GraphicsDevice.SetRenderTarget(null);
}

在场景渲染中,您可以使用 spriteBatch.Draw(..., pageTarget, ...) 来渲染文本。这样,您只需要一个纹理来处理所有页面,只需记得在字体更改时重新绘制。
还有其他要考虑的事情是您的 SpriteBatch 的排序模式,在渲染许多三角形时可能会影响性能。
关于第二点,如我上面所提到的,SpriteFonts 是预渲染纹理,这意味着透明度已经烘焙到它们的精灵表中。因此,似乎默认库不使用透明度/抗锯齿。
如果您将它们以两倍大小和黑白颜色渲染,并将 SourceColor 用作 alpha 通道,然后将它们缩小并与 Color.Black 混合,您可能可以将其恢复。

0
请尝试使用指针进行颜色混合:
MixedColor = ((Alpha1 * Channel1) + (Alpha2 * Channel2))/(Alpha1 + Alpha2)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接