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.BindVertexArray(vaoHandle);
Gl.DrawArraysInstanced(PrimitiveType.TriangleStrip, 0, 4, faceCount);
Gl.BindVertexArray(0);
The VAO+VBOs are created like this:
// Create one VAO for this chunk
uint vaoHandle = Gl.GenVertexArray();
Gl.BindVertexArray(vaoHandle);
// Create the base triangle strip VBO
uint vboHandle = Gl.GenBuffer();
Gl.BindBuffer(BufferTarget.ArrayBuffer, vboHandle);
Gl.EnableVertexAttribArray(0);
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);
Helper.Free(triangleStripData);
// Create the instance VBO
uint instanceVBO = Gl.GenBuffer();
Gl.BindBuffer(BufferTarget.ArrayBuffer, instanceVBO);
int instanceAttrib = 1;
Gl.EnableVertexAttribArray(instanceAttrib);
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.BindVertexArray(0);
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.