func (ps *ParticleSystem) SetVaos() {
	ps.TransformProg.Use()

	ps.VaoTff1.Bind()
	ps.NonTransformBuffer.Bind(gl.ARRAY_BUFFER)
	helpers.SetAttribPointers(&ps.TransformLoc, &NonTransformBuffer{}, false)
	ps.Data1.Bind(gl.ARRAY_BUFFER)
	helpers.SetAttribPointers(&ps.TransformLoc, &ParticleVertex{}, false)
	ps.Data2.BindBufferBase(gl.TRANSFORM_FEEDBACK_BUFFER, 0)

	ps.VaoTff2.Bind()
	ps.NonTransformBuffer.Bind(gl.ARRAY_BUFFER)
	helpers.SetAttribPointers(&ps.TransformLoc, &NonTransformBuffer{}, false)
	ps.Data2.Bind(gl.ARRAY_BUFFER)
	helpers.SetAttribPointers(&ps.TransformLoc, &ParticleVertex{}, false)
	ps.Data1.BindBufferBase(gl.TRANSFORM_FEEDBACK_BUFFER, 0)

	ps.RenderProg.Use()

	ps.VaoRender1.Bind()
	ps.Data1.Bind(gl.ARRAY_BUFFER)
	helpers.SetAttribPointers(&ps.RenderLoc, &ParticleVertex{}, true)
	ps.ShapeData.Bind(gl.ARRAY_BUFFER)
	helpers.SetAttribPointers(&ps.RenderLoc, &ParticleShapeVertex{}, false)

	ps.VaoRender2.Bind()
	ps.Data2.Bind(gl.ARRAY_BUFFER)
	helpers.SetAttribPointers(&ps.RenderLoc, &ParticleVertex{}, true)
	ps.ShapeData.Bind(gl.ARRAY_BUFFER)
	helpers.SetAttribPointers(&ps.RenderLoc, &ParticleShapeVertex{}, false)
}
func NewLineRenderer() *LineRenderer {
	renderer := LineRenderer{}
	renderer.Prog = helpers.MakeProgram("Line.vs", "Line.fs")
	renderer.Prog.Use()
	renderer.vao = gl.GenVertexArray()
	renderer.vao.Bind()
	helpers.BindLocations("line", renderer.Prog, &renderer.RenLoc)
	renderer.buffer = gl.GenBuffer()
	renderer.buffer.Bind(gl.ARRAY_BUFFER)
	helpers.SetAttribPointers(&renderer.RenLoc, &debug.LineVertex{}, false)

	fmt.Println("Line render location ", renderer.RenLoc)
	return &renderer
}
func LoadMeshToGpu(mesh *Mesh, renLoc *RenderLocations) (rd RenderData) {
	rd.VAO = gl.GenVertexArray()
	rd.VAO.Bind()

	{
		vertices := mesh.Vertices
		verticesType := reflect.TypeOf(vertices)
		if verticesType.Kind() != reflect.Slice {
			panic("Vertices is not a slice")
		}
		rd.Vertices = gl.GenBuffer()
		rd.Vertices.Bind(gl.ARRAY_BUFFER)
		gl.BufferData(gl.ARRAY_BUFFER, helpers.ByteSizeOfSlice(vertices), vertices, gl.STATIC_DRAW)
		rd.Numverts = reflect.ValueOf(vertices).Len()
		helpers.SetAttribPointers(renLoc, reflect.ValueOf(vertices).Index(0).Addr().Interface(), false)
		switch mesh.Mode {
		case Points:
			rd.Mode = gl.POINTS
		case LineStrip:
			rd.Mode = gl.LINE_STRIP
		case LineLoop:
			rd.Mode = gl.LINE_LOOP
		case Lines:
			rd.Mode = gl.LINES
		case TriangleStrip:
			rd.Mode = gl.TRIANGLE_STRIP
		case TriangleFan:
			rd.Mode = gl.TRIANGLE_FAN
		case Triangles:
			rd.Mode = gl.TRIANGLES
		default:
			panic("unsupported mode")
		}
	}

	if indices := mesh.Indices; indices != nil {
		indicesType := reflect.TypeOf(indices)
		if indicesType.Kind() != reflect.Slice {
			panic("Indices is not a slice")
		}
		rd.Indices = gl.GenBuffer()
		rd.Indices.Bind(gl.ELEMENT_ARRAY_BUFFER)
		gl.BufferData(gl.ELEMENT_ARRAY_BUFFER, helpers.ByteSizeOfSlice(indices), indices, gl.STATIC_DRAW)
		rd.Numverts = reflect.ValueOf(indices).Len()
		switch indicesType.Elem().Kind() {
		case reflect.Uint8, reflect.Int8:
			rd.IndexType = gl.UNSIGNED_BYTE
		case reflect.Uint16, reflect.Int16:
			rd.IndexType = gl.UNSIGNED_SHORT
		case reflect.Uint32, reflect.Int32:
			rd.IndexType = gl.UNSIGNED_INT
		default:
			panic(fmt.Sprint("unsupported index type", indicesType.Elem().Kind()))
		}
	}

	if instanceData := mesh.InstanceData; instanceData != nil {
		Type := reflect.TypeOf(instanceData)
		if Type.Kind() != reflect.Slice {
			panic("InstanceData is not a slice")
		}
		rd.InstanceData = gl.GenBuffer()
		rd.InstanceData.Bind(gl.ARRAY_BUFFER)
		gl.BufferData(gl.ARRAY_BUFFER, helpers.ByteSizeOfSlice(instanceData), instanceData, gl.STATIC_DRAW)
		helpers.SetAttribPointers(renLoc, reflect.ValueOf(instanceData).Index(0).Addr().Interface(), true)

		rd.NumInstances = reflect.ValueOf(instanceData).Len()
	}
	return
}