2013-06-25 36 views
1

我想创建一个GLKView,我在其中添加多维数据集并绘制它们。问题是,每个立方体都是NSObject类型,并有自己的顶点和纹理缓冲区,但我想在单个上下文中绘制它们。为了做到这一点,我遵循了一些WWDC视频并创建了两个上下文,一个用于渲染,另一个用于纹理加载,我将这两个上下文放在同一个共享组中。代码方面,我在这方面做了什么,在我的GLKView中添加了一个名为renderContext的属性,我想要所有的立方体都被绘制,并且我还设置了一个loaderContext属性,我要载入纹理。然而,没有任何东西,我没有看到任何东西,有时我得到一个崩溃和GL错误0x0500。它用于工作和模型视图矩阵应正确设置和一切。引入异步加载和两个共享上下文导致问题...在OpenGL ES 2.0和iOS中的异步纹理加载和共享组

下面是代码:

这在GLKView:(含有立方体)集装箱

- (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的共享组中,所以纹理应该被正确绘制,对吗?

-(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]; 

     }); 

    }]; 
} 

回答

4

它看起来像你做更多的上下文管理比是必要的:

  • GLKTextureLoader只需要知道哪些EAGLSharegroup在创建它的纹理你不必创建一个EAGLContext上。它的代表和您在代码中创建的那个已经不被传入任何GLKTextureLoader方法。
  • 您不应该手动管理当前的EAGLContext-事实上,GLKView的文档特别提到您不应该在绘图方法中更改当前上下文。

这样做的最终结果是,不是从现有的情况下提取EAGLSharegroupGLKTextureLoader创作等,你应该没有新的环境管理代码。

此外,它看起来像加载纹理的结果永远不会使它从loadTextureForTexture:withView:。您的texN变量未通过引用传递到函数中,因此texName仅对loadTextureForTexture:withView:和您的纹理加载完成块可见。一旦loadTextureForTexture:withView:返回并且您的完成块被调用,数据就消失了。似乎应该有某种CubeView二传手,需要调用您收到的GLKTextureInfo *

+0

非常感谢你枢轴,这非常帮助我!但是,异步绘图仍然存在问题。如果我异步调用'-display'方法,那么应用程序会崩溃,如果我同步执行它,它将起作用。 –

+0

你如何试图触发异步显示?看起来你应该在你的视图中从主队列异步调用'setNeedsDisplay'。 – Pivot

+0

setNeedsDisplay在GLKView中做了什么?当我打电话给我时,我确实在你的代码中看到了上面的内容。我实际上在容器(GLKView)上调用'-display',它基本上遍历所有的立方体(NSObjects),并在GLKView的委托方法中绘制它们,它是' - (void)glkView:(GLKView *)view drawInRect :(CGRect)rect' –

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); 
+0

首先,谢谢你的回答。我相对确定没有颜色缓冲区并不是问题的罪魁祸首,因为它曾经在没有颜色缓冲区的情况下工作。如果我的代码是正确的,我会看到纹理,或者,在没有纹理的情况下,黑色立方体...但我只是没有看到任何东西,这是非常奇怪的...... –