This is one of the main pain points I have with unity. Proper texture filtering is so 90’s, I still don’t understand why there is no support for it.
Anyways, this is how we solved it: It goes along the lines of what bgolus mentioned and works quite ok for us. Anisotropy is the tricky part here, and making it blend nicely. (the code is a bit of a mess, haven’t had the time yet to refactor everything nicely)
float4 crispMipMapTex2D(sampler2D tex, float2 uv, float4 texelSize)
{
float2 dx = ddx(uv);
float2 dy = ddy(uv);
// approximate texel size in texture
// this is not correct since the derivatives are float2
//float lod = max(dx * texelSize.zw.x, dy * texelSize.zw.x);
float lod = sqrt(pow(dx * texelSize.zw.x, 2) + pow(dy * texelSize.zw.x, 2));
float t = mapAndClamp(0.5, 1, 0, 1, lod);
return lerp(pointSampleTex2D(tex, uv, texelSize), tex2D(tex, uv, dx, dy), t);
//return (lod > 1) ? (tex2D(tex, uv, dx, dy)) : pointSampleTex2D(tex, uv, texelSize);
}
float4 pointSampleTex2D(sampler2D tex, float2 uv, float4 st)
{
float2 snappedUV = ((float2)((int2)(uv * st.zw + float2(1, 1))) - float2(0.5, 0.5)) * st.xy;
return tex2Dlod(tex, float4(snappedUV.x, snappedUV.y, 0, 0));
}
float map(float a, float b, float r, float s, float value)
{
if (a == b)
{
if (value <= a)
{
return r;
}
else
{
return s;
}
}
float ratio = (value - a) / (b - a);
return r + (s - r) * ratio;
}
float mapAndClamp(float a, float b, float s, float t, float value)
{
return clamp(map(a, b, s, t, value), s, t);
}