Example #1
0
        public static Texture FlushTextures()
        {
            var count = Textures.Count;

            TexturesPerLine = 1 << (int)Math.Ceiling(Math.Log(Math.Ceiling(Math.Sqrt(count))) / Math.Log(2));
            var wid = TexturesPerLine * pixelPerTexture;

            using (Texture texture = Texture.New2D(Context.GraphicsDevice, wid, wid, PixelFormat.R8G8B8A8_UNorm),
                   result = Texture.New2D(Context.GraphicsDevice, pixelPerTexture, pixelPerTexture,
                                          PixelFormat.R8G8B8A8_UNorm, TextureFlags.RenderTarget | TextureFlags.ShaderResource))
            {
                using (var scaler = new ImageScaler(SamplingPattern.Linear))
                {
                    scaler.SetOutput(result);
                    for (var i = 0; i < count; ++i)
                    {
                        var tile = Textures[i];
                        scaler.SetInput(tile);
                        scaler.Draw(Context.RdwContext);
                        var x  = i % TexturesPerLine;
                        var y  = i / TexturesPerLine;
                        var rx = x * pixelPerTexture;
                        var ry = y * pixelPerTexture;
                        Context.RdwContext.CommandList.CopyRegion(
                            result, result.GetSubResourceIndex(0, 0), null,
                            texture, texture.GetSubResourceIndex(0, 0), rx, ry);
                    }

                    return(MakeMipmap(texture, (int)Math.Floor(Math.Log(pixelPerTexture) / Math.Log(2)), scaler));
                }
            }
        }
Example #2
0
 private void CopyOrScaleTexture(RenderDrawContext drawContext, Texture input, Texture output)
 {
     if (input.Size != output.Size)
     {
         Scaler.SetInput(0, input);
         Scaler.SetOutput(output);
         Scaler.Draw(drawContext);
     }
     else
     {
         drawContext.CommandList.Copy(input, output);
     }
 }
Example #3
0
        private static Texture MakeMipmap(Texture input, int levels, ImageScaler scaler)
        {
            var ret  = Texture.New2D(Context.GraphicsDevice, input.Width, input.Height, levels + 1, input.Format);
            var fact = 1;

            scaler.SetInput(input);
            for (var i = 0; i <= levels; ++i)
            {
                using (var target = Texture.New2D(Context.GraphicsDevice, input.Width / fact, input.Height / fact,
                                                  input.Format, TextureFlags.RenderTarget | TextureFlags.ShaderResource))
                {
                    scaler.SetOutput(target);
                    scaler.Draw(Context.RdwContext);
                    Context.RdwContext.CommandList.CopyRegion(
                        target, target.GetSubResourceIndex(0, 0), null,
                        ret, ret.GetSubResourceIndex(0, i), 0, 0);
                }

                fact *= 2;
            }

            return(ret);
        }
Example #4
0
        protected override void DrawCore(RenderDrawContext context)
        {
            var output = PrefilteredRadiance;

            if (output == null || (output.ViewDimension != TextureDimension.Texture2D && output.ViewDimension != TextureDimension.TextureCube) || output.ArraySize != 6)
            {
                throw new NotSupportedException("Only array of 2D textures are currently supported as output");
            }

            if (!output.IsRenderTarget)
            {
                throw new NotSupportedException("Only render targets are supported as output");
            }

            var input = RadianceMap;

            if (input == null || input.ViewDimension != TextureDimension.TextureCube)
            {
                throw new NotSupportedException("Only cubemaps are currently supported as input");
            }

            var roughness = 0f;
            var faceCount = output.ArraySize;
            var levelSize = new Int2(output.Width, output.Height);
            var mipCount  = MipmapGenerationCount == 0 ? output.MipLevels : MipmapGenerationCount;

            for (int mipLevel = 0; mipLevel < mipCount; mipLevel++)
            {
                for (int faceIndex = 0; faceIndex < faceCount; faceIndex++)
                {
                    using (var outputView = output.ToTextureView(ViewType.Single, faceIndex, mipLevel))
                    {
                        var inputLevel = MathUtil.Log2(input.Width / output.Width);
                        if (mipLevel == 0 && DoNotFilterHighestLevel)
                        {
                            if (input.Width >= output.Width && inputLevel < input.MipLevels && input.Format == output.Format)
                            {
                                // Optimization: make a simple copy of the texture when possible
                                var inputSubresource  = inputLevel + faceIndex * input.MipLevels;
                                var outputSubresource = 0 + faceIndex * output.MipLevels;
                                context.CommandList.CopyRegion(input, inputSubresource, null, output, outputSubresource);
                            }
                            else // otherwise rescale the closest mipmap
                            {
                                var inputMipmapLevel = Math.Min(inputLevel, input.MipLevels - 1);
                                using (var inputView = input.ToTextureView(ViewType.Single, faceIndex, inputMipmapLevel))
                                {
                                    scaler.SetInput(inputView);
                                    scaler.SetOutput(outputView);
                                    scaler.Draw(context);
                                }
                            }
                        }
                        else
                        {
                            shader.Parameters.Set(RadiancePrefilteringGGXNoComputeShaderKeys.Face, faceIndex);
                            shader.Parameters.Set(RadiancePrefilteringGGXNoComputeShaderKeys.Roughness, roughness);
                            shader.Parameters.Set(RadiancePrefilteringGGXNoComputeShaderKeys.MipmapCount, input.MipLevels - 1);
                            shader.Parameters.Set(RadiancePrefilteringGGXNoComputeShaderKeys.RadianceMap, input);
                            shader.Parameters.Set(RadiancePrefilteringGGXNoComputeShaderKeys.RadianceMapSize, input.Width);
                            shader.Parameters.Set(RadiancePrefilteringGGXNoComputeParams.NbOfSamplings, SamplingsCount);
                            shader.SetOutput(outputView);
                            shader.Draw(context);
                        }
                    }
                }

                if (mipCount > 1)
                {
                    roughness += 1f / (mipCount - 1);
                    levelSize /= 2;
                }
            }
        }