Deep-Fold / PixelPlanets

MIT License
1.05k stars 120 forks source link

Masking malfunction on mobile? #2

Closed JWBWork closed 3 years ago

JWBWork commented 3 years ago

I'm implementing this (amazing) shader in a project, but it misbehaves on mobile. It looks like the method to make the shader result circular isn't working properly, and portions of the shader that should be removed or masked are remaining.

Here's what it looks like on mobile

I'm not very famliar with shaders, but I understand there are limitations on mobile platforms - is this one of those cases or can it be fixed?

JWBWork commented 3 years ago

Alright, after some investigating I think I've found the source of the problem, but I'm still searching for a solution. I think this is a result of how the spherify function works in the shader. When I try to "plot" the results using the d_circle value (which is calculated with the uv results of the spherify like so:

COLOR = vec4(d_circle, d_circle, d_circle, a);

And that results in this: test (Ignore the sprites in front please)

So I think this is a result of the step function which calculates the alpha value, float a = step(d_circle, 0.5); - and I've read that mobile can have poor float precision. On desktop when I do this I see solid black around the "sphere" - which makes as that should be completely transparent. So I'll have to see why exactly the spherify function isn't returning the expected results

JWBWork commented 3 years ago

Alright, so I found a fix with a different alpha calculation to cut off the circle. instead of this:

float a = step(d_circle, 0.5);

I did this:

vec2 centered= uv *2.0-1.0;
float r = pow(centered.x, 2) + pow(centered.y, 2);
float a = step(r, 0.49);

No idea why the previous method wasn't working, something to do with the UV map I think. This also cuts off a little bit more than the other method, but it works on mobile (at least on my note 8).

JWBWork commented 3 years ago

Ok, bad solution - this doesn't account for the shaders that apply lava, craters, continents ect.

JWBWork commented 3 years ago

I fixed it by making this tweak to the spherify function:

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;
    }
}

This worked for each planet type except for GasPlanet.tscn