首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >试图在Windows.Forms.Panels上呈现纹理

试图在Windows.Forms.Panels上呈现纹理
EN

Stack Overflow用户
提问于 2014-06-13 18:45:56
回答 1查看 1.1K关注 0票数 1

使用SlimDX.Windows.RenderForm,我想动态创建一个美国地图的纹理,将该纹理复制到其他两个纹理中,然后在每个纹理上绘制唯一的雷达数据。然后,我将把这两个纹理传递给每个被绘制在自己的Windows.Forms.Panel上。这样,用户将能够,例如,查看基础反射率和基础速度并排在两个面板。现在,我已经成功地在纹理上生成了我的美国地图。但是当我试图把它渲染到面板上时,我会变黑(顺便说一句,我清晰的颜色是柔和的灰色,而不是黑色)。

编辑:经过一些操作之后,我修改了我的代码,以获取TextureRenderer正在使用的纹理,将其转换为流,并在RuntimeRenderer设备下创建一个新的纹理。现在我有一个柔软的灰色广场,里面有一个黄色的方块(它与-0.9,-0.9兼容.0.9,0.9我用于顶点)。我知道新的纹理是正确的,但正方形仍然是黄色的。

这是我的密码:

代码语言:javascript
复制
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 Device mDevice = null;
    protected SwapChain mSwapChain = null;
    protected RenderTargetView RenderTarget { get; set; }

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

    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 void CreateDevice(IntPtr inHandle)
    {
        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(1, 0),
            Flags = SwapChainFlags.AllowModeSwitch,
            SwapEffect = SwapEffect.Discard
        };

        Device.CreateWithSwapChain(DriverType.Hardware, DeviceCreationFlags.Debug, chainDescription, out mDevice, out mSwapChain);
    }



    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, new Color4(0.117f, 0.117f, 0.117f));
    }



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



    public virtual void 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);
        }
    }



    // the inCount parameter is used in the TextureRenderer, but not in the code I've given
    public abstract void Render(int inCount = -1);
    public abstract void Prepare(string inShaderName = null);

}



// I use this to render the texture. This is working fine
public class TextureRenderer : Renderer
{
    .
    .
    .
}



public class RuntimeRenderer : Renderer
{
    public TextureRenderer TextureRenderer { get; protected set; }



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

        TextureRenderer = inTextureRenderer;

        // I save to a file to make sure the texture is what it should be (and it is)
        TextureRenderer.Save();

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

        SetupViewport(inParms.Width, inParms.Height);

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



    public override void Prepare(string inShaderName)
    {
        DataStream data = new DataStream(12 * 4, true, true);
        data.Write(new Vector3(-0.9f, -0.9f, 0.0f));
        data.Write(new Vector3(-0.9f, 0.9f, 0.0f));
        data.Write(new Vector3(0.9f, -0.9f, 0.0f));
        data.Write(new Vector3(0.9f, 0.9f, 0.0f));
        data.Position = 0;

        DataStream indices = new DataStream(sizeof(int) * 4, true, true);
        indices.Write(0);
        indices.Write(1);
        indices.Write(2);
        indices.Write(3);
        indices.Position = 0;

        VertexBuffer = new Buffer(Device, data, (int)data.Length, ResourceUsage.Default, BindFlags.VertexBuffer, CpuAccessFlags.None, ResourceOptionFlags.None, 0);
        Buffer indexBuffer = new Buffer(Device, indices, (int)indices.Length, ResourceUsage.Default, BindFlags.IndexBuffer, CpuAccessFlags.None, ResourceOptionFlags.None, 0);

        Context.InputAssembler.SetVertexBuffers(0, new VertexBufferBinding(VertexBuffer, 12, 0));
        Context.InputAssembler.SetIndexBuffer(indexBuffer, Format.R32_UInt, 0);
        Context.InputAssembler.PrimitiveTopology = PrimitiveTopology.TriangleStrip;

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

        using (ShaderBytecode bytecode = ShaderBytecode.CompileFromFile("ShaderFX.fx", "SimplePixelShader", "ps_5_0", ShaderFlags.Debug, EffectFlags.None))
            PixelShader = new PixelShader(Device, bytecode);

        InputElement[] inputEl = new InputElement[2];
        inputEl[0].SemanticName = "POSITION";
        inputEl[0].SemanticIndex = 0;
        inputEl[0].Format = Format.R32G32B32_Float;
        inputEl[0].Slot = 0;
        inputEl[0].AlignedByteOffset = 0;
        inputEl[0].Classification = InputClassification.PerVertexData;
        inputEl[0].InstanceDataStepRate = 0;

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

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

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

        MatrixBuffer = new Buffer(Device, matrixDescription);

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

        ShaderResourceView resourceView = new ShaderResourceView(Device, TextureRenderer.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 = new Color4(0, 0, 0, 0),
            MinimumLod = 0,
            MaximumLod = 99999
        };

        SamplerState = SamplerState.FromDescription(Device, samplerDescription);

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

        Vector3 position = new Vector3(0.0f, 0.0f, 10.0f);
        Vector3 target = new Vector3(0.0f, 0.0f, 0.0f);
        Matrix view = Matrix.LookAtLH(position, target, Vector3.UnitY);
        Matrix projection = Matrix.PerspectiveFovLH((float)(Math.PI / 4.0), 1.0f, 0.0f, 100.0f);
        Matrix world = Matrix.Identity;

        DataBox dataBox = Context.MapSubresource(MatrixBuffer, MapMode.WriteDiscard, MapFlags.None);
        dataBox.Data.Write(world);
        dataBox.Data.Write(view);
        dataBox.Data.Write(projection);

        Context.UnmapSubresource(MatrixBuffer, 0);

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



    public override void Render(int inCount = -1)
    {
        Context.DrawIndexed(4, 0, 0);
    }
}
}

