예제 #1
0
        /// <summary>
        /// adds pixels to the image edges
        /// </summary>
        /// <param name="src">source image</param>
        /// <param name="leftPad">padding on the left/top/front side</param>
        /// <param name="rightPad">padding on the right/bot/back side</param>
        /// <param name="fill">padding fill mode</param>
        /// <param name="scaling">used for regenerating mipmaps (may be null if no mipmaps need to be generated)</param>
        /// <param name="shared"></param>
        /// <param name="keepMipmaps">if set to false, no mipmaps will be generated</param>
        /// <returns>same as source with added padding (amount of mipmaps might change, format remains)</returns>
        public ITexture Run(ITexture src, Size3 leftPad, Size3 rightPad, FillMode fill, ScalingModel scaling, SharedModel shared, bool keepMipmaps = true)
        {
            Size3 dstSize  = leftPad + rightPad + src.Size;
            int   nMipmaps = src.NumMipmaps > 1 ? dstSize.MaxMipLevels : 1;

            if (!keepMipmaps)
            {
                nMipmaps = 1;
            }

            var dst = src.Create(new LayerMipmapCount(src.NumLayers, nMipmaps), dstSize, src.Format, src.HasUaViews,
                                 true);

            var dev = DirectX.Device.Get();

            shared.Upload.SetData(new BufferData
            {
                Depth  = dstSize.Depth,
                Offset = new Float3(leftPad) / new Float3(dstSize),
                Scale  = new Float3(dstSize) / new Float3(src.Size),
            });

            shared.QuadShader.Bind(src.Is3D);
            if (src.Is3D)
            {
                dev.Pixel.Set(shader3D.Pixel);
            }
            else
            {
                dev.Pixel.Set(shader.Pixel);
            }
            dev.Pixel.SetSampler(0, sampler[(int)fill]);
            dev.Pixel.SetConstantBuffer(0, shared.Upload.Handle);

            foreach (var lm in src.LayerMipmap.RangeOf(LayerMipmapRange.MostDetailed))
            {
                dev.OutputMerger.SetRenderTargets(dst.GetRtView(lm));
                dev.SetViewScissors(dstSize.Width, dstSize.Height);
                dev.Pixel.SetShaderResource(0, src.GetSrView(lm));

                dev.DrawFullscreenTriangle(dstSize.Depth);
            }

            // remove bindings
            shared.QuadShader.Unbind();
            dev.Pixel.Set(null);
            dev.OutputMerger.SetRenderTargets((RenderTargetView)null);
            dev.Pixel.SetShaderResource(0, null);

            if (dst.NumMipmaps > 1)
            {
                Debug.Assert(scaling != null);
                scaling.WriteMipmaps(dst);
            }

            return(dst);
        }
예제 #2
0
        /// <summary>
        /// returns one unused texture if available. creates a new texture if not textures were available
        /// </summary>
        /// <returns></returns>
        public ITexture GetTexture()
        {
            if (textures.Count > 0)
            {
                return(textures.Pop());
            }

            // make new texture with the current configuration
            return(templateTex.Create(templateTex.LayerMipmap, templateTex.Size,
                                      format, createUav));
        }
