Last Three Vertices in an Instanced Triangle Strip Don't Render

Hi all,

I’m facing a strange error where the last three vertices in my mesh don’t render unless I increase the size of the VBO by 12 bytes.

The mesh is rendered with instancing:

Gl.DrawArraysInstanced(PrimitiveType.TriangleStrip, 0, 4, faceCount);

The VAO+VBOs are created like this:

// Create one VAO for this chunk
uint vaoHandle = Gl.GenVertexArray();

// Create the base triangle strip VBO
uint vboHandle = Gl.GenBuffer();
Gl.BindBuffer(BufferTarget.ArrayBuffer, vboHandle);
Gl.VertexAttribIPointer(0, 1, VertexAttribType.Int, sizeof(int), IntPtr.Zero);
Gl.VertexAttribDivisor(0, 0); // Advance once per vertex

// Triangle strip data, which represents a 1x1 voxel face
int triangleStripByteCount = 4 * sizeof(int);
int* triangleStripData = (int*)Helper.Alloc(triangleStripByteCount);
triangleStripData[0] = 0;             // 0, 0
triangleStripData[1] = 1;             // 1, 0
triangleStripData[2] = 1 << 8;        // 0, 1
triangleStripData[3] = 1 | (1 << 8);  // 1, 1

Gl.BufferData(BufferTarget.ArrayBuffer, triangleStripByteCount, triangleStripData, GL_STATIC_DRAW);

// Create the instance VBO
uint instanceVBO = Gl.GenBuffer();
Gl.BindBuffer(BufferTarget.ArrayBuffer, instanceVBO);

int instanceAttrib = 1;
Gl.VertexAttribIPointer(instanceAttrib, intSize, VertexAttribType.Int, sizeof(int), IntPtr.Zero);
Gl.VertexAttribDivisor(instanceAttrib, 1); // Advance once per instance

// Upload packed instance data (32 bits containing xyz, normal, length, etc)
int* instanceData = ...;
int instanceBytes = faceCount * sizeof(int);
Gl.BufferData(BufferTarget.ArrayBuffer, instanceBytes, instanceData, GL_STREAM_DRAW);

Gl.BindBuffer(BufferTarget.ArrayBuffer, 0);

The vertex shader:

layout (location = 0) in int aBasePosition;
layout (location = 1) in int aData; // 32 bits of packed voxel data

uniform mat4 mvp;

void main()
    // Triangle strip position, initially flat on the ground, facing up
    vec3 netPos = vec3(float(aBasePosition&(255)), 0, float((aBasePosition >> 8)&(255)));

    // Unpack aData, then position and orient the voxel face
    netPos.x += ...

    // Voxel space to screen space
    gl_Position = mvp * vec4(position, 1.0);

The three missing faces are shown below. Face culling is disabled for demonstration, and the bottom face is never meshed as it’s on the bottom of the map. The random face rendering in the corner of the map is not indended. I think that’s what happens when part of the buffer has no data in it.

I then changed the upload code to include space for 1 more vertex.

int* instanceData = ...;
int bufferBytes = (faceCount + 1) * sizeof(int);
int instanceBytes = faceCount * sizeof(int);

Gl.BufferData(BufferTarget.ArrayBuffer, bufferBytes, IntPtr.Zero, GL_STREAM_DRAW);
Gl.BufferSubData(BufferTarget.ArrayBuffer, 0, instanceBytes, instanceData);

This displayed one more vertex, even though I haven’t changed the data I upload to the buffer:

Repeated again with int bufferBytes = (faceCount + 2) * sizeof(int);, another vertex appeared:

And finally with int bufferBytes = (faceCount + 3) * sizeof(int);, it renders correctly:

I’m happy to add 3 entries to the end of each VBO but I’m confused why. I think the faces in the corner of the map are a clue - the vertices are rendering, but the instance data is just zero.

This is sized for 4 bytes, not 4 ints and not 4 vertices.


Specifies the size in bytes of the buffer object’s new data store.

1 Like

Thank you for the reply, good pickup! It looks like this is a typo though, it’s 4 * sizeof(int) in my code.

Just to triple check I checked the size of my buffers with glGetBufferParameteriv and GL_BUFFER_SIZE and it’s returning the correct sizes for each buffer.

Figured it out, I had the wrong size on my instance VBO:
Gl.VertexAttribIPointer(instanceAttrib, intSize, VertexAttribType.Int, sizeof(int), IntPtr.Zero);

Correct size:
Gl.VertexAttribIPointer(instanceAttrib, 1, VertexAttribType.Int, sizeof(int), IntPtr.Zero);