static void BuildLightContext(MeshFilter[] meshes, List <Light> lights, BakeContext ctx)
        {
            int lightCount = lights.Count;

            // light data size
            const int lightPosSize   = 3; // padded with extra float
            const int LightDirSize   = 3; // padded with extra float
            const int lightColorSize = 3; // padded with extra float (don't need alpha)
            const int lightRIATSize  = 4; // range, intensity, angle, type

            int totalLightSize = lightCount * SIZE_FLOAT * (lightPosSize + LightDirSize + lightColorSize + lightRIATSize);

            VertexBakerLib instance = VertexBakerLib.Instance;

            ctx.m_lightsDataPtr = instance.Alloc(totalLightSize);
            ctx.m_lightsOptPtr  = instance.Alloc(lightCount * SIZE_LONG);
            int lightDestOffset = 0;

            float[] riat = new float[4];
            long[]  data = new long[lightCount];

            // light layout
            for (int l = 0; l < lightCount; ++l)
            {
                Light light = lights[l];
                riat[0] = light.range;
                riat[1] = light.intensity;
                riat[2] = light.spotAngle;
                riat[3] = (float)light.type;

                // position data
                IntPtr lightPosPtr = new IntPtr(ctx.m_lightsDataPtr.ToInt64() + lightDestOffset * SIZE_FLOAT);
                instance.CopyVector4(lightPosPtr, lightPosSize * SIZE_FLOAT, light.transform.position.ToVector4(1f), lightPosSize * SIZE_FLOAT);
                lightDestOffset += lightPosSize;

                // direction data
                IntPtr lightDirPtr = new IntPtr(ctx.m_lightsDataPtr.ToInt64() + lightDestOffset * SIZE_FLOAT);
                instance.CopyVector4(lightDirPtr, LightDirSize * SIZE_FLOAT, light.transform.forward.ToVector4(0f), LightDirSize * SIZE_FLOAT);
                lightDestOffset += LightDirSize;

                // color data
                IntPtr lightColorPtr = new IntPtr(ctx.m_lightsDataPtr.ToInt64() + lightDestOffset * SIZE_FLOAT);
                instance.CopyVector4(lightColorPtr, lightColorSize * SIZE_FLOAT, light.color.ToVector4(1f), lightColorSize * SIZE_FLOAT);
                lightDestOffset += LightDirSize;

                // IRAT data
                IntPtr lightIRATPtr = new IntPtr(ctx.m_lightsDataPtr.ToInt64() + lightDestOffset * SIZE_FLOAT);
                instance.CopyFloatArray(lightIRATPtr, lightRIATSize * SIZE_FLOAT, riat, lightRIATSize * SIZE_FLOAT);
                lightDestOffset += lightRIATSize;

                // set lighting options
                ulong dataValue = 0;
                // 3 bits
                dataValue |= (ulong)lights[l].shadows;
                // 32 bits max
                dataValue |= (ulong)(((long)lights[l].cullingMask) << 3);

                data[l] |= (long)dataValue;
            }

            Marshal.Copy(data, 0, ctx.m_lightsOptPtr, lightCount);
        }