うにてぃブログ

UnityやUnreal Engineの記事を書いていきます

【Unity】RendererFeature を利用したソナー表現

qiita.com

上記の記事を参考に RendererFeature の FullScreen で利用できるソナー表現を作成しました

※ Unity2021 URP12.1.8

Shader "Hidden/SonarImageEffectShader"
{
    SubShader
    {
        Cull Off ZWrite Off ZTest Always
 
        Pass
        {
            HLSLPROGRAM
            #pragma vertex FullscreenVert
            #pragma fragment frag
            
            #include "Packages/com.unity.render-pipelines.universal/Shaders/PostProcessing/Common.hlsl"
            #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/DeclareDepthTexture.hlsl"
            
            TEXTURE2D_X(_SourceTex);
            SAMPLER(sampler_SourceTex);
 
            half4 _Param;
            half4 _SonarColor;
            
            float Sonar(half2 uv)
            {
                half3 center = half3(0, 0, 0);
                
                float depth = SampleSceneDepth(uv);
                half3 pos = ComputeWorldSpacePosition(uv, depth, UNITY_MATRIX_I_VP);
                 
                float distance = length(pos - center);
                 
                float w = distance - _Time.y * _Param.w;
 
                w /= _Param.z;
                w = w - floor(w);
 
                float p = _Param.y;
                w = (pow(w, p) + pow(1 - w, p * 4)) * 0.5;
  
                w *= _Param.x;
                 
                return w * step(distance, 1000);
            }

            half4 frag(Varyings i) : SV_Target
            {
                half4 col = SAMPLE_TEXTURE2D_X( _SourceTex, sampler_SourceTex, i.uv);
                
                float strength = Sonar(i.uv);
                col.rgb = lerp(col.rgb, _SonarColor, strength);
                
                return col;
            }
            
            ENDHLSL
        }
    }
}
using System;
using UnityEngine;
using UnityEngine.Rendering;
using UnityEngine.Rendering.Universal;

public class SonarRendererFeature : ScriptableRendererFeature
{
    [SerializeField]
    private Shader _shader;

    [SerializeField]
    private Param _param;
 
    private SonarRendererPass _pass;
 
    [Serializable]
    public class Param
    {
        [SerializeField]
        private float Amplify;
        [SerializeField]
        private float Exponent;
        [SerializeField]
        private float Interval;
        [SerializeField]
        private float Speed;

        public Color Color;

        public Vector4 Data => new Vector4(Amplify, Exponent, Interval, Speed);
    }
    
    public override void Create()
    {
        _pass = new SonarRendererPass(_shader, _param);
    }
 
    public override void AddRenderPasses(ScriptableRenderer renderer, ref RenderingData renderingData)
    {
        renderer.EnqueuePass(_pass);
    }
}
 
public class SonarRendererPass : ScriptableRenderPass
{
    private Material _material;
    private const string _name = nameof(SonarRendererPass);
    private SonarRendererFeature.Param _param;
    
    private static readonly int Param = Shader.PropertyToID("_Param");
    private static readonly int SonarColor = Shader.PropertyToID("_SonarColor");

    public SonarRendererPass(Shader shader, SonarRendererFeature.Param param)
    {
        if (shader == null)
            return;
 
        _param = param;
        renderPassEvent = RenderPassEvent.AfterRenderingPostProcessing;
        _material = CoreUtils.CreateEngineMaterial(shader);
        
        ConfigureInput(ScriptableRenderPassInput.Depth);
    }
 
    public override void Execute(ScriptableRenderContext context, ref RenderingData data)
    {
        if (_material == null
            || !data.cameraData.postProcessEnabled
           )
        {
            return;
        }
        
        var commandBuffer = CommandBufferPool.Get(_name);
 
        using (new ProfilingScope(commandBuffer, new ProfilingSampler(_name)))
        {
            _material.SetVector(Param, _param.Data);
            _material.SetColor(SonarColor, _param.Color);
            Blit(commandBuffer, ref data, _material);
        }
 
        context.ExecuteCommandBuffer(commandBuffer);
        CommandBufferPool.Release(commandBuffer);
    }
}