Unity功能記錄(十一) ------ 實現3D模型遮罩效果
阿新 • • 發佈:2018-12-25
事情是這樣的,之前呢,用Sprite Mask做了遮罩效果,但是,老闆想要月球來回轉動,就不能用圖片轉動,只能用UI了,那相應的,遮罩怎麼辦呢,老闆也是神人,給我指了一條新的思路,就是將3D遮罩轉化成2D遮罩,不過放在手機上卡成狗,幸好群裡大佬ific指點了一下遮罩的shader,效果不錯,在此將兩種方法都分享出來~
一.使用RenderTexture渲染成Sprite,然後使用Sprite Mask進行遮罩
1.為要遮罩的模型單獨建立layer,新建一個攝像機只看該層
2.將攝像機的畫面渲染到sprite上
public class MoonMask : MonoBehaviour { public Camera ModelMaskCamera; public Texture2D CamTexture; public RenderTexture renderTexture; public SpriteRenderer spriteRenderer; // Use this for initialization void Start () { //注意這裡的第三個引數 renderTexture = new RenderTexture(Screen.width, Screen.height, 24, RenderTextureFormat.ARGB32); ModelMaskCamera.targetTexture = renderTexture; ModelMaskCamera.Render(); RenderTexture.active = renderTexture; spriteRenderer.transform.localPosition = new Vector3(-(float)Screen.width / 100, -(float)Screen.height/100,0); CamTexture = new Texture2D(Screen.width, Screen.height, TextureFormat.RGB24, false); } // Update is called once per frame void Update () { getScreenTexture(); } void getScreenTexture() { Rect r = new Rect(0, 0, Screen.width, Screen.height); RenderTexture.active = renderTexture; CamTexture.ReadPixels(r, 0, 0); CamTexture.Apply(); Sprite sprite = Sprite.Create(CamTexture, new Rect(0, 0, Screen.width, Screen.height), Vector2.zero); spriteRenderer.sprite = sprite; } }
這裡踩了挺多坑,因為攝像機看到的只有模型時會有殘影出現,所以要在後面加一層背景,當時我不能加UI,因為加UI會覆蓋在模型上面,透明度又不能設定為0,設定為0了殘影還是會出現,不設定為0會影響模型顯示效果
好吧,加了Sprite,使它的Z軸在模型後面,擴大攝像機的far值, 使其能看到該Sprite,但是神奇的是還是覆蓋在模型上面,偶然發現將RenderTexture的Depth Buffer賦值為At least 16 bit depth或者At least 24 bit depth的時候能夠讓sprite顯示在模型後面,雖然不知道什麼原理~
上面程式碼中的第三個引數就是設定這個的 : 傳16是At least 16 bit depth,傳24是At least 24 bit depth
官方API : https://docs.unity3d.com/ScriptReference/RenderTexture-depth.html
3.遮罩實現
unity內建了sprite的遮罩 :
被遮罩物體上:
遮罩的原理 : 顯示遮罩圖片不透明部分與被遮罩圖片的不透明部分相交部分
二.使用shader中的ColorMask屬性進行遮罩
1.建立遮罩模型(比如我的需求是一塊麵板中間挖個洞)
2.新建一個shader,將下面程式碼賦值過去
Shader "DepthMask" { SubShader{ // Render the mask after regular geometry, but before masked geometry and // transparent things. Tags {"Queue" = "Geometry-10" } // Turn off lighting, because it's expensive and the thing is supposed to be // invisible anyway. Lighting Off // Draw into the depth buffer in the usual way. This is probably the default, // but it doesn't hurt to be explicit. ZTest LEqual ZWrite On // Don't draw anything into the RGBA channels. This is an undocumented // argument to ColorMask which lets us avoid writing to anything except // the depth buffer. ColorMask 0 // Do nothing specific in the pass: Pass {} } }