유니티 환경에서 쉐이더에 대해서 알아보기 위해 기본 환경을 구축하였습니다.
https://learn-and-give.tistory.com/71
작성한 쉐이더 코드에서 빨간색이 보이도록 설정했던 부분은, 알베도라는 속성을 설정하는 것으로 구현이 되었는데, 알베도 외에도 다양한 속성들이 SurfaceOutputStandard에 포함되어 있습니다. 결과적으로는 이런 저런 계산을 다 한 후에 SurfaceOutputStandard에 적절한 값을 넣어주는 것이 우리가 Unity환경의 쉐이더 코딩에서 할 일입니다. 그러기 위해서, 입력과 출력이 무엇인지 잘 이해해야 되겠습니다.
Unity Custom Shader의 입력
우선, 앞장에서 사용했던 샘플 코드를 보면서 입력을 살펴보겠습니다.
Shader "Custom/NewSurfaceShader"
{
Properties
{
_Color ("Color", Color) = (1,1,1,1)
_MainTex ("Albedo (RGB)", 2D) = "white" {}
_Glossiness ("Smoothness", Range(0,1)) = 0.5
_Metallic ("Metallic", Range(0,1)) = 0.0
}
SubShader
{
Tags { "RenderType"="Opaque" }
LOD 200
CGPROGRAM
// Physically based Standard lighting model, and enable shadows on all light types
#pragma surface surf Standard fullforwardshadows
// Use shader model 3.0 target, to get nicer looking lighting
#pragma target 3.0
sampler2D _MainTex;
struct Input
{
float2 uv_MainTex;
};
half _Glossiness;
half _Metallic;
fixed4 _Color;
// Add instancing support for this shader. You need to check 'Enable Instancing' on materials that use the shader.
// See https://docs.unity3d.com/Manual/GPUInstancing.html for more information about instancing.
// #pragma instancing_options assumeuniformscaling
UNITY_INSTANCING_BUFFER_START(Props)
// put more per-instance properties here
UNITY_INSTANCING_BUFFER_END(Props)
void surf (Input IN, inout SurfaceOutputStandard o)
{
// Albedo comes from a texture tinted by color
fixed4 c = tex2D (_MainTex, IN.uv_MainTex) * _Color;
o.Albedo = float3(1,0,0);
o.Alpha = c.a;
}
ENDCG
}
FallBack "Diffuse"
}
크게 나눠보면, Property, surf함수, 그 외 부분으로 나눠 볼 수 있습니다.
이번에 살펴 볼 것은 Property 부분입니다.
Properties
{
_Color ("Color", Color) = (1,1,1,1)
_MainTex ("Albedo (RGB)", 2D) = "white" {}
_Glossiness ("Smoothness", Range(0,1)) = 0.5
_Metallic ("Metallic", Range(0,1)) = 0.0
}
이 부분이 Unity에서 Shader 사용을 매우 편리하게 해 주는 부분인 것 같습니다.
Property 내에 선언 된 각 속성들은 하나 하나가 Unity Editor에서 해당 Shader가 적용 된 Material의 Inspector에 보여지는 UI로 표현됩니다.
쉐이더는 Inspector에서 속성들이 코드처럼 나열되어 보이고,
쉐이더가 적용 된 Material에서는 Property에 작성 된 코드에 따라 속성을 설정하는 UI가 만들어 집니다.
Property의 코드와 Material에 보이는 UI를 보면 어떤 것이 어떻게 쓰이는지 어렵지 않게 이해 됩니다.
Property 표현 형식
Property 표현 형식은 다음과 같습니다.
_Name("display name", UI Control 정보 ) = 초기값
아래 링크 자료에 관련 된 내용이 잘 정리되어 있는데, 양이 좀 되니 일단은 간단하게 형식 정도만 이해하고 진행하는 것도 나쁘지 않을 것 같습니다. 나중에 필요할 때 다시 찾아보면 되니까요.
https://docs.unity3d.com/kr/2021.3/Manual/SL-Properties.html
Color은 ColorPicker UI가 나오고,
2D는 이미지 입력이고,
Range는 Slider를 이용해서 값을 설정하는 UI이네요.
Property의 사용
그럼 이렇게 UI로 설정되는 값은 어떻게 사용해야 할까요??
기본 코드를 보면 잘 나타나 있습니다.
Color만 한번 살펴 보겠습니다.
Shader "Custom/NewSurfaceShader"
{
Properties
{
_Color ("Color", Color) = (1,1,1,1)
...
}
SubShader
{
...
fixed4 _Color;
...
void surf (Input IN, inout SurfaceOutputStandard o)
{
fixed4 c = tex2D (_MainTex, IN.uv_MainTex) * _Color;
o.Albedo = float3(1,0,0);
o.Alpha = c.a;
}
ENDCG
}
FallBack "Diffuse"
}
Properties에 정의 된 속성은 SubShader 내에서 변수의 선언처럼 같은 이름으로 따로 선언이 됩니다. 그 후, surf 함수에서 그 이름으로 사용 됩니다.
이 과정을 GLSL 공부했던 것에 맵핑 해 보면(GLSL이 나름대로 좀 정리가 된 상태라면..) 조금 더 쉽게 이해 할 수 있을 것 같아요.
즉, Property는 쉐이더 외부에서 쉐이더의 uniform 변수 핸들을 얻어오는 부분이고,
SubShader 내부의 변수 선언은 쉐이더 내에서 uniform 변수의 선언에 해당하는 것으로 보면 되겠습니다.
(*surf 함수를 보면 Input IN이 있는데, 이것은 varying 변수라고 보면 될 것 같네요.)
위 코드를 보면 _Color로 얻어온 값을 텍스쳐에서 구해진 색상에 곱해주는 용도로 사용되었는데요,
실제로 이 값을 알베도에 할당해서 어떻게 되는지 한번 보겠습니다.
코드를 보면 알베도는 float3 형태로 3개 성분을 입력으로 받는데, _Color은 4개의 성분(rgba)입니다.
요건 쉐이더의 재미있는(?) 속성인데, 변수 뒤에 각 성분을 나열하면 해당 성분으로 벡터가 조합됩니다. 즉, _Color의 rgb 성분만 넘기려면 _Color.rgb라고 하면 됩니다.
surf 코드를 아래와 같이 고쳐보겠습니다.
void surf (Input IN, inout SurfaceOutputStandard o)
{
// Albedo comes from a texture tinted by color
fixed4 c = tex2D (_MainTex, IN.uv_MainTex) * _Color;
o.Albedo = _Color.rgb;
o.Alpha = c.a;
}
테스트를 해보면, Play를 하지 않은 Editor 상태에서도 적용이 되는 것을 볼 수 있습니다. Play 상태에서도 Script를 이용해서 제어를 할 수 있겠죠? 당연히? 아마도?
슬라이더를 이용한 Range나 그냥 입력하는 것이나, Texture를 입력하는 것이나 다 같은 방법입니다.
Texture의 경우, 우리가 Texture 좌표를 따로 설정하지 않았는데, 어떻게 되는 것일까요??
작동하는 모습을 보면 대표적인 유형으로 아마도 셋팅이 되어 있을 것으로 생각 됩니다.
GLSL에서 Texture를 쓰려면 또 여러가지 준비를 했어야 했는데, 여기서는 간단히 테스트 해 볼 수 있겠네요.
코드를 아래와 같이 수정하여 텍스쳐 색상에 선택한 색상이 섞이게 해보면, GLSL 테스트때 했던 샘플을 쉽게 만들 수 있습니다. Project 창에 GLSL에서 사용했던 이미지를 추가하고, 그것을 다시 저 Property의 Texture 부분으로 Drag & Drop을 하고, 코드를 아래와 같이 텍스쳐와 선택 색상의 곱으로 알베도를 설정하도록 수정합니다.
void surf (Input IN, inout SurfaceOutputStandard o)
{
// Albedo comes from a texture tinted by color
fixed4 c = tex2D (_MainTex, IN.uv_MainTex) * _Color;
o.Albedo = c.rgb;
o.Alpha = c.a;
}
결과는~
색상을 초록색 계통으로 선택을 해보면~
오브젝트를 육면체로 테스트 해보는 것도 매우 쉽습니다. 그냥 육면체를 추가하고, Material을 Drag & Drop하면 끝~!
GLSL에서 코드로 uniform 값을 전달하는 과정 또한 GUI를 만들면 이렇게 편리하게 할 수 있을 것입니다. 못하는 것은 아니죠. 다만 고단할 뿐인 것이니... 그렇게 고단하게 만드는 과정 자체도 대단히 의미가 있고 배울 것이 많으나, 쉐이더를 공부하는 입장에서 보면 효율성은 다소 떨어지고 활용도에서도 좀 아쉬운 부분이 있죠. 그래서, 이렇게 널리 쓰이는 툴 환경에서 공부를 하는 것이 (마음 한 구석 좀 쓰린 느낌이 있지만...) 좋은 것 같아요. GLSL에 대한 애착이 집착이 되지 않도록..ㅋ
Property로 입력하는 것은 이렇게 간단히 살펴 본 것으로 하고, 다음에는 surf에서 결과값으로 출력되는 SurfaceOutputStandard를 간단히 살펴보겠습니다. 일단 입출력을 이해하고 나면, 그것을 조정 해 가면서 공부를 할 수 있는 기본이 되고, 스스로 다른 방향의 공부도 해 볼 수 있으니까요.
https://learn-and-give.tistory.com/74
'공허의 유산 > 표현의 자유' 카테고리의 다른 글
[Unity3D/Shader] 04. 텍스쳐 맛보기 (2) | 2023.02.21 |
---|---|
[Unity3D/Shader] 03. SurfaceOutputStandard 맛보기 (0) | 2023.02.20 |
[Unity3D/Shader] 01. 기본 환경 준비 (0) | 2023.02.16 |
[3DReconstruction] 03.meshroom tutorial review(3) (0) | 2023.02.14 |
[3DReconstruction] 02.meshroom tutorial review(2) (0) | 2023.02.13 |
댓글