簡體   English   中英

OpenGL ES 2.0和iOS中的異步紋理加載和共享組

[英]Asynchronous texture loading and sharegroups in OpenGL ES 2.0 and iOS

我正在嘗試創建一個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];

        });

    }];
}

看起來您正在進行比必要更多的上下文管理:

  • GLKTextureLoader只需要知道哪個EAGLSharegroup可以創建它的紋理。你不必代表它創建一個EAGLContext ,而你在代碼中創建的EAGLContext已經沒有傳遞給任何GLKTextureLoader方法。
  • 你不應該需要手動管理當前EAGLContext -in事實上,對於文檔GLKView特別提到,你不應該在當前背景下,從您的繪圖方法中改變。

最終結果是,除了從現有上下文中提取EAGLSharegroup以創建GLKTextureLoader ,您應該沒有新的上下文管理代碼。

此外,看起來加載紋理的結果永遠不會使它超出loadTextureForTexture:withView: . 您的texN變量不會通過引用傳遞給函數,因此texName僅對loadTextureForTexture:withView:和紋理加載完成塊可見。 一旦loadTextureForTexture:withView:返回並調用完成塊,數據就會消失。 似乎應該有某種CubeView設置器需要使用您收到的GLKTextureInfo *進行調用。

我在你的代碼中看到的第一個問題是沒有顏色附加到渲染緩沖區,所以你只能獲得不會繪制任何東西的深度輸出。

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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM