feat: add Tilt Shift effect

main
uc-hoba 3 weeks ago
parent 1e5428816d
commit bbb6cd59e6
  1. 2
      Assets/Main/GlobalVolumeProfile.asset
  2. 23
      Assets/Settings/PC_Renderer.asset
  3. 8
      Assets/TiltShift.meta
  4. 8
      Assets/TiltShift/Shaders.meta
  5. 101
      Assets/TiltShift/Shaders/TiltShift.shader
  6. 9
      Assets/TiltShift/Shaders/TiltShift.shader.meta
  7. 132
      Assets/TiltShift/TiltShiftFeature.cs
  8. 2
      Assets/TiltShift/TiltShiftFeature.cs.meta
  9. 1
      Unity-25014-ReadySetRide.slnx

@ -111,7 +111,7 @@ MonoBehaviour:
m_Script: {fileID: 11500000, guid: c01700fd266d6914ababb731e09af2eb, type: 3}
m_Name: DepthOfField
m_EditorClassIdentifier: Unity.RenderPipelines.Universal.Runtime::UnityEngine.Rendering.Universal.DepthOfField
active: 1
active: 0
mode:
m_OverrideState: 1
m_Value: 2

@ -1,5 +1,25 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!114 &-3999075185107018374
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 0}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: aff85384491b2c84fb68adcd676beaca, type: 3}
m_Name: TiltShiftFeature
m_EditorClassIdentifier: Assembly-CSharp::TiltShiftFeature
m_Active: 1
settings:
centerOffset: 0
focusWidth: 0.2
falloffRange: 0.3
maxBlurRadius: 50
sampleCount: 16
injectionPoint: 600
--- !u!114 &11400000
MonoBehaviour:
m_ObjectHideFlags: 0
@ -27,7 +47,8 @@ MonoBehaviour:
m_RendererFeatures:
- {fileID: 7833122117494664109}
- {fileID: 8703437150354955497}
m_RendererFeatureMap: ad6b866f10d7b46ce95cd8b7f9d1c878
- {fileID: -3999075185107018374}
m_RendererFeatureMap: ad6b866f10d7b46ce95cd8b7f9d1c8787add9da14e6e80c8
m_UseNativeRenderPass: 1
xrSystemData: {fileID: 0}
postProcessData: {fileID: 11400000, guid: 41439944d30ece34e96484bdb6645b55, type: 2}

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 2c68054ffd8fd3345bea8887a0f038e2
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: df079c0fdb908c94c9f648fdda464782
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

