首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >SDL2:渲染引擎设计

SDL2:渲染引擎设计
EN

Stack Overflow用户
提问于 2014-03-26 02:19:07
回答 2查看 2.5K关注 0票数 1

我正在创建基于SDL2库的简单游戏渲染引擎。我的设计看起来类似于这个ASCII图表。

代码语言:javascript
复制
DrawTarget     RenderTarget
    |                |
    |                |
    +---> Window <---+

DrawTarget是一个适用于SDL_Surface blitting的绘制目标的抽象类。RenderTarget是适用于SDL_Texture的渲染对象的抽象类。Window是管理SDL_Window、SDL_Renderer以及所有绘制和渲染函数的派生类。

代码语言:javascript
复制
Renderable
  |  |  |
  |  |  |
  |  |  +-> Player
  |  |         ^
  |  |         |
  |  +----> Animation
  |            ^
  |            |
  +-------> Texture

Renderable就是一切,它可以呈现在屏幕上或其他RenderTarget上。Texture是SDL_Texture实现。纹理不应该知道自己的位置。Animation有一个私有纹理成员,允许设置动画帧。动画本身不应该知道渲染位置。Player有一个私人的动画成员。玩家应该知道当前的位置。

在这个时候,我有一个SDL_Renderer的每个窗口,并传递它周围的纹理,动画等纹理是与SDL_Renderer渲染本身到屏幕的知识。但我不认为总是调用Texture->draw( x,y)是高效的,也不是对缓存友好的。

我喜欢SFML呈现的方式。所有可渲染的对象都有draw方法,它只调用窗口的draw方法。我想实现类似的系统。

这将打破我的要求有些可渲染对象知道它们的渲染位置,有些则不知道。

例如,类Player不应该有render( x, y )方法,因为它知道自己的位置。另一方面,纹理类不应该有render( void )方法,因为它不是它的位置。

我的问题是:如何以尽可能少的开销设计出适合SDL2的渲染引擎?

EN

回答 2

Stack Overflow用户

发布于 2015-09-03 06:30:27

回答你的问题:“我的问题是:如何用尽可能少的开销设计合适的SDL2渲染引擎?”

快速解释一下用于最小化SDL2渲染器开销的可伸缩、惰性渲染器方案:

“层”由具有相同z属性的所有纹理组成。只要修改图层中的纹理,该图层就会被标记为无效。层是在渲染器运行时管理的,该渲染器处于设定的帧率。跟踪最大层和最高无效层。渲染器从最高的无效层开始,在最大层结束。将每个层设置为渲染器目标并清除。然后将上一层复制到当前层。然后,它遍历图层中的每个纹理,重新绘制标记为无效的纹理,并将每个纹理复制到当前图层的顶部。结果是前一层是背景,而当前层绘制在它的顶部。当层被标记为无效时,该纹理将被缓存并失效。运行完任何无效的层后,将渲染目标设置回默认(null),将最高纹理复制到屏幕上,然后显示。

在具有层的2d用户界面类型的环境中,上面的是可伸缩的和惰性的。在我的低端赛扬n2830上,我的测试应用程序空闲,cpu使用率为0%。即使我添加了100个测试层,它也或多或少地保持了这种状态。由于它只从向上更改的层中提取,并且所有更改都以合理的帧率排队,因此实际完成的工作很少。迭代通过无效层到最大层看起来比每次迭代所有层要友好得多。以设定的时间间隔运行渲染器并完成所有绘制,这有助于节省时间,因为它将忽略本来看不到的多余更改。使用一些应用程序代码来避免绘制东西和复制纹理是值得的。这些往往比一些if检查和属性查找花费更长的时间。

请注意,这种设计是为具有层的2d设计的,就像用户界面一样。有些原则可能在其他环境中不一定能很好地工作。

此外,上面只支持纹理,而不支持表面。对我来说,将两者混合在一起并不值得这么复杂。让sdl2渲染器绘制到特定的纹理需要一些工作,但仅满足我的需求就足够了。如果将两者混合在一起,似乎很难避免一些额外的工作。加上纹理受益于gpu,这增加了cpu时间方面的效率优势。

在我的系统中,窗口对象有一个绘图方法。此方法使用渲染器将绘制操作排入队列,而不是立即绘制它们。窗口对象具有面积属性。要支持没有area属性的对象,也许可以对没有area属性的对象应用一个包装器。这样,当提示输入一个区域时,它仍然可以提供一个区域,即使它内部没有一个区域。或者可以使用将对象映射到区域的表,或者使用跟踪其纹理的任何对象的方法调用。我不确定这种限制的性质。

请注意,此绘制方法是对象绘制本身和渲染器绘制对象的混合方法。对象看起来是自己绘制的,而渲染器实际上是在做这项工作。

简而言之:

当批量processing

  • cache纹理绘制时,
  • 纹理的绘制和复制操作比批量绘制和复制操作快得多
  • 将所有纹理复制到缓存图层后
  • 使用缓存来避免将除无效图层以外的所有图层渲染到最大图层
票数 5
EN

Stack Overflow用户

发布于 2014-03-26 08:08:11

在我看来,您所说的是您希望实体只知道它们的位置,但对于渲染,您希望它是完全独立的。每个实体都需要存储某种渲染数据。我会说你应该看看基于组件的实体系统。位置、渲染器数据、输入等有不同的类。请尝试Component Based Entity System

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/22643101

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档