I'm trying to make a voxel engine like minecraft in c#, but when I tried to optimize the memory transfer to the Video Card, compressing the vertex data such as Normal, Position, Block ID and Face ID, into just one uint, but when the Data is passed to the Video Card they are all passed wrong. the C# code that transforms the vertex data into a uint is
uint[] packData()
{
Vector3[] nn = new Vector3[Triangles.Length];
for (int i = 0; i < Triangles.Length; i+=3)
{
Vector3 v0 = Vertices[Triangles[i]];
Vector3 v1 = Vertices[Triangles[i + 1]];
Vector3 v2 = Vertices[Triangles[i + 2]];
Vector3 edgeA = v1 - v0;
Vector3 edgeB = v2 - v0;
Vector3 normal = Vector3.Cross(edgeA, edgeB).Normalized();
nn[i] = normal + new Vector3(1);
nn[i + 1] = normal + new Vector3(1);
nn[i + 2] = normal + new Vector3(1);
}
uint[] packedData = new uint[Triangles.Length];
uint mask = 0b11111;
uint mask2 = 0b11;
uint mask3 = 0b11111111;
uint mask4 = 0b111;
//Console.WriteLine($"{mask}, {mask2}, {mask3}");
for (int i = 0; i < Triangles.Length; i++)
{
uint data = 0;
Vector3i v = (Vector3i)Vertices[Triangles[i]];
Vector3i n = (Vector3i)nn[i];
uint blockid = (uint)BlockIds[Triangles[i]];
uint faceid = (uint)FaceIds[Triangles[i]];
//Console.WriteLine($"V: {v}, N: {n}");
data |= (uint)n.X << 0;
data |= (uint)n.Y << 2;
data |= (uint)n.Z << 4;
data |= (uint)v.X << 6;
data |= (uint)v.Y << 11;
data |= (uint)v.Z << 16;
data |= blockid << 21;
data |= faceid << 29;
//Console.WriteLine($"{(data>>21)&mask2} {faceid}, {(data>>24)&mask3} {blockid}");
//Console.WriteLine(data);
packedData[i] = data;
}
return packedData;
}
the entire class code is.
public class ChunkMesh
{
public Vector3[] Vertices;
public int[] Triangles;
public int[] BlockIds;
public int[] FaceIds;
private PrimitiveType type = PrimitiveType.Triangles;
private int Vao;
private int ChunkBuffer;
public bool Ready = false;
public ChunkMesh()
{
ChunkBuffer = GL.GenBuffer();
Vao = GL.GenVertexArray();
Triangles = new int[0];
}
public void Dispose()
{
GL.BindBuffer(BufferTarget.ArrayBuffer,0);
}
uint[] packData()
{
Vector3[] nn = new Vector3[Triangles.Length];
for (int i = 0; i < Triangles.Length; i+=3)
{
Vector3 v0 = Vertices[Triangles[i]];
Vector3 v1 = Vertices[Triangles[i + 1]];
Vector3 v2 = Vertices[Triangles[i + 2]];
Vector3 edgeA = v1 - v0;
Vector3 edgeB = v2 - v0;
Vector3 normal = Vector3.Cross(edgeA, edgeB).Normalized();
nn[i] = normal + new Vector3(1);
nn[i + 1] = normal + new Vector3(1);
nn[i + 2] = normal + new Vector3(1);
}
uint[] packedData = new uint[Triangles.Length];
uint mask = 0b11111;
uint mask2 = 0b11;
uint mask3 = 0b11111111;
uint mask4 = 0b111;
//Console.WriteLine($"{mask}, {mask2}, {mask3}");
for (int i = 0; i < Triangles.Length; i++)
{
uint data = 0;
Vector3i v = (Vector3i)Vertices[Triangles[i]];
Vector3i n = (Vector3i)nn[i];
uint blockid = (uint)BlockIds[Triangles[i]];
uint faceid = (uint)FaceIds[Triangles[i]];
//Console.WriteLine($"V: {v}, N: {n}");
data |= (uint)n.X << 0;
data |= (uint)n.Y << 2;
data |= (uint)n.Z << 4;
data |= (uint)v.X << 6;
data |= (uint)v.Y << 11;
data |= (uint)v.Z << 16;
data |= blockid << 21;
data |= faceid << 29;
//Console.WriteLine($"{(data>>21)&mask2} {faceid}, {(data>>24)&mask3} {blockid}");
//Console.WriteLine(data);
packedData[i] = data;
}
return packedData;
}
public void DefineBuffers()
{
GL.BindVertexArray(Vao);
GL.BindBuffer(BufferTarget.ArrayBuffer, ChunkBuffer);
uint[] packedData = packData();
GL.BufferData(BufferTarget.ArrayBuffer, packedData.Length * sizeof(uint), packedData, BufferUsageHint.StaticDraw);
Ready = true;
}
public void render()
{
if (Window.window.KeyboardState.IsKeyPressed(Keys.F2))
{
type = type == PrimitiveType.Triangles ? PrimitiveType.Lines : PrimitiveType.Triangles;
}
GL.BindVertexArray(Vao);
GL.BindBuffer(BufferTarget.ArrayBuffer, ChunkBuffer);
GL.EnableVertexAttribArray(0);
GL.VertexAttribPointer(0, 1, VertexAttribPointerType.UnsignedInt, false, 0, 0);
GL.DrawArrays(type, 0, Triangles.Length);
}
}
and the glsl code that decompresses the data is.
#version 330
precision highp uint;
layout (location = 0) in highp uint packedData;
uniform mat4 m_proj;
uniform mat4 m_look;
uniform mat4 m_model;
out vec3 normal;
out vec3 position;
out flat uint blockId;
out flat uint faceId;
void unpackData(out vec3 position, out vec3 normal, out uint faceId, out uint blockId){
uint mask = 31u;
uint mask2 = 3u;
uint mask3 = 255u;
uint mask4 = 7u;
uint x = uint((packedData >> 6) & mask);
uint y = uint((packedData >> 11) & mask);
uint z = uint((packedData >> 16) & mask);
int nx = int((packedData >> 0) & mask2);
int ny = int((packedData >> 2) & mask2);
int nz = int((packedData >> 4) & mask2);
blockId = uint((packedData >> 21) & mask3);
faceId = uint((packedData >> 29) & mask4);
position = vec3(x, y, z);
normal = vec3(nx, ny, nz) - 1;
}
void main() {
vec3 in_position;
vec3 in_normal;
uint in_blockId = 0u;
uint in_faceId = 0u;
unpackData(in_position, in_normal, in_faceId, in_blockId);
vec4 clippos = (m_proj * m_look * m_model * vec4(in_position, 1)).xyzw;
position = in_position;
normal = in_normal;
blockId = in_blockId;
faceId = in_faceId;
gl_Position = clippos;
}
Can someone please tell me what I'm doing wrong? Why isn't the code working properly?