TECHARTNOMAD | TECHARTFLOWIO.COM

GRAPHICS PROGRAMMING

DualKwaseBlur

jplee 2025. 4. 22. 15:51
Shader "DualKwaseBlur"
{
    HLSLINCLUDE
#pragma exclude_renderers gles
#pragma multi_compile_local _ _USE_RGBM

#include "Packages/com.unity.render-pipelines.core/ShaderLibrary/Common.hlsl"
#include "Packages/com.unity.render-pipelines.core/ShaderLibrary/Filtering.hlsl"
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"
#include "Packages/com.unity.render-pipelines.universal/Shaders/PostProcessing/Common.hlsl"

    TEXTURE2D_X(_SourceTex);
    float4 _SourceTex_TexelSize;
    TEXTURE2D_X(_SourceTexLowMip);
    float4 _SourceTexLowMip_TexelSize;

    float4 _Params; // x: scatter, y: clamp, z: threshold (linear), w: threshold knee
    float _Offset;
#define Scatter             _Params.x
#define ClampMax            _Params.y
#define Threshold           _Params.z
#define ThresholdKnee       _Params.w

    half4 EncodeHDR(half3 color)
    {
#if _USE_RGBM
        half4 outColor = EncodeRGBM(color);
#else
        half4 outColor = half4(color, 1.0);
#endif

#if UNITY_COLORSPACE_GAMMA
        return half4(sqrt(outColor.xyz), outColor.w); // linear to γ
#else
        return outColor;
#endif
    }

    half3 DecodeHDR(half4 color)
    {
#if UNITY_COLORSPACE_GAMMA
        color.xyz *= color.xyz; // γ to linear
#endif

#if _USE_RGBM
        return DecodeRGBM(color);
#else
        return color.xyz;
#endif
    }

    struct v2f_DownSample
    {
        float4 vertex: SV_POSITION;
        float2 texcoord: TEXCOORD0;
        float2 uv: TEXCOORD1;
        float4 uv01: TEXCOORD2;
        float4 uv23: TEXCOORD3;
    };


    struct v2f_UpSample
    {
        float4 vertex: SV_POSITION;
        float2 texcoord: TEXCOORD0;
        float4 uv01: TEXCOORD1;
        float4 uv23: TEXCOORD2;
        float4 uv45: TEXCOORD3;
        float4 uv67: TEXCOORD4;
    };

    float2 TransformTriangleVertexToUV(float2 vertex)
    {
        float2 uv = (vertex + 1.0) * 0.5;
        return uv;
    }


    v2f_DownSample Vert_DownSample(Attributes v)
    {
        v2f_DownSample o;
        o.vertex = TransformObjectToHClip(v.positionOS.xyz);
        o.texcoord = TransformTriangleVertexToUV(v.positionOS.xy);

        
#if UNITY_UV_STARTS_AT_TOP
        o.texcoord = o.texcoord * float2(1.0, -1.0) + float2(0.0, 1.0);
#endif
        float2 uv = v.uv;////TRANSFORM_TEX(o.texcoord, _SourceTex);

        _SourceTex_TexelSize *= 0.5;
        o.uv = uv;
        o.uv01.xy = uv - _SourceTex_TexelSize * float2(1 + _Offset, 1 + _Offset);//top right
        o.uv01.zw = uv + _SourceTex_TexelSize * float2(1 + _Offset, 1 + _Offset);//bottom left
        o.uv23.xy = uv - float2(_SourceTex_TexelSize.x, -_SourceTex_TexelSize.y) * float2(1 + _Offset, 1 + _Offset);//top left
        o.uv23.zw = uv + float2(_SourceTex_TexelSize.x, -_SourceTex_TexelSize.y) * float2(1 + _Offset, 1 + _Offset);//bottom right

        return o;
    }

    half4 Frag_DownSample(v2f_DownSample i) : SV_Target
    {
        //SAMPLE_TEXTURE2D_X(_sourceTex,sampler_LinearClamp,i.uv) * 4;
        half4 sum = SAMPLE_TEXTURE2D_X(_SourceTex, sampler_LinearClamp, i.uv) * 4;
        sum += SAMPLE_TEXTURE2D_X(_SourceTex, sampler_LinearClamp, i.uv01.xy);
        sum += SAMPLE_TEXTURE2D_X(_SourceTex, sampler_LinearClamp, i.uv01.zw);
        sum += SAMPLE_TEXTURE2D_X(_SourceTex, sampler_LinearClamp, i.uv23.xy);
        sum += SAMPLE_TEXTURE2D_X(_SourceTex, sampler_LinearClamp, i.uv23.zw);

        return sum * 0.125;
    }


        v2f_UpSample Vert_UpSample(Attributes v)
    {
        v2f_UpSample o;
        o.vertex = TransformObjectToHClip(v.positionOS.xyz);
        o.texcoord = TransformTriangleVertexToUV(v.positionOS.xy);

#if UNITY_UV_STARTS_AT_TOP
        o.texcoord = o.texcoord * float2(1.0, -1.0) + float2(0.0, 1.0);
#endif
        float2 uv = v.uv;// TRANSFORM_TEX(o.texcoord, _SourceTex);

        _SourceTex_TexelSize *= 0.5;
        _Offset = float2(1 + _Offset, 1 + _Offset);

        o.uv01.xy = uv + float2(-_SourceTexLowMip_TexelSize.x * 2, 0) * _Offset;
        o.uv01.zw = uv + float2(-_SourceTexLowMip_TexelSize.x, _SourceTexLowMip_TexelSize.y) * _Offset;
        o.uv23.xy = uv + float2(0, _SourceTexLowMip_TexelSize.y * 2) * _Offset;
        o.uv23.zw = uv + _SourceTexLowMip_TexelSize * _Offset;
        o.uv45.xy = uv + float2(_SourceTexLowMip_TexelSize.x * 2, 0) * _Offset;
        o.uv45.zw = uv + float2(_SourceTexLowMip_TexelSize.x, -_SourceTexLowMip_TexelSize.y) * _Offset;
        o.uv67.xy = uv + float2(0, -_SourceTexLowMip_TexelSize.y * 2) * _Offset;
        o.uv67.zw = uv - _SourceTexLowMip_TexelSize * _Offset;

        return o;
    }

    half4 Frag_UpSample(v2f_UpSample i) : SV_Target
    {
        half4 sum = 0;
        sum += SAMPLE_TEXTURE2D_X(_SourceTex, sampler_LinearClamp, i.uv01.xy);
        sum += SAMPLE_TEXTURE2D_X(_SourceTex, sampler_LinearClamp, i.uv01.zw) * 2;
        sum += SAMPLE_TEXTURE2D_X(_SourceTex, sampler_LinearClamp, i.uv23.xy);
        sum += SAMPLE_TEXTURE2D_X(_SourceTex, sampler_LinearClamp, i.uv23.zw) * 2;
        sum += SAMPLE_TEXTURE2D_X(_SourceTex, sampler_LinearClamp, i.uv45.xy);
        sum += SAMPLE_TEXTURE2D_X(_SourceTex, sampler_LinearClamp, i.uv45.zw) * 2;
        sum += SAMPLE_TEXTURE2D_X(_SourceTex, sampler_LinearClamp, i.uv67.xy);
        sum += SAMPLE_TEXTURE2D_X(_SourceTex, sampler_LinearClamp, i.uv67.zw) * 2;

        return sum * 0.0833;
    }

        ENDHLSL

        SubShader
    {
        Tags{ "RenderType" = "Opaque" "RenderPipeline" = "UniversalPipeline" }
            LOD 100
            ZTest Always ZWrite Off Cull Off

            Pass
        {
            Name "DualKawaseBlur DownSample"

            HLSLPROGRAM
                #pragma vertex Vert_DownSample
                #pragma fragment Frag_DownSample
                #pragma multi_compile_local _ _BLOOM_HQ
            ENDHLSL
        }

            Pass
        {
            Name "DualKawaseBlur UpSample"

            HLSLPROGRAM
                #pragma vertex Vert_UpSample
                #pragma fragment Frag_UpSample
            ENDHLSL
        }
    }
}

엮어서 읽기.
https://techartnomad.tistory.com/m/312

SSAO and Kawase Blur

개인적으로는 SSAO 를 사용하지 않고 있고 이 전 프로젝트에서도 5년 전부터는 사용하지 않았습니다. 최근에는 GTAO 도 모바일 디바이스 게임개발 환경에서 자주 사용되고 있을 만큼 최적화가 되

techartnomad.tistory.com