본문 바로가기
튜터리얼_스터디

(셰이더 그래프/HLSL)아티스트를 위한 URP 셰이더 Shader #1

by 대마왕J 2021. 7. 4.

셰이더 처음 만들기 (노드버전) 


그럼 맨 먼저 시작해 보죠. 이론 같은거야 좋은 책들이 많을테고, 여기 오시 분들은 그래요.. 서론 싫어하는거 다 안다고요... 하긴 저도 유투브에서 5분 설명할거 10분 서론 설명하는 강좌보면 막 빡치고 그래요. 

그러니 일단 무식하게 시작해 보도록 합시다 
여기서 할 일은 다음과 같습니다. 
셰이더를 만들고, 메터리얼에 적용시키고, 그걸 다시 오브젝트에 적용시킵니다. 
네 그래요. 별 것 아니죠. 그냥 빈 거 하나 만드는 겁니다. 겁내지 말고 따라해 봅시다. 

 

셰이더 만들기 

유니티 빈 화면에 공 하나 만드시고요 

Project 창에서 + 키를 누르고 Shader / Universal Render Pipelint/ Unlit Shader Graph 를 눌러줍니다. 
이름은 기본적으로 New Shader Graph 가 나옵니다만, 되도록이면 바꿔주는게 현명하겠죠. 이름은 알아보기 쉽게 써 주는 것이 국률입니다. 
하지만 전 게으르니까 그냥 이 이름으로 갑니다. 

Asset 폴더에서 오른쪽 클릭해서 Create.. 를 선택해도 됩니다. 취향껏.  

이 부분이 근데 버전마다 조금씩 달라요. 뭘 이리 자꾸 바꾸는지.. 

 

 

메터리얼 만들기

셰이더가 만들어졌으면, 메터리얼에 이 셰이더를 적용해 줘야 합니다. 

3Ds max 같은 프로그램을 다루셨던 분들에게는 익숙하지 않겠지만, 셰이더-> 메터리얼 -> 오브젝트 식으로 적용됩니다. 
언리얼도 3Ds Max 와 비슷한 느낌이지요. 저는 개인적으로 이렇게 셰이더와 메터리얼이 분리되어 있는 쪽이 좋다고 생각합니다. (한 셰이더가 여러 메터리얼에 들어가는 개념이 좋아서요) 

적용하는 법은, 셰이더를 만들때와 마찬가지로 + 버튼을 누르고 메터리얼을 생성한 후에, 아까 만든 셰이더를 메터리얼로 드래그엔 드롭 하는 방법도 있습니다만, 

아래처럼 아예 만들어진 셰이더를 잡고 오른클릭하면 메터리얼이 생성될 때 부터 그 셰이더가 적용된 채 태어난다는 장점이 있습니다. 

그 외에도 메뉴에서 선택하는 방법이 있는데 그건 나중에..

 

오브젝트에 메터리얼 적용하기. 

자 다시 설명할께요. 셰이더에 메터리얼이 적용되었습니다. 이제 그 메터리얼을 오브젝트에 적용시켜주면 되는 겁니다. 

Inspector에서 적용하는 법도 있지만 여기는 그게 중요한게 아니니까 간단하게 그냥 드래그엔 드롭으로 적용시켜 주도록 하지요

즉 정리하자면 이런겁니다. 셰이더 그래프를 만들고, 이를 메터리얼에 적용시키고, 이를 다시 오브젝트에 적용시킨다. 
제일 쉬운 적용 방법은, 그냥 드래그 엔 드롭하는 것이다. 

뭐 그렇다는 겁니다. 이러면 준비 완료입니다. 
야호 


셰이더 처음 만들기 (코드버전) 


이번에는 셰이더를 처음 만드는 코드 버전입니다. 위와 똑같습니다만 코드인게 다르죠 노드와는 다릅니다. 
노드만 보실 분들은 여길 보실 필요가 없습니다. 

노드와는 다르다! 노드와는!! 

 

코드로 만드는 것도 여기서는 매우 심플하고 쉬운 방향으로 시작해 보도록 하죠. 
좋은 이론을 배우는 것도 좋지만, 일단 흥미를 잃어버리면 그게 무슨 의미가 있겠습니까 ...? 

쉽게 시작하는 법은 다음과 같습니다. 

일단 이전과 똑같은 방법으로, 이번에는 셰이더를 하나 만드는데 

Shasder/Unlit Shader 를 하나 생성합니다. 

그럼 셰이더가 하나 생성이 되지요. 이름을 바꿔주면 더 좋겠지만 뭐 ...
일단 만들었으니 열어봅시다. 
VS 나 VScode 등을 이용해서 열어보면 다음과 같은게 열릴텐데요, 

Shader "Unlit/NewUnlitShader"
{
    Properties
    {
        _MainTex ("Texture", 2D) = "white" {}
    }
    SubShader
    {
        Tags { "RenderType"="Opaque" }
        LOD 100

        Pass
        {
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            // make fog work
            #pragma multi_compile_fog

            #include "UnityCG.cginc"

            struct appdata
            {
                float4 vertex : POSITION;
                float2 uv : TEXCOORD0;
            };

            struct v2f
            {
                float2 uv : TEXCOORD0;
                UNITY_FOG_COORDS(1)
                float4 vertex : SV_POSITION;
            };

            sampler2D _MainTex;
            float4 _MainTex_ST;

            v2f vert (appdata v)
            {
                v2f o;
                o.vertex = UnityObjectToClipPos(v.vertex);
                o.uv = TRANSFORM_TEX(v.uv, _MainTex);
                UNITY_TRANSFER_FOG(o,o.vertex);
                return o;
            }

            fixed4 frag (v2f i) : SV_Target
            {
                // sample the texture
                fixed4 col = tex2D(_MainTex, i.uv);
                // apply fog
                UNITY_APPLY_FOG(i.fogCoord, col);
                return col;
            }
            ENDCG
        }
    }
}

