Choosing a Processing Renderer: JAVA2D vs P2D vs P3D vs FX2D
A decision guide for picking a Processing renderer — JAVA2D, P2D, P3D, or FX2D — with a comparison table, correct settings() usage, and a frameRate-based validation sketch.
13 Nov 2025, 23:56 UTC

The decision you're actually making
Every Processing sketch picks a renderer, whether you choose one or not. The default, JAVA2D, draws on the CPU and works everywhere — until your sketch starts drawing thousands of shapes per frame and the frame rate collapses. The question this guide answers: which renderer constant should you pass to size(), and how do you confirm the choice was right?
The short version: JAVA2D for simple or text-heavy 2D work, P2D for performance-critical 2D, P3D whenever you touch the z-axis, and FX2D only when you specifically need JavaFX output quality and control the deployment machine.
The four supported options
| Renderer | Pipeline | Best for | Main trade-off |
|---|---|---|---|
| JAVA2D (default) | CPU, Java2D | Static or modest 2D sketches, crisp text and images | Slows sharply with thousands of primitives per frame |
| P2D | GPU, OpenGL | Large shape counts, particle systems, fast 2D animation | Driver-dependent quirks; slightly different text/anti-aliasing |
| P3D | GPU, OpenGL | Any 3D: box(), sphere(), z-translate, lights, camera | Depth buffering can surprise 2D-only drawing inside it |
| FX2D | JavaFX | Fast 2D with high-quality text on controlled environments | Extra setup outside the IDE; least portable option |
Trade-offs that matter in practice
JAVA2D is the safe default. It runs on any machine that runs Processing, renders text and images cleanly, and is perfectly adequate up to a few hundred drawn primitives per frame. Its failure mode is predictable: as shape count climbs into the thousands, the CPU becomes the bottleneck and frameRate drops well below 60.
P2D moves the work to the GPU. For particle systems, dense scatter plots, or per-frame redraws of thousands of ellipses and lines, it is typically several times faster than JAVA2D. The costs are real but manageable: anti-aliasing and text rendering look subtly different, and behavior can vary across operating systems and GPU drivers. If your sketch will run on hardware you don't control, test there before committing.
P3D is not optional for 3D. If you call box(), sphere(), translate(x, y, z), lights(), or manipulate the camera, you need P3D — the other renderers simply don't implement z-depth. You can draw ordinary 2D shapes inside P3D, but the depth buffer means overlapping 2D elements may not layer in the order you drew them. For a purely 2D sketch, prefer P2D over P3D to avoid those surprises.
FX2D is a niche choice. It can render 2D scenes quickly with excellent text quality, but it has historically required extra JavaFX configuration outside the Processing IDE and is the least portable of the four. Reach for it only when you have a specific reason and you control where the sketch runs.
One more caveat: some features are renderer-dependent. Certain blend modes, hint() settings, and direct pixel operations (loadPixels()/updatePixels()) can be ignored or unexpectedly slow depending on the renderer. Check the reference for any function you rely on heavily.
Declaring the renderer correctly
When you use a non-default renderer, declare it in settings(), not setup(). This matters because the renderer must be known before the sketch window is created, and it is the only form that reliably accepts variables for width and height:
void settings() {
size(800, 600, P2D); // renderer as third argument
}
void setup() {
frameRate(60);
}
void draw() {
background(20);
for (int i = 0; i < 5000; i++) {
ellipse(random(width), random(height), 4, 4);
}
}
Calling size() with a renderer directly in setup() only works with literal values in some modes, so settings() is the habit to build. The same applies to fullScreen(P2D).
Validating the choice with frameRate
Don't pick a renderer on faith — measure it. Run the same heavy draw loop under JAVA2D and P2D and compare sustained frame rates. This sketch prints the frame rate every 60 frames; run it in the Processing IDE (no special permissions needed):
// Change P2D to JAVA2D (or remove the renderer) and re-run to compare.
void settings() {
size(800, 600, P2D);
}
void draw() {
background(20);
for (int i = 0; i < 5000; i++) {
ellipse(random(width), random(height), 4, 4);
}
if (frameCount % 60 == 0) {
println("frame " + frameCount + " fps: " + nf(frameRate, 0, 1));
}
}
What to look for: let each run settle for a few seconds (the first readings are noisy while the JVM warms up), then compare the sustained numbers. On a typical laptop you should see JAVA2D struggle with 5,000 ellipses per frame while P2D holds near the 60 fps cap. If both renderers already hold 60 fps for your real sketch, stay on JAVA2D — the GPU buys you nothing and costs you portability.
Limitations and final checks
- OpenGL behavior varies by OS and GPU driver. If the sketch will run elsewhere, export it as an application for that platform (File > Export Application) and confirm the renderer initializes without erroring or falling back.
- Renderer defaults and availability can change between Processing major versions (3.x vs 4.x). Confirm against your installed version via Help > Reference and the
size()entry. - Frame rate numbers are machine-specific; treat the comparison as a decision aid for your target hardware, not a universal benchmark.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.