简体   繁体   English

在Android上进行OpenGL ES 2.0渲染的最佳实践

[英]Best practice for OpenGL ES 2.0 rendering on Android

With the languages and libraries I've worked so far, there was always an option to sync the main loop of the program (a game or anything with an always changing context) to the current display's refresh rate. 使用到目前为止我已经使用的语言和库,总有一个选项可以将程序的主循环(游戏或上下文始终变化的任何内容)同步到当前显示器的刷新率。 So I had the option to either switch on VSYNC or just let the loop execute as many times per second as it could. 因此,我可以选择打开VSYNC或只是让循环每秒执行尽可能多的次数。 I'm referring to SDL2, OpenGL 3.0 with GLFW, the HTML5 canvas etc. 我指的是SDL2,带有GLFW的OpenGL 3.0,HTML5画布等。

I'm looking for something similar on Android now in OpenGL ES 2.0, but so far all the example code I can find simply uses a variation of sleep and set the framerate to 60 or 30. So they basically count the amount of time passed since the last iteration, and only advance further and call the requestRender() function if a given amount of time has passed (0.016 ms in case of 60 frames per second etc.). 我现在正在OpenGL ES 2.0中寻找Android上类似的东西,但是到目前为止,我可以找到的所有示例代码都只是使用了睡眠的变化,并将帧速率设置为60或30。因此,它们基本上是计算自最后一次迭代,并且仅在经过给定时间(如果每秒60帧的情况下为0.016毫秒,等等)之后才进一步前进并调用requestRender()函数。

I'm simply wondering if there's a better option than this or not. 我只是想知道是否有比这更好的选择。 I'm just concerned that not every phone has the same screen refresh rate, so hard coding any amount doesn't seem to be a desired method. 我只是担心并不是每部手机都具有相同的屏幕刷新率,因此硬编码任何数量似乎都不是理想的方法。 As far as I understand it is not that simple to figure out the given phone's refresh rate, or at least it is not possible with "pure" Java and OpenGL. 据我了解,弄清给定手机的刷新率并不是那么简单,或者至少使用“纯” Java和OpenGL是不可能的。

What you need to do is match the display's frame rate, and advance game state according to how much time has elapsed since the previous frame. 您需要做的就是匹配显示器的帧频,并根据自上一帧以来已经过的时间前进游戏状态。 There are two ways to go about this: 有两种解决方法:

  1. Stuff the BufferQueue full and rely on the "swap buffers" back-pressure. 将BufferQueue塞满,并依靠“交换缓冲区”背压。

    This is very easy to implement: just swap buffers as fast as you can. 这很容易实现:只需尽快交换缓冲区即可。 In early versions of Android this could actually result in a penalty where SurfaceView#lockCanvas() would put you to sleep for 100ms. 在早期的Android版本中,这实际上可能会导致SurfaceView#lockCanvas()使您进入睡眠状态100毫秒的惩罚。 Now it's paced by the BufferQueue, and the BufferQueue is emptied as quickly as SurfaceFlinger is able. 现在,它由BufferQueue加快速度,并且BufferQueue的排空速度与SurfaceFlinger一样快。

  2. Use Choreographer. 使用编舞。

    Choreographer allows you to set a callback that fires on the next VSYNC. Choreographer允许您设置在下一个VSYNC上触发的回调。 The actual VSYNC time is passed in as an argument. 实际的VSYNC时间将作为参数传递。 So even if your app doesn't wake up right away, you still have an accurate picture of when the display refresh period began. 因此,即使您的应用没有立即唤醒,您仍然可以准确了解显示刷新周期的开始时间。 Using this value, rather than the current time, yields a consistent time source for your game state update logic. 使用此值而不是当前时间可以为您的游戏状态更新逻辑提供一致的时间源。

source: https://source.android.com/devices/graphics/arch-gameloops 来源: https : //source.android.com/devices/graphics/arch-gameloops

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM