[rlgl] Add opt-in highp precision for default GLES shaders#5670
[rlgl] Add opt-in highp precision for default GLES shaders#5670ghera wants to merge 1 commit intoraysan5:masterfrom
Conversation
|
Hi @ghera for case by case device I think it is better to leave the game dev decide, you can load the a custom shader to avoid using the default. |
|
Hi @maiconpintoabreu, thanks, that makes sense. |
|
@ghera thanks for the detailed report and the sample images illustrating the issue... not sure what to do with this one yet... |
|
Just my opinion, I agree with @maiconpintoabreu, setting |
|
@Bigfoot71 Thanks for the feedback. The example was specifically crafted to make the precision issue obvious; on some affected devices, the artifact is quite noticeable not only in the arcs but also in the red squares, which end up stretched into rectangles. I agree that in real-world cases, especially for UI elements, different approaches are usually preferable, such as using N-patch textures. Anyway, you guys convinced me in the end, so @raysan5 I’ll close the PR. |
Problem
On certain Android devices (tested: Redmi Note 14 Pro), the default GLES fragment shader precision
mediump floatis not sufficient for stable rendering of 2D geometry. The result is visibly irregular rounded corners when usingDrawRectangleRounded(), regardless of segment count.Snapping coordinates to integers doesn't solve nor mitigate the issue on the affected device.
This PR adds an opt-in compile-time flag that switches the default GLES shader float precision from
mediumptohighp.Root Cause
mediump floaton GLES is specified to have at least 10 bits of mantissa (~3 decimal digits). On certain Mali drivers this is insufficient to maintain sub-pixel accuracy for arc vertices computed from screen-space positions at typical UI resolutions, causing visible snapping artifacts in the rendered curve.highp float(IEEE 754 single precision, 23-bit mantissa) eliminates the precision loss and produces smooth curves on the same hardware.Why Samsung was unaffected
Investigation revealed a key difference in the underlying GLES implementation between the two devices:
Renderer: ANGLE (Samsung Xclipse 540) on Vulkan 1.3.279). ANGLE translates GLES calls to a higher-level API (Vulkan or desktop GL), and in doing so it normalises float precision internally —mediumpeffectively behaves closer tohighpregardless of what the shader declares.Renderer: Mali-G57 MC2). The driver therefore enforcesmediumpstrictly as specified, exposing the precision loss in the rendered geometry.This explains why the artifact is device-specific and not reproducible across all Android hardware, and why simply testing on a Samsung device is not sufficient to catch the issue.
As far as I could tell, whether ANGLE is used is decided by the OS/vendor and cannot be forced from application code, meaning there may be no workaround available at the raylib or app level short of changing the shader precision.
Fix
A new macro
RLGL_ENABLE_GLES_DEFAULT_HIGHP_PRECISIONis added at the top ofrlgl.h.The flag defaults to
0(no behaviour change).I intentionally kept this as a boolean-style opt-in flag for clarity and readability, even though the conditional could have been expressed without an explicit
0/1default.@raysan5 I kept this as an explicit compile-time flag so the choice remains with the user, but if you would prefer enabling it by default for Android builds, I can update the PR accordingly.
Visual Evidence
Samsung Galaxy A56 —
mediump, correct rendering (no fix needed)Corners are smooth and correct with the default
mediumpprecision:Redmi Note 14 Pro —
mediump, broken renderingRounded corners are jagged and irregular on the same code:
Redmi Note 14 Pro —
highpvia flagCorners now match the Samsung result almost exactly: