[英]On-demand OpenGL ES rendering using GLKit
I am looking into converting my OpenGL rendering code to take advantage of a few features of GLKit
(namely the asynchronous texture loading and the automation provided by GLKView/Controller
). 我正在研究转换我的OpenGL渲染代码以利用
GLKit
的一些功能(即异步纹理加载和GLKView/Controller
提供的自动化)。 However, it appears that the classes are designed mainly to accommodate people rendering using an animation loop, whereas I'm working with on-demand rendering. 但是,似乎这些类的设计主要是为了适应使用动画循环渲染的人,而我正在使用按需渲染。 Additionally, some of the rendering is to a texture rather than the GLKView's framebuffer, so should I be looking to just subclass the GLKView and add additional FBOs?
另外,一些渲染是针对纹理而不是GLKView的帧缓冲,所以我是否应该只是将GLKView子类化并添加其他FBO?
Is there a recommended approach for this type of setup? 这种类型的设置是否有推荐的方法? I would expect something along the lines of:
我希望有类似的东西:
preferredFramesPerSecond
to 0
, or just pause the frame updates? preferredFramesPerSecond
为0
,或者只是暂停帧更新? glkViewControllerUpdate
or glkView:drawInRect:
methods and just draw what I need, when I need it. glkViewControllerUpdate
或glkView:drawInRect:
方法,只需在需要时绘制我需要的东西。 setNeedsDisplay
as with a normal UIView
in order to display the frame (do I need to call bindDrawable
given that I will be rendering to a texture as well?). setNeedsDisplay
和普通的UIView
一起显示框架(我是否需要调用bindDrawable
因为我也将渲染到纹理?)。 Perhaps it's not worth the effort if this is not what the new API is designed for? 如果这不是新API的设计,那么也许不值得努力? I wish the documentation was a little more thorough than it is.
我希望文档比它更彻底。 Perhaps more samples will be provided when the API has 'matured' a little...
当API稍微“成熟”时,可能会提供更多样本......
Thanks 谢谢
The approach I ended up using was to not bother with the GLKViewController
, but just use GLKView
directly under a UIViewController
subclass. 我最终使用的方法是不打扰
GLKViewController
,而只是直接在UIViewController
子类下使用GLKView
。
Clearly, the GLKViewController
is intended for use by people who need a consistent rendering loop for apps such as games. 显然,
GLKViewController
旨在供那些需要为游戏等应用程序提供一致渲染循环的人使用。 Without it, drawing to the GLKView
is as simple as calling [glkView setNeedsDisplay]
. 没有它,绘制到
GLKView
就像调用[glkView setNeedsDisplay]
一样简单。 Be sure to set enableSetNeedsDisplay
to YES
in order to enable this behaviour. 请务必将
enableSetNeedsDisplay
设置为YES
以启用此行为。
If you did still want to make use of a GLKViewController
, you can disable the animation rendering loop in viewWillAppear
like so: 如果您仍想使用
GLKViewController
,则可以在viewWillAppear
禁用动画渲染循环,如下所示:
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated]; // setPaused automatically set to NO in super's implementation
[self setPaused:YES];
}
Also, set resumeOnDidBecomeActive
to NO
to prevent the view controller from resuming again automatically. 另外,将
resumeOnDidBecomeActive
设置为NO
以防止视图控制器自动重新开始。
Using a plain UIViewController
with a GLKView
is perfectly acceptable however, and I have seen it recommended by an Apple engineer as an appropriate way to perform on-demand drawing. 然而,使用带有
GLKView
的普通UIViewController
是完全可以接受的,我已经看到Apple工程师推荐它作为执行按需绘图的适当方式。
I've just converted my code from using an EAGLContext manager I rolled myself to using the GLKit classes. 我刚刚使用EAGLContext管理器将我的代码转换为使用GLKit类。
You suggest you might "..ignore the.. glkView:drawInRect:
methods and just draw what [you] need, when I need it". 你建议你可以“..
glkView:drawInRect:
.. glkView:drawInRect:
方法,只需要在我需要的时候画出你需要的东西”。 This seems like a sensible option performance-wise; 这似乎是表现明智的明智选择; I assume (though haven't tried) if you simply don't specify a
GLKViewDelegate
or provide a subclassed GLKView
with its drawInRect:
defined then no animation loop rendering will occur. 我假设(虽然没有尝试过)如果你只是没有指定
GLKViewDelegate
或者提供带有drawInRect:
的子类GLKView
drawInRect:
定义那么就不会发生动画循环渲染。 Have you attempted this? 你试过这个吗?
The alternative would be to simply create some @property (assign, nonatomic) BOOL shouldUpdate;
另一种方法是简单地创建一些
@property (assign, nonatomic) BOOL shouldUpdate;
in your MyController : GLKViewController <GLKViewDelegate>
class which will only update if there is something to do: 在你的
MyController : GLKViewController <GLKViewDelegate>
类中,只有在有事情要做时才会更新:
[self setDelegate:self]; // in init or awakeFromNib or other..
-(void)glkView:(GLKView *)view drawInRect:(CGRect)rect {
if ([self shouldUpdate]) { ...
I'm sure you get the idea, it's hardly complicated. 我相信你明白了,这并不复杂。
One thing worth mentioning: the official API docs state that viewDidLoad
should be used in your GLKViewController
for initial GL setup. 值得一提的是:官方API文档声明
viewDidLoad
应该在您的GLKViewController
用于初始GL设置。 I had issues with this; 我有这个问题; for some reason my
glCreateShader
calls always returned zero. 由于某种原因,我的
glCreateShader
调用总是返回零。 This may have been due to my setting the EAGLContext
post-initialisation; 这可能是由于我设置
EAGLContext
后初始化; I couldn't pass it as an init
parameter since I created the controller in Storyboard. 我无法将其作为
init
参数传递,因为我在Storyboard中创建了控制器。 However, there was nothing logically wrong with the code, so I offer this friendly warning in case you encounter similar issues. 但是,代码没有任何逻辑上的错误,所以如果您遇到类似问题,我会提供此友好警告。 My solution is simply to have the following in my drawInRect:
我的解决方案只是在我的drawInRect中有以下内容:
-(void)glkView:(GLKView *)view drawInRect:(CGRect)rect {
if ([self initialGLSetupDone] == NO) {
[self beforeFirstRender];
[self setInitialGLSetupDone:YES];
}
// .. rest of render code goes here.
}
Obviously it's not ideal to have an IF in there unnecessarily, but it was an easy solution. 显然,不必要地在那里安装IF并不理想,但这是一个简单的解决方案。
Let me know how it goes if you try updating to use GLKit. 如果您尝试更新以使用GLKit,请告诉我它是怎么回事。
After you have created GLKView, add this line: 创建GLKView后,添加以下行:
glkView.enableSetNeedsDisplay = TRUE;
(Because of this, no one will redraw the view automatically) (因此,没有人会自动重绘视图)
When you want redraw, insert this line: 如果要重绘,请插入以下行:
[glkView setNeedsDisplay];
... then drawInRect
routine will be called only once. ...然后
drawInRect
例程将只调用一次。
Hope it helps. 希望能帮助到你。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.