public bool LoadFromKtx(string path)
        {
            string iblPath = path + "_ibl.ktx";

            if (!File.Exists(iblPath))
            {
                return(false);
            }

            string skyPath = path + "_skybox.ktx";

            if (!File.Exists(skyPath))
            {
                return(false);
            }

            var iblKtx = CreateKtx(iblPath);
            var skyKtx = CreateKtx(skyPath);

            _skyboxTexture = KtxUtility.CreateTexture(_engine, skyKtx, false);
            _texture       = KtxUtility.CreateTexture(_engine, iblKtx, false);

            if (!iblKtx.GetSphericalHarmonics(out _bands))
            {
                return(false);
            }

            IndirectLight = IndirectLightBuilder.Create()
                            .WithReflections(_texture)
                            .WithIntensity(Intensity)
                            .Build(_engine);

            Skybox = SkyboxBuilder.Create()
                     .WithEnvironment(_skyboxTexture)
                     .WithSun(true)
                     .Build(_engine);

            return(true);
        }
        public bool LoadFromDirectory(string path)
        {
            // First check if KTX files are available.
            if (LoadFromKtx(Path.Combine(path, Path.GetFileName(path))))
            {
                return(true);
            }

            // Read spherical harmonics
            string sh      = Path.Combine(path, "sh.txt");
            var    pattern = new Regex(@"^\([\s]{0,}(.+),[\s]{0,}(.+),[\s]{0,}(.+)\)", RegexOptions.Compiled);

            if (File.Exists(sh))
            {
                var lines = File.ReadAllLines(sh);

                if (lines.Length != _bands.Length)
                {
                    return(false);
                }

                for (var i = 0; i < _bands.Length; i++)
                {
                    var matches = pattern.Matches(lines[i]);

                    if (!pattern.IsMatch(lines[0]))
                    {
                        return(false);
                    }

                    var parts = matches[0].Groups;

                    if (!float.TryParse(parts[1].Value, out var r))
                    {
                        return(false);
                    }

                    if (!float.TryParse(parts[2].Value, out var g))
                    {
                        return(false);
                    }

                    if (!float.TryParse(parts[3].Value, out var b))
                    {
                        return(false);
                    }

                    _bands[i] = new Vector3(r, g, b);
                }
            }
            else
            {
                return(false);
            }

            // Read mip-mapped cubemap
            string prefix = "m";

            if (!LoadCubemapLevel(ref _texture, path, 0, prefix + "0_"))
            {
                return(false);
            }

            int numLevels = _texture.Levels;

            for (var i = 1; i < numLevels; i++)
            {
                LoadCubemapLevel(ref _texture, path, i, prefix + i + "_");
            }

            if (!LoadCubemapLevel(ref _skyboxTexture, path))
            {
                return(false);
            }

            IndirectLight = IndirectLightBuilder.Create()
                            .WithReflections(_texture)
                            .WithIrradiance(3, _bands)
                            .WithIntensity(Intensity)
                            .Build(_engine);

            Skybox = SkyboxBuilder.Create()
                     .WithEnvironment(_skyboxTexture)
                     .WithSun(true)
                     .Build(_engine);

            return(true);
        }