GodotVR / godot_oculus_mobile

Godot Oculus mobile drivers (Oculus Go / Oculus Quest)
MIT License
170 stars 34 forks source link

Quality of visual shaders deteriorates when using Time input #60

Closed fakedeltatime closed 4 years ago

fakedeltatime commented 5 years ago

When using the Time input in a Visual Shader, then the quality of the change in the Time input as well as the quality of textures altered with it deteriorates, making the changes stutter and lowering the resolution of the textures. The project I've provided shows three cubes, two with the same noise texture the right of which has an animated shader using the Time input, and one with a cycling opacity. The quality of the latter two should deteriorate in under 60 seconds.

time_deterioration.zip

NeoSpark314 commented 5 years ago

I tried the attached reproducer and the problem is clearly visible on the quest while it does not occur on desktop:

time_deterioration_screenshot

I used renderdoc to inspect the created shader and it seems to be a floating point precision problem: In the final fragment shader there is at the top a

#if defined(USE_HIGHP_PRECISION)
precision highp float;
precision highp int;
#else
precision mediump float;
precision mediump int;
#endif

but USE_HIGHP_PRECISION is not defined. So the default precision for computations is mediump.

The computation from the shader graph later looks like this.

{
    vec3 m_n_out7p0;
    m_n_out7p0 = vec3(uv_interp, 0.0);
    float m_n_out2p0;
    m_n_out2p0 = time;
    float m_n_in5p1 = 0.3;
    float m_n_out5p0;
    m_n_out5p0 = (m_n_out2p0 * m_n_in5p1);
    float m_n_in4p2 = 0.0;
    vec3 m_n_out4p0;
    m_n_out4p0 = vec3(m_n_out5p0, m_n_out5p0, m_n_in4p2);
    vec3 m_n_out6p0;
    m_n_out6p0 = (m_n_out7p0 + m_n_out4p0);
    vec3 m_n_out3p0;
    float m_n_out3p1;
    vec4 m_tex_frg_3_read = texture2D(m_tex_frg_3, m_n_out6p0.xy);
    m_n_out3p0 = m_tex_frg_3_read.rgb;
    m_n_out3p1 = m_tex_frg_3_read.a;
    albedo = m_n_out3p0;
}

even though the time variable is defined as uniform highp float time; the actual computation is done in mediump!

Querying the precision on the oculus quest using glGetShaderPrecisionFormat gives

V GodotOVRMobile:     Fragment Shader Precision: LOW  [15, 15] 10
V GodotOVRMobile:     Fragment Shader Precision: MED  [15, 15] 10
V GodotOVRMobile:     Fragment Shader Precision: HIGH [127, 127] 23

so all computations are done with 10bit mantissa.

Looking into the godot code the only place where USE_HIGHP_PRECISION is defined for the shader seems to be in the JavaScript case: https://github.com/godotengine/godot/blob/ac38f0782fbf781265ec34a43196e3ea157f3696/drivers/gles2/shader_gles2.cpp#L180

Forcing this define to be always present by disabling the #ifdef JAVASCRIPT_ENABLED fixed the issue.

I don't know what the proper solution to this problem is. Two ideas from my side are

m4gr3d commented 5 years ago

cc @akien-mga

m4gr3d commented 5 years ago

@fakedeltatime Can you open an issue on the main Godot engine issues page as well since as @NeoSpark314 mentions this may also affect other platforms.

akien-mga commented 5 years ago

Related: godotengine/godot#32813

akien-mga commented 5 years ago

Related: godotengine/godot#32813

I tested the reproduction project there on a Xiaomi Pocophone F1 and I can confirm that the same issue happens as described here, so it's the same bug.

@NeoSpark314 Would be worth adding your findings there.

fakedeltatime commented 5 years ago

I'm surprised that I'm not getting these problems with my low tier Nokia 1 phone, but I guess that might be because it's running Android Go (a lighter version of Android) instead of regular Android?

Firepal commented 4 years ago

Since godotengine/godot#33646 was merged into master and included in 3.2.3, shouldn't this issue be closed? That PR was probably the best that could've been done in any case ^^'

m4gr3d commented 4 years ago

Agree, thanks for the reminder @Firepal!