You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
WebGL / WebGPU: nested clipRect replaces the outer clip instead of intersecting it #1816
On WebGL and WebGPU, a clipRect() made while another clip is active replaces it. On Canvas, the two clips intersect, as context.clip() does. So content clipped by an inner container is not also clipped by an outer one.
The case that shows it: a scrolling UIPanel inside another clipping container (another scrolling panel, or a Container with clipping on). The inner panel's content is cropped to the inner panel's own area only. Where the inner panel extends past the outer one, its content draws outside the outer panel. On Canvas it is cropped to both.
This is documented as a known limitation in the melonjs-ui-and-text skill and in UIPanel's class doc (#1815).
Why
WebGLRenderer#clipRect (src/video/webgl/webgl_renderer.js) computes the new rectangle's screen-space box and calls gl.scissor() with it. It never intersects with the active currentScissor.
WebGPURenderer#clipRect (src/video/webgpu/webgpu_renderer.js) does the same.
CanvasRenderer#clipRect uses context.clip(), which intersects with the current clip region.
save() / restore() already store and re-apply the scissor, so an intersected scissor would be undone at the right time.
Suggested fix
In both GPU renderers, when a scissor is active, intersect the new box with currentScissor before applying it. An empty intersection should mean "draw nothing", not "no clip".
The "covers the whole canvas → disable the scissor" shortcut should become "keep the current scissor" when one is active.
Things to check
Clipping is shared by everything these renderers draw, so the change should be tested on:
Cameras: multiple viewports.
Post-effects: the render-target path calls clipRect and _resumeSavedClip.
clearRect: it clips inside save() / restore().
Nested clipping containers: a test drawing a nested pair on all three renderers and comparing pixels (Canvas is the reference).
Activity
Rendering: a clip inside a clip is the overlap of the two on WebGL an…