예제 #3
0
        /// <summary>
        /// converts the texture into another format and performs cropping if requested
        /// </summary>
        /// <param name="texture">source texture</param>
        /// <param name="dstFormat">destination format</param>
        /// <param name="srcLm">layer/mipmap to export</param>
        /// <param name="multiplier">rgb channels will be multiplied by this value</param>
        /// <param name="crop">indicates if the image should be cropped, only works with 1 mipmap to export</param>
        /// <param name="offset">if crop: offset in source image</param>
        /// <param name="size">if crop: size of the destination image</param>
        /// <param name="align">if nonzero: texture width will be aligned to this (rounded down)</param>
        /// <param name="scaling">required for regenerating mipmaps after cropping.</param>
        /// <param name="overlay">overlay</param>
        /// <param name="scale">scales the destination image by this factor</param>
        /// <returns></returns>
        public ITexture Convert(ITexture texture, SharpDX.DXGI.Format dstFormat, LayerMipmapRange srcLm, float multiplier, bool crop,
                                Size3 offset, Size3 size, Size3 align, ScalingModel scaling, ITexture overlay = null, int scale = 1)
        {
            Debug.Assert(ImageFormat.IsSupported(dstFormat));
            Debug.Assert(ImageFormat.IsSupported(texture.Format));
            Debug.Assert(overlay == null || texture.HasSameDimensions(overlay));
            Debug.Assert(scale >= 1);

            // set width, height mipmap
            int nMipmaps = srcLm.IsSingleMipmap ? 1: texture.NumMipmaps;
            int nLayer   = srcLm.IsSingleLayer ? 1 : texture.NumLayers;

            // set correct width, height, offsets
            if (!crop)
            {
                size   = texture.Size.GetMip(srcLm.FirstMipmap);
                offset = Size3.Zero;
            }

            if (scale != 1)
            {
                size.X *= scale;
                size.Y *= scale;
                if (texture.Is3D)
                {
                    size.Z *= scale;
                }
                offset.X *= scale;
                offset.Y *= scale;
                if (texture.Is3D)
                {
                    offset.Z *= scale;
                }
            }

            // adjust alignments
            for (int i = 0; i < 3; ++i)
            {
                if (align[i] != 0)
                {
                    if (size[i] % align[i] != 0)
                    {
                        if (size[i] < align[i])
                        {
                            throw new Exception($"image needs to be aligned to {align[i]} but one axis is only {size[i]}. Axis should be at least {align[i]}");
                        }

                        crop = true;
                        var remainder = size[i] % align[i];
                        offset[i] = offset[i] + remainder / 2;
                        size[i]   = size[i] - remainder;
                    }
                }
            }

            bool recomputeMips = nMipmaps > 1 && (crop || scale != 1);

            if (recomputeMips)
            {
                // number of mipmaps might have changed
                nMipmaps      = size.MaxMipLevels;
                recomputeMips = nMipmaps > 1;
            }

            var res = texture.Create(new LayerMipmapCount(nLayer, nMipmaps), size, dstFormat, false);

            var dev = DirectX.Device.Get();

            quad.Bind(texture.Is3D);
            if (texture.Is3D)
            {
                dev.Pixel.Set(convert3D.Pixel);
            }
            else
            {
                dev.Pixel.Set(convert2D.Pixel);
            }

            dev.Pixel.SetShaderResource(0, texture.View);
            if (overlay != null)
            {
                dev.Pixel.SetShaderResource(1, overlay.View);
            }
            else
            {
                dev.Pixel.SetShaderResource(1, null);
            }

            foreach (var dstLm in res.LayerMipmap.Range)
            {
                cbuffer.SetData(new LayerLevelOffsetData
                {
                    Layer      = dstLm.Layer + srcLm.FirstLayer + offset.Z,
                    Level      = dstLm.Mipmap + srcLm.FirstMipmap,
                    Xoffset    = offset.X,
                    Yoffset    = offset.Y,
                    Multiplier = multiplier,
                    UseOverlay = overlay != null ? 1 : 0,
                    Scale      = scale
                });

                var dim = res.Size.GetMip(dstLm.Mipmap);
                dev.Pixel.SetConstantBuffer(0, cbuffer.Handle);
                dev.OutputMerger.SetRenderTargets(res.GetRtView(dstLm));
                dev.SetViewScissors(dim.Width, dim.Height);
                dev.DrawFullscreenTriangle(dim.Depth);

                if (recomputeMips && dstLm.Mipmap > 0)
                {
                    break;                                    // only write most detailed mipmap
                }
            }

            // remove bindings
            dev.Pixel.SetShaderResource(0, null);
            dev.Pixel.SetShaderResource(1, null);
            dev.OutputMerger.SetRenderTargets((RenderTargetView)null);
            quad.Unbind();

            if (recomputeMips)
            {
                scaling.WriteMipmaps(res);
            }

            return(res);
        }
