2011-02-15 2 views
3

필자가 작성한 WPF 응용 프로그램에서 이상한 동작이 발생합니다. PerspectiveCamera.PositionProperty의 Point3DAnimation이라는 카메라 위치에서 애니메이션을 실행하면 응용 프로그램 내부에서 실제로 깜박 거리는 결함이 발생합니다. 3D로 렌더링 된 오브젝트는 특정 프레임에서 사라지는 것처럼 보이고 창의 배경이 보이도록합니다.Viewport3D에서 애니메이션 중 WPF가 깜박입니다.

내 컴퓨터의 문제를 보여주기 위해 아래의 간단한 샘플 응용 프로그램을 작성했습니다. 그것을 사용하려면 컴파일하고 화살표 위아래 화살표를 사용하여 확대 및 축소하십시오. 문제는 컴퓨터에서 반복적으로 발생합니다. 확대 또는 축소하려고 할 때마다 애니메이션이 진행되는 동안 오브젝트가 깜박이고 애니메이션이 완료되면 다시 '단색'이됩니다.

저는 Windows 7 32 비트를 실행 중이며 NVIDIA GeForce 8600GT를 사용하고 있습니다. 다음은 몇 가지 흥미로운 세부 사항입니다 :

1) 하드웨어와 관련된 것 같습니다. 나는 WPF 포럼에 게시물을 올렸고 한 사용자는 모든 것이 훌륭하다고 말했습니다. 나는 몇몇 친구에게 그것을 시도 해달라고 부탁했다. 그리고 나는 경험하고있는 정확하게 같은 깜박 거림을보고했다. 그리고 다른 것은 모든 것이 멋지게 보인다고 말했다.

2) 수직 동기화를 강제하고 NVIDIA 제어판을 통해 트리플 버퍼링을 활성화해도 문제가 해결되지 않습니다.

3) 애니메이션의 원하는 FPS를 줄이면 문제가 크게 개선됩니다. 낮은 프레임 속도 (예 : 5FPS)에서는 깜박임이 사라지지만 애니메이션은 끔찍한 것처럼 보입니다. 아래에서 제공하는 샘플 애플리케이션은 쿼드에 매핑 된 단일 이미지 만 표시하므로 처리 능력의 문제라고 생각하지 않습니다.

4)이 문제는 가시 창 외부 외부의 다각형 정점과 직접적으로 관련되어있는 것 같습니다.. 프로그램의 closeDist 값을 4로 설정하면 (즉 확대/축소 되어도 오브젝트가 윈도우 내에 완전히 들어갈 때도) 이 깜박이지 않습니다. 그러나 closeDist를 늘리 자마자 'zoomed in'상태가 꼭지점이 창 밖으로 나가는 값에 도달하면 깜박임이 발생합니다. 깜박임이 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); 
    } 
    } 
} 
+0

그냥 줘서 나에게 잘 어울리 네요. 실제로 하드웨어와 관련이 있다는 당신의 직감이 정확합니다. 나는 랩톱에있다 ... 평범한 것 ... 아무것도 실행하지 않는다. .NET 3.5 SP1; DirectX/Direct3D를 업데이트하셨습니까? –

+0

@Aaron 우수 제안. 최신 DirectX 런타임을 얻으려고했는데 이미 새로운 버전이나 동등한 버전이 있다고 들었습니다. dxdiag는 DirectX 11을 실행하는 것을 보여줍니다. 아래에 게시 할 또 다른 재미있는 음식을 발견했습니다. – aardvarkk

+0

@aardvarkk 나는 9.0c에있다 ... –

답변

0

실제 솔루션을 찾지 못했지만 해결 방법으로 표시 할 것입니다.모델이 화면 영역 내에 있고 오래 지나지 않아서 깜박임이 발생하지 않았습니다. 죄송합니다!

0

귀하의 애니메이션이 KeyDown 이벤트에 의해 트리거 - 사용자가 아래로 키를 보유하고있는 경우, 당신은 압도 할 수있다 당신의 BeginAnimation 호출로 애플리케이션.

+0

