SharpDX 2.5 в DirectX11 в WPF

Я пытаюсь реализовать DirectX 11 с помощью SharpDX 2.5 в WPF. К сожалению http://directx4wpf.codeplex.com/ и http://sharpdxwpf.codeplex.com/ не работают правильно с SharpDX 2.5. Я также не смог перенести образец WPFHost DX10 в DX11, и полный пакет кода этого примера не работает: http://www.indiedev.de/wiki/DirectX_in_WPF_integrieren

Может кто-нибудь предложить другой способ реализации?

Ответ 1

SharpDX поддерживает WPF через SharpDXElement.

Взгляните в Samples репозиторий в Toolkit.sln - все проекты, у которых WPF в их имени используется SharpDXElement как поверхность рендеринга:

  • MiniCube.WPF - демонстрирует базовую интеграцию SharpDX-WPF;
  • MiniCube.SwitchContext.WPF - демонстрирует базовый сценарий, когда время жизни экземпляра игры отличается от времени жизни SharpDXElement (другими словами - при необходимости переключения воспроизведения игры на другую поверхность).
  • MiniCube.SwitchContext.WPF.MVVM - то же, что и выше, но больше "MVVM-way".

Обновление: SharpDX.Toolkit устарел, и он больше не поддерживается. Он перемещается в отдельный репозиторий. Образцы Toolkit были удалены, однако я изменил ссылку на набор изменений, где они все еще присутствуют.

Ответ 2

Вы можете использовать http://sharpdxwpf.codeplex.com/.

Чтобы правильно работать с SharpDX 2.5.0, вам нужно сделать несколько изменений.

1) В проекте Sharp.WPF в классе DXUtils.cs в методе

Direct3D11.Buffer CreateBuffer<T>(this Direct3D11.Device device, T[] range)

добавить эту строку

stream.Position = 0;

сразу после

stream.WriteRange(range);

Таким образом, фиксированный метод выглядит следующим образом:

public static Direct3D11.Buffer CreateBuffer<T>(this Direct3D11.Device device, T[] range)
        where T : struct
    {
        int sizeInBytes = Marshal.SizeOf(typeof(T));
        using (var stream = new DataStream(range.Length * sizeInBytes, true, true))
        {
            stream.WriteRange(range);
            stream.Position = 0; // fix
            return new Direct3D11.Buffer(device, stream, new Direct3D11.BufferDescription
            {
                BindFlags = Direct3D11.BindFlags.VertexBuffer,
                SizeInBytes = (int)stream.Length,
                CpuAccessFlags = Direct3D11.CpuAccessFlags.None,
                OptionFlags = Direct3D11.ResourceOptionFlags.None,
                StructureByteStride = 0,
                Usage = Direct3D11.ResourceUsage.Default,
            });
        }
    }

2) И в классе D3D11 в файле D3D11.cs переименуйте это

m_device.ImmediateContext.Rasterizer.SetViewports(new Viewport(0, 0, w, h, 0.0f, 1.0f));

в этот

  m_device.ImmediateContext.Rasterizer.SetViewport(new Viewport(0, 0, w, h, 0.0f, 1.0f));

то есть. SetViewports в SetViewport.

И теперь он должен работать.