大修
This commit is contained in:
8
Assets/Shaders/ScriptablePostProcessor/Base.meta
Normal file
8
Assets/Shaders/ScriptablePostProcessor/Base.meta
Normal file
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 34ca6761a4ba8cd4aa70251567021b53
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,76 @@
|
||||
using UnityEngine;
|
||||
using UnityEngine.Rendering;
|
||||
|
||||
namespace Echovoid.Runtime.Behavior.Rendering
|
||||
{
|
||||
public static class InternalShaderHelpers
|
||||
{
|
||||
public static Material GenerateTransientMaterial(string shaderName)
|
||||
{
|
||||
var shader = Shader.Find(shaderName);
|
||||
return CoreUtils.CreateEngineMaterial(shader);
|
||||
}
|
||||
|
||||
public static class ID
|
||||
{
|
||||
// RGB Split Glitch
|
||||
public static readonly int _RGBSplitGlitchParams = Shader.PropertyToID("_RGBSplitGlitchParams");
|
||||
public static readonly int _RGBSplitGlitchIntensity = Shader.PropertyToID("_RGBSplitGlitchIntensity");
|
||||
|
||||
// Radial Blur
|
||||
public static readonly int _RadialBlurParams = Shader.PropertyToID("_RadialBlurParams");
|
||||
public static readonly int _BlurRadius = Shader.PropertyToID("_BlurRadius");
|
||||
public static readonly int _RadialCenterX = Shader.PropertyToID("_RadialCenterX");
|
||||
public static readonly int _RadialCenterY = Shader.PropertyToID("_RadialCenterY");
|
||||
|
||||
// Speed Lines
|
||||
public static readonly int _SpeedLinesColour = Shader.PropertyToID("_Colour");
|
||||
public static readonly int _SpeedLinesTiling = Shader.PropertyToID("_SpeedLinesTiling");
|
||||
public static readonly int _SpeedLinesRadialScale = Shader.PropertyToID("_SpeedLinesRadialScale");
|
||||
public static readonly int _SpeedLinesPower = Shader.PropertyToID("_SpeedLinesPower");
|
||||
public static readonly int _SpeedLinesRemap = Shader.PropertyToID("_SpeedLinesRemap");
|
||||
public static readonly int _SpeedLinesAnimation = Shader.PropertyToID("_SpeedLinesAnimation");
|
||||
public static readonly int _MaskScale = Shader.PropertyToID("_MaskScale");
|
||||
public static readonly int _MaskHardness = Shader.PropertyToID("_MaskHardness");
|
||||
public static readonly int _MaskPower = Shader.PropertyToID("_MaskPower");
|
||||
|
||||
// --- Strobe Flash ---
|
||||
public static readonly int _StrobeColorHigh = Shader.PropertyToID("_StrobeColorHigh");
|
||||
public static readonly int _StrobeColorLow = Shader.PropertyToID("_StrobeColorLow");
|
||||
public static readonly int _StrobeParams = Shader.PropertyToID("_StrobeParams");
|
||||
public static readonly int _StrobeAdvParams = Shader.PropertyToID("_StrobeAdvParams");
|
||||
public static readonly int _LuminanceWeights = Shader.PropertyToID("_LuminanceWeights");
|
||||
|
||||
// --- Sharpen ---
|
||||
public static readonly int _SharpnessParams = Shader.PropertyToID("_SharpnessParams");
|
||||
|
||||
// --- Advanced Chromatic Aberration ---
|
||||
public static readonly int _ACA_Params1 = Shader.PropertyToID("_ACA_Params1");
|
||||
public static readonly int _ACA_Params2 = Shader.PropertyToID("_ACA_Params2");
|
||||
public static readonly int _ACA_Split = Shader.PropertyToID("_ACA_Split");
|
||||
public static readonly int _DispersionMap = Shader.PropertyToID("_DispersionMap");
|
||||
|
||||
// --- Advanced Vignette ---
|
||||
public static readonly int _ColorInner = Shader.PropertyToID("_ColorInner");
|
||||
public static readonly int _ColorOuter = Shader.PropertyToID("_ColorOuter");
|
||||
public static readonly int _VignetteParams1 = Shader.PropertyToID("_VignetteParams1");
|
||||
public static readonly int _VignetteCenter = Shader.PropertyToID("_VignetteCenter");
|
||||
|
||||
// --- Anime Bloom ---
|
||||
public static readonly int _BloomParams = Shader.PropertyToID("_BloomParams");
|
||||
public static readonly int _BloomTint = Shader.PropertyToID("_BloomTint");
|
||||
public static readonly int _AnimeBloom_BlurRadius = Shader.PropertyToID("_BlurRadius");
|
||||
public static readonly int _BloomTex = Shader.PropertyToID("_BloomTex");
|
||||
|
||||
// --- Anime ACES ---
|
||||
public static readonly int _TonemapParams = Shader.PropertyToID("_TonemapParams");
|
||||
public static readonly int _ACESCoeffs = Shader.PropertyToID("_ACESCoeffs");
|
||||
public static readonly int _ACES_E = Shader.PropertyToID("_ACES_E");
|
||||
public static readonly int _ColorFilter = Shader.PropertyToID("_ColorFilter");
|
||||
|
||||
// --- Pixelate ---
|
||||
public static readonly int _PixelateStrengthX = Shader.PropertyToID("_PixelateStrengthX");
|
||||
public static readonly int _PixelateStrengthY = Shader.PropertyToID("_PixelateStrengthY");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: e46d8eed8c36ac84caf7ea20f2a0b134
|
||||
@@ -0,0 +1,94 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using UnityEngine.Rendering;
|
||||
using UnityEngine.Rendering.Universal;
|
||||
|
||||
namespace SLSUtilities.Rendering.PostProcessing
|
||||
{
|
||||
public class ScriptablePostProcessorFeature : ScriptableRendererFeature
|
||||
{
|
||||
private List<ScriptablePostProcessorVolume> postProcessorVolumes;
|
||||
|
||||
private ScriptablePostProcessorPass afterTransparentPass;
|
||||
private ScriptablePostProcessorPass beforePostProcessPass;
|
||||
private ScriptablePostProcessorPass afterPostProcessPass;
|
||||
|
||||
public override void Create()
|
||||
{
|
||||
var stack = VolumeManager.instance.stack;
|
||||
|
||||
postProcessorVolumes = VolumeManager.instance.baseComponentTypeArray
|
||||
.Where(t => t.IsSubclassOf(typeof(ScriptablePostProcessorVolume)))
|
||||
.Select(t => stack.GetComponent(t) as ScriptablePostProcessorVolume)
|
||||
.ToList();
|
||||
|
||||
var afterTransparentPostProcessors = postProcessorVolumes
|
||||
.Where(c => c.InjectionPoint == CustomPostProcessInjectionPoint.AfterTransparent)
|
||||
.OrderBy(c => c.OrderInInjectionPoint)
|
||||
.ToList();
|
||||
afterTransparentPass = new ScriptablePostProcessorPass("Custom PostProcessor - after Transparent", afterTransparentPostProcessors)
|
||||
{
|
||||
renderPassEvent = RenderPassEvent.AfterRenderingTransparents
|
||||
};
|
||||
|
||||
var beforePostProcessPostProcessors = postProcessorVolumes
|
||||
.Where(c => c.InjectionPoint == CustomPostProcessInjectionPoint.BeforePostProcess)
|
||||
.OrderBy(c => c.OrderInInjectionPoint)
|
||||
.ToList();
|
||||
beforePostProcessPass = new ScriptablePostProcessorPass("Custom PostProcessor - before PostProcessing", beforePostProcessPostProcessors)
|
||||
{
|
||||
renderPassEvent = RenderPassEvent.BeforeRenderingPostProcessing
|
||||
};
|
||||
|
||||
var afterPostProcessPostProcessors = postProcessorVolumes
|
||||
.Where(c => c.InjectionPoint == CustomPostProcessInjectionPoint.AfterPostProcess)
|
||||
.OrderBy(c => c.OrderInInjectionPoint)
|
||||
.ToList();
|
||||
afterPostProcessPass = new ScriptablePostProcessorPass("Custom PostProcessor - after PostProcessing", afterPostProcessPostProcessors)
|
||||
{
|
||||
renderPassEvent = RenderPassEvent.AfterRenderingPostProcessing
|
||||
};
|
||||
}
|
||||
|
||||
public override void AddRenderPasses(ScriptableRenderer renderer, ref RenderingData renderingData)
|
||||
{
|
||||
if (renderingData.cameraData.postProcessEnabled)
|
||||
{
|
||||
if (afterTransparentPass.Setup(ref renderingData))
|
||||
{
|
||||
afterTransparentPass.ConfigureInput(ScriptableRenderPassInput.Color);
|
||||
renderer.EnqueuePass(afterTransparentPass);
|
||||
}
|
||||
|
||||
if (beforePostProcessPass.Setup(ref renderingData))
|
||||
{
|
||||
beforePostProcessPass.ConfigureInput(ScriptableRenderPassInput.Color);
|
||||
renderer.EnqueuePass(beforePostProcessPass);
|
||||
}
|
||||
|
||||
if (afterPostProcessPass.Setup(ref renderingData))
|
||||
{
|
||||
afterPostProcessPass.ConfigureInput(ScriptableRenderPassInput.Color);
|
||||
renderer.EnqueuePass(afterPostProcessPass);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
if (disposing)
|
||||
{
|
||||
// 关键点:调用 Pass 的清理函数,销毁缓存池中的材质
|
||||
afterTransparentPass?.Cleanup();
|
||||
beforePostProcessPass?.Cleanup();
|
||||
afterPostProcessPass?.Cleanup();
|
||||
|
||||
afterTransparentPass = null;
|
||||
beforePostProcessPass = null;
|
||||
afterPostProcessPass = null;
|
||||
postProcessorVolumes = null;
|
||||
}
|
||||
base.Dispose(disposing);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 278f6128b25bcd644b3e798a37d9827b
|
||||
@@ -0,0 +1,159 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Rendering;
|
||||
using UnityEngine.Rendering.RenderGraphModule;
|
||||
using UnityEngine.Rendering.Universal;
|
||||
|
||||
namespace SLSUtilities.Rendering.PostProcessing
|
||||
{
|
||||
public class ScriptablePostProcessorPass : ScriptableRenderPass
|
||||
{
|
||||
private List<ScriptablePostProcessorVolume> postProcessors;
|
||||
private List<int> activePostProcessorIndex;
|
||||
|
||||
private string profilerTag;
|
||||
private List<ProfilingSampler> profilingSamplers;
|
||||
|
||||
// 核心:材质缓存池,确保每个 Shader 只对应一个材质实例
|
||||
private Dictionary<string, Material> m_MaterialCache = new Dictionary<string, Material>();
|
||||
|
||||
public ScriptablePostProcessorPass(string profilerTag, List<ScriptablePostProcessorVolume> postProcessors)
|
||||
{
|
||||
this.profilerTag = profilerTag;
|
||||
this.postProcessors = postProcessors;
|
||||
activePostProcessorIndex = new List<int>(postProcessors.Count);
|
||||
profilingSamplers = postProcessors.Select(c => new ProfilingSampler(c.ToString())).ToList();
|
||||
}
|
||||
|
||||
private RenderingData m_RenderingData;
|
||||
|
||||
// 清理函数,由 Feature.Dispose 调用
|
||||
public void Cleanup()
|
||||
{
|
||||
foreach (var mat in m_MaterialCache.Values)
|
||||
{
|
||||
if (mat != null) CoreUtils.Destroy(mat);
|
||||
}
|
||||
m_MaterialCache.Clear();
|
||||
}
|
||||
|
||||
private Material GetOrCreateMaterial(string shaderName)
|
||||
{
|
||||
if (string.IsNullOrEmpty(shaderName)) return null;
|
||||
if (m_MaterialCache.TryGetValue(shaderName, out var mat) && mat != null) return mat;
|
||||
|
||||
// 调用你的静态工具类创建材质
|
||||
var shader = Shader.Find(shaderName);
|
||||
if (shader == null) return null;
|
||||
|
||||
mat = CoreUtils.CreateEngineMaterial(shader);
|
||||
m_MaterialCache[shaderName] = mat;
|
||||
return mat;
|
||||
}
|
||||
|
||||
private class PassData
|
||||
{
|
||||
public TextureHandle SourceTexture;
|
||||
public TextureHandle TargetTexture;
|
||||
public TextureHandle TempTextureA;
|
||||
public TextureHandle TempTextureB;
|
||||
public List<int> ActiveIndices;
|
||||
public List<ScriptablePostProcessorVolume> Volumes;
|
||||
public List<ProfilingSampler> Profilers;
|
||||
public RenderingData RenderingData;
|
||||
}
|
||||
|
||||
public bool Setup(ref RenderingData renderingData)
|
||||
{
|
||||
this.m_RenderingData = renderingData;
|
||||
|
||||
activePostProcessorIndex.Clear();
|
||||
for (int i = 0; i < postProcessors.Count; i++)
|
||||
{
|
||||
var volume = postProcessors[i];
|
||||
// 关键修复:从 Pass 的缓存池获取材质并注入给 Volume
|
||||
var mat = GetOrCreateMaterial(volume.GetShaderName());
|
||||
volume.SetMaterial(mat);
|
||||
|
||||
volume.Setup();
|
||||
if (volume.IsActive())
|
||||
{
|
||||
activePostProcessorIndex.Add(i);
|
||||
}
|
||||
}
|
||||
return activePostProcessorIndex.Count != 0;
|
||||
}
|
||||
|
||||
public override void RecordRenderGraph(RenderGraph renderGraph, ContextContainer frameData)
|
||||
{
|
||||
var resourceData = frameData.Get<UniversalResourceData>();
|
||||
var cameraData = frameData.Get<UniversalCameraData>();
|
||||
|
||||
if (activePostProcessorIndex.Count == 0) return;
|
||||
|
||||
var cameraDesc = cameraData.cameraTargetDescriptor;
|
||||
var rgDesc = new TextureDesc(cameraDesc.width, cameraDesc.height);
|
||||
rgDesc.colorFormat = cameraDesc.graphicsFormat;
|
||||
rgDesc.depthBufferBits = DepthBits.None;
|
||||
rgDesc.msaaSamples = MSAASamples.None;
|
||||
|
||||
using (var builder = renderGraph.AddUnsafePass<PassData>(profilerTag, out var passData))
|
||||
{
|
||||
passData.SourceTexture = resourceData.activeColorTexture;
|
||||
passData.TargetTexture = resourceData.activeColorTexture;
|
||||
passData.ActiveIndices = activePostProcessorIndex;
|
||||
passData.Volumes = postProcessors;
|
||||
passData.Profilers = profilingSamplers;
|
||||
passData.RenderingData = m_RenderingData;
|
||||
|
||||
rgDesc.name = "_TemporaryRenderTextureA";
|
||||
passData.TempTextureA = renderGraph.CreateTexture(rgDesc);
|
||||
|
||||
rgDesc.name = "_TemporaryRenderTextureB";
|
||||
passData.TempTextureB = renderGraph.CreateTexture(rgDesc);
|
||||
|
||||
builder.UseTexture(passData.SourceTexture, AccessFlags.Read);
|
||||
builder.UseTexture(passData.TempTextureA, AccessFlags.ReadWrite);
|
||||
builder.UseTexture(passData.TempTextureB, AccessFlags.ReadWrite);
|
||||
builder.UseTexture(passData.TargetTexture, AccessFlags.ReadWrite);
|
||||
|
||||
builder.SetRenderFunc((PassData data, UnsafeGraphContext context) =>
|
||||
{
|
||||
var cmd = CommandBufferHelpers.GetNativeCommandBuffer(context.cmd);
|
||||
var source = data.SourceTexture;
|
||||
var target = data.TargetTexture;
|
||||
var tempA = data.TempTextureA;
|
||||
var tempB = data.TempTextureB;
|
||||
|
||||
if (data.ActiveIndices.Count == 1)
|
||||
{
|
||||
int index = data.ActiveIndices[0];
|
||||
using (new ProfilingScope(cmd, data.Profilers[index]))
|
||||
{
|
||||
data.Volumes[index].Render(cmd, ref data.RenderingData, source, tempA);
|
||||
}
|
||||
Blitter.BlitCameraTexture(cmd, tempA, target);
|
||||
}
|
||||
else
|
||||
{
|
||||
Blitter.BlitCameraTexture(cmd, source, tempA);
|
||||
var currSource = tempA;
|
||||
var currDest = tempB;
|
||||
|
||||
foreach (int index in data.ActiveIndices)
|
||||
{
|
||||
var postProcessor = data.Volumes[index];
|
||||
using (new ProfilingScope(cmd, data.Profilers[index]))
|
||||
{
|
||||
postProcessor.Render(cmd, ref data.RenderingData, currSource, currDest);
|
||||
}
|
||||
CoreUtils.Swap(ref currSource, ref currDest);
|
||||
}
|
||||
Blitter.BlitCameraTexture(cmd, currSource, target);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 5c198108d8fe5ea4fad878bf9623c573
|
||||
@@ -0,0 +1,41 @@
|
||||
using System;
|
||||
using Echovoid.Runtime.Behavior.Rendering;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Rendering;
|
||||
using UnityEngine.Rendering.Universal;
|
||||
|
||||
namespace SLSUtilities.Rendering.PostProcessing
|
||||
{
|
||||
public enum CustomPostProcessInjectionPoint
|
||||
{
|
||||
AfterTransparent,
|
||||
BeforePostProcess,
|
||||
AfterPostProcess
|
||||
}
|
||||
|
||||
public abstract class ScriptablePostProcessorVolume : VolumeComponent, IPostProcessComponent
|
||||
{
|
||||
public virtual CustomPostProcessInjectionPoint InjectionPoint =>
|
||||
CustomPostProcessInjectionPoint.AfterPostProcess;
|
||||
|
||||
public virtual int OrderInInjectionPoint => 0;
|
||||
|
||||
protected Material material;
|
||||
|
||||
// 注入材质的句柄,由 Pass 调用
|
||||
public void SetMaterial(Material mat) => material = mat;
|
||||
|
||||
public abstract string GetShaderName();
|
||||
|
||||
public virtual void Setup()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public abstract void Render(CommandBuffer cmd, ref RenderingData renderingData, RTHandle source, RTHandle destination);
|
||||
|
||||
public abstract bool IsActive();
|
||||
|
||||
public bool IsTileCompatible() => false;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: da1ac4541bff9ba4980b8e18d53bb76e
|
||||
8
Assets/Shaders/ScriptablePostProcessor/Shaders.meta
Normal file
8
Assets/Shaders/ScriptablePostProcessor/Shaders.meta
Normal file
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: f9d89e0aea11e6947bb9f9c65db23e43
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,122 @@
|
||||
Shader "SLS/Postprocessing/AdvancedChromaticAberration"
|
||||
{
|
||||
SubShader
|
||||
{
|
||||
Tags
|
||||
{
|
||||
"RenderType" = "Opaque"
|
||||
"RenderPipeline" = "UniversalPipeline"
|
||||
}
|
||||
ZWrite Off
|
||||
Cull Off
|
||||
|
||||
HLSLINCLUDE
|
||||
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"
|
||||
#include "Packages/com.unity.render-pipelines.core/Runtime/Utilities/Blit.hlsl"
|
||||
|
||||
// --- 参数定义 ---
|
||||
float4 _ACA_Params1;
|
||||
// x: Intensity (总强度)
|
||||
// y: Center X
|
||||
// z: Center Y
|
||||
// w: Mask Radius (中心保留半径)
|
||||
|
||||
float4 _ACA_Params2;
|
||||
// x: Jitter Intensity
|
||||
// y: Jitter Speed
|
||||
// z: Dispersion Map Strength (贴图影响力度)
|
||||
// w: Mask Hardness (边缘硬度)
|
||||
|
||||
float4 _ACA_Split; // x: R权重, y: G权重, z: B权重
|
||||
|
||||
// 纹理
|
||||
TEXTURE2D(_DispersionMap);
|
||||
SAMPLER(sampler_DispersionMap); // 建议设置为 Repeat 模式
|
||||
|
||||
// --- 辅助函数 ---
|
||||
|
||||
// 简单的伪随机函数 (0-1)
|
||||
float random(float2 uv)
|
||||
{
|
||||
return frac(sin(dot(uv, float2(12.9898, 78.233))) * 43758.5453123);
|
||||
}
|
||||
|
||||
half4 Frag(Varyings input) : SV_Target
|
||||
{
|
||||
float2 uv = input.texcoord;
|
||||
|
||||
// 1. 参数解包
|
||||
float intensity = _ACA_Params1.x;
|
||||
float2 center = _ACA_Params1.yz;
|
||||
float maskRadius = _ACA_Params1.w;
|
||||
|
||||
float jitterAmount = _ACA_Params2.x;
|
||||
float jitterSpeed = _ACA_Params2.y;
|
||||
float mapStrength = _ACA_Params2.z;
|
||||
float maskHardness = _ACA_Params2.w;
|
||||
|
||||
float3 splitWeights = _ACA_Split.rgb;
|
||||
|
||||
// 2. 计算基础方向向量 (径向)
|
||||
float2 dir = uv - center;
|
||||
float dist = length(dir);
|
||||
|
||||
// 3. 计算中心遮罩 (Vignette Mask)
|
||||
// 距离小于 Radius 的地方强度为 0,向外渐变
|
||||
float mask = smoothstep(maskRadius, maskRadius + maskHardness, dist);
|
||||
|
||||
// 如果在遮罩内,直接返回原图,节省性能
|
||||
// (为了 Jitter 的连贯性,这里我们只把 mask 乘到 offset 上,不直接 return)
|
||||
|
||||
// 4. 计算 Jitter (采样抖动)
|
||||
// 利用 Time 和 UV 做随机,模拟不稳定的信号
|
||||
float timeVal = _Time.y * jitterSpeed;
|
||||
// 这里的 floor 模拟“跳动”的帧率感,如果想要平滑 jitter 可以去掉 floor
|
||||
float2 jitterUV = uv + float2(random(uv + timeVal), random(uv - timeVal)) * 0.1;
|
||||
float2 jitterOffset = (float2(random(jitterUV), random(jitterUV * 1.5)) - 0.5) * 2.0; // -1 ~ 1
|
||||
jitterOffset *= jitterAmount * 0.05; // 缩放幅度
|
||||
|
||||
// 5. 采样 Dispersion Map (破碎感)
|
||||
// 让贴图随时间缓慢流动一点点,或者固定
|
||||
float4 noiseTex = SAMPLE_TEXTURE2D(_DispersionMap, sampler_DispersionMap, uv * 3.0 + jitterOffset); // 缩放 UV
|
||||
float noiseFactor = noiseTex.r * 2.0 - 1.0; // -1 ~ 1
|
||||
|
||||
// 混合 Map 影响
|
||||
// 如果 mapStrength 为 0,则 noiseFactor 为 0 (不影响),我们希望默认为 1
|
||||
float finalNoise = lerp(1.0, noiseFactor, mapStrength);
|
||||
|
||||
// 6. 组合最终偏移量
|
||||
// 基础方向 * (1 + 噪声) + 抖动
|
||||
float2 finalOffset = dir * finalNoise;
|
||||
|
||||
// 加上纯粹的位置抖动 (不依赖方向)
|
||||
finalOffset += jitterOffset;
|
||||
|
||||
// 应用遮罩和总强度
|
||||
finalOffset *= mask * intensity;
|
||||
|
||||
// 7. 分离通道采样
|
||||
// 注意:URP 的 _BlitTexture 采样时最好 Clamp,防止边缘溢出
|
||||
float2 uvR = uv - finalOffset * splitWeights.r;
|
||||
float2 uvG = uv - finalOffset * splitWeights.g;
|
||||
float2 uvB = uv - finalOffset * splitWeights.b;
|
||||
|
||||
half r = SAMPLE_TEXTURE2D_X(_BlitTexture, sampler_LinearClamp, uvR).r;
|
||||
half g = SAMPLE_TEXTURE2D_X(_BlitTexture, sampler_LinearClamp, uvG).g;
|
||||
half b = SAMPLE_TEXTURE2D_X(_BlitTexture, sampler_LinearClamp, uvB).b;
|
||||
|
||||
// 8. 重新组合
|
||||
return half4(r, g, b, 1.0);
|
||||
}
|
||||
ENDHLSL
|
||||
|
||||
Pass
|
||||
{
|
||||
Name "Advanced Chromatic Aberration"
|
||||
HLSLPROGRAM
|
||||
#pragma vertex Vert
|
||||
#pragma fragment Frag
|
||||
ENDHLSL
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
fileFormatVersion: 2
|
||||
guid: c195927c5e8d7b54482f7cc52dc314df
|
||||
ShaderImporter:
|
||||
externalObjects: {}
|
||||
defaultTextures: []
|
||||
nonModifiableTextures: []
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,90 @@
|
||||
Shader "SLS/Postprocessing/AdvancedVignette"
|
||||
{
|
||||
SubShader
|
||||
{
|
||||
Tags
|
||||
{
|
||||
"RenderType" = "Opaque"
|
||||
"RenderPipeline" = "UniversalPipeline"
|
||||
}
|
||||
ZWrite Off
|
||||
Cull Off
|
||||
|
||||
HLSLINCLUDE
|
||||
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"
|
||||
#include "Packages/com.unity.render-pipelines.core/Runtime/Utilities/Blit.hlsl"
|
||||
|
||||
// --- 参数定义 ---
|
||||
float4 _VignetteColors; // xy: Unused, z: Unused, w: Unused (颜色单独传)
|
||||
float4 _ColorInner; // 内部颜色 (过渡色)
|
||||
float4 _ColorOuter; // 外部颜色 (边缘色)
|
||||
|
||||
float3 _VignetteParams1;
|
||||
// x: Intensity (强度)
|
||||
// y: Smoothness (柔和度)
|
||||
// z: Roundness (圆度)
|
||||
|
||||
float4 _VignetteCenter; // xy: Center
|
||||
|
||||
// 简单的伪随机噪声函数 (用于 Dithering)
|
||||
float Random(float2 uv)
|
||||
{
|
||||
return frac(sin(dot(uv, float2(12.9898, 78.233))) * 43758.5453);
|
||||
}
|
||||
|
||||
half4 Frag(Varyings input) : SV_Target
|
||||
{
|
||||
float2 uv = input.texcoord;
|
||||
|
||||
// 1. 参数解包
|
||||
float intensity = _VignetteParams1.x;
|
||||
float smoothness = max(0.001, _VignetteParams1.y);
|
||||
float roundness = _VignetteParams1.z;
|
||||
float2 center = _VignetteCenter.xy;
|
||||
|
||||
half3 colInner = _ColorInner.rgb;
|
||||
half3 colOuter = _ColorOuter.rgb;
|
||||
|
||||
// 2. 计算距离场 (SDF)
|
||||
float2 d = uv - center;
|
||||
|
||||
// 圆度计算
|
||||
d = d * lerp(1.0, 0.5, roundness);
|
||||
float vdist = length(d);
|
||||
float boxDist = max(abs(d.x), abs(d.y));
|
||||
vdist = lerp(boxDist, vdist, roundness);
|
||||
|
||||
// 3. 计算遮罩 (Mask)
|
||||
// 归一化距离,使其适配 Intensity
|
||||
float maxDist = 0.8;
|
||||
float threshold = 1.0 - intensity;
|
||||
|
||||
// 计算平滑的 0-1 遮罩值
|
||||
// mask = 0 (中心区域,显示原图) -> 1 (边缘区域,显示暗角)
|
||||
float mask = smoothstep(threshold - smoothness * 0.5, threshold + smoothness * 0.5, vdist * 2.0);
|
||||
|
||||
// 5. 计算最终暗角颜色 (Gradient)
|
||||
// 随着 mask 从 0 变到 1,颜色从 Inner 变到 Outer
|
||||
// 我们可以用 mask 本身作为插值系数,或者用 vdist
|
||||
// 这里用 mask 保证颜色变化与透明度变化同步
|
||||
half3 finalVignetteColor = lerp(colInner, colOuter, mask);
|
||||
|
||||
// 6. 混合原图
|
||||
half4 sceneColor = SAMPLE_TEXTURE2D_X(_BlitTexture, sampler_LinearClamp, uv);
|
||||
|
||||
// sceneColor * (1 - mask) + vignetteColor * mask
|
||||
// 即:Lerp(sceneColor, finalVignetteColor, mask)
|
||||
return lerp(sceneColor, half4(finalVignetteColor, 1), mask);
|
||||
}
|
||||
ENDHLSL
|
||||
|
||||
Pass
|
||||
{
|
||||
Name "Advanced Vignette"
|
||||
HLSLPROGRAM
|
||||
#pragma vertex Vert
|
||||
#pragma fragment Frag
|
||||
ENDHLSL
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
fileFormatVersion: 2
|
||||
guid: e9424f71b68fc594b82da3259df1d2c5
|
||||
ShaderImporter:
|
||||
externalObjects: {}
|
||||
defaultTextures: []
|
||||
nonModifiableTextures: []
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
109
Assets/Shaders/ScriptablePostProcessor/Shaders/AnimeACES.shader
Normal file
109
Assets/Shaders/ScriptablePostProcessor/Shaders/AnimeACES.shader
Normal file
@@ -0,0 +1,109 @@
|
||||
Shader "SLS/Postprocessing/AnimeACES"
|
||||
{
|
||||
SubShader
|
||||
{
|
||||
Tags
|
||||
{
|
||||
"RenderType" = "Opaque"
|
||||
"RenderPipeline" = "UniversalPipeline"
|
||||
}
|
||||
ZWrite Off
|
||||
Cull Off
|
||||
ZTest Always
|
||||
|
||||
Pass
|
||||
{
|
||||
Name "Anime ACES Tonemapping"
|
||||
Blend Off // 强制覆盖
|
||||
|
||||
HLSLPROGRAM
|
||||
#pragma vertex Vert
|
||||
#pragma fragment Frag
|
||||
|
||||
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"
|
||||
#include "Packages/com.unity.render-pipelines.core/Runtime/Utilities/Blit.hlsl"
|
||||
|
||||
// --- 参数定义 ---
|
||||
float4 _TonemapParams;
|
||||
// x: Exposure
|
||||
// y: Contrast
|
||||
// z: Saturation
|
||||
// w: Hue Preservation (新增:色彩保留强度 0-1)
|
||||
|
||||
float4 _ACESCoeffs;
|
||||
// x: A, y: B, z: C, w: D
|
||||
|
||||
float _ACES_E; // E
|
||||
|
||||
float4 _ColorFilter;
|
||||
|
||||
// Narkowicz ACES 曲线
|
||||
float3 ACESCurve(float3 x)
|
||||
{
|
||||
float a = _ACESCoeffs.x;
|
||||
float b = _ACESCoeffs.y;
|
||||
float c = _ACESCoeffs.z;
|
||||
float d = _ACESCoeffs.w;
|
||||
float e = _ACES_E;
|
||||
|
||||
return saturate((x * (a * x + b)) / (x * (c * x + d) + e));
|
||||
}
|
||||
|
||||
// 标量版本
|
||||
float ACESCurve(float x)
|
||||
{
|
||||
float a = _ACESCoeffs.x;
|
||||
float b = _ACESCoeffs.y;
|
||||
float c = _ACESCoeffs.z;
|
||||
float d = _ACESCoeffs.w;
|
||||
float e = _ACES_E;
|
||||
|
||||
return saturate((x * (a * x + b)) / (x * (c * x + d) + e));
|
||||
}
|
||||
|
||||
half4 Frag(Varyings input) : SV_Target
|
||||
{
|
||||
float2 uv = input.texcoord;
|
||||
half4 sceneColor = SAMPLE_TEXTURE2D_X(_BlitTexture, sampler_LinearClamp, uv);
|
||||
half3 color = sceneColor.rgb;
|
||||
|
||||
// 1. Exposure (曝光)
|
||||
color *= _TonemapParams.x;
|
||||
|
||||
// 2. Contrast (对比度) - 【核心修正】
|
||||
// Pivot 从 0.5 改为 0.18 (Linear Middle Gray)
|
||||
// 这样增加对比度会压暗阴影,而不是提亮阴影
|
||||
float midGray = 0.18;
|
||||
color = (color - midGray) * _TonemapParams.y + midGray;
|
||||
color = max(0, color);
|
||||
|
||||
// 3. ACES Tonemapping with Hue Preservation (色彩保留) - 【核心修正】
|
||||
float huePreserve = _TonemapParams.w;
|
||||
|
||||
// A. 标准 ACES (会吃色,RGB 通道独立压缩)
|
||||
float3 acesFit = ACESCurve(color);
|
||||
|
||||
// B. 亮度 ACES (不吃色,只压缩亮度)
|
||||
float lum = Luminance(color);
|
||||
float lumTonemapped = ACESCurve(lum);
|
||||
// 重建颜色:保持原色相,只改变亮度
|
||||
float3 colorPreserved = color * (lumTonemapped / max(lum, 1e-4));
|
||||
|
||||
// 混合两者:二次元通常希望皮肤保色(B),但场景光影有电影感(A)
|
||||
// 建议 Hue Preservation 设为 0.5 左右
|
||||
color = lerp(acesFit, colorPreserved, huePreserve);
|
||||
|
||||
// 4. Saturation (饱和度)
|
||||
// 重新计算亮度进行饱和度调整
|
||||
float finalLum = Luminance(color);
|
||||
color = lerp(finalLum.xxx, color, _TonemapParams.z);
|
||||
|
||||
// 5. Color Filter
|
||||
color *= _ColorFilter.rgb;
|
||||
|
||||
return half4(color, sceneColor.a);
|
||||
}
|
||||
ENDHLSL
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
fileFormatVersion: 2
|
||||
guid: d66798f4c56ff9d43bf821e0cd4f4b95
|
||||
ShaderImporter:
|
||||
externalObjects: {}
|
||||
defaultTextures: []
|
||||
nonModifiableTextures: []
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
163
Assets/Shaders/ScriptablePostProcessor/Shaders/AnimeBloom.shader
Normal file
163
Assets/Shaders/ScriptablePostProcessor/Shaders/AnimeBloom.shader
Normal file
@@ -0,0 +1,163 @@
|
||||
Shader "SLS/Postprocessing/AnimeBloom"
|
||||
{
|
||||
Properties
|
||||
{
|
||||
_MainTex ("Texture", 2D) = "white" {}
|
||||
}
|
||||
|
||||
HLSLINCLUDE
|
||||
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"
|
||||
#include "Packages/com.unity.render-pipelines.core/Runtime/Utilities/Blit.hlsl"
|
||||
|
||||
// --- 参数定义 ---
|
||||
float4 _BloomParams; // x: Intensity, y: Threshold, z: SoftKnee, w: Clamp
|
||||
float4 _BloomTint; // 泛光染色
|
||||
float _BlurRadius; // 模糊扩散半径 (控制光晕大小的关键)
|
||||
|
||||
// 纹理
|
||||
TEXTURE2D(_BloomTex);
|
||||
SAMPLER(sampler_BloomTex);
|
||||
|
||||
// --- 辅助函数:Prefilter (提取高亮) ---
|
||||
half3 Prefilter(half3 color)
|
||||
{
|
||||
float threshold = _BloomParams.y;
|
||||
float softKnee = _BloomParams.z;
|
||||
float clampVal = _BloomParams.w;
|
||||
|
||||
// 1. 限制最大亮度 (防闪烁/萤火虫噪点)
|
||||
color = min(color, clampVal);
|
||||
|
||||
// 2. 阈值计算 (使用 Soft Knee 曲线让过渡更自然)
|
||||
// 标准公式:(Brightness - Threshold) / max(Brightness, 0.0001)
|
||||
// 这里使用一个更平滑的曲线版本,防止高光边缘切变太硬
|
||||
float brightness = Max3(color.r, color.g, color.b);
|
||||
float soft = brightness - threshold + softKnee;
|
||||
soft = clamp(soft, 0, 2 * softKnee);
|
||||
soft = soft * soft / (4 * softKnee + 1e-4);
|
||||
|
||||
float contribution = max(soft, brightness - threshold);
|
||||
contribution /= max(brightness, 1e-4);
|
||||
|
||||
return color * contribution;
|
||||
}
|
||||
|
||||
// --- Pass 0: Prefilter ---
|
||||
half4 FragPrefilter(Varyings input) : SV_Target
|
||||
{
|
||||
// 采样原图
|
||||
half4 color = SAMPLE_TEXTURE2D_X(_BlitTexture, sampler_LinearClamp, input.texcoord);
|
||||
// 提取高亮
|
||||
half3 bloom = Prefilter(color.rgb);
|
||||
return half4(bloom, 1.0);
|
||||
}
|
||||
|
||||
// --- Pass 1: Downsample (Kawase 4-Tap) ---
|
||||
// 降采样:取 4 个对角像素的平均值,范围随分辨率降低而扩大
|
||||
half4 FragDownsample(Varyings input) : SV_Target
|
||||
{
|
||||
float2 uv = input.texcoord;
|
||||
float4 texelSize = _BlitTexture_TexelSize;
|
||||
|
||||
// 扩散偏移量,随 BlurRadius 调整
|
||||
float2 offset = texelSize.xy * _BlurRadius;
|
||||
|
||||
half3 c0 = SAMPLE_TEXTURE2D_X(_BlitTexture, sampler_LinearClamp, uv - offset).rgb;
|
||||
half3 c1 = SAMPLE_TEXTURE2D_X(_BlitTexture, sampler_LinearClamp, uv + float2(offset.x, -offset.y)).rgb;
|
||||
half3 c2 = SAMPLE_TEXTURE2D_X(_BlitTexture, sampler_LinearClamp, uv - float2(offset.x, -offset.y)).rgb;
|
||||
half3 c3 = SAMPLE_TEXTURE2D_X(_BlitTexture, sampler_LinearClamp, uv + offset).rgb;
|
||||
|
||||
half3 color = (c0 + c1 + c2 + c3) * 0.25;
|
||||
return half4(color, 1.0);
|
||||
}
|
||||
|
||||
// --- Pass 2: Upsample (Kawase 4-Tap + Blend) ---
|
||||
// 升采样:高质量混合。
|
||||
// 这里采用 Dual Kawase 的升采样逻辑,混合上一级纹理
|
||||
half4 FragUpsample(Varyings input) : SV_Target
|
||||
{
|
||||
float2 uv = input.texcoord;
|
||||
float4 texelSize = _BlitTexture_TexelSize;
|
||||
float2 offset = texelSize.xy * _BlurRadius * 0.5; // 升采样时半径减半,为了更平滑
|
||||
|
||||
// 4-Tap 采样高一级的纹理
|
||||
half3 c0 = SAMPLE_TEXTURE2D_X(_BlitTexture, sampler_LinearClamp, uv - offset * float2(1, 1)).rgb;
|
||||
half3 c1 = SAMPLE_TEXTURE2D_X(_BlitTexture, sampler_LinearClamp, uv + offset * float2(1, -1)).rgb;
|
||||
half3 c2 = SAMPLE_TEXTURE2D_X(_BlitTexture, sampler_LinearClamp, uv - offset * float2(1, -1)).rgb;
|
||||
half3 c3 = SAMPLE_TEXTURE2D_X(_BlitTexture, sampler_LinearClamp, uv + offset * float2(1, 1)).rgb;
|
||||
|
||||
half3 blur = (c0 + c1 + c2 + c3) * 0.25;
|
||||
|
||||
// 这一步在 C# 中是通过 Blit 叠加到上一级 RT 上的
|
||||
// 所以这里直接输出 blur 结果,混合模式设为 Add 即可
|
||||
return half4(blur, 1.0);
|
||||
}
|
||||
|
||||
// --- Pass 3: Composite (最终合成) ---
|
||||
half4 FragComposite(Varyings input) : SV_Target
|
||||
{
|
||||
float2 uv = input.texcoord;
|
||||
|
||||
// 原始画面
|
||||
half4 baseColor = SAMPLE_TEXTURE2D_X(_BlitTexture, sampler_LinearClamp, uv);
|
||||
|
||||
// 泛光结果 (经过多次升采样后的最终纹理)
|
||||
half3 bloom = SAMPLE_TEXTURE2D(_BloomTex, sampler_BloomTex, uv).rgb;
|
||||
|
||||
// 应用强度和染色
|
||||
bloom *= _BloomParams.x * _BloomTint.rgb;
|
||||
|
||||
// 叠加 (Additive)
|
||||
// 也可以尝试 Screen 混合模式让光变得更柔和,但 Additive 最符合物理发光
|
||||
return half4(baseColor.rgb + bloom, baseColor.a);
|
||||
}
|
||||
|
||||
ENDHLSL
|
||||
|
||||
SubShader
|
||||
{
|
||||
Tags { "RenderType"="Opaque" "RenderPipeline"="UniversalPipeline" }
|
||||
ZWrite Off Cull Off
|
||||
|
||||
// 0: Prefilter
|
||||
Pass
|
||||
{
|
||||
Name "Bloom Prefilter"
|
||||
HLSLPROGRAM
|
||||
#pragma vertex Vert
|
||||
#pragma fragment FragPrefilter
|
||||
ENDHLSL
|
||||
}
|
||||
|
||||
// 1: Downsample
|
||||
Pass
|
||||
{
|
||||
Name "Bloom Downsample"
|
||||
HLSLPROGRAM
|
||||
#pragma vertex Vert
|
||||
#pragma fragment FragDownsample
|
||||
ENDHLSL
|
||||
}
|
||||
|
||||
// 2: Upsample
|
||||
Pass
|
||||
{
|
||||
Name "Bloom Upsample"
|
||||
Blend One One // Additive Blend for upsampling accumulation
|
||||
HLSLPROGRAM
|
||||
#pragma vertex Vert
|
||||
#pragma fragment FragUpsample
|
||||
ENDHLSL
|
||||
}
|
||||
|
||||
// 3: Composite
|
||||
Pass
|
||||
{
|
||||
Name "Bloom Composite"
|
||||
HLSLPROGRAM
|
||||
#pragma vertex Vert
|
||||
#pragma fragment FragComposite
|
||||
ENDHLSL
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 3bc1d4066f58f6e47aeb7c358d24d593
|
||||
ShaderImporter:
|
||||
externalObjects: {}
|
||||
defaultTextures: []
|
||||
nonModifiableTextures: []
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,42 @@
|
||||
Shader "Hidden/Custom/Pixelate"
|
||||
{
|
||||
SubShader
|
||||
{
|
||||
Tags { "RenderPipeline" = "UniversalPipeline" }
|
||||
ZTest Always Cull Off ZWrite Off
|
||||
|
||||
Pass
|
||||
{
|
||||
Name "PixelatePass"
|
||||
|
||||
HLSLPROGRAM
|
||||
#pragma vertex Vert
|
||||
#pragma fragment Frag
|
||||
|
||||
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"
|
||||
// URP 提供的前端 Blit 工具,拥有内置的 Varyings, Vert 函数和防颠倒运算
|
||||
#include "Packages/com.unity.render-pipelines.core/Runtime/Utilities/Blit.hlsl"
|
||||
|
||||
float _PixelateStrengthX;
|
||||
float _PixelateStrengthY;
|
||||
|
||||
half4 Frag(Varyings input) : SV_Target
|
||||
{
|
||||
float2 uv = input.texcoord;
|
||||
float2 strength = float2(_PixelateStrengthX, _PixelateStrengthY);
|
||||
|
||||
// 防止除数为0的极小可能崩溃
|
||||
strength = max(strength, float2(1.0, 1.0));
|
||||
|
||||
float2 uvScaled = uv * strength;
|
||||
float2 uvFloor = floor(uvScaled);
|
||||
float2 uvCenter = uvFloor + 0.5;
|
||||
float2 uvPixelated = uvCenter / strength;
|
||||
|
||||
// Blitter框架将自动把 SourceTexture 注入为 _BlitTexture
|
||||
return SAMPLE_TEXTURE2D_X(_BlitTexture, sampler_LinearClamp, uvPixelated);
|
||||
}
|
||||
ENDHLSL
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 4bfe329b76eedf443b922d74642c32a7
|
||||
ShaderImporter:
|
||||
externalObjects: {}
|
||||
defaultTextures: []
|
||||
nonModifiableTextures: []
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,57 @@
|
||||
Shader "SLS/Postprocessing/RGBSplitGlitch"
|
||||
{
|
||||
SubShader
|
||||
{
|
||||
Tags
|
||||
{
|
||||
"RenderType" = "Opaque"
|
||||
"RenderPipeline" = "UniversalPipeline"
|
||||
}
|
||||
ZWrite Off
|
||||
Cull Off
|
||||
|
||||
HLSLINCLUDE
|
||||
// 1. 引入 Unity 核心库 (替代原本的 #include "PostProcessingPass.hlsl")
|
||||
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"
|
||||
// 引入 Blit 库以获得 Vert 顶点函数和 _BlitTexture
|
||||
#include "Packages/com.unity.render-pipelines.core/Runtime/Utilities/Blit.hlsl"
|
||||
|
||||
// 2. 定义该效果专用的变量
|
||||
float4 _RGBSplitGlitchParams;
|
||||
#define _RGBSplitGlitchIntensity _RGBSplitGlitchParams.x
|
||||
#define _TimeX _RGBSplitGlitchParams.y
|
||||
|
||||
// 3. 辅助函数 (仅在此 Shader 内部使用)
|
||||
float randomNoise(float x, float y)
|
||||
{
|
||||
return frac(sin(dot(float2(x, y), float2(12.9898, 78.233))) * 43758.5453);
|
||||
}
|
||||
|
||||
// 4. 片段着色器逻辑
|
||||
float4 RGBSplitGlitchPassFragment(Varyings input) : SV_Target
|
||||
{
|
||||
UNITY_SETUP_STEREO_EYE_INDEX_POST_VERTEX(input);
|
||||
|
||||
float splitAmount = _RGBSplitGlitchIntensity * randomNoise(_TimeX, 2);
|
||||
|
||||
// 使用 _BlitTexture 采样当前画面
|
||||
half4 colorR = SAMPLE_TEXTURE2D_X(_BlitTexture, sampler_LinearClamp, input.texcoord);
|
||||
half4 colorG = SAMPLE_TEXTURE2D_X(_BlitTexture, sampler_LinearClamp,
|
||||
float2(input.texcoord.x + splitAmount, input.texcoord.y + splitAmount));
|
||||
half4 colorB = SAMPLE_TEXTURE2D_X(_BlitTexture, sampler_LinearClamp,
|
||||
float2(input.texcoord.x - splitAmount, input.texcoord.y - splitAmount));
|
||||
|
||||
return half4(colorR.r, colorG.g, colorB.b, 1);
|
||||
}
|
||||
ENDHLSL
|
||||
|
||||
Pass
|
||||
{
|
||||
Name "RGB Split Glitch"
|
||||
HLSLPROGRAM
|
||||
#pragma vertex Vert // 使用 Blit.hlsl 中的 Vert
|
||||
#pragma fragment RGBSplitGlitchPassFragment
|
||||
ENDHLSL
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 6e8fe2c8a03163c419a4034561209dff
|
||||
ShaderImporter:
|
||||
externalObjects: {}
|
||||
defaultTextures: []
|
||||
nonModifiableTextures: []
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
117
Assets/Shaders/ScriptablePostProcessor/Shaders/RadialBlur.shader
Normal file
117
Assets/Shaders/ScriptablePostProcessor/Shaders/RadialBlur.shader
Normal file
@@ -0,0 +1,117 @@
|
||||
Shader "SLS/Postprocessing/RadialBlur"
|
||||
{
|
||||
SubShader
|
||||
{
|
||||
Tags
|
||||
{
|
||||
"RenderType" = "Opaque"
|
||||
"RenderPipeline" = "UniversalPipeline"
|
||||
}
|
||||
ZWrite Off
|
||||
Cull Off
|
||||
|
||||
HLSLINCLUDE
|
||||
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"
|
||||
#include "Packages/com.unity.render-pipelines.core/Runtime/Utilities/Blit.hlsl"
|
||||
|
||||
// 变量定义
|
||||
float4 _RadialBlurParams;
|
||||
#define _BlurRadius _RadialBlurParams.x
|
||||
#define _RadialCenter _RadialBlurParams.yz
|
||||
|
||||
// --- 具体实现函数 ---
|
||||
|
||||
half4 RadialBlurPassFragment_4Tap(Varyings input): SV_Target
|
||||
{
|
||||
float2 uv = input.texcoord - _RadialCenter;
|
||||
half scale = 1;
|
||||
half4 color = SAMPLE_TEXTURE2D_X(_BlitTexture, sampler_LinearClamp, uv * scale + _RadialCenter);
|
||||
|
||||
scale = _BlurRadius + 1;
|
||||
color += SAMPLE_TEXTURE2D_X(_BlitTexture, sampler_LinearClamp, uv * scale + _RadialCenter);
|
||||
scale = 2 * _BlurRadius + 1;
|
||||
color += SAMPLE_TEXTURE2D_X(_BlitTexture, sampler_LinearClamp, uv * scale + _RadialCenter);
|
||||
scale = 3 * _BlurRadius + 1;
|
||||
color += SAMPLE_TEXTURE2D_X(_BlitTexture, sampler_LinearClamp, uv * scale + _RadialCenter);
|
||||
|
||||
color *= 0.25f; // 1/4
|
||||
return color;
|
||||
}
|
||||
|
||||
half4 RadialBlurPassFragment_8Tap(Varyings input): SV_Target
|
||||
{
|
||||
float2 uv = input.texcoord - _RadialCenter;
|
||||
half4 color = 0;
|
||||
// 为了代码简洁,这里可以使用循环,但在 Shader 中手动展开(Unroll)通常性能更好或便于控制
|
||||
// 这里保留你原本的展开逻辑
|
||||
[unroll]
|
||||
for(int i=0; i<8; i++)
|
||||
{
|
||||
half scale = i * _BlurRadius + 1;
|
||||
color += SAMPLE_TEXTURE2D_X(_BlitTexture, sampler_LinearClamp, uv * scale + _RadialCenter);
|
||||
}
|
||||
return color * 0.125f;
|
||||
}
|
||||
|
||||
|
||||
half4 RadialBlurPassFragment_12Tap(Varyings input): SV_Target
|
||||
{
|
||||
float2 uv = input.texcoord - _RadialCenter;
|
||||
half4 color = 0;
|
||||
for(int i=0; i<12; i++) {
|
||||
half scale = i * _BlurRadius + 1;
|
||||
color += SAMPLE_TEXTURE2D_X(_BlitTexture, sampler_LinearClamp, uv * scale + _RadialCenter);
|
||||
}
|
||||
return color * 0.0833f;
|
||||
}
|
||||
|
||||
half4 RadialBlurPassFragment_16Tap(Varyings input): SV_Target
|
||||
{
|
||||
float2 uv = input.texcoord - _RadialCenter;
|
||||
half4 color = 0;
|
||||
for(int i=0; i<16; i++) {
|
||||
half scale = i * _BlurRadius + 1;
|
||||
color += SAMPLE_TEXTURE2D_X(_BlitTexture, sampler_LinearClamp, uv * scale + _RadialCenter);
|
||||
}
|
||||
return color * 0.0625f;
|
||||
}
|
||||
|
||||
ENDHLSL
|
||||
|
||||
Pass
|
||||
{
|
||||
Name "Radial Blur 4 Tap"
|
||||
HLSLPROGRAM
|
||||
#pragma vertex Vert
|
||||
#pragma fragment RadialBlurPassFragment_4Tap
|
||||
ENDHLSL
|
||||
}
|
||||
|
||||
Pass
|
||||
{
|
||||
Name "Radial Blur 8 Tap"
|
||||
HLSLPROGRAM
|
||||
#pragma vertex Vert
|
||||
#pragma fragment RadialBlurPassFragment_8Tap
|
||||
ENDHLSL
|
||||
}
|
||||
|
||||
Pass
|
||||
{
|
||||
Name "Radial Blur 12 Tap"
|
||||
HLSLPROGRAM
|
||||
#pragma vertex Vert
|
||||
#pragma fragment RadialBlurPassFragment_12Tap
|
||||
ENDHLSL
|
||||
}
|
||||
|
||||
Pass
|
||||
{
|
||||
Name "Radial Blur 16 Tap"
|
||||
HLSLPROGRAM
|
||||
#pragma vertex Vert
|
||||
#pragma fragment RadialBlurPassFragment_16Tap
|
||||
ENDHLSL
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 7528b766c67bf974e9d2eebb25b43c04
|
||||
ShaderImporter:
|
||||
externalObjects: {}
|
||||
defaultTextures: []
|
||||
nonModifiableTextures: []
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,77 @@
|
||||
Shader "SLS/Postprocessing/Sharpen"
|
||||
{
|
||||
SubShader
|
||||
{
|
||||
Tags
|
||||
{
|
||||
"RenderType" = "Opaque"
|
||||
"RenderPipeline" = "UniversalPipeline"
|
||||
}
|
||||
ZWrite Off
|
||||
Cull Off
|
||||
|
||||
HLSLINCLUDE
|
||||
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"
|
||||
#include "Packages/com.unity.render-pipelines.core/Runtime/Utilities/Blit.hlsl"
|
||||
|
||||
// 变量定义
|
||||
float4 _SharpnessParams;
|
||||
// x: Strength (锐化强度)
|
||||
// y: Threshold (对比度阈值,用于降噪)
|
||||
// z: Clamp (最大亮度变化限制,防光晕)
|
||||
// w: Unused
|
||||
|
||||
half4 SharpenPassFragment(Varyings input) : SV_Target
|
||||
{
|
||||
half2 uv = input.texcoord;
|
||||
// _BlitTexture_TexelSize 包含了纹理像素的大小 (1/width, 1/height)
|
||||
float4 texelSize = _BlitTexture_TexelSize;
|
||||
|
||||
// 1. 5-Tap 采样 (中心 + 上下左右)
|
||||
half4 center = SAMPLE_TEXTURE2D_X(_BlitTexture, sampler_LinearClamp, uv);
|
||||
half3 up = SAMPLE_TEXTURE2D_X(_BlitTexture, sampler_LinearClamp, uv + float2(0, texelSize.y)).rgb;
|
||||
half3 down = SAMPLE_TEXTURE2D_X(_BlitTexture, sampler_LinearClamp, uv - float2(0, texelSize.y)).rgb;
|
||||
half3 left = SAMPLE_TEXTURE2D_X(_BlitTexture, sampler_LinearClamp, uv - float2(texelSize.x, 0)).rgb;
|
||||
half3 right = SAMPLE_TEXTURE2D_X(_BlitTexture, sampler_LinearClamp, uv + float2(texelSize.x, 0)).rgb;
|
||||
|
||||
// 2. 计算周围像素的平均值
|
||||
half3 neighborsAvg = (up + down + left + right) * 0.25;
|
||||
|
||||
// 3. 计算差异 (边缘信号)
|
||||
// 如果 center 比周围亮,diff 为正;反之为负。
|
||||
half3 diff = center.rgb - neighborsAvg;
|
||||
|
||||
// 参数解包
|
||||
float strength = _SharpnessParams.x;
|
||||
float threshold = _SharpnessParams.y;
|
||||
float clampVal = _SharpnessParams.z;
|
||||
|
||||
// 4. 【优化一】对比度阈值 (Threshold) - 降噪用
|
||||
// 计算差异的亮度值
|
||||
float lumaDiff = dot(abs(diff), float3(0.2126, 0.7152, 0.0722));
|
||||
// 如果差异小于阈值,则不进行锐化 (factor = 0)
|
||||
// 使用 smoothstep 让过渡更平滑
|
||||
float factor = smoothstep(threshold, threshold + 0.001, lumaDiff);
|
||||
|
||||
// 5. 应用锐化
|
||||
half3 sharpened = center.rgb + diff * strength * factor;
|
||||
|
||||
// 6. 【优化二】钳制 (Clamp) - 防光晕用
|
||||
// 限制锐化后的值与原始值的偏差不能超过 clampVal
|
||||
sharpened = max(sharpened, center.rgb - clampVal); // 不能太暗
|
||||
sharpened = min(sharpened, center.rgb + clampVal); // 不能太亮
|
||||
|
||||
return half4(sharpened, center.a);
|
||||
}
|
||||
ENDHLSL
|
||||
|
||||
Pass
|
||||
{
|
||||
Name "Sharpen Pass"
|
||||
HLSLPROGRAM
|
||||
#pragma vertex Vert
|
||||
#pragma fragment SharpenPassFragment
|
||||
ENDHLSL
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
fileFormatVersion: 2
|
||||
guid: ca578cdeed02a0e4185a591e727a1a6f
|
||||
ShaderImporter:
|
||||
externalObjects: {}
|
||||
defaultTextures: []
|
||||
nonModifiableTextures: []
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,97 @@
|
||||
Shader "SLS/Postprocessing/SpeedLines"
|
||||
{
|
||||
SubShader
|
||||
{
|
||||
Tags
|
||||
{
|
||||
"RenderType" = "Opaque"
|
||||
"RenderPipeline" = "UniversalPipeline"
|
||||
}
|
||||
ZWrite Off
|
||||
Cull Off
|
||||
|
||||
HLSLINCLUDE
|
||||
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"
|
||||
#include "Packages/com.unity.render-pipelines.core/Runtime/Utilities/Blit.hlsl"
|
||||
|
||||
// 变量
|
||||
float4 _Colour;
|
||||
float _SpeedLinesTiling;
|
||||
float _SpeedLinesRadialScale;
|
||||
float _SpeedLinesPower;
|
||||
float _SpeedLinesRemap;
|
||||
float _SpeedLinesAnimation;
|
||||
float _MaskScale;
|
||||
float _MaskHardness;
|
||||
float _MaskPower;
|
||||
|
||||
// --- 噪声算法库 (Simplex Noise) ---
|
||||
float3 mod2D289( float3 x ) { return x - floor( x * ( 1.0 / 289.0 ) ) * 289.0; }
|
||||
float2 mod2D289( float2 x ) { return x - floor( x * ( 1.0 / 289.0 ) ) * 289.0; }
|
||||
float3 permute( float3 x ) { return mod2D289( ( ( 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 );
|
||||
float2 i1 = ( x0.x > x0.y ) ? float2( 1.0, 0.0 ) : float2( 0.0, 1.0 );
|
||||
float4 x12 = x0.xyxy + C.xxzz; x12.xy -= i1;
|
||||
i = mod2D289( 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( x12.xy, x12.xy ), dot( x12.zw, x12.zw ) ), 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;
|
||||
g.x = a0.x * x0.x + h.x * x0.y; g.yz = a0.yz * x12.xz + h.yz * x12.yw;
|
||||
return 130.0 * dot( m, g );
|
||||
}
|
||||
|
||||
// --- 主逻辑 ---
|
||||
half4 SpeedLinesPassFragment(Varyings input) : SV_Target
|
||||
{
|
||||
half2 uv = input.texcoord;
|
||||
half4 SceneColour7 = SAMPLE_TEXTURE2D_X(_BlitTexture, sampler_LinearClamp, uv);
|
||||
|
||||
float2 CenteredUV15_g1 = ( uv - float2( 0.5,0.5 ) );
|
||||
float2 break17_g1 = CenteredUV15_g1;
|
||||
|
||||
float2 appendResult23_g1 = (float2(( length( CenteredUV15_g1 ) * _SpeedLinesRadialScale * 2.0 ) , ( atan2( break17_g1.x , break17_g1.y ) * ( 1.0 / 6.28318548202515 ) * _SpeedLinesTiling )));
|
||||
|
||||
float2 appendResult58 = (float2(( -_SpeedLinesAnimation * _Time.y ) , 0.0));
|
||||
|
||||
float simplePerlin2D10 = snoise( ( appendResult23_g1 + appendResult58 ) );
|
||||
simplePerlin2D10 = simplePerlin2D10*0.5 + 0.5;
|
||||
|
||||
float temp_output_1_0_g6 = _SpeedLinesRemap;
|
||||
float SpeedLines21 = saturate( ( ( pow( simplePerlin2D10 , _SpeedLinesPower ) - temp_output_1_0_g6 ) / ( 1.0 - temp_output_1_0_g6 ) ) );
|
||||
|
||||
float2 texCoord60 = uv * float2( 2,2 ) + float2( -1,-1 );
|
||||
float temp_output_1_0_g5 = _MaskScale;
|
||||
float lerpResult71 = lerp( 0.0 , _MaskScale , _MaskHardness);
|
||||
float Mask24 = pow( ( 1.0 - saturate( ( ( length( texCoord60 ) - temp_output_1_0_g5 ) / ( ( lerpResult71 - 0.001 ) - temp_output_1_0_g5 ) ) ) ) , _MaskPower );
|
||||
|
||||
float MaskedSpeedLines29 = ( SpeedLines21 * Mask24 );
|
||||
|
||||
float3 ColourRGB38 = (_Colour).rgb;
|
||||
float ColourA40 = _Colour.a;
|
||||
|
||||
float4 speedLineColor = float4( ( MaskedSpeedLines29 * ColourRGB38 ) , SceneColour7.a );
|
||||
float4 lerpResult2 = lerp( SceneColour7 , speedLineColor , ( MaskedSpeedLines29 * ColourA40 ));
|
||||
|
||||
return lerpResult2;
|
||||
}
|
||||
ENDHLSL
|
||||
|
||||
Pass
|
||||
{
|
||||
Name "Speed Lines Pass"
|
||||
HLSLPROGRAM
|
||||
#pragma vertex Vert
|
||||
#pragma fragment SpeedLinesPassFragment
|
||||
ENDHLSL
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
fileFormatVersion: 2
|
||||
guid: a46d3ad17881bcc40bb90b165375974f
|
||||
ShaderImporter:
|
||||
externalObjects: {}
|
||||
defaultTextures: []
|
||||
nonModifiableTextures: []
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,135 @@
|
||||
Shader "SLS/Postprocessing/StrobeFlash"
|
||||
{
|
||||
SubShader
|
||||
{
|
||||
Tags
|
||||
{
|
||||
"RenderType" = "Opaque"
|
||||
"RenderPipeline" = "UniversalPipeline"
|
||||
}
|
||||
ZWrite Off
|
||||
Cull Off
|
||||
|
||||
HLSLINCLUDE
|
||||
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"
|
||||
#include "Packages/com.unity.render-pipelines.core/Runtime/Utilities/Blit.hlsl"
|
||||
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/DeclareDepthTexture.hlsl"
|
||||
|
||||
// --- 参数定义 ---
|
||||
float4 _StrobeColorHigh;
|
||||
float4 _StrobeColorLow;
|
||||
float4 _StrobeParams;
|
||||
|
||||
float4 _StrobeAdvParams;
|
||||
// x: Noise Reduction
|
||||
// y: Softness
|
||||
// z: Outline Thickness
|
||||
// w: Outline Threshold (新增:深度差异阈值)
|
||||
|
||||
float4 _LuminanceWeights;
|
||||
|
||||
// --- 辅助函数 ---
|
||||
half3 BoxBlur(float2 uv, float radius)
|
||||
{
|
||||
float4 offset = _BlitTexture_TexelSize.xyxy * radius * float4(-1, -1, 1, 1);
|
||||
half3 c1 = SAMPLE_TEXTURE2D_X(_BlitTexture, sampler_LinearClamp, uv + offset.xy).rgb;
|
||||
half3 c2 = SAMPLE_TEXTURE2D_X(_BlitTexture, sampler_LinearClamp, uv + offset.zy).rgb;
|
||||
half3 c3 = SAMPLE_TEXTURE2D_X(_BlitTexture, sampler_LinearClamp, uv + offset.xw).rgb;
|
||||
half3 c4 = SAMPLE_TEXTURE2D_X(_BlitTexture, sampler_LinearClamp, uv + offset.zw).rgb;
|
||||
return (c1 + c2 + c3 + c4) * 0.25;
|
||||
}
|
||||
|
||||
// 修改:增加 threshold 参数
|
||||
float GetEdge(float2 uv, float thickness, float threshold)
|
||||
{
|
||||
if(thickness <= 0) return 0;
|
||||
|
||||
float2 size = _BlitTexture_TexelSize.xy * thickness;
|
||||
|
||||
float d1 = SampleSceneDepth(uv + size);
|
||||
float d2 = SampleSceneDepth(uv - size);
|
||||
float d3 = SampleSceneDepth(uv + float2(size.x, -size.y));
|
||||
float d4 = SampleSceneDepth(uv + float2(-size.x, size.y));
|
||||
|
||||
d1 = LinearEyeDepth(d1, _ZBufferParams);
|
||||
d2 = LinearEyeDepth(d2, _ZBufferParams);
|
||||
d3 = LinearEyeDepth(d3, _ZBufferParams);
|
||||
d4 = LinearEyeDepth(d4, _ZBufferParams);
|
||||
|
||||
float diff1 = abs(d1 - d2);
|
||||
float diff2 = abs(d3 - d4);
|
||||
|
||||
// 使用传入的阈值,而不是写死的 0.1
|
||||
// 只有当深度差 > threshold 时,才认为是边缘
|
||||
return step(threshold, diff1 + diff2);
|
||||
}
|
||||
|
||||
half4 StrobeFlashPassFragment(Varyings input) : SV_Target
|
||||
{
|
||||
half2 uv = input.texcoord;
|
||||
|
||||
float frequency = _StrobeParams.x;
|
||||
float threshold = _StrobeParams.y;
|
||||
float noiseReduction = _StrobeAdvParams.x;
|
||||
float softness = _StrobeAdvParams.y;
|
||||
|
||||
// 新增参数获取
|
||||
float outlineThickness = _StrobeAdvParams.z;
|
||||
float outlineThreshold = max(0.001, _StrobeAdvParams.w); // 防止除0或负数
|
||||
|
||||
float3 lumWeights = _LuminanceWeights.rgb;
|
||||
|
||||
// 采样颜色 (带降噪)
|
||||
half3 sceneColor;
|
||||
if (noiseReduction > 0.01)
|
||||
{
|
||||
sceneColor = BoxBlur(uv, noiseReduction);
|
||||
}
|
||||
else
|
||||
{
|
||||
sceneColor = SAMPLE_TEXTURE2D_X(_BlitTexture, sampler_LinearClamp, uv).rgb;
|
||||
}
|
||||
|
||||
float luminance = dot(sceneColor, lumWeights);
|
||||
float softRange = max(0.001, softness);
|
||||
float t = smoothstep(threshold - softRange, threshold + softRange, luminance);
|
||||
|
||||
float isAuto = _StrobeParams.z;
|
||||
float isManualInvert = _StrobeParams.w;
|
||||
float invertSignal = 0;
|
||||
|
||||
if (isAuto > 0.5)
|
||||
{
|
||||
invertSignal = step(0, sin(_Time.y * frequency * PI));
|
||||
}
|
||||
invertSignal = max(invertSignal, isManualInvert);
|
||||
|
||||
// 边缘检测:传入 Thickness 和 Threshold
|
||||
float edge = GetEdge(uv, outlineThickness, outlineThreshold);
|
||||
|
||||
t = abs(t - edge);
|
||||
|
||||
float3 finalColor;
|
||||
if (invertSignal > 0.5)
|
||||
{
|
||||
finalColor = lerp(_StrobeColorHigh.rgb, _StrobeColorLow.rgb, t);
|
||||
}
|
||||
else
|
||||
{
|
||||
finalColor = lerp(_StrobeColorLow.rgb, _StrobeColorHigh.rgb, t);
|
||||
}
|
||||
|
||||
return half4(finalColor, 1);
|
||||
}
|
||||
ENDHLSL
|
||||
|
||||
Pass
|
||||
{
|
||||
Name "Strobe Flash Pass"
|
||||
HLSLPROGRAM
|
||||
#pragma vertex Vert
|
||||
#pragma fragment StrobeFlashPassFragment
|
||||
ENDHLSL
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
fileFormatVersion: 2
|
||||
guid: aa12587766ec16842a16c1965e43da43
|
||||
ShaderImporter:
|
||||
externalObjects: {}
|
||||
defaultTextures: []
|
||||
nonModifiableTextures: []
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
8
Assets/Shaders/ScriptablePostProcessor/Volumes.meta
Normal file
8
Assets/Shaders/ScriptablePostProcessor/Volumes.meta
Normal file
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: ca35e3cf743bc4240a318ee3bde84ece
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,86 @@
|
||||
using Echovoid.Runtime.Behavior.Rendering;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Rendering;
|
||||
using UnityEngine.Rendering.Universal;
|
||||
|
||||
namespace SLSUtilities.Rendering.PostProcessing
|
||||
{
|
||||
[System.Serializable, VolumeComponentMenu("SLS/Postprocessing/Advanced Chromatic Aberration")]
|
||||
public class AdvancedChromaticAberration : ScriptablePostProcessorVolume
|
||||
{
|
||||
// 建议放在 PostProcess 之后,作为最终的镜头效果
|
||||
public override CustomPostProcessInjectionPoint InjectionPoint => CustomPostProcessInjectionPoint.AfterPostProcess;
|
||||
public override int OrderInInjectionPoint => 20;
|
||||
|
||||
[Header("Main Settings")]
|
||||
[Tooltip("色散总强度")]
|
||||
public ClampedFloatParameter intensity = new(0f, 0f, 1f);
|
||||
|
||||
[Tooltip("扩散中心点 (0.5, 0.5 为屏幕中心)")]
|
||||
public Vector2Parameter center = new(new Vector2(0.5f, 0.5f));
|
||||
|
||||
[Tooltip("RGB 分离权重。控制每个通道向外扩散的程度。\n例如 (1, 0, -1) 会让红蓝向相反方向分离,绿色不动。")]
|
||||
public Vector3Parameter channelSplit = new(new Vector3(1f, 0f, -1f));
|
||||
|
||||
[Header("Dispersion Map (Broken Glass/Glitch)")]
|
||||
[Tooltip("输入的噪波贴图,用于打乱色散的方向")]
|
||||
public TextureParameter dispersionMap = new(null);
|
||||
|
||||
[Tooltip("贴图对色散方向的影响力")]
|
||||
public ClampedFloatParameter dispersionStrength = new(0f, 0f, 2f);
|
||||
|
||||
[Header("Jitter (Temporal Instability)")]
|
||||
[Tooltip("UV 采样抖动强度")]
|
||||
public ClampedFloatParameter jitterIntensity = new(0f, 0f, 1f);
|
||||
|
||||
[Tooltip("抖动速度")]
|
||||
public FloatParameter jitterSpeed = new(10f);
|
||||
|
||||
[Header("Masking")]
|
||||
[Tooltip("中心保留清晰的半径 (0-1)")]
|
||||
public ClampedFloatParameter maskRadius = new(0.2f, 0f, 1f);
|
||||
|
||||
[Tooltip("遮罩边缘的软硬度")]
|
||||
public ClampedFloatParameter maskHardness = new(0.2f, 0.01f, 1f);
|
||||
|
||||
public override string GetShaderName() => "SLS/Postprocessing/AdvancedChromaticAberration";
|
||||
|
||||
public override void Render(CommandBuffer cmd, ref RenderingData renderingData, RTHandle source, RTHandle destination)
|
||||
{
|
||||
if (material == null) return;
|
||||
|
||||
// Pack Params 1
|
||||
Vector4 p1 = new Vector4(
|
||||
intensity.value,
|
||||
center.value.x,
|
||||
center.value.y,
|
||||
maskRadius.value
|
||||
);
|
||||
|
||||
// Pack Params 2
|
||||
Vector4 p2 = new Vector4(
|
||||
jitterIntensity.value,
|
||||
jitterSpeed.value,
|
||||
dispersionStrength.value,
|
||||
maskHardness.value
|
||||
);
|
||||
|
||||
material.SetVector(InternalShaderHelpers.ID._ACA_Params1, p1);
|
||||
material.SetVector(InternalShaderHelpers.ID._ACA_Params2, p2);
|
||||
material.SetVector(InternalShaderHelpers.ID._ACA_Split, channelSplit.value);
|
||||
|
||||
if (dispersionMap.value != null)
|
||||
{
|
||||
material.SetTexture(InternalShaderHelpers.ID._DispersionMap, dispersionMap.value);
|
||||
}
|
||||
|
||||
Blitter.BlitCameraTexture(cmd, source, destination, material, 0);
|
||||
}
|
||||
|
||||
public override bool IsActive()
|
||||
{
|
||||
// 只要有强度,或者有抖动,就需要渲染
|
||||
return intensity.value > 0f || jitterIntensity.value > 0f;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: d692dfd6cc3001c4993ac48b98cf416c
|
||||
@@ -0,0 +1,63 @@
|
||||
using Echovoid.Runtime.Behavior.Rendering;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Rendering;
|
||||
using UnityEngine.Rendering.Universal;
|
||||
|
||||
namespace SLSUtilities.Rendering.PostProcessing
|
||||
{
|
||||
[System.Serializable, VolumeComponentMenu("SLS/Postprocessing/Advanced Vignette")]
|
||||
public class AdvancedVignette : ScriptablePostProcessorVolume
|
||||
{
|
||||
// 放在最最后
|
||||
public override CustomPostProcessInjectionPoint InjectionPoint => CustomPostProcessInjectionPoint.AfterPostProcess;
|
||||
public override int OrderInInjectionPoint => 100;
|
||||
|
||||
[Header("Gradient Colors")]
|
||||
[Tooltip("外部颜色(边缘)。最暗的地方显示的颜色。")]
|
||||
public ColorParameter colorOuter = new(Color.black, true, true, true);
|
||||
|
||||
[Tooltip("内部颜色(过渡区)。\n当暗角开始出现时显示的颜色。\n设为与外部相同则为单色暗角。\n设为红色可做受伤效果。")]
|
||||
public ColorParameter colorInner = new(Color.black, true, true, true);
|
||||
|
||||
[Header("Shape Settings")]
|
||||
[Tooltip("中心位置")]
|
||||
public Vector2Parameter center = new(new Vector2(0.5f, 0.5f));
|
||||
|
||||
[Tooltip("强度。0 = 无效果")]
|
||||
public ClampedFloatParameter intensity = new(0f, 0f, 1f);
|
||||
|
||||
[Tooltip("柔和度。控制渐变区域的宽度。")]
|
||||
public ClampedFloatParameter smoothness = new(0.5f, 0.01f, 1f);
|
||||
|
||||
[Tooltip("圆度。1 = 圆形,0 = 方形。")]
|
||||
public ClampedFloatParameter roundness = new(1f, 0f, 1f);
|
||||
|
||||
|
||||
public override string GetShaderName() => "SLS/Postprocessing/AdvancedVignette";
|
||||
|
||||
public override void Render(CommandBuffer cmd, ref RenderingData renderingData, RTHandle source, RTHandle destination)
|
||||
{
|
||||
if (material == null) return;
|
||||
|
||||
material.SetColor(InternalShaderHelpers.ID._ColorInner, colorInner.value);
|
||||
material.SetColor(InternalShaderHelpers.ID._ColorOuter, colorOuter.value);
|
||||
material.SetVector(InternalShaderHelpers.ID._VignetteCenter, center.value);
|
||||
|
||||
// Pack Params
|
||||
Vector3 p1 = new Vector3(
|
||||
intensity.value,
|
||||
smoothness.value,
|
||||
roundness.value
|
||||
);
|
||||
|
||||
material.SetVector(InternalShaderHelpers.ID._VignetteParams1, p1);
|
||||
|
||||
Blitter.BlitCameraTexture(cmd, source, destination, material, 0);
|
||||
}
|
||||
|
||||
public override bool IsActive()
|
||||
{
|
||||
return intensity.value > 0f;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 4b3eae192e53bb542bb66bee3b8ac936
|
||||
59
Assets/Shaders/ScriptablePostProcessor/Volumes/AnimeACES.cs
Normal file
59
Assets/Shaders/ScriptablePostProcessor/Volumes/AnimeACES.cs
Normal file
@@ -0,0 +1,59 @@
|
||||
using Echovoid.Runtime.Behavior.Rendering;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Rendering;
|
||||
using UnityEngine.Rendering.Universal;
|
||||
|
||||
namespace SLSUtilities.Rendering.PostProcessing
|
||||
{
|
||||
[System.Serializable, VolumeComponentMenu("SLS/Postprocessing/Anime ACES")]
|
||||
public class AnimeACES : ScriptablePostProcessorVolume
|
||||
{
|
||||
public override CustomPostProcessInjectionPoint InjectionPoint => CustomPostProcessInjectionPoint.AfterPostProcess;
|
||||
public override int OrderInInjectionPoint => 1000;
|
||||
|
||||
[Header("Tone Settings")]
|
||||
[Tooltip("是否开启")]
|
||||
public BoolParameter enabled = new(false);
|
||||
|
||||
[Tooltip("曝光度。如果画面太亮,请降低此值 (0.8 - 1.2)。")]
|
||||
public FloatParameter exposure = new(1.0f); // 默认降回 1.0
|
||||
|
||||
[Tooltip("对比度。基于中灰(0.18)调整。值越高,黑的越黑,亮的越亮。")]
|
||||
public ClampedFloatParameter contrast = new(1.1f, 0f, 2f);
|
||||
|
||||
[Tooltip("饱和度。建议 1.1 - 1.3 以获得鲜艳色彩。")]
|
||||
public ClampedFloatParameter saturation = new(1.15f, 0f, 2f);
|
||||
|
||||
[Tooltip("色彩保留 (Hue Preservation)。\n0 = 标准ACES (皮肤泛白/胶片感)\n1 = 完美保色 (皮肤红润/卡通感)\n二次元建议 0.3 - 0.7。")]
|
||||
public ClampedFloatParameter huePreservation = new(0.5f, 0f, 1f);
|
||||
|
||||
[Tooltip("色彩滤镜")]
|
||||
public ColorParameter colorFilter = new(Color.white, true, true, true);
|
||||
|
||||
[Header("ACES Curve")]
|
||||
public ClampedFloatParameter coeffA = new(2.51f, 0f, 5f);
|
||||
public ClampedFloatParameter coeffB = new(0.03f, 0f, 1f);
|
||||
public ClampedFloatParameter coeffC = new(2.43f, 0f, 5f);
|
||||
public ClampedFloatParameter coeffD = new(0.59f, 0f, 1f);
|
||||
public ClampedFloatParameter coeffE = new(0.14f, 0f, 1f);
|
||||
|
||||
public override string GetShaderName() => "SLS/Postprocessing/AnimeACES";
|
||||
|
||||
public override void Render(CommandBuffer cmd, ref RenderingData renderingData, RTHandle source, RTHandle destination)
|
||||
{
|
||||
if (material == null) return;
|
||||
|
||||
// 传入 w 分量作为 Hue Preservation
|
||||
material.SetVector(InternalShaderHelpers.ID._TonemapParams, new Vector4(exposure.value, contrast.value, saturation.value, huePreservation.value));
|
||||
|
||||
material.SetVector(InternalShaderHelpers.ID._ACESCoeffs, new Vector4(coeffA.value, coeffB.value, coeffC.value, coeffD.value));
|
||||
material.SetFloat(InternalShaderHelpers.ID._ACES_E, coeffE.value);
|
||||
|
||||
material.SetColor(InternalShaderHelpers.ID._ColorFilter, colorFilter.value);
|
||||
|
||||
Blitter.BlitCameraTexture(cmd, source, destination, material, 0);
|
||||
}
|
||||
|
||||
public override bool IsActive() => enabled.value;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 5a892c0c0e4da4241b39a6d7e8ca14d3
|
||||
140
Assets/Shaders/ScriptablePostProcessor/Volumes/AnimeBloom.cs
Normal file
140
Assets/Shaders/ScriptablePostProcessor/Volumes/AnimeBloom.cs
Normal file
@@ -0,0 +1,140 @@
|
||||
using Echovoid.Runtime.Behavior.Rendering;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Rendering;
|
||||
using UnityEngine.Rendering.Universal;
|
||||
|
||||
namespace SLSUtilities.Rendering.PostProcessing
|
||||
{
|
||||
[System.Serializable, VolumeComponentMenu("SLS/Postprocessing/Anime Bloom")]
|
||||
public class AnimeBloom : ScriptablePostProcessorVolume
|
||||
{
|
||||
// 放在 ToneMapping 之前效果最强,但放在 AfterPostProcess 最安全(不易过曝)
|
||||
// 这里建议 AfterPostProcess,配合 HDR 使用
|
||||
public override CustomPostProcessInjectionPoint InjectionPoint => CustomPostProcessInjectionPoint.AfterPostProcess;
|
||||
public override int OrderInInjectionPoint => 5; // 放在 Vignette 之前
|
||||
|
||||
[Header("Glow Settings")]
|
||||
[Tooltip("泛光强度。值越大越亮。")]
|
||||
public ClampedFloatParameter intensity = new(0f, 0f, 10f);
|
||||
|
||||
[Tooltip("阈值。亮度超过此值的像素才会发光。\n关键:设为 1.1 可以过滤掉白墙(1.0),只让灯光发光。")]
|
||||
public MinFloatParameter threshold = new(1.1f, 0f); // 默认设为 1.1
|
||||
|
||||
[Tooltip("柔膝 (Soft Knee)。让阈值过渡更平滑,避免高光边缘有硬切痕迹。")]
|
||||
public ClampedFloatParameter softKnee = new(0.5f, 0f, 1f);
|
||||
|
||||
[Tooltip("最大亮度钳制。防止极亮像素(如太阳)产生乱跳的噪点。")]
|
||||
public MinFloatParameter clamp = new(65472f, 1f); // 默认很大,基本不限制
|
||||
|
||||
[Header("Anime Style")]
|
||||
[Tooltip("扩散半径。值越大,光晕越松散、范围越大(二次元感核心)。")]
|
||||
public ClampedFloatParameter scatter = new(0.7f, 0f, 5f); // 推荐 0.5 - 1.0
|
||||
|
||||
[Tooltip("迭代次数。次数越多,光晕越平滑、范围越大,但性能开销越高。")]
|
||||
public ClampedIntParameter diffusion = new(6, 1, 8); // 6次通常足够高品质
|
||||
|
||||
[Tooltip("泛光染色。可以做粉色霓虹、蓝色科技光等效果。")]
|
||||
public ColorParameter tint = new(Color.white, true, true, true);
|
||||
|
||||
// 内部使用的 RT 数组
|
||||
private RTHandle[] _bloomPyramidUp;
|
||||
private RTHandle[] _bloomPyramidDown;
|
||||
private const int k_MaxPyramidSize = 16;
|
||||
|
||||
public override string GetShaderName() => "SLS/Postprocessing/AnimeBloom";
|
||||
|
||||
public override void Render(CommandBuffer cmd, ref RenderingData renderingData, RTHandle source, RTHandle destination)
|
||||
{
|
||||
if (material == null) return;
|
||||
|
||||
var desc = renderingData.cameraData.cameraTargetDescriptor;
|
||||
desc.msaaSamples = 1;
|
||||
desc.depthBufferBits = 0;
|
||||
|
||||
// 1. 设置参数
|
||||
Vector4 bloomParams = new Vector4(intensity.value, threshold.value, softKnee.value, clamp.value);
|
||||
material.SetVector(InternalShaderHelpers.ID._BloomParams, bloomParams);
|
||||
material.SetVector(InternalShaderHelpers.ID._BloomTint, tint.value);
|
||||
material.SetFloat(InternalShaderHelpers.ID._BlurRadius, scatter.value);
|
||||
|
||||
// 2. 初始化金字塔数组
|
||||
int iterations = Mathf.Clamp(diffusion.value, 1, k_MaxPyramidSize);
|
||||
|
||||
// 确保 RT 数组大小足够
|
||||
if (_bloomPyramidUp == null || _bloomPyramidUp.Length != k_MaxPyramidSize)
|
||||
{
|
||||
_bloomPyramidUp = new RTHandle[k_MaxPyramidSize];
|
||||
_bloomPyramidDown = new RTHandle[k_MaxPyramidSize];
|
||||
}
|
||||
|
||||
// 3. Prefilter Pass (提取高亮)
|
||||
// 先降一半分辨率,节省性能且增加模糊感
|
||||
desc.width = Mathf.Max(1, desc.width >> 1);
|
||||
desc.height = Mathf.Max(1, desc.height >> 1);
|
||||
|
||||
RenderingUtils.ReAllocateIfNeeded(ref _bloomPyramidDown[0], desc, FilterMode.Bilinear, TextureWrapMode.Clamp, name: "_BloomMipDown0");
|
||||
RenderingUtils.ReAllocateIfNeeded(ref _bloomPyramidUp[0], desc, FilterMode.Bilinear, TextureWrapMode.Clamp, name: "_BloomMipUp0");
|
||||
|
||||
// Source -> Down[0] (Prefilter)
|
||||
Blitter.BlitCameraTexture(cmd, source, _bloomPyramidDown[0], material, 0);
|
||||
|
||||
// 4. Downsample Loop (降采样金字塔)
|
||||
int lastDown = 0;
|
||||
for (int i = 1; i < iterations; i++)
|
||||
{
|
||||
// 每次分辨率减半
|
||||
desc.width = Mathf.Max(1, desc.width >> 1);
|
||||
desc.height = Mathf.Max(1, desc.height >> 1);
|
||||
|
||||
RenderingUtils.ReAllocateIfNeeded(ref _bloomPyramidDown[i], desc, FilterMode.Bilinear, TextureWrapMode.Clamp, name: "_BloomMipDown" + i);
|
||||
RenderingUtils.ReAllocateIfNeeded(ref _bloomPyramidUp[i], desc, FilterMode.Bilinear, TextureWrapMode.Clamp, name: "_BloomMipUp" + i);
|
||||
|
||||
// Down[i-1] -> Down[i]
|
||||
Blitter.BlitCameraTexture(cmd, _bloomPyramidDown[i - 1], _bloomPyramidDown[i], material, 1);
|
||||
lastDown = i;
|
||||
}
|
||||
|
||||
// 5. Upsample Loop (升采样并混合)
|
||||
// 从最小的一张开始,往上叠加
|
||||
// 先把最小的 Down 直接拷给 Up
|
||||
Blitter.BlitCameraTexture(cmd, _bloomPyramidDown[lastDown], _bloomPyramidUp[lastDown]);
|
||||
|
||||
for (int i = lastDown - 1; i >= 0; i--)
|
||||
{
|
||||
// 设置上一级 Up 为输入
|
||||
// Upsample Pass 会混合:Up[i+1] (Blur) + Down[i] (High Res Detail)
|
||||
// 这里我们稍微简化逻辑:直接把 Up[i+1] 升采样并叠加到 Up[i] 上
|
||||
// 为了保留细节,Dual Kawase 通常是将 Up[i+1] 叠加回 Down[i] 存入 Up[i]
|
||||
|
||||
// 第一步:先把 Down[i] 拷进 Up[i] 作为底图
|
||||
Blitter.BlitCameraTexture(cmd, _bloomPyramidDown[i], _bloomPyramidUp[i]);
|
||||
|
||||
// 第二步:把 Up[i+1] 升采样并 Additive 混合进 Up[i]
|
||||
// Shader Pass 2 开启了 Blend One One
|
||||
Blitter.BlitCameraTexture(cmd, _bloomPyramidUp[i + 1], _bloomPyramidUp[i], material, 2);
|
||||
}
|
||||
|
||||
// 6. Composite (合成)
|
||||
// 此时 _bloomPyramidUp[0] 包含了最终的泛光纹理
|
||||
material.SetTexture(InternalShaderHelpers.ID._BloomTex, _bloomPyramidUp[0]);
|
||||
|
||||
// Source + BloomTex -> Destination
|
||||
Blitter.BlitCameraTexture(cmd, source, destination, material, 3);
|
||||
}
|
||||
|
||||
// 清理 RT
|
||||
public void Dispose()
|
||||
{
|
||||
if (_bloomPyramidDown != null)
|
||||
{
|
||||
for (int i = 0; i < _bloomPyramidDown.Length; i++)
|
||||
{
|
||||
if (_bloomPyramidDown[i] != null) _bloomPyramidDown[i].Release();
|
||||
if (_bloomPyramidUp[i] != null) _bloomPyramidUp[i].Release();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override bool IsActive() => intensity.value > 0f;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: bb4cc52ae13b01a44ab204c23af5263f
|
||||
42
Assets/Shaders/ScriptablePostProcessor/Volumes/Pixelate.cs
Normal file
42
Assets/Shaders/ScriptablePostProcessor/Volumes/Pixelate.cs
Normal file
@@ -0,0 +1,42 @@
|
||||
using System;
|
||||
using Echovoid.Runtime.Behavior.Rendering;
|
||||
using SLSUtilities.Rendering.PostProcessing;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Rendering;
|
||||
using UnityEngine.Rendering.Universal;
|
||||
|
||||
namespace SLSUtilities.Rendering.PostProcessing
|
||||
{
|
||||
[Serializable, VolumeComponentMenu("SLS/Postprocessing/Pixelate")]
|
||||
public class PixelateVolume : ScriptablePostProcessorVolume
|
||||
{
|
||||
public override CustomPostProcessInjectionPoint InjectionPoint => CustomPostProcessInjectionPoint.AfterPostProcess;
|
||||
public override int OrderInInjectionPoint => 100;
|
||||
|
||||
[Tooltip("是否强制开启像素化效果")]
|
||||
public BoolParameter forceActive = new BoolParameter(false);
|
||||
|
||||
public FloatParameter strengthX = new FloatParameter(1920f);
|
||||
public FloatParameter strengthY = new FloatParameter(1080f);
|
||||
|
||||
// 返回我们在 Shader 里定义的名字,保证管家可以据此获取材质
|
||||
public override string GetShaderName() => "Hidden/Custom/Pixelate";
|
||||
|
||||
public override bool IsActive()
|
||||
{
|
||||
// 当激活开关开启时才执行后期渲染(节省平时不开时的性能)
|
||||
return forceActive.value;
|
||||
}
|
||||
|
||||
public override void Render(CommandBuffer cmd, ref RenderingData renderingData, RTHandle source, RTHandle destination)
|
||||
{
|
||||
if (material == null) return;
|
||||
|
||||
cmd.SetGlobalFloat(InternalShaderHelpers.ID._PixelateStrengthX, strengthX.value);
|
||||
cmd.SetGlobalFloat(InternalShaderHelpers.ID._PixelateStrengthY, strengthY.value);
|
||||
|
||||
// 使用你的统一管家分发的 Blitter 进行优雅渲染
|
||||
Blitter.BlitCameraTexture(cmd, source, destination, material, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b25e6f237f6016f4191dd203dbfde0ee
|
||||
@@ -0,0 +1,36 @@
|
||||
using Echovoid.Runtime.Behavior.Rendering;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Rendering;
|
||||
using UnityEngine.Rendering.Universal;
|
||||
|
||||
namespace SLSUtilities.Rendering.PostProcessing
|
||||
{
|
||||
[System.Serializable, VolumeComponentMenu("SLS/Postprocessing/RGBSplitGlitch")]
|
||||
public class RGBSplitGlitch : ScriptablePostProcessorVolume
|
||||
{
|
||||
public override CustomPostProcessInjectionPoint InjectionPoint => CustomPostProcessInjectionPoint.BeforePostProcess;
|
||||
public override int OrderInInjectionPoint => 0;
|
||||
|
||||
public ClampedFloatParameter intensity = new(0f, 0f, 1f);
|
||||
public ClampedFloatParameter speed = new(10f, 0f, 100f);
|
||||
public override string GetShaderName() => "SLS/Postprocessing/RGBSplitGlitch";
|
||||
|
||||
private float elapsedTime = 1.0f;
|
||||
|
||||
public override void Render(CommandBuffer cmd, ref RenderingData renderingData, RTHandle source, RTHandle destination)
|
||||
{
|
||||
if (material == null) return;
|
||||
elapsedTime += Time.unscaledDeltaTime;
|
||||
if (elapsedTime > 100)
|
||||
{
|
||||
elapsedTime = 0;
|
||||
}
|
||||
cmd.SetGlobalVector(InternalShaderHelpers.ID._RGBSplitGlitchParams,
|
||||
new Vector4(intensity.value * 0.01f, Mathf.Floor(elapsedTime * speed.value)));
|
||||
Blitter.BlitCameraTexture(cmd, source, destination, material, 0);
|
||||
}
|
||||
|
||||
public override bool IsActive() => intensity.value > 0f;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 308c07db68b430d46b6d74d0847371b4
|
||||
39
Assets/Shaders/ScriptablePostProcessor/Volumes/RadialBlur.cs
Normal file
39
Assets/Shaders/ScriptablePostProcessor/Volumes/RadialBlur.cs
Normal file
@@ -0,0 +1,39 @@
|
||||
using Echovoid.Runtime.Behavior.Rendering;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Rendering;
|
||||
using UnityEngine.Rendering.Universal;
|
||||
|
||||
namespace SLSUtilities.Rendering.PostProcessing
|
||||
{
|
||||
public enum RadialBlurQuality
|
||||
{
|
||||
RadialBlur_4Tap_Fatest = 0,
|
||||
RadialBlur_8Tap_Balance = 1,
|
||||
RadialBlur_12Tap = 2,
|
||||
RadialBlur_16Tap_Quality = 3,
|
||||
}
|
||||
|
||||
[System.Serializable, VolumeComponentMenu("SLS/Postprocessing/Radial Blur")]
|
||||
public class RadialBlur : ScriptablePostProcessorVolume
|
||||
{
|
||||
public override CustomPostProcessInjectionPoint InjectionPoint => CustomPostProcessInjectionPoint.BeforePostProcess;
|
||||
public override int OrderInInjectionPoint => 10;
|
||||
|
||||
public EnumParameter<RadialBlurQuality> qualityLevel = new (RadialBlurQuality.RadialBlur_8Tap_Balance);
|
||||
public ClampedFloatParameter blurRadius = new(0f, -1f, 1f);
|
||||
public ClampedFloatParameter radialCenterX = new(0.5f, 0f, 1f);
|
||||
public ClampedFloatParameter radialCenterY = new(0.5f, 0f, 1f);
|
||||
|
||||
public override string GetShaderName() => "SLS/Postprocessing/RadialBlur";
|
||||
|
||||
public override void Render(CommandBuffer cmd, ref RenderingData renderingData, RTHandle source, RTHandle target)
|
||||
{
|
||||
if (material == null) return;
|
||||
cmd.SetGlobalVector(InternalShaderHelpers.ID._RadialBlurParams,
|
||||
new Vector4(blurRadius.value * 0.02f, radialCenterX.value, radialCenterY.value));
|
||||
Blitter.BlitCameraTexture(cmd, source, target, material, (int)qualityLevel.value);
|
||||
}
|
||||
|
||||
public override bool IsActive() => !Mathf.Approximately(blurRadius.value, 0);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 1f10b1f364acbb743804f8a970bce230
|
||||
48
Assets/Shaders/ScriptablePostProcessor/Volumes/Sharpen.cs
Normal file
48
Assets/Shaders/ScriptablePostProcessor/Volumes/Sharpen.cs
Normal file
@@ -0,0 +1,48 @@
|
||||
using Echovoid.Runtime.Behavior.Rendering;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Rendering;
|
||||
using UnityEngine.Rendering.Universal;
|
||||
|
||||
namespace SLSUtilities.Rendering.PostProcessing
|
||||
{
|
||||
[System.Serializable, VolumeComponentMenu("SLS/Postprocessing/Sharpen")]
|
||||
public class Sharpen : ScriptablePostProcessorVolume
|
||||
{
|
||||
// 放在所有后处理之后,对最终画面进行锐化
|
||||
public override CustomPostProcessInjectionPoint InjectionPoint => CustomPostProcessInjectionPoint.AfterPostProcess;
|
||||
// 排序靠后,确保是最后几步操作之一
|
||||
public override int OrderInInjectionPoint => 10;
|
||||
|
||||
[Header("General Settings")]
|
||||
[Tooltip("锐化强度。值越大画面越锋利。建议范围 0.5 - 2.0。过大会导致失真。")]
|
||||
public ClampedFloatParameter sharpness = new(0f, 0f, 5f);
|
||||
|
||||
[Header("Optimizations (Visual Quality)")]
|
||||
[Tooltip("对比度阈值(降噪)。\n只有当像素差异大于此值时才锐化。\n增加此值可避免平坦区域(如天空、皮肤)出现噪点。\n建议值:0.01 - 0.05。")]
|
||||
public ClampedFloatParameter threshold = new(0.01f, 0f, 0.2f);
|
||||
|
||||
[Tooltip("最大亮度钳制(防光晕)。\n限制像素亮度的最大变化幅度,防止边缘出现刺眼的白边或黑边。\n减小此值可让锐化更自然。\n建议值:0.1 - 0.3。")]
|
||||
public ClampedFloatParameter clamp = new(0.2f, 0f, 1f);
|
||||
|
||||
public override string GetShaderName() => "SLS/Postprocessing/Sharpen";
|
||||
|
||||
public override void Render(CommandBuffer cmd, ref RenderingData renderingData, RTHandle source, RTHandle destination)
|
||||
{
|
||||
if (material == null) return;
|
||||
|
||||
Vector4 paramsVec = new Vector4(
|
||||
sharpness.value,
|
||||
threshold.value,
|
||||
clamp.value,
|
||||
0 // unused
|
||||
);
|
||||
|
||||
material.SetVector(InternalShaderHelpers.ID._SharpnessParams, paramsVec);
|
||||
|
||||
Blitter.BlitCameraTexture(cmd, source, destination, material, 0);
|
||||
}
|
||||
|
||||
// 只有强度大于 0 时才激活
|
||||
public override bool IsActive() => sharpness.value > 0f;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 148ba37ea406c934ea39cee8e2dd1108
|
||||
49
Assets/Shaders/ScriptablePostProcessor/Volumes/SpeedLines.cs
Normal file
49
Assets/Shaders/ScriptablePostProcessor/Volumes/SpeedLines.cs
Normal file
@@ -0,0 +1,49 @@
|
||||
using Echovoid.Runtime.Behavior.Rendering;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Rendering;
|
||||
using UnityEngine.Rendering.Universal;
|
||||
|
||||
namespace SLSUtilities.Rendering.PostProcessing
|
||||
{
|
||||
[System.Serializable, VolumeComponentMenu("SLS/Postprocessing/Speed Lines")]
|
||||
public class SpeedLines : ScriptablePostProcessorVolume
|
||||
{
|
||||
public override CustomPostProcessInjectionPoint InjectionPoint => CustomPostProcessInjectionPoint.AfterPostProcess;
|
||||
public override int OrderInInjectionPoint => 20;
|
||||
|
||||
[Header("Effect Color & Intensity")]
|
||||
public ColorParameter color = new(new Color(1f, 1f, 1f, 0.5f), true, true, true);
|
||||
|
||||
[Header("Lines")]
|
||||
public FloatParameter speedLinesTiling = new(200f);
|
||||
public ClampedFloatParameter speedLinesRadialScale = new(0.1f, 0f, 10f);
|
||||
public FloatParameter speedLinesPower = new(0f);
|
||||
public ClampedFloatParameter speedLinesRemap = new(1f, 0f, 1f);
|
||||
public FloatParameter speedLinesAnimation = new(3f);
|
||||
|
||||
[Header("Radial Mask")]
|
||||
public ClampedFloatParameter maskScale = new(1f, 0f, 2f);
|
||||
public ClampedFloatParameter maskHardness = new(0f, 0f, 1f);
|
||||
public FloatParameter maskPower = new(5f);
|
||||
|
||||
public override string GetShaderName() => "SLS/Postprocessing/SpeedLines";
|
||||
public override bool IsActive() => speedLinesRemap.value < 1f && color.value.a > 0f;
|
||||
|
||||
public override void Render(CommandBuffer cmd, ref RenderingData renderingData, RTHandle source, RTHandle target)
|
||||
{
|
||||
if (material == null) return;
|
||||
|
||||
material.SetColor(InternalShaderHelpers.ID._SpeedLinesColour, color.value);
|
||||
material.SetFloat(InternalShaderHelpers.ID._SpeedLinesTiling, speedLinesTiling.value);
|
||||
material.SetFloat(InternalShaderHelpers.ID._SpeedLinesRadialScale, speedLinesRadialScale.value);
|
||||
material.SetFloat(InternalShaderHelpers.ID._SpeedLinesPower, speedLinesPower.value);
|
||||
material.SetFloat(InternalShaderHelpers.ID._SpeedLinesRemap, speedLinesRemap.value);
|
||||
material.SetFloat(InternalShaderHelpers.ID._SpeedLinesAnimation, speedLinesAnimation.value);
|
||||
material.SetFloat(InternalShaderHelpers.ID._MaskScale, maskScale.value);
|
||||
material.SetFloat(InternalShaderHelpers.ID._MaskHardness, maskHardness.value);
|
||||
material.SetFloat(InternalShaderHelpers.ID._MaskPower, maskPower.value);
|
||||
|
||||
Blitter.BlitCameraTexture(cmd, source, target, material, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b67ae72a3d84887438324358c0932509
|
||||
@@ -0,0 +1,76 @@
|
||||
using Echovoid.Runtime.Behavior.Rendering;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Rendering;
|
||||
using UnityEngine.Rendering.Universal;
|
||||
|
||||
namespace SLSUtilities.Rendering.PostProcessing
|
||||
{
|
||||
[System.Serializable, VolumeComponentMenu("SLS/Postprocessing/Strobe Flash")]
|
||||
public class StrobeFlash : ScriptablePostProcessorVolume
|
||||
{
|
||||
public override CustomPostProcessInjectionPoint InjectionPoint => CustomPostProcessInjectionPoint.BeforePostProcess;
|
||||
public override int OrderInInjectionPoint => 5;
|
||||
|
||||
[Header("Master Switch")]
|
||||
public BoolParameter enableEffect = new(false);
|
||||
|
||||
[Header("Binary Colors")]
|
||||
public ColorParameter colorHigh = new(Color.white);
|
||||
public ColorParameter colorLow = new(Color.black);
|
||||
|
||||
[Header("Threshold & Flash")]
|
||||
public ClampedFloatParameter grading = new(0.5f, 0f, 1f);
|
||||
public BoolParameter autoFlash = new(false);
|
||||
public FloatParameter frequency = new(15f);
|
||||
public BoolParameter manualInvert = new(false);
|
||||
|
||||
[Header("Optimizations (Art Style)")]
|
||||
[Tooltip("预模糊:消除地面的细碎噪点。")]
|
||||
public ClampedFloatParameter noiseReduction = new(1.5f, 0f, 5f);
|
||||
|
||||
[Tooltip("柔化边缘:让黑白交界处不那么生硬。")]
|
||||
public ClampedFloatParameter softness = new(0.05f, 0f, 0.5f);
|
||||
|
||||
[Header("Outline Settings")]
|
||||
[Tooltip("描边粗细:建议值 1.0 - 2.0。如果太小可能看不见。")]
|
||||
public ClampedFloatParameter outlineThickness = new(1f, 0f, 5f);
|
||||
|
||||
[Tooltip("描边敏感度阈值 (米):深度差超过此值才画线。\n解决地面全黑的关键参数!\n建议值:0.5 - 2.0。")]
|
||||
public MinFloatParameter outlineThreshold = new(1.0f, 0f); // 默认设为 1米
|
||||
|
||||
[Tooltip("感光权重")]
|
||||
public Vector3Parameter luminanceWeights = new(new Vector3(0.2126f, 0.7152f, 0.0722f));
|
||||
|
||||
public override string GetShaderName() => "SLS/Postprocessing/StrobeFlash";
|
||||
|
||||
public override void Render(CommandBuffer cmd, ref RenderingData renderingData, RTHandle source, RTHandle destination)
|
||||
{
|
||||
if (material == null) return;
|
||||
|
||||
material.SetColor(InternalShaderHelpers.ID._StrobeColorHigh, colorHigh.value);
|
||||
material.SetColor(InternalShaderHelpers.ID._StrobeColorLow, colorLow.value);
|
||||
material.SetVector(InternalShaderHelpers.ID._LuminanceWeights, new Vector4(luminanceWeights.value.x, luminanceWeights.value.y, luminanceWeights.value.z, 0));
|
||||
|
||||
Vector4 paramsVec = new Vector4(
|
||||
frequency.value,
|
||||
grading.value,
|
||||
autoFlash.value ? 1f : 0f,
|
||||
manualInvert.value ? 1f : 0f
|
||||
);
|
||||
material.SetVector(InternalShaderHelpers.ID._StrobeParams, paramsVec);
|
||||
|
||||
// 更新:传入 outlineThreshold (w分量)
|
||||
Vector4 advParamsVec = new Vector4(
|
||||
noiseReduction.value,
|
||||
softness.value,
|
||||
outlineThickness.value,
|
||||
outlineThreshold.value
|
||||
);
|
||||
material.SetVector(InternalShaderHelpers.ID._StrobeAdvParams, advParamsVec);
|
||||
|
||||
Blitter.BlitCameraTexture(cmd, source, destination, material, 0);
|
||||
}
|
||||
|
||||
public override bool IsActive() => enableEffect.value;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 6a1f971f558014244b688b0d0a91e039
|
||||
Reference in New Issue
Block a user