오버레이 사용 시 성능 최적화를 위한 가이드입니다.
오버레이는 개별 DOM element를 포함하는 객체로, 생성/삭제가 잦을 경우 성능 부하가 큽니다.
따라서 클러스터링 시에도 생성/삭제보다는 show/hide 방식으로 가시성을 제어하는 것을 권장합니다.
이미 show/hide를 사용 중이라면, show/hide 시 오버레이가 사용하는 _onChange 이벤트를 함께 on/off 하면 추가적인 성능 향상이 가능합니다.
기본적으로 오버레이는 app change 이벤트(카메라 변경) 발생 시 오버레이가 출력될 위치를 갱신합니다.
hide 상태에서도 이벤트가 살아있으면 불필요한 계산이 매 프레임 발생하므로 성능 저하의 원인이 됩니다.
// show 할때 이벤트 등록
overlay.show();
app.on('change', overlay._onChange);
// hide 할때 이벤트 제거
overlay.hide();
app.off('change', overlay._onChange);
근본적으로는 화면에 출력되는 오버레이 개수를 최소화하는 것이 가장 중요합니다.
지도 레벨 별 클러스터링도 유효하지만, 카메라 프러스텀 밖에 있는 오버레이는 아예 출력하지 않는 방식이 가장 효과적입니다.
이를 위해 카메라 프러스텀과 오버레이 간의 교차 여부를 검사하는 코드를 사용해보길 추천드립니다.
아래 코드를 참고해주세요.
app.setRenderBefore('frustumCheck', frustumCheck);
function frustumCheck () {
const frustum = app._frustum;
const overlays = app.getOverlayList();
if(!frustum || !overlays || overlays.length ===0) return;
for(let t of overlays) {
const geo = t.getPosition();
const pos = app.geographicToVector3(geo); // 또는 t.point3D
if(frustum.containsPoint(pos)) {
t.show();
app.on('change', t._onChange);
} else {
t.hide();
app.off('change', t._onChange);
}
}
}
app.setRenderBefore 는 랜더링 시 호출되는 코드입니다 .
해당 함수에 원하는 키 명을 넣고, 콜백 함수를 등록하면 랜더 할 때 마다 자동으로 등록한 콜백 함수가 동작합니다.
app._frustum이 메인 카메라의 프러스텀이고, three.js의 Frustum을 상속 받습니다.
추가적으로 필요한 api가 있는경우 https://threejs.org/docs/#Frustum 문서를 참고하시면 도움이 될 것 입니다.
frustum.containsPoint(pos); 이 부분이 실제 교차여부를 판단하는 부분이고, pos는 반드시 3D 월드좌표 값이여야 합니다.
오버레이의 월드 좌표는 overlay.point3D 로 참조하거나,
overlay.getPosition() api를 활용해 위경도 좌표를 얻은후 이것을 app.geographicToVector3 api로 월드좌표로 전환해 얻을수 있습니다.
더 이상 프러스텀 교차 검사가 필요 없을때는 app.removeRenderBefor api를 사용해 제거해 줘야 부하가 없습니다.
app.removeRenderBefor('frustumCheck');
앞서 말한대로 프러스텀 교차 시 오버레이를 켜고, 이벤트를 켜고/ 교차 하지 않을때는 오버레이를 끄고, 이벤트도 제거하면 최적의 성능으로 오버레이를 사용하실 수 있습니다.
추가로 더 나은 성능을 위한 업데이트가 최신버전에서 제공될 예정입니다. 적용해보고 여전히 성능의 문제가 있다면 알려주세요.
|