0

I would like to set up a texture array to use for my shape. I have researched this topic on the internet but there are hardly any references a newbie like me can make use of. Again, what I am trying to achieve, is a texture array that I can use to map different textures onto the different faces of my shape. As of now I have got only one texture that I generate from a UIView.

My core questions are:

  • How do I set up this array ?
  • How do I load textures into that array ?
  • How do I use this array ?

Here is my code:

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



}

This method is called when it gets drawn:

- (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));
}
keaukraine
  • 5,315
  • 29
  • 54
the_critic
  • 12,720
  • 19
  • 67
  • 115

1 Answers1

0

Seeing as you are using GLKit I think you can load the textures more easily. First create your CGImageRef:

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

Load that into a GLKTextureInfo ivar textureInfo0 as follows:

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

Do exactly the same with your second texture. That should be named textureInfo1.

Loading the texture coords is done with glEnableVertexAttribArray and glVertexAttribPointer using the GLKVertexAttribTexCoord0 attribute. I think you have that set up above. You will need to map the coordinates from your texture to the target triangles. For example, if you wanted to draw a square - which composes of two triangles - you would need to map the S and T coordinates of the source image twice, i.e. for each respective triangle. For example triangle 1 with coords:

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

(if you plot that you will see it is a triangle)

Then, the second triangle of the square would be as follows:

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

Next, in your drawing method;

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

first, set up the initial texture:

    self.effect.texture2d0.name = self.textureInfo0.name;
    self.effect.texture2d0.target = self.textureInfo0.target;

    [self.effect prepareToDraw];

Draw your triangles as need be with glDrawArrays. Then, replace with the second texture:

    self.effect.texture2d0.name = self.textureInfo1.name;
    self.effect.texture2d0.target = self.textureInfo1.target;

   [self.effect prepareToDraw];

and draw the rest of the triangles with glDrawArrays. They will use the second texture.

Continue replacing self.effect.texture2d0.name and self.effect.texture2d0.target with different GLKTextureInfo instances to draw the different textures.

Max MacLeod
  • 26,115
  • 13
  • 104
  • 132