0
\$\begingroup\$

I'm developing a game for iOS and I'm quite new to OpenGL.

I'd like to ask some help please, hoping that it could be useful to other people too.

At the moment I'm managing buttons simply by drawing textured 'quads' and detecting the user's tapping. I understand that in OpenGL objects are drawn in a sequential order, but I'd like to manage the visibility of the buttons independently from the order in which my buttons (and more in general objects) are drawn.

My question is: is there a not too complex way to accomplish that (without changing the alpha component, but assigning a certain 'depth' to objects for example)?

Here's my class that handles this (hope it's not too much code, but it's for the sake of clarity):

#import "Sprite.h"
#import <QuartzCore/QuartzCore.h>
#import <GLKit/GLKit.h>

typedef struct {
    CGPoint geometryVertex;
    CGPoint textureVertex;
} TexturedVertex;

typedef struct {
    TexturedVertex bl;
    TexturedVertex br;
    TexturedVertex tl;
    TexturedVertex tr;

} TexturedQuad;

@interface Sprite()

@property (strong, nonatomic) GLKBaseEffect     *effect;
@property (assign, nonatomic) TexturedQuad      quad;
@property (strong, nonatomic) GLKTextureInfo    *textureInfo;

@end

@implementation Sprite

@synthesize effect          = _effect;
@synthesize quad            = _quad;
@synthesize textureInfo     = _textureInfo;
@synthesize position        = _position;

@synthesize contentSize     = _size;
@synthesize moveVelocity    = _moveVelocity;

- (void)setupGeometry
{
    self.contentSize = CGSizeMake(self.textureInfo.width, self.textureInfo.height);

    TexturedQuad newQuad;
    newQuad.bl.geometryVertex = CGPointMake(0.0f, 0.0f);
    newQuad.br.geometryVertex = CGPointMake(self.textureInfo.width, 0.0f);
    newQuad.tl.geometryVertex = CGPointMake(0.0f, self.textureInfo.height);
    newQuad.tr.geometryVertex = CGPointMake(self.textureInfo.width, self.textureInfo.height);

    newQuad.bl.textureVertex = CGPointMake(0.0f, 0.0f);
    newQuad.br.textureVertex = CGPointMake(1.0f, 0.0f);
    newQuad.tl.textureVertex = CGPointMake(0.0f, 1.0f);
    newQuad.tr.textureVertex = CGPointMake(1.0f, 1.0f);

    self.quad = newQuad;
}

#pragma mark - Constructors

- (id)initWithLoader:(GLKTextureInfo * (^)(NSDictionary *))textureLoader andEffect:(GLKBaseEffect *)effect
{
    self = [super init];
    if (self)
    {
        self.effect = effect;
        NSDictionary *options = [NSDictionary dictionaryWithObjectsAndKeys:[NSNumber numberWithBool:YES], GLKTextureLoaderOriginBottomLeft, nil];
        self.textureInfo = textureLoader(options);

        [self setupGeometry];
    }
    return self;
}

- (id)initWithFile:(NSString *)fileName effect:(GLKBaseEffect *)effect
{
    return [self initWithLoader:^GLKTextureInfo *(NSDictionary *options) {
        NSString *path = [[NSBundle mainBundle] pathForResource:fileName ofType:nil];

        NSError *error;
        GLKTextureInfo *textureInfo = [GLKTextureLoader textureWithContentsOfFile:path options:options error:&error];

        return textureInfo;
    } andEffect:effect];
}

- (id)initWithCGImage:(CGImageRef)image effect:(GLKBaseEffect *)effect
{
    return [self initWithLoader:^GLKTextureInfo *(NSDictionary *options) {
        NSError *error;
        GLKTextureInfo *textureInfo = [GLKTextureLoader textureWithCGImage:image options:options error:&error];

        return textureInfo;
    } andEffect:effect];
}

#pragma mark - Screen functions

- (GLKMatrix4)modelMatrix
{
    GLKMatrix4 modelMatrix = GLKMatrix4Identity;
    modelMatrix = GLKMatrix4Translate(modelMatrix, self.position.x, self.position.y, self.Zindex);

    modelMatrix = GLKMatrix4Scale(modelMatrix, self.scaleFactor, self.scaleFactor, 1.0f);

    return modelMatrix;
}

- (void)render
{
    self.effect.texture2d0.name = self.textureInfo.name;
    self.effect.texture2d0.enabled = YES;
    self.effect.transform.modelviewMatrix = self.modelMatrix;
    [self.effect prepareToDraw];

    glEnableVertexAttribArray(GLKVertexAttribPosition);
    glEnableVertexAttribArray(GLKVertexAttribTexCoord0);

    long offset = (long)&_quad;
    glVertexAttribPointer(GLKVertexAttribPosition, 2, GL_FLOAT, GL_FALSE, sizeof(TexturedVertex), (void *) (offset + offsetof(TexturedVertex, geometryVertex)));
    glVertexAttribPointer(GLKVertexAttribTexCoord0, 2, GL_FLOAT, GL_FALSE, sizeof(TexturedVertex), (void *) (offset + offsetof(TexturedVertex, textureVertex)));

    glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
}

- (void)update:(float)seconds
{
    GLKVector2 curMove = GLKVector2MultiplyScalar(self.moveVelocity, seconds);
    self.position = GLKVector2Add(self.position, curMove);
}

@end

Thank you very much in advance.

\$\endgroup\$

1 Answer 1

1
\$\begingroup\$

To draw things with transparency in OpenGL you will have to sort them by depth so you can render them in back-to-front order.

I would suggest that your render function create a list of all the textured quads to draw along with a depth value. Then sort the list. Then draw it.

\$\endgroup\$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .