1

我无法找到正确的位置来为使用 GLKView 和 GLKViewController 的 OpenGLES 应用程序进行着色器设置。

看起来 viewDidLoad 是一个很自然的地方,但是当我在这里尝试这样做时,着色器创建失败。我的设置是这样的:

//shader helper method
int setupShaders(const char* vShader, const char* fShader); //returns a program handle

//inside GLKViewController subclass

static int program;

-(void)viewDidLoad{
    [super viewDidLoad];
    program = setupShaders(vsh, fsh); //program will be zero indicating setup failure
}

我知道设置代码有效,因为如果我在 -(void)glkView:(GLKView *)view drawInRect:(CGRect)rect 中调用它,它就会成功。

所以我假设当调用 -(void)viewDidLoad 时 OpenGL 没有完全初始化,或者必须做一些事情来为我正在尝试做的设置设置正确的 OpenGL 上下文,我只是找不到任何文档关于在哪里或如何正确进行设置。

4

3 回答 3

2

您是对的,您可以轻松设置着色器的最早位置是在drawRect方法中。这是因为必须有一个有效的 GL 上下文当前。根据GLKView 文档

在调用其 drawRect: 方法之前,视图将其 EAGLContext 对象作为当前 OpenGL ES 上下文,并将其帧缓冲区对象绑定到 OpenGL ES 上下文作为渲染命令的目标。

因此,最简单的做法是保留一些信息,例如program句柄,并且仅在它为非零时才进行初始化。

if (program == 0)
    program = setupShaders(vsh, fsh);

如果您不喜欢这种方法,您可以考虑使用您提供的上下文初始化您的 GLKView,或者覆盖bindDrawable. 或者您不能使用 GLKView 并手动执行操作...

于 2013-09-04T04:09:29.447 回答
1

EAGLContext在调用任何 OpenGL ES API 之前需要有一个电流,这包括编译着色器等设置工作。GLKView在调用您的drawRect:(or glkView:drawInRect:) 方法之前使其上下文成为当前上下文,但欢迎您随时将其设置为当前上下文。

视图的上下文是当前的,viewDidAppear:因为该方法是在视图第一次绘制自身之后调用的。不过,我不确定它是否保证在那时是最新的——没有记录的 API 合同表明 aGLKView的上下文在绘图结束后将保持最新。因此,[EAGLContext setCurrentContext:myContext]当您想为您的 OpenGL ES 场景进行设置工作时,最好打电话给自己(即使您选择在 中进行viewDidAppear:)。

创建新 Xcode 项目时,请参阅OpenGL ES 游戏GLKView模板以获取/ GLKViewControllersetup的示例。

于 2013-09-06T21:17:37.973 回答
0

所以事实证明,如果你从内部初始化 -(void)viewDidAppear,它就可以完美地工作。Jacob 的解决方案也可以正常工作,但对我来说,使用回调而不是在 draw 方法中添加条件似乎稍微干净一些。

于 2013-09-06T17:17:49.550 回答