overbound / SonicTimeTwisted

Source Code for a Sonic Fan Game Made in Game Maker Studio
https://overboundstudio.com/
GNU General Public License v3.0
60 stars 16 forks source link

Time Travel Shader doesn't work on some platforms due to a mistake in code. #63

Closed nkrapivin closed 4 years ago

nkrapivin commented 4 years ago

I found this while I was working on my PS4 branch. The original code in the Create event looks like this:

tts = TimeTravelShader;
// send some information to the shader; the shader has to be set for this to work
// (I don't know if this can be screwed up by using other shaders; if so, this info might have to be sent in the draw event...)
shader_set(tts);
// send: the scaling of the sparkly SCD texture so it will repeat enough times to not be stretched
shader_set_uniform_f(shader_get_uniform(tts, "scl"), sprite_width / background_get_width(tt_texture), sprite_height / background_get_height(tt_texture));
// send: the texture index of the sparkly SCD texture
texture_set_stage(shader_get_sampler_index(tts, "mask"), background_get_texture(tt_texture));
// send: the texture index of the the gradient used to cycle the colours
texture_set_stage(shader_get_sampler_index(tts, "grad"), background_get_texture(tt_gradient));
shader_reset();

But for some reason, PS4 (and maybe some other platforms, need to recheck), do not save uniform values after shader_reset() As such, you need to set uniform values every single time. Like this (still Create):

// why i hate PS4?
tt_texhandle = background_get_texture(tt_texture);
grad_texhandle = background_get_texture(tt_gradient);
tt_width = background_get_width(tt_texture);
tt_height = background_get_height(tt_texture);

tts_ok = shader_is_compiled(tts);
if (!tts_ok) show_message_async("Could not compile Time Travel Shader!");
param_shift = shader_get_uniform(tts, "shift");
param_scl = shader_get_uniform(tts, "scl");
stage_mask = shader_get_sampler_index(tts, "mask");
stage_grad = shader_get_sampler_index(tts, "grad");

And then in the Draw event:

    shader_set(tts);

        // send: the scaling of the sparkly SCD texture so it will repeat enough times to not be stretched
        shader_set_uniform_f(param_scl, sprite_width / tt_width, sprite_height / tt_height);
        // send: the texture index of the sparkly SCD texture
        texture_set_stage(stage_mask, tt_texhandle);
        // send: the texture index of the the gradient used to cycle the colours
        texture_set_stage(stage_grad, grad_texhandle);

        shader_set_uniform_f(param_shift, shift); // send the shift amount (for colour cycling) to the shader
        draw_surface_ext(tt_surface, 0, view_yview, image_xscale, image_yscale, 0, c_white, 1);
    shader_reset();

Who knows, maybe NoShader objects weren't needed at all...(?)

PS: this fixed the shader issues on PS4, the game is working perfectly.

AlexKhayrullin commented 4 years ago

This is very interesting, I've created the NoShader objects for the Android port, I'll try your fix later today. I confirm that the shader does not work on Android at the moment.

And another thing: I remember seeing similar malfunctions in the shader after an attempt to convert the project to GMS2 a while ago, even on PC. I'll try both today, if I have time.

nkrapivin commented 4 years ago

TimeTravelShader is very simple, just some math stuff like mod(), it's really weird that it doesn't work on Android.

Maybe try my fix? Also what's your test phone? Maybe your phone's GPU is quite poor?

nkrapivin commented 4 years ago

Here's a video of TT shader working on my phone (after the fix): https://drive.google.com/file/d/1wHQcCB3ajU5ADuLcZ2D2YYV6S31Pbuy0/view?usp=sharing

Redmi 6A, Android 9, MediaTek Helio A22 It's a pretty low-budget phone yet STT runs. It's not really smooth, when doing surfaces framerate drops a lot. But overall you can complete the first zone :p

AlexKhayrullin commented 4 years ago

I managed to integrate this, and... yes, it works so well!

You are right, the NoShader objects are not needed.

I test with my old phone, a Xiaomi Mi A1, and while the game runs well on it, the shaders simply glitch out, with random outcomes really: in case of the wave during the name crawl, sometimes I get a solid white wave, sometimes I get a solid white wave with rectangular holes, sometimes nothing at all. All the while, the rest of the game works. So I don't know whether it's the GPU that's the issue, or something with the Android runner...?

Anyhow, your code fixed it. So weird to see the effect on my phone after three years ^^.

It's committed and pushed. Thanks a lot for your submission!