VBO を使用して、OpenTK を使用して C# でモデルを描画しようとしています。私のオンライン調査では、インターリーブされたデータ構造のサイズを正確に 32 バイトの倍数にすることをお勧めします。
[Serializable]
[StructLayout(LayoutKind.Sequential)]
public struct Byte4
{
public byte R, G, B, A;
public Byte4(byte[] input)
{
R = input[0];
G = input[1];
B = input[2];
A = input[3];
}
public uint ToUInt32()
{
byte[] temp = new byte[] { this.R, this.G, this.B, this.A };
return BitConverter.ToUInt32(temp, 0);
}
}
[Serializable]
[StructLayout(LayoutKind.Sequential)]
public struct VertexInterleaved
{
// data section is exactly 36 bytes long??? - need padding to get multiple of 32?
public Vector3 vertex; // Vertex
public Vector3 normal; // Normal Vector
public Vector2 textureCoord; // First Texture Coordinates
public Byte4 rgbaColor; // RGBA value of this vertex
//public byte[] padding;
public static int VertexStride()
{
// if I'm using the padding I have to add the appropriate size to this...
return (8 * sizeof(float) + 4 * sizeof(byte));
}
}
public class VertexBufferObject
{
private uint[] _VBOid;
private int _vertexStride;
private int _totalIndices;
private int _totalVertices;
public VertexBufferObject ()
{
_VBOid = new uint[2];
GL.GenBuffers(2, _VBOid);
}
public bool DeleteVBO()
{
GL.DeleteBuffers(2, _VBOid);
}
private void BindBuffers()
{
GL.BindBuffer(BufferTarget.ArrayBuffer, _VBOid[0]);
GL.BindBuffer(BufferTarget.ElementArrayBuffer, _VBOid[1]);
}
private void ReleaseBuffers()
{
GL.BindBuffer(BufferTarget.ArrayBuffer, 0);
GL.BindBuffer(BufferTarget.ElementArrayBuffer, 0);
}
public void BufferMeshData(Mesh3DCollection mesh3Ds)
{
_vertexStride = VertexInterleaved.VertexStride();
_totalIndices = mesh3Ds.TotalIndices();
_totalVertices = mesh3Ds.TotalVertices();
VertexInterleaved[] vboVertices = new VertexInterleaved[_totalVertices];
uint[] vboIndices = new uint[_totalIndices];
int vertexCounter = 0;
int indexCounter = 0;
foreach (Mesh3D m in mesh3Ds)
{
foreach (VertexInterleaved v in m.vertices)
{
vboVertices[vertexCounter] = v;
vertexCounter++;
}
foreach (uint i in m.indices)
{
vboIndices[indexCounter] = i;
indexCounter++;
}
}
BindBuffers();
GL.BufferData(BufferTarget.ElementArrayBuffer, (IntPtr) (_totalIndices * sizeof(uint)), vboIndices, BufferUsageHint.StaticDraw);
GL.BufferData(BufferTarget.ArrayBuffer, (IntPtr)(_totalVertices * _vertexStride), vboVertices, BufferUsageHint.StaticDraw);
ReleaseBuffers();
}
public void RenderVBO()
{
GL.EnableClientState(ArrayCap.VertexArray);
GL.EnableClientState(ArrayCap.NormalArray);
GL.EnableClientState(ArrayCap.ColorArray);
BindBuffers();
GL.VertexPointer(3, VertexPointerType.Float, _vertexStride, (IntPtr) (0));
GL.NormalPointer(NormalPointerType.Float, _vertexStride, (IntPtr) (3 * sizeof(float)));
GL.TexCoordPointer(2, TexCoordPointerType.Float, _vertexStride, (IntPtr) (6 * sizeof(float)));
GL.ColorPointer(4, ColorPointerType.Byte, _vertexStride, (IntPtr) (8 * sizeof(float)));
GL.DrawElements(BeginMode.Quads, numIndices, DrawElementsType.UnsignedInt, startLocation);
ReleaseBuffers();
GL.DisableClientState(ArrayCap.VertexArray);
GL.DisableClientState(ArrayCap.NormalArray);
GL.DisableClientState(ArrayCap.ColorArray);
{
}
具体的な質問:
1.) インターリーブされた頂点データ構造は、構造体またはクラスのどちらである必要がありますか? これは、VBO および/またはメモリ フットプリントに関する限り、違いがありますか? (私は構造体を使用することにしましたが、それは間違っていると感じました。頂点はメモリに格納されると変更されないためです。)
2.) このデータ構造は本当に 32 バイトの倍数のサイズである必要がありますか? (つまり、正しいサイズを強制するために「ダミー」のパディングメンバーが必要ですか?オンラインで見つけた例はすべて C++ であったため、同じアイデア/動機が C# に引き継がれるかどうかに特に関心があります。
3.) [Serializable] [StructLayout(LayoutKind.Sequential)] は本当に必要ですか? これをオンラインで見つけた例からコピーしたので...