
Is glInterleavedArrays usable with VAOs?
Posted Wednesday, 18 January, 2012 - 18:55 by WaltN inHaving previously used interleaved arrays (with the "old OpenGL"), I blindly assumed that glInterleavedArrays was useable with vertex-array objects. But my experience suggests that my assumption was all wet.
The subject code (much of it for context) appears below where a VAO and two VBOs (index and vertex) are created for an object. The vertex array is interleaved, compatible with T2fN3fV3f. (The code below does not include creation of the texture image.) Note that the index and vertex arrays are arguments to the StandardObject constructor. The helper method GenVBOID() is illustrated separately below.
protected int VAOID { get; set; } // Vertex Array Object identifier protected List<int> VBOIDs = new List<int>(); protected TexImage TexImage { get; set; } public int ElementCount { get; protected set; } // Number of elements in index array /// <summary> /// General form interleaved array constructor. /// </summary> /// <param name="x">Element (index) array (optional)</param> /// <param name="v">Vertex (interleaved) array</param> /// <param name="iPath">Path to texture image file</param> public StandardObject(int[] x, Vertex[] v, string iPath = null) { ErrorCode ec = GL.GetError(); // Clears errors int[] vaoid = new int[1]; // Temporary VAO identifier array GL.GenVertexArrays(1, vaoid); VAOID = vaoid[0]; // Store as scalar member ElementCount = x.Length; int vertexSize = Marshal.SizeOf(v[0]); // 32 int vSize = v.Length * vertexSize; int xSize = x.Length * sizeof(int); // Local VBO IDs int vID; // vertices int xID = 0; // elements // Define VAO GL.BindVertexArray(VAOID); // VBO for elements (x) xID = GenVBOID(); // add a single buffer GL.BindBuffer(BufferTarget.ElementArrayBuffer, xID); GL.BufferData(BufferTarget.ElementArrayBuffer, (IntPtr)xSize, x, BufferUsageHint.StaticDraw); // VBO for vertices (v) vID = GenVBOID(); // Add a single buffer GL.BindBuffer(BufferTarget.ArrayBuffer, vID); GL.BufferData<Vertex>(BufferTarget.ArrayBuffer, (IntPtr)vSize, v, BufferUsageHint.StaticDraw); GL.EnableVertexAttribArray((int)AttributeTypes.Vertex); GL.EnableVertexAttribArray((int)AttributeTypes.Normal); GL.EnableVertexAttribArray((int)AttributeTypes.TexCoord); //GL.InterleavedArrays(InterleavedArrayFormat.T2fN3fV3f, 0, (IntPtr)null); // Invalid operation GL.VertexAttribPointer((int)AttributeTypes.TexCoord, 2, VertexAttribPointerType.Float, false, vertexSize, 0); GL.VertexAttribPointer((int)AttributeTypes.Normal, 3, VertexAttribPointerType.Float, false, vertexSize, 8); GL.VertexAttribPointer((int)AttributeTypes.Vertex, 3, VertexAttribPointerType.Float, false, vertexSize, 20); // ( attributeIndex, sz, type, nmlzd, stride, offset)
/// <summary> /// Generates a buffer and records its ID in VBOIDs array. /// </summary> /// <returns>Buffer ID</returns> private int GenVBOID() { int id; // VBO ID GL.GenBuffers(1, out id); // Generate a single buffer VBOIDs.Add(id); // Record it for this instance return id; // Return it } // end GenVBOID
The crucial statements are the last group of statements in the first block of code, comprising three GL.EnableVertexAttribArray statements, a commented out GL.InterleavedArrays statement, and three GL.VertexAttribPointer statements. The code as illustrated (with the commented out glInterleavedArrays) works and works properly. But, I had to add the three GL.EnableVertexAttribArray statements and the three GL.VertexAttribPointer statements to get it to work. (I initially assumed that GL.InterleavedArrays would do the work for me.) As a matter of fact, the code continues to work if the GL.InterleavedArrays statement is not commented out. However, until I looked explicitly, I didn't realize that it was failing with an InvalidOperation error code.
I've tentatively concluded that glInterleavedArrays was not meant to work with VAOs. This after realizing that glInterleavedArrays is a compatibility extension as of GL 3.1 and reading that the InvalidOperation could be signaling the removal of glInterleavedArrays. (Or, perhaps signaling that glInterleavedArrays is incompatible with VAOs?)
I'm glad that I was able to get this to work because I'm a believer in interleaved array formats, but I'm surprised that I didn't read statements regarding this compatibility issue in either the Redbook or SuperBible 5.
My question is: Is my tentative conclusion an appropriate conclusion?


Comments
Re: Is glInterleavedArrays usable with VAOs?
I did not read your code fully, however, I can say the following:
Re: Is glInterleavedArrays usable with VAOs?
I struggled a bit to feel I was interpreting your enumeration correctly because (1) and (2) appear to be contradictory. However, your points do agree literally with my experience.
I would summarize by saying that, if one is using VAOs (which means glVertexAttribPointer is called for rather than glVertexPointer, etc.), they almost always should be using interleaved arrays, but they should not be trying to use glInterleavedArrays to construct and enable them. If the OpenGL literature had pointed something like that out, it would have saved me a lot of struggle and cussing.
Thanks for understanding and addressing my question.