0

Using GLKit (OpenGLES 2.0) on iOS.

I'm modifying some code that renders cubes in a 3d environment so that it will render waveforms in 2 dimensions in a 3d scene. I have it working great except for one problem which is:

Suppose I render n x/y coordinates using GL_LINES. It will draw a line from 0 -> 1, then 1 -> 2, and so on. But then point N will always have a line drawn back to point 0. I would expect GL_LINE_LOOP to this, but not GL_LINES.

I have a work around in mind if I cannot solve this and that is to use 2 GL_TRIANGLE_STRIP to draw each line segment. I'd really rather just understand why this isn't working though.

Here are the important parts of the code:

typedef struct {
    float Position[3];
} Vertex;

const NSUInteger kVerticiesSize = 320;
Vertex Vertices[kVersiciesSize] = {};
const GLubyte Indices[] = {
    0,1,
    1,2,
    2,3,
    3,4,
    4,5,
    5,6,
    6,7,
    7,8,
    8,9,
    9,10,
// keeps going to kVerticiesSize

The GL setup

- (void)setupGL {
    [EAGLContext setCurrentContext:self.context];
    self.effect = [[GLKBaseEffect alloc] init];

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

    glGenBuffers(1, &_vertexBuffer);
    glBindBuffer(GL_ARRAY_BUFFER, _vertexBuffer);
    glBufferData(GL_ARRAY_BUFFER, sizeof(Vertices), Vertices, GL_STATIC_DRAW);

    glGenBuffers(1, &_indexBuffer);
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _indexBuffer);
    glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(Indices), Indices, GL_STATIC_DRAW);

    glEnableVertexAttribArray(GLKVertexAttribPosition);
    glVertexAttribPointer(GLKVertexAttribPosition,
                          3,
                          GL_FLOAT,
                          GL_FALSE,
                          sizeof(Vertex),
                          offsetof(Vertex, Position));


    float aspect = fabsf(self.bounds.size.width / self.bounds.size.height);
    GLKMatrix4 projectionMatrix = GLKMatrix4MakePerspective(GLKMathDegreesToRadians(65.0f), aspect, 0.0f, 50.0f);
    self.effect.transform.projectionMatrix = projectionMatrix;
}

And the Update and Render methods:

// Always called once before "render"
-(void)update {
    static bool hasRun = NO;
    for(int x = 0; x < kVersiciesSize; x++){
        // normalize x variable to x coord -1 .. 1 and set Y to math function
        Vertex v = Vertices[x];
        v.Position[0] = [self normalizedX:x];
        v.Position[1] = cos(x);
        v.Position[2] = 0;
        Vertices[x] = v;
        if(!hasRun){
            NSLog(@"x=%f y=%f z=%f", v.Position[0], v.Position[1], v.Position[2]);
        }
    }
    hasRun = YES;
    glBufferData(GL_ARRAY_BUFFER, sizeof(Vertices), Vertices, GL_STATIC_DRAW);
    [self updateTransforms];
}

-(void)render {
    [self.effect prepareToDraw];

    glBindVertexArrayOES(_vertexArray);
    glDrawElements(GL_LINE_STRIP,
                   sizeof(Indices)/sizeof(Indices[0]),
                   GL_UNSIGNED_BYTE,
                   0);
}
VaporwareWolf
  • 10,143
  • 10
  • 54
  • 80

1 Answers1

0

You have:

glVertexAttribPointer(GLKVertexAttribPosition,
                      3,
                      GL_FLOAT,
                      GL_FALSE,
                      sizeof(Vertex),
                      offsetof(Vertex, Position));

But the signature of glVertexAttribPointer is:

glVertexAttribPointer (GLuint indx,          // GLKVertexAttribPosition
                       GLint size,           // 3 floats per vertex
                       GLenum type,          // Vertices are GL_FLOAT-s
                       GLboolean normalized, // GL_FALSE
                       GLsizei stride,       // *** Should be 0, no?
                       const GLvoid* ptr);   // *** Should be &Vertices[0], no?

I'm pretty sure that, if you make the commented suggestions above, it would work. Then you just render the whole thing with:

glDrawArrays(GL_LINES, 0, kVerticiesSize);

or

glDrawArrays(GL_LINES, startIndex, lineCount);

...right?

DISCLAIMER: I'm not fluent with the whole bound-buffers pipeline, but it strikes me as unnecessary complication, in this case.

ALSO NOTE: Your text mentions GL_LINES, but your sample code uses GL_LINE_STRIP. A line-strip works like a triangle-strip, where the first 2 vertices define the first line segment but, after that, each single vertex defines the next line-segment, which picks-up where the previous one left off. Hence, your vertex indices are correct for GL_LINES but, for GL_LINE_STRIP, you'd just want { 0, 1, 2, 3, 4, 5... }

Olie
  • 24,597
  • 18
  • 99
  • 131
  • Thanks for looking into this. This is an old project but I will probably dig it out and take a look at it again. Thank you. It does looks like there are some mismatches as you have suggested. The difference in GL_LINES and GL_LINE_STRIP is just a paste error. I remember digging deeply into both of them. I remember how they are intended to act from older OpenGL. – VaporwareWolf May 28 '13 at 21:14