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
'GRAPHICS PROGRAMMING' 카테고리의 다른 글
PBR Neutral Tone Mapping 코드 해설. (1) | 2025.05.28 |
---|---|
헤어 메시카드의 버텍스 소팅과 SIMD 프로그래밍 토론 기록 (5) | 2025.05.13 |
VXGI for advanced render mode on mobile devices (0) | 2025.04.15 |
바인딩(Binding)과 바이닝(Binning) (0) | 2025.03.16 |
UNROLL (2) | 2025.03.09 |