Skip to content

[rlgl] Add opt-in highp precision for default GLES shaders#5670

Closed
ghera wants to merge 1 commit intoraysan5:masterfrom
ghera:feature/rlgl-gles-highp-precision-opt-in
Closed

[rlgl] Add opt-in highp precision for default GLES shaders#5670
ghera wants to merge 1 commit intoraysan5:masterfrom
ghera:feature/rlgl-gles-highp-precision-opt-in

Conversation

@ghera
Copy link
Contributor

@ghera ghera commented Mar 18, 2026

Problem

On certain Android devices (tested: Redmi Note 14 Pro), the default GLES fragment shader precision mediump float is not sufficient for stable rendering of 2D geometry. The result is visibly irregular rounded corners when using DrawRectangleRounded(), 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 mediump to highp.

Root Cause

mediump float on 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:

  • Samsung Galaxy A56 uses ANGLE as its GLES backend, running on top of Vulkan via the Samsung Xclipse 540 GPU (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 — mediump effectively behaves closer to highp regardless of what the shader declares.
  • Redmi Note 14 Pro 5G uses the Mali driver directly, with no translation layer (Renderer: Mali-G57 MC2). The driver therefore enforces mediump strictly 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_PRECISION is added at the top of rlgl.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/1 default.

@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 mediump precision:

samsung

Redmi Note 14 Pro — mediump, broken rendering

Rounded corners are jagged and irregular on the same code:

redmi

Redmi Note 14 Pro — highp via flag

Corners now match the Samsung result almost exactly:

redmi_after

@maiconpintoabreu
Copy link
Contributor

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.

@ghera
Copy link
Contributor Author

ghera commented Mar 19, 2026

Hi @maiconpintoabreu, thanks, that makes sense.
My reasoning for opening this PR was mainly usability: it seemed simpler for users who just want to draw primitives with the built-in API, without having to load a custom shader themselves.
At the same time, a custom shader definitely gives more flexibility on a case-by-case basis, so I am happy to leave the final decision to @raysan5. I am totally fine with closing the PR if that is the preferred direction.

@raysan5
Copy link
Owner

raysan5 commented Mar 19, 2026

@ghera thanks for the detailed report and the sample images illustrating the issue... not sure what to do with this one yet...

@Bigfoot71
Copy link
Contributor

Bigfoot71 commented Mar 20, 2026

Just my opinion, I agree with @maiconpintoabreu, setting highp everywhere by default is clearly excessive, especially in the example shown, there are more energy efficient / portable ways to achieve the desired result here.

@ghera
Copy link
Contributor Author

ghera commented Mar 20, 2026

@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.

@ghera ghera closed this Mar 20, 2026
@ghera ghera deleted the feature/rlgl-gles-highp-precision-opt-in branch March 20, 2026 14:51
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants