以前Unityのビルトインのディザ抜き用テクスチャを取得しました。
今回はこれを使って実際にディザ抜きしてみます。
Unity2017.4.1
ディザ抜き?
ディザ抜き自体は他の記事で説明しているので下記を参照してください。
シェーダ(_DitherMaskLOD2D版)
まずはシェーダを書いてみます。
Shader "Sample" { Properties { _Alpha ("Alpha", Range(0.0, 1.0)) = 1.0 } SubShader { Tags { "RenderType"="Opaque" } Pass { CGPROGRAM #pragma vertex vert #pragma fragment frag #pragma target 3.0 #include "UnityCG.cginc" struct appdata { float4 vertex : POSITION; }; struct v2f { }; sampler2D _DitherMaskLOD2D; half _Alpha; v2f vert (appdata v, out float4 vertex : SV_POSITION) { v2f o; vertex = UnityObjectToClipPos(v.vertex); return o; } fixed4 frag (v2f i, UNITY_VPOS_TYPE vpos : VPOS) : SV_Target { // 4px x 4pxのブロック毎にテクスチャをマッピングする vpos *= 0.25; // ディザテクスチャのheightは4*16pxなので小数部分を16で割る(0.0625 = 1/16) // これでyは0 ~ 1/16の値を取る vpos.y = frac(vpos.y) * 0.0625; // Alphaに応じてyにオフセットを加える // Alphaが1のときはyが0.9375~1の値を取るように(0.9375 = 1 - 1/16) vpos.y += _Alpha * 0.9375; // ディザの値はAチャンネルに格納されている clip(tex2D(_DitherMaskLOD2D, vpos).a - 0.5); return 1; } ENDCG } } }
少し複雑なのでコメントを少し細かく書いておきました。
DitherMaskLOD2Dがビルトインシェーダ内で使われている様子はUnity.cgincで見ることができます。
また、それを見るとAlphaに0.9375を掛けていませんが、掛けないとうまくいきません。
(Unity.cgincのほうは事前計算されている?)
_DitherMaskLOD2Dがどんなテクスチャかを見たい方は下記の記事を参照してください。
シェーダ(_DitherMaskLOD版)
_DitherMaskLODという3Dテクスチャを使っている部分もあったので、
こちらを使ったソースコードも載せておきます。
Shader "Sample" { Properties { _Alpha ("Alpha", Range(0.0, 1.0)) = 1.0 } SubShader { Tags { "RenderType"="Opaque" } Pass { CGPROGRAM #pragma vertex vert #pragma fragment frag #pragma target 3.0 #include "UnityCG.cginc" struct appdata { float4 vertex : POSITION; }; struct v2f { }; sampler3D _DitherMaskLOD; half _Alpha; v2f vert (appdata v, out float4 vertex : SV_POSITION) { v2f o; vertex = UnityObjectToClipPos(v.vertex); return o; } fixed4 frag (v2f i, UNITY_VPOS_TYPE vpos : VPOS) : SV_Target { // 4px x 4pxのブロック毎にテクスチャをマッピングする vpos *= 0.25; // ディザ用テクスチャは4px x 4px x 16px clip(tex3D(_DitherMaskLOD, float3(vpos.xy, _Alpha * 0.9375)).a - 0.5); return 1; } ENDCG } } }
こっちのほうが楽かも?
ちなみにUnityStandardShadow.cginc内で使われています。
結果
上記のシェーダを適当なCubeに適用してみます。
正常にディザ抜きができました。