无法在 Windows 10 Universal App 上使用 SharpDX 绘制图元(但仍然可以清除背景)
Cannot draw primitives with SharpDX on Windows 10 Universal App (but still able to clear the background)
对不起,因为我的英语不好。我正在尝试使用 SharpDX 在 Windows 10 应用程序上编写一个非常简单的 DirectX 11,它在 windows 的中间绘制一个三角形。问题是三角形没有显示,但我仍然可以更改背景颜色(使用 ClearRenderTargetView)。我验证了定期调用渲染函数并且我的三角形是正面(顺时针)。我尝试过的:
- 禁用背面剔除
- 设置静态宽度和高度
- 尝试其他图元(直线、三角带)
- 将顶点着色器输入从 float3 更改为 float4,反之亦然
我发现这个 的症状非常相似,但仍然不起作用!
我已经在 GitHub 上发布了我的代码:https://github.com/minhcly/UWP3DTest
这是我的初始化代码(我认为问题所在):
D3D11.Device2 device;
D3D11.DeviceContext deviceContext;
DXGI.SwapChain2 swapChain;
D3D11.Texture2D backBufferTexture;
D3D11.RenderTargetView backBufferView;
private void InitializeD3D()
{
using (D3D11.Device defaultDevice = new D3D11.Device(D3D.DriverType.Hardware, D3D11.DeviceCreationFlags.Debug))
this.device = defaultDevice.QueryInterface<D3D11.Device2>();
this.deviceContext = this.device.ImmediateContext2;
DXGI.SwapChainDescription1 swapChainDescription = new DXGI.SwapChainDescription1()
{
AlphaMode = DXGI.AlphaMode.Ignore,
BufferCount = 2,
Format = DXGI.Format.R8G8B8A8_UNorm,
Height = (int)(this.swapChainPanel.RenderSize.Height),
Width = (int)(this.swapChainPanel.RenderSize.Width),
SampleDescription = new DXGI.SampleDescription(1, 0),
Scaling = SharpDX.DXGI.Scaling.Stretch,
Stereo = false,
SwapEffect = DXGI.SwapEffect.FlipSequential,
Usage = DXGI.Usage.RenderTargetOutput
};
using (DXGI.Device3 dxgiDevice3 = this.device.QueryInterface<DXGI.Device3>())
using (DXGI.Factory3 dxgiFactory3 = dxgiDevice3.Adapter.GetParent<DXGI.Factory3>())
{
DXGI.SwapChain1 swapChain1 = new DXGI.SwapChain1(dxgiFactory3, this.device, ref swapChainDescription);
this.swapChain = swapChain1.QueryInterface<DXGI.SwapChain2>();
}
using (DXGI.ISwapChainPanelNative nativeObject = ComObject.As<DXGI.ISwapChainPanelNative>(this.swapChainPanel))
nativeObject.SwapChain = this.swapChain;
this.backBufferTexture = this.swapChain.GetBackBuffer<D3D11.Texture2D>(0);
this.backBufferView = new D3D11.RenderTargetView(this.device, this.backBufferTexture);
this.deviceContext.OutputMerger.SetRenderTargets(this.backBufferView);
deviceContext.Rasterizer.State = new D3D11.RasterizerState(device, new D3D11.RasterizerStateDescription()
{
CullMode = D3D11.CullMode.None,
FillMode = D3D11.FillMode.Solid,
IsMultisampleEnabled = true
});
deviceContext.Rasterizer.SetViewport(0, 0, (int)swapChainPanel.Width, (int)swapChainPanel.Height);
CompositionTarget.Rendering += CompositionTarget_Rendering;
Application.Current.Suspending += Current_Suspending;
isDXInitialized = true;
}
InitScene() 函数:
D3D11.Buffer triangleVertBuffer;
D3D11.VertexShader vs;
D3D11.PixelShader ps;
D3D11.InputLayout vertLayout;
RawVector3[] verts;
private void InitScene()
{
D3D11.InputElement[] inputElements = new D3D11.InputElement[]
{
new D3D11.InputElement("POSITION", 0, DXGI.Format.R32G32B32_Float, 0)
};
using (CompilationResult vsResult = ShaderBytecode.CompileFromFile("vs.hlsl", "main", "vs_4_0"))
{
vs = new D3D11.VertexShader(device, vsResult.Bytecode.Data);
vertLayout = new D3D11.InputLayout(device, vsResult.Bytecode, inputElements);
}
using (CompilationResult psResult = ShaderBytecode.CompileFromFile("ps.hlsl", "main", "ps_4_0"))
ps = new D3D11.PixelShader(device, psResult.Bytecode.Data);
deviceContext.VertexShader.Set(vs);
deviceContext.PixelShader.Set(ps);
verts = new RawVector3[] {
new RawVector3( 0.0f, 0.5f, 0.5f ),
new RawVector3( 0.5f, -0.5f, 0.5f ),
new RawVector3( -0.5f, -0.5f, 0.5f )
};
triangleVertBuffer = D3D11.Buffer.Create(device, D3D11.BindFlags.VertexBuffer, verts);
deviceContext.InputAssembler.InputLayout = vertLayout;
deviceContext.InputAssembler.PrimitiveTopology = D3D.PrimitiveTopology.TriangleList;
}
渲染函数:
private void RenderScene()
{
this.deviceContext.ClearRenderTargetView(this.backBufferView, new RawColor4(red, green, blue, 0));
deviceContext.InputAssembler.SetVertexBuffers(0,
new D3D11.VertexBufferBinding(triangleVertBuffer, Utilities.SizeOf<RawVector3>(), 0));
deviceContext.Draw(verts.Length, 0);
this.swapChain.Present(0, DXGI.PresentFlags.None);
}
感谢您的帮助。
我已经解决了问题。我在 Visual Studio 中使用了图形调试器并检测到 OutputMerger 没有 RenderTarget。所以我移动线
this.deviceContext.OutputMerger.SetRenderTargets(this.backBufferView);
到 RenderScene() 函数,它可以工作。但是,我不明白为什么我必须每一帧都重置它。我是 Direct3D 的新手,所以如果有人有答案,请发表评论。谢谢。
P/s:我已经在 GitHub 上为遇到相同问题的任何人提交了工作项目。
对不起,因为我的英语不好。我正在尝试使用 SharpDX 在 Windows 10 应用程序上编写一个非常简单的 DirectX 11,它在 windows 的中间绘制一个三角形。问题是三角形没有显示,但我仍然可以更改背景颜色(使用 ClearRenderTargetView)。我验证了定期调用渲染函数并且我的三角形是正面(顺时针)。我尝试过的:
- 禁用背面剔除
- 设置静态宽度和高度
- 尝试其他图元(直线、三角带)
- 将顶点着色器输入从 float3 更改为 float4,反之亦然
我发现这个
我已经在 GitHub 上发布了我的代码:https://github.com/minhcly/UWP3DTest
这是我的初始化代码(我认为问题所在):
D3D11.Device2 device;
D3D11.DeviceContext deviceContext;
DXGI.SwapChain2 swapChain;
D3D11.Texture2D backBufferTexture;
D3D11.RenderTargetView backBufferView;
private void InitializeD3D()
{
using (D3D11.Device defaultDevice = new D3D11.Device(D3D.DriverType.Hardware, D3D11.DeviceCreationFlags.Debug))
this.device = defaultDevice.QueryInterface<D3D11.Device2>();
this.deviceContext = this.device.ImmediateContext2;
DXGI.SwapChainDescription1 swapChainDescription = new DXGI.SwapChainDescription1()
{
AlphaMode = DXGI.AlphaMode.Ignore,
BufferCount = 2,
Format = DXGI.Format.R8G8B8A8_UNorm,
Height = (int)(this.swapChainPanel.RenderSize.Height),
Width = (int)(this.swapChainPanel.RenderSize.Width),
SampleDescription = new DXGI.SampleDescription(1, 0),
Scaling = SharpDX.DXGI.Scaling.Stretch,
Stereo = false,
SwapEffect = DXGI.SwapEffect.FlipSequential,
Usage = DXGI.Usage.RenderTargetOutput
};
using (DXGI.Device3 dxgiDevice3 = this.device.QueryInterface<DXGI.Device3>())
using (DXGI.Factory3 dxgiFactory3 = dxgiDevice3.Adapter.GetParent<DXGI.Factory3>())
{
DXGI.SwapChain1 swapChain1 = new DXGI.SwapChain1(dxgiFactory3, this.device, ref swapChainDescription);
this.swapChain = swapChain1.QueryInterface<DXGI.SwapChain2>();
}
using (DXGI.ISwapChainPanelNative nativeObject = ComObject.As<DXGI.ISwapChainPanelNative>(this.swapChainPanel))
nativeObject.SwapChain = this.swapChain;
this.backBufferTexture = this.swapChain.GetBackBuffer<D3D11.Texture2D>(0);
this.backBufferView = new D3D11.RenderTargetView(this.device, this.backBufferTexture);
this.deviceContext.OutputMerger.SetRenderTargets(this.backBufferView);
deviceContext.Rasterizer.State = new D3D11.RasterizerState(device, new D3D11.RasterizerStateDescription()
{
CullMode = D3D11.CullMode.None,
FillMode = D3D11.FillMode.Solid,
IsMultisampleEnabled = true
});
deviceContext.Rasterizer.SetViewport(0, 0, (int)swapChainPanel.Width, (int)swapChainPanel.Height);
CompositionTarget.Rendering += CompositionTarget_Rendering;
Application.Current.Suspending += Current_Suspending;
isDXInitialized = true;
}
InitScene() 函数:
D3D11.Buffer triangleVertBuffer;
D3D11.VertexShader vs;
D3D11.PixelShader ps;
D3D11.InputLayout vertLayout;
RawVector3[] verts;
private void InitScene()
{
D3D11.InputElement[] inputElements = new D3D11.InputElement[]
{
new D3D11.InputElement("POSITION", 0, DXGI.Format.R32G32B32_Float, 0)
};
using (CompilationResult vsResult = ShaderBytecode.CompileFromFile("vs.hlsl", "main", "vs_4_0"))
{
vs = new D3D11.VertexShader(device, vsResult.Bytecode.Data);
vertLayout = new D3D11.InputLayout(device, vsResult.Bytecode, inputElements);
}
using (CompilationResult psResult = ShaderBytecode.CompileFromFile("ps.hlsl", "main", "ps_4_0"))
ps = new D3D11.PixelShader(device, psResult.Bytecode.Data);
deviceContext.VertexShader.Set(vs);
deviceContext.PixelShader.Set(ps);
verts = new RawVector3[] {
new RawVector3( 0.0f, 0.5f, 0.5f ),
new RawVector3( 0.5f, -0.5f, 0.5f ),
new RawVector3( -0.5f, -0.5f, 0.5f )
};
triangleVertBuffer = D3D11.Buffer.Create(device, D3D11.BindFlags.VertexBuffer, verts);
deviceContext.InputAssembler.InputLayout = vertLayout;
deviceContext.InputAssembler.PrimitiveTopology = D3D.PrimitiveTopology.TriangleList;
}
渲染函数:
private void RenderScene()
{
this.deviceContext.ClearRenderTargetView(this.backBufferView, new RawColor4(red, green, blue, 0));
deviceContext.InputAssembler.SetVertexBuffers(0,
new D3D11.VertexBufferBinding(triangleVertBuffer, Utilities.SizeOf<RawVector3>(), 0));
deviceContext.Draw(verts.Length, 0);
this.swapChain.Present(0, DXGI.PresentFlags.None);
}
感谢您的帮助。
我已经解决了问题。我在 Visual Studio 中使用了图形调试器并检测到 OutputMerger 没有 RenderTarget。所以我移动线
this.deviceContext.OutputMerger.SetRenderTargets(this.backBufferView);
到 RenderScene() 函数,它可以工作。但是,我不明白为什么我必须每一帧都重置它。我是 Direct3D 的新手,所以如果有人有答案,请发表评论。谢谢。
P/s:我已经在 GitHub 上为遇到相同问题的任何人提交了工作项目。