Drawing by mixing VBO and client pointer does not work

Hi guys,
I’m just drawing some points by passing an vertex array and a color array without using shader. I found that

  1. if I pass both array as client pointer (that is, without bind any buffer to GL_ARRAY_BUFFER, before call glVertexPointer and glColorPointer), it works :heavy_check_mark:
  2. if I create 2 buffers(VBOs) and fill them with the 2 arrays, then call glVertexPointer and glColorPointer, it works :heavy_check_mark:
  3. but I can’t mix approach 1 and 2, for example, pass vertex array by client address and pass color array by buffer. this combination does not work :x:. How does this happen? Is this by design?
    Many thanks.

It works just fine, in a compatibility context. I do this all the time.

When you want to pass a vertex array to a vertex attribute…
Before calling the relevant gl*Pointer() call to set the vertex array pointer…

  • To pass a client array (vertex array in app CPU memory), bind 0 to GL_ARRAY_BUFFER.
  • To pass a vertex array in a buffer object (VBO), bind that buffer object’s handle to GL_ARRAY_BUFFER.

And of course, enable/disable the vertex attribute arrays as usual. In your case, you’re using the old legacy vertex attributes, so that’s via glEnableClientState() / glDisableClientState().

Thanks for reply. I believe there are some mistakes in my code I did not check carefully. this is the working code

static const float axis[] = {
  0.0f,  0.0f, 0.0f,  // o
  1.0f,  0.0f, 0.0f,  // x
  0.0f,  1.0f, 0.0f,  // y
  0.0f,  0.0f, 1.0f,  // z
  5.0f,  5.0f, -5.0f, //
}, colors[] = {
  1.0f,1.0f,1.0f,
  1.0f,0.0f,0.0f,
  0.0f,1.0f,0.0f,    
  0.0f,0.0f,1.0f,
  1.0f,1.0f,1.0f,
};
static const GLubyte indices[] = {
  0,1,0,2,0,3,0,4
};
  
void drawAxis() {
  static struct {
    bool initialized = false;
    GLuint vbo;
    GLuint vbo2;
    GLuint ibo;
    GLuint query;
    unsigned total = 0;
  } ctl;
  
  if(!ctl.initialized) {
    ctl.initialized = true;
    glGenBuffers(1,&ctl.ibo);
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,ctl.ibo);
    glBufferData(GL_ELEMENT_ARRAY_BUFFER,sizeof(indices),indices,GL_STATIC_DRAW);
    // A use VBO to pass vertex
    if(true) {
      glGenBuffers(1,&ctl.vbo);
      glBindBuffer(GL_ARRAY_BUFFER,ctl.vbo);
      glBufferData(GL_ARRAY_BUFFER,sizeof(axis),axis,GL_STATIC_DRAW);
      glVertexPointer(3,GL_FLOAT,sizeof(float)*3,(void*)0);
      glBindBuffer(GL_ARRAY_BUFFER,0);
    } else {
      glVertexPointer(3,GL_FLOAT,sizeof(float)*3,(void*)axis);
    }
    // B use client address to pass color
    if(false) {
      glGenBuffers(1,&ctl.vbo2);
      glBindBuffer(GL_ARRAY_BUFFER,ctl.vbo2);
      glBufferData(GL_ARRAY_BUFFER,sizeof(colors),colors,GL_STATIC_DRAW);
      glColorPointer(3,GL_FLOAT,sizeof(float)*3,(void*)0);
      glBindBuffer(GL_ARRAY_BUFFER,0);
    } else {
      glColorPointer(3,GL_FLOAT,sizeof(float)*3,(void*)colors);
    }
    //
    glEnableClientState(GL_VERTEX_ARRAY);
    glEnableClientState(GL_COLOR_ARRAY);
    //
    glGenQueries(1,&ctl.query);
  }
  glBeginQuery(GL_PRIMITIVES_GENERATED,ctl.query);
  glDrawElements(GL_LINES,6,GL_UNSIGNED_BYTE,0);
  glEndQuery(GL_PRIMITIVES_GENERATED);
  GLuint val;
  glGetQueryObjectuiv(ctl.query,GL_QUERY_RESULT,&val);
  ctl.total += val;
  printf("GL_PRIMITIVES_GENERATED %d\n",ctl.total);
};