У меня странное поведение в приложении WPF, которое я пишу.Когда я запускаю анимацию в положении камеры (Point3DAnimation в PerspectiveCamera.PositionProperty), я получаю очень плохие мерцающие артефакты внутри приложения.3D-рендеринг объекта, кажется, исчезает для определенных кадров и позволяет фону окна просвечивать.
Я написал очень простой пример приложения ниже, чтобы продемонстрировать проблему на моем компьютере.Чтобы использовать его, просто скомпилируйте его и используйте клавиши со стрелками вверх и вниз для увеличения и уменьшения масштаба.Проблема очень повторяется на моей машине: каждый раз, когда я пытаюсь увеличить или уменьшить масштаб, объект мерцает во время анимации и затем снова становится «твердым» после завершения анимации.
Я работаю под управлением Windows 732-битная и с использованием NVIDIA GeForce 8600GT.Вот несколько интересных деталей:
1) Похоже, это связано с аппаратным обеспечением.Я разместил сообщение на форумах WPF, и один пользователь ответил, что все выглядит хорошо для него.Я попросил нескольких друзей попробовать его, и один из них сообщил о том же мерцании, с которым я столкнулся, а другой сказал, что все выглядит хорошо.
2) Принудительная вертикальная синхронизация и включение тройной буферизации через панель управления NVIDIA нене решить проблему.
3) Уменьшение требуемого FPS анимации значительно улучшает проблему.При низкой требуемой частоте кадров (скажем, 5 кадров в секунду) мерцание исчезает ... но тогда анимация выглядит ужасно.Пример приложения, который я предоставляю ниже, показывает только одно изображение, отображенное на четырехугольник, поэтому я не думаю, что это должно быть связано с вычислительной мощностью!
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);
}
}
}