Sharpdx动态纹理更新错误

时间:2018-04-19 07:28:43

标签: c# wpf 3d direct3d sharpdx

这是使用SharpDX 4.0的C#WPF。

我正在尝试使用从库生成的颜色缓冲区更新每个渲染循环上的动态纹理。我发现结果纹理与预期位图不匹配的问题。纹理看起来比预期的要宽,或者格式比预期的要大。

var surfaceWidth = 200; var surfaceHeight = 200; 
var pixelBytes = surfaceWidth * surfaceHeight * 4;

//Set up the color buffer and byte array to stream to the texture
_colorBuffer = new int[surfaceWidth * surfaceHeight]; 
_textureStreamBytes = new byte[pixelBytes]; //16000 length

//Create the texture to update
_scanTexture = new Texture2D(Device, new Texture2DDescription()
        {
            Format = Format.B8G8R8A8_UNorm,
            ArraySize = 1,
            MipLevels = 1,
            Width = SurfaceWidth,
            Height = SurfaceHeight,
            SampleDescription = new SampleDescription(1, 0),
            Usage = ResourceUsage.Dynamic,
            BindFlags = BindFlags.ShaderResource,
            CpuAccessFlags = CpuAccessFlags.Write,
            OptionFlags = ResourceOptionFlags.None,
        });

_scanResourceView= new ShaderResourceView(Device, _scanTexture);
context.PixelShader.SetShaderResource(0, _scanResourceView);

在渲染中,我填充颜色缓冲区并写入纹理。

protected void Render()
{
    Device.ImmediateContext.ClearRenderTargetView(
        RenderTargetView, new SharpDX.Mathematics.Interop.RawColor4(0.8f,0.8f,0,1));
    Library.GenerateColorBuffer(ref _colorBuffer);
    System.Buffer.BlockCopy(_colorBuffer, 0, depthPixels, 0, depthPixels.Length);

    _parent.DrawBitmap(ref _colorBuffer);

    DataBox databox = context.MapSubresource(_scanTexture, 0, MapMode.WriteDiscard, SharpDX.Direct3D11.MapFlags.None, out DataStream stream);

    if (!databox.IsEmpty)
        stream.Write(_textureStreamBytes, 0, _textureStreamBytes.Length);
    context.UnmapSubresource(_scanTexture, 0);
    context.Draw(4, 0);
}

在上述情况发生之前创建和设置采样器:

var sampler = new SamplerState(_device, new SamplerStateDescription()
        {
            Filter = SharpDX.Direct3D11.Filter.MinMagMipLinear,
            AddressU = TextureAddressMode.Wrap,
            AddressV = TextureAddressMode.Wrap,
            AddressW = TextureAddressMode.Wrap,
            BorderColor = SharpDX.Color.Blue,
            ComparisonFunction = Comparison.Never,
            MaximumAnisotropy = 1,
            MipLodBias = 0,
            MinimumLod = 0,
            MaximumLod = 0,
        });
context = _device.ImmediateContext;
context.InputAssembler.PrimitiveTopology = PrimitiveTopology.TriangleStrip;
context.VertexShader.Set(vertexShader);
context.Rasterizer.SetViewport(new Viewport(0, 0, SurfaceWidth, SurfaceHeight, 0.0f, 1.0f));
context.PixelShader.Set(pixelShader);
context.PixelShader.SetSampler(0, sampler);
context.OutputMerger.SetTargets(depthView, _renderTargetView);

着色器(使用没有顶点的全屏三角形):

SamplerState pictureSampler;
Texture2D picture;

struct PS_IN
{
    float4 pos : SV_POSITION;
    float2 tex : TEXCOORD;
};
PS_IN VS(uint vI : SV_VERTEXID)
{
    float2 texcoord = float2(vI & 1,vI >> 1); //you can use these for texture coordinates later
    PS_IN output = (PS_IN)0;
    output.pos = float4((texcoord.x - 0.5f) * 2, -(texcoord.y - 0.5f) * 2, 0, 1);
    output.tex = texcoord;
    return output;
}

float4 PS(PS_IN input) : SV_Target
{
    return picture.Sample(pictureSampler, input.tex);
}

我所看到的是:

_colorBuffer长度40000(200宽* 200高)

_textureStreamBytes长度为160000(200 * 200 * 4bytes)

来自数据库的流长度= 179200 19200字节/ 4800像素的差异。 这转换为24行200像素宽度。换句话说,纹理比预期宽24个像素。但调试显示宽度/高度为200。

Image showing the issue. Left is rendered view, right is bitmap

有谁知道我在这里做错了什么?或者应该/可以以不同方式完成的事情?

谢谢。

P.S。我通过使用类似的过程在OpenGL中正常工作,但需要让它适用于directx:

gl.TexSubImage2D(OpenGL.GL_TEXTURE_2D, 0, 0, 0, (int)width, (int)height, OpenGL.GL_RGBA, OpenGL.GL_UNSIGNED_BYTE, colorBuffer);

1 个答案:

答案 0 :(得分:0)

从实验开始,宽度和高度都需要32的倍数。例如100 * 128即使32的倍数也会引起问题。相反,我正在使用:

var newHeight = (int)(initialHeight / 32) * 32;
var newWidth = (int)(initialWidth / 32) * 32;

我不确定root问题是我自己的错误还是sharpDX问题或DirectX问题。我看到解决这个问题的另一种方法是在像素数组中添加填充,以说明每行末尾的长度差异。