Issue with Open GL VBO & Texturing (I guess)

Posts: 10
Joined: 2009.01
Post: #1

I am new to Open GL (and still fairly new to Obj-c).
I'm trying to use VBO to speed up my Open GL code.. however, I'm stuck since 2 days with my scene not showing any texture.
I started by adapting the GL Sprite example, adding some transforms and vbo along the way..
I have tried hard to fix it by myself, but I cant found what is the problem with my code.. so If an expert can spot the bug (and explain what I did wrong), I would gladly appreciate it..

here is the code (i extracted the exact parts, to keep the code simple to read):
// Sets up an array of values to use as the sprite vertices.
const GLfloat spriteVertices[] = {
-16.f, -16.f,
16.f, -16.f,
-16.f,  16.f,
16.f,  16.f

// Sets up an array of values for the texture coordinates.
const GLshort spriteTexcoords[] = {
0, 0,
1, 0,
0, -1,
1, -1,

const GLushort spriteIndexes[] = { 0, 1, 2, 3 };

- (void)setupView
    CGImageRef spriteImage;
    CGContextRef spriteContext;
    GLubyte *spriteData;
    size_t    width, height;
    // Sets up matrices and transforms for OpenGL ES
    glViewport(0, 0, backingWidth, backingHeight);
    glOrthof(0.f, 480.0f, 320.0f, 0.0f, -1.0f, 1.0f);

    // Clears the view with black
    glClearColor(0.0f,0.0f, 0.0f, 1.0f);
    // Sets up pointers and enables states needed for using vertex arrays and textures
    glGenBuffers(1, &elementVerticesID);
    glBindBuffer(GL_ARRAY_BUFFER, elementVerticesID);
    glBufferData(GL_ARRAY_BUFFER, sizeof(spriteVertices), spriteVertices, GL_STATIC_DRAW);  
    NSLog(@"sizeof texture coordinates: %d", sizeof(spriteTexcoords));
    glGenBuffers(1, &elementTextureCoordinatesID);
    glBindBuffer(GL_ARRAY_BUFFER, elementTextureCoordinatesID);
    glBufferData(GL_ARRAY_BUFFER, sizeof(spriteTexcoords), spriteTexcoords, GL_STATIC_DRAW);

    // Indexes
    glGenBuffers(1, &elementIndexesID);
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, elementIndexesID);
    glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(spriteIndexes), spriteIndexes, GL_STATIC_DRAW);
    // Creates a Core Graphics image from an image file
    spriteImage = [UIImage imageNamed:@"flower_green.png"].CGImage;
    // Texture dimensions must be a power of 2. If you write an application that allows users to supply an image,
    // you'll want to add code that checks the dimensions and takes appropriate action if they are not a power of 2.

    if( spriteImage ) {
        // Get the width and height of the image
        width = CGImageGetWidth(spriteImage);
        height = CGImageGetHeight(spriteImage);
        if ( width < 64 || height < 64 ) width = height = 64;
        //NSLog(@"%d, %d", width, height);

        // Allocated memory needed for the bitmap context
        spriteData = (GLubyte *) malloc(width * height * 4);
        // Uses the bitmatp creation function provided by the Core Graphics framework.
        spriteContext = CGBitmapContextCreate(spriteData, width, height, 8, width * 4, CGImageGetColorSpace(spriteImage), kCGImageAlphaNoneSkipLast); //kCGImageAlphaPremultipliedLast);
        // After you create the context, you can draw the sprite image to the context.
        CGContextDrawImage(spriteContext, CGRectMake(0.0, 0.0, (CGFloat)width, (CGFloat)height), spriteImage);
        // You don't need the context at this point, so you need to release it to avoid memory leaks.
        // Use OpenGL ES to generate a name for the texture.
        glGenTextures(1, &spriteTextureID);
        // Bind the texture name.
        glBindTexture(GL_TEXTURE_2D, spriteTextureID);
        // Speidfy a 2D texture image, provideing the a pointer to the image data in memory
        glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_SHORT, spriteData);
        // Release the image data
        // Set the texture parameters to use a minifying filter and a linear filer (weighted average)
        // Enable use of the texture
        // Set a blending function to use
        glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
        // Enable blending

    glBindBuffer(GL_ARRAY_BUFFER, elementVerticesID);
    glVertexPointer(2, GL_FLOAT, 0, 0);
    glBindBuffer(GL_ARRAY_BUFFER, elementTextureCoordinatesID);
    glTexCoordPointer(2, GL_SHORT, 0, 0);
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, elementIndexesID);

