DirectX newb-在广告牌上具有深度的Multisampled Texture2D [英] DirectX newb - Multisampled Texture2D with depth on a Billboard

查看:96
本文介绍了DirectX newb-在广告牌上具有深度的Multisampled Texture2D的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这里是我的要求:使用DirectX11(通过SlimDX)时,我必须下载一系列顶点,然后使用它们来创建县边界地图的Texture2D。然后,我需要对州边界做同样的事情,并将其绘制在县边界上。然后,我需要获取该纹理并从中创建2个不同的纹理,每个纹理都包含唯一的雷达数据。然后,我想获取这些纹理并显示它们,以便用户可以并排查看例如基本反射率和基本速度。用户应该能够放大和缩小地图的特定区域。

Here's my requirement: Using DirectX11 (via SlimDX) I have to download a series of verteces and use them to create a Texture2D of a map of county borders. Then I need to do the same thing with state borders, and draw them over the county borders. Then, I need to take that texture and create 2 different textures from it, each containing unique radar data. Then I want to take those textures and display them so that the user can look at, for example, base reflectivity and base velocity side by side. The user should be able to zoom in and out of particular areas of the map.

这就是我要进行的工作:我创建的Texture2D没有多重采样或深度在以2个独立视图显示的广告牌上。但这看起来像是块状的,如果放大得太远,某些边界会开始消失。

Here's what I've got working: I'm creating my Texture2D without multisampling or depth on a billboard which is displaying in 2 separate views. But it looks blocky, and if you zoom too far out, some of the borders start to disappear.

这是我的问题:

1)我无法终生获得任何多重采样质量。我使用的是ATI Radeon HD 5750,所以我知道它一定能够做到,但是我尝试过的任何格式都不支持大于0的质量。

1) I can't for the life of me get any multisampling quality. I'm using an ATI Radeon HD 5750, so I know it must be able to do it, but no formats I've tried support a quality greater than 0.

2)我不确定是否需要使用深度模具,因为我将所有这些纹理相互叠加绘制。我希望不会,因为当我尝试时,ShaderResourceView会说: Puny Human!您不能在ShaderResourceView中使用深度模具格式!哇!!! (我正在点缀)

