HDRP Custom Pass Post Effect Snippets
using
Unity 2020.1.0f1
HDRP 8.2.0
code:OutlinePass.cs
using UnityEngine;
using UnityEngine.Rendering.HighDefinition;
using UnityEngine.Rendering;
using UnityEngine.Experimental.Rendering;
public class OutlinePass : CustomPass
{
public LayerMask outlineLayer = 0;
public Color outlineColor = Color.black;
public float threshold = 1;
public float thickness = 1;
Shader outlineShader;
Material fullscreenMaterial;
MaterialPropertyBlock materialProperties;
ShaderTagId[] shaderTags;
RTHandle rtBuffer;
protected override void Setup(ScriptableRenderContext renderContext, CommandBuffer cmd)
{
outlineShader = Shader.Find("FullScreen/OutlinePass");
fullscreenMaterial = CoreUtils.CreateEngineMaterial(outlineShader);
materialProperties = new MaterialPropertyBlock();
// List all the materials that will be replaced in the frame
shaderTags = new ShaderTagId3 {
new ShaderTagId("Forward"),
new ShaderTagId("ForwardOnly"),
new ShaderTagId("SRPDefaultUnlit"),
};
rtBuffer = RTHandles.Alloc(
Vector2.one, TextureXR.slices, dimension: TextureXR.dimension,
colorFormat: GraphicsFormat.B10G11R11_UFloatPack32,
useDynamicScale: true, name: "Outline Buffer"
);
}
void DrawMeshes(ScriptableRenderContext renderContext, CommandBuffer cmd, HDCamera hdCamera, CullingResults cullingResult)
{
var result = new RendererListDesc(shaderTags, cullingResult, hdCamera.camera)
{
// We need the lighting render configuration to support rendering lit objects
rendererConfiguration = PerObjectData.LightProbe | PerObjectData.LightProbeProxyVolume | PerObjectData.Lightmaps,
renderQueueRange = RenderQueueRange.all,
sortingCriteria = SortingCriteria.BackToFront,
excludeObjectMotionVectors = false,
layerMask = outlineLayer,
};
CoreUtils.SetRenderTarget(cmd, rtBuffer, ClearFlag.Color);
HDUtils.DrawRendererList(renderContext, cmd, RendererList.Create(result));
}
protected override void Execute(ScriptableRenderContext renderContext, CommandBuffer cmd, HDCamera hdCamera, CullingResults cullingResult)
{
DrawMeshes(renderContext, cmd, hdCamera, cullingResult);
SetCameraRenderTarget(cmd);
materialProperties.SetColor("_OutlineColor", outlineColor);
materialProperties.SetTexture("_OutlineBuffer", rtBuffer);
materialProperties.SetFloat("_Threshold", threshold);
materialProperties.SetFloat("_Thickness", thickness);
CoreUtils.DrawFullScreen(cmd, fullscreenMaterial, materialProperties, shaderPassId: 0);
}
protected override void Cleanup()
{
CoreUtils.Destroy(fullscreenMaterial);
rtBuffer.Release();
}
}
code:OutlinePass.shader
Shader "FullScreen/OutlinePass"
{
HLSLINCLUDE
#pragma only_renderers d3d11 playstation xboxone vulkan metal switch #include "Packages/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/RenderPass/CustomPass/CustomPassCommon.hlsl" TEXTURE2D_X(_OutlineBuffer);
float4 _OutlineColor;
float _Threshold;
float _Thickness;
// Neighbour pixel positions
{
float2(1, 1),
float2(0, 1),
float2(-1, 1),
float2(-1, 0),
float2(-1, -1),
float2(0, -1),
float2(1, -1),
float2(1, 0),
};
float4 FullScreenPass(Varyings varyings) : SV_Target
{
UNITY_SETUP_STEREO_EYE_INDEX_POST_VERTEX(varyings);
float depth = LoadCameraDepth(varyings.positionCS.xy);
PositionInputs posInput = GetPositionInput(varyings.positionCS.xy, _ScreenSize.zw, depth, UNITY_MATRIX_I_VP, UNITY_MATRIX_V);
float4 color = float4(0.0, 0.0, 0.0, 0.0);
float luminanceThreshold = max(0.000001, _Threshold * 0.01);
// Load the camera color buffer at the mip 0 if we're not at the before rendering injection point
if (_CustomPassInjectionPoint != CUSTOMPASSINJECTIONPOINT_BEFORE_RENDERING)
color = float4(CustomPassSampleCameraColor(posInput.positionNDC.xy, 0), 1);
// When sampling RTHandle texture, always use _RTHandleScale.xy to scale your UVs first.
float2 uv = posInput.positionNDC.xy * _RTHandleScale.xy;
float4 outline = SAMPLE_TEXTURE2D_X_LOD(_OutlineBuffer, s_linear_clamp_sampler, uv, 0);
outline.a = 0;
if (Luminance(outline.rgb) < luminanceThreshold)
{
for (int i = 0; i < MAXSAMPLES; i++)
{
float2 uvN = uv + _ScreenSize.zw * _RTHandleScale.xy * samplingPositionsi * _Thickness; float4 neighbour = SAMPLE_TEXTURE2D_X_LOD(_OutlineBuffer, s_linear_clamp_sampler, uvN, 0);
if (Luminance(neighbour) > luminanceThreshold)
{
outline.rgb = _OutlineColor.rgb;
outline.a = 1;
break;
}
}
}
return outline;
}
ENDHLSL
SubShader
{
Pass
{
Name "Outline Pass"
ZWrite Off
ZTest Always
Blend SrcAlpha OneMinusSrcAlpha
Cull Off
HLSLPROGRAM
ENDHLSL
}
}
Fallback Off
}
code:CRTPass.cs
using UnityEngine;
using UnityEngine.Rendering.HighDefinition;
using UnityEngine.Rendering;
using UnityEngine.Experimental.Rendering;
public class CRTPass : CustomPass
{
Shader crtShader;
Material fullscreenMaterial;
MaterialPropertyBlock materialProperties;
ShaderTagId[] shaderTags;
RTHandle rtBuffer;
protected override void Setup(ScriptableRenderContext renderContext, CommandBuffer cmd)
{
crtShader = Shader.Find("FullScreen/CRTPass");
fullscreenMaterial = CoreUtils.CreateEngineMaterial(crtShader);
materialProperties = new MaterialPropertyBlock();
// List all the materials that will be replaced in the frame
shaderTags = new ShaderTagId3 {
new ShaderTagId("Forward"),
new ShaderTagId("ForwardOnly"),
new ShaderTagId("SRPDefaultUnlit"),
};
rtBuffer = RTHandles.Alloc(
Vector2.one, TextureXR.slices, dimension: TextureXR.dimension,
colorFormat: GraphicsFormat.B10G11R11_UFloatPack32,
useDynamicScale: true, name: "CRT Buffer"
);
}
void DrawMeshes(ScriptableRenderContext renderContext, CommandBuffer cmd, HDCamera hdCamera, CullingResults cullingResult)
{
var result = new RendererListDesc(shaderTags, cullingResult, hdCamera.camera)
{
// We need the lighting render configuration to support rendering lit objects
rendererConfiguration = PerObjectData.LightProbe | PerObjectData.LightProbeProxyVolume | PerObjectData.Lightmaps,
renderQueueRange = RenderQueueRange.all,
sortingCriteria = SortingCriteria.BackToFront,
excludeObjectMotionVectors = false,
layerMask = 0,
};
CoreUtils.SetRenderTarget(cmd, rtBuffer, ClearFlag.Color);
HDUtils.DrawRendererList(renderContext, cmd, RendererList.Create(result));
}
protected override void Execute(ScriptableRenderContext renderContext, CommandBuffer cmd, HDCamera hdCamera, CullingResults cullingResult)
{
DrawMeshes(renderContext, cmd, hdCamera, cullingResult);
SetCameraRenderTarget(cmd);
CoreUtils.DrawFullScreen(cmd, fullscreenMaterial, materialProperties, shaderPassId: 0);
}
protected override void Cleanup()
{
CoreUtils.Destroy(fullscreenMaterial);
rtBuffer.Release();
}
}
code:CRTPass.shader
Shader "FullScreen/CRTPass"
{
HLSLINCLUDE
#pragma only_renderers d3d11 ps4 xboxone vulkan metal switch #include "Packages/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/RenderPass/CustomPass/CustomPassCommon.hlsl" float2 barrel(float2 uv) {
float s1 = .99, s2 = .125;
float2 centre = 2. * uv - 1.;
float barrel = min(1. - length(centre) * s1, 1.0) * s2;
return uv - centre * barrel;
}
float2 CRT(float2 uv)
{
float2 nu = uv * 2. - 1.;
float2 offset = abs(nu.yx) / float2(6.4, 4.8);
nu += nu * offset * offset;
return nu;
}
float Scanline(float2 uv)
{
float scanline = clamp(0.95 + 0.05 * cos(3.14 * (uv.y + 0.008 * floor(_Time.y * 15.) / 15.) * 240.0 * 1.0), 0.0, 1.0);
float grille = 0.85 + 0.15 * clamp(1.5 * cos(3.14 * uv.x * 640.0 * 1.0), 0.0, 1.0);
return clamp(scanline * grille * .85, .0, 1.);
}
float4 FullScreenPass(Varyings varyings) : SV_Target
{
UNITY_SETUP_STEREO_EYE_INDEX_POST_VERTEX(varyings);
float depth = LoadCameraDepth(varyings.positionCS.xy);
PositionInputs posInput = GetPositionInput(varyings.positionCS.xy, _ScreenSize.zw, depth, UNITY_MATRIX_I_VP, UNITY_MATRIX_V);
float3 viewDirection = GetWorldSpaceNormalizeViewDir(posInput.positionWS);
float4 color = float4(0.0, 0.0, 0.0, 0.0);
// Load the camera color buffer at the mip 0 if we're not at the before rendering injection point
if (_CustomPassInjectionPoint != CUSTOMPASSINJECTIONPOINT_BEFORE_RENDERING)
color = float4(CustomPassSampleCameraColor(posInput.positionNDC.xy, 0), 1);
float2 uv = posInput.positionNDC.xy;
// barrel distortion
float2 p = barrel(posInput.positionNDC.xy);
float3 col = CustomPassSampleCameraColor(p, 0);
col = clamp(col, .0, 1.);
// color grading
col *= float3(1.25, 0.95, 0.7);
// scanline
col.rgb *= Scanline(posInput.positionNDC.xy);
// crt monitor
float2 crt = CRT(posInput.positionNDC.xy);
crt = abs(crt);
crt = pow(crt, 15.);
col.rgb = lerp(col.rgb, (.0).xxx, crt.x + crt.y);
color.rgb = col;
return color;
}
ENDHLSL
SubShader
{
Pass
{
Name "CRT Pass"
ZWrite Off
ZTest Always
Blend SrcAlpha OneMinusSrcAlpha
Cull Off
HLSLPROGRAM
ENDHLSL
}
}
Fallback Off
}
code:KuwaharaPass.cs
using UnityEngine;
using UnityEngine.Rendering.HighDefinition;
using UnityEngine.Rendering;
using UnityEngine.Experimental.Rendering;
public class KuwaharaPass : CustomPass
{
public int radius = 7;
public int radExpand = 1;
Shader kuwaharaShader;
Material fullscreenMaterial;
MaterialPropertyBlock materialProperties;
ShaderTagId[] shaderTags;
RTHandle rtBuffer;
protected override void Setup(ScriptableRenderContext renderContext, CommandBuffer cmd)
{
kuwaharaShader = Shader.Find("FullScreen/KuwaharaPass");
fullscreenMaterial = CoreUtils.CreateEngineMaterial(kuwaharaShader);
materialProperties = new MaterialPropertyBlock();
// List all the materials that will be replaced in the frame
shaderTags = new ShaderTagId3 {
new ShaderTagId("Forward"),
new ShaderTagId("ForwardOnly"),
new ShaderTagId("SRPDefaultUnlit"),
};
rtBuffer = RTHandles.Alloc(
Vector2.one, TextureXR.slices, dimension: TextureXR.dimension,
colorFormat: GraphicsFormat.B10G11R11_UFloatPack32,
useDynamicScale: true, name: "Kuwahara Buffer"
);
}
void DrawMeshes(ScriptableRenderContext renderContext, CommandBuffer cmd, HDCamera hdCamera, CullingResults cullingResult)
{
var result = new RendererListDesc(shaderTags, cullingResult, hdCamera.camera)
{
// We need the lighting render configuration to support rendering lit objects
rendererConfiguration = PerObjectData.LightProbe | PerObjectData.LightProbeProxyVolume | PerObjectData.Lightmaps,
renderQueueRange = RenderQueueRange.all,
sortingCriteria = SortingCriteria.BackToFront,
excludeObjectMotionVectors = false,
layerMask = 0,
};
CoreUtils.SetRenderTarget(cmd, rtBuffer, ClearFlag.Color);
HDUtils.DrawRendererList(renderContext, cmd, RendererList.Create(result));
}
protected override void Execute(ScriptableRenderContext renderContext, CommandBuffer cmd, HDCamera hdCamera, CullingResults cullingResult)
{
DrawMeshes(renderContext, cmd, hdCamera, cullingResult);
SetCameraRenderTarget(cmd);
materialProperties.SetInt("_Radius", radius);
materialProperties.SetInt("_RadEx", radExpand);
CoreUtils.DrawFullScreen(cmd, fullscreenMaterial, materialProperties, shaderPassId: 0);
}
protected override void Cleanup()
{
CoreUtils.Destroy(fullscreenMaterial);
rtBuffer.Release();
}
}
code:KuwaharaPass.shader
Shader "FullScreen/KuwaharaPass"
{
HLSLINCLUDE
#pragma only_renderers d3d11 ps4 xboxone vulkan metal switch #include "Packages/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/RenderPass/CustomPass/CustomPassCommon.hlsl" int _Radius = 7;
int _RadEx = 1;
float4 FullScreenPass(Varyings varyings) : SV_Target
{
UNITY_SETUP_STEREO_EYE_INDEX_POST_VERTEX(varyings);
float depth = LoadCameraDepth(varyings.positionCS.xy);
PositionInputs posInput = GetPositionInput(varyings.positionCS.xy, _ScreenSize.zw, depth, UNITY_MATRIX_I_VP, UNITY_MATRIX_V);
float3 viewDirection = GetWorldSpaceNormalizeViewDir(posInput.positionWS);
float4 color = float4(0.0, 0.0, 0.0, 0.0);
// Load the camera color buffer at the mip 0 if we're not at the before rendering injection point
if (_CustomPassInjectionPoint != CUSTOMPASSINJECTIONPOINT_BEFORE_RENDERING)
color = float4(CustomPassSampleCameraColor(posInput.positionNDC.xy, 0), 1);
float2 uv = posInput.positionNDC.xy;
{0, 0, 0},
{0, 0, 0},
{0, 0, 0},
{0, 0, 0}
};
{0, 0, 0},
{0, 0, 0},
{0, 0, 0},
{0, 0, 0}
};
float2 start4 = { {-_Radius, -_Radius}, {-_Radius, 0}, {0, -_Radius}, {0, 0} }; float2 pos;
float3 col;
for (int k = 0; k < 4; k++) {
for (int i = 0; i <= _Radius; i++) {
for (int j = 0; j <= _Radius; j++) {
pos = float2(i, j) + startk; col = CustomPassSampleCameraColor(posInput.positionNDC.xy + float2(pos.x / _ScreenSize.x, pos.y / _ScreenSize.y), 0);
}
}
}
float sigma2;
float n = pow(_Radius + _RadEx, 2);
float min = 1;
for (int l = 0; l < 4; l++) {
sigmal = abs(sigmal / n - meanl * meanl); sigma2 = sigmal.r + sigmal.g + sigmal.b; if (sigma2 < min) {
min = sigma2;
}
}
float lum = dot(color.rgb, float3(.1, .7, .2));
color.rgb *= (.5 + lum);
return color;
}
ENDHLSL
SubShader
{
Pass
{
Name "Kuwahara Pass"
ZWrite Off
ZTest Always
Blend SrcAlpha OneMinusSrcAlpha
Cull Off
HLSLPROGRAM
ENDHLSL
}
}
Fallback Off
}
code:HalftonePass.cs
using UnityEngine;
using UnityEngine.Rendering.HighDefinition;
using UnityEngine.Rendering;
using UnityEngine.Experimental.Rendering;
public class HalftonePass : CustomPass
{
public float freq = 1;
public float radM = 1;
public float radA = 0;
public Color toneColor = Color.white;
Shader halftoneShader;
Material fullscreenMaterial;
MaterialPropertyBlock materialProperties;
ShaderTagId[] shaderTags;
RTHandle rtBuffer;
protected override void Setup(ScriptableRenderContext renderContext, CommandBuffer cmd)
{
halftoneShader = Shader.Find("FullScreen/HalftonePass");
fullscreenMaterial = CoreUtils.CreateEngineMaterial(halftoneShader);
materialProperties = new MaterialPropertyBlock();
// List all the materials that will be replaced in the frame
shaderTags = new ShaderTagId3 {
new ShaderTagId("Forward"),
new ShaderTagId("ForwardOnly"),
new ShaderTagId("SRPDefaultUnlit"),
};
rtBuffer = RTHandles.Alloc(
Vector2.one, TextureXR.slices, dimension: TextureXR.dimension,
colorFormat: GraphicsFormat.B10G11R11_UFloatPack32,
useDynamicScale: true, name: "Halftone Buffer"
);
}
void DrawMeshes(ScriptableRenderContext renderContext, CommandBuffer cmd, HDCamera hdCamera, CullingResults cullingResult)
{
var result = new RendererListDesc(shaderTags, cullingResult, hdCamera.camera)
{
// We need the lighting render configuration to support rendering lit objects
rendererConfiguration = PerObjectData.LightProbe | PerObjectData.LightProbeProxyVolume | PerObjectData.Lightmaps,
renderQueueRange = RenderQueueRange.all,
sortingCriteria = SortingCriteria.BackToFront,
excludeObjectMotionVectors = false,
layerMask = 0,
};
CoreUtils.SetRenderTarget(cmd, rtBuffer, ClearFlag.Color);
HDUtils.DrawRendererList(renderContext, cmd, RendererList.Create(result));
}
protected override void Execute(ScriptableRenderContext renderContext, CommandBuffer cmd, HDCamera hdCamera, CullingResults cullingResult)
{
DrawMeshes(renderContext, cmd, hdCamera, cullingResult);
SetCameraRenderTarget(cmd);
materialProperties.SetFloat("_Freq", freq);
materialProperties.SetFloat("_RadM", radM);
materialProperties.SetFloat("_RadA", radA);
materialProperties.SetColor("_ToneColor", toneColor);
CoreUtils.DrawFullScreen(cmd, fullscreenMaterial, materialProperties, shaderPassId: 0);
}
protected override void Cleanup()
{
CoreUtils.Destroy(fullscreenMaterial);
rtBuffer.Release();
}
}
code:HalftonePass.shader
Shader "FullScreen/HalftonePass"
{
HLSLINCLUDE
#pragma only_renderers d3d11 playstation xboxone vulkan metal switch #include "Packages/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/RenderPass/CustomPass/CustomPassCommon.hlsl" float _Freq;
float _RadM;
float _RadA;
float4 _ToneColor;
float mod(float x, float y) { return x - floor(x / y) * y; }
float3 mod289(float3 x) { return x - floor(x * (1.0 / 289.0)) * 289.0; }
float2 mod289(float2 x) { return x - floor(x * (1.0 / 289.0)) * 289.0; }
float3 permute(float3 x) { return mod289(((x * 34.0) + 1.0) * x); }
float snoise(float2 v) {
const float4 C = float4(0.211324865405187,
0.366025403784439,
-0.577350269189626,
0.024390243902439);
float2 i = floor(v + dot(v, C.yy));
float2 x0 = v - i + dot(i, C.xx);
// Other two corners (x1, x2)
float2 i1 = float2(0.0, 0.0);
i1 = (x0.x > x0.y) ? float2(1.0, 0.0) : float2(0.0, 1.0);
float2 x1 = x0.xy + C.xx - i1;
float2 x2 = x0.xy + C.zz;
i = mod289(i);
float3 p = permute(
permute(i.y + float3(0.0, i1.y, 1.0))
+ i.x + float3(0.0, i1.x, 1.0));
float3 m = max(0.5 - float3(
dot(x0, x0),
dot(x1, x1),
dot(x2, x2)
), 0.0);
m = m * m;
m = m * m;
float3 x = 2.0 * frac(p * C.www) - 1.0;
float3 h = abs(x) - 0.5;
float3 ox = floor(x + 0.5);
float3 a0 = x - ox;
m *= 1.79284291400159 - 0.85373472095314 * (a0 * a0 + h * h);
float3 g = (.0).xxx;
g.x = a0.x * x0.x + h.x * x0.y;
g.yz = a0.yz * float2(x1.x, x2.x) + h.yz * float2(x1.y, x2.y);
return 130.0 * dot(m, g);
}
float aastep(float threshold, float value) {
return step(threshold, value);
}
float3 halftone(float3 texcolor, float2 st, float frequency) {
float n = 0.1 * snoise(st * 200.0); // fracal noise
n += 0.05 * snoise(st * 400.0);
n += 0.025 * snoise(st * 800.0);
n *= _RadM;
n += _RadA;
// Perform a rough RGB-to-CMYK conversion
float4 cmyk;
cmyk.xyz = 1.0 - texcolor;
cmyk.w = min(cmyk.x, min(cmyk.y, cmyk.z)); // Create K
cmyk.xyz -= cmyk.w; // Subtract K equivalent from CMY
// Distance to nearest point in a grid of
// (frequency x frequency) points over the unit square
float2 Kst = frequency * mul(float2x2(0.707, -0.707, 0.707, 0.707) , st);
float2 Kuv = 2.0 * frac(Kst) - 1.0;
float k = aastep(0.0, sqrt(cmyk.w) - length(Kuv) + n);
float2 Cst = frequency * mul(float2x2(0.966, -0.259, 0.259, 0.966) , st);
float2 Cuv = 2.0 * frac(Cst) - 1.0;
float c = aastep(0.0, sqrt(cmyk.x) - length(Cuv) + n);
float2 Mst = frequency * mul(float2x2(0.966, 0.259, -0.259, 0.966) , st);
float2 Muv = 2.0 * frac(Mst) - 1.0;
float m = aastep(0.0, sqrt(cmyk.y) - length(Muv) + n);
float2 Yst = frequency * st; // 0 deg
float2 Yuv = 2.0 * frac(Yst) - 1.0;
float y = aastep(0.0, sqrt(cmyk.z) - length(Yuv) + n);
float3 rgbscreen = 1.0 - 0.9 * float3(c, m, y) + n;
return lerp(rgbscreen, _ToneColor.rgb, 0.85 * k + 0.3 * n);
}
float4 FullScreenPass(Varyings varyings) : SV_Target
{
UNITY_SETUP_STEREO_EYE_INDEX_POST_VERTEX(varyings);
float depth = LoadCameraDepth(varyings.positionCS.xy);
PositionInputs posInput = GetPositionInput(varyings.positionCS.xy, _ScreenSize.zw, depth, UNITY_MATRIX_I_VP, UNITY_MATRIX_V);
float4 color = float4(0.0, 0.0, 0.0, 0.0);
// Load the camera color buffer at the mip 0 if we're not at the before rendering injection point
if (_CustomPassInjectionPoint != CUSTOMPASSINJECTIONPOINT_BEFORE_RENDERING)
color = float4(CustomPassSampleCameraColor(posInput.positionNDC.xy, 0), 1);
// When sampling RTHandle texture, always use _RTHandleScale.xy to scale your UVs first.
float2 uv = posInput.positionNDC.xy * _RTHandleScale.xy;
color.rgb = halftone(color.rgb, uv, _Freq);
return color;
}
ENDHLSL
SubShader
{
Pass
{
Name "Halftone Pass"
ZWrite Off
ZTest Always
Blend SrcAlpha OneMinusSrcAlpha
Cull Off
HLSLPROGRAM
ENDHLSL
}
}
Fallback Off
}
code:RainPass.cs
using UnityEngine;
using UnityEngine.Rendering.HighDefinition;
using UnityEngine.Rendering;
using UnityEngine.Experimental.Rendering;
public class RainPass : CustomPass
{
public float rainAmount = 0.5f;
public float zoom = 1.0f;
public float speed = 0.25f;
Shader rainShader;
Material fullscreenMaterial;
MaterialPropertyBlock materialProperties;
ShaderTagId[] shaderTags;
RTHandle rtBuffer;
protected override void Setup(ScriptableRenderContext renderContext, CommandBuffer cmd)
{
rainShader = Shader.Find("FullScreen/RainPass");
fullscreenMaterial = CoreUtils.CreateEngineMaterial(rainShader);
materialProperties = new MaterialPropertyBlock();
// List all the materials that will be replaced in the frame
shaderTags = new ShaderTagId3 {
new ShaderTagId("Forward"),
new ShaderTagId("ForwardOnly"),
new ShaderTagId("SRPDefaultUnlit"),
};
rtBuffer = RTHandles.Alloc(
Vector2.one, TextureXR.slices, dimension: TextureXR.dimension,
colorFormat: GraphicsFormat.B10G11R11_UFloatPack32,
useDynamicScale: true, name: "Rain Buffer"
);
}
void DrawOutlineMeshes(ScriptableRenderContext renderContext, CommandBuffer cmd, HDCamera hdCamera, CullingResults cullingResult)
{
var result = new RendererListDesc(shaderTags, cullingResult, hdCamera.camera)
{
// We need the lighting render configuration to support rendering lit objects
rendererConfiguration = PerObjectData.LightProbe | PerObjectData.LightProbeProxyVolume | PerObjectData.Lightmaps,
renderQueueRange = RenderQueueRange.all,
sortingCriteria = SortingCriteria.BackToFront,
excludeObjectMotionVectors = false,
layerMask = 0,
};
CoreUtils.SetRenderTarget(cmd, rtBuffer, ClearFlag.Color);
HDUtils.DrawRendererList(renderContext, cmd, RendererList.Create(result));
}
protected override void Execute(ScriptableRenderContext renderContext, CommandBuffer cmd, HDCamera hdCamera, CullingResults cullingResult)
{
DrawOutlineMeshes(renderContext, cmd, hdCamera, cullingResult);
SetCameraRenderTarget(cmd);
materialProperties.SetTexture("_BufferTex", rtBuffer);
materialProperties.SetFloat("_RainAmount", rainAmount);
materialProperties.SetFloat("_Zoom", zoom);
materialProperties.SetFloat("_Speed", speed);
CoreUtils.DrawFullScreen(cmd, fullscreenMaterial, materialProperties, shaderPassId: 0);
}
protected override void Cleanup()
{
CoreUtils.Destroy(fullscreenMaterial);
rtBuffer.Release();
}
}
code:RainPass.shader
Shader "FullScreen/RainPass"
{
HLSLINCLUDE
#pragma only_renderers d3d11 ps4 xboxone vulkan metal switch #include "Packages/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/RenderPass/CustomPass/CustomPassCommon.hlsl" TEXTURE2D_X(_BufferTex);
float _RainAmount;
float _Zoom;
float _Speed;
float S(float a, float b, float t) {
return smoothstep(a, b, t);
}
float3 S(float3 a, float3 b, float t) {
return smoothstep(a, b, t);
}
float3 N13(float p) {
// from DAVE HOSKINS
float3 p3 = frac(float3(p, p, p) * float3(.1031, .11369, .13787));
p3 += dot(p3, p3.yzx + 19.19);
return frac(float3((p3.x + p3.y) * p3.z, (p3.x + p3.z) * p3.y, (p3.y + p3.z) * p3.x));
}
float N(float t) {
return frac(sin(t * 12345.564) * 7658.76);
}
float Saw(float b, float t) {
return S(0., b, t) * S(1., b, t);
}
float2 DropLayer2(float2 uv, float t) {
float2 UV = uv;
uv.y += t * 0.75;
float2 a = float2(6., 1.);
float2 grid = a * 2.;
float2 id = floor(uv * grid);
float colShift = N(id.x);
uv.y += colShift;
id = floor(uv * grid);
float3 n = N13(id.x * 35.2 + id.y * 2376.1);
float2 st = frac(uv * grid) - float2(.5, 0);
float x = n.x - .5;
float y = UV.y * 20.;
float wiggle = sin(y + sin(y));
x += wiggle * (.5 - abs(x)) * (n.z - .5);
x *= .7;
float ti = frac(t + n.z);
y = (Saw(.85, ti) - .5) * .9 + .5;
float2 p = float2(x, y);
float d = length((st - p) * a.yx);
float mainDrop = S(.4, .0, d);
float r = sqrt(S(1., y, st.y));
float cd = abs(st.x - x);
float trail = S(.23 * r, .15 * r * r, cd);
float trailFront = S(-.02, .02, st.y - y);
trail *= trailFront * r * r;
y = UV.y;
float trail2 = S(.2 * r, .0, cd);
float droplets = max(0., (sin(y * (1. - y) * 120.) - st.y)) * trail2 * trailFront * n.z;
y = frac(y * 10.) + (st.y - .5);
float dd = length(st - float2(x, y));
droplets = S(.3, 0., dd);
float m = mainDrop + droplets * r * trailFront;
return float2(m, trail);
}
float StaticDrops(float2 uv, float t) {
uv *= 40.;
float2 id = floor(uv);
uv = frac(uv) - .5;
float3 n = N13(id.x * 107.45 + id.y * 3543.654);
float2 p = (n.xy - .5) * .7;
float d = length(uv - p);
float fade = Saw(.025, frac(t + n.z));
float c = S(.3, 0., d) * frac(n.z * 10.) * fade;
return c;
}
float2 Drops(float2 uv, float t, float l0, float l1, float l2) {
float s = StaticDrops(uv, t) * l0;
float2 m1 = DropLayer2(uv, t) * l1;
float2 m2 = DropLayer2(uv * 1.85, t) * l2;
float c = s + m1.x + m2.x;
c = S(.3, 1., c);
return float2(c, max(m1.y * l0, m2.y * l1));
}
float3 rain(float2 i) {
float time = _Time.y;
float rainAmount = _RainAmount;
float zoom = _Zoom;
float speed = _Speed;
float rainTime = 360.;
float2 uv = ((i * _ScreenSize.xy) - .5 * _ScreenSize.xy) / min(_ScreenSize.x, _ScreenSize.y);
float2 UV = i;
float T = time - floor(time / rainTime) * rainTime;
float t = T * .2;
t = min(1., T / rainTime); // remap drop time so it goes slower when it freezes
t = 1. - t;
t = (1. - t * t) * rainTime;
// tweak uv, time
uv *= zoom;
t *= speed;
// let the rain fall down
float staticDrops = S(-.5, 1., rainAmount) * 2.;
float layer1 = S(.25, .75, rainAmount);
float layer2 = S(.0, .5, rainAmount);
float2 c = Drops(uv, t, staticDrops, layer1, layer2);
float2 e = float2(.001, 0.);
float cx = Drops(uv + e, t, staticDrops, layer1, layer2).x;
float cy = Drops(uv + e.yx, t, staticDrops, layer1, layer2).x;
float2 n = float2(cx - c.x, cy - c.x);
// load tex
float2 texCoord = float2(UV.x + n.x, UV.y + n.y);
float3 col = CustomPassSampleCameraColor(texCoord, 0);
return col;
}
float4 FullScreenPass(Varyings varyings) : SV_Target
{
UNITY_SETUP_STEREO_EYE_INDEX_POST_VERTEX(varyings);
float depth = LoadCameraDepth(varyings.positionCS.xy);
PositionInputs posInput = GetPositionInput(varyings.positionCS.xy, _ScreenSize.zw, depth, UNITY_MATRIX_I_VP, UNITY_MATRIX_V);
float3 viewDirection = GetWorldSpaceNormalizeViewDir(posInput.positionWS);
float4 color = float4(0.0, 0.0, 0.0, 0.0);
// Load the camera color buffer at the mip 0 if we're not at the before rendering injection point
if (_CustomPassInjectionPoint != CUSTOMPASSINJECTIONPOINT_BEFORE_RENDERING)
color = float4(CustomPassSampleCameraColor(posInput.positionNDC.xy, 0), 1);
float2 uv = posInput.positionNDC.xy;
color.rgb = rain(uv);
return color;
}
ENDHLSL
SubShader
{
Pass
{
Name "Rain Pass"
ZWrite Off
ZTest Always
Blend SrcAlpha OneMinusSrcAlpha
Cull Off
HLSLPROGRAM
ENDHLSL
}
}
Fallback Off
}