@ -0,0 +1,101 @@
Shader "Custom/TiltShift"
{
SubShader
{
Tags { "RenderType" = "Opaque" "RenderPipeline" = "UniversalPipeline" }
ZTest Always ZWrite Off Cull Off Blend Off
HLSLINCLUDE
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"
#include "Packages/com.unity.render-pipelines.core/Runtime/Utilities/Blit.hlsl"
float _TiltShift_CenterOffset;
float _TiltShift_FocusWidth;
float _TiltShift_FalloffRange;
float _TiltShift_MaxBlurRadius;
int _TiltShift_SampleCount;
// _BlitTexture and _BlitTexture_TexelSize are provided by Blit.hlsl
// _BlitTexture_TexelSize: (1/w, 1/h, w, h)
// sampler_LinearClamp is provided by GlobalSamplers.hlsl (included via Blit.hlsl)
// Returns blur radius in pixels for a given vertical UV coordinate.
float ComputeBlurRadius(float uvY)
{
float dist = abs(uvY - 0.5 + _TiltShift_CenterOffset);
float halfFocus = _TiltShift_FocusWidth * 0.5;
float range = max(_TiltShift_FalloffRange, 0.001);
return smoothstep(halfFocus, halfFocus + range, dist) * _TiltShift_MaxBlurRadius;
}
// Gaussian blur in an arbitrary direction.
// direction: offset per sample step in UV space (already multiplied by texelSize)
float4 GaussianBlur(float2 uv, float2 stepUV)
{
int n = max(1, _TiltShift_SampleCount);
float4 color = 0;
float totalWeight = 0;
[loop]
for (int i = -n; i <= n; i++)
{
// t in [-1, 1]; weight peaks at centre and falls near edges.
float t = float(i) / float(n);
float weight = exp(-4.5 * t * t);
float2 sampleUV = uv + stepUV * float(i);
color += SAMPLE_TEXTURE2D_X_LOD(_BlitTexture, sampler_LinearClamp, sampleUV, 0) * weight;
totalWeight += weight;
}
return color / totalWeight;
}
float4 HorizontalBlur(Varyings input) : SV_Target
{
UNITY_SETUP_STEREO_EYE_INDEX_POST_VERTEX(input);
float2 uv = input.texcoord;
float radius = ComputeBlurRadius(uv.y);
if (radius < 0.5)
return SAMPLE_TEXTURE2D_X_LOD(_BlitTexture, sampler_LinearClamp, uv, 0);
// stepUV: one step in the horizontal direction, spread over [−radius, +radius] pixels
int n = max(1, _TiltShift_SampleCount);
float2 stepUV = float2((radius / float(n)) * _BlitTexture_TexelSize.x, 0.0);
return GaussianBlur(uv, stepUV);
}
float4 VerticalBlur(Varyings input) : SV_Target
{
UNITY_SETUP_STEREO_EYE_INDEX_POST_VERTEX(input);
float2 uv = input.texcoord;
float radius = ComputeBlurRadius(uv.y);
if (radius < 0.5)
return SAMPLE_TEXTURE2D_X_LOD(_BlitTexture, sampler_LinearClamp, uv, 0);
int n = max(1, _TiltShift_SampleCount);
float2 stepUV = float2(0.0, (radius / float(n)) * _BlitTexture_TexelSize.y);
return GaussianBlur(uv, stepUV);
}
ENDHLSL
// Pass 0 — Horizontal blur
Pass
{
Name "TiltShift_H"
HLSLPROGRAM
#pragma vertex Vert
#pragma fragment HorizontalBlur
ENDHLSL
}
// Pass 1 — Vertical blur
Pass
{
Name "TiltShift_V"
HLSLPROGRAM
#pragma vertex Vert
#pragma fragment VerticalBlur
ENDHLSL
}
}
}

@ -0,0 +1,9 @@
fileFormatVersion: 2
guid: 73dea10312786894ea13fd32ffab89b3
ShaderImporter:
externalObjects: {}
defaultTextures: []
nonModifiableTextures: []
userData:
assetBundleName:
assetBundleVariant:

