シェーダーはFragmentシェーダーでテクスチャをサンプルするのが普通ですが,GPUパーティクルなどではVertexシェーダーでもテクスチャをサンプルします.
Vertexシェーダーでテクスチャをサンプルする場合でも,テクスチャの設定でFilterをBilinearに設定しておけば tex2Dlod() などでサンプルするときに線形補間されます.
...と思っていたのですが,モバイル環境では強制的にPointサンプルになる場合があるようです.SampleLevel() も試してみましたがダメでした.
仕方ないのでマニュアルでBilinearサンプルにします.
Sampler sampler_point_clamp;
float4 BilinearSample( Texture2D<float4> tex, float4 texelSize, float2 uv )
{
float4 scaledUv;
scaledUv.xy = uv * texelSize.zw - 0.5;
scaledUv.zw = scaledUv.xy + 1.0;
scaledUv = clamp( scaledUv, 0, texelSize.zwzw - 1.0 );
float2 ratio = frac( scaledUv.xy );
float4 sampleUv = ( floor( scaledUv ) + 0.5 ) * texelSize.xyxy;
float4 c00 = tex.SampleLevel( sampler_point_clamp, sampleUv.xy, 0 );
float4 c10 = tex.SampleLevel( sampler_point_clamp, sampleUv.zy, 0 );
float4 c01 = tex.SampleLevel( sampler_point_clamp, sampleUv.xw, 0 );
float4 c11 = tex.SampleLevel( sampler_point_clamp, sampleUv.zw, 0 );
return lerp(
lerp( c00, c10, ratio.x ),
lerp( c01, c11, ratio.x ),
ratio.y
);
}
#define BILINEAR_SAMPLE( tex, uv ) BilinearSample( tex, tex##_TexelSize, uv )
...
Texture2D<float4> _MainTex;
float4 _MainTex_TexelSize;
v2f vert( appdata v )
{
...
float4 data = BILINEAR_SAMPLE( _MainTex, v.uv.xy );
...
}
こんな感じでしょうか.サンプルの負荷が増えそうですが,仕方がないですね.
VertexステージでBilinearサンプルしなくて済むように設計するのがベストなんだと思います.