我正在尝试创建一个GLKView,我在其中添加多维数据集并绘制它们。问题是,每个立方体都是NSObject类型,并且有自己的顶点和纹理缓冲区,但我想在单个上下文中绘制它们。为了做到这一点,我跟踪了一些WWDC视频并创建了两个上下文,一个用于渲染,一个用于纹理加载,我将两者放在同一个共享组中。代码方面我在这方面所做的是在我的GLKView中添加一个名为renderContext的属性,我想要绘制所有多维数据集,并且我还设置了一个loaderContext属性,我想在其中加载纹理。但是,根本没有绘制,我什么都没看到,有时我得到崩溃和GL ERROR 0x0500。它曾经工作和模型视图矩阵应正确设置和一切。引入异步加载和两个共享上下文导致了这个问题......
以下是代码:
这是GLKView:Container(包含多维数据集)
- (void)setupGL {
self.renderContext = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2];
self.loaderContext = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2 sharegroup:self.renderContext.sharegroup];
glGenFramebuffers(1, &defaultFrameBuffer);
glBindFramebuffer(GL_FRAMEBUFFER, defaultFrameBuffer);
glGenRenderbuffers(1, &depthBuffer);
glBindRenderbuffer(GL_RENDERBUFFER, depthBuffer);
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, self.bounds.size.width, self.bounds.size.height);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, depthBuffer);
glEnable(GL_DEPTH_TEST);
}
- (void)glkView:(GLKView *)view drawInRect:(CGRect)rect {
self.opaque = NO;
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
[EAGLContext setCurrentContext:self.renderContext];
for(Cube *cube in self.cubes){
[cube draw];
}
}
每个单独的多维数据集都设置如下:
-(id)init {
self = [super init];
if(self){
self.effect = [[GLKBaseEffect alloc]init];
self.effect.transform.projectionMatrix = GLKMatrix4MakePerspective(45.0f,0.95f, 0.1f, 2.0f);
self.effect.transform.projectionMatrix = GLKMatrix4Translate(self.effect.transform.projectionMatrix, 0, 0.0, 0.0);
self.effect.transform.modelviewMatrix = GLKMatrix4Translate(self.effect.transform.modelviewMatrix,0,0,-1.3);
glGenBuffers(1, &vertexArray);
glBindBuffer(GL_ARRAY_BUFFER, vertexArray);
glEnableVertexAttribArray(GLKVertexAttribPosition);
glBufferData(GL_ARRAY_BUFFER, sizeof(Vertices), Vertices, GL_STATIC_DRAW);
glVertexAttribPointer(GLKVertexAttribPosition,3,GL_FLOAT,GL_FALSE,0,0);
glGenBuffers(1, &texArray);
glBindBuffer(GL_ARRAY_BUFFER, texArray);
glEnableVertexAttribArray(GLKVertexAttribTexCoord0);
glBufferData(GL_ARRAY_BUFFER, sizeof(TexCoords), TexCoords, GL_STATIC_DRAW);
glVertexAttribPointer(GLKVertexAttribTexCoord0, 2, GL_FLOAT, GL_FALSE, 0,0);
}
return self;
}
并有一个绘制方法:
-(void)draw{
[self.effect prepareToDraw];
self.effect.texture2d0.enabled = YES;
for(int i=0;i<6;i++){
if(i==0)glBindTexture(GL_TEXTURE_2D, frontTexture.name);
if(i==1)glBindTexture(GL_TEXTURE_2D, rightTexture.name);
if(i==2)glBindTexture(GL_TEXTURE_2D, backTexture.name);
if(i==3)glBindTexture(GL_TEXTURE_2D, leftTexture.name);
if(i==4)glBindTexture(GL_TEXTURE_2D, bottomTexture.name);
if(i==5)glBindTexture(GL_TEXTURE_2D, topTexture.name);
glDrawArrays(GL_TRIANGLES, i*6, 6);
}
}
以下是我尝试异步加载纹理的方法:
注意:GLKView(容器)是每个多维数据集的父级,我检索的loaderContext位于renderContext的sharegroup中,因此应该正确绘制纹理,对吧?
-(void)loadTextureForTexture:(GLKTextureInfo*)texN withView:(CubeView *)cV{
__block GLKTextureInfo *texName = texN;
EAGLContext *loaderContext = self.parent.loaderContext;
self.textureLoader = [[GLKTextureLoader alloc]initWithSharegroup:loaderContext.sharegroup];
[EAGLContext setCurrentContext:loaderContext];
NSDictionary *options = [NSDictionary dictionaryWithObject:[NSNumber numberWithBool:YES] forKey:GLKTextureLoaderOriginBottomLeft];
dispatch_queue_t loaderQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_queue_t mainQueue = dispatch_get_main_queue();
[self.textureLoader textureWithCGImage:[self imageWithView:cV].CGImage options:options queue:loaderQueue completionHandler:^(GLKTextureInfo *tex, NSError *err){
texName = tex;
if(err)
NSLog(@"%@", err);
else
NSLog(@"no error");
dispatch_async(mainQueue, ^{
[self display];
});
}];
}
答案 0 :(得分:4)
看起来你正在进行比必要更多的上下文管理:
GLKTextureLoader
只需要知道哪个EAGLSharegroup
来创建其纹理。您不必代表它创建EAGLContext
,而是创建一个GLKTextureLoader
。代码已经没有传递给任何EAGLContext
方法。GLKView
- 事实上,EAGLSharegroup
的文档特别提到您不应该从绘图方法中更改当前上下文。除此之外,除了从GLKTextureLoader
创建的现有上下文中提取loadTextureForTexture:withView:
之外,您应该没有新的上下文管理代码。
此外,看起来加载纹理的结果永远不会超出texN
。您的texName
变量未通过引用传递给函数,因此loadTextureForTexture:withView:
仅对loadTextureForTexture:withView:
和纹理加载完成块可见。一旦CubeView
返回并且您的完成块被调用,数据就会消失。似乎应该有某种GLKTextureInfo *
setter需要使用您收到的{{1}}来调用。
答案 1 :(得分:0)
我在你的代码中看到的第一个问题是没有颜色附加到渲染缓冲区,因此你只能获得不会绘制任何东西的深度输出。
glGenRenderbuffers(1, &colorBuffer);
glBindRenderbuffer(GL_RENDERBUFFER, colorBuffer);
glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA4, self.bounds.size.width, self.bounds.size.height);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT, GL_RENDERBUFFER, colorBuffer);