int step;
// Updates the OpenGL view when the timer fires
- (void)drawView
    // Make sure that you are drawing to the current context
    [EAGLContext setCurrentContext:context];
    glBindFramebufferOES(GL_FRAMEBUFFER_OES, viewFramebuffer);

    for(int i = 0; i < 12; ++i)
        for (int j = 0; j < 8; ++j)

            glTranslatef((i * 40.) + 20., (j * 40.) + 20., 0.f);
            glRotatef((i + 1) * step, .0f, .0f, 1.0f);
            glScalef(1. + (i / 10.), 1. + (i / 10.), 1. + (i / 10.));
            glColor4f(1.f, 1.f, 1.f, 1.f);
            glDrawElements(GL_TRIANGLE_STRIP, 4, GL_UNSIGNED_SHORT, 0);
    glBindRenderbufferOES(GL_RENDERBUFFER_OES, viewRenderbuffer);
    [context presentRenderbuffer:GL_RENDERBUFFER_OES];

Thanks a lot!

Quote this message in a reply
Posts: 6
Joined: 2008.12
Post: #2
Hi, are you sure with all those translate and scale your mesh is not off screen ?

Have you tried using glDisable(GL_CULL_FACE) ? Sometimes it happened to me that mesh was drawn CCW ...
Quote this message in a reply
Posts: 249
Joined: 2008.10
Post: #3
Try to add

By the way, opengl textures are from up to bottom.

Usually when you render or draw your mesh you do:

glEnableClientState (GL_VERTEX_ARRAY);
glEnableClientState (GL_NORMAL_ARRAY);
if (m_has_texcoord0) glEnableClientState (GL_TEXTURE_COORD_ARRAY);
glEnableClientState (GL_INDEX_ARRAY);

draw you mesh

if (m_has_texcoord0) glDisableClientState(GL_TEXTURE_COORD_ARRAY);
Quote this message in a reply
Posts: 10
Joined: 2009.01
Post: #4
Nope, did not work Sad
Still all white, no texture..

Any other idea?
Quote this message in a reply
Posts: 241
Joined: 2008.07
Post: #5
Step through the code that loads your texture, line by line, ensure that everything is as it should be. I have a hunch it's not finding the texture. If it isn't, just make sure that the texture is included with the project. One difference between Xcode and VisualStudio is, the assets are copied to a bundle where the program accesses the assets. Another thing you can do is, use the absolute path of the texture and see if it works then. (Using the absolute path, is loading it separately from the bundle.)

If that's not it, try re-saving your png file. I had a hard time with png's because some of them have weird formatting. I'm not really sure how/why but to get around it, load the png in Photoshop or whatever you use and re-save it with no compression or RLE or any of that stuff.

If your model is loading and displaying, applying the texture to it is only a matter of loading the texture and binding it, whether you're using a VBO or passing verts to OpenGL one at a time. Let me know if this helps. Smile
Quote this message in a reply
Posts: 10
Joined: 2009.01
Post: #6
Png is loaded fine & it's in the target.
(it used to work with a simpler code)

My geometry is showing up, animated, but all white.
There must be something in the code somewhere..
Quote this message in a reply
Posts: 249
Joined: 2008.10
Post: #7
You can also try to load a "safe or dummy" texture. Something like this (C++)
So you will know if your problem is png loading or not.

(4 pixels, 2 white, 2 black, "1" means padding)
unsigned char pixels[]={255,255,255,0,0,0,1,1,255,255,255,0,0,0,1,1};
glTexImage2D(GL_TEXTURE_2D,0,3,2,2,0,GL_RGB, GL_UNSIGNED_BYTE, pixels);
Quote this message in a reply
Posts: 10
Joined: 2009.01
Post: #8
Okay, I found out where was the bug:

glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_SHORT, spriteData);


glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, spriteData);

Damn me!!! I certainly changed it while trying to fix something else...

Thanks for your help everyone.

Quote this message in a reply
Posts: 10
Joined: 2008.11
Post: #9
You're creating two separate GL_ARRAY_BUFFER VBOs for the vertex and texture coordinates. There can only be a single bound VBO of a given type (GL_ARRAY_BUFFER ot GL_ELEMENT_ARRAY_BUFFER) at any given time.

You can either create a single vertex data structure containing both vertex and texture coordinates or have the texture coordinates follow the vertices in memory and adjust the offset passed to glTexCoordPointer accordingly. Having a combined structure is recommended since there are fewer cache misses when fetching the data. Be careful to pass a correct value for the stride parameter though.
Quote this message in a reply
Posts: 1,232
Joined: 2002.10
Post: #10
@q2dm1, while it may be better cache-wise to keep data interleaved in a single buffer object, it's perfectly valid to have multiple ARRAY_BUFFERs. The current buffer is used when you set a pointer or set/get the data.

The usage case where you want attributes in separate buffer objects like this is when some of them are static and some are streaming.
Quote this message in a reply
Posts: 10
Joined: 2008.11
Post: #11
Learning a new thing every day Smile
Quote this message in a reply
Post Reply