좋은 제안이지만 그게 문제라고 생각하지 않습니다. 나는이 문제를 해결하기 위해 두 가지를 시도했다. (어느 것이 든 문제를 해결하지 못한다.) 1) 프로그램이 처음 시작될 때 한 번만 애니메이션을 적용하고 keydown 이벤트가 발생하면 콘솔 출력을 추가한다. 그것은 하나의 출력만을 보여주기 때문에, 내가 키를 두드리면 그것이 한 번만 호출된다고 가정합니다. 그래도 도와 ​​줘서 고마워! – aardvarkk

1

동적 카메라 위치 지정으로 PerspectiveCamera를 사용하여 비슷한 문제가 발생했습니다. 카메라가 카메라에 너무 가깝고 어떤 물체의 일부 ("배경"의 물체도 포함)가 부분적으로 가려져있을 때 카메라가 물체 (또는 그 일부)를 표시할지 여부에 대해 카메라가 "혼란스러워"하는 것 같습니다. ..

PerspectiveCamera의 "근거리 투영 거리"를 0이지만 0이 아닌 값은 작게 설정하십시오.

+0

제안 해 주셔서 감사합니다. 카메라의 NearPlaneDistance를 매우 작은 값으로 설정하려고 시도했지만 내일 다시 시도하여 문제가 해결되는지 확인합니다. 우리의 현재 해결 방법은 어떤 꼭짓점이 윈도우 경계를 벗어나지 않도록 오브젝트를 '확대'하지 않는 것입니다. 버텍스가 창 안에 있으면 애니메이션이 깜박이지 않습니다. – aardvarkk

+0

값을 0.01으로 다시 시도 했으므로 해당 객체가 절대로 닫히지 않도록 할 수 있습니다. 깜박임이 수정되지 않았습니다. 그래도 좋은 생각이야! – aardvarkk

+0

제안에 감사드립니다. 나를 위해 움직이는 카메라의 Y 위치에 따라 NearPlaneDistance를 다른 값으로 설정했습니다. – Loghman

1

나는이 질문이 더 오래되었다는 것을 알고 있지만, 나는 직장에서이 버그에 부딪혔다. 그리고 마침내 해결책을 찾기 전에 약 10 시간 동안 벽에 부딪쳤다. 나는 이것이 다른 누군가를 돕기를 바랍니다.

Viewport3d의 높이/너비를 수동으로 설정해야합니다. 하드 코딩 (하드 코딩, 그리드에 뷰포트 배치 등) 할 필요가 없습니다. 내 경험에 비추어 볼 때 뷰포트의 크기는 창 크기보다 작아야합니다.

여기서 가정하고있는 작업은 WPF가 뷰포트의 이미지가 표시 가능한 창 내에 있는지 여부를 결정하는 데 약간의 문제가 있다는 것입니다.

어쨌든, HTH

2

그것은 오래된 오래된 질문이지만, 내가 똑같은 문제 싸워 마침내 작업 솔루션을 발견 이후, 내가 여기에 메모 가치가 될 줄 알았는데 그것 :

아브람 이미 언급 한 바와 같이

, NearPlaneDistance가 나를위한 해결책 이었지만, 나는 작은 값으로 설정하지 않았습니다. 사실, 저에게있어서 저는 25 세까지 모두 가야했습니다. 제가 그리는 모델에서는 모든 것이 커졌습니다. 1 단위는 1 밀리미터이고, 평면은 서로 10 단위보다 가깝게 그려지지 않습니다. NearPlaneDistance를 계속 높게 유지하면서, 25 점에 이르기까지 모든 것이 훌륭하게 작동 할 때까지 계속 찢어짐이 줄어 들었습니다.

다른 사람이이 문제로 어려움을 겪고 있다면 NearPlaneDistance를 사용해보세요.

+0

제안에 감사드립니다. 매우 큰지도를로드하고 카메라가 멀리 떨어지면 깜박 거리는 렌더링이 시작됩니다.움직일 때 카메라의 Y 위치에 따라 각 범위에 대해 NearPlaneDistance를 다르게 설정하고 깜박임없이 좋은 결과를 얻었습니다. – Loghman

관련 문제