예제 #4
0
        /// <summary>
        /// converts the texture into another format and performs cropping if requested
        /// </summary>
        /// <param name="texture">source texture</param>
        /// <param name="dstFormat">destination format</param>
        /// <param name="mipmap">mipmap to export, -1 for all mipmaps</param>
        /// <param name="layer">layer to export, -1 for all layers</param>
        /// <param name="multiplier">rgb channels will be multiplied by this value</param>
        /// <param name="crop">indicates if the image should be cropped, only works with 1 mipmap to export</param>
        /// <param name="offset">if crop: offset in source image</param>
        /// <param name="size">if crop: size of the destination image</param>
        /// <param name="align">if nonzero: texture width will be aligned to this (rounded down)</param>
        /// <returns></returns>
        public ITexture Convert(ITexture texture, SharpDX.DXGI.Format dstFormat, int mipmap, int layer, float multiplier, bool crop,
                                Size3 offset, Size3 size, Size3 align)
        {
            Debug.Assert(ImageFormat.IsSupported(dstFormat));
            Debug.Assert(ImageFormat.IsSupported(texture.Format));

            // set width, height mipmap
            int firstMipmap = Math.Max(mipmap, 0);
            int firstLayer  = Math.Max(layer, 0);
            int nMipmaps    = mipmap == -1 ? texture.NumMipmaps : 1;
            int nLayer      = layer == -1 ? texture.NumLayers : 1;

            // set correct width, height, offsets
            if (!crop)
            {
                size   = texture.Size.GetMip(firstMipmap);
                offset = Size3.Zero;
            }

            // adjust alignments
            for (int i = 0; i < 3; ++i)
            {
                if (align[i] != 0)
                {
                    if (size[i] % align[i] != 0)
                    {
                        if (size[i] < align[i])
                        {
                            throw new Exception($"image needs to be aligned to {align[i]} but one axis is only {size[i]}. Axis should be at least {align[i]}");
                        }

                        crop = true;
                        var remainder = size[i] % align[i];
                        offset[i] = offset[i] + remainder / 2;
                        size[i]   = size[i] - remainder;
                    }
                }
            }

            bool recomputeMips = nMipmaps > 1 && crop;

            if (recomputeMips)
            {
                // number of mipmaps might have changed
                nMipmaps      = ImagesModel.ComputeMaxMipLevels(size);
                recomputeMips = nMipmaps > 1;
            }

            var res = texture.Create(nLayer, nMipmaps, size, dstFormat, false);

            var dev = DirectX.Device.Get();

            quad.Bind(texture.Is3D);
            if (texture.Is3D)
            {
                dev.Pixel.Set(convert3D.Pixel);
            }
            else
            {
                dev.Pixel.Set(convert2D.Pixel);
            }

            dev.Pixel.SetShaderResource(0, texture.View);

            for (int curLayer = 0; curLayer < nLayer; ++curLayer)
            {
                for (int curMipmap = 0; curMipmap < nMipmaps; ++curMipmap)
                {
                    cbuffer.SetData(new LayerLevelOffsetData
                    {
                        Layer      = curLayer + firstLayer + offset.Z,
                        Level      = curMipmap + firstMipmap,
                        Xoffset    = offset.X,
                        Yoffset    = offset.Y,
                        Multiplier = multiplier
                    });

                    var dim = res.Size.GetMip(curMipmap);
                    dev.Pixel.SetConstantBuffer(0, cbuffer.Handle);
                    dev.OutputMerger.SetRenderTargets(res.GetRtView(curLayer, curMipmap));
                    dev.SetViewScissors(dim.Width, dim.Height);
                    dev.DrawFullscreenTriangle(dim.Depth);

                    if (recomputeMips)
                    {
                        break;               // only write most detailed mipmap
                    }
                }
            }

            // remove bindings
            dev.Pixel.SetShaderResource(0, null);
            dev.OutputMerger.SetRenderTargets((RenderTargetView)null);
            quad.Unbind();

            if (recomputeMips)
            {
                res.RegenerateMipmapLevels();
            }

            return(res);
        }