如何同步Direct3D 11覆盖与WPF Viewport3D

本文关键字:覆盖 WPF Viewport3D Direct3D 何同步 同步 | 更新日期: 2023-09-27 18:04:49

我正在开发一个显示3D场景的WPF应用程序。虽然我使用Viewport3D控件在该场景中显示2D WPF控件,但我在透明覆盖窗口中使用原生Direct3D 11来显示复杂的动画3D几何形状。

唯一的问题是,目前可能会有明显的延迟,因为Direct3D覆盖窗口没有与WPF Viewport3D同步。它只在相机移动时才可见,因为Viewport3D渲染必须像Direct3D渲染一样更新。理想情况下,Direct3D缓冲区应该在WPF缓冲区之后立即交换。

我的问题:是否有任何方法在Viewport3D呈现其内容后执行代码?或者至少接近那个时刻?不必是一个干净的解决方案-我也可以生活在一个肮脏的本地hack…

我设法创建了一个方法,该方法从(内部)Viewport3DVisual类的RenderContent调用,但这比实际呈现的屏幕更频繁地执行,并且可能不在渲染线程上。

如何同步Direct3D 11覆盖与WPF Viewport3D

好的,我自己找到了解决办法。可以使用反射为内部MediaContext类的内部RenderComplete事件添加事件处理程序:

Assembly oAssemblyPresentationCore = typeof( Visual ).Assembly;
Type oTypeMediaContext = oAssemblyPresentationCore.GetType( "System.Windows.Media.MediaContext" );
MethodInfo oMethodInfoGetMediaContextFromDispatcher = oTypeMediaContext.GetMethod( "From", BindingFlags.Static | BindingFlags.NonPublic );
object oMediaContext = oMethodInfoGetMediaContextFromDispatcher.Invoke( null, new object[] { oViewport3D.Dispatcher } );
EventInfo oEventInfoRenderComplete = oMediaContext.GetType().GetEvent( "RenderComplete", BindingFlags.NonPublic | BindingFlags.Instance );
oEventInfoRenderComplete.GetAddMethod( true ).Invoke( oMediaContext, new object[] { new EventHandler( EventHandlerRendered ) } );