소개
일반적으로 2D 게임을 플레이하거나 HTML5 캔버스를 렌더링할 때 여러 레이어를 사용하여 합성 장면을 구축하도록 최적화를 수행해야 합니다. OpenGL 또는 WebGL과 같은 저수준 렌더링에서는 프레임별로 장면을 정리하고 페인팅하여 렌더링이 수행됩니다. 렌더링을 구현한 후에는 게임을 최적화하여 렌더링 양을 줄여야 하며 비용은 상황에 따라 달라집니다. 캔버스는 DOM 요소이므로 최적화 방법으로 여러 캔버스를 계층화할 수 있습니다.
자주 사용되는 약어
이 기사에서는 캔버스 레이어링의 이론적 근거를 살펴보겠습니다. 계층화된 캔버스를 구현하기 위한 DOM 설정을 이해합니다. 레이어링을 사용하여 최적화하려면 다양한 실습이 필요합니다. 이 기사에서는 계층화된 접근 방식을 확장하는 몇 가지 최적화 전략 개념과 기술도 살펴보겠습니다.
이 기사에 사용된 예제의 소스 코드를 다운로드할 수 있습니다.
최적화 전략 선택
최상의 최적화 전략을 선택하는 것은 어려울 수 있습니다. 레이어된 장면을 선택할 때 장면이 어떻게 구성되어 있는지 고려해야 합니다. 대형 화면에서 고정된 개체를 렌더링하려면 여러 구성 요소를 재사용해야 하는 경우가 많으며 이러한 구성 요소는 훌륭한 연구 대상입니다. 시차 또는 애니메이션 엔터티와 같은 효과에는 다양한 화면 공간이 많이 필요한 경우가 많습니다. 최적의 최적화 전략을 탐색할 때 이러한 상황을 알고 있는 것이 좋습니다. 캔버스 레이어링 최적화에는 여러 가지 다른 기술이 필요하지만 이러한 기술을 올바르게 적용하면 성능이 크게 향상되는 경우가 많습니다.
레이어 설정
계층적 접근 방식을 사용할 때 첫 번째 단계는 DOM에 캔버스를 설정하는 것입니다. 일반적으로 이는 캔버스 요소를 정의하고 이를 DOM에 배치하는 것만큼 간단하지만 캔버스 레이어에는 몇 가지 추가 스타일이 필요할 수 있습니다. CSS를 사용할 때 캔버스 레이어링을 성공적으로 구현하려면 두 가지 요구 사항이 있습니다.
각 캔버스 요소는 뷰포트의 동일한 위치에 공존해야 합니다.
각 캔버스는 다른 캔버스 아래에 표시되어야 합니다.
그림 1은 레이어 설정 뒤에 있는 일반적인 오버레이 개념을 보여줍니다.
그림 1. 레이어 예시
레이어 설정 단계는 다음과 같습니다.
캔버스 오버랩 스택 설정
CSS에서 오버레이 스택을 생성하려면 약간의 스타일링이 필요할 수 있습니다. HTML과 CSS를 사용하여 겹치는 방법에는 여러 가지가 있습니다. 이 문서의 예에서는
Container
이러한 HTML5 캔버스 요소의 순서도 중요합니다. 순서는 DOM에 요소가 나타나는 순서로 관리하거나 캔버스가 나타나는 순서대로 z-index 스타일을 스타일 지정하여 관리할 수 있습니다. 항상 그런 것은 아니지만 다른 스타일이 렌더링에 영향을 미칠 수 있습니다. 추가 스타일(예: CSS 변환)을 도입할 때는 주의하세요.
투명한 배경
겹침 가시성을 활용하여 레이어 기법의 두 번째 스타일링 요구 사항을 달성합니다. 이 예제에서는 목록 2에 표시된 대로 이 옵션을 사용하여 DOM 요소 배경색을 설정합니다.
목록 2. 투명 배경 설정을 위한 스타일 시트 규칙
투명한 배경을 갖도록 캔버스 스타일을 지정합니다. 이는 겹쳐진 캔버스가 눈에 보이도록 하는 두 번째 요구 사항을 충족합니다. 이제 레이어 요구 사항에 맞게 마크업과 스타일을 구성했으므로 레이어 장면을 설정할 수 있습니다.
레이어링 고려사항
최적화 전략을 선택할 때는 해당 전략을 사용할 때의 모든 장단점을 알고 있어야 합니다. HTML5 캔버스 장면 레이어링은 런타임 속도 이점을 얻기 위해 사용되는 런타임 메모리 중심 전략입니다. 더 빠른 프레임 속도를 얻으려면 페이지 브라우저에 더 많은 가중치를 추가할 수 있습니다. 일반적으로 캔버스는 그래픽 API를 포함하는 브라우저의 그래픽 평면으로 간주됩니다.
Google Chrome 19에서 테스트하고 브라우저의 탭 메모리 사용량을 기록하면 메모리 사용량의 명확한 추세를 확인할 수 있습니다. 이 테스트에서는 이전 섹션에서 설명한 대로 이미 스타일이 지정된
Google Chrome의 작업 관리자에서는 페이지에서 사용하는 메모리(RAM이라고도 함)의 양을 확인할 수 있습니다. Chrome은 GPU 메모리, 즉 GPU에서 사용되는 메모리도 제공합니다. 이는 컴퓨터가 캔버스 데이터를 화면에 푸시하는 데 필요할 수 있는 기하학, 질감 또는 모든 형태의 캐시된 데이터와 같은 일반적인 정보입니다. 메모리가 낮을수록 컴퓨터에 가해지는 무게가 줄어듭니다. 아직 근거로 삼을 수 있는 확실한 숫자는 없지만 항상 이를 테스트하여 프로그램이 한계를 초과하거나 너무 많은 메모리를 사용하지 않는지 확인해야 합니다. 메모리를 너무 많이 사용하면 메모리 리소스 부족으로 인해 브라우저나 페이지가 중단됩니다. GPU 처리는 이 기사의 범위를 벗어나는 야심찬 프로그래밍 추구입니다. OpenGL을 배우거나 Chrome 문서를 확인하여 시작할 수 있습니다(참고자료 참조).
표 1. 캔버스 레이어의 메모리 오버헤드
표 1에서는 페이지에 HTML5 Canvas 요소가 더 많이 도입되고 사용될수록 더 많은 메모리가 사용됩니다. 일반 메모리에도 선형 상관 관계가 있지만 각 추가 레이어마다 메모리 증가량이 크게 줄어듭니다. 이 테스트에서는 이러한 레이어가 성능에 미치는 영향을 자세히 설명하지 않지만 캔버스가 GPU 메모리에 심각한 영향을 미칠 수 있음을 보여줍니다. 플랫폼 제한으로 인해 애플리케이션이 수행할 수 없는 상태가 되지 않도록 대상 플랫폼에서 스트레스 테스트를 수행하는 것을 항상 기억하십시오.
계층화된 솔루션의 단일 캔버스 렌더링 주기를 변경하기로 선택한 경우 메모리 오버헤드와 관련된 성능 향상을 고려하세요. 메모리 비용에도 불구하고 이 기술은 각 프레임에서 수정되는 픽셀 수를 줄여 작업을 수행합니다.
다음 섹션에서는 레이어를 사용하여 장면을 구성하는 방법을 설명합니다.
장면 레이어링: 게임
이 섹션에서는 스크롤 플랫폼 러너 스타일 게임에서 시차 효과의 단일 캔버스 구현을 리팩토링하여 다층 솔루션을 살펴보겠습니다. 그림 2는 구름, 언덕, 땅, 배경 및 일부 대화형 엔터티를 포함하는 게임 보기의 구성을 보여줍니다.
그림 2. 합성 게임 뷰
게임에서는 구름, 언덕, 땅, 배경이 모두 서로 다른 속도로 움직입니다. 기본적으로 배경에 있는 요소는 앞에 있는 요소보다 느리게 이동하므로 시차 효과가 생성됩니다. 상황을 더 복잡하게 만들기 위해 배경은 0.5초마다 다시 렌더링될 정도로 천천히 움직입니다.
일반적으로 좋은 해결책은 배경이 이미지이고 끊임없이 변화하기 때문에 모든 프레임을 지우고 화면을 다시 렌더링하는 것입니다. 이 경우 배경은 초당 2번만 변경되므로 각 프레임을 다시 렌더링할 필요가 없습니다.
현재 작업 공간을 정의했으므로 장면의 어느 부분이 동일한 레이어에 있어야 하는지 결정할 수 있습니다. 레이어를 정리하면서 레이어링을 위한 다양한 렌더링 전략을 살펴보겠습니다. 먼저 목록 3에 표시된 것처럼 단일 캔버스를 사용하여 이 솔루션을 구현하는 방법을 고려해야 합니다.
목록 3. 단일 캔버스 렌더링 루프를 위한 의사 코드
목록 3의 코드와 마찬가지로 이 솔루션에는 모든 게임 루프 호출 또는 모든 업데이트 간격이라고 불리는 렌더링 함수가 있습니다. 이 경우 렌더링은 메인 루프 호출과 각 요소의 위치를 업데이트하는 업데이트 호출에서 추상화됩니다.
"clear to render" 솔루션에 따라 렌더링은 명확한 컨텍스트를 호출하고 화면의 각 렌더링 기능에서 엔터티를 호출하여 이를 추적합니다. 목록 3은 캔버스에 요소를 배치하는 프로그래밍 방식의 경로를 따릅니다. 이 솔루션은 화면의 엔터티를 렌더링하는 데 효과적이지만 사용된 모든 렌더링 방법을 설명하지도 않고 어떤 형태의 렌더링 최적화도 지원하지 않습니다.
엔티티 렌더링 방법을 더 잘 지정하려면 두 가지 유형의 엔터티 객체를 사용해야 합니다. 목록 4에서는 사용하고 개선할 두 엔터티를 보여줍니다.
목록 4. 렌더링 가능한 엔터티 의사코드
목록 4의 개체는 엔터티의 이미지, x, y, 너비 및 높이에 대한 인스턴스 변수를 저장합니다. 이러한 개체는 JavaScript 구문을 따르지만 간결성을 위해 대상 개체에 대한 불완전한 의사 코드만 제공됩니다. 현재 렌더링 알고리즘은 게임 루프의 다른 요구 사항에 관계없이 캔버스에 이미지를 렌더링하는 데 매우 욕심이 많습니다.
성능을 향상하려면 패닝 렌더 호출이 원하는 이미지보다 더 큰 이미지를 출력한다는 점에 유의하는 것이 중요합니다. 이 문서에서는 이러한 특정 최적화를 무시합니다. 그러나 사용된 공간이 이미지가 제공하는 것보다 작은 경우 필요한 패치만 렌더링해야 합니다.
레이어 결정
이제 단일 캔버스를 사용하여 이 예제를 구현하는 방법을 알았으므로 이러한 유형의 장면을 개선하고 렌더링 루프 속도를 높일 수 있는 방법이 있는지 살펴보겠습니다. 레이어링 기술을 사용하려면 엔터티의 렌더링 중복을 찾아 레이어링에 필요한 HTML5 캔버스 요소를 식별해야 합니다.
영역 다시 그리기
겹치는 부분이 있는지 확인하려면 다시 그리기 영역이라는 보이지 않는 영역을 고려하세요. 다시 그리기 영역은 개체의 이미지를 그릴 때 캔버스를 지워야 하는 영역입니다. 다시 그리기 영역은 그림 3과 같이 렌더링된 장면을 완벽하게 만드는 최적화 기술을 찾을 수 있게 해주기 때문에 렌더링 분석에 중요합니다.
그림 3. 합성 게임 보기 및 다시 그리기 영역
그림 3의 효과를 시각화하기 위해 장면의 각 개체에는 뷰포트 너비와 개체의 이미지 높이에 걸쳐 있는 다시 그리기 영역을 나타내는 오버레이가 있습니다. 장면은 배경, 전경, 상호작용의 세 그룹으로 나눌 수 있습니다. 장면에서 다시 칠해진 영역에는 색상이 지정된 오버레이가 있어 서로 다른 영역을 구별할 수 있습니다.
공과 장애물을 제외한 모든 겹침의 경우 다시 그리기 영역은 뷰포트 너비에 걸쳐 있습니다. 이러한 개체의 이미지는 거의 전체 화면을 채웁니다. 변환 요구 사항으로 인해 그림 4와 같이 전체 뷰포트 너비를 렌더링합니다. 공과 장애물은 이 뷰포트를 통과할 것으로 예상되며 엔터티 위치에 따라 정의된 자체 영역을 가질 수 있습니다. 다시 그려진 영역만 남기고 장면에 렌더링된 이미지를 제거하면 개별 레이어를 쉽게 볼 수 있습니다.
그림 4. 영역 다시 그리기
첫 번째 레이어는 서로 겹치는 다양한 영역을 확인할 수 있기 때문에 명확합니다. 공과 장애물 영역은 언덕과 지면을 덮기 때문에 이러한 개체는 상호 작용 레이어라는 하나의 레이어로 그룹화될 수 있습니다. 게임 엔터티의 렌더링 순서에 따르면 상호 작용 레이어가 최상위 레이어입니다.
추가 레이어를 찾는 또 다른 방법은 겹치지 않는 모든 영역을 수집하는 것입니다. 뷰포트를 차지하는 빨간색, 녹색, 파란색 영역은 겹치지 않으며 두 번째 레이어인 전경을 형성합니다. 구름 영역과 대화형 엔터티는 겹치지 않지만 공이 빨간색 영역으로 점프할 가능성이 있으므로 이 엔터티를 별도의 레이어로 만드는 것을 고려해야 합니다.
검은색 영역의 경우 배경 개체가 최종 레이어를 구성할 것임을 쉽게 추론할 수 있습니다. 전체 뷰포트(예: 배경 엔터티)를 채우는 모든 영역은 전체 레이어에서 해당 영역을 채우는 것으로 간주되어야 하지만 이 장면에는 적용되지 않습니다. 세 개의 레이어를 정의한 후 그림 5와 같이 이 레이어를 캔버스에 할당할 수 있습니다.
그림 5. 계층화된 게임 보기
이제 그룹화된 각 개체에 대한 레이어를 정의했으므로 캔버스 지우기 최적화를 시작할 수 있습니다. 이 최적화의 목표는 처리 시간을 절약하는 것인데, 이는 각 단계에서 렌더링되는 화면상의 고정 장치 수를 줄임으로써 달성할 수 있습니다. 다양한 전략을 사용하면 이미지가 더 잘 최적화될 수 있다는 점에 유의하는 것이 중요합니다. 다음 섹션에서는 다양한 엔터티 또는 레이어에 대한 최적화 방법을 살펴봅니다.
렌더링 최적화
엔터티 최적화는 계층형 전략의 핵심입니다. 레이어링 엔터티를 사용하면 렌더링 전략을 채택할 수 있습니다. 일반적으로 최적화 기술은 오버헤드를 제거하려고 시도합니다. 표 1에서 언급했듯이 레이어 도입으로 인해 메모리 오버헤드가 증가했습니다. 여기에서 설명하는 최적화 기술은 게임 속도를 높이기 위해 프로세서가 수행해야 하는 작업량을 줄여줍니다. 우리의 목표는 렌더링할 공간을 줄이고 각 단계에서 가능한 한 많은 렌더링 및 정리 호출을 제거하는 방법을 찾는 것입니다.
단일 엔터티 지우기
첫 번째 최적화는 공간 정리를 목표로 하며, 엔터티를 구성하는 화면의 하위 집합만 지워서 처리 속도를 높입니다. 먼저 영역의 각 엔터티 주위의 투명 픽셀과 겹치는 다시 그리기 영역의 양을 줄입니다. 이 기술을 사용하면 뷰포트의 작은 영역을 채우는 상대적으로 작은 개체가 포함됩니다.
첫 번째 대상은 공과 장애물 개체입니다. 단일 엔터티 클리어링 기술은 엔터티를 새 위치로 렌더링하기 전에 이전 프레임에서 엔터티가 렌더링된 위치를 지우는 작업을 포함합니다. 각 엔터티 렌더링에 대한 정리 단계를 소개하고 엔터티 이미지의 경계 상자를 저장합니다. 이 단계를 추가하면 목록 5에 표시된 대로 정리 단계를 포함하도록 엔터티 개체가 수정됩니다.
목록 5. 단일 상자 지우기를 포함하는 엔터티
업데이트 단계 전에 호출되는 각 엔터티에 대한 명확한 메서드를 생성하여 이 렌더링 솔루션을 구현할 수 있습니다(그러나 이 문서에서는 명확한 메서드를 사용하지 않습니다). 목록 6에 표시된 대로 이 청산 전략을 PanningEntity에 도입하여 지상 및 구름 엔터티에 청산을 추가할 수도 있습니다.
PanningEntity는 전체 뷰포트에 걸쳐 있기 때문에 캔버스 너비를 지우기 직사각형의 크기로 사용할 수 있습니다. 이 제거 전략을 사용하면 구름, 언덕 및 지상 개체에 대해 정의된 다시 그리기 영역이 제공됩니다.
클라우드 엔터티를 더욱 최적화하기 위해 클라우드를 자체 다시 그리기 영역이 있는 별도의 엔터티로 분리할 수 있습니다. 이렇게 하면 클라우드 다시 그리기 영역 내에서 지워야 하는 화면 공간의 양이 크게 줄어듭니다. 그림 7은 새로운 다시 그리기 영역을 보여줍니다.
그림 7. 별도의 다시 그리기 영역이 있는 클라우드
단일 엔터티 삭제 전략은 이와 같은 계층형 캔버스 게임의 대부분의 문제를 해결하는 솔루션을 생성하지만 여전히 최적화할 수 있습니다. 이 렌더링 전략의 극단적인 경우를 찾기 위해 공이 삼각형과 충돌한다고 가정합니다. 두 엔터티가 충돌하는 경우 엔터티의 다시 그리기 영역이 겹쳐서 원하지 않는 렌더링 아티팩트가 생성될 수 있습니다. 충돌할 수 있는 엔터티에 더 적합한 또 다른 정리 최적화로, 레이어링에도 도움이 됩니다.
더티 직사각형 클리어
단일 청소 전략이 없는 경우 더티 직사각형 청소 전략이 강력한 대안이 될 수 있습니다. 조밀한 입자 시스템이나 소행성이 있는 우주 게임과 같이 영역을 다시 칠한 대규모 엔터티에 대해 이 지우기 전략을 사용할 수 있습니다.
개념적으로 알고리즘은 알고리즘이 관리하는 모든 개체의 다시 그리기 영역을 수집하고 한 번의 명확한 호출로 전체 영역을 삭제합니다. 추가 최적화를 위해 이 정리 전략은 목록 7에 표시된 것처럼 각 독립 엔터티에서 수행한 중복 정리 호출도 제거합니다.
목록 7.DirtyRectManager
将脏矩算法集成到渲染循环, 这要求재进行渲染调사용지前调用清单 7中的管理器。将实体添加到管理器,管理器可以는 清除时计算清除矩형의 각도에 맞춰져 있습니다.会产生预期的优化,但根据游戏循环,管理器能够针对游戏循环进行优化,如图 8所示。
图 8.绘区域
이것은 완전히 불가능하며, 더 이상 정의할 수 없습니다.认会将image素放在该区域中,不需要考虑该区域中的原始渲染. 🎜> 통상적인 중대형 네트워크, 您已经有效地为层및它们所包含的实体找到优化策略.
结束语
对画布进行分层是一个可以应用于所有交互式实时场景的优化策略。析场景 的 重绘区域来考虑场景如何 重叠这些区域。 一些场景是具画布的良好候选.如果您需要粒子系统或大樹分理对象碰撞는 一起,对画布进行分层可能是一个很好的优化选择。