Godot 4용 3D 픽셀 아트 셰이더
스프라이트 시트에 구울 수 없는 것들이 있습니다. 3D 레벨 전체, 플레이어가 어디로든 몰고 다니는 탈것, 포즈가 백 가지인 보스. Pixor는 자신의 룩을 Godot 4 셰이더로 써 주므로, 이런 것들도 구워 낸 캐릭터와 같은 픽셀로 실시간으로 그려집니다.


3D 게임에서 픽셀 아트를 얻는 두 가지 방법
Godot 게임을 픽셀 아트처럼 보이게 하는 흔한 방법은 두 가지입니다. 첫째는 베이크입니다. 각 캐릭터를 모든 방향에서 스프라이트 시트로 렌더링하고 AnimatedSprite2D로 재생합니다. 둘째는 3D 장면 자체를 낮은 해상도로 그리는 것입니다. 빛을 띠로 나누고 색을 제한하고 외곽선을 그리는 셰이더를 거친 뒤 nearest 필터링으로 확대합니다. “3D pixel art shader Godot”이나 “Godot 4 post processing pixel art”라는 검색은 둘째 방법에 관한 것입니다.
각각 쓸 곳이 있습니다. 베이크한 시트는 직접 손볼 수 있는 통제력을 주고, 그리는 데 비용이 들지 않습니다. 실시간은 시트에 담을 수 없는 것을 처리합니다. 카메라가 지나가는 레벨, 어느 각도로든 도는 자동차, 모든 것이 한꺼번에 움직이는 장면입니다. 문제는 둘이 잘 맞지 않는다는 점입니다. 스프라이트는 한 파이프라인에서, 레벨은 따로 쓴 셰이더에서 나와 외곽선, 색, 빛이 어긋납니다.
pxr shader는 스프라이트를 구울 때 쓴 바로 그 스타일에서 Godot 셰이더를 써서 이 문제를 해결합니다.
셰이더 쓰기
모델과 룩, 또는 프로젝트를 지정하고, Godot 프로젝트 안의 폴더를 지정하세요.
pxr shader knight.glb --preset selout --size 64 -o my-game/pixor
pxr shader game.pixor -o my-game/pixor --res res://pixor
-o는 디스크상의 폴더이고, --res는 같은 폴더를 Godot이 보는 방식인 res:// 경로입니다. res:// 뒤에 폴더 이름이 붙는 경우가 아니면 지정하세요. 폴더에는 파일 다섯 개가 생깁니다.
| 파일 | 하는 일 |
|---|---|
pixor_look.gdshader |
머티리얼. 각 픽셀은 구운 스프라이트처럼 자기 색의 램프, 빛 띠의 단계, 하이라이트를 팔레트 자체의 색으로 가져갑니다. 셰이딩이 없으며, 룩이 곧 빛입니다. |
pixor_lines.gdshader |
선, 즉 화면 패스. 모델 주위 빈 픽셀에 실루엣을, 한 면이 다른 면 앞에 있는 곳에 안쪽 선을 스타일의 선 색으로 그립니다. |
pixor_view.tscn |
픽셀 격자. 스프라이트 크기의 뷰포트를 nearest 필터링으로 4배 확대하며, 그 안에 Pixor의 카메라와 선이 들어 있습니다. |
pixor_look.gd |
PixorLook.apply($Level)은 노드 아래 모든 메시에 룩을 입히며, 각 머티리얼의 색과 텍스처는 유지합니다. |
pixor_shader.json |
크기, 배율, 팔레트, 그리고 셰이더가 생략하는 스타일 항목. |
장면에 넣기
- 폴더를 Godot 프로젝트에 복사하거나,
-o로 곧바로 그곳에 쓰세요. - 메인 장면에
pixor_view.tscn을 추가하세요. 그 안에 있는 3D 월드를 픽셀 격자와 외곽선 패스를 거쳐 그려 줍니다. - 메시에 룩을 입히세요. 스크립트에서는
PixorLook.apply($Level)이 노드 아래 모든 메시에 머티리얼을 설정합니다. 직접 하려면 메시의 머티리얼에pixor_look.gdshader를 지정하세요.
따로 설정할 것은 없습니다. 명암 띠, 램프, 팔레트, 선 색이 모두 셰이더에 들어 있습니다. 룩을 바꾸려면 Pixor에서 바꾸고 pxr shader를 다시 실행하세요.
--view-scale은 아트 픽셀 하나가 화면 픽셀 몇 개가 될지 정합니다(기본값 4). 다른 픽셀 아트와 마찬가지로 정수로 두세요. 이유는 스프라이트 크기 가이드에 설명되어 있습니다.
실시간이 생략하는 것
실시간에서는 프레임을 구운 것과 같은 방식으로 그리되, 세 가지가 다릅니다.
- 캐스트 섀도 없음. 표면은 빛을 받고 띠로 나뉘지만, 한 오브젝트가 다른 오브젝트에 그림자를 드리우지는 않습니다.
- 깊이 차이가 없으면 부품 사이 선 없음. 소매와 팔처럼 맞닿은 두 부품은 한쪽이 다른 쪽 앞에 있는 곳에만 선이 생깁니다.
- 프레임 전체를 보는 단계 없음. 프레임 전체를 읽거나 프레임끼리 비교하는 단계, 예컨대 정리 단계와 그렇게 표시된 손그림 원자는 베이크할 때만 실행됩니다.
모든 스타일 노드는 실시간으로 실행되는지 알려 줍니다. pxr nodes --graph style은 노드마다 아래에 “in real time: yes” 또는 “not yet”을 출력합니다. 실시간으로 실행할 수 없는 노드가 그래프에 있는 스타일은 거부되며, 오류가 그 노드의 이름을 알려 줍니다. --partial을 붙이면 그 노드를 뺀 나머지 설정의 셰이더를 그래도 씁니다.
둘 다 쓰기
가장 강력한 구성은 양쪽을 모두 쓰는 것입니다. 손보기, 많은 프레임, 정확한 실루엣이 필요한 캐릭터는 시트로 베이크하세요(Pixor for Godot에 SpriteFrames와 바로 연결된 장면이 있습니다). 월드, 탈것, 구워 두기에는 너무 크거나 자유로운 것은 pxr shader로 그리세요. 둘 다 하나의 스타일에서 나오므로 램프, 띠, 팔레트를 공유하고, 플레이어는 두 게임이 아니라 하나의 게임을 봅니다.
2D 장면에서 빛에 반응해야 하는 스프라이트라면, 조명 키트(--export light-kit)가 Godot, Unity, GameMaker에서 구운 스프라이트를 노멀 맵으로 비추면서도 빛을 받은 모든 픽셀이 자기 램프 안에 머물게 합니다. 팔레트에 맞는 조명을 참고하세요. 실시간 셰이더의 모든 옵션은 매뉴얼의 해당 절에 있습니다.
질문
실시간 셰이더의 Unity나 Unreal 버전이 있나요?
아직 없습니다. pxr shader는 Godot 4 셰이더만 씁니다. Unity와 GameMaker에는 Pixor의 조명 키트가 엔진 안에서 구운 스프라이트를 팔레트 자체의 단계에 맞춰 비추며, 각각 셰이더가 있습니다.
실시간 룩이 구운 스프라이트와 똑같나요?
같은 램프, 명암 띠, 하이라이트, 팔레트를 씁니다. 캐스트 섀도, 깊이 차이 없이 맞닿은 부품 사이의 선, 프레임 전체를 읽거나 프레임끼리 비교하는 단계(정리 등)는 생략됩니다.
셰이더 파라미터를 직접 설정해야 하나요?
아니요. 룩은 셰이더 파일에 구워져 있고, 뷰 장면이 카메라와 선 패스를 담고 있으며, PixorLook.apply가 노드 아래 모든 메시에 머티리얼을 입히면서 각 메시의 색과 텍스처를 유지합니다.