2) I'm uncertain whether I need to use a depth stencil since I'm drawing all these textures on top of each other. I hope not because when I try, the ShaderResourceView says, "Puny Human! You cannot use a depth stencil format in a ShaderResourceView! Bwa ha ha!" (I'm embellishing)

我敢打赌,如果我将原语直接引入世界空间,那么其中许多问题都将得到解决。我这样做渲染时间太长,因为要渲染的行太多。

I'm willing to bet that a lot of these issues would be solved if I just drew the primitives directly into the world space, but when I do that rendering takes way too long because there are so many lines to render. Is there perhaps a way I can cut down on the time it takes?

这是我上一个工作版本的代码:

And here's the code of my last working version:

using SlimDX;
using SlimDX.D3DCompiler;
using SlimDX.Direct3D11;
using SlimDX.DXGI;
using SlimDX.Windows;
using System;
using System.Windows.Forms;
using System.Collections.Generic;

using Device = SlimDX.Direct3D11.Device;
using Buffer = SlimDX.Direct3D11.Buffer;
using Resource = SlimDX.Direct3D11.Resource;
using Format = SlimDX.DXGI.Format;
using MapFlags = SlimDX.Direct3D11.MapFlags;



namespace Radar
{
abstract public class Renderer
{
    protected static Device mDevice = null;
    protected SwapChain mSwapChain = null;
    protected RenderTargetView RenderTarget { get; set; }

    public static Device Device { get { return mDevice; } protected set { mDevice = value; } }
    public static DeviceContext Context { get { return Device.ImmediateContext; } }
    protected SwapChain SwapChain { get { return mSwapChain; } set { mSwapChain = value; } }

    public Texture2D Texture { get; protected set; }
    protected int RenderTargetIndex { get; set; }
    protected VertexShader VertexShader { get; set; }
    protected PixelShader PixelShader { get; set; }
    protected Buffer VertexBuffer { get; set; }
    protected Buffer MatrixBuffer { get; set; }
    protected InputLayout Layout { get; set; }
    protected ShaderSignature InputSignature { get; set; }
    protected SamplerState SamplerState { get; set; }

    protected Color4 mClearColor = new Color4(0.117f, 0.117f, 0.117f);
    protected Color4 ClearColor { get { return mClearColor; } }



    protected void CreateDevice(IntPtr inHandle)
    {
        if (Device == null)
            Device = new Device(DriverType.Hardware, DeviceCreationFlags.Debug);

        SwapChainDescription chainDescription = new SwapChainDescription()
        {
            BufferCount = 2,
            Usage = Usage.RenderTargetOutput,
            OutputHandle = inHandle,
            IsWindowed = true,
            ModeDescription = new ModeDescription(0, 0, new Rational(60, 1), Format.R8G8B8A8_UNorm),
            SampleDescription = new SampleDescription(8, 0),
            Flags = SwapChainFlags.AllowModeSwitch,
            SwapEffect = SwapEffect.Discard
        };

        SwapChain = new SwapChain(Device.Factory, Device, chainDescription);
    }



    protected void SetupViewport(int inWidth, int inHeight)
    {
        Viewport viewport = new Viewport(0.0f, 0.0f, inWidth, inHeight);
        Context.OutputMerger.SetTargets(RenderTarget);
        Context.Rasterizer.SetViewports(viewport);
    }



    public void Clear()
    {
        Context.ClearRenderTargetView(RenderTarget, ClearColor);
    }



    public void Present()
    {
        SwapChain.Present(0, PresentFlags.None);
    }



    // I do this to ensure the texture is correct
    public void Save()
    {
        Texture2D.ToFile(Context, Texture, ImageFileFormat.Png, "test.png");
    }



    public virtual void Dispose()
    {
        Texture.Dispose();
        SamplerState.Dispose();
        VertexBuffer.Dispose();
        Layout.Dispose();
        InputSignature.Dispose();
        VertexShader.Dispose();
        PixelShader.Dispose();
        RenderTarget.Dispose();
        SwapChain.Dispose();
        Device.Dispose();
    }



    public class RenderTargetParameters
    {
        public int Width { get; set; }
        public int Height { get; set; }
        public IntPtr Handle { get; set; }


        public RenderTargetParameters()
        {
            Width = 0;
            Height = 0;
            Handle = new IntPtr(0);
        }
    }



    public abstract void Render(int inWidth, int inHeight, int inCount = -1);
    public abstract void Prepare(string inShaderName = null);
}



public class TextureRenderer : Renderer
{
    public TextureRenderer(RenderTargetParameters inParms)
    {
        CreateDevice(inParms.Handle);

        Texture2DDescription description = new Texture2DDescription()
        {
            Width = inParms.Width,
            Height = inParms.Height,
            MipLevels = 1,
            ArraySize = 1,
            Format = Format.R8G8B8A8_UNorm,
            SampleDescription = new SampleDescription(8, 0),
            Usage = ResourceUsage.Default,
            BindFlags = BindFlags.RenderTarget | BindFlags.ShaderResource,
            CpuAccessFlags = CpuAccessFlags.None,
            OptionFlags = ResourceOptionFlags.None
        };

        Texture = new Texture2D(Device, description);

        RenderTarget = new RenderTargetView(Device, Texture);

        SetupViewport(inParms.Width, inParms.Height);

        using (ShaderBytecode bytecode = ShaderBytecode.CompileFromFile("ShaderFX.fx", "VShader", "vs_5_0", ShaderFlags.Debug, EffectFlags.None))
        {
            InputSignature = ShaderSignature.GetInputSignature(bytecode);
            VertexShader = new VertexShader(Device, bytecode);
        }

        // load and compile the pixel shader

        InputElement[] elements = new[] { new InputElement("POSITION", 0, Format.R32G32B32_Float, 0) };

        Layout = new InputLayout(Device, InputSignature, elements);

        Context.InputAssembler.InputLayout = Layout;
        Context.InputAssembler.PrimitiveTopology = PrimitiveTopology.LineStrip;

        Context.VertexShader.Set(VertexShader);
    }



    public override void Prepare(string inShaderName)
    {
        using (ShaderBytecode bytecode = ShaderBytecode.CompileFromFile("ShaderFX.fx", inShaderName, "ps_4_0", ShaderFlags.Debug, EffectFlags.None))
            PixelShader = new PixelShader(Device, bytecode);

        Context.PixelShader.Set(PixelShader);
    }



    public void SetVertices(DataStream inShape)
    {
        VertexBuffer = new Buffer(Device, inShape, (int)inShape.Length, ResourceUsage.Default, BindFlags.VertexBuffer, CpuAccessFlags.None, ResourceOptionFlags.None, 0);

        Context.InputAssembler.SetVertexBuffers(0, new VertexBufferBinding(VertexBuffer, 12, 0));
    }



    public override void Render(int inWidth, int inHeight, int inCount = -1)
    {
        Context.Draw(inCount, 0);
    }
}



public class RuntimeRenderer : Renderer
{
    private ShaderResourceView ResourceView { get; set; }



    public RuntimeRenderer(RenderTargetParameters inParms, ref TextureRenderer inTextureRenderer)
    {
        CreateDevice(inParms.Handle);

        Texture = inTextureRenderer.Texture;

        using (Resource resource = Resource.FromSwapChain<Texture2D>(SwapChain, 0))
            RenderTarget = new RenderTargetView(Device, resource);

        //using (var factory = SwapChain.GetParent<Factory>())
            //factory.SetWindowAssociation(inParms.Handle, WindowAssociationFlags.IgnoreAltEnter);
    }



    public void Resize()
    {
        RenderTarget.Dispose();

        SwapChain.ResizeBuffers(2, 0, 0, Format.R8G8B8A8_UNorm, SwapChainFlags.AllowModeSwitch);
        using (SlimDX.Direct3D11.Resource resource = Resource.FromSwapChain<Texture2D>(SwapChain, 0))
            RenderTarget = new RenderTargetView(Device, resource);
    }



    public override void Prepare(string inShaderName)
    {
        using (ShaderBytecode bytecode = ShaderBytecode.CompileFromFile("ShaderFX.fx", "TextureVertexShader", "vs_4_0", ShaderFlags.EnableStrictness, EffectFlags.None))
        {
            InputSignature = ShaderSignature.GetInputSignature(bytecode);
            VertexShader = new VertexShader(Device, bytecode);
        }

        using (ShaderBytecode bytecode = ShaderBytecode.CompileFromFile("ShaderFX.fx", "TexturePixelShader", "ps_4_0", ShaderFlags.EnableStrictness, EffectFlags.None))
            PixelShader = new PixelShader(Device, bytecode);

        InputElement[] elements = new InputElement[2];

        elements[0].SemanticName = "POSITION";
        elements[0].SemanticIndex = 0;
        elements[0].Format = Format.R32G32B32_Float;
        elements[0].Slot = 0;
        elements[0].AlignedByteOffset = 0;
        elements[0].Classification = InputClassification.PerVertexData;
        elements[0].InstanceDataStepRate = 0;

        elements[1].SemanticName = "TEXCOORD";
        elements[1].SemanticIndex = 0;
        elements[1].Format = Format.R32G32_Float;
        elements[1].Slot = 0;
        elements[1].AlignedByteOffset = InputElement.AppendAligned;
        elements[1].Classification = InputClassification.PerVertexData;
        elements[1].InstanceDataStepRate = 0;

        Layout = new InputLayout(Device, InputSignature, elements);

        BufferDescription matrixDescription = new BufferDescription()
        {
            Usage = ResourceUsage.Dynamic,
            SizeInBytes = sizeof(float) * 16 * 4,
            BindFlags = BindFlags.ConstantBuffer,
            CpuAccessFlags = CpuAccessFlags.Write,
            OptionFlags = ResourceOptionFlags.None,
            StructureByteStride = 0
        };

        MatrixBuffer = new Buffer(Device, matrixDescription);

        ShaderResourceViewDescription resourceViewDescription = new ShaderResourceViewDescription()
        {
            Format = Texture.Description.Format,
            Dimension = ShaderResourceViewDimension.Texture2DMultisampled,
            MipLevels = Texture.Description.MipLevels,
            MostDetailedMip = 0,
        };

        //Texture2D.ToFile(Context, Texture, ImageFileFormat.Png, "test.png");

        ResourceView = new ShaderResourceView(Device, Texture, resourceViewDescription);

        SamplerDescription samplerDescription = new SamplerDescription()
        {
            Filter = Filter.MinMagMipLinear,
            AddressU = TextureAddressMode.Wrap,
            AddressV = TextureAddressMode.Wrap,
            AddressW = TextureAddressMode.Wrap,
            MipLodBias = 0.0f,
            MaximumAnisotropy = 1,
            ComparisonFunction = Comparison.Always,
            BorderColor = ClearColor,
            MinimumLod = 0,
            MaximumLod = 99999
        };

        SamplerState = SamplerState.FromDescription(Device, samplerDescription);
    }



    public override void Render(int inWidth, int inHeight, int inCount = -1)
    {
        Clear();
        Billboard.SetVerteces(Device, Texture.Description.Width, Texture.Description.Height, inWidth, inHeight);

        SetupViewport(inWidth, inHeight);

        Context.InputAssembler.SetVertexBuffers(0, new VertexBufferBinding(Billboard.Verteces, 20, 0));
        Context.InputAssembler.SetIndexBuffer(Billboard.Indeces, Format.R32_UInt, 0);
        Context.InputAssembler.PrimitiveTopology = PrimitiveTopology.TriangleStrip;

        Context.InputAssembler.InputLayout = Layout;
        Context.VertexShader.Set(VertexShader);
        Context.PixelShader.Set(PixelShader);
        Context.PixelShader.SetSampler(SamplerState, 0);

        Context.VertexShader.SetConstantBuffer(MatrixBuffer, 0);
        Context.PixelShader.SetConstantBuffer(MatrixBuffer, 0);
        Context.PixelShader.SetShaderResource(ResourceView, 0);

        Context.DrawIndexed(4, 0, 0);
        Present();
    }
}
}

图片1看起来像就像我将纹理保存到文件中一样(我将其按比例缩小以适合我的文章)。

Image 1 is what it looks like if I save the texture to a file (I scaled this down a LOT so it would fit in my post).

图片2是运行时的外观在大约中等距离处观看(不理想,但还不错)

Image 2 is what it looks like in runtime when viewed at about a medium distance (not ideal, but not so bad)

图3看起来像是放大到一个县(Eww!块状且模糊!)

Image 3 is what it looks like zoomed in to a county (Eww! Blocky and fuzzy!)

图像4看起来像是缩小了(所有边框都在哪里?)

Image 4 is what it looks like zoomed out (where did all the borders go?)




推荐答案

关于多重采样,通常您可以将质量保持为0,质量设置通常会有所不同ixels(又称样本)模式。一般情况下,0会很好。

About multisampling, generally you can keep quality to 0, quality setting generally are different "subpixels" (aka : samples) patterns. 0 generally does fine.

如果使用多重采样渲染到纹理,则还需要解析资源,将多个采样纹理绑定为Texture2DMS(而不是Texture2D),着色器。

In case you render to texture with multisampling, you also need to resolve your resource, multi sampled textures are bound as Texture2DMS (instead of Texture2D) in shaders.

要这样做,您需要创建第二个纹理(具有相同的格式/大小),但只有一个样本。

To do so, you need to create a second texture (with same format/size), but with only one sample.

然后,完成多采样纹理的渲染后,需要进行以下调用:

Then once you're done rendering your multisampled texture, you need to do the following call:

deviceContext.ResolveSubresource(multisampledtexture, 0, nonmultisampledtexture,
                0, format);

然后可以在后续遍历中使用非多采样纹理的ShaderView。

You can then use the ShaderView of the non multisampled texture in subsequent passes.

据我所见,您不必使用深度模具,只需确保以正确的顺序绘制元素即可。

From what I see you should not need to use a depth stencil, just make sure you draw your elements in the correct order.

关于格式,这是正常现象,因为深度有点特殊,您需要为资源/视图传递不同的格式。如果要使用D24_UNorm_S8_UInt(我会说最常用的格式),则需要设置以下内容:

About formats, this is normal since depth is a bit "special", you need to pass different formats for resource/views. If you want to use D24_UNorm_S8_UInt (most common format i'd say), you need to setup the following:


  • 在纹理说明中,格式必须为Format.R24_UNorm_X8_Typeless

  • 在深度模具视图描述中为Format.D24_UNorm_S8_UInt

  • 在着色器视图描述中为Format.R24_UNorm_X8_Typeless

这将允许您构建一个可以读取的深度模板(如果不需要读取深度缓冲区,只需忽略着色器

That will allow you to build a depth stencil that you can read (if you don't need to read your depth buffer, just ignore shader view and use depth format directly).

此外,您还可以通过使用mipmaps来提高质量(这很有帮助,特别是在缩小时)。

Also you can increase quality by using mipmaps (which would help a lot, specially when zooming out).

为此,请在纹理描述中设置以下选项(确保该纹理未进行多次采样)

To do so, in your texture description, set the following options (make sure that this texture is not multisampled)

texBufferDesc.OptionFlags |= ResourceOptionFlags.GenerateMipMaps;
texBufferDesc.MipLevels = 0; //0 means "all"

一旦渲染完成,请致电:

once you're done with your rendering, call:

context.GenerateMips

使用刚渲染的纹理的着色器资源视图。

using the shader resource view of the texture that just got rendered.

关于直接在其后面绘制线条是绝对可能的,并且一定会为您提供最佳质量。

About drawing the lines directly behind that's definitely possible, and for certain will give you the best quality.

不知道您渲染了多少行,但看起来不太像现代的卡就很难解决。而且,进行一些剔除可以轻松地丢弃掉屏幕外的线条,这样它们就不会被绘制。

Not sure how many lines you render, but it doesn't look like something a reasonably modern card would struggle with. And a bit of culling can easily help discard lines that are out of the screen so they don't get drawn.

您还可以做一些混合(使用纹理)缩小时,渲染时渲染线的子集),也不太难设置。

You could also do some "hybrid" (use texture when zoomed out, render a subset of the lines when zoomed in), that's not too hard to setup either.

这篇关于DirectX newb-在广告牌上具有深度的Multisampled Texture2D的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