-
-
Notifications
You must be signed in to change notification settings - Fork 19.2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Offsetting UV in the fragment shader is stretching textures on Android GLES2 #32813
Comments
At a first guess, this is something which isn't immediately obvious about a lot of GLES 2 devices - I have found on a lot of them you shouldn't touch the texture coords in a fragment shader. It is actually to do with precision. I wrote a bit about it here:
If you work it out that gives you a maximum precision for texture coordinates of 1024 different positions, which is not even enough to give sub-texel accuracy. So what is going on? What I believe happens is that on these devices they follow a different optimized high precision path, which can offer good texture resolution, until you touch the texture coords in the fragment shader. Once you do that it has to revert to the fragment precision, which may only be 10 bit. And once this happens you get something that looks like point filtering, and all kinds of crazy stuff. So the upshot is if you want to make your shaders compatible on the most GLES2 devices possible, don't touch the texture coords (or perhaps even some other calculations) in the fragment shader. If this is indeed the problem here, then it is not strictly speaking a godot bug, more a 'feature' of GLES2 devices. Unfortunately one of the big problems of GLES hardware is that it is like the wild west, with different combinations of hardware caps, hopefully with vulkan that situation might get better (what we would prefer as developers are several tiers of hardware caps, rather than random combinations). What can we do godot side to help deal with this?
I don't know whether this is something that other devs would consider a good idea, or instead rely on users downloading a second diagnostic app to check caps, or online hardware databases (I don't know if https://opengles.gpuinfo.org currently shows precision caps).
|
Related: GodotVR/godot_oculus_mobile#60 |
Assigning a few GLES2 and shader experts :) See the analysis in GodotVR/godot_oculus_mobile#60, it does seem to be the same bug. |
For the reference, I can reproduce the issue with the attached MRP on a Xiaomi Pocophone F1 (Adreno 630) running GLES2. It's a GLES3 and Vulkan-capable device, so I don't think the hardware is to blame here, or at least it's likely that all Android OpenGL ES 2.0 drivers would be affected. |
I can confirm that accessing shader_type canvas_item;
uniform bool enabled = true;
void vertex() {
if (enabled) {
UV.x += TIME;
}
}
void fragment() {
COLOR = texture(TEXTURE, UV);
} (modified shader code from MRP) The above works fine on my phone. |
I investigated the issue in GodotVR/godot_oculus_mobile#60; what I found there was that on GLES2 the final fragment shader has at the beginning:
but godot/drivers/gles2/shader_gles2.cpp Line 180 in ac38f07
So all variable declarations and computations without precision modifier default to
would make the computation in high precision and fix the issue on devices where highp is float32. So one potential solution could be to have an optional "enable high precision" option in visual shader that would declare all variables has |
I've looked through my bookmarks from years ago and amazingly found where I discovered this. It was in a comment in an article on precision. A good read. Enjoy! 😄
|
I will check it on my device(Xiaomi Mi Max) soon. If I've not finds this, I cannot help - I cannot make blindly change - it's against my principles. |
Ah, I see this bug too, will try to fix... |
I've fairly tried to compile android templates using these instructions http://docs.godotengine.org/en/latest/development/compiling/compiling_for_android.html. |
Beware here, I think I'd encountered this myself and a quick search suggests this: However, here: It mentions GL_FRAGMENT_PRECISION_HIGH which is "1 if highp is supported in the fragment language, else undefined", which might be useful. Also note that setting highp in fragment shader is not a good idea in many devices as even though it may be supported it may be super slow (I think reduz mentioned this too). I've also read it can be a bad idea to set an overall precision for the whole shader anyway because only certain parts may need higher precision (i.e. it can be better to use the lowest precision necessary for any particular operation). |
An additional project setting under rendering/gles2/compatibility with the name enable_high_float.Android is introduced that enables #define USE_HIGHP_PRECISION in GLES2 shader on Android when it is supported by the shader compiler. This fixes godotengine#33633 and godotengine#32813 and also GodotVR/godot_oculus_mobile#60 and GodotVR/godot_oculus_mobile#68 on devices that support the highp (high precision) modifier.
Fixed by #33646. |
An additional project setting under rendering/gles2/compatibility with the name enable_high_float.Android is introduced that enables #define USE_HIGHP_PRECISION in GLES2 shader on Android when it is supported by the shader compiler. This fixes godotengine#33633 and godotengine#32813 and also GodotVR/godot_oculus_mobile#60 and GodotVR/godot_oculus_mobile#68 on devices that support the highp (high precision) modifier.
Godot version: 3.1.1-stable
OS/device including version:
Issue description:
A friend of mine was doing some experiments with visual shaders, adding
TIME
toUV.x
to simulate texture scrolling.The equivalent shader code:
I'm not a shader expert, so I don't know if this code is safe, but it works fine on GLES3 (Windows and Android Adreno-509) and GLES2 on Windows.
Running this shader on Android using GLES2 (Mali-400 MP and Adreno-509) stretches the texture as
TIME
increases.So the more
TIME
increases, the more the texture stretches.Tests on Android GLES2
I thought it was some issue with
UV.x
being greater than 1.0f, so I tried the following code:But it also causes the same stretch bug on Android GLES2.
So, is this an actual bug?
Steps to reproduce:
Run the minimal reproduction project on Android with GLES2.
Minimal reproduction project:
UvOffsetTest.zip
The text was updated successfully, but these errors were encountered: