render layer와 render group 설계
layer는 z-order만 뜻하지 않습니다. renderer에서는 업데이트 빈도, pass 분리, cache 단위까지 함께 생각해야 합니다.
render group을 만드는 코드
렌더링 목적과 갱신 빈도에 따라 group을 나눕니다.
function buildRenderGroups(snapshot) {
return [
{
name: "content",
camera: snapshot.camera,
items: snapshot.scene.nodes,
cacheable: true
},
{
name: "selection-overlay",
camera: snapshot.camera,
items: snapshot.selection,
cacheable: false
},
{
name: "debug-overlay",
camera: snapshot.camera,
items: snapshot.debug.enabled ? snapshot.debug.items : [],
cacheable: false
}
];
}
editor layer 예시
content layer
selection overlay
smart guides
DOM text input
debug overlay
content와 overlay는 같은 camera를 공유할 수 있지만, 같은 batch나 같은 cache 단위일 필요는 없습니다.
group 단위로 cache invalidation을 계산한다
function invalidateRenderGroups(groups, change) {
return groups.map((group) => {
if (group.name === "selection-overlay") {
return { ...group, dirty: change.type === "selection" || change.type === "camera" };
}
if (group.name === "content") {
return {
...group,
dirty: ["node", "asset", "camera"].includes(change.type)
};
}
return { ...group, dirty: true };
});
}
function renderGroups(renderer, groups) {
for (const group of groups) {
if (!group.dirty && group.cacheable) {
renderer.drawCachedGroup(group.name);
continue;
}
renderer.renderGroup(group);
}
}
selection만 바뀌었는데 content layer 전체를 다시 그리면 비용이 커집니다. render group은 cache와 invalidation의 단위로 설계해야 효과가 있습니다.
오늘의 핵심
render group은 “무엇이 위에 보이는가”보다 “무엇을 함께 렌더링하고 함께 갱신하는가”에 가깝습니다.