윈도우에서 이중 버퍼링 된 GDI를 사용하는 애니메이션, DWM 구성이 활성화 된 시스템에서 애니메이션을 그리며 화면에 tearing이 명확하게 표시됩니다. 이것을 막을 수있는 방법이 있습니까?DWM으로 구성된 윈도우에서 GDI를 사용하여 드로잉 할 때 인위적 인열을 방지 할 수 있습니까?
상세
애니메이션은 동일한 이미지를 받아, 오른쪽 스크린상에서 왼쪽으로 이동한다; 건너 뛴 픽셀 수는 현재 시간과 애니메이션이 시작된 시간과 끝나는 시간의 차이에 의해 결정되어 전체 창 너비에 적용되는 부분을 얻고 1ms resolution이있는 timeGetTime
을 사용합니다. 애니메이션은 응용 프로그램 메시지를 처리하지 않고 루프로 그립니다. (VCL 라이브러리) 메서드 Repaint
을 호출하여 내부적으로 무효화 한 다음 해당 창에 대해 UpdateWindow
을 호출하여 WM_PAINT
이라는 메시지 프로 시저를 직접 호출합니다. 페인트 핸들러의 VCL 구현은 BeginBufferedPaint
을 사용합니다. 페인팅 자체가 이중 버퍼링됩니다.
이 목표는 가능한 한 높은 프레임 속도를 유지하여 화면에서 부드러운 애니메이션을 얻는 것입니다. (그림은 이중 버퍼링을 사용하여 깜박임 현상을 제거하고 한 번에 전체 이미지 또는 프레임을 화면에 표시합니다. 다른 메시지 처리를 수행하지 않고 메시지 프로 시저를 호출하여 직접 무효화하고 업데이트합니다. 예를 들어, BeginBufferedPaint).이 안에서 페인팅은 두 개의 BitBlt 호출 (애니메이션의 왼쪽면, 즉 화면 밖으로 움직이는 부분과 애니메이션의 오른쪽면, 즉 화면상에서 움직이는 부분)에 대해 수행됩니다.)
애니메이션을 볼 때 명확하게 tearing으로 볼 수 있습니다. 다른 그래픽 카드가있는 여러 시스템의 Windows Vista, 7 및 8.1에서 발생합니다.
이 문제를 해결하기위한 나의 접근 방식은 그리기 속도를 줄이거 나 다시 페인팅하기 전에 VSync를 기다리는 것입니다. 이것은 잘못된 접근 일 수 있으므로이 질문에 대한 대답은 "완전히 다른 일을하십시오 : X"일 수 있습니다. 큰, 그렇다면 :)
(내가 좋아하는 정말 줄 것은 /이 특정 창에 대해서만 완전히 그린 프레임을 사용 구도를 DWM을 요청하는 방법입니다.)
나는 다음과 같은 방법을 시도했습니다 , 눈에 보이는 모든 찢어짐이 제거되는 것은 아닙니다. 따라서 질문은 입니다. DWM 컴포지션을 사용할 때 찢어지지 않도록 할 수 있습니까? 그렇다면 어떻게해야합니까?
접근 시도 :
이
GetDeviceCaps(Application.MainForm.Handle, VREFRESH)
를 통해 모니터 주사율을 얻기; 1/새로 고침 빈도 밀리 초 동안 자고 있습니다. 가능한 한 빨리 그림을 약간 개선했지만 희망적인 생각 일 수 있습니다. 지각 적으로 약간 부드러운 애니메이션 속도. (비틀기 :Sleep
정상 및 높은 해상도는timeGetTime
를 사용하여 스핀 기다립니다.)코드가립니다으로 같은 속도로 업데이트 제한하려고
DwmSetPresentParameters
사용. 대안 : 많은 버퍼 (cBuffer = 8) (눈에 보이지 않는 효과), 위의 코드를 사용하여 모니터 새로 고침 빈도/1의 소스 속도 지정 및 잠자기 (잠자기 방식과 동일), 프레임 당 새로 고침 지정 1, 10 등 (보이는 효과 없음), 소스 프레임 적용 범위 변경 (눈에 띄는 효과 없음.) 다양한 방법으로DwmGetCompositionTimingInfo
를 사용:
-
cFramesPending
> 0, 스핀 동안; 이 번호는 변경되지 않습니다 동안
-
cFrame
(프레임 구성)과 스핀을 얻으십시오; 이 변경되지 않습니다 동안
-
cFrameDisplayed
스핀을 얻으십시오;QueryPerformanceCounter
은 이보다 적은 시간, 스핀을 반환하면서qpcVBlank + qpcRefreshPeriod
을 추가로 잠을 시간을 계산 은
-
- 다음
이러한 모든 방법
-
몇 가지 눈에 보이는 효과가있는 것 같고 그 효과는 자격이 없으며 낮은 프레임 속도의 결과 일 수 있습니다. 아무도 찢어짐을 방지합니다. 즉, DWM이 창 DC의 내용 전체를 "창"으로 구성하지 못하게합니다.
조언에 감사드립니다 :)
GDI는 오래되고 피 각질이며 애니메이션이 매끄럽지 않습니다. 어쩌면 Direct2D를 사용해 보시겠습니까? –
@JonathanPotter 좋은 지적입니다. 내가 겪고있는 제약 중 하나는 어떤 종류의 DX도 사용하지 않는 것입니다. 하나의 이유는 플랫폼의 수와 요구 사항이 부족하기 때문입니다. 최종 코드는 계속 실행해야합니다. (모두 최신 Windows가 아닙니다.) Aero가있을 때만 도우미 DX 코드가 ... 아마도? 그러나 시각적 결함이없는 GDI/DX에서 애니메이션을 켜거나 끌 때 끊김없이 전환해야합니다. 그게 가능하니? –
DX를 사용할 수있는 경우 드로퍼 도우미 클래스를 작성하고, 그렇지 않은 경우 GDI로 돌아갈 수도 있습니다. D2D가 아니더라도 Direct3D를 지원하지 않는 시스템을 찾는 것은 매우 드뭅니다. –