2DのUIなどは常に画面に表示されますが、3Dオブジェクトの場合は奥行きなどによって表示されないケースが出てきます。
しかし、VRゲームなどでは3DでUIを作る必要があり、なにかの後ろに隠れてしまうのは問題になるケースがあるかと思います。
そんなときに使えるシェーダ。記述量はとても少ないです。
SubShader {
Tags { "RenderType"="Opaque" "Queue"="Geometry+5" }
ZTest Always
}
Tags
に "Queue"="Geometry+5"
を追加します。
さらに ZTest Always
も追加します。
こうすることで、少なくとも通常のGeometryよりは常に前面に描かれるようになります。
解説
レンダリングのソートを変更する
"Queue"="Geometry+5"
とすることで、通常のモデル(Geometry)よりも +5
だけあとにレンダリングされるようになります。
こうすることで、常にモデルよりも最後にレンダリングされるようになります。
ZTestを常に合格させる
次に、ZTest Always
を指定します。
こうすることで、奥行きがどうであれ必ずレンダリングされることになります。
結果として、レンダリングのソートをできるだけ後ろにしつつ、常にレンダリングを行うことで通常のモデルよりも常に前面にオブジェクトがレンダリングされるというわけです。
透明オブジェクトの場合
ちなみに透明オブジェクトを上記の方法で実装するとうまく動きません。
いくつかパラメータを追加・変更する必要があります。
Transparentを指定する
以下のように、RenderType
などを Transparent
に変更する必要があります。
Tags { "RenderType"="Transparent" "Queue"="Transparent+2" }
また、#pragma
に alpha
を追加する必要があります。
#pragma surface surf Standard fullforwardshadows alpha
alpha
の手前の記述はデフォルトのままです。(つまり最後に alpha
を追記します)
コード
最後に、最終的なコードを載せておきます。
Shader "Custom/UIShader" {
Properties {
_Color ("Color", Color) = (1,1,1,1)
_MainTex ("Albedo (RGB)", 2D) = "white" {}
_Glossiness ("Smoothness", Range(0,1)) = 0.5
_Metallic ("Metallic", Range(0,1)) = 0.0
}
SubShader {
Tags { "RenderType"="Transparent" "Queue"="Transparent+2" }
LOD 200
ZTest Always
CGPROGRAM
// Physically based Standard lighting model, and enable shadows on all light types
#pragma surface surf Standard fullforwardshadows alpha
// Use shader model 3.0 target, to get nicer looking lighting
#pragma target 3.0
sampler2D _MainTex;
struct Input {
float2 uv_MainTex;
};
half _Glossiness;
half _Metallic;
fixed4 _Color;
void surf (Input IN, inout SurfaceOutputStandard o) {
// Albedo comes from a texture tinted by color
fixed4 c = tex2D (_MainTex, IN.uv_MainTex) * _Color;
o.Albedo = c.rgb;
// Metallic and smoothness come from slider variables
o.Metallic = _Metallic;
o.Smoothness = _Glossiness;
o.Alpha = c.a;
}
ENDCG
}
FallBack "Diffuse"
}