I agree this is pretty boiled down but this is where something I believe is a miss. In here I have three calls. One to build a VBO object, one to render the VBO object and one to render using Vertex Arrays. The application calls either RenderVBO() or RenderArrays() based on the state of a key passing the same arguments to each method, BuildVBO is always called.
The RenderArrays renders properly with geometry, lighting and texels using the activated shader. The RenderVBO call renders the geometry and lighting correctly but the texels are random. See attached screen shots. Not sure whats wrong. Do I need to pass the buffer offsets along somewhere for texels? Why would lighting work if that’s the case?
For anyone who may ask the code branch is…
if (blnUseVBO) {
VBO.Instance.RenderVBO(objModel.arySegments[0], a_vVertex, a_vNormal, a_vTexel);
} else {
VBO.Instance.RenderArrays(objModel.arySegments[0], a_vVertex, a_vNormal, a_vTexel);
}
BTW…This is some C# code using OpenTK and TAO.Compatibility in a Windows form for rapid development.
Any insight is greatly appreciated.
using System;
using Tao.OpenGl;
using Engine;
using Engine.DataTypes;
using Engine.MathLib;
namespace VBOShaders
{
class VBO : Singleton<VBO>
{
public void BuildVBO(Segment objSegment)
{
// Calculate sizes
int tri_buf_size = objSegment.intTriangleCount * Vector3s.SizeInBytes; // Size of triangle array in bytes
int vrt_buf_size = objSegment.intVertexCount * Vector3f.SizeInBytes; // vertex
int nrm_buf_size = objSegment.intVertexCount * Vector3f.SizeInBytes; // normal
int txl_buf_size = objSegment.intVertexCount * Vector2f.SizeInBytes; // texel
int geo_buf_size = vrt_buf_size + nrm_buf_size + txl_buf_size; // all geometry arrays in bytes
int offset = 0; // current buffer starting location
// Setup geometry array and allocate space
Gl.glGenBuffers(1, out objSegment.geometryVBOId);
Gl.glBindBuffer(Gl.GL_ARRAY_BUFFER, objSegment.geometryVBOId);
Gl.glBufferData(Gl.GL_ARRAY_BUFFER, (IntPtr)geo_buf_size, IntPtr.Zero, Gl.GL_STATIC_DRAW);
// Copy geometry data to the hardware buffer starting at offset
Gl.glBufferSubData(Gl.GL_ARRAY_BUFFER, (IntPtr)offset, (IntPtr)vrt_buf_size, objSegment.aryVertexes);
offset += vrt_buf_size;
Gl.glBufferSubData(Gl.GL_ARRAY_BUFFER, (IntPtr)offset, (IntPtr)nrm_buf_size, objSegment.aryVNormals);
offset += nrm_buf_size;
Gl.glBufferSubData(Gl.GL_ARRAY_BUFFER, (IntPtr)offset, (IntPtr)txl_buf_size, objSegment.aryVertexes);
// Setup indices array and allocate space
Gl.glGenBuffers(1, out objSegment.indicesVBOId);
Gl.glBindBuffer(Gl.GL_ELEMENT_ARRAY_BUFFER, objSegment.indicesVBOId);
Gl.glBufferData(Gl.GL_ELEMENT_ARRAY_BUFFER, (IntPtr)tri_buf_size, IntPtr.Zero, Gl.GL_STATIC_DRAW);
// Copy index data to the hardware buffer starting at offset 0
Gl.glBufferSubData(Gl.GL_ELEMENT_ARRAY_BUFFER, IntPtr.Zero, (IntPtr)tri_buf_size, objSegment.aryTriangles);
// Unbind any buffers so remaining GL stays happy
Gl.glBindBuffer(Gl.GL_ARRAY_BUFFER, 0);
Gl.glBindBuffer(Gl.GL_ELEMENT_ARRAY_BUFFER, 0);
}
public void RenderVBO(Segment objSegment, int a_vVertex, int a_vNormal, int a_vTexel)
{
// Step 1
Gl.glBindBuffer(Gl.GL_ARRAY_BUFFER, objSegment.geometryVBOId);
Gl.glBindBuffer(Gl.GL_ELEMENT_ARRAY_BUFFER, objSegment.indicesVBOId);
// Step 2
Gl.glEnableVertexAttribArray(a_vVertex);
Gl.glVertexAttribPointer(a_vVertex, 3, Gl.GL_FLOAT, Gl.GL_FALSE, 0, IntPtr.Zero);
Gl.glEnableVertexAttribArray(a_vNormal);
Gl.glVertexAttribPointer(a_vNormal, 3, Gl.GL_FLOAT, Gl.GL_FALSE, 0, IntPtr.Zero);
Gl.glEnableVertexAttribArray(a_vTexel);
Gl.glVertexAttribPointer(a_vTexel, 2, Gl.GL_FLOAT, Gl.GL_FALSE, 0, IntPtr.Zero);
// Step 3
int tcount = objSegment.intTriangleCount * 3;
Gl.glDrawElements(Gl.GL_TRIANGLES, tcount, Gl.GL_UNSIGNED_SHORT, IntPtr.Zero);
// Step 4
Gl.glDisableVertexAttribArray(a_vVertex);
Gl.glDisableVertexAttribArray(a_vNormal);
Gl.glDisableVertexAttribArray(a_vTexel);
// Step 5
Gl.glBindBuffer(Gl.GL_ARRAY_BUFFER, 0);
Gl.glBindBuffer(Gl.GL_ELEMENT_ARRAY_BUFFER, 0);
}
public void RenderArrays(Segment objSegment, int a_vVertex, int a_vNormal, int a_vTexel)
{
// Step 2
Gl.glEnableVertexAttribArray(a_vVertex);
Gl.glVertexAttribPointer(a_vVertex, 3, Gl.GL_FLOAT, Gl.GL_FALSE, 0, objSegment.aryVertexes);
Gl.glEnableVertexAttribArray(a_vNormal);
Gl.glVertexAttribPointer(a_vNormal, 3, Gl.GL_FLOAT, Gl.GL_FALSE, 0, objSegment.aryVNormals);
Gl.glEnableVertexAttribArray(a_vTexel);
Gl.glVertexAttribPointer(a_vTexel, 2, Gl.GL_FLOAT, Gl.GL_FALSE, 0, objSegment.aryVTexels);
// Step 3
int tcount = objSegment.intTriangleCount * 3;
Gl.glDrawElements(Gl.GL_TRIANGLES, tcount, Gl.GL_UNSIGNED_SHORT, objSegment.aryTriangles);
// Step 4
Gl.glDisableVertexAttribArray(a_vVertex);
Gl.glDisableVertexAttribArray(a_vNormal);
Gl.glDisableVertexAttribArray(a_vTexel);
}
}
}