Exemplo n.º 1
0
        public void Create(long key, byte[] data, GalImage image)
        {
            int handle = GL.GenTexture();

            TextureTarget target = ImageUtils.GetTextureTarget(image.TextureTarget);

            GL.BindTexture(target, handle);

            const int level  = 0; //TODO: Support mipmap textures.
            const int border = 0;

            _textureCache.AddOrUpdate(key, new ImageHandler(handle, image), (uint)data.Length);

            if (ImageUtils.IsCompressed(image.Format) && !IsAstc(image.Format))
            {
                InternalFormat internalFmt = OglEnumConverter.GetCompressedImageFormat(image.Format);

                switch (target)
                {
                case TextureTarget.Texture1D:
                    GL.CompressedTexImage1D(
                        target,
                        level,
                        internalFmt,
                        image.Width,
                        border,
                        data.Length,
                        data);
                    break;

                case TextureTarget.Texture2D:
                    GL.CompressedTexImage2D(
                        target,
                        level,
                        internalFmt,
                        image.Width,
                        image.Height,
                        border,
                        data.Length,
                        data);
                    break;

                case TextureTarget.Texture3D:
                    GL.CompressedTexImage3D(
                        target,
                        level,
                        internalFmt,
                        image.Width,
                        image.Height,
                        image.Depth,
                        border,
                        data.Length,
                        data);
                    break;

                // Cube map arrays are just 2D texture arrays with 6 entries
                // per cube map so we can handle them in the same way
                case TextureTarget.TextureCubeMapArray:
                case TextureTarget.Texture2DArray:
                    GL.CompressedTexImage3D(
                        target,
                        level,
                        internalFmt,
                        image.Width,
                        image.Height,
                        image.LayerCount,
                        border,
                        data.Length,
                        data);
                    break;

                case TextureTarget.TextureCubeMap:
                    Span <byte> array = new Span <byte>(data);

                    int faceSize = ImageUtils.GetSize(image) / 6;

                    for (int Face = 0; Face < 6; Face++)
                    {
                        GL.CompressedTexImage2D(
                            TextureTarget.TextureCubeMapPositiveX + Face,
                            level,
                            internalFmt,
                            image.Width,
                            image.Height,
                            border,
                            faceSize,
                            array.Slice(Face * faceSize, faceSize).ToArray());
                    }
                    break;

                default:
                    throw new NotImplementedException($"Unsupported texture target type: {target}");
                }
            }
            else
            {
                //TODO: Use KHR_texture_compression_astc_hdr when available
                if (IsAstc(image.Format))
                {
                    int textureBlockWidth  = ImageUtils.GetBlockWidth(image.Format);
                    int textureBlockHeight = ImageUtils.GetBlockHeight(image.Format);
                    int textureBlockDepth  = ImageUtils.GetBlockDepth(image.Format);

                    data = AstcDecoder.DecodeToRgba8888(
                        data,
                        textureBlockWidth,
                        textureBlockHeight,
                        textureBlockDepth,
                        image.Width,
                        image.Height,
                        image.Depth);

                    image.Format = GalImageFormat.Rgba8 | (image.Format & GalImageFormat.TypeMask);
                }

                (PixelInternalFormat internalFmt,
                 PixelFormat format,
                 PixelType type) = OglEnumConverter.GetImageFormat(image.Format);


                switch (target)
                {
                case TextureTarget.Texture1D:
                    GL.TexImage1D(
                        target,
                        level,
                        internalFmt,
                        image.Width,
                        border,
                        format,
                        type,
                        data);
                    break;

                case TextureTarget.Texture2D:
                    GL.TexImage2D(
                        target,
                        level,
                        internalFmt,
                        image.Width,
                        image.Height,
                        border,
                        format,
                        type,
                        data);
                    break;

                case TextureTarget.Texture3D:
                    GL.TexImage3D(
                        target,
                        level,
                        internalFmt,
                        image.Width,
                        image.Height,
                        image.Depth,
                        border,
                        format,
                        type,
                        data);
                    break;

                // Cube map arrays are just 2D texture arrays with 6 entries
                // per cube map so we can handle them in the same way
                case TextureTarget.TextureCubeMapArray:
                case TextureTarget.Texture2DArray:
                    GL.TexImage3D(
                        target,
                        level,
                        internalFmt,
                        image.Width,
                        image.Height,
                        image.LayerCount,
                        border,
                        format,
                        type,
                        data);
                    break;

                case TextureTarget.TextureCubeMap:
                    Span <byte> array = new Span <byte>(data);

                    int faceSize = ImageUtils.GetSize(image) / 6;

                    for (int face = 0; face < 6; face++)
                    {
                        GL.TexImage2D(
                            TextureTarget.TextureCubeMapPositiveX + face,
                            level,
                            internalFmt,
                            image.Width,
                            image.Height,
                            border,
                            format,
                            type,
                            array.Slice(face * faceSize, faceSize).ToArray());
                    }
                    break;

                default:
                    throw new NotImplementedException($"Unsupported texture target type: {target}");
                }
            }
        }