ainatipen 发表于 2022-10-27 11:09

Unity 黑白闪效果

游戏中经常会使用将画面通过短暂的黑白闪来实现激烈的表现效果.如下图:


为了让特效有跟好的控制,目前使用较大粒子片盖在相机前实现 整体思路如下:
1、截取画面Pass

URP中自带了屏幕颜色_CameraOpaqueTexture, 使用SampleSceneColor来获取,但是这个只是不透明层的.如果需要加入透明层物体,需要在不透明渲染之后插入一个CopyColorPass来实现. 这里_CameraTransparentTexture就是包含了透明物体的颜色缓冲.
public class TransparentTextureFeature:ScriptableRendererFeature
    {

      private CustomCopyColorPass _copyColorPass;
      private Material m_SamplingMaterial;
      RenderTargetHandle m_TransparentColor;
      RenderTargetHandle m_CameraColorAttachment;
      public override void Create()
      {
            m_SamplingMaterial = CoreUtils.CreateEngineMaterial(Shader.Find("Hidden/Universal Render Pipeline/Sampling"));
            _copyColorPass = new CustomCopyColorPass(RenderPassEvent.AfterRenderingTransparents, m_SamplingMaterial);
            m_TransparentColor.Init("_CameraTransparentTexture");
            m_CameraColorAttachment.Init("_CameraColorTexture");
      }

      public override void AddRenderPasses(ScriptableRenderer renderer, ref RenderingData renderingData)
      {
            if ( renderingData.cameraData.renderType == CameraRenderType.Base)
            {
                _copyColorPass.Setup(m_CameraColorAttachment.Identifier(), m_TransparentColor, UniversalRenderPipeline.asset.opaqueDownsampling);
                renderer.EnqueuePass(_copyColorPass);
            }

      }

    }2、黑白闪shader

这里计算原理就是, 先计算当前像素在屏幕中的位置,然后采样_CameraTransparentTexture纹理,得到屏幕像素. 然后计算灰度值, 通过step控制黑白阀值. 在用oneminus 得到黑白相反的颜色.
Shader "Effect/Effect_GJ_URP_BlackWhite"
{
    Properties
    {
      _BlackWhiteBlend ("【BlackWhiteBlend】", range (0,1) ) = 0
      _BlackWhitePower ("BlackWhitePower", range(0.1,30) ) = 1
      _BlackWhiteAphaStrength ("BlackWhiteAphaStrength", range (0,5) ) = 5
    }
    SubShader
    {
      Tags
      {
            "IgnoreProjector"="True"
            "Queue"="Transparent"
            "RenderType"="Transparent"
      }
      Pass
      {
            Tags
            {
                "LightMode" = "UniversalForward_BlackWhite"
            }

            ZWrite On
            HLSLPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"
            CBUFFER_START (UnityPerMaterial)
            float _BlackWhiteBlend;
            float _BlackWhitePower;
            float _BlackWhiteAphaStrength;
            CBUFFER_END
            SAMPLER(_CameraTransparentTexture);

            struct VertexInput
            {
                float4 vertex : POSITION;
            };

            struct VertexOutput
            {
                float4 pos : SV_POSITION;
            };

            VertexOutput vert(VertexInput v)
            {
                VertexOutput o = (VertexOutput)0;
                o.pos = TransformObjectToHClip( v.vertex.xyz);
                return o;
            }


            float4 frag(VertexOutput i, float facing : VFACE) : COLOR
            {
                //BlackWhite
                //float4 blackwhite = float4(SampleSceneColor(i.pos.xy / _ScreenParams.xy), 1);
                float4 blackwhite = tex2D(_CameraTransparentTexture, i.pos.xy / _ScreenParams.xy);
                float grey = dot(blackwhite.rgb, float3(0.22, 0.707, 0.071));
                blackwhite.rgb = step(0.5, pow(grey, _BlackWhitePower));
                blackwhite.a = _BlackWhiteAphaStrength;
                return lerp(blackwhite, float4((1 - blackwhite).rgb, blackwhite.a), _BlackWhiteBlend);
            }
            ENDHLSL
      }
    }
}3、效果调试

再UniversalPipelineAsset中设置TransparentTextureFeature抓取颜色缓冲, 然后再beforerenderpostprocess阶段渲染单独该粒子即可(正常渲染通过shadertag排除该粒子的渲染),配置如下


粒子系统控制_BlackWhiteBlend来实现效果,



mypro334 发表于 2022-10-27 11:09

直接用URP中的CopyColorPass一样效果,

DomDomm 发表于 2022-10-27 11:10

大佬可以分享一下工程吗
页: [1]
查看完整版本: Unity 黑白闪效果