问题描述
对此有种种麻烦,我觉得这应该很容易。这是我的设置:
- 我正在使用SharpDX在带有rendertarget的Direct2d上的d3dimage上绘制图元(有效)
- 我正在循环使用计时器重绘此内容。
对于我的应用程序,我希望我们的用户能够绘制很多项目(例如50,000行)。因为我不想每次都重新渲染这些内容,所以我正在寻找一种方法将这些行保存到位图,另一个渲染器,缓冲区中,这样我就可以说“绘制整个内容” ”,而不必遍历每个人再次绘制它。
我尝试创建辅助rendertarget并将其通过bitmap.copyFromrendertarget转换为Direct2d1位图,但是它似乎是在复制我的整个图像,而不只是复制该渲染目标上的图像。
除了我正在尝试的方法之外,我对如何解决此问题也持开放态度。这是一些代码:
public abstract class D2dControl : System.Windows.Controls.Image {
private SharpDX.Direct3D11.Device device ;
private Texture2D rendertarget ;
private Dx11ImageSource d3DSurface ;
private rendertarget d2Drendertarget;
private SharpDX.Direct2D1.Factory d2DFactory ;
//background renderer
private Texture2D bmprendertarget;
private rendertarget d2dbmprendertarget;
private SharpDX.Direct2D1.Factory d2DbmpFactory;
private readonly Stopwatch renderTimer = new Stopwatch();
protected ResourceCache resCache = new ResourceCache();
private long lastFrameTime = 0;
private long lastRenderTime = 0;
private int frameCount = 0;
private int frameCountHistTotal = 0;
private Queue<int> frameCountHist = new Queue<int>();
private object lockObject = new object();
// - property --------------------------------------------------------------------
public static bool IsInDesignMode {
get {
var prop = DesignerProperties.IsInDesignModeProperty;
var isDesignMode = (bool)DependencyPropertyDescriptor.FromProperty(prop,typeof(FrameworkElement)).Metadata.DefaultValue;
return isDesignMode;
}
}
private static readonly DependencyPropertyKey FpsPropertyKey = DependencyProperty.RegisterReadOnly(
"Fps",typeof(int),typeof(D2dControl),new FrameworkPropertyMetadata(0,FrameworkPropertyMetadataOptions.None)
);
public static readonly DependencyProperty FpsProperty = FpsPropertyKey.DependencyProperty;
public int Fps {
get { return (int)GetValue( FpsProperty ); }
protected set { SetValue( FpsPropertyKey,value ); }
}
public static DependencyProperty RenderWaitProperty = DependencyProperty.Register(
"RenderWait",new FrameworkPropertyMetadata( 2,OnRenderWaitChanged )
);
public int RenderWait {
get { return (int)GetValue( RenderWaitProperty ); }
set { SetValue( RenderWaitProperty,value ); }
}
// - public methods --------------------------------------------------------------
public D2dControl() {
base.Loaded += Window_Loaded;
base.Unloaded += Window_Closing;
base.Stretch = System.Windows.Media.Stretch.Fill;
}
public abstract void Render( rendertarget target );
public abstract Bitmap RenderBmp(rendertarget target);
// - event handler ---------------------------------------------------------------
private void Window_Loaded( object sender,RoutedEventArgs e ) {
if ( D2dControl.IsInDesignMode ) {
return;
}
StartD3D();
StartRendering();
}
private void Window_Closing( object sender,RoutedEventArgs e ) {
if ( D2dControl.IsInDesignMode ) {
return;
}
StopRendering();
EndD3D();
}
private void OnRendering( object sender,EventArgs e ) {
if ( !renderTimer.IsRunning ) {
return;
}
if (System.Threading.Monitor.TryEnter(lockObject))
{
try
{
PrepareAndCallRender();
d3DSurface.Invalidated3dimage(0);
lastRenderTime = renderTimer.ElapsedMilliseconds;
}
finally
{
System.Threading.Monitor.Exit(lockObject);
}
}
}
protected override void OnRenderSizeChanged( SizeChangedInfo sizeInfo ) {
CreateAndBindTargets();
base.OnRenderSizeChanged( sizeInfo );
}
private void OnIsFrontBufferAvailableChanged( object sender,DependencyPropertyChangedEventArgs e ) {
if ( d3DSurface.IsFrontBufferAvailable ) {
StartRendering();
} else {
StopRendering();
}
}
private static void OnRenderWaitChanged(DependencyObject d,DependencyPropertyChangedEventArgs e) {
var control = (D2dControl)d;
control.d3DSurface.RenderWait = (int)e.NewValue;
}
// - private methods -------------------------------------------------------------
private void StartD3D() {
device = new SharpDX.Direct3D11.Device( DriverType.Hardware,DeviceCreationFlags.BgraSupport );
d3DSurface = new Dx11ImageSource();
d3DSurface.IsFrontBufferAvailableChanged += OnIsFrontBufferAvailableChanged;
CreateAndBindTargets();
base.source = d3DSurface;
}
private void EndD3D() {
d3DSurface.IsFrontBufferAvailableChanged -= OnIsFrontBufferAvailableChanged;
base.source = null;
disposer.Safedispose( ref d2Drendertarget );
disposer.Safedispose( ref d2DFactory );
disposer.Safedispose( ref d3DSurface );
disposer.Safedispose( ref rendertarget );
disposer.Safedispose( ref device );
}
private void CreateAndBindTargets()
{
if (d3DSurface == null) {
return;
}
d3DSurface.Setrendertarget( null );
disposer.Safedispose( ref d2Drendertarget );
disposer.Safedispose( ref d2DFactory );
disposer.Safedispose( ref rendertarget );
var width = Math.Max((int)ActualWidth,100);
var height = Math.Max((int)ActualHeight,100);
var renderDesc = new Texture2DDescription {
BindFlags = BindFlags.rendertarget | BindFlags.ShaderResource,Format = Format.B8G8R8A8_Unorm,Width = width,Height = height,MipLevels = 1,SampleDescription = new SampleDescription(1,0),Usage = ResourceUsage.Default,OptionFlags = ResourceOptionFlags.Shared,cpuAccessFlags = cpuAccessFlags.None,ArraySize = 1
};
rendertarget = new Texture2D( device,renderDesc );
bmprendertarget = new Texture2D(device,renderDesc);
var surface = rendertarget.QueryInterface<Surface>();
d2DFactory = new SharpDX.Direct2D1.Factory();
d2DbmpFactory = new SharpDX.Direct2D1.Factory();
var rtp = new rendertargetProperties(new PixelFormat(Format.UnkNown,SharpDX.Direct2D1.AlphaMode.Premultiplied));
d2Drendertarget = new rendertarget(d2DFactory,surface,rtp);
d2dbmprendertarget = new rendertarget(d2DFactory,rtp);
resCache.rendertarget = d2Drendertarget;
d3DSurface.Setrendertarget( rendertarget );
device.ImmediateContext.Rasterizer.SetViewport( 0,width,height,0.0f,1.0f );
}
private void StartRendering() {
if ( renderTimer.IsRunning ) {
return;
}
System.Windows.Media.CompositionTarget.Rendering += OnRendering;
renderTimer.Start();
}
private void StopRendering() {
if ( !renderTimer.IsRunning ) {
return;
}
System.Windows.Media.CompositionTarget.Rendering -= OnRendering;
renderTimer.Stop();
}
private void PrepareAndCallRender() {
if ( device == null ) {
return;
}
var bitmap = RenderBmp(d2dbmprendertarget);
d2Drendertarget.BeginDraw();
d2Drendertarget.Clear(new SharpDX.Mathematics.Interop.RawColor4(0,1));
d2Drendertarget.Flush();
if (bitmap != null)
{
d2Drendertarget.DrawBitmap(bitmap,1,BitmapInterpolationMode.Linear);
}
Render(d2Drendertarget);
d2Drendertarget.EndDraw();
CalcFps();
device.ImmediateContext.Flush();
}
private void CalcFps() {
frameCount++;
if ( renderTimer.ElapsedMilliseconds - lastFrameTime > 1000 ) {
frameCountHist.Enqueue( frameCount );
frameCountHistTotal += frameCount;
if ( frameCountHist.Count > 5 ) {
frameCountHistTotal -= frameCountHist.Dequeue();
}
Fps = frameCountHistTotal / frameCountHist.Count;
frameCount = 0;
lastFrameTime = renderTimer.ElapsedMilliseconds;
}
}
private void PrepareAndCallRender() {
if ( device == null ) {
return;
}
RenderBmp(d2dbmprendertarget);
BitmapProperties properties = new BitmapProperties(new SharpDX.Direct2D1.PixelFormat(Format.B8G8R8A8_Unorm,SharpDX.Direct2D1.AlphaMode.Premultiplied),96f,96f);
var bitmap = new SharpDX.Direct2D1.Bitmap(d2dbmprendertarget,new Size2((int)d2dbmprendertarget.Size.Width,(int)d2dbmprendertarget.Size.Height),properties);
bitmap.copyFromrendertarget(d2dbmprendertarget);
d2Drendertarget.BeginDraw();
d2Drendertarget.Clear(new SharpDX.Mathematics.Interop.RawColor4(0,1));
d2Drendertarget.Flush();
d2Drendertarget.DrawBitmap(bitmap,BitmapInterpolationMode.Linear);
Render(d2Drendertarget);
d2Drendertarget.EndDraw();
CalcFps();
device.ImmediateContext.Flush();
}
RenderBmp和Render都转到使用rendertarget进行绘制的方法。 RenderBmp仅在检测到已发生更改时才绘制,而不是在每个循环上绘制。
解决方法
暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!
如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。
小编邮箱:dio#foxmail.com (将#修改为@)