这是我的着色文件(ShaderFX.fx):

代码语言:javascript
复制
float4 VShader(float4 position : POSITION) : SV_POSITION
{
return position;
}



float4 PShader_Counties(float4 position : SV_POSITION) : SV_Target
{
return float4(0.5f, 0.5f, 0.5f, 1.0f);
}



float4 PShader_States(float4 position : SV_POSITION) : SV_Target
{
return float4(0.883f, 0.883f, 0.883f, 1.0f);
}



struct VertexShaderInput
{
float2 pos : POSITION;
};



struct PixelShaderInput
{
float4 pos : SV_POSITION;
};



PixelShaderInput SimpleVertexShader(VertexShaderInput input)
{
PixelShaderInput vertexShaderOutput;

vertexShaderOutput.pos = float4(input.pos, 0.5f, 1.0f);

return vertexShaderOutput;
}



float4 SimplePixelShader(PixelShaderInput input) : SV_TARGET
{
return float4(1.0f, 1.0f, 0.0f, 1.0f);
}
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2014-06-14 10:47:31

这里有很多东西。

首先,每个渲染器创建一个设备,这是不必要的,您可以在同一设备上呈现所有内容。

要创建设备,请执行以下操作:

代码语言:javascript
复制
Device device = new Device(DriverType.Hardware,DeviceCreationFlags.Debug);

然后您可以使用相同的设备创建多个交换链(每个面板一个)。

代码语言:javascript
复制
SwapChain swapchain = new SwapChain(device.Factory, device, chainDescription);

第二个问题,您的四边形缺少纹理坐标,所以您将无法显示纹理使用它。请注意,您当然只需要每个设备一个四位数,您不需要一个每个渲染器。

代码语言:javascript
复制
DataStream data = new DataStream(20 * 4, true, true);
data.Write(new Vector3(-0.9f, -0.9f, 0.0f));
data.Write(new Vector2(0.0f,1.0f));

data.Write(new Vector3(-0.9f, 0.9f, 0.0f));
data.Write(new Vector2(0.0f,0.0f));

data.Write(new Vector3(0.9f, -0.9f, 0.0f));
data.Write(new Vector2(1.0f,1.0f));

data.Write(new Vector3(0.9f, 0.9f, 0.0f));
data.Write(new Vector2(1.0f,0.0f));
data.Position = 0;

您的输入布局已经考虑到纹理坐标,所以您不需要修改它。

接下来,在顶点着色器中不使用任何投影矩阵,所以除非您计划这样做,否则可以忽略该代码。

最后,使用单个设备,确保设备上下文调用在呈现函数中,例如:

代码语言:javascript
复制
public override void Render(int inCount = -1)
{
    Context.OutputMerger.SetTargets(RenderTarget);

    Context.InputAssembler.SetVertexBuffers(0, new VertexBufferBinding(VertexBuffer, 12, 0));
    Context.InputAssembler.SetIndexBuffer(indexBuffer, 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.SetShaderResource(resourceView, 0);

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

最后,您当然需要在着色器中传递纹理坐标,以便正确地对纹理进行采样:

代码语言:javascript
复制
struct vsInput
{
float4 position: POSITION;
float2 texCoord: TEXCOORD0;
};

struct psInput
{
    float4 posScreen : SV_POSITION;
    float2 texCoord : TEXCOORD0;
};

Texture2D texture : register(t0);
SamplerState linearSampler : register(s0);

psInput VS(vsInput input)
{
    psInput output;
    output.posScreen = input.position;
    output.texCoord = input.texCoord;
    return output;
}

float4 PS(psInput input): SV_Target
{
    return texture.Sample(linearSampler, input.texCoord);
}
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/24212019

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档