Vol. III · 2026 · 본문 Entry

8. Lambert와 ShaderLab

URP Pass tags: LightMode (ShaderTag)


Unity가 주어진 프레임 동안 패스를 실행할지,

프레임 동안 Unity가 패스를 실행하는 시기 및 Unity가 출력으로 수행하는 작업을 결정하는 데

사용하는 미리 정의된 패스 태그입니다.

조명의 모드와는 상관없습니다.

“LightMode” = “[value]” 형식으로 사용하며,

유니티에서 기본적으로 사용하는 태그는 다음과 같습니다.

Untitled

Custom LightMode

이걸 이제 마음대로 설정해서 사용할 수 있습니다.

ShaderLab에서 사용하는 기능이므로 HLSLPROGRAM 정의 전에 설정합니다.

Untitled

그다음 렌더설정을 합니다.

일단 기본렌더링에서 Prop을 제외합니다.

시각적으로 확실한 테스트를 위해서요.

Untitled

그다음 렌더설정을 합니다.

Untitled

그러면 깊이검사가 큰 값들은

Untitled

다음과 같이 CustomPass라고 명명한 태그를 사용한

다른 패스를 사용해서 그릴 수 있음을 확인할 수 있습니다.

ShdaerLab Properties Attribute


대략적인 구성에 대한 내용은 저번주차에서 했으니 넘어가겠습니다.

hlsl Anatomy 2.png

[MainColor]와 [MainTexture]는 무엇일까요? 이런 [어쩌구]를 보통 Attribute라고 일컫습니다.

정리해보면 다음과 같습니다

[Gamma]

float 또는 vector 속성이 sRGB 값을 사용함을 나타냅니다.

즉, 프로젝트의 색상 공간에서 이를 요구하는 경우 다른 sRGB 값과 함께 변환해야 합니다.

[HDR]

텍스처 혹은 색상속성이 HDR을 사용함을 나타냅니다.

텍스처 프로퍼티의 경우 LDR 텍스처가 할당되면 Unity 편집기에 경고가 표시됩니다. 

색상 프로퍼티의 경우 Unity 편집기는 HDR 색상 선택기를 사용하여 이 값을 편집합니다.

[HideInInspector]

말 그대로 인스펙터에서 표시하지 않습니다.

[MainTexture] & [MainColor]

코드나 애니메이터 등에서 머테리얼에 접근하면 몇가지 수정할 수 있는 값들이 있습니다.

바로 Material.mainTextureMateria.color입니다.

기본값은 _MainTex와 _Color 로 선언된 프로퍼티지만, 해당 어트리뷰트를 통해 대상을 변경할 수 있습니다.

중복 사용시 처음 사용된 프로퍼티를 적용합니다.

[NoScaleOffset]

이 텍스처 속성에 대한 타일링 및 오프셋 필드를 숨기도록 Unity 편집기에 지시합니다.

_BaseMap_ST를 적용하지 않을 때, 애초에 숨겨버리자는 것이죠.

[Normal]

텍스처 속성에 노멀 맵이 필요함을 나타냅니다.

호환되지 않는 텍스처를 할당하면 Unity 에디터에 경고가 표시됩니다.

[PerRendererData]

텍스처 프로퍼티가 렌더러별 데이터에서 MaterialPropertyBlock 형태로 나올 것임을 나타냅니다.

머티리얼 인스펙터는 이러한 속성을 읽기 전용으로 표시합니다.


Tags

RenderPipeline tag

“RenderPipeline” = “[name]”

이것에 대해서는

UniversalRenderPipeline,HighDefinitionRenderPipeline 등이 될 수 있습니다.

Queue

“Queue” = “[queue name]”

“Queue” = “[queue name] + [offset]”

과 같은 형식으로 사용합니다. 강의에는 숫자도 넣을 수 있다고 말씀하셨는데.. 잘 모르겠습니다?

Untitled

아무튼 해당하는queue name은 익숙한 그것들입니다.

Background (1000)

Geometry (2000)

AlphaTest (2450)

여기까지 불투명(2500이하)

Transparent(3000)

Overlay(4000)

즉 “Queue” = “Transparent+5”

이런식으로 선언할 수 있다는 것입니다.

RenderType

“RenderType” = “[renderType]”

어떤방식으로 렌더링 할 것인지를 지정합니다.

대게 Opaque, Transparent를 사용하며, 기타 아래의 것들이 존재합니다.

Untitled

여기부터는 이제 살짝 쓸모없습니다.

ForceNoShadowCasting

“ForceNoShadowCasting” = “[boolean]”

그림자를 받을지에 대한 여부입니다.

기본값은 false이며, true로 한다면 Forward(URP,HDRP-Forward), Legacy Vertex Lit(레거시 렌더파이프라인의 버텍스라이트), Legacy Deferred에서 그림자를 받는걸 방지합니다.

