Shader function different results on android mobile vs windows

:information_source: Attention Topic was automatically imported from the old Question2Answer platform.
:bust_in_silhouette: Asked By jwbwork

So I’m trying to use these shaders, but I’m getting different results on android than I am on my PC. I think I found the source of the issue, the function below which is meant to map the UV to a sphere

vec2 spherify(vec2 uv) {
    vec2 centered= uv *2.0-1.0;
    float z = sqrt(1.0 - dot(centered.xy, centered.xy));
    vec2 sphere = centered/(z + 1.0);
    return sphere * 0.5+0.
}

When I change the COLOR assignment to show the results of this on the UV I get these results. On PC it looks like it maps properly and areas outside of the sphere are dropped.
PC results
But on android I can see the results are mapped to a sphere, but regions beyond the sphere are kept.
Android results

I know mobile devices can have issues with shaders. I’ve tried changing the project settings with not luck. Does anyone know why this function is producing different results or have any ideas on how it can be fixed?

:bust_in_silhouette: Reply From: Wakatta

Know that the mobile graphics OpenGL ES 2/3 are stripped down versions of the desktop’s OpenGL and getting a 1-to-1 comparison is near impossible. Actually i’m amazed at how well Godot handles those differences.

Your issue though could be the use of floats as they are not as precise on the MIPS architecture making it hard to get consistency with shaders and sadly Godot doesn’t support #IFDEF’s

Very few mobile devices nowadays use a MIPS-based architecture. It’s all ARM :slight_smile:

Calinou | 2021-02-19 21:08

:bust_in_silhouette: Reply From: jwbwork

I managed to implement a fix by changing the spherify function like so:

vec2 spherify(vec2 uv) {
    vec2 centered= uv *2.0-1.0;
    float z = sqrt(1.0 - dot(centered.xy, centered.xy));
    vec2 sphere = centered/(z + 1.0);
    float r = pow(centered.x, 2) + pow(centered.y, 2);
    if (r > 1.0) {
        	return vec2(0.0, 0.0);
    	} else {
	    return sphere * 0.5+0.5;
    }
}