1 of 24

Differentiable Meshing and Rendering

CMSC 498Z · DIFFERENTIABLE PROGRAMMING

DMesh (NeurIPS 2024) and its successor, DMesh++

Richard Chen · Tuesday, October 27, 2026

2 of 24

The plan for this lecture

TODAY

01

The problem

Why a mesh’s connectivity blocks gradients, and the old workarounds.

02

DMesh

Turning “does this face exist?” into a smooth probability.

03

DMesh++

A cheaper test that scales to hundreds of thousands of points.

04

Analysis

What the meshes still can’t do, then discussion.

DMesh & DMesh++ · Richard Chen · 2

3 of 24

Why meshes resist gradients

PART 1 · THE PROBLEM

A mesh is two things: where the vertices are, and which triangles connect them.

Positions are continuous. Nudge a vertex and the loss changes smoothly.

Connectivity is discrete. A face is in or out, so it has no gradient.

And it explodes. Possible connectivities grow exponentially with the number of points.

Same four points, different faces. No small nudge gets from the left mesh to the right one: it’s a jump.

DMesh & DMesh++ · Richard Chen · 3

4 of 24

Three earlier workarounds

PART 1 · THE PROBLEM

Route

Examples

What breaks

Keep the topology fixed, move the vertices

Template meshes, continuous remeshing

Can’t change genus or global connectivity

Learn a field, then extract a surface

Neural SDFs, DMTet, FlexiCubes

Mostly closed surfaces; dense meshes; soft sharp edges

Predict connectivity with a network

MeshGPT, MeshAnything

Outliers and self-intersections

DMesh’s approach: make the connectivity itself differentiable.

DMesh & DMesh++ · Richard Chen · 4

5 of 24

A quick primer: Delaunay and power diagrams

PART 2 · BACKGROUND

Delaunay rule: the circle through any triangle’s corners (dashed) contains no other point.

Delaunay triangulation

Connect points so every triangle’s circumcircle (circumsphere in 3D) is empty. Result: well-shaped triangles, no crossings.

Weighted version

Give each point a weight w and measure with the power distance below. A heavy point claims more space; a light one can vanish.

π(p, q) = |p − q|² − w_p − w_q

Power diagram (the dual)

Each point owns the region closest to it in power distance. Two points are joined exactly when their regions touch.

DMesh & DMesh++ · Richard Chen · 5

6 of 24

Every face gets a probability

PART 2 · DMESH

Λ(F) = Λ_wdt(F) × Λ_real(F)

Each point = 5 numbers

Position (x, y, z), a weight w, and a “real” value ψ between 0 and 1.

Λ_wdt: a candidate?

Does F appear in the weighted Delaunay triangulation of the points?

Λ_real: on the surface?

Are F’s corners marked real? The final mesh keeps faces where both tests pass 0.5.

Only per-point numbers are optimized, so gradients reach positions, weights and ψ, and the topology changes as the points move.

DMesh & DMesh++ · Richard Chen · 6

7 of 24

The real part and the imaginary part

PART 2 · DMESH

2D version: teal edges are the shape (real); thin gray edges only hold the tessellation together (imaginary). Teal dots have ψ ≈ 1.

Fill the space. The weighted Delaunay triangulation splits the whole convex domain into tetrahedra.

Pick a subset. The mesh is just the faces marked real; the rest is scaffolding that gets thrown away.

Free guarantee. Triangulation faces never cross, so the mesh can’t self-intersect.

Any shape. Open, closed, even non-orientable surfaces like a Möbius strip.

DMesh & DMesh++ · Richard Chen · 7

8 of 24

Making both tests smooth

PART 2 · DMESH

Λ_wdt: how close is F to being in?

Using the power diagram (the triangulation’s dual), measure a signed distance τ: positive if F is in, negative if not.

Λ_wdt = mean σ(α_wdt · τ)

About O(N) instead of O(N²) for the earlier differentiable triangulation (Rakotosaona et al. 2021).

Λ_real: are the corners on the surface?

Λ_real = min(ψ₁, ψ₂, ψ₃)

