Hello everyone,
I am trying to implement a simple URP (14.0) RenderPass using a shader created in the shader graph that would modify the alpha value of my fragment. Surprisingly I cannot get it to work at all, nothing changes even though I only have a simple Mesh using the Default-Line material to modify the colour of.
For that I am using a global volume with a simple float parameter directly set into the output alpha. I have enabled the post-processing on my camera as well.
I recently made the decision to switch from the built-in to URP and I have to admit that I was expecting something more reliable and user-friendly.
Here’s my code:
public class AlphaRenderFeature : ScriptableRendererFeature
{
public class AlphaVolumeData : VolumeComponent
{
public static readonly int AlphaId = Shader.PropertyToID("_Alpha");
[Range(0, 1)] public FloatParameter m_Alpha = new(.5f);
}
public class AlphaRenderPass : ScriptableRenderPass
{
private const RenderTextureFormat ColorFormat = RenderTextureFormat.ARGB32;
private readonly Material m_material;
private RTHandle m_handle;
private RenderTargetIdentifier m_targetIdentifier;
private RenderTextureDescriptor m_textureDescriptor;
public AlphaRenderPass(Material a_material) {
m_material = a_material;
m_textureDescriptor = new RenderTextureDescriptor(Screen.width, Screen.height, ColorFormat);
}
public override void Configure(CommandBuffer a_cmd, RenderTextureDescriptor a_cameraTextureDescriptor) {
base.Configure(a_cmd, a_cameraTextureDescriptor);
m_textureDescriptor.width = a_cameraTextureDescriptor.width;
m_textureDescriptor.height = a_cameraTextureDescriptor.height;
// Note: I tried with and without this line, but it doesn't seem to make a difference.
//m_textureDescriptor.colorFormat = a_cameraTextureDescriptor.colorFormat;
Debug.Log(
$"Configuring AlphaRenderPass with {m_textureDescriptor.width}x{m_textureDescriptor.height} {m_textureDescriptor.colorFormat}");
RenderingUtils.ReAllocateIfNeeded(ref m_handle, in m_textureDescriptor);
}
public override void Execute(ScriptableRenderContext a_context, ref RenderingData a_renderingData) {
var cmd = CommandBufferPool.Get();
var cameraHandle = a_renderingData.cameraData.renderer.cameraColorTargetHandle;
var volumeData = VolumeManager.instance.stack.GetComponent<AlphaVolumeData>();
if (volumeData is not null) {
m_material.SetFloat(AlphaVolumeData.AlphaId, volumeData.m_Alpha.value);
}
Blit(cmd, cameraHandle, m_handle, m_material, 0);
Blit(cmd, m_handle, cameraHandle, m_material, 1);
a_context.ExecuteCommandBuffer(cmd);
CommandBufferPool.Release(cmd);
}
[UsedImplicitly]
public void Dispose() {
m_handle?.Release();
}
}
[SerializeField] private Shader m_shader;
private Material m_material;
private AlphaRenderPass m_renderPass;
public override void Create() {
if (m_shader == null)
return;
m_material = CoreUtils.CreateEngineMaterial(m_shader);
m_renderPass = new AlphaRenderPass(m_material) {
renderPassEvent = RenderPassEvent.AfterRenderingTransparents
};
}
public override void AddRenderPasses(ScriptableRenderer a_renderer, ref RenderingData a_renderingData) {
if (a_renderingData.cameraData.cameraType == CameraType.Game)
a_renderer.EnqueuePass(m_renderPass);
}
protected override void Dispose(bool a_disposing) {
if (a_disposing)
CoreUtils.Destroy(m_material);
}
}
And my shader: