我正在尝试用gl上下文设置一个CAEAGLLayer子类。也就是说,我不是创建一个返回CAEAGLLayer的UIView子类,并从UIView子类别中将gl上下文绑定到该层,而是直接对该层进行子类别化,并尝试在该层的init中设置上下文,如下所示:
- (id)init
{
self = [super init];
if (self) {
self.opaque = YES;
_glContext = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2];
NSAssert([EAGLContext setCurrentContext:_glContext], @"");
glGenRenderbuffers(1, &_colorRenderBuffer);
glBindRenderbuffer(GL_RENDERBUFFER, _colorRenderBuffer);
[_glContext renderbufferStorage:GL_RENDERBUFFER fromDrawable:self];
glGenFramebuffers(1, &_framebuffer);
glBindFramebuffer(GL_FRAMEBUFFER, _framebuffer);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, _colorRenderBuffer);
/// . . .
到那时为止,一切似乎都很好。然而,我随后尝试创建一个具有"直通"顶点/片段着色器对的着色器程序,并且在链接该程序时未返回任何错误,验证失败,表示:"当前绘制帧缓冲区无效。"
链接和验证着色器程序的代码(在附加着色器之后)看起来是这样的,以防万一:
- (BOOL)linkAndValidateProgram
{
GLint status;
glLinkProgram(_shaderProgram);
#ifdef DEBUG
GLint infoLogLength;
GLchar *infoLog = NULL;
glGetProgramiv(_shaderProgram, GL_INFO_LOG_LENGTH, &infoLogLength);
if (infoLogLength > 0) {
infoLog = (GLchar *)malloc(infoLogLength);
glGetProgramInfoLog(_shaderProgram, infoLogLength, &infoLogLength, infoLog);
NSLog(@"Program link log:n%s", infoLog);
free(infoLog);
}
#endif
glGetProgramiv(_shaderProgram, GL_LINK_STATUS, &status);
if (!status) {
return NO;
}
glValidateProgram(_shaderProgram);
#ifdef DEBUG
glGetProgramiv(_shaderProgram, GL_INFO_LOG_LENGTH, &infoLogLength);
if (infoLogLength > 0) {
infoLog = (GLchar *)malloc(infoLogLength);
glGetProgramInfoLog(_shaderProgram, infoLogLength, &infoLogLength, infoLog);
NSLog(@"Program validation log:n%s", infoLog);
free(infoLog);
}
#endif
glGetProgramiv(_shaderProgram, GL_VALIDATE_STATUS, &status);
if (!status) {
return NO;
}
glUseProgram(_shaderProgram);
return YES;
}
我想知道在CAEAGLLayer的整个生命周期中,是否有一些我可能不知道的额外设置,并且可能会通过尝试在init中设置GL来跳过?
问题是该层在init中没有维度。这反过来又使得尝试将渲染缓冲区存储设置为层意味着缓冲区为0。
UPDATE:我目前最好的想法是,我不应该在init上强加一个大小(这对于测试来说很好,但有点过时),而应该在层改变大小时重新设置缓冲区存储。所以我像这样重写-setBounds:
:
- (void)setBounds:(CGRect)bounds
{
[super setBounds:bounds];
[_context renderbufferStorage:GL_RENDERBUFFER fromDrawable:self];
glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_WIDTH, &someVariableToHoldWidthIfYouNeedIt);
glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_HEIGHT, &someVariableToHoldHeightIfYouNeedIt);
}
据我所知,您必须覆盖View中的layerClass方法,如以下
+ (Class)layerClass
{
return [MYCEAGLLayer class];
}
此外,您还必须在MYCEAGLLayer上设置drawableProperties。