OCCT visualization → Metal: research findings
Research-only document scoping what it would take to render OCCT geometry on Apple’s Metal API, and which of three concrete paths makes the most sense for the OCCTSwift / OCCTSwiftViewport stack.
TL;DR
Three real paths exist; one is already deployed.
- Path A. Full TKMetal driver port (replace
TKOpenGlwith a newGraphic3d_GraphicDriversubclass). Multi-year effort, high maintenance burden, but full AIS surface fidelity and visionOS-native. - Path B. Mesh-extraction + native Metal, which is what
OCCTSwiftViewportalready does today. Working now on macOS / iOS, no OCCT visualization toolkit dependency. Doesn’t give youAIS_InteractiveContextsemantics (selection→topology, manipulators, dimensions). - Path C. AIS-bridge layer on top of Path B. Keep OCCT visualization off in the xcframework; build the high-value AIS-equivalent functionality (selection-from-topology, manipulator widgets, dimension annotations) as a Swift layer over
OCCTSwiftViewport’s existing Metal renderer. ~80% of AIS value at ~10% of TKMetal effort.
Recommendation: don’t port TKOpenGl to TKMetal. Extend Path B with Path C. Visualization stays out of the OCCTSwift xcframework; the Metal rendering surface stays in OCCTSwiftViewport; new AIS-equivalent features become Swift code on top.
OCCT visualization architecture today
OCCT’s visualization is layered across three toolkits, each in Sources/Visualization/ of the OCCT tree:
| Toolkit | Layer | Role |
|---|---|---|
| TKV3d | High-level | AIS_InteractiveContext, AIS_Shape, AIS_Trihedron, AIS_Manipulator, etc. application-facing object model. |
| TKService | Mid-level | Platform-independent primitive arrays (points, segments, triangles, fans), graphic structures, the abstract Graphic3d_GraphicDriver interface. Also Aspect_, Quantity_, PrsMgr_, SelectMgr_, StdSelect_, V3d_. |
| TKOpenGl | Low-level | The only concrete Graphic3d_GraphicDriver implementation in OCCT. ~50k+ lines of GL/GLES code: shader compilation, texture binding, buffer management, render passes, picking buffers, ray tracing, PBR, shadows, transparency sorting. |
We currently set BUILD_MODULE_Visualization=OFF and USE_OPENGL=OFF / USE_GLES2=OFF in Scripts/build-occt.sh, so the OCCTSwift xcframework ships none of these toolkits. OCCTSwift is a pure modeling kernel; visualization is OCCTSwiftViewport’s job.
The driver interface
Graphic3d_GraphicDriver is designed to be subclassed. The doc explicitly notes “potential for new Graphic3d_GraphicDriver implementations using other graphic APIs”. TKD3DHost is a precedent, but it isn’t a standalone driver, it’s a glue layer that wraps a TKOpenGl viewer in a Direct3D9 host surface. The cleanest historical example shows OCCT doesn’t ship a fully-parallel driver implementation; the abstraction surface has only ever had one concrete consumer.
What’s hardcoded to OpenGL
Quick spot check inside TKOpenGl: GLSL shaders for Phong + PBR + ray-tracing renderers, fixed-function pipeline state translation, framebuffer object management, multisample depth peeling for transparency, GPU pick buffer, environment cubemaps, shadow maps, FXAA. Every one of those would need a Metal-native equivalent in TKMetal.
OCCT roadmap signals
- No Vulkan, no Metal in active development. As of OCCT 8.0.0-beta1 (May 2026):
- Zero open PRs mentioning Vulkan in
Open-Cascade-SAS/OCCT. - Zero issues mentioning Metal renderer.
- No experimental branches.
- Zero open PRs mentioning Vulkan in
- OCCT maintainer Dmitrii Pasukhin on the forum (Future of OpenGL on Macs): “OCCT have plans to support Vulkan. It will be not so soon, but on long term plan we plan to support that renderer.”
- The OCCT visualization page does say the 3D Viewer “might change considerably in the future with implementation of new features, improvements and adaptations to other graphic libraries like Vulkan”, but with no commitment to a date.
- CADRays (sibling Open-Cascade-SAS project) provides a separate GPU ray tracer for OCCT models, it isn’t a Metal port either.
If you want OCCT-on-Metal, you build it. Don’t expect upstream.
Apple platform reality
| Platform | OpenGL status | Native Metal | Vulkan via MoltenVK |
|---|---|---|---|
| macOS 26 | Deprecated since 10.14 (2018), still works via Apple’s GL-on-Metal compat shim | Yes | Yes (production-quality) |
| iOS 26 | GLES deprecated since iOS 12, still works via compat | Yes | Yes |
| visionOS | Not natively supported. OpenGL ES exists only as the WebGL2 base in Safari. App-level GL apps don’t run. | Yes (only path) | MoltenVK 1.3 added visionOS in 2025 (preview-class) |
| tvOS | Same as iOS | Yes | Yes |
visionOS is the forcing function for any move beyond OpenGL. OCCT’s TKOpenGl currently won’t run there at all without a translation layer, and Apple has been clear they won’t add native GL for new platforms.
We currently ship xros-arm64 and xros-arm64-simulator slices in OCCT.xcframework (v0.167.0), but those slices contain only the modeling kernel because we built with BUILD_MODULE_Visualization=OFF. If we wanted AIS_InteractiveContext on visionOS, today we have nothing.
Path A. Full TKMetal driver
Approach: subclass Graphic3d_GraphicDriver, mirror the TKOpenGl public surface in Metal terms.
Scope of work
- Shader translation: every GLSL shader in TKOpenGl becomes MSL. Phong, PBR (metal-roughness), shadow map, post-process, ray-tracing kernels, picking. Either a manual rewrite or an automated path via spirv-cross / Naga.
- Resource model: GL buffers/textures → Metal
MTLBuffer/MTLTexturewith discrete heap management. - Render passes: GL framebuffers → Metal
MTLRenderPassDescriptor. - Command encoding: Metal’s modern explicit-encoder model has no GL equivalent, large architectural rewrite of the inner render loop.
- Picking: GPU-side ID buffer with Metal imageblock memory (Apple TBDR-friendly).
- Selection BVH: re-use
SelectMgr_/StdSelect_from TKService unchanged. - Transparency: depth-peeling implementation in Metal.
- Ray tracing: optional. MetalRT exists for hardware ray tracing; mapping from OCCT’s
OpenGl_View::raytraceis non-trivial. - Environment maps, FXAA, anisotropic textures, line stipple emulation: lots of small features each requiring a Metal port.
Effort estimate
Realistic range: 6–18 person-months for a usable subset, multi-year for production parity with current TKOpenGl. Comparable porting efforts:
- VTK WebGPU backend (Kitware, 2024–): ongoing multi-year project, year 1 covered only polydata mappers; composite, glyph, volume, surface-LIC mappers still TBD.
- Skia Metal backend: Google has a dedicated team, took years to reach parity with the GL backend.
- Filament: ~2-year effort to ship Metal alongside GL/Vulkan, and Filament is a much smaller surface than OCCT’s viz layer.
Maintenance burden
OCCT releases land roughly twice yearly (8.0.0 in May 2026 after 7.9.x). Each release touches TKOpenGl. A downstream TKMetal would need to track those changes, an ongoing tax, not a one-shot.
Pros / cons
Pros
- Full AIS surface preserved on Apple platforms including visionOS.
- Same OCCT app code runs cross-platform with platform-specific drivers.
- Upstream-friendly, could potentially be contributed back.
Cons
- Largest possible scope.
- Highest technical risk (Metal/GL architectural mismatch around resource state, command encoding).
- Locked into OCCT’s release cadence for backports.
Path B. Mesh-extraction + native Metal (current)
Approach: OCCTSwift extracts triangulation (Mesh, Triangulation, Polygon3D) from B-Rep shapes; OCCTSwiftViewport renders those meshes natively in Metal.
What OCCTSwiftViewport already provides
From the README of gsdali/OCCTSwiftViewport:
- Metal renderer with Blinn-Phong shading, 3-light setup, shadow maps, environment mapping
- Camera systems: arcball / turntable / first-person, with inertia and animation
- ViewCube: 26-region clickable orientation widget
- GPU picking via TBDR imageblock-based pick ID buffer (body and face selection)
- Display modes: wireframe, shaded, shaded-with-edges
- Lighting presets:
.threePoint,.studio,.architectural,.flat - Gesture presets:
.default,.blender,.fusion360 - Section / clip planes
- Distance, angle, radius measurement overlays
- Adaptive instanced dot grid + RGB axis lines
- Swift 6
Sendableconformance,@MainActorisolation - iOS 18+ / macOS 15+
What it doesn’t do
- No
AIS_InteractiveContext-equivalent: app code holds the(Shape, ViewportBody)mapping itself. When Metal picking returns a face ID, the app has to look up whichTopoDS_Faceof whichShapethat came from. - No standard OCCT widgets:
AIS_Trihedron,AIS_Manipulator,AIS_Plane,AIS_Axis,AIS_PointCloud, dimension-annotation primitives, none of these exist as ready-made objects. - No ray-tracing renderer: TKOpenGl has one; OCCTSwiftViewport currently rasterizes only.
- No PBR material editor surface (Blinn-Phong + light presets only).
- No visionOS slice yet: OCCTSwiftViewport currently builds for macOS 15 / iOS 18.
Pros / cons
Pros
- Already shipped, working, low maintenance.
- Native Metal, clean visionOS path once the slice is added.
- No coupling to OCCT release cadence.
- Renders only what the app cares about; pure Apple stack.
Cons
- App code carries the topology-to-pick-id mapping.
- Standard CAD widgets (manipulators, dimensions, trihedrons) don’t exist; each is an app-level project.
Path C. AIS-bridge on OCCTSwiftViewport (recommended)
Approach: keep OCCT visualization OFF in the xcframework. Build the high-value parts of AIS_InteractiveContext as a Swift layer on top of OCCTSwiftViewport’s Metal renderer.
What you’d build
A new product (call it OCCTSwiftAIS, sitting alongside OCCTSwiftTools):
Your App
├── OCCTSwift (geometry kernel)
├── OCCTSwiftViewport (Metal rendering, no OCCT)
├── OCCTSwiftTools (Shape ↔ ViewportBody bridge)
└── OCCTSwiftAIS (NEW, AIS-equivalent layer)
├── InteractiveContext (selection / hover / highlight, topology-aware)
├── ManipulatorWidget (translate / rotate gizmos in Metal)
├── DimensionAnnotation (linear / angular / radial overlays)
├── PresentationStyle (highlighted, hover, dimmed, ghosted)
└── Trihedron / Plane / Axis / PointCloud standard objects
Each of these is pure Swift logic over already-extracted topology metadata + Metal rendering primitives provided by OCCTSwiftViewport. The hard parts (vertex pipeline, lighting, shadow mapping, GPU picking) are already done; OCCTSwiftAIS adds the “this pick result is topoFace[7] of shape[3], highlight it” semantics.
Effort estimate
1–3 person-months for the headline features:
InteractiveContextand selection-from-topology: 2–3 weeks- Manipulator widget (translate/rotate, with snap): 2–3 weeks
- Dimension annotations (linear, angular, radial; placement, leader lines, labels): 3–4 weeks
- Standard objects (trihedron, plane, axis, point cloud): 1–2 weeks total
- Hover/highlight/ghost styling: 1 week
- Polish, docs, examples: 2 weeks
Pros / cons
Pros
- Keeps the existing clean architecture (OCCTSwift = kernel, OCCTSwiftViewport = renderer).
- Native Metal everywhere, including visionOS once OCCTSwiftViewport adds the slice.
- Decoupled from OCCT release cadence, when OCCT 8.1 lands we don’t have to re-port a Metal driver.
- Each feature is independently shippable; you can prioritise (selection first, manipulator second, dimensions third).
Cons
- Not source-compatible with
AIS_InteractiveContext-using OCCT C++ apps. OK for our stack, we’re Swift-first. - Doesn’t get OCCT’s ray-tracing renderer for free. (Probably not needed for interactive CAD anyway.)
- Some duplication: the selection BVH logic in
SelectMgr_/StdSelect_would have to be re-implemented in Swift on top of the topology metadata we already extract.
Other paths considered and rejected
Path D. MoltenVK + OCCT-Vulkan
Build an OCCT Vulkan backend, run on Apple via MoltenVK.
- Blocker: OCCT doesn’t have a Vulkan backend. If we wrote one, we’d be doing Path A’s effort for Vulkan instead of Metal, same scope, more dependencies.
- MoltenVK on visionOS is preview-class as of late 2025; production risk is high.
- Skip.
Path E. ANGLE-Metal
Route TKOpenGl’s GLES calls through Google’s ANGLE Metal backend.
- ANGLE Metal backend exists and is active (Apple/Google collaboration upstreaming WebKit’s branch). MetalANGLE (the standalone fork) is unmaintained as of 2023.
- ANGLE supports GLES 3.0 mostly; 3.1+ not fully. TKOpenGl uses GLES 3.0+ features.
- No documented visionOS support for either ANGLE or MetalANGLE.
- Performance penalty from translation layer.
- Skip unless OCCT picks this up officially, and they haven’t.
Path F. WebGPU (Dawn / wgpu)
Use WebGPU as the cross-platform abstraction (it sits over Metal, Vulkan, D3D12).
- VTK is doing this, multi-year effort. Apple Safari supports WebGPU.
- Same scope as Path A, replace TKOpenGl entirely with TKWebGPU.
- Doesn’t avoid the work; just changes which abstraction we target.
- Interesting if we ever needed WebAssembly support; out of scope for an Apple-only Metal goal.
- Skip for now.
Recommendation
| Question | Answer |
|---|---|
| Should we port TKOpenGl to TKMetal? | No. Multi-year, high-risk, mostly duplicates OCCTSwiftViewport. |
| Should we ship visionOS visualization support? | Yes, via OCCTSwiftViewport. Add the visionOS slice to that repo. |
What’s missing from our current stack vs. OCCT’s AIS_InteractiveContext? | High-level scene objects, selection-from-topology mapping, manipulator widgets, dimension annotations. |
| What’s the cheapest way to fill that gap? | Path C, OCCTSwiftAIS as a Swift layer on top of OCCTSwiftViewport. ~1–3 person-months. |
Concrete next step (when ready)
When the user wants to start the AIS layer:
- Create
OCCTSwiftAISrepo (or a new product inside OCCTSwiftViewport, adjacent toOCCTSwiftTools). - Start with selection-from-topology: an
InteractiveContextSwift API that takes aShape+ extractedViewportBodyand exposespickFace(at: CGPoint) -> TopoDS_Face?-style queries via OCCTSwiftViewport’s existing GPU picking buffer. This is the single highest-value missing piece. - Add manipulator widget next, biggest visible win for user-facing CAD apps.
- Defer dimension annotations and standard-object widgets until there’s a concrete consumer (e.g.
UnfolderortemplotUX) asking for them.
This path keeps our architecture clean, keeps OCCTSwift’s xcframework at modeling-kernel-only (no GL dependency anywhere), and gives us full Apple platform reach including visionOS without a multi-year TKMetal project.
Sources
- OCCT visualization toolkit (TKV3d / TKService / TKOpenGl) docs
- OCCT Forum, Future of OpenGL on Macs (Pasukhin Vulkan-roadmap quote)
- OCCT Forum, Ray tracing as alternative rendering method
- OCCT GitHub, Open-Cascade-SAS/OCCT (no Vulkan PRs / Metal issues as of 2026-05-02)
- Apple, OpenGL deprecation across all OSes (2018)
- Apple Developer Forums, OpenGL on future iPhones and Macs
- Hacker News, visionOS doesn’t support OpenGL
- MoltenVK, Vulkan-on-Metal translation layer
- ANGLE, Google’s GL/GLES translation layer (Metal backend in active development with Apple)
- MetalANGLE, unmaintained since 2023
- VTK WebGPU port, multi-year ongoing effort
- OCCTSwiftViewport, current Metal renderer