비동기식 힌트를 사용한 짧은 지연 시간 렌더링

Joe Medley
Joe Medley

스타일러스 렌더링의 차이점

웹용으로 빌드된 스타일러스 기반 그리기 애플리케이션은 웹페이지에서 그래픽 업데이트를 DOM과 동기화해야 하므로 오랫동안 지연 시간 문제가 발생했습니다. 모든 그리기 애플리케이션에서 50밀리초보다 긴 지연 시간은 사용자의 손과 눈의 협응을 방해하여 애플리케이션 사용이 어려워질 수 있습니다.

canvas.getContext()desynchronized 힌트는 일반적인 DOM 업데이트 메커니즘을 우회하는 다른 코드 경로를 호출합니다. 대신 힌트는 기본 시스템에 최대한 많은 합성을 건너뛰라고 지시합니다. 일부 경우에는 캔버스의 기본 버퍼가 화면의 디스플레이 컨트롤러로 직접 전송됩니다. 이렇게 하면 렌더기 컴포지터 큐를 사용할 때 발생하는 지연 시간이 사라집니다.

마음에 드셨나요?

Sintel 동시 렌더링

코드를 가져오려면 앞으로 스크롤합니다. 실제로 작동하는 것을 보려면 터치스크린이 있는 기기가 필요하며 가능하면 스타일러스가 필요합니다. 손가락도 작동됩니다. 있는 경우 2d 또는 webgl 샘플을 사용해 보세요. 나머지 분들은 이 기능을 구현한 엔지니어 중 한 명인 Miguel Casas의 데모도 확인해 보세요. 데모를 열고 재생을 누른 다음 슬라이더를 빠르고 앞뒤로 움직입니다.

이 예에서는 블렌더 공개 영화 프로젝트인 두리안의 단편 영화 Sintel에서 1분 21초 분량의 클립을 사용합니다. 이 예에서 영화는 콘텐츠가 동시에 <canvas> 요소로 렌더링되는 <video> 요소에서 재생됩니다. 많은 기기에서 테어링 없이 이 작업을 실행할 수 있지만 ChromeOS와 같은 전면 버퍼 렌더링이 있는 기기는 테어링이 발생할 수 있습니다. (영화는 훌륭하지만 가슴 설레는데요. 그걸 보고 한 시간도 쓸모없었어. 주의를 받았다고 생각하세요.)

힌트 사용

desynchronizedcanvas.getContext()에 추가하는 것보다 짧은 지연 시간을 사용하는 것이 더 많습니다. 한 번에 하나씩 문제를 살펴보겠습니다.

캔버스 만들기

먼저 다른 API에서 특성 감지에 대해 설명하겠습니다. desynchronized 힌트의 경우 먼저 캔버스를 만들어야 합니다. canvas.getContext()를 호출하고 true 값과 함께 새 desynchronized 힌트를 전달합니다.

const canvas = document.querySelector('myCanvas');
const ctx = canvas.getContext('2d', {
  desynchronized: true,
  // Other options. See below.
});

기능 감지

그런 다음 getContextAttributes()를 호출합니다. 반환된 속성 객체에 desynchronized 속성이 있으면 테스트합니다.

if (ctx.getContextAttributes().desynchronized) {
  console.log('Low latency canvas supported. Yay!');
} else {
  console.log('Low latency canvas not supported. Boo!');
}

깜박임 방지

올바르게 코딩하지 않으면 깜박임이 발생할 수 있는 두 가지 경우가 있습니다.

Chrome을 포함한 일부 브라우저에서는 프레임 간의 WebGL 캔버스를 지웁니다. 버퍼가 비어 있을 때 디스플레이 컨트롤러가 버퍼를 판독하여 이미지가 깜박일 수 있습니다. 이를 방지하려면 preserveDrawingBuffertrue로 설정합니다.

const canvas = document.querySelector('myCanvas');
const ctx = canvas.getContext('webgl', {
  desynchronized: true,
  preserveDrawingBuffer: true
});

깜박임은 자체 그리기 코드에서 화면 컨텍스트를 지울 때도 발생할 수 있습니다. 삭제해야 하는 경우 오프스크린 프레임 버퍼에 그린 다음 화면에 복사합니다.

알파 채널

알파가 true로 설정된 반투명 캔버스 요소는 여전히 비동기화될 수 있지만 그 위에 다른 DOM 요소가 있어서는 안 됩니다.

하나의

canvas.getContext()를 처음 호출한 후에는 컨텍스트 속성을 변경할 수 없습니다. 이것은 항상 사실이지만, 이 작업을 반복하면 잘 알지 못하거나 잊어버렸을 때 좌절감을 줄일 수 있습니다 .

예를 들어 컨텍스트를 가져와서 알파를 false로 지정한 다음, 아래와 같이 코드의 뒷부분에서 알파를 true로 설정하고 canvas.getContext()를 두 번째로 호출한다고 가정해 보겠습니다.

const canvas = document.querySelector('myCanvas');
const ctx1 = canvas.getContext('2d', {
  alpha: false,
  desynchronized: true,
});

//Some time later, in another corner of code.
const ctx2 = canvas.getContext('2d', {
  alpha: true,
  desynchronized: true,
});

ctx1ctx2가 같은 객체라는 것은 분명하지 않습니다. 알파는 여전히 false이며 알파가 true인 컨텍스트는 생성되지 않습니다.

지원되는 캔버스 유형

getContext()에 전달된 첫 번째 매개변수는 contextType입니다. getContext()에 이미 익숙하다면 '2d' 컨텍스트 유형이 아닌 다른 컨텍스트 유형이 지원되는지 궁금할 것입니다. 아래 표는 desynchronized를 지원하는 컨텍스트 유형을 보여줍니다.

contextType 컨텍스트 유형 객체

'2d'

CanvasRenderingContext2D

'webgl'

WebGLRenderingContext

'webgl2'

WebGL2RenderingContext

결론

더 자세히 알아보려면 샘플을 확인하세요. 이미 설명한 동영상 예 외에도 '2d''webgl' 컨텍스트를 모두 보여주는 예가 있습니다.