【问题标题】:How to use multiple textures in OpenGL ES 2.0如何在 OpenGL ES 2.0 中使用多个纹理
【发布时间】:2013-01-06 23:40:41
【问题描述】:

我想设置一个纹理数组用于我的形状。我在互联网上研究过这个话题,但几乎没有像我这样的新手可以使用的参考资料。 同样,我想要实现的是一个纹理数组,我可以使用它来将不同的纹理映射到我形状的不同面上。 到目前为止,我只有一个从 UIView 生成的纹理。

我的核心问题是:

  • 如何设置这个阵列?
  • 如何将纹理加载到该数组中?
  • 如何使用这个数组?

这是我的代码:

- (void)setupGL {



    [EAGLContext setCurrentContext:self.myContext];

    self.effect = [[GLKBaseEffect alloc] init];
    self.layer.contentsScale = 2.0;
    BOOL useTexture = YES;

    // Create default framebuffer object.
    glGenFramebuffers(1, &defaultFrameBuffer);
    glBindFramebuffer(GL_FRAMEBUFFER, defaultFrameBuffer);

    myView = [[MyView alloc]initWithFrame:CGRectMake(0,0,320,320)];

    self.effect.transform.projectionMatrix = GLKMatrix4MakePerspective(45.0f,0.9f, 0.01f, .08f);
    self.effect.transform.projectionMatrix = GLKMatrix4Translate(self.effect.transform.projectionMatrix, 0, 0.1, 1.2);
    rotMatrix = GLKMatrix4Translate(self.effect.transform.modelviewMatrix,0,0,-2);
    self.effect.transform.modelviewMatrix = rotMatrix;


        /*********************
         MAPPING UIVIEW ONTO THE FACE
         ****************/

        CGColorSpaceRef colourSpace = CGColorSpaceCreateDeviceRGB();

        self.effect.texture2d0.enabled = true;

        GLubyte *pixelBuffer = (GLubyte *)malloc(
                                                 4 *
                                                 myView.bounds.size.width * coordToPixScale *
                                                 myView.bounds.size.height * coordToPixScale);


            CGContextRef context =
            CGBitmapContextCreate(pixelBuffer,
                                  myView.bounds.size.width*coordToPixScale, myView.bounds.size.height*coordToPixScale,
                                  8, 4*myView.bounds.size.width *coordToPixScale,
                                  colourSpace,
                                  kCGImageAlphaPremultipliedLast | kCGBitmapByteOrder32Big);
            CGColorSpaceRelease(colourSpace);

            // draw the view to the buffer
            [myView.layer renderInContext:context];

            // upload to OpenGL
            glTexImage2D(GL_TEXTURE_2D, 0,
                         GL_RGBA,
                         myView.bounds.size.width * coordToPixScale, myView.bounds.size.height * coordToPixScale, 0,
                         GL_RGBA, GL_UNSIGNED_BYTE, pixelBuffer);

            glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
            glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
            glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
            glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);

            // clean up
            CGContextRelease(context);




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

        /**************************
         ******************************************/
        free(pixelBuffer);




    glGenRenderbuffers(1, &depthBuffer);
    glBindRenderbuffer(GL_RENDERBUFFER, depthBuffer);
    glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, myView.bounds.size.width * coordToPixScale, myView.bounds.size.height * coordToPixScale);
    glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, depthBuffer);

    glEnable(GL_DEPTH_TEST);

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



}

绘制时调用此方法:

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

    [self.effect prepareToDraw];

    glDrawArrays(GL_TRIANGLES, 0, sizeof(Vertices) / (sizeof(GLfloat) * 3));
}

【问题讨论】:

    标签: iphone ios opengl-es-2.0 textures glkit


    【解决方案1】:

    看到您正在使用GLKit,我认为您可以更轻松地加载纹理。首先创建你的CGImageRef

       CGImageRef image0 = 
      [[UIImage imageNamed:@"image0.png"] CGImage];
    

    将其加载到GLKTextureInfo ivar textureInfo0 中,如下所示:

      self.textureInfo0 = [GLKTextureLoader 
      textureWithCGImage:image1
      options:[NSDictionary dictionaryWithObjectsAndKeys:
         [NSNumber numberWithBool:YES], 
         GLKTextureLoaderOriginBottomLeft, nil] 
      error:NULL];
    

    对第二个纹理执行完全相同的操作。那应该命名为textureInfo1

    通过glEnableVertexAttribArrayglVertexAttribPointer 使用GLKVertexAttribTexCoord0 属性加载纹理坐标。我想你上面已经设置好了。您需要将坐标从纹理映射到目标三角形。例如,如果您想绘制一个正方形 - 它由两个三角形组成 - 您需要将源图像的 S 和 T 坐标映射两次,即针对每个相应的三角形。例如带坐标的三角形 1:

    {0.0f, 0.0f}, {1.0f, 0.0f}, {0.0f, 1.0f}. 
    

    (如果你画出来你会看到它是一个三角形)

    那么,正方形的第二个三角形如下:

    {1.0f, 0.0f}, {0.0f, 1.0f}, {1.0f, 1.0f}. 
    

    接下来,在你的绘图方法中;

    - (void)glkView:(GLKView *)view drawInRect:(CGRect)rect 
    

    首先,设置初始纹理:

        self.effect.texture2d0.name = self.textureInfo0.name;
        self.effect.texture2d0.target = self.textureInfo0.target;
    
        [self.effect prepareToDraw];
    

    根据需要使用glDrawArrays 绘制三角形。然后,替换为第二个纹理:

        self.effect.texture2d0.name = self.textureInfo1.name;
        self.effect.texture2d0.target = self.textureInfo1.target;
    
       [self.effect prepareToDraw];
    

    并使用glDrawArrays 绘制其余的三角形。他们将使用第二个纹理。

    继续用不同的GLKTextureInfo 实例替换self.effect.texture2d0.nameself.effect.texture2d0.target 以绘制不同的纹理。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-05-19
      • 2017-11-09
      • 1970-01-01
      • 2014-10-28
      • 2012-04-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多