4

作成しているWPFアプリ内で奇妙な動作が発生しています。カメラの位置(PerspectiveCamera.PositionPropertyのPoint3DAnimation)でアニメーションを実行すると、アプリケーション内で非常にひどいちらつきアーティファクトが発生します。3Dレンダリングされたオブジェクトは、特定のフレームで消えるように見え、ウィンドウの背景が透けて見えるようになります。

私のマシンの問題を示すために、以下に非常に簡単なサンプルアプリケーションを作成しました。使用するには、コンパイルし、上下の矢印キーを使用してズームインおよびズームアウトします。この問題は私のマシンでは非常に再現性があります。ズームインまたはズームアウトしようとするたびに、アニメーション中にオブジェクトがちらつき、アニメーションが完了すると再び「ソリッド」になります。

私はWindows732ビットを実行しており、NVIDIAGeForce8600GTを使用しています。ここにいくつかの興味深い詳細があります:

1)ハードウェアに関連しているようです。私はWPFフォーラムに投稿しましたが、1人のユーザーがすべてがうまくいったと答えました。数人の友人に試してもらいましたが、1人は私が経験したのとまったく同じちらつきを報告し、もう1人はすべてがうまくいったと言いました。

2)NVIDIAコントロールパネルを介して垂直同期を強制し、トリプルバッファリングを有効にしても、問題は解決しません。

3)アニメーションの目的のFPSを下げると、問題が大幅に改善されます。必要なフレームレートが低い場合(たとえば、5FPS)、ちらつきは消えます...しかし、アニメーションはひどく見えます。以下に示すサンプルアプリケーションは、クワッドにマッピングされた単一の画像のみを示しているため、処理能力の問題になるとは思われません。

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'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);
    }
  }
}
4

5 に答える 5

2

これは古い質問ですが、まったく同じ問題に苦労し、最終的に有効な解決策を見つけたので、ここでのメモは価値があるかもしれないと思いました。

Abramがすでに述べたように、NearPlaneDistanceは私にとっての解決策でしたが、私はそれを小さな値に設定しませんでした。実際、私にとっては、25まで行かなければなりませんでした。私が描いているモデルでは、すべてが大きいです。1単位は1ミリメートルであり、互いに10単位より近くに描画される平面はありません。私がNearPlaneDistanceをどんどん高くしていくにつれて、25ですべてがうまくいくまで、引き裂きはどんどん少なくなっていきました。

したがって、他の誰かがこれに苦労している場合は、NearPlaneDistanceを試してみてください。

于 2016-07-07T10:40:35.543 に答える
1

動的カメラポジショニングでPerspectiveCameraを使用して、同様の問題が発生しました。カメラに近すぎてオブジェクトの一部(「背景」にあるオブジェクトでさえ)が部分的に隠されている場合、カメラはオブジェクト(またはその一部)を表示するかどうかについて「混乱」しているようです。 ..

PerspectiveCameraの「NearPlaneDistance」を低い値に設定してみてください。ただし、0.001などのゼロ以外の値に設定してください。

于 2011-02-23T14:56:44.573 に答える
1

私はこれが古い質問であることを知っていますが、私は仕事でこのバグに遭遇し、最終的に解決策を見つける前に約10時間壁にぶつかりました。これが他の誰かの助けになることを願っています-

Viewport3dの高さ/幅を手動で設定する必要があります。ハードコーディングする必要はありません(バインド、ハードコーディング、ビューポートのグリッドへの配置などが可能です)。私の経験から、ビューポートのサイズはウィンドウサイズより小さくなければなりません。

ここでの作業上の前提は、WPFがビューポート内の画像が表示可能なウィンドウ内にあるかどうかを判断するのに問題があるということです。

とにかく、HTH

于 2012-01-04T17:31:30.103 に答える
0

アニメーションはKeyDownイベントによってトリガーされます。ユーザーがキーを押したままにすると、BeginAnimation呼び出しでアプリケーションを圧倒する可能性があります。

于 2011-02-15T16:06:07.223 に答える
0

実際の解決策が見つからなかったとしても、これを解決済みとしてマークします。モデルが画面の領域内に保持され、それを超えて拡張されない限り、ちらつきは発生しませんでした。ごめん!

于 2011-08-24T19:55:49.680 に答える