public OctreeRenderer(OctreeModel model, OpenGL gl) { _gl = gl; _octreeProgram = new OctreeShader(gl); _cubes = new VAO(gl); _cubeBuffer = new VBO(gl); var filled = model.Node.Flatten().Where(o => o.State == NodeState.Filled).ToArray(); _count = filled.Length; var list = new List <float>(); foreach (var octreeNode in filled) { list.AddRange(octreeNode.Center.ToArray().Select(d => (float)d)); list.AddRange(new[] { (float)MathsHelper.Map(octreeNode.Color.R, 0, 255, 0, 1), (float)MathsHelper.Map(octreeNode.Color.G, 0, 255, 0, 1), (float)MathsHelper.Map(octreeNode.Color.B, 0, 255, 0, 1), (float)MathsHelper.Map(octreeNode.Color.A, 0, 255, 0, 1), (float)octreeNode.Size }); } var vertices = list.ToArray(); using (new Bind(_cubes)) using (new Bind(_cubeBuffer)) { _cubeBuffer.Update(vertices, vertices.Length * sizeof(float)); const int stride = sizeof(float) * 8; gl.EnableVertexAttribArray(0); gl.VertexAttribPointer(0, 3, OpenGL.GL_FLOAT, false, stride, new IntPtr(0)); gl.EnableVertexAttribArray(1); gl.VertexAttribPointer(1, 4, OpenGL.GL_FLOAT, false, stride, new IntPtr(sizeof(float) * 3)); gl.EnableVertexAttribArray(2); gl.VertexAttribPointer(2, 1, OpenGL.GL_FLOAT, false, stride, new IntPtr(sizeof(float) * 7)); gl.BindVertexArray(0); } }