- Test now correctly finds "Finish" button on last wizard page - Added CLAUDE.md note about running e2e tests via npm scripts - Simplified test to click through wizard with proper button detection Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
3.4 KiB
Wha# Emscripten LEGACY_GL_EMULATION - Immediate Mode Notes
Overview
This document describes the behavior and limitations of Emscripten's LEGACY_GL_EMULATION when using OpenGL immediate mode (glBegin/glEnd) in WebAssembly builds.
Key Finding: Color Per Vertex Requirement
Emscripten's immediate mode requires color to be specified per-vertex, not using OpenGL's "current color" semantic.
Standard OpenGL Behavior
In desktop OpenGL, you can set a color once and it applies to all subsequent vertices:
glBegin(GL_TRIANGLES);
glColor3f(1.0f, 0.0f, 0.0f); // Set current color to red
glVertex3f(0, 0, 0); // Uses red
glVertex3f(1, 0, 0); // Still uses red
glVertex3f(0, 1, 0); // Still uses red
glEnd();
Emscripten Behavior
In Emscripten's LEGACY_GL_EMULATION, you must call glColor*() before each glVertex*():
glBegin(GL_TRIANGLES);
glColor3f(1.0f, 0.0f, 0.0f); // Color for vertex 1
glVertex3f(0, 0, 0);
glColor3f(1.0f, 0.0f, 0.0f); // Color for vertex 2 - REQUIRED!
glVertex3f(1, 0, 0);
glColor3f(1.0f, 0.0f, 0.0f); // Color for vertex 3 - REQUIRED!
glVertex3f(0, 1, 0);
glEnd();
Why This Happens
Emscripten's GLImmediate module calculates vertex stride based on enabled attributes:
- Position (glVertex3f): 16 bytes (4 floats: x, y, z, w)
- Color (glColor3f/4f): 4 bytes (4 unsigned bytes: r, g, b, a)
- Total stride: 20 bytes per vertex
The numVertices calculation is:
numVertices = 4 * vertexCounter / stride
If color is only specified once but vertices are specified multiple times, vertexCounter won't be evenly divisible by stride, causing the assertion:
Assertion failed: `numVertices` must be an integer.
Verified Working Functions
The following immediate mode primitives work correctly with the color-per-vertex pattern:
| Primitive | Status | Notes |
|---|---|---|
| GL_TRIANGLES | Working | RGB color interpolation works |
| GL_QUADS | Working | Use glVertex3f (glVertex2f also works) |
| GL_LINES | Working | |
| GL_LINE_STRIP | Working | |
| GL_LINE_LOOP | Working |
Unsupported Functions
glVertex2d- Not implemented in Emscripten, useglVertex2forglVertex3finstead
Build Flags
Enable legacy GL emulation with these Emscripten flags:
-sLEGACY_GL_EMULATION
-sMAX_WEBGL_VERSION=2
You may see these warnings (they are expected):
WARNING: using emscripten GL emulation. This is a collection of limited workarounds, do not expect it to work.
WARNING: using emscripten GL immediate mode emulation. This is very limited in what it supports
Implications for KiCad
KiCad uses immediate mode in several places:
- Cursor rendering in
opengl_gal.cpp - Bitmap quad rendering
- Antialiasing overlays
Any code that sets a color once and draws multiple vertices will need modification for WASM builds.
Possible Solutions
- Compatibility layer: Wrap glColor/glVertex calls to automatically replicate colors
- Code modification: Update KiCad's GAL to always specify color per-vertex
- VBO migration: Convert immediate mode code to use Vertex Buffer Objects
Test Results
All immediate mode tests pass with the color-per-vertex pattern:
- RGB triangle with smooth color interpolation
- Yellow quad
- White line
- Cyan line strip
- Magenta line loop
See apps/minimal_test.cpp for working examples.