如何同步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
调用,但这比实际呈现的屏幕更频繁地执行,并且可能不在渲染线程上。
好的,我自己找到了解决办法。可以使用反射为内部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 ) } );