wip: Main postprocess

This commit is contained in:
Alexandre Coirier
2026-05-25 17:50:44 +02:00
parent 0710f59b9d
commit 0405f337cd
17 changed files with 1336 additions and 88 deletions
@@ -0,0 +1,552 @@
{
"m_SGVersion": 3,
"m_Type": "UnityEditor.ShaderGraph.GraphData",
"m_ObjectId": "bad98fc4fdb44f30940907c69e065bf7",
"m_Properties": [
{
"m_Id": "a50e4944b7f14398b3018f3c3d627822"
}
],
"m_Keywords": [],
"m_Dropdowns": [],
"m_CategoryData": [
{
"m_Id": "b9782225abb9483c85024af7c4b9a57c"
}
],
"m_Nodes": [
{
"m_Id": "0a9843ed20a94d59902f2d26c002ed64"
},
{
"m_Id": "72a96e3c01214831bec7cea6fa437e31"
},
{
"m_Id": "e372fee5cae141e88964209e505cfe9b"
},
{
"m_Id": "5b3e329ec4094ae4bc2abb0232536617"
},
{
"m_Id": "acd4a53e615644308e5396077e64ea1f"
}
],
"m_GroupDatas": [],
"m_StickyNoteDatas": [],
"m_Edges": [
{
"m_OutputSlot": {
"m_Node": {
"m_Id": "5b3e329ec4094ae4bc2abb0232536617"
},
"m_SlotId": 0
},
"m_InputSlot": {
"m_Node": {
"m_Id": "e372fee5cae141e88964209e505cfe9b"
},
"m_SlotId": 2
}
},
{
"m_OutputSlot": {
"m_Node": {
"m_Id": "acd4a53e615644308e5396077e64ea1f"
},
"m_SlotId": 0
},
"m_InputSlot": {
"m_Node": {
"m_Id": "e372fee5cae141e88964209e505cfe9b"
},
"m_SlotId": 0
}
},
{
"m_OutputSlot": {
"m_Node": {
"m_Id": "e372fee5cae141e88964209e505cfe9b"
},
"m_SlotId": 3
},
"m_InputSlot": {
"m_Node": {
"m_Id": "0a9843ed20a94d59902f2d26c002ed64"
},
"m_SlotId": 0
}
}
],
"m_VertexContext": {
"m_Position": {
"x": 7.999984264373779,
"y": 59.999996185302737
},
"m_Blocks": []
},
"m_FragmentContext": {
"m_Position": {
"x": -8.344650268554688e-7,
"y": 203.0
},
"m_Blocks": [
{
"m_Id": "0a9843ed20a94d59902f2d26c002ed64"
},
{
"m_Id": "72a96e3c01214831bec7cea6fa437e31"
}
]
},
"m_PreviewData": {
"serializedMesh": {
"m_SerializedMesh": "{\"mesh\":{\"instanceID\":0}}",
"m_Guid": ""
},
"preventRotation": false
},
"m_Path": "Shader Graphs",
"m_GraphPrecision": 1,
"m_PreviewMode": 2,
"m_OutputNode": {
"m_Id": ""
},
"m_SubDatas": [],
"m_ActiveTargets": [
{
"m_Id": "721edf9773f04429aa73dba209212df6"
}
]
}
{
"m_SGVersion": 0,
"m_Type": "UnityEditor.ShaderGraph.BlockNode",
"m_ObjectId": "0a9843ed20a94d59902f2d26c002ed64",
"m_Group": {
"m_Id": ""
},
"m_Name": "SurfaceDescription.BaseColor",
"m_DrawState": {
"m_Expanded": true,
"m_Position": {
"serializedVersion": "2",
"x": 0.0,
"y": 0.0,
"width": 0.0,
"height": 0.0
}
},
"m_Slots": [
{
"m_Id": "744ba17487394e16b7267fc8861ca742"
}
],
"synonyms": [],
"m_Precision": 0,
"m_PreviewExpanded": true,
"m_DismissedVersion": 0,
"m_PreviewMode": 0,
"m_CustomColors": {
"m_SerializableColors": []
},
"m_SerializedDescriptor": "SurfaceDescription.BaseColor"
}
{
"m_SGVersion": 0,
"m_Type": "UnityEditor.ShaderGraph.BooleanMaterialSlot",
"m_ObjectId": "1b359f2fdaf64a209b6b5ed1f9c632f5",
"m_Id": 2,
"m_DisplayName": "IsVertical",
"m_SlotType": 0,
"m_Hidden": false,
"m_ShaderOutputName": "IsVertical",
"m_StageCapability": 3,
"m_Value": false,
"m_DefaultValue": false
}
{
"m_SGVersion": 0,
"m_Type": "UnityEditor.Rendering.Fullscreen.ShaderGraph.FullscreenData",
"m_ObjectId": "3bb7351cc39844cb95efd642c32186d1",
"m_Version": 0,
"m_fullscreenMode": 0,
"m_BlendMode": 0,
"m_SrcColorBlendMode": 0,
"m_DstColorBlendMode": 1,
"m_ColorBlendOperation": 0,
"m_SrcAlphaBlendMode": 0,
"m_DstAlphaBlendMode": 1,
"m_AlphaBlendOperation": 0,
"m_EnableStencil": false,
"m_StencilReference": 0,
"m_StencilReadMask": 255,
"m_StencilWriteMask": 255,
"m_StencilCompareFunction": 8,
"m_StencilPassOperation": 0,
"m_StencilFailOperation": 0,
"m_StencilDepthFailOperation": 0,
"m_DepthWrite": false,
"m_depthWriteMode": 0,
"m_AllowMaterialOverride": false,
"m_DepthTestMode": 0
}
{
"m_SGVersion": 0,
"m_Type": "UnityEditor.ShaderGraph.PropertyNode",
"m_ObjectId": "5b3e329ec4094ae4bc2abb0232536617",
"m_Group": {
"m_Id": ""
},
"m_Name": "Property",
"m_DrawState": {
"m_Expanded": true,
"m_Position": {
"serializedVersion": "2",
"x": -472.9999694824219,
"y": 330.0,
"width": 125.0,
"height": 34.000030517578128
}
},
"m_Slots": [
{
"m_Id": "b17cccf2792142d5a394e1ea5badc029"
}
],
"synonyms": [],
"m_Precision": 0,
"m_PreviewExpanded": true,
"m_DismissedVersion": 0,
"m_PreviewMode": 0,
"m_CustomColors": {
"m_SerializableColors": []
},
"m_Property": {
"m_Id": "a50e4944b7f14398b3018f3c3d627822"
}
}
{
"m_SGVersion": 0,
"m_Type": "UnityEditor.Rendering.Universal.ShaderGraph.UniversalFullscreenSubTarget",
"m_ObjectId": "67ffc5ea38334198b53c195bbb22a21e"
}
{
"m_SGVersion": 1,
"m_Type": "UnityEditor.Rendering.Universal.ShaderGraph.UniversalTarget",
"m_ObjectId": "721edf9773f04429aa73dba209212df6",
"m_Datas": [
{
"m_Id": "3bb7351cc39844cb95efd642c32186d1"
}
],
"m_ActiveSubTarget": {
"m_Id": "67ffc5ea38334198b53c195bbb22a21e"
},
"m_AllowMaterialOverride": false,
"m_SurfaceType": 0,
"m_ZTestMode": 4,
"m_ZWriteControl": 0,
"m_AlphaMode": 0,
"m_RenderFace": 2,
"m_AlphaClip": false,
"m_CastShadows": true,
"m_ReceiveShadows": true,
"m_DisableTint": false,
"m_Sort3DAs2DCompatible": false,
"m_AdditionalMotionVectorMode": 0,
"m_AlembicMotionVectors": false,
"m_SupportsLODCrossFade": false,
"m_CustomEditorGUI": "",
"m_SupportVFX": false
}
{
"m_SGVersion": 0,
"m_Type": "UnityEditor.ShaderGraph.BlockNode",
"m_ObjectId": "72a96e3c01214831bec7cea6fa437e31",
"m_Group": {
"m_Id": ""
},
"m_Name": "SurfaceDescription.Alpha",
"m_DrawState": {
"m_Expanded": true,
"m_Position": {
"serializedVersion": "2",
"x": 0.0,
"y": 0.0,
"width": 0.0,
"height": 0.0
}
},
"m_Slots": [
{
"m_Id": "8789342de42c4bc3ae71d086329d5e3e"
}
],
"synonyms": [],
"m_Precision": 0,
"m_PreviewExpanded": true,
"m_DismissedVersion": 0,
"m_PreviewMode": 0,
"m_CustomColors": {
"m_SerializableColors": []
},
"m_SerializedDescriptor": "SurfaceDescription.Alpha"
}
{
"m_SGVersion": 0,
"m_Type": "UnityEditor.ShaderGraph.ColorRGBMaterialSlot",
"m_ObjectId": "744ba17487394e16b7267fc8861ca742",
"m_Id": 0,
"m_DisplayName": "Base Color",
"m_SlotType": 0,
"m_Hidden": false,
"m_ShaderOutputName": "BaseColor",
"m_StageCapability": 2,
"m_Value": {
"x": 0.5,
"y": 0.5,
"z": 0.5
},
"m_DefaultValue": {
"x": 0.5,
"y": 0.5,
"z": 0.5
},
"m_Labels": [],
"m_ColorMode": 0,
"m_DefaultColor": {
"r": 0.5,
"g": 0.5,
"b": 0.5,
"a": 1.0
}
}
{
"m_SGVersion": 0,
"m_Type": "UnityEditor.ShaderGraph.Vector3MaterialSlot",
"m_ObjectId": "8010e36d947b4c6dae41cf0131705a5c",
"m_Id": 3,
"m_DisplayName": "Output",
"m_SlotType": 1,
"m_Hidden": false,
"m_ShaderOutputName": "Output",
"m_StageCapability": 3,
"m_Value": {
"x": 0.0,
"y": 0.0,
"z": 0.0
},
"m_DefaultValue": {
"x": 0.0,
"y": 0.0,
"z": 0.0
},
"m_Labels": []
}
{
"m_SGVersion": 0,
"m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot",
"m_ObjectId": "8789342de42c4bc3ae71d086329d5e3e",
"m_Id": 0,
"m_DisplayName": "Alpha",
"m_SlotType": 0,
"m_Hidden": false,
"m_ShaderOutputName": "Alpha",
"m_StageCapability": 2,
"m_Value": 1.0,
"m_DefaultValue": 1.0,
"m_Labels": [],
"m_LiteralMode": false
}
{
"m_SGVersion": 0,
"m_Type": "UnityEditor.ShaderGraph.Internal.BooleanShaderProperty",
"m_ObjectId": "a50e4944b7f14398b3018f3c3d627822",
"m_Guid": {
"m_GuidSerialized": "abb0ee7b-effe-42ec-84de-a0971412938d"
},
"promotedFromAssetID": "",
"promotedFromCategoryName": "",
"promotedOrdering": -1,
"m_Name": "IsVertical",
"m_DefaultRefNameVersion": 1,
"m_RefNameGeneratedByDisplayName": "IsVertical",
"m_DefaultReferenceName": "_IsVertical",
"m_OverrideReferenceName": "",
"m_GeneratePropertyBlock": true,
"m_UseCustomSlotLabel": false,
"m_CustomSlotLabel": "",
"m_DismissedVersion": 0,
"m_Precision": 0,
"overrideHLSLDeclaration": true,
"hlslDeclarationOverride": 2,
"m_Hidden": false,
"m_PerRendererData": false,
"m_customAttributes": [],
"m_Value": false
}
{
"m_SGVersion": 0,
"m_Type": "UnityEditor.ShaderGraph.ScreenPositionNode",
"m_ObjectId": "acd4a53e615644308e5396077e64ea1f",
"m_Group": {
"m_Id": ""
},
"m_Name": "Screen Position",
"m_DrawState": {
"m_Expanded": true,
"m_Position": {
"serializedVersion": "2",
"x": -492.99993896484377,
"y": 119.99998474121094,
"width": 144.99996948242188,
"height": 128.0
}
},
"m_Slots": [
{
"m_Id": "be3a5e50a8c94b92a979f94a841c5764"
}
],
"synonyms": [],
"m_Precision": 0,
"m_PreviewExpanded": false,
"m_DismissedVersion": 0,
"m_PreviewMode": 0,
"m_CustomColors": {
"m_SerializableColors": []
},
"m_ScreenSpaceType": 0
}
{
"m_SGVersion": 0,
"m_Type": "UnityEditor.ShaderGraph.BooleanMaterialSlot",
"m_ObjectId": "b17cccf2792142d5a394e1ea5badc029",
"m_Id": 0,
"m_DisplayName": "IsVertical",
"m_SlotType": 1,
"m_Hidden": false,
"m_ShaderOutputName": "Out",
"m_StageCapability": 3,
"m_Value": false,
"m_DefaultValue": false
}
{
"m_SGVersion": 0,
"m_Type": "UnityEditor.ShaderGraph.CategoryData",
"m_ObjectId": "b9782225abb9483c85024af7c4b9a57c",
"m_Name": "",
"m_ChildObjectList": [
{
"m_Id": "a50e4944b7f14398b3018f3c3d627822"
}
]
}
{
"m_SGVersion": 0,
"m_Type": "UnityEditor.ShaderGraph.Vector4MaterialSlot",
"m_ObjectId": "be3a5e50a8c94b92a979f94a841c5764",
"m_Id": 0,
"m_DisplayName": "Out",
"m_SlotType": 1,
"m_Hidden": false,
"m_ShaderOutputName": "Out",
"m_StageCapability": 3,
"m_Value": {
"x": 0.0,
"y": 0.0,
"z": 0.0,
"w": 0.0
},
"m_DefaultValue": {
"x": 0.0,
"y": 0.0,
"z": 0.0,
"w": 0.0
},
"m_Labels": []
}
{
"m_SGVersion": 0,
"m_Type": "UnityEditor.ShaderGraph.Vector2MaterialSlot",
"m_ObjectId": "d2638a2b712c4cdaba6fd90e89969648",
"m_Id": 0,
"m_DisplayName": "UV",
"m_SlotType": 0,
"m_Hidden": false,
"m_ShaderOutputName": "UV",
"m_StageCapability": 3,
"m_Value": {
"x": 0.0,
"y": 0.0
},
"m_DefaultValue": {
"x": 0.0,
"y": 0.0
},
"m_Labels": []
}
{
"m_SGVersion": 1,
"m_Type": "UnityEditor.ShaderGraph.CustomFunctionNode",
"m_ObjectId": "e372fee5cae141e88964209e505cfe9b",
"m_Group": {
"m_Id": ""
},
"m_Name": "Blur (Custom Function)",
"m_DrawState": {
"m_Expanded": true,
"m_Position": {
"serializedVersion": "2",
"x": -305.9999694824219,
"y": 200.00003051757813,
"width": 193.00003051757813,
"height": 125.0
}
},
"m_Slots": [
{
"m_Id": "d2638a2b712c4cdaba6fd90e89969648"
},
{
"m_Id": "1b359f2fdaf64a209b6b5ed1f9c632f5"
},
{
"m_Id": "8010e36d947b4c6dae41cf0131705a5c"
}
],
"synonyms": [
"code",
"HLSL"
],
"m_Precision": 0,
"m_PreviewExpanded": false,
"m_DismissedVersion": 0,
"m_PreviewMode": 0,
"m_CustomColors": {
"m_SerializableColors": []
},
"m_SourceType": 0,
"m_FunctionName": "Blur",
"m_FunctionSource": "9ee8e88c9f1853d42b4be28b04cb1a57",
"m_FunctionSourceUsePragmas": true,
"m_FunctionBody": "Enter function body here..."
}
@@ -0,0 +1,18 @@
fileFormatVersion: 2
guid: 2c8a30d85a2db19408479b2d8130154b
ScriptedImporter:
internalIDToNameTable: []
externalObjects: {}
serializedVersion: 2
userData:
assetBundleName:
assetBundleVariant:
script: {fileID: 11500000, guid: 625f186215c104763be7675aa2d941aa, type: 3}
useAsTemplate: 0
exposeTemplateAsShader: 0
template:
name:
category:
description:
icon: {instanceID: 0}
thumbnail: {instanceID: 0}
@@ -0,0 +1,44 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!21 &2100000
Material:
serializedVersion: 8
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_Name: BlurFullscreenVertical
m_Shader: {fileID: -6465566751694194690, guid: 2c8a30d85a2db19408479b2d8130154b, type: 3}
m_Parent: {fileID: 0}
m_ModifiedSerializedProperties: 0
m_ValidKeywords: []
m_InvalidKeywords: []
m_LightmapFlags: 4
m_EnableInstancingVariants: 0
m_DoubleSidedGI: 0
m_CustomRenderQueue: -1
stringTagMap: {}
disabledShaderPasses: []
m_LockedProperties:
m_SavedProperties:
serializedVersion: 3
m_TexEnvs:
- unity_Lightmaps:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- unity_LightmapsInd:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- unity_ShadowMasks:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
m_Ints: []
m_Floats:
- _BlurRadius: 0.05
- _IsVertical: 1
m_Colors: []
m_BuildTextureStacks: []
m_AllowLocking: 1
@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 9d42267752d1a7e40bc5061e7d657513
NativeFormatImporter:
externalObjects: {}
mainObjectFileID: 2100000
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,177 @@
using UnityEngine;
using UnityEngine.Rendering;
using UnityEngine.Rendering.Universal;
using UnityEngine.Rendering.RenderGraphModule;
public class BlurRendererFeature : ScriptableRendererFeature
{
[System.Serializable]
public class Settings
{
[Range(0f, 0.2f)] public float blurRadius = 0.02f;
[Range(0f, 1f)] public float glowThreshold = 0.6f;
[Range(0f, 2f)] public float glowIntensity = 0f;
public Material blurHorizontal;
public Material blurVertical;
}
public Settings settings = new Settings();
BlurPass horizontalPass;
BlurPass verticalPass;
CopyToRTPass copyPass;
RenderTexture blurRT;
RTHandle blurRTHandle;
static readonly int BlurTexID = Shader.PropertyToID("_BlurredTexture");
static readonly int BlurRadiusID = Shader.PropertyToID("_BlurRadius");
static readonly int GlowThresholdID = Shader.PropertyToID("_GlowThreshold");
static readonly int GlowIntensityID = Shader.PropertyToID("_GlowIntensity");
static readonly int BlurSourceID = Shader.PropertyToID("_BlurSource");
public override void Create()
{
horizontalPass = new BlurPass("Blur Horizontal", RenderPassEvent.BeforeRenderingPostProcessing);
verticalPass = new BlurPass("Blur Vertical", RenderPassEvent.BeforeRenderingPostProcessing);
copyPass = new CopyToRTPass(RenderPassEvent.BeforeRenderingPostProcessing);
}
public override void AddRenderPasses(ScriptableRenderer renderer, ref RenderingData renderingData)
{
if (settings.blurHorizontal == null || settings.blurVertical == null) return;
var desc = renderingData.cameraData.cameraTargetDescriptor;
if (blurRT != null && (blurRT.width != desc.width / 2 || blurRT.height != desc.height / 2))
{
blurRT.Release();
blurRTHandle?.Release();
blurRT = null;
blurRTHandle = null;
}
if (blurRT == null)
{
blurRT = new RenderTexture(desc.width / 4, desc.height / 4, 0, RenderTextureFormat.DefaultHDR);
blurRT.Create();
blurRTHandle = RTHandles.Alloc(blurRT);
Shader.SetGlobalTexture(BlurTexID, blurRT);
}
Shader.SetGlobalFloat(BlurRadiusID, settings.blurRadius);
Shader.SetGlobalFloat(GlowThresholdID, settings.glowThreshold);
Shader.SetGlobalFloat(GlowIntensityID, settings.glowIntensity);
horizontalPass.Setup(settings.blurHorizontal);
renderer.EnqueuePass(horizontalPass);
verticalPass.Setup(settings.blurVertical);
renderer.EnqueuePass(verticalPass);
copyPass.Setup(blurRTHandle);
renderer.EnqueuePass(copyPass);
}
protected override void Dispose(bool disposing)
{
if (blurRT != null)
{
blurRT.Release();
blurRT = null;
}
blurRTHandle?.Release();
blurRTHandle = null;
}
class BlurPass : ScriptableRenderPass
{
string passName;
Material material;
static readonly int BlurSourceID = Shader.PropertyToID("_BlurSource");
public BlurPass(string name, RenderPassEvent evt)
{
passName = name;
renderPassEvent = evt;
}
public void Setup(Material mat) => material = mat;
class PassData
{
public TextureHandle source;
public Material material;
}
public override void RecordRenderGraph(RenderGraph renderGraph, ContextContainer frameData)
{
var resourceData = frameData.Get<UniversalResourceData>();
var srcDesc = renderGraph.GetTextureDesc(resourceData.activeColorTexture);
srcDesc.name = passName + " Temp";
srcDesc.clearBuffer = false;
var tempHandle = renderGraph.CreateTexture(srcDesc);
using (var builder = renderGraph.AddRasterRenderPass<PassData>(passName + " Blit", out var passData))
{
passData.source = resourceData.activeColorTexture;
passData.material = material;
builder.UseTexture(passData.source, AccessFlags.Read);
builder.SetRenderAttachment(tempHandle, 0, AccessFlags.Write);
builder.AllowGlobalStateModification(true);
builder.SetRenderFunc((PassData data, RasterGraphContext ctx) =>
{
ctx.cmd.SetGlobalTexture(BlurSourceID, data.source);
Blitter.BlitTexture(ctx.cmd, data.source, new Vector4(1, 1, 0, 0), data.material, 0);
});
}
using (var builder = renderGraph.AddRasterRenderPass<PassData>(passName + " Restore", out var passData))
{
passData.source = tempHandle;
builder.UseTexture(passData.source, AccessFlags.Read);
builder.SetRenderAttachment(resourceData.activeColorTexture, 0, AccessFlags.Write);
builder.SetRenderFunc((PassData data, RasterGraphContext ctx) =>
{
Blitter.BlitTexture(ctx.cmd, data.source, new Vector4(1, 1, 0, 0), 0, false);
});
}
}
}
class CopyToRTPass : ScriptableRenderPass
{
RTHandle targetHandle;
public CopyToRTPass(RenderPassEvent evt) => renderPassEvent = evt;
public void Setup(RTHandle handle) => targetHandle = handle;
class CopyPassData { public TextureHandle source; }
public override void RecordRenderGraph(RenderGraph renderGraph, ContextContainer frameData)
{
var resourceData = frameData.Get<UniversalResourceData>();
var destHandle = renderGraph.ImportTexture(targetHandle);
using (var builder = renderGraph.AddRasterRenderPass<CopyPassData>("Copy Blur To RT", out var passData))
{
passData.source = resourceData.activeColorTexture;
builder.UseTexture(passData.source, AccessFlags.Read);
builder.SetRenderAttachment(destHandle, 0, AccessFlags.Write);
builder.SetRenderFunc((CopyPassData data, RasterGraphContext ctx) =>
{
Blitter.BlitTexture(ctx.cmd, data.source, new Vector4(1, 1, 0, 0), 0, false);
});
}
}
}
}
@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 28f54721245b3fe43aec9e49469d9d4b
@@ -1,74 +0,0 @@
#ifndef ENKI_BILLAL_FULLSCREEN_INCLUDED
#define ENKI_BILLAL_FULLSCREEN_INCLUDED
#include "Assets/_Content/Shaders/Include/Noises.hlsl"
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/DeclareOpaqueTexture.hlsl"
// Gaussian blur on scene color
// blurRadius controls the spread in pixels — adjust to taste
float3 SampleSceneColorBlurred(float2 uv, float blurRadius)
{
float3 result = 0;
float totalWeight = 0;
// Gaussian weights for 5 samples (sigma ~ 1.0)
float weights[5] = { 0.0625, 0.25, 0.375, 0.25, 0.0625 };
float offsets[5] = { -2, -1, 0, 1, 2 };
float2 texelSize = blurRadius / _ScreenParams.xy;
// Horizontal pass
for (int i = 0; i < 5; i++)
{
float2 offsetUV = uv + float2(offsets[i] * texelSize.x, 0);
result += SAMPLE_TEXTURE2D_X(_CameraOpaqueTexture, sampler_LinearClamp, offsetUV).rgb * weights[i];
}
return result;
}
void EnkiBillalFullscreen_float
(
float2 UV,
out float3 Output
)
{
float2 screenUV = UV;
// DEPTH
float rawDepth = SampleSceneDepth(screenUV);
float depthMeters = LinearEyeDepth(rawDepth, _ZBufferParams); // linear eye-space depth in metres
float depth01 = Linear01Depth(rawDepth, _ZBufferParams); // normalised linear depth [0..1]
// POSITION WORLD SPACE
// Remap depth for non-reversed-Z platforms before reconstruction
float depthForReconstruct = rawDepth;
#if !UNITY_REVERSED_Z
depthForReconstruct = lerp(UNITY_NEAR_CLIP_VALUE, 1.0, rawDepth);
#endif
// ComputeWorldSpacePosition handles perspective divide and platform differences
float3 positionWS = ComputeWorldSpacePosition(screenUV, depthForReconstruct, UNITY_MATRIX_I_VP);
// NORMAL WORLD SPACE
// Requires DepthNormals PrePass to be enabled in the URP Renderer
float3 normalWS = SampleSceneNormals(screenUV);
// SCENE COLOR
float3 originColor = SampleSceneColor(screenUV);
float greyscale = (originColor.x + originColor.y + originColor.z) / 3.0;
float3 offsetUV = PerlinColor3D(positionWS * float3(1, 5, 1), 1) * smoothstep(smoothstep(20, 3, depthMeters), 1, greyscale) * .1 / depthMeters;
float3 sceneColor = SampleSceneColor(screenUV + offsetUV);
//float3 sceneColor = SAMPLE_TEXTURE2D_X(_CameraOpaqueTexture, sampler_PointClamp, screenUV).rgb;
// OUTPUT
Output = SampleSceneColorBlurred(screenUV, 10);
}
#endif
@@ -0,0 +1,43 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!21 &2100000
Material:
serializedVersion: 8
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_Name: EnkiBillalFullscreen
m_Shader: {fileID: -6465566751694194690, guid: 9256acd168941544ea69594ff8763468, type: 3}
m_Parent: {fileID: 0}
m_ModifiedSerializedProperties: 0
m_ValidKeywords: []
m_InvalidKeywords: []
m_LightmapFlags: 4
m_EnableInstancingVariants: 0
m_DoubleSidedGI: 0
m_CustomRenderQueue: -1
stringTagMap: {}
disabledShaderPasses: []
m_LockedProperties:
m_SavedProperties:
serializedVersion: 3
m_TexEnvs:
- unity_Lightmaps:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- unity_LightmapsInd:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- unity_ShadowMasks:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
m_Ints: []
m_Floats:
- _Test: 0
m_Colors: []
m_BuildTextureStacks: []
m_AllowLocking: 1
@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 14d54f1b8620b4f469a8f7cbb0f38746
NativeFormatImporter:
externalObjects: {}
mainObjectFileID: 2100000
userData:
assetBundleName:
assetBundleVariant:
@@ -2,7 +2,11 @@
"m_SGVersion": 3,
"m_Type": "UnityEditor.ShaderGraph.GraphData",
"m_ObjectId": "5582b09252bc41cda9a92382e0bc37b6",
"m_Properties": [],
"m_Properties": [
{
"m_Id": "cdb17cfce9e347a890695f6bb440d9ed"
}
],
"m_Keywords": [],
"m_Dropdowns": [],
"m_CategoryData": [
@@ -22,6 +26,9 @@
},
{
"m_Id": "1d5c0b04e69841c9bade5e8e87181a13"
},
{
"m_Id": "c5cee5deced342b7ba5119bc3e0a4eeb"
}
],
"m_GroupDatas": [],
@@ -54,6 +61,20 @@
},
"m_SlotId": 0
}
},
{
"m_OutputSlot": {
"m_Node": {
"m_Id": "c5cee5deced342b7ba5119bc3e0a4eeb"
},
"m_SlotId": 0
},
"m_InputSlot": {
"m_Node": {
"m_Id": "a7bb6da6110b4bd2a09bff6b04958011"
},
"m_SlotId": 2
}
}
],
"m_VertexContext": {
@@ -119,6 +140,22 @@
"m_Labels": []
}
{
"m_SGVersion": 0,
"m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot",
"m_ObjectId": "131be3abda9f406597ba5042775c2409",
"m_Id": 2,
"m_DisplayName": "New",
"m_SlotType": 0,
"m_Hidden": false,
"m_ShaderOutputName": "New",
"m_StageCapability": 3,
"m_Value": 0.0,
"m_DefaultValue": 0.0,
"m_Labels": [],
"m_LiteralMode": false
}
{
"m_SGVersion": 0,
"m_Type": "UnityEditor.ShaderGraph.ScreenPositionNode",
@@ -131,10 +168,10 @@
"m_Expanded": true,
"m_Position": {
"serializedVersion": "2",
"x": -927.1663818359375,
"y": 116.83366394042969,
"width": 208.0,
"height": 312.0
"x": -610.0,
"y": 200.00003051757813,
"width": 145.0,
"height": 128.0
}
},
"m_Slots": [
@@ -144,7 +181,7 @@
],
"synonyms": [],
"m_Precision": 0,
"m_PreviewExpanded": true,
"m_PreviewExpanded": false,
"m_DismissedVersion": 0,
"m_PreviewMode": 0,
"m_CustomColors": {
@@ -306,10 +343,10 @@
"m_Expanded": true,
"m_Position": {
"serializedVersion": "2",
"x": -511.9999694824219,
"y": 191.99998474121095,
"x": -387.0,
"y": 200.00003051757813,
"width": 262.0,
"height": 77.00001525878906
"height": 94.0
}
},
"m_Slots": [
@@ -318,6 +355,9 @@
},
{
"m_Id": "f840ccb65a474f4c999bc6357918f904"
},
{
"m_Id": "131be3abda9f406597ba5042775c2409"
}
],
"synonyms": [
@@ -338,12 +378,108 @@
"m_FunctionBody": "Enter function body here..."
}
{
"m_SGVersion": 0,
"m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot",
"m_ObjectId": "b57799888be6474b86b25290647e3aa2",
"m_Id": 0,
"m_DisplayName": "Test",
"m_SlotType": 1,
"m_Hidden": false,
"m_ShaderOutputName": "Out",
"m_StageCapability": 3,
"m_Value": 0.0,
"m_DefaultValue": 0.0,
"m_Labels": [],
"m_LiteralMode": false
}
{
"m_SGVersion": 0,
"m_Type": "UnityEditor.ShaderGraph.PropertyNode",
"m_ObjectId": "c5cee5deced342b7ba5119bc3e0a4eeb",
"m_Group": {
"m_Id": ""
},
"m_Name": "Property",
"m_DrawState": {
"m_Expanded": true,
"m_Position": {
"serializedVersion": "2",
"x": -563.0,
"y": 359.0,
"width": 98.0,
"height": 34.0
}
},
"m_Slots": [
{
"m_Id": "b57799888be6474b86b25290647e3aa2"
}
],
"synonyms": [],
"m_Precision": 0,
"m_PreviewExpanded": true,
"m_DismissedVersion": 0,
"m_PreviewMode": 0,
"m_CustomColors": {
"m_SerializableColors": []
},
"m_Property": {
"m_Id": "cdb17cfce9e347a890695f6bb440d9ed"
}
}
{
"m_SGVersion": 0,
"m_Type": "UnityEditor.Rendering.Universal.ShaderGraph.UniversalFullscreenSubTarget",
"m_ObjectId": "cba6f25984a64bdcb4659d47165011b5"
}
{
"m_SGVersion": 1,
"m_Type": "UnityEditor.ShaderGraph.Internal.Vector1ShaderProperty",
"m_ObjectId": "cdb17cfce9e347a890695f6bb440d9ed",
"m_Guid": {
"m_GuidSerialized": "7c5584ea-2894-41c1-963c-f04c035d1e3e"
},
"promotedFromAssetID": "",
"promotedFromCategoryName": "",
"promotedOrdering": -1,
"m_Name": "Test",
"m_DefaultRefNameVersion": 1,
"m_RefNameGeneratedByDisplayName": "Test",
"m_DefaultReferenceName": "_Test",
"m_OverrideReferenceName": "",
"m_GeneratePropertyBlock": true,
"m_UseCustomSlotLabel": false,
"m_CustomSlotLabel": "",
"m_DismissedVersion": 0,
"m_Precision": 0,
"overrideHLSLDeclaration": false,
"hlslDeclarationOverride": 0,
"m_Hidden": false,
"m_PerRendererData": false,
"m_customAttributes": [],
"m_Value": 0.0,
"m_FloatType": 1,
"m_LiteralFloatMode": false,
"m_RangeValues": {
"x": 0.0,
"y": 1.0
},
"m_SliderType": 0,
"m_SliderPower": 3.0,
"m_EnumType": 0,
"m_CSharpEnumString": "",
"m_EnumNames": [
"Default"
],
"m_EnumValues": [
0
]
}
{
"m_SGVersion": 1,
"m_Type": "UnityEditor.Rendering.Universal.ShaderGraph.UniversalTarget",
@@ -404,7 +540,11 @@
"m_Type": "UnityEditor.ShaderGraph.CategoryData",
"m_ObjectId": "ee714d8b4e8e40cf9723c0f8c2f5bfea",
"m_Name": "",
"m_ChildObjectList": []
"m_ChildObjectList": [
{
"m_Id": "cdb17cfce9e347a890695f6bb440d9ed"
}
]
}
{
@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: e43c66bae4052fd48afb62ab2095f613
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,81 @@
#ifndef BLUR_FULLSCREEN_INCLUDED
#define BLUR_FULLSCREEN_INCLUDED
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/DeclareDepthTexture.hlsl"
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/DeclareOpaqueTexture.hlsl"
float _BlurRadius;
float _GlowThreshold;
float _GlowIntensity;
TEXTURE2D_X(_BlurSource);
SAMPLER(sampler_BlurSource);
float4 _BlurSource_TexelSize;
float Hash(float2 p)
{
return frac(sin(dot(p, float2(127.1, 311.7))) * 43758.5453);
}
float3 ApplyGlowThreshold(float3 color)
{
float luminance = dot(color, float3(0.2126, 0.7152, 0.0722));
float mask = smoothstep(_GlowThreshold, _GlowThreshold + 0.3, luminance);
return color * mask;
}
void Blur_float
(
float2 UV,
bool IsVertical,
out float3 Output
)
{
float rawDepth = SampleSceneDepth(UV);
float depthMeters = LinearEyeDepth(rawDepth, _ZBufferParams);
float depthFactor = smoothstep(3, 20, depthMeters);
float stepY = (_BlurRadius * depthFactor) / 6.0;
float stepX = stepY * (_BlurSource_TexelSize.w / _BlurSource_TexelSize.z);
float jitter = (Hash(UV * _BlurSource_TexelSize.zw) - 0.5) * _BlurRadius * depthFactor * 20.0;
float2 dir = IsVertical ? float2(0.0, stepY) : float2(stepX, 0.0);
const int TAPS = 13;
const float offsets[13] = { -6.0, -4.7, -3.2, -2.1, -1.2, -0.4, 0.0, 0.4, 1.2, 2.1, 3.2, 4.7, 6.0 };
const float weights[13] =
{
0.00650, 0.02981, 0.07810, 0.14624, 0.22230, 0.27240,
0.29000,
0.27240, 0.22230, 0.14624, 0.07810, 0.02981, 0.00650
};
float3 centerColor = SAMPLE_TEXTURE2D_X(_BlurSource, sampler_BlurSource, UV).rgb;
float3 result = float3(0.0, 0.0, 0.0);
float totalWeight = 0.0;
for (int i = 0; i < TAPS; i++)
{
float2 offsetUV = UV + dir * (offsets[i] + jitter);
float tapRawDepth = SampleSceneDepth(offsetUV);
float tapDepth = LinearEyeDepth(tapRawDepth, _ZBufferParams);
float depthDiff = abs(tapDepth - depthMeters);
float depthWeight = exp(-depthDiff * 0.5);
float sw = weights[i] * depthWeight;
float3 tapColor = SAMPLE_TEXTURE2D_X(_BlurSource, sampler_BlurSource, offsetUV).rgb;
// GlowIntensity = 0 → full color blur, GlowIntensity = 1 → bright pixels only
float3 contribution = lerp(tapColor, ApplyGlowThreshold(tapColor), saturate(_GlowIntensity));
result += contribution * sw;
totalWeight += sw;
}
float3 center = lerp(centerColor, ApplyGlowThreshold(centerColor), saturate(_GlowIntensity));
// Scene color for additive glow compositing
float3 sceneColor = SAMPLE_TEXTURE2D_X(_CameraOpaqueTexture, sampler_LinearClamp, UV).rgb;
float3 blurred = totalWeight > 0.01 ? result / totalWeight : center;
// GlowIntensity = 0 → pure blur, GlowIntensity > 0 → scene + additive glow
Output = lerp(blurred, sceneColor + blurred, saturate(_GlowIntensity));
}
#endif
@@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: 9ee8e88c9f1853d42b4be28b04cb1a57
ShaderIncludeImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,131 @@
#ifndef ENKI_BILLAL_FULLSCREEN_INCLUDED
#define ENKI_BILLAL_FULLSCREEN_INCLUDED
#include "Assets/_Content/Shaders/Include/Noises.hlsl"
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/DeclareOpaqueTexture.hlsl"
#include "Assets/_Content/Shaders/Postprocess/Include/BlurFullscreen.hlsl"
TEXTURE2D_X(_BlurredTexture);
SAMPLER(sampler_BlurredTexture);
// ─── OUTLINE ────────────────────────────────────────────────────────────────
// Width is expressed as a fraction of screen height.
// Both depth discontinuities and normal discontinuities contribute.
float ComputeOutline(float2 uv, float outlineWidthPx, float depthThreshold, float normalThreshold)
{
// Pixel size in UV space, scaled by desired width
float2 texel = outlineWidthPx / float2(_ScreenParams.x, _ScreenParams.y);
// ── Sample depth at 4 neighbours (Roberts Cross pattern) ────────────────
float d0 = LinearEyeDepth(SampleSceneDepth(uv + float2(texel.x, texel.y)), _ZBufferParams);
float d1 = LinearEyeDepth(SampleSceneDepth(uv + float2(-texel.x, texel.y)), _ZBufferParams);
float d2 = LinearEyeDepth(SampleSceneDepth(uv + float2(texel.x, -texel.y)), _ZBufferParams);
float d3 = LinearEyeDepth(SampleSceneDepth(uv + float2(-texel.x, -texel.y)), _ZBufferParams);
// Roberts Cross gradient magnitude on depth
float depthEdge = sqrt(pow(d0 - d3, 2) + pow(d1 - d2, 2));
// Normalise by depth so far geometry doesn't get thick outlines
float dCenter = LinearEyeDepth(SampleSceneDepth(uv), _ZBufferParams);
depthEdge /= (dCenter + 1e-4);
// ── Sample normals at the same 4 neighbours ──────────────────────────────
float3 n0 = SampleSceneNormals(uv + float2(texel.x, texel.y));
float3 n1 = SampleSceneNormals(uv + float2(-texel.x, texel.y));
float3 n2 = SampleSceneNormals(uv + float2(texel.x, -texel.y));
float3 n3 = SampleSceneNormals(uv + float2(-texel.x, -texel.y));
// Dot-product difference: 0 = identical normals, 1 = orthogonal / flipped
float normalEdge = 0;
normalEdge += 1.0 - saturate(dot(n0, n3));
normalEdge += 1.0 - saturate(dot(n1, n2));
normalEdge *= 0.5;
// ── Combine and threshold ────────────────────────────────────────────────
float edge = max(
step(depthThreshold, depthEdge),
step(normalThreshold, normalEdge)
);
return edge;
}
void EnkiBillalFullscreen_float
(
float2 UV,
float Test,
out float3 Output
)
{
float2 screenUV = UV;
// DEPTH
float rawDepth = SampleSceneDepth(screenUV);
float depthMeters = LinearEyeDepth(rawDepth, _ZBufferParams); // linear eye-space depth in metres
float depth01 = Linear01Depth(rawDepth, _ZBufferParams); // normalised linear depth [0..1]
// POSITION WORLD SPACE
// Remap depth for non-reversed-Z platforms before reconstruction
float depthForReconstruct = rawDepth;
#if !UNITY_REVERSED_Z
depthForReconstruct = lerp(UNITY_NEAR_CLIP_VALUE, 1.0, rawDepth);
#endif
// ComputeWorldSpacePosition handles perspective divide and platform differences
float3 positionWS = ComputeWorldSpacePosition(screenUV, depthForReconstruct, UNITY_MATRIX_I_VP);
// NORMAL WORLD SPACE
// Requires DepthNormals PrePass to be enabled in the URP Renderer
float3 normalWS = SampleSceneNormals(screenUV);
// SCENE COLOR
float3 originColor = SampleSceneColor(screenUV);
float3 sceneColorBlurred = SAMPLE_TEXTURE2D_X(_BlurredTexture, sampler_BlurredTexture, screenUV).rgb;
float greyscale = (originColor.x + originColor.y + originColor.z);
float greyscaleBlurred = (sceneColorBlurred.x + sceneColorBlurred.y + sceneColorBlurred.z);
float hilightMask = smoothstep(.7, 1, greyscale);
hilightMask = lerp(hilightMask, smoothstep(.7, 1, greyscaleBlurred), .5);
hilightMask *= pow(smoothstep(3, 20, depthMeters), 2);
float offsetMask = hilightMask;
float3 offset3D = PerlinColor3D(positionWS * float3(1, 6, 1), 1);
offset3D = smoothstep(.45, .55, offset3D);
float3 offsetUV = offset3D * offsetMask * .4 / depthMeters;
float3 sceneColor = SampleSceneColor(screenUV + offsetUV);
sceneColor = lerp(sceneColor, sceneColorBlurred, hilightMask);
sceneColor = lerp(sceneColor, originColor, .5);
sceneColor = lerp(sceneColor * .5, sceneColor * 1, hilightMask);
//float3 sceneColor = SAMPLE_TEXTURE2D_X(_CameraOpaqueTexture, sampler_PointClamp, screenUV).rgb;
// OUTLINE
float OutlineWidthPx = max(PerlinNoise3D(positionWS, 1) * 3 - 1, 0);
float OutlineDepthThreshold = .03;
float OutlineNormalThreshold = .35;
float OutlineColor = float3(0, 0, 0);
// Width is normalised to screen height so it stays consistent at any resolution.
float widthInPixels = OutlineWidthPx * (_ScreenParams.y / 1080.0);
float outline = ComputeOutline(screenUV, widthInPixels, OutlineDepthThreshold, OutlineNormalThreshold);
sceneColor = lerp(sceneColor, OutlineColor, outline);
// OUTPUT
Output = sceneColor; //BlurSceneColor(screenUV, .1);
//Output = offsetMask;
//Output = hilightMask; //BlurSceneColor(screenUV, .1);
//Output = lerp(originColor, sceneColorBlurred, smoothstep(3, 20, depthMeters));
}
#endif