Unityで、GameObjectの一部にマスクをかけるには、DepthMaskを使う。
参考:Unity - Manual: ShaderLab syntax: SubShader Tags
1. Maskとなるオブジェクトの設定
1-1. 新規シェーダを作成。Maskシェーダのスクリプト(下記)を記述する。
Maskオブジェクトの順番を、レギュラー・ジオメトリとマスクをかけるジオメトリの間に設定している。
Shader "Masked/Mask" { SubShader { // Render the mask after regular geometry, but before masked geometry and // transparent things. Tags {"Queue" = "Geometry+10" } // Don't draw in the RGBA channels; just the depth buffer ColorMask 0 ZWrite On // Do nothing specific in the pass: Pass {} } }
肝は、SubShaderの中の、
Tags {"Queue" = "Geometry+10" }
の部分。Queueはレンダリングの順番を指定するタグ。デフォルトの設定値は次の通り。数字が小さいものから先にレンダリングされる。
Queue | Value |
---|---|
Background | 1000 |
Geometry | 2000 |
AlphaTest | 2450 |
Transparent | 3000 |
Overlay | 4000 |
Geometryは一般のオブジェクトを指す。上のスクリプトでは、Geometryのデフォルト値に10を加えた値、すなわち2010をQueueタグに設定していることになる。
1-2. 新しいMaterialを作り、Maskシェーダをアタッチする。
1-3. このMaterialを、Maskとして使用したいオブジェクトにアタッチ。
2.Maskをかけるオブジェクトの設定
2-1. Maskをかけたいオブジェクトに、任意のMaterialを設定する。
2-2. 同オブジェクトに、次のスクリプトをアタッチ。
/* SetRenderQueue.cs Sets the RenderQueue of an object's materials on Awake. This will instance the materials, so the script won't interfere with other renderers that reference the same materials. */ using UnityEngine; [AddComponentMenu("Rendering/SetRenderQueue")] public class SetRenderQueue : MonoBehaviour { [SerializeField] protected int[] m_queues = new int[]{3000}; protected void Awake() { Material[] materials = renderer.materials; for (int i = 0; i < materials.Length && i < m_queues.Length; ++i) { materials[i].renderQueue = m_queues[i]; } } }
[SerializeField]は、public変数ではないが、Inspectorウィンドウから値を設定できるようにする修飾子。
このスクリプトは、MaskをかけたいオブジェクトのRenderQueueを3000にしている。これによって、Regular Geometry(2000)→Mask(2010)→Maskをかけたいオブジェクト(3000)の順番にレンダリングされ、MaskをかけたいオブジェクトのみにMaskがかかることになる。
要は、RenderQueueの値を相対的に変えることで、レンダリングの順番を変更し、Maskをかけることになる。