Domanda

I am rendering a scene that has to get rebuilt whenever there is an orientation change in order to fill the screen appropriately. The scene renders a few vertex array objects of regular colored quads and an array of textured vertex array objects. All of these drawing elements including any shaders and associated arrays of vertices, indices, etc are included in a class, so I just blow away the class each time and do a new alloc/init on rotation.

When the scene is first created, everything looks fine. However for some reason and in no discernible pattern, weird triangles may show up on any subsequent rotation. For a particular scene, the occurrence seems to be deterministic every time it is loaded. However, from scene to scene, sometimes the artifacts show up, and sometimes everything looks lovely.

I can't figure out whether it is how I am breaking my memory down (even in ARC, I need to release some of it) or if it is how I am creating my VAOs. However, since the problem only occurs when I tearDown the scene and rebuild it... and then I start spinning my wheels again with that thought process.

I have quite a bit of code so here is some (hopefully) relevant code.

Here is some drawing code for colored quad VAO. I'm adding vertices to an NSMutableArray because I don't know how many quads there will be.

- (void) buildNode : (NSDictionary *) nodeDictionary
            bounds : (BoundsGL) bounds
{
    if (!nodeDictionary)
    {
        return;
    }

    NSString *jobidstr = [nodeDictionary objectForKey:kNodeJobidKey];
    NSInteger jobid = jobidstr == NULL ? -1 : [jobidstr intValue];

    NSString *colorHexStr = [nodeDictionary objectForKey:kNodeColorKey];
    ColorGL color = HexidecimalStringToColorGL(colorHexStr);


    //
    // indices

    [_coloredQuadIndices addObject:[NSNumber numberWithInt:_coloredQuadVertices.count]];
    [_coloredQuadIndices addObject:[NSNumber numberWithInt:_coloredQuadVertices.count+1]];
    [_coloredQuadIndices addObject:[NSNumber numberWithInt:_coloredQuadVertices.count+2]];
    [_coloredQuadIndices addObject:[NSNumber numberWithInt:_coloredQuadVertices.count+2]];
    [_coloredQuadIndices addObject:[NSNumber numberWithInt:_coloredQuadVertices.count+1]];
    [_coloredQuadIndices addObject:[NSNumber numberWithInt:_coloredQuadVertices.count+3]];


    //
    // vertices

    GLfloat x2 = bounds.pos.x + bounds.size.w;
    GLfloat y2 = bounds.pos.y + bounds.size.h;

    PointGL blp = {bounds.pos.x, bounds.pos.y};
    PointGL brp = {x2, bounds.pos.y};
    PointGL tlp = {bounds.pos.x, y2};
    PointGL trp = {x2, y2};

    ColoredVertex bl = { .pos = blp, .color = color };
    ColoredVertex br = { .pos = brp, .color = color };
    ColoredVertex tl = { .pos = tlp, .color = color };
    ColoredVertex tr = { .pos = trp, .color = color };

    NSValue *tlv = [NSValue valueWithBytes:&tl objCType:@encode(ColoredVertex)];
    NSValue *blv = [NSValue valueWithBytes:&bl objCType:@encode(ColoredVertex)];
    NSValue *trv = [NSValue valueWithBytes:&tr objCType:@encode(ColoredVertex)];
    NSValue *brv = [NSValue valueWithBytes:&br objCType:@encode(ColoredVertex)];
    [_coloredQuadVertices addObject:tlv];
    [_coloredQuadVertices addObject:blv];
    [_coloredQuadVertices addObject:trv];
    [_coloredQuadVertices addObject:brv];
}

some code to create the VAO for textured quads:

#import "TexturedQuadVAO.h"
#import "Texture.h"
#import "ShaderUtil.h"

@interface TexturedQuadVAO()
{
    GLuint _textureUniformLocation;
}

@property (strong, nonatomic) Texture *texture;

@end


@implementation TexturedQuadVAO

@synthesize vaoid = _vaoid;

@synthesize vertexBuffer = _vertexBuffer;
@synthesize vcount = _vcount;
@synthesize vsize = _vsize;

@synthesize indexBuffer = _indexBuffer;
@synthesize icount = _icount;
@synthesize isize = _isize;

@synthesize texture = _texture;

- (id) initWithData : (TexturedVertex *) vertices
   numberOfVertices : (NSUInteger) vcount
       verticesSize : (size_t) vsize
            indices : (GLushort *) indices
    numberOfIndices : (NSUInteger) icount
        indicesSize : (size_t) isize
           viewSize : (CGSize) viewSize
               text : (NSString *) text
        textureSize : (SizeGL) textureSize
    foregroundColor : (UIColor *) fgcolor
    backgroundColor : (UIColor *) bgcolor
textureUniformLocation : (GLuint) textureUniformLocation
{
    self = [super init];

    if (self)
    {
        //
        // geometry

        self.vcount = vcount;
        self.vsize = vsize;

        self.icount = icount;
        self.isize = isize;


        //
        // texture

        self.texture = [[Texture alloc] init];
        UIFont *font = [UIFont fontWithName:@"Arial" size:24];
        SizeGL tSize = {textureSize.w * 2.5, textureSize.h * 2.5};
        UIImage *img = createTextImage(viewSize, text, tSize, font, fgcolor, bgcolor);

        [self.texture setupTextureWithImage:img];


        //
        // for shaders
        _textureUniformLocation = textureUniformLocation;


        [self createVertexArrayObject:vertices indices:indices];
    }

    return self;
}