A differentiable min. Lowering one point’s ψ switches off every face around it without moving anything.

The temperature α sets how sharp the soft decision is: the same continuous-relaxation trade-off from lecture.

DMesh & DMesh++ · Richard Chen · 8

9 of 24

Faster and more reliable than the earlier method

PART 2 · DMESH

Points (2D)

Previous: time

DMesh: time

Previous: missed edges

DMesh: missed edges

1K

139 ms

108 ms

49.9%

0%

3K

739 ms

111 ms

49.9%

0%

10K

4,376 ms

116 ms

49.9%

0.08%

30K

—

125 ms

—

0.29%

Times are for triangles in 2D; missed edges are existing edges scored below 0.5, the case like surfaces in 3D. Previous = Rakotosaona et al. 2021, both in PyTorch (DMesh, Appendix Table 4).

Scales flat: ~110–125 ms from 1K to 30K points. The old method ran out of memory at 100K.

Honest catch: under ~1K points the old method is faster, since DMesh must build the power diagram first.

DMesh & DMesh++ · Richard Chen · 10

10 of 24

One representation, three kinds of input

PART 2 · DMESH

A mesh

Push Λ up on the true faces and down on every other face. A check that the representation can express real meshes.

A point cloud

Expected Chamfer distance: sample points from faces, each weighted by its face’s probability.

Multi-view images

Render each face with Λ as its opacity and compare to the photos with an L1 loss.

PLUS THREE REGULARIZERS

Weight: simplify the triangulation, fewer vertices

Real: neighbors agree on ψ, which fills holes

Quality: penalize thin, sliver triangles

DMesh & DMesh++ · Richard Chen · 11

11 of 24

From images: two phases, two renderers

PART 2 · DMESH

Phase 1 · move everything

Positions, weights and ψ all update

Renderer A sorts see-through faces in screen tiles, like Gaussian splatting, averaged 50/50 with nvdiffrast for edge gradients. Its depth order is approximate, which leaves false inner faces.

Phase 2 · pick faces

Freeze the triangulation, update ψ only

With positions and weights fixed, Λ_wdt is exactly 0 or 1. Renderer B walks each ray tetrahedron to tetrahedron: exact depth order, low memory.

Start: a 20×20×20 grid of points for images; for point clouds, samples plus Voronoi vertices, which sit near the medial axis.

Coarse to fine: 4 epochs, resampling 1K → 3K → 10K points from the current mesh.

Clean-up rule: a face survives only if a point on one side has ψ = 0, which deletes hidden inner faces.

DMesh & DMesh++ · Richard Chen · 12

12 of 24

What the regularizers actually do

PART 2 · DMESH

Weight regularization

λ_weight

CD ↓

Faces

10⁻⁶

7.48

4,753

10⁻⁵

8.08

2,809

10⁻⁴

10.82

1,786

A true trade-off: 60% fewer faces costs 45% more error, plus holes and bumps at the high end.

Quality regularization

λ_qual

CD ↓

Faces

Aspect ↓

10⁻⁴

7.60

8,266

2.33

10⁻³

7.42

8,349

2.06

10⁻²

7.28

10,806

1.55

No trade-off in error: nicer triangles and lower CD, but more faces and more holes.

Point-cloud reconstruction, each regularizer tested with the other switched off (DMesh, Appendix E.3, Tables 5 and 6).

DMesh & DMesh++ · Richard Chen · 13

13 of 24

Results: compact and accurate, but slow

PART 2 · DMESH

>99%

of faces recovered when converting the Stanford bunny, dragon and Buddha

<1%

false faces added in the same test

Method

Input

CD ↓

Vertices

Time

Poisson (PSR)

points

690

159K

10.6 s

NDC

points

3.61

20.7K

3.49 s

DMesh

points

3.36

3.56K

743 s

FlexiCubes

images

273

10.9K

56 s

DMesh

images

34.6

4.19K

1,434 s

Chamfer distance ×10⁻⁵, averaged over 11 closed, open and mixed models (DMesh, Table 2).

