texture atlas 기본
이미지나 glyph를 그릴 때 texture를 자주 바꾸면 비용이 커집니다. 작은 이미지들을 하나의 큰 texture에 모아두고, uv 범위만 다르게 쓰는 방법이 texture atlas입니다.
atlas rect를 uv로 바꾸는 코드
atlas 안의 pixel rect를 shader가 읽을 uv rect로 변환합니다.
function atlasRectToUv(rect, atlas) {
return {
u0: rect.x / atlas.width,
v0: rect.y / atlas.height,
u1: (rect.x + rect.width) / atlas.width,
v1: (rect.y + rect.height) / atlas.height
};
}
function pushAtlasQuad(vertices, node, uv) {
const x0 = node.x;
const y0 = node.y;
const x1 = node.x + node.width;
const y1 = node.y + node.height;
vertices.push(
x0, y0, uv.u0, uv.v0,
x1, y0, uv.u1, uv.v0,
x0, y1, uv.u0, uv.v1,
x0, y1, uv.u0, uv.v1,
x1, y0, uv.u1, uv.v0,
x1, y1, uv.u1, uv.v1
);
}
같은 atlas texture를 쓰는 quad는 같은 gl.bindTexture 상태로 이어서 그릴 수 있습니다. 이것이 atlas가 batching에 유리한 이유입니다.
atlas는 이미지 묶음이다
여러 작은 이미지를 하나의 큰 texture에 배치합니다.
atlas texture
icon A: x, y, w, h
icon B: x, y, w, h
glyph ㄱ: x, y, w, h
각 sub image는 atlas 안의 rect를 가집니다.
uv rect를 계산한다
atlas pixel rect를 0..1 uv 범위로 바꿉니다.
u0 = x / atlasWidth
v0 = y / atlasHeight
u1 = (x + width) / atlasWidth
v1 = (y + height) / atlasHeight
renderer는 node마다 이 uv rect를 vertex나 instance data로 보낼 수 있습니다.
atlas는 batching에 좋다
같은 atlas texture를 쓰는 image quad들은 texture bind를 바꾸지 않고 한 batch로 그릴 수 있습니다.
same shader
same texture atlas
many quads
text rendering에서도 glyph atlas를 쓰면 많은 글자를 같은 texture로 그릴 수 있습니다.
오늘의 핵심
texture atlas는 texture 전환을 줄이기 위한 렌더링 자료구조입니다.
many small images
-> one texture
-> many uv rects
-> fewer state changes
문서 모델에는 atlas packing 결과가 아니라 asset reference와 layout 정보가 남아야 합니다.