본문 바로가기
공허의 유산/표현의 자유

[Unity3D/Shader] 02. Editor UI와 연동하는 Property

by 바른생활머시마 2023. 2. 19.
728x90
반응형

유니티 환경에서 쉐이더에 대해서 알아보기 위해 기본 환경을 구축하였습니다.

https://learn-and-give.tistory.com/71

 

[Unity3D/Shader] 01. 기본 환경 준비

최근에 GLSL에 대해 리뷰를 해왔습니다. https://learn-and-give.tistory.com/12 [opengl].[#2.GLSL] 01. OpenGL 1.1 기반의 랜더링 최신의 OpenGL과 Shader를 사용하기 위해 glew 연동까지 준비가 되었습니다. 1. 기본 랜더

learn-and-give.tistory.com

 

작성한 쉐이더 코드에서 빨간색이 보이도록 설정했던 부분은, 알베도라는 속성을 설정하는 것으로 구현이 되었는데, 알베도 외에도 다양한 속성들이 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

 

ShaderLab: 머티리얼 프로퍼티 정의 - Unity 매뉴얼

이 페이지는 ShaderLab 코드에서 Properties 블록을 사용하여 셰이더 오브젝트의 머티리얼 프로퍼티를 정의하는 방법에 대한 정보를 포함합니다.

docs.unity3d.com

 

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를 이용해서 제어를 할 수 있겠죠? 당연히? 아마도?

https://youtu.be/gtEyXqkzggc

 

반응형

 

슬라이더를 이용한 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] 03. SurfaceOutputStandard 맛보기

앞에서 Property에 대해서 알아보았습니다. [Unity3D/Shader] 02. Editor UI와 연동하는 Property (tistory.com) [Unity3D/Shader] 02. Editor UI와 연동하는 Property 유니티 환경에서 쉐이더에 대해서 알아보기 위해 기본

learn-and-give.tistory.com

 

728x90
반응형

댓글