Testing our game and leaving the mobile for some minutes playing we found out that many of the texture looks pixelated, bad tilling, blurry and the phone was kinda hot. (the texture quality get worse and worse with time)
Looking for a solution and moving some code i found out that using Half precision was the problem,
before all my vars were HALF and now i change like 5% of them to FLOAT and the game is running faster, no more pixelated textures, bad tiling or melting phone (still get hot but it take a lot longer).
UV coord and deformations the UV where the ones i change back to FLOAT.
The device i test was nexus 5. those problems never show up in faster devices anyway.
FYI: some GPUs that are being used in Android devices don’t provide support for float in fragment shaders at all, only half and fixed (it’s not a requirement to have float in fragment shaders in OpenGL ES 2).
Hm, very interesting. Just to be clear on that. If I want to target devices from lets say nexus 5 and up, does it make sense to avoid halfs all together? I think I read in the documentation that this is the case for fixed precision values, but I’m not completely sure.
And what about e.g. color values in the frag shader. I think almost all shaders I write and saw from others use a fixed4 as return value, so whats the best practice here?
If you’re targeting only devices that have OpenGL ES 3 support, you don’t need to worry about lack of high precision in fragment shaders, it’s a requirement in the standard.
In general it’s best to use the lowest precision possible, since it might positively affect the battery life, frame rate and device temperature. For the colors that end up on the screen, for example, it’s enough to use fixed precision. For texture UVs it’s usually enough to have half precision.
Thanks for your reply! That is the rule of thumb I was using for writing my shaders, but then I’m wondering why @resetme had a performance boost when he changed the values to floats again. What is the explanation for that?
@Johannski it’s very hard to say, what exactly caused this, and whether it’s specific to the combination of device/driver that was under test or not. It could, for example, have been caused by the shader doing conversions from one precision to another needlessly, or the hardware trying to emulate something it doesn’t support. But it’s all guesswork
For older mobiles, beware of conversion costs. You’re probably fine using half or float for vertex but these are bad in frag, fixed is best there.
But the problems come when converting between float/half to fixed. While float and half are probably the same on some of them, fixed is not, and there’s a cost on older hardware.
That would be nice, but it seems that when using GL ES 3.0, Unity overrides a lot of the precision choices and does whatever it wants. For example, textures in frag are always lowp, no matter what you write in CG.
Also, by default it does super weird casts from one precision to another for lightmaps.
Notice how the lightmap is originally taken as mediump, then is cast to lowp, then is cast to mediump, then is combined with the MainTex in lowp. I don’t think there’s any valid reason for any of those casts.
I did more test with older phones and the problem is solved, had all the phones playing for 10 minutes.
Nexus 5, samsung s6, many old sony xperia.
The problem was inside the uv rotation and polar coordinates uv effect, after some seconds or minutes the texture quality start pixelating and the tiling become visible, the phone get slower and hotter.
For example one 128x128 texture that have circular points after 1 minute it start getting pixelated that the circular points transform to rectangles, lol.
changing the half to float fixed the issues, maybe is related with atan2 and length.
Do all these phones use a Mali GPU? It sounds like the texture coordinates themselves are far outside the 0…1 range, and for some reason, if it goes too far out, Mali GPUs will start pixelating stuff.
I once got this issue with a water distortion shader on my really old Mali-based tablet, the solution is to clam or wrap the coordinates into the 0…1 range. (Being as you’re using atan2, you’ll want to wrap around to avoid snapping)
As for the overheating/slowdown, no idea what’s going on there.
FYI you should be doing that for PC too. Even with a full 32 bit float, if you’re panning the UVs over time it will eventually start to lose precision and pixelate. Technically even with the wrap you’re still going to run into precision issues eventually as the panning motion will start to stutter, and the UV might start to shift, but the wrap should prevent it from pixelating the texture.
Sorry to bump up.
Is the proper way of doing the “Wrap” by using “frac”??
like this:
float2 _TimeSpeed = (float2((_Uspeed* _Time.g),(_Time.g*_vspeed)));
float2 _FlowUV1= (i.uv0+ frac(_TimeSpeed*_FlowSpeed));
fixed4 _Flowmap_var = tex2D(_Flowmap,TRANSFORM_TEX(_FlowUV1, _Flowmap));
float2 _FlowUV2= (i.uv0+ frac(_TimeSpeed+float2(_Flowmap_var.r,_Flowmap_var.r)*_FlowIntensity));
fixed4 _Maintex_var = tex2D(_Maintex,TRANSFORM_TEX(_FlowUV2, _Maintex));