I have a specific texture that needs to be both point filtered and bilinear filtered in two different texture reads. It’s also massive (4k-sq, on mobile) and must be RGBA32 uncompressed.
The only way currently to do this is to have two complete copies of the texture loaded and set different filter modes on the texture, which is a bit of a disaster
Is there a way to override filter mode on the sampler state in a Shaderlab shader? For bonus points, if I’m targeting a fairly wide range of ios/android hardware (but it has to be capable of rendering Unity’s standard shader with occlusion and normal maps, so not totally ghetto hardware) is this likely to work in practice even if Unity supports it?
You can define the sampling state directly in the shader, but I think only in DX11, not mobile. However you can just do some basic UV manipulation in the shader to get the same results as point sampling.
This is true - I probably should have said “on iOS.” On android there’s a QualitySettings adjustment done during a boot scene to throw the top mipmap away, so they’re only 2k-square. Occasionally I consider doing a glGet(MAX_TEXTURE_SIZE) and letting some android devices have 4k-sq textures, but I don’t know if I trust what the driver reports anyway.
Do you know how well tex2dLoD is supported on Android hardware. Like I said, it has to be capable of rendering full screens of standard shader, so not complete garbage devices, but I still barely trust droids to support rendertextures in 2017, nevermind any feature that became mainstream after 1998…
If it’s OpenGL ES 3.0 capable hardware, it has support. Otherwise it’s not great as the ES 2.0 spec only requires tex2Dlod in the vertex shader. If the texture doesn’t have mip-maps then you can obviously skip it all together and just use tex2D. However Unity’s fallback has been to use tex2Dbias which is supported on all hardware in the fragment shader.
float2 pointUV = (floor(uv * _MyTexture_TexelSize.zw) + 0.5) * _MyTexture_TexelSize.xy; #if defined(SHADER_API_GLES) // is compilation target gles 2.0
fixed4 point = tex2Dbias(_MyTexture, float4(pointUV, 0, -11)); // bias for keeping largest mip for a 2048x2048 texture #else
fixed4 point = tex2Dlod(_MyTexture, float4(pointUV, 0, 0)); #endif
You could just use bias on all platforms, Unity does for light cookies. Also note that doing this kind of in-fragment shader UV manipulation will significantly slow down the shader on those old ES 2.0 platforms … as will the fact it’s an uncompressed 2048 texture, but presumably you’re not too worried about framerate, just compatibility.