1

Whenever I attempt to render a textured quad, I end up with a triangular section of the texture distorted: see this image .

The texture is a PNG created in GIMP, and I've tried two seperate methods of loading the texture (both from Apple's own sample code). Each method of loading the texture produced different results (I don't know if it is different default settings, or if there is a problem with the texture), but I couldn't get either to render proper.

I've tried setting up my indices/verticles/texices in multiple different ways, from suggestions posted in Fastest way to draw quads in OpenGL ES? yet still no luck.

What could I be missing?

Code to Load Texture

- (GLuint)setupTexture:(NSString *)fileName {    
    CGImageRef spriteImage = [UIImage imageNamed:fileName].CGImage;
    if (!spriteImage) {
        NSLog(@"Failed to load image %@", fileName);
        exit(1);
    }
    size_t width = CGImageGetWidth(spriteImage);
    size_t height = CGImageGetHeight(spriteImage);
    GLubyte * spriteData = (GLubyte *) calloc(width*height*4, sizeof(GLubyte));
    CGContextRef spriteContext = CGBitmapContextCreate(spriteData, width, height, 8, width*4, 
    CGImageGetColorSpace(spriteImage), kCGImageAlphaPremultipliedLast);    
    CGContextDrawImage(spriteContext, CGRectMake(0, 0, width, height), spriteImage);
    CGContextRelease(spriteContext);
    GLuint texName;
    glGenTextures(1, &texName);
    glBindTexture(GL_TEXTURE_2D, texName);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, spriteData);
    free(spriteData);        
    return texName;    
}

Texture Coordinates and Verticles

const GLfloat texices[] =
    { 0,1,
      1,1,
      0,0,
      1,0 };

glActiveTexture(GL_TEXTURE0);
glUniform1i(_texturedTextureUniformSlot, 0);
glVertexAttribPointer(_texturedTextureSlot, 2, GL_FLOAT, GL_FALSE, 0, texices);

GLfloat vertices[] = {-1, -1, 0, //bottom left corner
                  -1,  1, 0, //top left corner
                   1,  1, 0, //top right corner
                   1, -1, 0}; // bottom right rocner

GLubyte indices[] = {0,1,2, // first triangle (bottom left - top left - top right)
                 0,2,3}; // second triangle (bottom left - top right - bottom right)

glVertexAttribPointer(3, GL_FLOAT, 0, vertices);
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_BYTE, indices);
Glorfindel
  • 21,988
  • 13
  • 81
  • 109
Mr. Smith
  • 4,288
  • 7
  • 40
  • 82

1 Answers1

6

It looks like your texture coordinates may be wrong (notice the texture appears to be wrapping around the left side).

Here is a snippet of code that I've used in the past:

const float quadPositions[] = {  1.0,  1.0, 0.0, 
                                -1.0,  1.0, 0.0, 
                                -1.0, -1.0, 0.0, 
                                -1.0, -1.0, 0.0, 
                                 1.0, -1.0, 0.0, 
                                 1.0,  1.0, 0.0 };
const float quadTexcoords[] = { 1.0, 1.0, 
                                0.0, 1.0, 
                                0.0, 0.0, 
                                0.0, 0.0, 
                                1.0, 0.0, 
                                1.0, 1.0 };

// stop using VBO
glBindBuffer(GL_ARRAY_BUFFER, 0);

// setup buffer offsets
glVertexAttribPointer(ATTRIB_VERTEX, 3, GL_FLOAT, GL_FALSE, 3*sizeof(float), quadPositions);
glVertexAttribPointer(ATTRIB_TEXCOORD0, 2, GL_FLOAT, GL_FALSE, 2*sizeof(float), quadTexcoords);

// ensure the proper arrays are enabled
glEnableVertexAttribArray(ATTRIB_VERTEX);
glEnableVertexAttribArray(ATTRIB_TEXCOORD0);

// draw
glDrawArrays(GL_TRIANGLES, 0, 2*3);

That should draw a two triangles at z=0. You'll want to setup your projection from -1 to 1 in width and height.

Edit:

Here's a working version of your code:

const GLfloat texices[] = { 0, 0,
                            0, 1,
                            1, 1,
                            1, 0 };


const GLfloat vertices[] = { -1, -1, 0,  // bottom left corner
                             -1,  1, 0,  // top left corner
                              1,  1, 0,  // top right corner
                              1, -1, 0}; // bottom right corner

const GLubyte indices[] = { 0, 2, 1,     // first triangle (bottom left - top left - top right)
                            0, 3, 2 };


// ensure no VBOs or IBOs are bound
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);    

glVertexAttribPointer(ATTRIB_VERTEX, 3, GL_FLOAT, GL_FALSE, 3*sizeof(float), vertices);
glVertexAttribPointer(ATTRIB_TEXCOORD0, 2, GL_FLOAT, GL_FALSE, 2*sizeof(float), texices);

// ensure the proper arrays are enabled
glEnableVertexAttribArray(ATTRIB_VERTEX);
glEnableVertexAttribArray(ATTRIB_TEXCOORD0);

glDisable(GL_CULL_FACE);

glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_BYTE, indices);
bosmacs
  • 7,341
  • 4
  • 31
  • 31
  • There is no combination of texture coordinates and texture vertices that I have found that work. You may still be right, but I'm extremely skeptical, as my code is ripped straight off tutorials on OpenGL ES 2.0. The only difference is that said tutorials weren't written for 2D rendering. Is it possible there some function I need to call to get triangles rendering on Z=0.0f to appear correctly? – Mr. Smith Nov 19 '12 at 14:48
  • I looked into my `glDrawElements` approach, and I think what's happening is that `glDrawElements` doesn't select the proper texture coordinates when the indices are not monotonically increasing. Hence `glDrawElements` is pointless when dealing with textures. [Drawing cube using glDrawElements and glTexCoordPointer](http://www.gamedev.net/topic/602169-opengl-drawing-cube-using-gldrawelements-and-gltexcoordpointer/) – Mr. Smith Nov 19 '12 at 15:40
  • I'm not sure yet what the problem is; I think you should be able to use `glDrawElements` in this case. One problem may be the use of `glVertexPointer` -- that's only valid for ES 1.0. – bosmacs Nov 19 '12 at 15:43
  • Sorry, meant to write `glVertexAttribPointer` in my code sample (I don't use `glVertexPointer`). I've edited my original post just now to fix that. – Mr. Smith Nov 19 '12 at 15:45
  • I added an edit with a working adaptation of your code above. – bosmacs Nov 19 '12 at 15:53
  • Helped me out even 3 years later, very useful! Thank you! – John Sep 19 '15 at 08:47