Unity基于CommandBuffer的Outline(HDRP)

参考1:https://blog.csdn.net/u012740992/article/details/88795640

这个的例子,前面的小例子是Build-in的,HDRP下没有效果,后面的复杂点的例子就没测试了

参考2:https://forum.unity.com/threads/hdrp-how-to-render-anything-custom.592093/

官方例子:https://docs.unity3d.com/Packages/com.unity.render-pipelines.high-definition@7.1/manual/Custom-Pass.html

本来我学习CommandBuffer的目的就是得到高亮效果(outline)的,结果官方例子就是了。

一个CustomPass,一个Shader,再设置一下Layer,就能得到高亮效果了。

那我点击一个物体高亮的话,就是修改物体的Layer就好了。

不同物体不同高亮颜色,需要设置多个CustomPass了。

闪烁效果呢,是不是定时修改Layer就好了,但是Layer总共就32个,而且必须实现设置,这样的话,其实不同颜色的outline只能设置几种了。

---------------------------------------------------

写了个简单的选择高亮的脚本,现在的outlineColor参数还没用起来。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class OutlineManager : MonoBehaviour
{
    public Color outLineColor;

    public LayerMask outlineLayer;

    Dictionary<GameObject,int> go2layer=new Dictionary<GameObject, int>();

    // Update is called once per frame

    public bool MultiSelect=false;
    public GameObject selectedGO=null;

    public List<GameObject> selectedGOs=new List<GameObject>();

    void Update()
    {
        if(Input.GetKey(KeyCode.LeftControl)||Input.GetKey(KeyCode.RightControl))
        {
            MultiSelect=true;
        }
        else{
            MultiSelect=false;
        }

        if(Input.GetMouseButtonUp(0)){
            Debug.Log("Click");
            //var pos=
            var ray=Camera.main.ScreenPointToRay(Input.mousePosition);
            RaycastHit hitInfo;
            if(Physics.Raycast(ray,out hitInfo)){
                var go=hitInfo.collider.gameObject;
                SelectGO(go,MultiSelect);
            }
            else{
                RecoverGO();
            }
        }
    }

    private void RecoverGO(){
        foreach(GameObject g in selectedGOs){
            if(g!=null){
                g.layer=go2layer[g];
            }
        }
        if(selectedGO!=null){
            selectedGO.layer=go2layer[selectedGO];
        }
    }

    public void SelectGO(GameObject go,bool isMulti){
        if(!go2layer.ContainsKey(go)){
            go2layer.Add(go,go.layer);
            Debug.Log("AddLayer:"+go+"|"+go.layer);
        }

        if(isMulti==false){
            RecoverGO();
            selectedGO=go;
            selectedGOs.Add(go);

            go.layer=outlineLayer.GetLayerNumber();//Set Outline
        }
        else{
            if(selectedGOs.Contains(go)){
                selectedGOs.Remove(go);
                go.layer=go2layer[go];//Remove Outline
                Debug.Log("GetLayer:"+go+"|"+go.layer);
            }
            else{
                selectedGOs.Add(go);
                go.layer=outlineLayer.GetLayerNumber();//Set Outline
            }
        }
    }
}

---------------------------------------------------------------------------

扩展一下,不同的物体可以设置不同的颜色,只要在物体上挂设置颜色的脚本

public class OutlineInfo : MonoBehaviour
{
    [ColorUsage(false,true)]
    public Color color;
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Rendering.HighDefinition;

public class OutlineManager : MonoBehaviour
{
    [ColorUsage(false,true)]
    public Color outLineColor;

    public LayerMask outlineLayer;

    Dictionary<GameObject,int> go2layer=new Dictionary<GameObject, int>();

    // Update is called once per frame

    public bool MultiSelect=false;
    public GameObject selectedGO=null;

    public List<GameObject> selectedGOs=new List<GameObject>();


    public OutlinePass CurrentPass;
    public List<OutlinePass> outlinePasses;

    Dictionary<Color,int> color2layer=new Dictionary<Color, int>();

    public CustomPassVolume volume;

    public int MaxPassCount=6;

    public int CurrentPassId=1;

    void Start(){
        InitDefaultPass();
    }

