// Creates bricks at the coarsest level for all areas that are overlapped by the pass in volume
        private void Rasterize(Volume volume, List <Brick> outBricks)
        {
            Profiler.BeginSample("Rasterize");
            // Calculate bounding box for volume in refvol space
            var AABB = volume.CalculateAABB();

            // Calculate smallest brick size capable of covering shortest AABB dimension
            float minVolumeSize    = Mathf.Min(AABB.size.x, Mathf.Min(AABB.size.y, AABB.size.z));
            int   brickSubDivLevel = Mathf.Min(Mathf.CeilToInt(Mathf.Log(minVolumeSize, 3)), m_MaxSubdivision);
            int   brickTotalSize   = (int)Mathf.Pow(3, brickSubDivLevel);

            // Extend AABB to have origin that lies on a grid point
            AABB.Encapsulate(new Vector3(
                                 brickTotalSize * Mathf.Floor(AABB.min.x / brickTotalSize),
                                 brickTotalSize * Mathf.Floor(AABB.min.y / brickTotalSize),
                                 brickTotalSize * Mathf.Floor(AABB.min.z / brickTotalSize)));

            // Calculate origin of bricks and how many are needed to cover volume
            Vector3Int origin          = Vector3Int.FloorToInt(AABB.min);
            Vector3    logicalBrickRes = Vector3Int.CeilToInt(AABB.size / brickTotalSize);

            // Cover the volume with bricks
            for (int x = 0; x < logicalBrickRes.x; x++)
            {
                for (int y = 0; y < logicalBrickRes.y; y++)
                {
                    for (int z = 0; z < logicalBrickRes.z; z++)
                    {
                        Vector3Int pos = origin + new Vector3Int(x, y, z) * brickTotalSize;
                        outBricks.Add(new Brick(pos, brickSubDivLevel));
                    }
                }
            }
            Profiler.EndSample();
        }