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

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

问题描述

我正在编写的 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!

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

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