여하간 본론부터 말하자면 지금 셰이더는 이게.. URP 셰이더가 아니예요. URP 이전, 빌트인(레거시) 유니티의 셰이더입니다. 
뭐 그래도 사실 동작은 되는게, 프레그먼트로 짜여져 있는 기본 셰이더에 한해서는 빌트인 유니티 버전의 셰이더가 URP 에도 돌아 가기는 합니다만, 그게 제대로 돌아가는게 아니라서 사실 다시 짜 줘야 하는게 맞습니다. 


이래저래 복잡해서 고민하고 있던차에.. 고맙게도 유니티에서 예제를 공개했네요. 
https://docs.unity3d.com/Packages/com.unity.render-pipelines.universal@12.0/manual/writing-shaders-urp-basic-unlit-structure.html

 

URP unlit basic shader | Universal RP | 12.0.0

URP unlit basic shader This example shows a basic URP-compatible shader. This shader fills the mesh shape with a color predefined in the shader code. To see the shader in action, copy and paste the following ShaderLab code into the Shader asset. // This sh

docs.unity3d.com

예에이!!! 

그냥 간편하게 이걸 다 긁어 와서, 저 새로 만든 코드에 붙여 넣기만 하는 걸로 시작하겠습니다. 
아래 코드가 위 링크에 있는, 유니티가 공개한 기초 코드인데요. 이걸로 시작하면 되겠습니다. 
주석은 제가 일단 가볍게 번역해 봤어요. 
이걸 그대로 긁어서 저 셰이더 코드에 붙여넣기만 하면 됩니다. 

// 이 셰이더는 메쉬를 미리 지정된 칼라로 채우는 셰이더입니다 
Shader "Example/URPUnlitShaderBasic"
{
    // 유니티 셰이더의 프로퍼티 블럭(인터페이스를 만드는 곳)입니다. 지금은 비워놨습니다. 
    // 왜냐하면 프레그먼트 (픽셀) 셰이더 코드에서 출력 칼라를 걍 정의해 놨기 때문입니다 
    Properties
    { }

    // 섭셰이더 블럭에 셰이더 코드가 들어 있습니다 
    SubShader
    {
        // 섭셰이더 태그는 언제 어떤 조건에서 섭셰이더 블럭을 정의하는지 또는 
        //패스가 실행되는지를 정의합니다. (그냥 일종의 설정용 태그란 말입니다.) 
        Tags { "RenderType" = "Opaque" "RenderPipeline" = "UniversalPipeline" }

        Pass
        {
            // HLSL(High Level Shader Language) 코드 블럭입니다. SRP는 HLSL를 사용합니다 
            HLSLPROGRAM
            // 여기는 버텍스 셰이더의 이름을 정의하고요
            #pragma vertex vert
            // 여기는 프레그먼트(픽셀) 셰이더의 이름을 정의합니다. 
            #pragma fragment frag

            // Core.hlsl 파일에는 자주 사용되는 HLSL 메크로나 함수가 정의되어 있습니다. 
            // 그리고 이렇게 #include를 사용하면 다른 HLSL 파일들을 참조할 수 있습니다. 
            #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"

            // 이 구조체에는 어떤 변수가 들어 있는지 정의되어 있습니다. 
            // 이 예제에서는 Attributes 구조체를 버텍스 셰이더의 인풋 구조체로 사용하고 있습니다. 
            struct Attributes
            {
                // positionOS 변수는 오브젝트 스페이스의 버텍스 포지션을 가지고 있습니다 
                float4 positionOS   : POSITION;
            };

            struct Varyings
            {
                // 이 구조체의 포지션 변수는 반드시 SV_POSITION 시멘틱을 가지고 있어야 합니다. 
                float4 positionHCS  : SV_POSITION;
            };

            // 버텍스 셰이더는 Varyings의 요소로 정의됩니다. 
            // 버텍스 셰이더의 타입은 반드시 출력해 주는 구조체의 타입과 일치해야 합니다. 
            Varyings vert(Attributes IN)
            {
                //  Varyings 구조체로 출력(OUT) 선언을 해줍니다. 
                Varyings OUT;
                // TransformObjectToHClip 함수는 오브젝트 좌표계의 버텍스 포지션을 
                // 클립스페이스로 변환해줍니다. 
                OUT.positionHCS = TransformObjectToHClip(IN.positionOS.xyz);
                // output을 리턴해 줍니다. 
                return OUT;
            }

            // 프레그먼트 (픽셀) 셰이더 정의입니다. 
            half4 frag() : SV_Target
            {
                // 색상 정의하고 리턴해 줍니다. 
                half4 customColor = half4(0.5, 0, 0, 1);
                return customColor;
            }
            ENDHLSL
        }
    }
}

그리고 아까와 같이, 이 셰이더를 메터리얼에 적용해 주고, 메터리얼을 오브젝트에 적용해 주면 
이 그림과 같은 모습이 될 것입니다. 

이제 기초 준비는 끝났습니다. 정말로 준비만... 

위 코드가 필요하신분은 이걸 다운로드 받아주세요 

NewUnlitShader.shader
0.00MB

 

 

블로그 주인장에게 커피값을 후원할 수 있습니다! 

donaricano-btn

 

반응형

댓글