WPF flickers during animation in Viewport3D

I have strange behavior inside a WPF application that I am writing. When I start the animation at the camera position (Point3DAnimation on PerspectiveCamera.PositionProperty), I get very bad flickering artifacts inside the application. The 3D rendering object seems to disappear for certain frames and allows the window background to show.

I wrote a very simple sample application below to demonstrate the problem on my machine. To use it, just compile it and use the up and down arrows 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 after the animation finishes.

I am running a 32-bit version of Windows 7 and am using the NVIDIA GeForce 8600GT. Here are some interesting details:

1) It seems to be related to equipment. I posted a post on the WPF forums, and one user replied saying that everything looks good for him. I asked several friends to try this, and one said the exact same flicker as I did, and the other said that everything looked good.

2) Forced vertical synchronization and the possibility of triple buffering through the NVIDIA control panel do not fix the problem.

3) Reducing the desired FPS animation greatly improves the problem. At the low frame rate required (say 5FPS), the flicker disappears ... but then the animations look awful. The sample application below shows only one image displayed per square, so I don't think this should be a computational power issue!

4) , -, , . closeDist 4 ( , "" ), . , closeDist, , "" , , . , , closeDist. 9.8 ( , NearPlaneDistance ), .

, !

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:

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 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);
    }
  }
}
+3
5

, . , , . !

0

, , , , , :

, NearPlaneDistance , . , , 25. , , . 1 1 , , 10 . NearPlaneDistance , , 25 .

, - , NearPlaneDistance.

+2

PerspectiveCamera . , "" , ( ), , - "" - ...

NearPlaneDistance PerspectiveCamera , , 0,001.

+1

, , 10 , . , - -

/ Viewport3d. ( , , ..). , , .

, WPF , .

, HTH

+1

Your animation starts when an event occurs KeyDown- if the user holds the key down, you can suppress the application using BeginAnimation calls.

0
source

Source: https://habr.com/ru/post/1792258/


All Articles