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)); } } }
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); } }
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); }
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; } } }