Unityのビルトインシェーダをみていると、どうやら内部的にディザ抜き用のテクスチャをもっていることがわかります。
これを使えたら便利そうなのでどんなテクスチャなのか見てみます。
ディザ抜き用テクスチャを描画するシェーダ
ディザ抜き用テクスチャは_DitherMaskLOD2Dという名前のようです。
まずはこれをサンプリングするシェーダを書きます。
アルファ値に値が格納されているようなので、わかりやすいようにRGBに出力しています。
Shader "UnityDither" { SubShader { Tags { "RenderType"="Opaque" } Pass { CGPROGRAM #pragma vertex vert #pragma fragment frag #include "UnityCG.cginc" struct appdata { float4 vertex : POSITION; float2 uv : TEXCOORD0; }; struct v2f { float2 uv : TEXCOORD0; float4 vertex : SV_POSITION; }; sampler2D _DitherMaskLOD2D; v2f vert (appdata v) { v2f o; o.vertex = UnityObjectToClipPos(v.vertex); o.uv = v.uv; return o; } fixed4 frag (v2f i) : SV_Target { float value = tex2D(_DitherMaskLOD2D, i.uv).a; return half4(value, value, value, 1); } ENDCG } } }
png化
次にこれをスクリプトでpngに変換します。
ビルトインシェーダをみる限りディザテクスチャのサイズは横4px、縦4*16pxっぽいのでこのサイズのテクスチャに格納します。
#if UNITY_EDITOR using UnityEngine; using UnityEditor; public class DitherCreator { [MenuItem("Assets/Create Dither Texture")] private static void CreateDitherTexture() { // RenderTextureにUnityのDitherテクスチャをレンダリングする var rt = RenderTexture.GetTemporary(4, 4 * 16); Graphics.Blit(rt, rt, new Material(Shader.Find("UnityDither"))); // RenderTextureからテクスチャを作る var currentRT = RenderTexture.active; RenderTexture.active = rt; var texture = new Texture2D(rt.width, rt.height); texture.ReadPixels(new Rect(0, 0, rt.width, rt.height), 0, 0); texture.Apply(); // テクスチャを保存する var bytes = texture.EncodeToPNG(); System.IO.File.WriteAllBytes("Assets/dither_tex.png", bytes); AssetDatabase.Refresh(); // 元に戻す RenderTexture.active = currentRT; RenderTexture.ReleaseTemporary(rt); } } #endif
とりあえずAssets直下に適当に保存してます。
Projectビューの右クリックからCreate Dither Textureを選択するとdither_texという名前のテクスチャが作成されます。
結果
このようなテクスチャが得られます。
結果は正しそうですが、あまりに小さいので拡大してみます。
これのV座標を変えて透過度に応じた4pxを取得してディザ抜きするわけです。
実際にディザ抜きに使ってみる記事は別で書こうと思います。