Hi guys, I’m currently implementing a shadow volume technique in URP, and I just had a question if something was possible. Essentially, everything about the volume generation and shadows works great; the only problem comes from the lack of blurring in the shadows. Since my shadow extrusion technique is based on triangles that don’t face the light, this causes hard polygonal edges to be extruded (see pic below) for self-shadowing. My idea to solve this problem is to essentially render the stencil buffer as a mask to a render texture, where from there, I could apply a gaussian blur on it and then blit it back to the main camera as a post-processing feature. This would create much more blurry shadows, but would also be a cheap way to fake/emulate soft shadows. Since I’m on URP, I can’t natively use multi-pass in my shaders, so I had to make a render feature to do this (see code below). What I was wondering, is if there is any way for me to set up my feature to be able to pipe in the stencil buffer into a mask texture, or something of the sort. If anyone has any ideas, it would be greatly appreciated, thanks!
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Rendering;
using UnityEngine.Rendering.Universal;
[System.Serializable]
public class SilhouetteEdgeHighlightSettings
{
public Material targetMaterial = null; // Assign this in the inspector
}
public class SilhouetteEdgeHighlightFeature : ScriptableRendererFeature
{
public SilhouetteEdgeHighlightSettings settings = new SilhouetteEdgeHighlightSettings();
class SilhouetteRenderPass : ScriptableRenderPass
{
private List<ShaderTagId> m_Tags;
private Material targetMaterial;
public SilhouetteRenderPass(List<string> tags, Material material)
{
targetMaterial = material;
m_Tags = new List<ShaderTagId>();
foreach (string tag in tags)
{
m_Tags.Add(new ShaderTagId(tag));
}
this.renderPassEvent = RenderPassEvent.AfterRenderingOpaques;
}
public override void Execute(ScriptableRenderContext context, ref RenderingData renderingData)
{
int layerIndex = 3;
int layerMask = 1 << layerIndex;
FilteringSettings filterSettings = new FilteringSettings(RenderQueueRange.opaque, layerMask); // Or any specific range or layer mask
// Iterate over each ShaderTagId you wish to render with the targetMaterial
foreach (ShaderTagId tag in m_Tags)
{
DrawingSettings drawingSettings = CreateDrawingSettings(tag, ref renderingData, SortingCriteria.CommonOpaque);
context.DrawRenderers(renderingData.cullResults, ref drawingSettings, ref filterSettings);
}
context.Submit();
}
}
private SilhouetteRenderPass m_ScriptablePass;
public List<string> lightModePasses;
public override void Create()
{
m_ScriptablePass = new SilhouetteRenderPass(lightModePasses, settings.targetMaterial);
}
public override void AddRenderPasses(ScriptableRenderer renderer, ref RenderingData renderingData)
{
if(settings.targetMaterial != null)
{
renderer.EnqueuePass(m_ScriptablePass);
}
}
}