DMesh & DMesh++ · Richard Chen · 14

14 of 24

Where DMesh falls short

PART 2 · DMESH

Slow

The triangulation runs on the CPU (CGAL), step by step. Over a second for 100K points, and it can’t be parallelized.

No manifold guarantee

Faces are switched on independently, so stray non-manifold edges appear.

Patchwork renderer

Two partially differentiable renderers. The first leaves false inner faces that a post-processing rule deletes.

Low resolution

A few thousand vertices per shape; fine detail on closed surfaces is lost.

DMesh++ goes after the first problem, and that also fixes the last one.

DMesh & DMesh++ · Richard Chen · 15

15 of 24

Replace the triangulation with a Minimum-Ball test

PART 3 · DMESH++

Dashed gray: rejected, a point sits inside its smallest ball. Solid teal: accepted, its ball is empty.

Drop the weight. Each point is now (x, y, z, ψ).

New rule. A face counts if the smallest ball through its corners holds no other point.

d = dist(center, nearest other point) − radius

Λ_min = σ(α_min · d)

Same guarantees. Every such face is a Delaunay face, so still no self-intersections and few thin triangles. Λ = Λ_min × Λ_real.

DMesh & DMesh++ · Richard Chen · 16

16 of 24

Why it’s so much faster

PART 3 · DMESH++

32×

faster face probabilities in 3D (16× in 2D)

75%

less GPU memory in 3D (96% less in 2D)

168 ms

for 200K points in 3D (117 ms in 2D)

Local instead of global

Each face only needs a nearest-neighbor search, which runs in parallel on the GPU. The triangulation was sequential. Roughly O(N) → O(log N) per face.

Cache the neighbors

Neighbors barely change between steps, so they’re cached and refreshed every 50 steps during reconstruction.

DMesh & DMesh++ · Richard Chen · 18

17 of 24

The reconstruction loop

PART 3 · DMESH++

Step 1

Initialize

A regular grid, or the input point cloud if there is one.

Step 2

Move points

Optimize positions with ψ fixed, using a Chamfer or image loss.

Step 3

Pick faces

Optimize ψ with positions fixed; drop faces no camera sees.

Step 4

Subdivide

Insert edge midpoints for detail, then repeat, coarse to fine.

A better renderer

Anti-aliased triangle edges give visibility gradients that DMesh’s renderer lacked, so shapes can actually slide into place.

Extra per-point features

Points can carry color, blended across each face, to reconstruct textured shapes.

DMesh & DMesh++ · Richard Chen · 19

18 of 24

Results: point clouds, 2D and 3D

PART 3 · DMESH++

Method

CD closed

CD open

F1 closed

F1 open

Poisson

12.1

16.3

0.47

0.45

PoNQ

2.44

7.86

0.48

0.45

DMesh

2.82

3.29

0.25

0.22

DMesh++

0.37

0.37

0.48

0.47

3D, 500 random Thingi10K models, half closed and half open; 200K input points; CD ×10⁻⁴ (DMesh++, Table 3).

Others get worse on open surfaces; DMesh++’s error stays the same.

2.6×

faster than DMesh on 2D fonts (11.3 s vs 30.4 s), with lower error (1.82 vs 1.97 ×10⁻⁶)

~1M

edges in complex 2D drawings; DMesh ran out of GPU memory on them

DMesh & DMesh++ · Richard Chen · 20

19 of 24

Results: multi-view reconstruction

PART 3 · DMESH++

Method

CD ×10⁻³ ↓

Self-intersect ↓

Non-manifold edges ↓

Faces

Time

Remeshing

0.977

0.220

0

26.5K

25 s

FlexiCubes

3.493

0.011

0

28.9K

88 s

DMesh

0.697

0

0.042

5.1K

772 s

DMesh++

0.342

0

0.025

23.7K

205 s

Average over 50 models from Thingi10K and Objaverse, 64 rendered views each (DMesh++, Table 4).

½

DMesh’s Chamfer error

4.7×

more faces, so finer detail

3.8×

faster than DMesh