- (void) createVertexArrayObject : (TexturedVertex *) vertices
                         indices : (GLushort *) indices
{
    checkGLError(@"  TexturedQuadVAO createVertexArrayObject ");

    // vertex array object

    glGenVertexArraysOES(1, &_vaoid);
    glBindVertexArrayOES(_vaoid);


    //
    // vertices buffer

    GLuint vb;
    glGenBuffers(1, &vb);
    self.vertexBuffer = vb;
    glBindBuffer(GL_ARRAY_BUFFER, self.vertexBuffer);
    glBufferData(GL_ARRAY_BUFFER, self.vsize, vertices, GL_STATIC_DRAW);   // copy data into buffer object

    // position vertex attribute
    glEnableVertexAttribArray(GLKVertexAttribPosition);
    glVertexAttribPointer(GLKVertexAttribPosition, 2, GL_FLOAT, GL_FALSE, sizeof(TexturedVertex), (const GLvoid *) offsetof(TexturedVertex, pos));

    // color vertex attribute
    glEnableVertexAttribArray(GLKVertexAttribColor);
    glVertexAttribPointer(GLKVertexAttribColor, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(TexturedVertex), (const GLvoid *) offsetof(TexturedVertex, color));

    // textures vertex attribute
    glEnableVertexAttribArray(GLKVertexAttribTexCoord0);
    glVertexAttribPointer(GLKVertexAttribTexCoord0, 2, GL_FLOAT, GL_FALSE, sizeof(TexturedVertex), (const GLvoid  *) offsetof(TexturedVertex, texcoord));


    //
    // index data buffer

    GLuint ib;
    glGenBuffers(1, &ib);
    self.indexBuffer = ib;
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, self.indexBuffer);
    glBufferData(GL_ELEMENT_ARRAY_BUFFER, self.isize, indices, GL_STATIC_DRAW); // copy index data into buffer object


    //
    // clear binds

    glBindVertexArrayOES(0);        // ok to unbind for now, and bind when we want to render
    glBindBuffer(GL_ARRAY_BUFFER, 0);
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
    checkGLError(@"2 TexturedQuadVAO createVertexArrayObject ");
}

- (void) render
{
    checkGLError(@"  TexturedQuadVAO ");

    glBindVertexArrayOES(_vaoid);
    checkGLError(@"2 TexturedQuadVAO ");

    glActiveTexture(GL_TEXTURE0);
    checkGLError(@"3 TexturedQuadVAO ");

    [self.texture bind];
    checkGLError(@"4 TexturedQuadVAO ");

    glUniform1i(_textureUniformLocation, 0);
    checkGLError(@"5 TexturedQuadVAO ");

    //glDrawElements(GL_TRIANGLE_STRIP, self.vsize/sizeof(GLshort), GL_UNSIGNED_SHORT, 0);
    glDrawElements(GL_TRIANGLE_STRIP, self.vsize/sizeof(GLushort), GL_UNSIGNED_SHORT, 0);
    checkGLError(@"6 TexturedQuadVAO ");

    [self.texture unbind];
    checkGLError(@"7 TexturedQuadVAO ");

    glBindVertexArrayOES(0);
    checkGLError(@"8 TexturedQuadVAO ");
}

- (void) tearDown
{
    [self.texture deleteTexture];

    glDeleteBuffers(1, &_vertexBuffer);
    glDeleteBuffers(1, &_indexBuffer);
    glDeleteVertexArraysOES(1, &_vaoid);
}

@end

my teardown code:

- (void) tearDown
{
    // VAOs

    for (int i=0; i<_texturedQuadArray.count; i++)
    {
        TexturedVAO *vao = [_texturedQuadArray objectAtIndex:i];
        [vao tearDown];
        vao = nil;
    }
    [_texturedQuadArray removeAllObjects];

    if (_coloredQuadVAO)
    {
       [_coloredQuadVAO tearDown];
       _coloredQuadVAO = nil;
    }

    if (_coloredQuadOutlinesVAO)
    {
       [_coloredQuadOutlinesVAO tearDown];
       _coloredQuadOutlinesVAO = nil;
    }

    // shaders

    if (_shaders.colorShader)
    {
       glDeleteProgram(_shaders.colorShader);
       _shaders.colorShader = 0;
    }

    if (_shaders.textureShader)
    {
       glDeleteProgram(_shaders.textureShader);
       _shaders.textureShader = 0;
    }

    checkGLError(@"Main tearDown");
}

I have scoured the web and tried everything I could think of to ferret out the issue for the last several days and it is starting to become an enormous bummer. Any ideas would be very much appreciated!

Update: I found the problem!

As I had suspected, it was something incredibly trivial that I spent so many days trying to find - in all the wrong places!

The culprit was this line:

glDrawElements(GL_TRIANGLE_STRIP, self.vsize/sizeof(GLushort), GL_UNSIGNED_SHORT, 0);

I glazed over this line a zillion times before I noticed this messed up calculation and immediately changed it to:

glDrawElements(GL_TRIANGLE_STRIP, self.icount, GL_UNSIGNED_SHORT, 0);

i.e. I changed to count to the actual indice count.

È stato utile?

Soluzione

As I had thought, it was something incredibly trivial that I spent so many days trying to find - in all the wrong places!

The culprit was this line in the 2nd group of code for TexturedQuadVAOs:

glDrawElements(GL_TRIANGLE_STRIP, self.vsize/sizeof(GLushort), GL_UNSIGNED_SHORT, 0);

I glazed over this line a zillion times before I noticed this messed up calculation and immediately changed it to:

glDrawElements(GL_TRIANGLE_STRIP, self.icount, GL_UNSIGNED_SHORT, 0);

i.e. I changed to count to the actual indice count.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top