URP 셰이더는 이전에 말씀드린대로, 레거시의 서피스 셰이더를 버리고 정통파의 HLSL(High Level Shader Language) 방식의 셰이더를 채택했어요. 뭐 사실 그래도 ShaderLab이라고 하는 유니티 스크립트 껍데기 사이에 감싸진 HLSL 이지만 말이죠
이걸 다시 보실 때가 되었군요. 저기서 Pass 안의 HLSLPROGRAM ~ ENDHLSL 까지가 진짜 셰이더 코드고요, 나머지는 다 'ShaderLab' 이라 불리는 유니티 자체 스크립트입니다.
여기 말이죠. 그래서 여기 안에서는 전부 구문마다 ; 가 붙어 있지요? 밖에는 없는데 말이죠. 즉 저 영역 안이 진짜 셰이더 코드라는 것을 알 수 있습니다.
이렇게 유니티 자체 스크립트인 ShaderLab으로 짜는 방식으로 하면 좋은건, 유니티의 특성인 '멀티 플렛폼' 에 대응되기 좋은 방식입니다. 우리가 이 방식으로 하나만 짜두면, 유니티가 알아서 여러 플렛폼 (엑박이나 모바일, PC , 맥, PS4, 스위치 등등) 의 셰이더를 자동으로 변환 생성해 주기 때문이죠
셰이더는 기본적으로 vertex 셰이더와 fragment 셰이더로 이루어져 있습니다. fragment 셰이더는 'pixel' 셰이더라고도 부르는데, 이게 더 알아듣긴 편할지도 모르겠어요. 어쨌건 저기는,
지금부터 vertex 셰이더 함수 이름은 vert 로 하겠다. 그리고 fragment 셰이더 함수 이름은 frag로 하겠다
라고 써 있는 겁니다. 이렇게 맨 처음에 선언해 주도록 되어 있어요.
뭐 기초이므로 이 사이에 있는 지오메트리나 헐 도메인 그런건 패스..
#include
다음은 include 인데요, 저 인클루드에 선언되어 있는 코드를 찾아가서 직접 보면 와...
이런 코드가 열리는데요, 즉 이건 이 긴 코드가 우리 코드에 포함된다 (include) 된다는 얘기입니다. 각종 선언이나 함수명 등등이 정의되어 있지요. 게다가 저 위에 보면 또 #include 들이 보입니다. 즉 저기에 있는 수많은 코드들도 다 같이 주렁주렁 보따리에 싸서 가지고 오겠다는 뜻.
즉 우리가 셰이더에서 편하게 쓸 수 있는 각종 변수나 함수, 선언들이 주렁주렁 선물보따리로 묶여서 가지고 들어오겠다 라는 뜻입니다.
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl" 이 한 줄에 말이죠. 매우 파워풀하고 든든한 동료가 생긴 느낌적인 느낌!!!
내 코드에 흑염룡이 있다
struct Attributes -> vert -> struct Varings -> frag
자 그 다음은 버텍스의 입력구조체 -> 버텍스 셰이더 -> 버텍스 출력구조체 -> 프레그먼트(픽셀) 셰이더 의 구조를 볼께염. 구조체는 잘 모르겠으면 '보따리' 나 '가방 ' 정도로 생각하면 쉽습니다. 안에 쓸모있는게 잔뜩 들어 있는.
일단 버텍스가 가지는 데이터는 일반적으로 인덱스, 위치, 노말, 탄젠트, 칼라, UV(Texcoord) 들인데, 지금은 기초이므로 버텍스에게서 Position 만 받아와서 Attributes 라고 하는 구조체에 넣어 놨습니다. 나중에는 다른것도 많이 쓸 거예염.
그리고 이 구조체는 Vetex Shader 함수의 입력값, IN으로 들어갑니다.
이제 버텍스 셰이더에서 이 구조체 안의 정보를 사용하려면 IN.을 쓰고 정보를 부르면 되는 겁니다. IN.positionOS 처럼 말이죠. 이름앞에 호 붙이는 느낌으로
그리고 지금은 IN.positionOS.xyz 를 받아와서, TransformObjectToHClip 함수를 통해 Position을 homogenous clip space 로 바로 변환한 것을 볼 수 있습니다. (버텍스의 오브젝트 -> 월드 -> 뷰 -> 프로젝션 좌표계 변환입니다. 마지막 공간을 클립스페이스라고도 하지요. ... 자세한 이론은 역시 책을 참고하세요 )
그리고 버텍스 셰이더에서 계산이 끝난 값을 받아올 Varyings 라는 구조체를 만들고,
버텍스 셰이더는 이 구조체에 OUT 하도록 만들어 주는 겁니다. 이 Varyings 구조체에 나중에 추가적인 값을 버텍스 셰이더에서 연산해서 넣어주면 fragment 셰이더에서도 받아올 수 있습니다. 지금은 뭐 받아올게 없네요 .
그래서 fragment 셰이더 함수의 입력값은 비어 있습니다. 받아올게 없으니까요. 즉 버텍스 셰이더는 가장 기본적인, 없으면 안되는 , 버텍스 포지션 변환만 완료한거고 픽셀 셰이더 (fragment Shader) 에서는 customColor 라고 하는 float4 변수를 만들어서 0.5, 0, 0, 1 이라고 하는 '약간 어둡게 붉으면서 불투명한 ' 색을 만들어서 return으로 출력하게 되는 것입니다.
프로그래밍 기본은 안다고 생각하고 설명하였습니다. 역시 책을 한 번 대충이라도 떼셨다고 생각을...
댓글