    void Update()
    {
        if(Input.GetKey(KeyCode.LeftControl)||Input.GetKey(KeyCode.RightControl))
        {
            MultiSelect=true;
        }
        else{
            MultiSelect=false;
        }

        if(Input.GetMouseButtonUp(0)){
            Debug.Log("Click");
            //var pos=
            var ray=Camera.main.ScreenPointToRay(Input.mousePosition);
            RaycastHit hitInfo;
            if(Physics.Raycast(ray,out hitInfo)){
                var go=hitInfo.collider.gameObject;
                SelectGO(go,MultiSelect);
            }
            else{
                RecoverGO();
            }
        }
    }

    private void RecoverGO(){
        foreach(GameObject g in selectedGOs){
            if(g!=null){
                g.layer=go2layer[g];
            }
        }
        selectedGOs.Clear();
        if(selectedGO!=null){
            selectedGO.layer=go2layer[selectedGO];
            selectedGO=null;
        }
    }

    private int CreateOutlinePass(Color color,LayerMask layerMask){
        OutlinePass outlinePass=new OutlinePass();
        outlinePass.outlineColor=color;
        outlinePass.outlineLayer=layerMask;
        volume.customPasses.Add(outlinePass);

        int newLayer=layerMask.GetLayerNumber();//Set Outline
        color2layer.Add(color,newLayer);
        CurrentPass=outlinePass;
        return newLayer;
    }

    private void InitDefaultPass(){
        if(volume==null){
            volume=gameObject.GetComponent<CustomPassVolume>();
        }
        if(volume==null){
            volume=gameObject.AddComponent<CustomPassVolume>();
        }
        outlineLayer=LayerMask.GetMask("Outline"+CurrentPassId);
        CreateOutlinePass(outLineColor,outlineLayer);
        CurrentPassId++;
    }

    private void SetOutline(GameObject go,bool isMulti){
        OutlineInfo info=go.GetComponent<OutlineInfo>();
        if(info!=null){
            if(isMulti){
                int newLayer=go.layer;
                if(color2layer.ContainsKey(info.color))
                {
                    newLayer=color2layer[info.color];
                }
                else{

                    if(CurrentPassId>MaxPassCount){
                        CurrentPassId=1;

                        newLayer=outlineLayer.GetLayerNumber();//多了,
                    }
                    else{
                        newLayer=CreateOutlinePass(info.color,LayerMask.GetMask("Outline"+CurrentPassId));
                        CurrentPassId++;
                    }
                }
                go.layer=newLayer;
            }
            else{
                CurrentPass.outlineColor=info.color;
                go.layer=outlineLayer.GetLayerNumber();//Set Outline
            }
        }
        else{
            CurrentPass.outlineColor=outLineColor;
            go.layer=outlineLayer.GetLayerNumber();//Set Outline
        }
    }

    public void SelectGO(GameObject go,bool isMulti){
        if(!go2layer.ContainsKey(go)){
            go2layer.Add(go,go.layer);
            Debug.Log("AddLayer:"+go+"|"+go.layer);
        }

        if(isMulti==false){
            RecoverGO();
            selectedGO=go;
            selectedGOs.Add(go);
            SetOutline(go,isMulti);
        }
        else{
            if(selectedGOs.Contains(go)){
                selectedGOs.Remove(go);
                go.layer=go2layer[go];//Remove Outline
                Debug.Log("GetLayer:"+go+"|"+go.layer);
            }
            else{
                selectedGOs.Add(go);
                SetOutline(go,isMulti);
            }
        }
    }
}

--------------------------------------------------------------------------------

现在还差点,1.线条粗细 2.物体部分的颜色。

--------------------------------------------------------------------------------

Before Pre Refraction/Before Transparent/Before Post Process

After Post Process

---------------------------------------------------------------------------------

加个透明的板子

Before Transparent :透明板子会挡住Outline,透明度改为255时整个就看不到后面的Outline了,非透明的则不会,而且透明板子前面加个非透明的,反而会让Outline透过来。

Before Post Process:

After Post Process:

--------------------------------------------------------------------------------

具体到项目中

Before Pre Refraction/Before Transparent:

Before Post Process

Threshold:2(Editor)

Threshold:1(Editor)

Threshold:0(Editor)

但是Game窗口没有Outline效果,发现不同时间创建的Pass下过不同,InitDefaultPass的第一个Outline1有效果,

后续动态添加的Outline2、Outline3则直接没有效果。无论怎么设置颜色。

发现是摄像头的CullMask被设置了,正好设置的到Outline1。

 

已标记关键词 清除标记
©️2020 CSDN 皮肤主题: 大白 设计师:CSDN官方博客 返回首页