Game Dev/Unity Shader

14. UsePass, GrapPass - 다니엘 릿 쉐이더 프로젝트

Septentrions 2025. 10. 18. 03:53

UsePass

UsePass 커맨드는 모든 렌더링 파이프라인에서 사용가능하며, 다른 쉐이더로 보내는(insert) 하는 커맨드이다.

이때, 패스는 특정한 이름으로써 넘겨진다. 당연하지만, 쉐이더 재사용성을 위함이다.

 

https://lucid-boundary.tistory.com/125

 

07. Depth Buffer 심화 (1) - 다니엘 릿 쉐이더 프로젝트

01. Depth Testing And Writing Depth Testing 하는 방식은 HLSL에서 커스터마이징 가능하다.여러가지 소개 전에 스탠다드한 "LessEqual" Depth Test에 대해 알아보려 한다. ZTest KeywordHLSL에서는 ZTest 라는 키워드를

lucid-boundary.tistory.com

 

Depth Buffer 관련 포스팅에서 CameraDepthTexture에 대해 다루었었다.

(04. Depth-Only Pass를 이용해서 Depth Texture 쓰기 (Writing))

유니티 내부에서 구현된 쉐이더 중 하나인 Depth-Only Pass는 우리의 쉐이더에 복사, 붙여넣기 해와서 기능을 그대로 사용한 것이다.

*#include "Packages/cohttp://m.unity.render-pipelines.universal/Shaders/DepthOnlyPass.hlsl" 이 부분을 말한 것 같다.

 

하지만 실제로 복사 붙여넣기를 해올 필요는 없다. UsePass가 있기 때문이다.

 

Name 키워드는 UsePass에서 접근하기 위해 유니티에서 제공해주는 키워드이다.

PassName은 Capital을 따른다.

Pass
{
	...
}

UsePass "Universal Render Pipeline/Unlit/DEPTHONLY"

 


GrabPass

GrabPass는 유니티가 이미 렌더링 완료된 오브젝트까지 포함하는 컬러 버퍼를 가져오도록 하고, 텍스처에 복사해서 우리의 쉐이더에 샘플링 가능하게 해주는 피쳐이다.

 

GrabPass 는 렌더링 파이프라인 어디서든 사용 가능하다. 그만큼 성능상의 비용은 커질 수 있다.

유니티는 샘플링 가능한 Scene Color Texture를 제공하지만, Opaque 오브젝트들이 모두 렌더링 된 후에 한 번만 생선된다.

 

GrabPass는 빌트-인에서만 사용 가능하다.

URP / HDRP 에서는 GrabPass를 우회해서 사용가능하다.

 


Sepia Tone Effect Using GrabPass

GrabPass { "_SceneColorTexture" }

Pass
{
	...
    
    sampler2D _SceneColorTexture;
    
    float4 frag(v2f i) : SV_Target
    {
    	const float3x3 sepia = float3x3
        {
        	0.393, 0.349, 0.272, //Red
            0.769, 0.686, 0.534, // Green
            0.189, 0.168, 0.131  // Blue
        };
        
        float2 screenUVs = i.positionSS.xy / i.positionSS.w;
        float3 sceneColor = tex2D(_SceneColorTexture, screenUVs);
        
        float3 outputColor = mul(sceneColor, sepia);
        
        return flaot4(outputColor, 1.0f);
    }


}

위 코드는 빌트-인 코드이다.

GrabPass에서 "_SceneColorTexture" 를 가져온다.

앞 서, 설명 했듯이 _SceneColorTexture는 모든 Opaque 오브젝트들이 렌더링 된 이후의 컬러 버퍼니까

스크린 전체를 텍스처에 담았다고 생각하면 된다.

screenUVs를 통해 쉐이더 오브젝트가 스크린 스페이스에 위치하는 UV를 가지고 텍스처 샘플링을 한다.

그리고, 컬러를 Sepia 톤으로 바꿔주도록 했다.

 

아쉽게도, URP 에서는 GrabPass를 사용할 수 없다.

대신에 _CameraDepthTexture 처럼, _CameraOpaqueTexture를 이용하여 접근 할 수 있다.

_CameraOpaqueTexture는 정확히 GrabPass처럼 모든 Opaque 오브젝트들이 렌더링 된 이후의 컬러 버퍼가 샘플링된 텍스처이다.

 

Opaque 오브젝트들이 끝난 이후이기 때문에, _CameraOpaqueTexture는 Transparent Shader에서만 사용 할 수 있다.

(그리고, Transparent 오브젝트들은 포함되지 않는다.)

내가 제일 싫어하는게 하위 호환인데.. 제약 조건이 좀 있다..

 

우선, URP Setting 에서 Opaque Texture를 체크하자.

이제 유니티에서 자동으로 _CameraOpaqueTexture를 쉐이더에 생성한다.

// 실제로 URP에서는 GrabPass를 사용하지 못한다.

Shader "Lucid-Boundary/GrapPassSepiaToneWithURP"
{
    Properties
    {

    }
    SubShader
    {
        Tags 
        { 
            "RenderType"="Transparent" 
            "RenderPipeline" = "UniversalPipeline"
            "Queue" = "Transparent"
        }

        Pass
        {
            Tags
            {
                "LightMode" = "UniversalForward"    
            }

            HLSLPROGRAM
            #pragma vertex vert
            #pragma fragment frag


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

            struct appdata
            {
                float4 vertex : POSITION;
            };

            struct v2f
            {
                float4 screenUV : TEXCOORD0;
                float4 vertex : SV_POSITION;
            };

            v2f vert (appdata v)
            {
                v2f o;
                o.vertex = TransformObjectToHClip(v.vertex.xyz);
                o.screenUV = ComputeScreenPos(o.vertex);
                return o;
            }

            float4 frag (v2f i) : SV_Target
            {
                const float3x3 sepia = float3x3 
                (
                    0.393f, 0.349f, 0.272f, // Red
                    0.769f, 0.686f, 0.534f, // Green
                    0.189f, 0.168f, 0.131f  // Blue
                );

                float2 scrUVs = i.screenUV.xy / i.screenUV.w;
                float3 sceneColor = SampleSceneColor(scrUVs);
                float3 outputColor = mul(sceneColor, sepia);
                return float4(outputColor, 1.0f);
            }
            ENDHLSL
        }
    }
}

세피아 톤이 적용된 2개의 오브젝트

Shader Graph에서 세피아 톤 이펙트 적용하기

쉐이더 그래프에서는 Scene Color Node가 지원된다.

이 방식은 URP의 _CameraOpaqueTexture와 거의 동일하게 동작하므로 URP 세팅에서 Opaque Texture를 체크하자.

 

Surface Type은 Transparent로 하자.

 


마치며

이번 포스티에서는 2개의 Pass에 대해 알아보았다.

셰이더는 흔히 정체되어있는 분야라고 하지만..

이 정도면 과거와 현재가 혼합되어있는게 아닌가 싶다..