DMesh & DMesh++ · Richard Chen · 21

20 of 24

Reinforce-Ball: removing points with REINFORCE

PART 3 · DMESH++

The trap

Point C sits between A and B and isn’t needed. Lower C’s probability to 0.8: faces AC and BC drop to 0.8, AB rises to 0.2. Alpha blending treats them as independent, so the ray sees 0.2 + 0.8 × 0.8 = 0.84 opacity instead of 1. The loss rises and the optimizer puts C back.

The fix

Keep each point with probability φ. Sample whole point sets (B = 1024), score each with reconstruction loss + ε × point count, and use the log-derivative trick:

∇E[L] ≈ (1/B) Σ ∇log P(Pᵢ | φ) · Lᵢ

2,793 → 152

edges on 2D fonts (ε = 10⁻⁵), CD 1.82 → 2.77

78% fewer

edges than DMesh’s weights at similar error

2D only

and slow: 200 s vs 11 s without it

DMesh & DMesh++ · Richard Chen · 22

21 of 24

What DMesh++ gave up

PART 3 · DMESH++

More non-manifold vertices

0.036 vs DMesh’s 0.002 in multi-view. The authors suspect a trade-off between expressiveness and topological errors.

No knob for mesh size

Without weights, nothing simplifies the mesh. Their fix, Reinforce-Ball (a REINFORCE-style trick), is experimental and 2D only.

Still costly on point clouds

282 s versus 4 s for Poisson reconstruction: more accurate, but far more compute.

Synthetic images only

Assumes known lighting and simple vertex colors. On real DTU photos the mesh fills with floaters.

DMesh & DMesh++ · Richard Chen · 23

22 of 24

DMesh vs DMesh++ side by side

RECAP

​

DMesh

DMesh++

Per-point numbers

position, weight w, ψ

position, ψ

Which faces can exist

weighted Delaunay (CGAL, CPU)

Minimum-Ball (GPU nearest neighbors)

Mesh-size control

weight regularization

Reinforce-Ball (2D, experimental)

Renderer

two partly differentiable renderers

anti-aliased, with visibility gradients

Multi-view CD ×10⁻³

0.697

0.342

Faces · time

5.1K faces · 772 s

23.7K faces · 205 s

Non-manifold vertices

0.002

0.036

Same core idea, a probability per face; DMesh++ trades the global triangulation for a local test.

DMesh & DMesh++ · Richard Chen · 24

23 of 24

Where this line of work is heading

PART 4 · ANALYSIS

Real photos

MeshSplatting (CVPR 2026, with Sanghyun Son) optimizes opaque, connected triangle meshes from real images, built to drop straight into game engines.

Simulation-ready meshes

HoloTetSphere (2026) found surface methods, DMesh included, often fail or fragment when turned into volume meshes for simulation.

Open problems they name

Manifold and watertight guarantees, handling self-occlusion, and generative models that learn mesh connectivity.

Natural next step: add differentiable checks for “is it a valid, physical solid?” to the same loss.

DMesh & DMesh++ · Richard Chen · 26

24 of 24

Papers and code

REFERENCES

Son, Gadelha, Zhou, Xu, Lin, Zhou. DMesh: A Differentiable Mesh Representation. NeurIPS 2024. arxiv.org/abs/2404.13445

Son, Gadelha, Zhou, Fisher, Xu, Qiao, Lin, Zhou. DMesh++: An Efficient Differentiable Mesh for Complex Shapes. arxiv.org/abs/2412.16776

Rakotosaona, Aigerman, Mitra, Ovsjanikov, Guerrero. Differentiable Surface Triangulation. ACM TOG 2021.

Held et al. MeshSplatting: Differentiable Rendering with Opaque Meshes. CVPR 2026. arxiv.org/abs/2512.06818

HoloTetSphere: Unified TetSphere Mesh Reconstruction for Physical Simulations. 2026. arxiv.org/abs/2607.08398

Code: github.com/SonSang/dmesh · github.com/SonSang/dmesh2

DMesh & DMesh++ · Richard Chen · 28