[고도엔진 내부 쉐이더 공부] 쉐이더 구조 및 기본적인 쉐이더 개발 시작 - Whitmem
[고도엔진 내부 쉐이더 공부] 쉐이더 구조 및 기본적인 쉐이더 개발 시작
Game Development
2025-01-19 21:32 게시 bccf5cef8b0ada22d918

0
0
136
이 페이지는 외부 공간에 무단 복제할 수 없으며 오직 있는 그대로 게시되며 부정확한 내용을 포함할 수 있습니다. 법률이 허용하는 한 가이드 라인에 맞춰 게시 내용을 인용하거나 출처로 표기할 수 있습니다.
This page is not to be distributed to external services; it is provided as is and may contain inaccuracies.
canvas_item 쉐이더의 흐름 구조 알아보기
이 게시글에서는 고도 엔진에서 2D 씬 내의 쉐이더 종류중 하나인 canvas_item 이 어떤식으로 파이프라인으로 넘겨지는지에 대해 알아보고 정리한 게시글이다. 필자도 고도 엔진에서의 쉐이더는 처음 입문하는 수준이며, 기존 다른 언어의 쉐이더와 비교하여 어떤 차이점이 있는지를 바탕으로 습득한 뒤 정리하는 겸 서술한다.
참고 자료
고도 엔진 공식 문서 - Canvas Item Shader
쉐이더란
쉐이더는 그래픽스에서 어떤 정점이 존재할 때 그 정점의 내부를 어떻게 채울 것이고, 어떤 색상으로 채울 것인지 등 모든 처리를 담당한다. 우리가 Sprite2D 등을 이용해서 텍스처를 화면에 띄우는 것 조차 그래픽 내부에서는 기본 정의된 쉐이더를 통해 정점을 초기화하고 그 정점 사이에 텍스처를 어떻게 띄울 것인지 처리하는 작업이 쉐이딩 작업이라고 볼 수 있다. 우리는 엔진에서 제공되는 기본 쉐이더를 사용하고 있었기 때문에 그 동안 텍스처 등 화면을 띄우기 위해서 이미지를 딸칵 클릭하고 좌표를 단순히 드래그 하면 해당 좌표에 출력이 되었었다. 즉, 어디 좌표에 출력할 것인지, 어떤 화면으로 출력할 것인지 등 모든 처리는 쉐이더 단에서 보간을 하고 처리하는 과정을 통해 화면상에 출력된다.
위 공간은 게임의 월드 공간을 나타낸 것이다. 게임 개발을 입문하거나 처음하는 경우, 월드 공간이라니, 이게 무슨 말인가 싶을 것이다. 이 부분은 뒤에서 자세히 서술한다. 사실 위 이미지가 그대로 화면에 출력되는 공간이라고 가정한다.
조금더 이해하기 쉽도록 창으로 표시하였다. 게임이라는 창이 존재하고 게임 창의 제일 좌측 위가 0,0 으로 시작하는 하나의 새로운 좌표계가 있다고 가정한다. 아래로 내려갈수록, Y는 증가하고, 오른쪽으로 갈수록 X는 증가하는 좌표계이다. (이미지 좌표계와 동일하다고 가정한다.) 위 공간에서 우리가 네 개의 꼭짓점인 (1,1) (1,4) (3,4) (3,1) 이 존재할 때 이 각각의 정점을 기준으로 안에 어떤 이미지 파일을 그리고 싶다고 가정한다. 이미지는 맵이 될 수도 있고 캐릭터가 될수도 있고 이펙트가 될 수도 있다.
하지만 위 정점은 결국 실제 어떤 실선을 의미하는 것이 아니라 메모리 상의 정점 4개를 의미하는 것이고 시각적으로 표현한 것에 불과하기 때문에 실제 해당 좌표 사이에 색상으로 모두 채워주는 작업이 필요하다.
어떤 이미지 파일을 왼쪽 정점 사이 공간에 우겨넣기 위해서는 각각의 정점에 색상을 가져와서 칠해주는 작업이 필요하다.
우리가 이미지를 그리고 싶은 영역 4개의 꼭짓점은 각각 가져오려는 이미지의 좌표계에서 또 상대적이다. 그리는 공간은 너비 3, 높이 2인 비율이 3:2을 가지지만 막상 이미지 파일은 막상 세로 비율을 가지고 있는데다가 크기도 다르다. 이런 경우 이미지를 그대로 게임 화면의 좌표에 그대로 복사하는 것이 아니라 변형을 가해서 가져와야 한다.
따라서 그리는 영역 내부에 존재하는 각각의 모든 좌표에 대해서 각 좌표에 이미지의 어느 지점 좌표를 가져와야하는지 연산하고 해당 이미지 좌표의 색상을 그리는 영역의 좌표에 색칠하는 작업을 쉐이딩 처리하는 것이라고 볼 수 있다.
그런데, 수학 좌표계만을 다루던 사람들이라면, 여기서 의문을 가질 수 있을 것이다. 위 그리는 영역 4개의 꼭짓점 사이의 면에 존재하는 모든 정점들에 들어갈 색 지점을 가져와 칠한다고 했었는데, 4개의 꼭짓점 사이에 정점은 셀 수 없을 정도로 무한히 많은 것이 아닌가?라는 의문을 가질 수 있다.
우리가 최종적으로 화면상에 그리는 영역은 픽셀 화면(스크린) 좌표계이다. 즉 좌표계라고는 불렀지만 좌표계의 최소 단위는 1 픽셀이며, 1 픽셀이 1 거리이다. 즉 위 사진을 정말 스크린 좌표계라고 한다면 총 6개의 픽셀이 존재한다.
즉 위와 같은 경우는 실제 그리는 영역이 색을 가져와서 칠해보면 픽셀 영역이 6개 밖에 없기 때문에 사실상 이미지 표현이 불가능하다. 사실상 스크린 좌표 공간이 저렇게 작으면 게임 이 매우 작을 것이다. 위 이미지는 예시를 보여주기 위해 크게 그렸을 뿐 실제로 저러면 손톱만한 창 크기가 될 것이다. 아무튼 픽셀 단위로 존재하는 각 모든 사이 좌표에 대해 이미지에서의 좌표를 연산해 가져와 색을 칠한다.
스크린 좌표의 크기를 조금 현실적으로 키웠다. 스크린 좌표의 (100, 100) 는 이미지 좌표에서 (0, 0) 을 의미하고, 스크린 좌표의 (400, 300) 은 이미지 좌표에서 (38, 46) 지점을 의미한다. 우리는 각각 정점 정보를 알고 있기 때문에 선형 보간을 통해 스크린 공간의 특정 좌표가 이미지의 어떤 좌표 값을 가져와서 칠해야 할 것인지에 대해 연산도 수행해야 한다.
즉 각각의 객체에 대해서 각각의 쉐이딩 처리하는 것이며 각 객체마다 쉐이더가 존재할 수 있다. 각 객체는 4개의 꼭짓점을 가지고 있기 때문에 해당 꼭짓점의 사이를 보간해서 채워지는 색상 정보를 정의할 수 있는 것이다.
변환 행렬
위 섹션까지 이해 했으면 정점 처리 및 쉐이더 처리 원리의 절반은 이해한 것이다. 그런데 바로 쉐이더 프로그래밍에 들어가기에는 무리가 있다. 도대체 왜? 바로 게임 세계에는 카메라라는 개념이 존재하기 때문이다.
위 사진이 있다고 가정하자. 좌표의 원점은 좌측 위에 존재한다.
즉 위와 같은 상황이라고 볼 수 있다. 맵의 전체 공간인 월드 공간이 존재하고, 게임 화면에는 카메라 영역만 표시된다. 여기서 유의 해야할 것은, 위 사진에서 각 이미지의 좌표 (300, 300) 는 카메라 공간의 기준 좌표가 아니라 월드 공간의 기준 좌표이다. 즉 하늘색으로 칠한 카메라 영역 안에 저렇게 객체가 존재하더라도 객체는 월드 공간에 상대적으로 존재하는 좌표이다. 이 객체의 정점을 카메라 정점에서 볼때 비로소 우리가 아까 계산하던 (300, 300) 좌표는 카메라 공간을 기준으로는 약 (100, 100) 가 되고, 이 좌표를 비로소 화면 공간에 출력해야 한다.즉 월드 공간에 존재하는 객체의 각 정점 정보를 카메라 공간의 내부 좌표계로 옮겨야 한다. 카메라 공간의 x, y를 단순히 객체의 x, y에서 빼면 되겠으나, 카메라가 확대하거나 회전되어 있는 경우 계산이 매우 복잡해진다. 따라서 이런 경우를 위해 크기, 회전, 이동 정보를 모두 포함하는 행렬이 존재하고, 이 행렬을 곱하면 알아서 해당 공간으로 이동되는 연산이 존재한다. 그것이 바로 변환 행렬이다. 이런 변환 행렬은 우리가 직접 계산할 필요는 없고 쉐이더에 같이 넘어온다. 단순히 곱해서 넘겨주기만 하면 알아서 공간이 변환된다. 다만 어떤 벡터나 처리 연산을 할 때에는 같은 공간에서 수학적인 연산을 해야지 논리적인 오류가 발생하지 않는다.
고도 엔진의 2D 기본 쉐이더는 이러한 변환 행렬이 기본적으로 처리되어 파이프라인으로 들어가기 때문에 이런 행렬에 관여할 필요도 없는 경우가 많다.
쉐이더의 생성 방법
기본적으로 어떤 스프라이트가 존재하고 이 스프라이트에 텍스처를 한다고 가정한다. 텍스처는 38x46 사이즈로, ImageTexture 을 통해 로드된다.
이 상태에서 우측 Material 내의 Shader을 비어 있음을 눌러 새 Shader을 생성한다.
새셰이더를 추가한다. 이 때 모드 Canvas Item 으로 추가하는데 이 부분에 대한 자세한 설명은 추후 서술한다.
새 쉐이더가 생성된 것을 확인할 수 있다.
즉 방금 방법을 통해서 우리는 텍스처 이미지를 가지는 Sprite2D 객체에 CanvasItem 이라는 쉐이더를 새로 추가했다. 쉐이더는 정점이나 색상정보를 처리할 수 있는 그래픽쪽 프로그래밍이라고 보면되며, 사실 우리가 이렇게 텍스처를 추가한 작업 역시 고도 엔진 내부에서는 쉐이딩 처리를 통해 텍스처가 화면상에 출력되는 것이다.
다음 게시물부터는 이 내부에서 쉐이더 행렬이 어떻게 처리되는지 간단히 알아본다.
댓글 0개
댓글은 일회용 패스워드가 발급되며 사이트 이용 약관에 동의로 간주됩니다.
확인
Whitmemit 개인 일지 블로그는 개인이 운영하는 정보 공유 공간으로 사용자의 민감한 개인 정보를 직접 요구하거나 요청하지 않습니다. 기본적인 사이트 방문시 처리되는 처리 정보에 대해서는 '사이트 처리 방침'을 참고하십시오. 추가적인 기능의 제공을 위하여 쿠키 정보를 사용하고 있습니다. Whitmemit 에서 처리하는 정보는 식별 용도로 사용되며 기타 글꼴 및 폰트 라이브러리에서 쿠키 정보를 사용할 수 있습니다.
이 자료는 모두 필수 자료로 간주되며, 사이트 이용을 하거나, 탐색하는 경우 동의로 간주합니다.