Reputation: 143
I am Trying to make a Game Engine in C# and OpenGL using OpenGL.NET. I have abstracted the Basic OpenGL Objects like VAO, VBO, etc. I Have a BufferLayout Class which specifies the Data present in the Vertex Buffer. The method in the VertexArray class that adds a buffer is this:
public void AddBuffer(uint index, ref VertexBuffer buffer)
{
Bind();
buffer.Bind();
uint i = index;
foreach (BufferElement element in buffer.Layout.Elements)
{
Gl.VertexAttribPointer(
i++,
element.GetComponentCount(),
Globals.ShaderDataTypeToOpenGLBaseType(element.Type),
element.Normalized,
buffer.Layout.Stride,
element.Offset
);
}
m_Buffers.Add(buffer);
}
This method has 2 Overloads: One which takes an IntPtr
as the Offset and another which takes in an object
.
This is the overload which takes in an object
. But for some reason, the element.Offset
is not working as expected. As I am only using a positions attribute for this test, it works when I replace element.Offset
with null
.
Here is BufferLayout.cs
public enum ShaderDataType
{
None,
Float, Float2, Float3, Float4,
Mat3, Mat4,
Int, Int2, Int3, Int4,
}
public class BufferElement
{
internal string Name;
internal ShaderDataType Type;
internal int Size;
internal int Offset;
internal bool Normalized;
public BufferElement(ShaderDataType type, string name, bool normalized = false)
{
Name = name;
Type = type;
Size = Globals.ShaderDataTypeSize(type);
Offset = 0;
Normalized = normalized;
}
internal void SetOffset(int offset) => Offset = offset;
public int GetComponentCount()
{
switch (Type)
{
case ShaderDataType.Float: return 1;
case ShaderDataType.Float2: return 2;
case ShaderDataType.Float3: return 3;
case ShaderDataType.Float4: return 4;
case ShaderDataType.Mat3: return 3 * 3;
case ShaderDataType.Mat4: return 4 * 4;
case ShaderDataType.Int: return 1;
case ShaderDataType.Int2: return 2;
case ShaderDataType.Int3: return 3;
case ShaderDataType.Int4: return 4;
}
return 0;
}
}
internal sealed class BufferLayout
{
public List<BufferElement> Elements { get; private set; }
public int Stride { get; private set; }
public BufferLayout(BufferElement[] e)
{
Elements = new List<BufferElement>();
Elements.AddRange(e);
CalculateOffsetsAndStride();
}
private void CalculateOffsetsAndStride()
{
int offset = 0;
Stride = 0;
for (int i = 0; i < Elements.Count; i++)
{
Elements[0].SetOffset(offset);
offset += Elements[0].Size;
Stride += Elements[0].Size;
}
}
}
Upvotes: 1
Views: 216
Reputation: 210978
The overload which takes an object is meant for compatibility profile OpenGL contex and the object has to be an object containing the vertex array data.
If you want to set an offset, then you have to create an IntPtr
. e.g:
var offset = new IntPtr(element.Offset);
Gl.VertexAttribPointer(
i++,
element.GetComponentCount(),
Globals.ShaderDataTypeToOpenGLBaseType(element.Type),
element.Normalized,
buffer.Layout.Stride,
offset
);
Note, the offset and the stride parameter have to be specified in bytes.
Upvotes: 1