@ -0,0 +1,132 @@
using UnityEngine;
using UnityEngine.Rendering;
using UnityEngine.Rendering.Universal;
using UnityEngine.Rendering.RenderGraphModule;
using UnityEngine.Rendering.RenderGraphModule.Util;
public class TiltShiftFeature : ScriptableRendererFeature
{
[System.Serializable]
public class Settings
{
[Tooltip("Vertical offset of the sharp focus band from screen centre. Positive = up.")]
[Range(-0.4f, 0.4f)]
public float centerOffset = 0f;
[Tooltip("Height of the fully-sharp band as a fraction of screen height.")]
[Range(0.01f, 0.8f)]
public float focusWidth = 0.2f;
[Tooltip("Distance over which blur fades in at each edge of the focus band.")]
[Range(0.01f, 0.4f)]
public float falloffRange = 0.15f;
[Tooltip("Maximum blur radius in pixels at the extreme top and bottom.")]
[Range(1f, 64f)]
public float maxBlurRadius = 20f;
[Tooltip("Samples per side per pass (higher = smoother blur, higher cost).")]
[Range(2, 20)]
public int sampleCount = 8;
public RenderPassEvent injectionPoint = RenderPassEvent.AfterRenderingPostProcessing;
}
public Settings settings = new Settings();
TiltShiftPass _pass;
Material _material;
public override void Create()
{
var shader = Shader.Find("Custom/TiltShift");
if (shader == null)
{
Debug.LogWarning("[TiltShift] Shader 'Custom/TiltShift' not found. " +
"Make sure TiltShift.shader is in the project.");
return;
}
_material = CoreUtils.CreateEngineMaterial(shader);
_pass = new TiltShiftPass(_material, settings);
_pass.renderPassEvent = settings.injectionPoint;
}
public override void AddRenderPasses(ScriptableRenderer renderer, ref RenderingData renderingData)
{
if (_material == null || _pass == null) return;
// Skip scene view and preview cameras to avoid visual noise.
var camType = renderingData.cameraData.cameraType;
if (camType == CameraType.Preview || camType == CameraType.Reflection) return;
_pass.UpdateSettings(settings);
renderer.EnqueuePass(_pass);
}
protected override void Dispose(bool disposing)
{
CoreUtils.Destroy(_material);
}
// -------------------------------------------------------------------------
class TiltShiftPass : ScriptableRenderPass
{
static readonly int s_CenterOffset = Shader.PropertyToID("_TiltShift_CenterOffset");
static readonly int s_FocusWidth = Shader.PropertyToID("_TiltShift_FocusWidth");
static readonly int s_FalloffRange = Shader.PropertyToID("_TiltShift_FalloffRange");
static readonly int s_MaxBlurRadius = Shader.PropertyToID("_TiltShift_MaxBlurRadius");
static readonly int s_SampleCount = Shader.PropertyToID("_TiltShift_SampleCount");
readonly Material _material;
Settings _settings;
public TiltShiftPass(Material material, Settings settings)
{
_material = material;
_settings = settings;
requiresIntermediateTexture = true;
}
public void UpdateSettings(Settings settings) => _settings = settings;
public override void RecordRenderGraph(RenderGraph renderGraph, ContextContainer frameData)
{
var resourceData = frameData.Get<UniversalResourceData>();
if (resourceData.isActiveTargetBackBuffer)
return;
// Push current settings to the material.
_material.SetFloat(s_CenterOffset, _settings.centerOffset);
_material.SetFloat(s_FocusWidth, _settings.focusWidth);
_material.SetFloat(s_FalloffRange, _settings.falloffRange);
_material.SetFloat(s_MaxBlurRadius, _settings.maxBlurRadius);
_material.SetInt(s_SampleCount, _settings.sampleCount);
var source = resourceData.activeColorTexture;
// Intermediate texture for horizontal-blur result.
var desc = renderGraph.GetTextureDesc(source);
desc.clearBuffer = false;
desc.name = "TiltShift_Temp";
TextureHandle temp = renderGraph.CreateTexture(desc);
// Final texture for vertical-blur result.
desc.name = "TiltShift_Final";
TextureHandle final = renderGraph.CreateTexture(desc);
// Pass 0 — horizontal blur: source → temp
var paraH = new RenderGraphUtils.BlitMaterialParameters(source, temp, _material, 0);
renderGraph.AddBlitPass(paraH, passName: "TiltShift_H");
// Pass 1 — vertical blur: temp → final
var paraV = new RenderGraphUtils.BlitMaterialParameters(temp, final, _material, 1);
renderGraph.AddBlitPass(paraV, passName: "TiltShift_V");
// Redirect the camera colour so subsequent passes see our result.
resourceData.cameraColor = final;
}
}
}

@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: aff85384491b2c84fb68adcd676beaca

@ -38,4 +38,5 @@
<Project Path="HBAO.Editor.csproj" />
<Project Path="HBAO.Universal.Editor.csproj" />
<Project Path="Unity.Collections.Editor.csproj" />
<Project Path="Assembly-CSharp.csproj" />
</Solution>

Loading…
Cancel
Save