设计OpenGL ES方针介绍(5)

设计OpenGL ES方针介绍(5)

6.7 高效的状态管理

实现OpenGL ES应用程序时,重要的事情之一是确保将用于修改OpenGL ES配置的API调用的数量减少到最少。
表6-2列出了OpenGL ES支持的状态容器的类型,以及每种对象类型所处状态的简短描述。
在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述在确保应用程序充分利用了所使用的OpenGL ES版本中可用的状态容器之后,提高渲染性能的下一步是确保应用程序不会进行冗余的API调用。 对于OpenGL ES应用程序来说,激活已经处于活动状态的程序对象或将值分配给与现有统一值完全相同的着色器统一性是常见的陷阱。 为了保持较低的开销,即使这些调用是多余的,驱动程序也可以将它们传递给硬件,从而有效地浪费了时间,这些时间可能花费在更重要的事情上。

最后,对绘制调用进行排序以减少OpenGL ES应用程序将要进行的状态更改的数量始终是一个好主意。 QTI建议按以下顺序对绘图调用进行排序:

  1. 按渲染目标–渲染目标之间的切换(使用glBindFramebuffer或glFramebuffer *调用)非常昂贵,因此仅在完成针对当前帧缓冲区对象配置的所有对象的渲染完成后,才重新配置帧缓冲区绑定或活动绘制帧缓冲区附件 。 如果需要使用多个程序将对象绘制到多个帧缓冲区中,则先在程序之间切换,然后再在帧缓冲区之间切换比较便宜。 这种方法以增加glUseProgram调用为代价,最大程度地减少了对glBindFramebuffer和/或glFramebuffer *的调用。
  2. 按程序–对于给定的帧缓冲区,请确保将程序切换的数量减少到最少。 例如,如果一个场景包含三个对象,其中两个使用相同的片段着色器,则最好先渲染这两个对象,然后更改程序并继续渲染其余对象。
  3. 通过其他状态-其他状态更改的成本较低,因此绘制调用的进一步顺序取决于应用程序。 经验法则是,状态切换越少越好。

6.8 节能提示

渲染过程是一个复杂的活动,消耗大量功率。 引擎程序员在设计应用程序时应考虑一些方面的渲染,以确保电池消耗水平保持合理。 它们如下:

  • 应用程序不时地渲染一次帧是否可以接受,还是用户希望视觉效果得到定期更新?
    例如,在照片浏览器应用程序中,一旦显示了照片,就锁定渲染管道,并保持渲染过程锁定,直到用户开始以某种方式与图像进行交互为止是可以接受的。 例如,如果他们尝试放大或朝某个方向移动。 届时,它将恢复渲染过程。 渲染看起来相同的帧流毫无意义,并且消耗更多功率。
    但是,如果UI的任何部分都具有动画效果,则可以证明需要进行更多的定期更新。 为了降低渲染仅UI帧的成本,应用程序可以缓存渲染常规帧时呈现照片的方式,然后对于较便宜的帧,可以将该纹理着色到后台缓冲区并渲染HUD。 超过它。
  • 如果应用程序需要频繁重绘,这些更新必须定期进行?
    视频播放器应用程序可以将其渲染速率限制为正在播放的视频剪辑的帧速率。 但是,当允许每秒渲染更多帧时,可以提供更流畅的视觉体验的视频游戏;如果将设备连接到电源,则可以绘制尽可能多的帧,或者可以限制为每秒绘制30帧 只要设备由电池供电。

电池消耗的强度通常可以由应用程序控制,排水的可伸缩性取决于应用程序执行的操作以及其渲染管道的构造方式。

应用程序可以使用帧速率限制器来减少每秒绘制的帧数。 有多种方法可以实现此功能:

  • 如果使用显示刷新率作为减少每秒绘制的帧数的基础是可接受的解决方案,则最快的方法是调用eglSwapInterval函数。
    该函数采用单个参数,该参数指定在发生缓冲区交换之前显示的最小视频帧数。 这意味着,如果显示器的刷新率为60 Hz,并且使用的值为2,则每秒渲染的帧数不会超过30。 通过阻止eglSwapBuffers中的执行流来执行此操作,直到由硬件切换前/后缓冲区为止。
    注意:
    硬件会定期更新显示内容。 如果应用程序调用eglSwapBuffers的时间太晚,则可能会错过给定帧的vsync时间窗口,并保持阻塞状态,直到发生下一个视频同步事件为止。
    使用0值会使eglSwapBuffers调用立即将前缓冲区与后缓冲区翻转,通常会产生撕裂效果,这在动态动画处理中会更加明显。
    默认情况下,eglSwapInterval配置为使用值1。
  • 更复杂的引擎通常将工作负载分配到多个线程,并在渲染管道之外执行计算。 当需要渲染框架时,他们将使用可用的最新数据。 在这种情况下,使用定制的帧速率限制器可能更合理,该限制器会在每个帧之前足够早地唤醒,绘制场景并最终在vsync发生之前调用eglSwapBuffers()。
    定制帧速率限制器的实际实现方式有所不同,并且通常在一定程度上涉及启发式,但是总体思路如下:
time_t current_time;
for (each frame)
{
time_t wakeup_time =
getNextWakeupTime()
while ( (current_time = currentTime()) <
wakeup_time)
{
time_t sleep_time =
getSleepTime(current_time,
wakeup_time);
sleep(sleep_time);
}
draw();
eglSwapBuffers(display, draw_surface_to_swap);
}

注意:
sleep()不保证在指定的时间间隔过去后立即返回执行线程。 但是,现代操作系统分配给线程的时间量通常足够小,以使3D应用程序可以安全地依赖此方法。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值