21

I am confused about glDrawElements() . I was following a tutorial which said that the 4th argument of the glDrawElements() is "Offset within the GL_ELEMENT_ARRAY_BUFFER". But I was having an error "Access voilation: Trying to read 0x0000", if I passed 0 as offset.

So I dig further into the problem and found that OpenGL Documentation provides two different definitions of the 4th argument:

First:

indices: Specifies a byte offset (cast to a pointer type) into the buffer bound to GL_ELEMENT_ARRAY_BUFFER​ to start reading indices from.

(Found Here: https://www.opengl.org/wiki/GLAPI/glDrawElements)

Second:

indices: Specifies a pointer to the location where the indices are stored.

(Found Here: https://www.opengl.org/sdk/docs/man4/index.php and Here: http://www.khronos.org/opengles/sdk/docs/man/xhtml/glDrawElements.xml)

Which one is true and How to use it correctly?

EDIT: Here is my code: http://pastebin.com/fdxTMjnC

Cashif Ilyas
  • 1,619
  • 2
  • 14
  • 22

4 Answers4

14

Both are correct. The 2 cases relate to how the buffer of indices is uploaded to the GL Hardware and how it is used to draw. These are described below:

(1) Without using VBO (Vertex Buffer Object):

In this case, the parameter indicates a pointer to the array of indices. Everytime glDrawElements is called, the buffer is uploaded to GL HW.

(2) Using VBO:

For this case - see the definition of Index as "Specifies a byte offset (cast to a pointer type) into the buffer bound to GL_ELEMENT_ARRAY_BUFFER​ to start reading indices from". This means that the data is already uploaded separately using glBufferData, and the index is used as an offset only. Everytime glDrawElements is called, the buffer is not uploaded, but only the offset can change if required. This makes it more efficient, especially where large number of vertices are involved.

Prabindh
  • 3,356
  • 2
  • 23
  • 25
  • I am using VBO... But I get "Access Voilation reading 0x00". That means my VBO is not set up properly? – Cashif Ilyas Feb 11 '14 at 15:56
  • What I found: It was VAO (Vertex Array Object) that you need to create in addition to VBO (Vertex Buffer Object) and EBO (Element Array Buffer) to work properly – Cashif Ilyas Feb 11 '14 at 16:08
  • And yes, you were right: Both definitions are correct based on the context. +1 for discussing the Efficiency – Cashif Ilyas Feb 11 '14 at 16:10
9

If you use direct drawing, then

indices​ defines the offset into the index buffer object (bound to GL_ELEMENT_ARRAY_BUFFER​, stored in the VAO) to begin reading data.

That means, you need to create VAO, bind to it, and then use glDrawElements() for rendering

BЈовић
  • 62,405
  • 41
  • 173
  • 273
  • 3
    VAO was the key point! I was creating VAO but after creating EBO. To clarify further to others: You need to create VAO before both EBO and VBO and bind these buffers to VAO to work correctly.. – Cashif Ilyas Feb 11 '14 at 16:06
  • @CashifIlyas Ok, in that case you may have to look into [this question and answers](http://stackoverflow.com/q/8923174/476681) – BЈовић Feb 11 '14 at 16:10
  • 1
    You don't have to do any of this technically. It depends on your OpenGL version and context. In a compatibility profile, you can use client memory instead of a buffer object. Likewise, you do not need a VAO at all in such a case. When no element array buffer is bound, it tells GL to read memory from the address you pass as the 4th parameter; when one ***is*** bound, it tells GL to use an offset into the memory defined by the bound element array buffer. – Andon M. Coleman Feb 11 '14 at 18:32
4

The interpretation of that argument depends on whether an internal array has been bound in the GL state machine. If such an array is bound, it's an offset. If no such array is bound, it's a pointer to your memory.

Using an internal array is more performant, so recent documentation (especially wikis) is strongly biased toward that usage. However, there's a long song and dance to set them up.

The function that binds or unbinds the internal array is glBindVertexArray. Check the documentation for these related functions:

  • glGenVertexArrays
  • glBufferData

(this is an incomplete list. I've got to run so I'll have to edit later.)

01d55
  • 1,872
  • 13
  • 22
0

Whatever is on opengl.org/wiki is most likely to be correct. And I can tell you from working projects that it is indeed defined as follows:

Specifies a byte offset (cast to a pointer type) into the buffer bound to
GL_ELEMENT_ARRAY_BUFFER​ to start reading indices from.

Just cast some integer to GLvoid* and you should be good to go. That is at least for the modern programmable pipeline, I have no idea for the fixed pipeline (nor should you use it!).

If you are using the modern pipeline, without further information, I would bet on the actual function not being loaded correctly. That being GLEW not initialized correctly or if you're doing things manually trying to use GetProcAddress on win32 (seeing as glDrawElements is core since 1.1, and 1.0/1.1 shouldn't be loaded with GetProcAddress on win32).

And indeed note you should've bound an element buffer to the binding point as others have said. Though in practice you can get away with it without binding a VAO. I've done this on NVidia, AMD and even Intel. But in production you should use VAOs.

Invalid
  • 1,870
  • 1
  • 16
  • 22
  • I am using OpenGL 3.1.0 and GLEW 1.10.0 on Windows Machine – Cashif Ilyas Feb 11 '14 at 15:54
  • I suggest printing your function pointers (thus checking them for 0x0000) and seeing if GLEW is initialized correctly. If both check out, it must be something else, either something else in your code we can't see here, or you've not bound an element buffer, or you're doing other weird voodoo related things. – Invalid Feb 11 '14 at 15:57
  • One thing more: If I use `glDrawArrays()` then it works fine. That means GLEW is initialized fine. Right? – Cashif Ilyas Feb 11 '14 at 15:59
  • Might be, might not be, I have no idea how GLEW handles errors internally. You should use the official way to check for initialization + printing out the relevant function pointers to check for NULL can't hurt. – Invalid Feb 11 '14 at 16:00