参考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/
本来我学习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。