在Viewport3D中动画期间WPF闪烁 [英] WPF flickering during animation in Viewport3D

查看:114
本文介绍了在Viewport3D中动画期间WPF闪烁的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在编写的WPF应用程序中发生一些奇怪的行为。当我在摄影机位置上运行动画(PerspectiveCamera.PositionProperty上的Point3DAnimation)时,应用程序内部会出现非常糟糕的闪烁现象。 3D渲染的对象似乎在某些帧中消失了,并允许窗口的背景透过。

I'm having some strange behaviour inside a WPF app I'm writing. When I run an animation on the camera position (a Point3DAnimation on PerspectiveCamera.PositionProperty), I get really bad flickering artifacts inside the application. The 3D-rendered object seems to disappear for certain frames and allows the background of the window to show through.

我在下面编写了一个非常简单的示例应用程序来演示机器上的问题。要使用它,只需对其进行编译,然后使用向上和向下箭头键进行放大和缩小。问题在我的机器上是非常可重复的:每次尝试放大或缩小时,对象在动画过程中都会闪烁,然后在动画完成后再次变为实体。

I've written a very simple sample application below to demonstrate the problem on my machine. To use it, just compile it and use the arrow up and down keys to zoom in and out. The problem is very repeatable on my machine: every time I try to zoom in or out, the object flickers during the animation and then becomes 'solid' again once the animation is complete.

我正在运行32位Windows 7,并使用NVIDIA GeForce 8600GT。以下是一些有趣的细节:

I'm running Windows 7 32-bit and using an NVIDIA GeForce 8600GT. Here are a few interesting details:

1)似乎与硬件有关。我在WPF论坛上发表了一篇文章,一位用户回答说一切对他都很好。我请了几个朋友尝试一下,一个报告说我经历的闪烁完全一样,另一个报告说一切看起来都很好。

1) It seems to be hardware-related. I placed a post in the WPF forums and one user responded saying everything looked fine to him. I've asked a few friends to try it, and one reported exactly the same flickering I was experiencing and the other said everything looked fine.

2)强制垂直同步和通过NVIDIA控制面板启用三重缓冲无法解决问题。

2) Forcing vertical sync and enabling triple buffering through the NVIDIA Control Panel doesn't fix the problem.

3)降低动画所需的FPS可以显着改善此问题。在较低的期望帧率(例如5FPS)下,闪烁消失了……但是动画看起来很糟糕。我在下面提供的示例应用程序仅显示了映射到四边形的单个图像,因此我认为这不应该是处理能力的问题!

3) Reducing the desired FPS of the animation significantly improves the problem. At low desired framerate (say, 5FPS), the flickering disappears... but then the animations look terrible. The sample application I provide below is only showing a single image mapped onto a quad, so I don't believe it should be an issue of processing power!

4)问题似乎与多边形顶点超出可见窗口直接相关。如果我在程序中将closeDist值设置为4(这样,即使放大该对象仍然完全适合窗口),则不会出现闪烁。但是,当我增加closeDist时,一旦达到放大状态且顶点在窗口外的值,就会发生闪烁。当我增加closeDist时,闪烁似乎逐渐变得更糟。值为9.8(恰好在相机的NearPlaneDistance可以完全切断对象之前),闪烁是最糟糕的。

4) The problem seems to be directly related to polygon vertices going outside of the viewable window. If I set the closeDist value in the program to 4 (such that even when 'zoomed in' the object still fits completely within the window), there is no flickering. However, as I increase the closeDist, as soon as I get to values wherein the 'zoomed in' state has the vertices going outside of the window, I get flicker occurring. The flicker appears to get progressively worse as I increase the closeDist. At a value of 9.8 (just before the camera's NearPlaneDistance would cut the object off completely), flickering is worst.

事不宜迟,这里是示例代码!

Without further ado, here's the sample code!

MainWindow.xaml:

MainWindow.xaml:

<Window x:Class="WPFFlickerTest.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        KeyDown="Window_KeyDown">
    <Grid>
        <Viewport3D Name="Viewport">
            <Viewport3D.Camera>
                <PerspectiveCamera LookDirection="0,0,1" FieldOfView="70" x:Name="viewportCam" />
            </Viewport3D.Camera>

            <ModelVisual3D>
                <ModelVisual3D.Content>
                    <AmbientLight />
                </ModelVisual3D.Content>
            </ModelVisual3D>
        </Viewport3D>
    </Grid>
</Window>

MainWindow.xaml.cs:

MainWindow.xaml.cs:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Windows.Media.Media3D;
using System.Windows.Media.Animation;

namespace WPFFlickerTest
{
  public partial class MainWindow : Window
  {
    // time the camera animation takes to complete
    private const double animTime = 0.25;

    // path to an image to use (assuming it's 1920x1200 or 1.6 aspect ratio)
    private const string imagePath = "C:/Windows/Web/Wallpaper/Windows/img0.jpg";

    // far and close camera distances
    private const double closeDist = 8, farDist = 10;

    // chosen to align with aspect ratio of the image
    private const double halfW = 4.8, halfH = 3;

    public MainWindow()
    {
      InitializeComponent();

      Model3DGroup modelGroup = new Model3DGroup();

      // set up the mesh
      MeshGeometry3D mesh = new MeshGeometry3D();
      mesh.Positions.Add(new Point3D(-halfW, halfH, farDist));
      mesh.Positions.Add(new Point3D(halfW, halfH, farDist));
      mesh.Positions.Add(new Point3D(halfW, -halfH, farDist));
      mesh.Positions.Add(new Point3D(-halfW, -halfH, farDist));

      // set up triangle indices
      mesh.TriangleIndices = (Int32Collection)new Int32CollectionConverter().ConvertFromString(
        "0,1,2 2,3,0");

      // set up texture coords
      mesh.TextureCoordinates = (PointCollection)new PointCollectionConverter().ConvertFromString(
        "1,0 0,0 0,1 1,1");

      // set up the brush
      ImageBrush brush = new ImageBrush(new BitmapImage(new Uri(imagePath, UriKind.Relative)));

      // create a geometry model based on the mesh and give it a material based on an image
      GeometryModel3D geom = new GeometryModel3D(mesh, new DiffuseMaterial(brush));

      // add the object
      modelGroup.Children.Add(geom);

      // we should have filled in our objects now
      // so we'll just add them to the viewport
      ModelVisual3D modelVisual = new ModelVisual3D();
      modelVisual.Content = modelGroup;
      Viewport.Children.Add(modelVisual);
    }

    // react to keypresses
    private void Window_KeyDown(object sender, KeyEventArgs e)
    {
      switch (e.Key)
      {
        // move the camera to the centre
        case Key.Down: AnimateTo(new Point3D(0, 0, 0)); break;

        // move the camera to the currently targeted image
        case Key.Up: AnimateTo(new Point3D(0, 0, closeDist)); break;
      }
    }

    // animate to a given position
    void AnimateTo(Point3D position)
    {
      Point3DAnimation camPosAnim = new Point3DAnimation(position, TimeSpan.FromSeconds(animTime));
      viewportCam.BeginAnimation(PerspectiveCamera.PositionProperty, camPosAnim);
    }
  }
}


推荐答案

即使没有找到实际的解决方案,我也会将其标记为已解决。只要模型保持在屏幕区域之内并且没有延伸到屏幕之外,就不会发生闪烁。抱歉!

I'm going to mark this as resolved even though there was no actual solution found. As long the models were kept within the region of the screen and didn't extend past it, the flickering didn't occur. Sorry!

这篇关于在Viewport3D中动画期间WPF闪烁的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