DisableBatching

“DisableBatching” = “[state]”

DynamicBatching을 방지합니다.

모델링 공간에서 연산을 처리할땐 필요할 수 있습니다.

IgnoreProjector

“IgnoreProjector” = “[boolean]”

true로 설정하면 프로젝터의 영향을 받지 않습니다.

PreviewType

“PreviewType” = “[shape]” (Sphere, Plane, Skybox)

유니티 에디터에서 보여지는 프리뷰의 형태를 결정합니다..

CanUseSpriteAtlas

“CanUseSpriteAtlas” = “[boolean]”

원본 텍스처 좌표에 의존하므로, 스프라이트 패킹(텍스쳐 아틀라스를 제작)을 할 경우 텍스쳐 좌표가 꼬여 이상해 질 수 있습니다.

따라서 해당 서브쉐이더를 사용하는 스프라이트는 패킹되지 않습니다

Lambert


패스를 배웠으니 써먹어 볼 것 입니다.

Untitled

1.라이트를 가져와야합니다.

2.노말을 가져와야합니다.

3.끝났네요.

자 하나하나 해봅시다.

라이트는 어디에 있나 하니

Untitled

RealtimeLights.hlsl에 들어있습니다.

가져옵니다.

컴파일오류를 냅니다

Untitled

대충 읽어보니 undeclared identifier ‘LerpWhiteTo’ 라고합니다.

저 함수는 무엇일까요?

Untitled

UnityStandardUtils를 가져오지 못한 것 같습니다.

그런데 저함수만 있으면 되는게 아닌가?

복붙해서 구현합니다.

그다음은 뭐.. IA에서 가져온 오브젝트의 노말 정보를 버텍스 쉐이더에서 빛과 연산한 다음,

Varyings을 통해 버텍스 쉐이더에서 픽셀 쉐이더로 TEXCOORD1을 사용해 이동합니다.

대충 곱합니다.

Pass
{
    Name "Lambert"
    Tags {"LightMode" = "Lambert"}
    
    HLSLPROGRAM
    #pragma vertex vert
    #pragma fragment frag
    
    //RealtimeLights.hlsl -> Shadows.hlsl throw Exception : undeclared identifier 'LerpWhiteTo' (UnityStandardUtils)
    //therefore. declare LerpWhiteTo (*^^*)
		//사실 Lighting.hlsl을 include하면 됩니다
    half3 LerpWhiteTo(half3 b, half t)
    {
        half oneMinusT = 1 - t;
        return half3(oneMinusT, oneMinusT, oneMinusT) + b * t;
    }

    //include
    #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"

		//for Get Main Light
    #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/RealtimeLights.hlsl"
    
    struct Input
    {
        float4 vertex : POSITION;
        float2 uv : TEXCOORD0;
        float3 normal : NORMAL;
    };

    struct Varyings
    {
        float2 uv : TEXCOORD0;
        float4 vertex : SV_POSITION;
        float diffuse : TEXCOORD1;
    };

    //properties
    TEXTURE2D(_MainTex);
    SAMPLER(sampler_MainTex);
    

    //constant buffer
    CBUFFER_START(UnityPerMaterial)
        float4 _MainTex_ST; //scale.x,scale.y,offset.x,offset.y
    CBUFFER_END

    Varyings vert(Input v)
    {
        Varyings o;
        o.vertex = TransformObjectToHClip(v.vertex);
        o.uv = TRANSFORM_TEX(v.uv, _MainTex);

        //getLightDirection
        Light mainLight = GetMainLight();
        float3 worldNormal = TransformObjectToWorldNormal(v.normal);
        float nDotl = dot(worldNormal, mainLight.direction);

        o.diffuse = saturate(nDotl);
        return o;
    }

    half4 frag(Varyings IN) : SV_Target
    {
        half4 color = SAMPLE_TEXTURE2D(_MainTex, sampler_MainTex, IN.uv);
        float diffuse = ceil( IN.diffuse * 4 ) * 0.25f;
        color *= diffuse;
        return color;
    }
    ENDHLSL
}
텍스처의 색상만 렌더링 했을 때
텍스처의 색상만 렌더링 했을 때
램버트 라이팅 모델 적용
램버트 라이팅 모델 적용
돌려봄
돌려봄

참조


https://docs.unity3d.com/Manual/SL-PassTags.html

https://docs.unity3d.com/Manual/SL-SubShaderTags.html

https://docs.unity3d.com/2021.2/Documentation/Manual/SL-Properties.html

https://docs.unity3d.com/Packages/com.unity.render-pipelines.universal@11.0/manual/urp-shaders/urp-shaderlab-pass-tags.html#urp-pass-tags-lightmode