我目前正在创建一个大型地图,它包含许多矩形(33,844),它们都有一个唯一的名称(标签),我使用SpriteFont绘制它们。
绘制所有矩形根本不会影响性能。但是,只要我尝试使用DrawString()编写所有标签,我的性能就会进入转储。
在我的脑海中,我想将所有矩形和文本同时绘制到一个纹理中,并且只需要重新绘制整个纹理。我的问题是,这是一个巨大的地图,矩形的一些坐标非常高(例如:一个插槽' sx是14869,y是23622),并且它们远远大于Texture2D允许的。
由于这是一张地图,我真的只需要绘制一次整个事物,然后让用户滚动/移动它。我不需要不断重绘所有单个矩形及其标签。
有没有人有这种情况的经验?
答案 0 :(得分:1)
尝试仅渲染您可以在屏幕上看到的标签,如果您可以缩放得足够远,则不要渲染它们。
Textrendering很昂贵,因为它基本上是为字体中的每个字符创建一个矩形,然后对其应用相同的RGBA纹理。因此,根据您编写的字符数,矩形数量会增加。这意味着每个角色有四个新顶点。
根据你所写的内容,你可以简单地创建一个纹理,其上已有文字并渲染它,但它不会非常动态。
编辑:我需要澄清一些事情。我不需要不断重绘所有单个矩形及其标签。
这是错误的。你必须每帧画出整个东西。当然,它不会以记忆方式增加,但渲染仍然很多,你需要每帧渲染它。
但正如我所说:尝试只渲染与屏幕边界碰撞的标签和矩形,那么你应该没问题。
答案 1 :(得分:0)
有两种方法可以解决您的问题。
您可以将地图渲染为RenderTarget(2D / 3D),也可以剔除屏幕外的矩形/文本。但是,我并非100%确定RenderTargets可以根据您的需要进行调整,但您可以随时将地图划分为多个较小的RenderTargets。
有关RenderTargets的更多信息,您可能需要查看RB Whitaker关于它们的文章,http://rbwhitaker.wikidot.com/render-to-texture
如果您熟悉在此上下文中使用的术语,则剔除仅表示呈现最终用户可见的内容。有多种方法可以实施剔除。但是,这确实需要您已经实现了一个摄像头(或某种类型的视图区域),并且您对照摄像机的视口执行矩形轴对齐的边界框碰撞(AABB碰撞,MonoGame的矩形支持开箱即用)并且只有在发生碰撞时才会渲染它。
剔除的基本实现看起来像这样:
Rectangle myRect = new Rectangle(100, 100, 48, 32);
public void DrawMapItem(SpriteBatch batch, Rectangle viewRegion)
{
if (viewRegion.Contains(myRect))
{
//Render your object here with the SpriteBatch
}
}
'viewRegion'是您的世界中相机/最终用户实际可以看到的区域。
您还可以组合这两种方法,并将地图渲染为多个渲染目标,然后剔除渲染目标。
希望这有帮助!