[Rendering] Investigate renderer parity: SFML (desktop) vs SDL2/WebGL (web) — shaders & pixel-perfect output #347
Labels
No labels
Alpha Release Requirement
Bugfix
Demo Target
Documentation
Major Feature
Minor Feature
priority:tier1-active
priority:tier2-foundation
priority:tier3-future
priority:tier4-deferred
Refactoring & Cleanup
system:animation
system:documentation
system:grid
system:input
system:performance
system:procgen
system:python-binding
system:rendering
system:ui-hierarchy
Tiny Feature
workflow:blocked
workflow:needs-benchmark
workflow:needs-documentation
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Blocks
Reference
john/McRogueFace#347
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Motivation
The desktop backend is SFML; the web backend is SDL2 + OpenGL ES 2 (
src/platform/SDL2Renderer.cpp,SDL2Types.h). Game code is written against the SFML API and the SDL2 types mirror it, but rendering fidelity parity is not established. Until it is, shipping a game to web is dependent on careful manual testing of that game's content in both modes — we can't assume desktop-correct rendering is web-correct.The existing CLAUDE.md "Web Build Constraints" table covers Audio / ImGui / Dynamic assets / Threading / Input, but says nothing about shader availability or pixel-perfect output. This issue is to investigate and document those gaps, then spin out concrete follow-up issues per confirmed defect.
Areas to investigate
1. Shader GLSL dialect portability. There is a real GL ES 2 shader impl on web (
SDL2Types.h:1375,Shader::loadFromMemory→ program compile). But nothing appears to reconcile desktop GLSL with WebGL GLSL ES 1.00:precisionqualifiers (required in ES, absent in desktop)#versiondirectivesvarying/attribute(ES 1.00) vsin/out(desktop)mcrfpyShader,PyShader.cpp) that compiles on desktop may fail on web or vice versa. Determine whether we translate, require ES-compatible source, or fail silently.2. Shader feature availability. The
Shader::Typeenum includesGeometry— geometry shaders do not exist in GL ES 2. Enumerate which shader features/uniform types are desktop-only.3. Pixel-perfect output. Compare desktop SFML vs WebGL for:
UIGriduses render-texture chunk caching)grid.center,center_camera, zoom)4. Headless testing gap. Headless
Shader::loadFromMemoryreturnsfalse(HeadlessTypes.h:931) — shader-dependent paths cannot be validated on headless CI. Decide how shader correctness gets tested cross-backend (screenshot comparison harness?).Deliverable
An investigation write-up (wiki + expanded CLAUDE.md constraints table) documenting confirmed parity gaps, plus granular follow-up issues (
system:rendering) for each fixable defect. This is a blocker to trusting the desktop→web transition for any shader-using or pixel-sensitive game.Related: web profiling docs (sibling), Emscripten/SDL2 backend notes in CLAUDE.md.
First divergences confirmed by the #388 harness
The #388 cross-backend screenshot-diff harness now renders the snippet corpus on web (SDL2/WebGL) and diffs against the desktop-headless oracle. On a calibration run over snippets 1–15 (
make test-wasm-diff SNIPPETS="1 6 8"), clean static frames match to ≤2.2% pixel diff, and two snippets flagged real divergences:1. Frame outline geometry (
008_frame_outline, 8.5% diff) — SDL2-specific bug.The divergence mask (
snippet-shots/web-diff/008_frame_outline_mask.png) shows the frame borders differ, and the difference scales with outline thickness (frames at thickness 0/2/5/10/20 — the thickness-20 frame is grossly wrong, ~solid mismatch). Root cause is inShape::draw(SDL2Renderer.cpp): the outline is built as per-edge quads extruded a fulloutlineThicknessoutward along each edge normal, with no corner miter/join and a different extrusion basis thansf::Shape::setOutlineThickness. Thin outlines are close; thick ones diverge badly. This is a concrete SDL2 outline-geometry defect → belongs in #390.2. Text rendering (labels in the same frame differ) — the §3d divergence, confirmed.
The outline snippet's caption labels also show as differing pixels, corroborating the no-kerning / byte-wise-glyph text divergence catalogued in §3d. Already routed to #390.
The harness passes clean frames and isolates genuine divergences with per-pixel masks for triage — exactly the CI signal this investigation called for. Full-corpus runs will surface the rest; each new divergence gets a mask and a line here / on #390.