Unity CommandBuffer实现毛玻璃特效

Unity毛玻璃特效

特效可以用于一般物体,也可以应用于UI。一直想在UI中实现这么个效果,现在终于实现了。

效果如下:

应用于场景中的屏物体毛玻璃效果物体
应用于UI

毛玻璃效果UI
调节Shader的参数,可以调整背景模糊和扭曲的程度,也可以调整毛玻璃的颜色,还可也换法线和纹理贴图。

原理

用到是CommandBuffer,其实就是拿官方的案例过来稍微一改就行了。关键是CommandBuffer啊,Custom Pass啊,这些东东,一直都是一知半解的,看文档吧又TM全是鸟语,硬着头皮看,到现在还是一知半解,呵呵。算球,能实现就行啊。

using UnityEngine;
using UnityEngine.Rendering;

[ExecuteInEditMode]
public class CommandBufferBlurRefraction : MonoBehaviour
{
    
    
    [SerializeField] private Camera cameraMain;
    [SerializeField] private Shader blurShader;
    private Material _material = null;
    private CommandBuffer _commandBuffer = null;

    private void Cleanup()
    {
    
    
        if (!_material)
        {
    
    
            cameraMain.RemoveCommandBuffer(CameraEvent.AfterSkybox, _commandBuffer);
            DestroyImmediate(_material);
            _material = null;
        }
    }

    public void OnDisable()
    {
    
    
        Cleanup();
    }

    private readonly int screenCopyID = Shader.PropertyToID("_ScreenCopyTexture");
    private readonly int blurredID = Shader.PropertyToID("_Temp1");
    private readonly int blurredID2 = Shader.PropertyToID("_Temp2");

    public void OnEnable()
    {
    
    
        if (!cameraMain)
            cameraMain = Camera.main;
        if (cameraMain == null)
            return;
        
        _material ??= new Material(blurShader) {
    
    hideFlags = HideFlags.HideAndDontSave};
        _commandBuffer ??= new CommandBuffer() {
    
    name = "Grab screen and blur"};

        // copy screen into temporary RT
        _commandBuffer.GetTemporaryRT(screenCopyID, -1, -1, 0, FilterMode.Bilinear);
        _commandBuffer.Blit(BuiltinRenderTextureType.CurrentActive, screenCopyID);

        // get two smaller RTs
        _commandBuffer.GetTemporaryRT(blurredID, -2, -2, 0, FilterMode.Bilinear);
        _commandBuffer.GetTemporaryRT(blurredID2, -2, -2, 0, FilterMode.Bilinear);

        // downsample screen copy into smaller RT, release screen RT
        _commandBuffer.Blit(screenCopyID, blurredID);
        _commandBuffer.ReleaseTemporaryRT(screenCopyID);

        // horizontal blur
        _commandBuffer.SetGlobalVector("offsets", new Vector4(2.0f / Screen.width, 0, 0, 0));
        _commandBuffer.Blit(blurredID, blurredID2, _material);
        // vertical blur
        _commandBuffer.SetGlobalVector("offsets", new Vector4(0, 2.0f / Screen.height, 0, 0));
        _commandBuffer.Blit(blurredID2, blurredID, _material);
        // horizontal blur
        _commandBuffer.SetGlobalVector("offsets", new Vector4(4.0f / Screen.width, 0, 0, 0));
        _commandBuffer.Blit(blurredID, blurredID2, _material);
        // vertical blur
        _commandBuffer.SetGlobalVector("offsets", new Vector4(0, 4.0f / Screen.height, 0, 0));
        _commandBuffer.Blit(blurredID2, blurredID, _material);

        _commandBuffer.SetGlobalTexture("_GrabBlurTexture", blurredID);

        cameraMain.AddCommandBuffer(CameraEvent.AfterSkybox, _commandBuffer);
    }
}

其实,这大体的原理就是,在摄像机上加一个CommandBuffer,相当于在渲染过程中添加了额外的处理指令,就是,在渲染这个毛玻璃物体之前,先把已经渲染好的屏幕拿过来模糊一下,扭曲一下,然后以屏幕空间作为UV再贴到这个物体上。
扭曲和模糊屏幕的Shader:
Shader代码
毛玻璃Shader:
Shader代码

源码下载:

点击下载源码

猜你喜欢

转载自blog.csdn.net/sdhexu/article/details/127142988