Releases: djanice1980/pcbview
Release list
pcbview 1.26.1 — Coated walls
The mask coats the trace walls
A follow-up to 1.26.0's drape, from the same user's macro lens: the
stepped drape's raised piece overhung each copper edge with an open
underside — at millimetre range the mask read as a little roof peeling
off the substrate, arguably worse than the hover it replaced.
Rebuilt as two overlapping solids instead of a partition. The whole
film sits at the dropped level, hugging the laminate and tunnelling
straight through the copper (buried inside an opaque solid, so
harmless — and it has no wall at the copper boundary, so nothing is
coplanar with anything). Over copper, a full-height climb piece runs
from the film's bottom clear to its proper top, so the mask encases
the trace's top and side walls — which is what conformal mask
actually does. Trace and pad edges now render as a coated green
shoulder; mask openings are rimmed the way a real board's are.
Silkscreen keeps the partition from 1.26.0: ink is opaque and sits on
the local mask surface, and its pieces' walls never overlap in Z.
pcbview 1.26.0 — The mask drapes
The mask drapes now
Found by a user camera move flying millimetres above a flex board: the
soldermask — and the silkscreen ink printed on it — was extruded as a
flat film at one Z, its underside on the copper's top face. Real LPI
mask conforms: over copper it rides the foil, and between traces it
drapes down onto the laminate. The flat film instead hovered a copper
thickness above the laminate wherever nothing supported it, silk
riding the hover. Invisible at normal distance; at macro range with
traced shadows the 35 µm slit reads as a dark line and every silk
stroke casts a visibly displaced shadow — the board looks like it is
delaminating.
The film is now split by the outer foil's copper and the unsupported
region sits a copper thickness lower, on the laminate where it belongs
— both sides, both importers, every render mode. The split boundary is
the copper edge inflated 20 µm (splitting exactly at the edge would
z-fight the dropped film's walls against every trace's walls — the
lesson the via barrels learnt first), and the overhang doubles as the
mask's shoulder over the trace edge. A correct side effect at close
range: traces now read as gentle raised ridges under the mask, the way
they do on a real board. Logged as fab-truth gap #5 (fixed) in
ARCHITECTURE.md.
The underside gets light
The environment's ground half was near-black — fine while "the board is
what turns" held, but the view presets and headless captures orbit the
CAMERA, so bottom views stared at a permanently unlit side (~3× darker
substrate than the top). The ground gradient is now a plausible
studio-floor bounce plus a broad, weak fill lobe opposite the sun —
environment-only, so no new shadows and no cost. Measured on an 8-layer
board: bottom substrate 62 → 98 mean green, top effectively unchanged.
The underside stays dimmer than the sunlit side on purpose.
Frame-fit covers both axes
Fit-to-view fitted the board's larger span against the vertical FOV
only, silently under-covering the horizontal axis — on a narrow
viewport a wide board clipped at the frame edges. Each axis now fits
against its own FOV and the larger distance wins. The math moved to a
pure header with no Qt/Vulkan/glm, so the geometry test suite pins it,
including the coverage identity at several aspect ratios.
pcbview 1.25.0 — Component picking
Hide and show individual components (KiCad boards)
A new Components panel lists every reference designator with a
checkbox, naturally sorted (C2 before C10), with a filter box. All
and None act on whatever the filter currently matches — filter to
C, hit None, and just the capacitors vanish.
The identity was in the export all along: kicad-cli's GLB names each
footprint's node by its refdes, and the importer had been merging that
away at parse time. It is now kept on the cached parts, and the merge
into a few colour/side render batches happens per assembly over only the
visible ones — so per-component visibility costs no draw calls, the
stackup tree's all-components master toggle works unchanged, and a
toggle costs one reassembly, the same as moving the thickness slider.
Hidden components are session state, deliberately: a component silently
missing on next week's open of the same board would read as an import
bug, not a remembered choice.
PCBVIEW_HIDE accepts reference designators now too — a name matching
a loaded component hides that one component; anything else is still a
stackup part name — so capture scripts can hide parts headlessly.
pcbview 1.24.0 — Sharing the GPU
Path tracing no longer fights the desktop (integrated GPUs)
On an integrated GPU the desktop compositor shares the silicon — and a
converging path trace was starving it. Each sample was one monolithic
50–80 ms compute dispatch, submitted back-to-back until convergence, and
the compositor got a scheduling window about twelve times a second. It
read as the mouse cursor hitching whenever the image was refining.
Measured with a second GPU client: 180 fps alone, an erratic 13 during
convergence.
Two changes, which only work together:
- Each sample is sliced into band-per-submission pieces
(PCBVIEW_PT_BANDS, default 4 on integrated GPUs, inline on
discrete). The bands are disjoint pixels of the same sample in the
same order, so the image is bitwise identical — verified by capture
comparison. Submission boundaries are where the kernel's GPU scheduler
can arbitrate between processes; bands alone changed nothing, because
the FIFO still ran every queued band before anyone else's job. - The device queue asks for LOW global priority
(VK_EXT_global_priority, integrated GPUs only, silent fallback): at
every boundary the scheduler now picks the desktop's work first.
Together: the second client holds 134–142 fps through convergence, and
accumulation pays 10–15% more wall time. The converged image is
unchanged.
The viewport says what is drawing it
Top-right corner, always on: the device name and the active mode —
raster, ray-traced lighting, path tracing, the Embree preview
modes on the CPU device, and raster (moving) while the fast-movement
downgrade is live. It is part of the overlay rather than the status bar,
so screenshots and captures carry their own provenance.
A first run has moves to play
The Record/Play panel used to start empty, which gave a new user no hint
what a step even looks like. A fresh install now seeds a default tour —
iso, a full spin, top, an explode there-and-back, bottom — as editable
examples of each step kind. A deliberately emptied list stays empty.
Fixed
- The build's warning output means something again on gcc: the Vulkan
{VK_STRUCTURE_TYPE_...}idiom tripped several hundred
-Wmissing-field-initializersfalse positives that buried real
warnings. What the noise was hiding is fixed too: two Gerber-importer
aggregate initialisers genuinely missing a member, a misleadingly
indented (but correct) command in the offscreen path, and two dead
functions removed. The build is now down to a single warning, in
third-party code.
pcbview 1.23.0 — Linux
Linux
pcbview now builds and runs natively on Linux. Developed and verified on
Arch/CachyOS under Wayland on RADV; anything with Qt 6.5+, Vulkan and a
recent Mesa should work.
Everything came across: the raster view, ray-traced shadows/AO, the full
path tracer with Open Image Denoise, CPU rendering, measurement, net
highlighting, exploded view, printing, screenshots — and video recording,
which pipes frames to the system ffmpeg instead of Media Foundation,
same H.265-preferred/H.264-fallback behaviour.
The one deliberate exception is VR, which stays Windows-only: it was
developed against a PSVR2 over SteamVR, and that headset has no Linux
path today. The OpenXR code compiles everywhere and is gated by a single
CMake option (PCBVIEW_ENABLE_VR), so if that ever changes it is a
rebuild, not a port.
Two Linux binaries are attached, both CI-built:
pcbview-1.23.0-x86_64.AppImage— portable:chmod +xand run on
any current 64-bit distro. Qt and the render libraries are bundled;
component bodies additionally want KiCad + its 3D model library
installed (the app says so if they are missing).pcbview-1.23.0-1-x86_64.pkg.tar.zst— native Arch/CachyOS
package:pacman -U, dependencies resolved by pacman, launcher entry
included. The-debugpackage is its split debug symbols; most people
do not need it. Building it yourself instead is one command:
cd packaging/linux && makepkg -si— which also offers the optional
pieces (KiCad + models,vulkan-swrastfor CPU rendering,ffmpeg
for recording) with the reason each is wanted.
Other distributions: see Building from source in the README.
Missing requirements now say so
Component bodies need KiCad's kicad-cli and its 3D model library,
and on Linux those are separate packages — an export without the models
succeeds with an empty file, which used to surface as an unexplained
"no components". pcbview now recognises that failure and names the fix
per platform, and no longer caches the empty export, so installing the
models heals an already-opened board on reload. The Windows installer
likewise now offers the KiCad download page when no install is found.
Fixed
- Single-digit frame rates on integrated GPUs. Ray-traced lighting
defaults on whenever the GPU reportsray_query, and the "fast
movement drops to raster" option's default was written when a
ray-query GPU meant a discrete card. An iGPU can report the feature
and still pay ~25–40× raster for it (measured on a Radeon 8060S:
5.5 ms raster vs 24–213 ms with RT on — single-digit fps through every
view transition). Fast movement now defaults ON for integrated GPUs,
as it already did for the CPU device: 181 fps through the same
transitions, shadows restored the moment the camera rests. Persisted
choices are untouched, andPCBVIEW_PERF_LOG=1prints the status
bar's frame-cost line to stdout — it is how these numbers were taken. - The path-tracer descriptor pool was undersized — it undercounted
storage images after three bindings were added to the layout. Windows
drivers do not enforce pool limits so it never failed there; RADV
enforces them strictly and refused the tonemap set on the first Linux
frame. - The last frames of a recorded video were silently dropped on every
platform: the encoder was finalised before the drain that writes the
tail of the capture ring, so every drain write failed. The drain now
runs first — and an aborted recording is finalised too, leaving a
short playable file rather than one with no index. - A first-ever run that went straight to
PCBVIEW_RECORDsat behind
the one-time support notice and never wrote a frame; the notice now
counts that hook among the headless runs it must not interrupt.
pcbview 1.22.0 — VR
VR mode
pcbview now renders to an OpenXR headset. Developed against a PSVR2 over
SteamVR; anything OpenXR should work, though nothing else has been tried.
VR mode is on the menu bar. Toggling it rebuilds the viewport, because
OpenXR wraps Vulkan instance and device creation and so has to be running
before either exists — the board, camera and explode state carry across.
What is in it:
- Stereo rendering at the runtime's own per-eye resolution, with the
asymmetric per-eye frusta the headset actually reports. - A submitted depth layer (
XR_KHR_composition_layer_depth), so a dropped
frame is reprojected by geometry rather than slid about as a flat sheet. - The hidden-area mesh (
XR_KHR_visibility_mask), so the corners the lenses
never show are not shaded. - Fixed foveation via
VK_KHR_fragment_shading_rate, and a quality ladder
that trades ray count, shading rate and render resolution against a
measured cost model to hold 90 Hz. - Sense controller grips: reach out and take hold of the board.
Controls
The pad works the same on a monitor and in the headset, so there is one set
to learn:
L1 / R1 |
shrink / grow the board |
L2 / R2 |
push further / bring nearer (pressure-proportional) |
Hold ✕ + L2/R2 |
collapse / explode the stack |
| D-pad | quarter-turns — up/down tumble, left/right spin |
Hold □ + D-pad |
fit / iso / top / bottom, labelled on screen |
Explode moved onto a chord. It used to be L2/R2 alone, until a zoom
control briefly shared those triggers and every attempt to zoom quietly
peeled the stack apart — reported, in good faith, as the silkscreen floating
above the board and the mask turning transparent. The controller map in the
README is updated to match.
Fixed
-
Close-range instability in the headset. The board's face appeared to
jump and swim when approached, on the lit side but not the shadowed one.
The cause was an unbounded shadow ray: on the lit side it traversed the
whole acceleration structure, on the dark side it terminated on the first
hit, so the cost was wildly asymmetric and the frame rate fell exactly
where the geometry was most detailed. The ray is now capped by range. -
The VR readout was unreadable. Not for any of the reasons first
guessed. The panel was drawn at a fixed distance across a board at arm's
length, which put about 7 degrees of vergence between the text and what it
was written on — more than ten times what can be fused, so whichever one
the eyes settled on, the other doubled. It now sits at the board's own
depth, latched when it appears so it holds still while it is read. -
Effects did not reach the headset. Entering VR builds a new renderer,
and the appearance settings were being pushed in a race against its
creation. Losing that race left the headset on the renderer's defaults,
which read as the chips going matte in VR. -
The status bar claimed "ray tracing" while path tracing was running,
which is a small thing that misled a real diagnosis for several rounds. It
reports the actual render mode now.
Known
- The quality ladder can change render resolution several times in quick
succession as the board moves through the view. Each change rebuilds the
per-eye targets and costs a few milliseconds, so it is visible as an
occasional hitch rather than as a dropped frame. Being worked on. - Path tracing in the headset is slow, and SteamVR does not enjoy it.
Ray-traced raster is the mode to use in VR. - No OpenXR action manifest is shipped yet, so controller bindings are not
rebindable from SteamVR's own UI.
pcbview 1.21.0 — Controllers, and the board as a real object
Controllers, and the board as a real object
Controller support
pcbview now takes a gamepad. A DualSense or Xbox pad is picked up automatically
when connected, hot-plug works mid-session, and buttons are read by position, so
one map serves both: ✕ ○ □ △ and A B X Y mean the same thing.
Right stick turns, left stick pans, L1/R1 zoom, and L2/R2 explode and
collapse the stack — those two are analogue, so pressing harder peels faster.
Face buttons pick Fit, Iso, Top and Bottom. Options/Start recentres.
Hold and turn. Hold the DualSense touchpad and physically twist the pad, and
the board turns with it, 1:1 — twist 30°, it turns 30°. Nose up and down
pitches, twisting it like a steering wheel turns it left and right, and turning
it flat flips it to the other side. The gyro's zero-rate offset is measured and
subtracted continuously while you're not holding, so the board is dead still
until the pad actually moves. Needs a pad with a gyro; an Xbox pad has none.
The board is an object now
The board has a real pose of its own, independent of the camera, and there are
two ways to move things:
- View mode (default) moves the camera around a stationary board. Its
shading stays put and the sky sweeps past — you are walking around a lit
object. - Object mode (
Shiftwith the mouse,R3on a pad) turns the board
while the camera holds still. The sky doesn't move and light sweeps across the
board as it turns — you are handling it. Only here can the board be slid
through space with a middle-drag.
Home, the View menu, or Start on a pad recentres: board square-on at the
origin, view framed.
The sun is fixed in the world now rather than travelling with the viewer, which
is what makes the difference visible — and it removes an old wart, because
turning the board over presents its underside to the light instead of leaving
bottom views murky.
Showcase
A Move board checkbox plays the very same playlist as object motion or as
camera motion. Checked, the board turns and light travels across it, which is
usually the better look for a recorded video. Existing playlists, recorded
custom moves and saved templates are untouched and work either way.
Fixes
- KiCad importer: back-side text applied
(justify mirror)twice, rendering
mirrored designators on some boards. - Bottom views in path-traced mode rendered murky with the sun glaring in frame.
Controller artwork by AL2009man (Gamepad Asset
Pack, MIT). Gamepad support is
built on SDL3 (zlib), input subsystem only.
pcbview 1.20.0 — Showcase & video
Showcase & video
pcbview can now produce a full product video of your board, end to end.
Showcase playlists
- Showcase dock: stack views into a playlist — Top/Bottom/Iso holds, explode levels (0–100%), and 360°/180° spins on every axis (spin, twist, flip, tumble) in both directions.
- Zoom steps: fly the board to a percentage of its framed size over a chosen duration (25%–200% presets or custom). Zooms stay pinned to the board — the camera re-centres as it closes in, angles untouched.
- Custom moves: record your own camera movement (drag, zoom, explode) as a playlist step — toggle with Ctrl+Shift+R anywhere in the app. Playback is smoothly interpolated.
- Templates: save the current playlist under a name and reuse it later. Templates carry the custom moves they reference, so they're self-contained.
- Playlist editing: drag to reorder, double-click or right-click to retime, right-click to delete; loop N times or repeat forever.
Video recording
- Record… renders the playlist to MP4 — H.265 through the GPU encoder when available, H.264 fallback. Choose resolution (window, 1080p, 1440p, 4K, or exact custom size), frame rate (24/30/60), and quality.
- Every frame is fully converged and denoised before it is encoded, on a fixed virtual clock — motion is exact at any frame rate.
- Recording renders offscreen at the target resolution regardless of window size, with a pipelined GPU capture ring: an 8-second 720p clip renders in under 10 seconds.
- Viewport aspect presets (16:9, 21:9, 1:1, 9:16, custom) under View → Viewport size.
Fixes
- Bottom view now uses the industry left-right flip convention, so bottom-side silkscreen reads correctly.
- KiCad importer: back-side text honoured
(justify mirror)twice, rendering mirrored designators on some boards. Fixed. - Nets: Clear button and Esc de-select highlighted nets.
Scripting hooks: PCBVIEW_SHOWCASE="iso:2;explode:100:2;spin:yaw,360:8" plays a playlist on launch; add PCBVIEW_RECORD="out.mp4|1920x1080|30|h265|0" for a headless render.
pcbview 1.19.1 - net de-select quality-of-life
pcbview 1.19.1 — quality-of-life fix over 1.19.0
Fixed
- De-selecting nets is now discoverable. Clearing all net highlights previously required knowing to click bare laminate on the board; the nets panel itself offered no way back to "nothing selected". Three routes now, all equivalent:
- a Clear button beside the net filter, shown while any net is highlighted;
- Esc in the viewport (measure mode keeps its existing Esc meaning of restarting the measurement);
- Esc while the nets panel has focus.
Everything from 1.19.0 — the ODB++, IPC-2581, Altium .PcbDoc and IPC-D-356 importers, importer text rendering, negative-layer planes, and panel view — is included.
pcbview 1.19.0 - every major exchange format
pcbview 1.19.0 — every major exchange format
pcbview now opens boards in six formats: KiCad, Gerber/Excellon, and — all new in this release — ODB++, IPC-2581, Altium .PcbDoc, and IPC-D-356 netlists. Every new importer was cross-validated against independent references on real boards (copper areas within 0.5%, net tables matching exactly).
New importers
ODB++ (.tgz, .tar.gz, .zip, or job folder)
- Full product-model import: matrix, features (all standard pad symbols plus user-defined symbols), profile, drills with plating, and real per-feature nets from eda/data — net highlighting and routed lengths work immediately.
- Member files compressed as
.gzor.Z(Unix compress) are handled transparently. - Negative layers render as what they are: a plane sheet over the profile with the layer's features as clearances.
- Panel jobs: step-repeat blocks expand into the full panelization. The board step opens by default; set
PCBVIEW_ODB_STEP=<step>to view the panel.
IPC-2581 (.xml, .cvg)
- Dictionary primitives, per-Set nets, contour planes, span-referenced drill holes — and the real stackup: IPC-2581 is the only format pcbview reads that ships actual layer thicknesses, so the board build-up is exact instead of derived.
Altium Designer (.PcbDoc)
- Reads the native binary format directly (record layouts adapted from KiCad's GPL importer; the OLE container via Microsoft's compoundfilereader). Tracks, arcs, vias, pads (all shapes incl. roundrect), regions, polygon pours, blind/buried vias, real stackup thicknesses, and nets.
- Internal plane layers render as true negative layers — a net-tied copper sheet with pullback and via clearances (KiCad's own import draws plane primitives as positive copper; pcbview shows the plane itself).
- Soldermask is derived from pads and vias with tenting flags honoured.
- Validated against KiCad's importer on real boards: identical net tables, track counts, and routed lengths to three decimal places.
IPC-D-356 netlists (.ipc, .356, .d356)
- A netlist riding with a netless Gerber package supplies real net names as test points; Infer nets then binds those names to the copper — and reports opens (one net across unconnected copper, the pieces named
NET#2,NET#3) and shorts (two nets in one copper group) as findings.
Text
- Boards imported from Altium and ODB++ now keep their silkscreen lettering: designators, labels, and titles render through the Newstroke engine. Altium designator/comment visibility flags are honoured, so hidden part numbers stay hidden.
Fixed / improved
- Gerber X2: plane-connectivity readout now distinguishes "joined through pour/plane copper" from "no track route".
- Primitives on unmapped Altium layers are reported (one summary line) instead of silently dropped.
- The CI test suite grew from 6 to 14 test groups and now imports real KiCad demo boards in gerber, ODB++, and IPC-2581 form on every push.
Full commit log: v1.18.1...v1.19.0