public static void CreateLightmapTexture(GLContext control, AglLightMap aglLightMap,
                                                 EnvironmentGraphics environmentSettings, string name, GLTextureCube output)
        {
            var lightMapEnv = aglLightMap.LightAreas.FirstOrDefault(x => x.Settings.Name == name);

            if (lightMapEnv == null)
            {
                return;
            }

            //Force generate mipmaps to update the mip allocation so mips can be assigned.
            output.Bind();
            GL.GenerateMipmap(GenerateMipmapTarget.TextureCubeMap);
            GL.BindTexture(TextureTarget.TextureCubeMap, 0);
            GL.Enable(EnableCap.TextureCubeMapSeamless);

            if (FilterLevel0 == null)
            {
                Init(output.Width);
            }

            int CUBE_SIZE = output.Width;

            FilterLevel0.Bind();
            LoadCubemapLevel(control, CUBE_SIZE, 0, aglLightMap, environmentSettings, lightMapEnv, output.ID);
            FilterLevel0.Unbind();

            FilterLevel1.Bind();
            LoadCubemapLevel(control, CUBE_SIZE / 2, 1, aglLightMap, environmentSettings, lightMapEnv, output.ID);
            FilterLevel1.Unbind();

            output.SaveDDS($"LIGHTMAP{name}.dds");
        }
        static void LoadCubemapLevel(GLContext control, int size, int level, AglLightMap aglLightMap,
                                     EnvironmentGraphics environmentSettings, AglLightMap.LightArea lightMapEnv, int ID)
        {
            GL.Viewport(0, 0, size, size);

            var shader = GlobalShaders.GetShader("LIGHTMAP");

            shader.Enable();

            UpdateUniforms(control, shader, level, aglLightMap, environmentSettings, lightMapEnv);

            for (int i = 0; i < 6; i++)
            {
                GL.FramebufferTexture2D(FramebufferTarget.Framebuffer,
                                        FramebufferAttachment.ColorAttachment0 + i,
                                        TextureTarget.TextureCubeMapPositiveX + i, ID, level);
            }

            GL.ClearColor(0, 0, 0, 0);
            GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit);
            ScreenQuadRender.Draw();

            var errorcheck = GL.CheckFramebufferStatus(FramebufferTarget.Framebuffer);

            if (errorcheck != FramebufferErrorCode.FramebufferComplete)
            {
                throw new Exception(errorcheck.ToString());
            }

            GL.UseProgram(0);
        }
        static void UpdateUniforms(GLContext control, ShaderProgram shader, int mipLevel,
                                   AglLightMap aglLightMap, EnvironmentGraphics environmentSettings, AglLightMap.LightArea lightMapEnv)
        {
            if (aglLightMap.TextureLUT == null)
            {
                aglLightMap.Setup();
            }

            GL.ActiveTexture(TextureUnit.Texture0 + 1);
            NormalsTexture.Bind();
            shader.SetInt("uNormalTex", 1);

            GL.ActiveTexture(TextureUnit.Texture0 + 2);
            aglLightMap.TextureLUT.Bind();
            shader.SetInt("uLutTex", 2);

            var settings = lightMapEnv.Settings;

            shader.SetFloat($"settings.rim_angle", settings.rim_angle);
            shader.SetFloat($"settings.rim_width", settings.rim_width);
            shader.SetInt($"settings.type", settings.lighting_hint);

            for (int i = 0; i < 6; i++)
            {
                shader.SetVector3($"lights[{i}].dir", new Vector3(0));
                shader.SetVector4($"lights[{i}].lowerColor", new Vector4(0));
                shader.SetVector4($"lights[{i}].upperColor", new Vector4(0));
                shader.SetInt($"lights[{i}].lutIndex", 0);
            }

            int index = 0;

            //Loop through the light sources and apply them from the env settings
            foreach (var light in lightMapEnv.Lights)
            {
                //If the name is empty, skip as there is no way to find it.
                if (string.IsNullOrEmpty(light.Name))
                {
                    continue;
                }

                //Skip mip levels for specific light sources
                if (!light.enable_mip0 && mipLevel == 0 || !light.enable_mip1 && mipLevel == 1)
                {
                    continue;
                }

                LightSource lightSource = null;
                switch (light.Type)
                {
                case "DirectionalLight":
                    var dir = environmentSettings.DirectionalLights.FirstOrDefault(x => x.Name == light.Name);
                    if (dir != null && dir.Enable)
                    {
                        lightSource = LoadDirectionalLighting(dir);
                    }
                    break;

                case "HemisphereLight":
                    var hemi = environmentSettings.HemisphereLights.FirstOrDefault(x => x.Name == light.Name);
                    if (hemi != null && hemi.Enable)
                    {
                        lightSource = LoadHemiLighting(hemi);
                    }
                    break;

                case "AmbientLight":
                    var ambient = environmentSettings.AmbientLights.FirstOrDefault(x => x.Name == light.Name);
                    if (ambient != null && ambient.Enable)
                    {
                        lightSource = LoadAmbientLighting(ambient);
                    }
                    break;
                }

                if (lightSource == null)
                {
                    continue;
                }

                //Setup shared settings
                lightSource.LutIndex = aglLightMap.GetLUTIndex(light.LutName);

                int programID = shader.program;

                shader.SetVector3($"lights[{index}].dir", lightSource.Direction);
                shader.SetVector4($"lights[{index}].lowerColor", lightSource.LowerColor);
                shader.SetVector4($"lights[{index}].upperColor", lightSource.UpperColor);
                shader.SetInt($"lights[{index}].lutIndex", lightSource.LutIndex);
                index++;
            }
            lightMapEnv.Initialized = true;
        }