We introduce DiffBMP, a scalable and efficient differentiable rendering engine for a collection of bitmap images. Our work addresses a limitation that traditional differentiable renderers are constrained to vector graphics, given that most images in the world are bitmaps. Our core contribution is a highly parallelized rendering pipeline, featuring a custom CUDA implementation for calculating gradients. This system can, for example, optimize the position, rotation, scale, color, and opacity of thousands of bitmap primitives all in under 1 min using a consumer GPU. We employ and validate several techniques to facilitate the optimization: soft rasterization via Gaussian blur, structure-aware initialization, noisy canvas, and specialized losses/heuristics for videos or spatially constrained images. We demonstrate DiffBMP is not just an isolated tool, but a practical one designed to integrate into creative workflows. It supports exporting compositions to a native, layered file format, and the entire framework is publicly accessible via an easy-to-hack Python package.
Figures & tables
Figure 2: An illustration of the algorithm flow of DiffBMP. Our core contribution is the renderer for bitmap images, introduced in Sec. 3.1 , which enables scalable and efficient differentiable rendering using a custom CUDA kernel. Additionally, we employ soft rasterization ( Sec. 3.2.1 ) for improved gradient propagation and an initialization technique ( Sec. 3.2.2 ) for better target approximation. After optimization, a native, layered file is generated, which enables diverse post-processing creation.
2D Differentiable rendering method
Primitive type
Applications
Opacity Support
Para- llelism
Engine / Interface
Differentiable Composition by Reddy et al. [44]
Bitmap
Specialized for patterns e.g . , manipulation, tiling
✗
✗
Pytorch / Python
DiffVG [ 27 ] and its extensions [ 43 , 33 , 4 , 5 , 60 , 59 ]
Vector
Very diverse e.g . , vectorization, painterly, etc.
✓
✓
C++ / Python
DiffBMP (Ours)
Bitmap
Very diverse. e.g . , painterly, assemblage, video, etc.
✓
✓
CUDA / Python
Table 1: Comparison with Prior Work. Prior work can be broadly classified into two main categories. DiffVG [ 27 ] is high-performing and broadly applicable, but it is limited to vector primitives. Due to the difficulty of matching DiffVG’s performance using bitmap primitives, only a few studies, such as Reddy et al. [44] , have attempted implementations for specialized tasks, but their efficiency and performance fall short of DiffVG. To put simply, DiffBMP aims to be the bitmap primitive counterpart to DiffVG.
Figure 3: Blur enriches the spatial gradients of primitives. The figure displays the per-pixel gradients with respect to xi and yi for three different primitives (a), extracted during the experiments of Tab. 3 , both (b) with and (c) without applying blur ( Sec. 3.2.1 ). Color indicates the direction of the gradient, and opacity represents its magnitude on a log scale (from 10−6 to 10−3 ). Applying blur results in richer and more coherent gradients. This, in turn, leads to the better optimization results shown in Tab. 3 .
Figure 4: Heuristics for Dynamic DiffBMP. Sequential optimization ( i.e . , initializing Θf with Θf−1⋆ ) can lead to local minima, as in b , where a large primitive is stuck on the face. c shows our remedy: reducing the opacity of such overly dominant primitives, resulting in PSNR gain.
Image res / Tile size
512 × 512 / 16 × 16
1024 × 1024 / 16 × 16
1024 × 1024 / 32 × 32
2048 × 2048 / 32 × 32
PyTorch
RTX 3090
1360ms / 2337ms / 6.4 GB
5514ms / 9811ms / 12.0 GB
1393ms / 2477ms / 5.0 GB
5405ms / 9483ms / 9.0 GB
L40S
1342ms / 2413ms / 6.6 GB
4570ms / 8151ms / 12.2 GB
1423ms / 2507ms / 5.2 GB
4914ms / 8707ms / 9.2 GB
CUDA-32bit
RTX 3090
3.9ms / 11.6ms / 1.0 GB
7.2ms / 9.7ms / 2.1 GB
7.6ms / 9.3ms / 2.0 GB
16.1ms / 10.0ms / 6.1 GB
L40S
4.7ms / 2.9ms / 1.2 GB
10.5ms / 2.8ms / 2.3 GB
8.5ms / 2.9ms / 2.2 GB
23.3ms / 3.8ms / 6.3 GB
CUDA-16bit
RTX 3090
2.3ms / 6.2ms / 1.1 GB
4.2ms / 5.8ms / 1.6 GB
4.3ms / 5.5ms / 1.6 GB
9.0ms / 6.4ms / 3.8 GB
L40S
2.0ms / 2.1 ms / 1.2 GB
5.4ms / 2.3ms / 1.8 GB
4.5ms / 2.3ms / 1.8 GB
12.8ms / 3.0ms / 4.0 GB
Table 2: Per-iteration performance across implementations and resolutions. Each cell reports a triple “forward / backward / VRAM” in the order of forward runtime, backward runtime, and total VRAM usage per iteration. Rows list the compared implementations ( e.g . , PyTorch baseline and our custom CUDA kernels in FP32/FP16), and columns specify the target image resolution and tile size.
Figure 5: Our DiffBMP works well for complex SVG primitives (second row) and bitmap primitives (third row), whereas existing DiffVG [ 27 ] fails or is not available, even though it works well for simple SVG primitives (first row). Note that SVG exportation is included in runtimes for row 1-2, while bitmap exports only PNG, so the third row takes less time (36s).
SoftRas Sec. 3.2.1
SA-Init. Sec. 3.2.2
Scenario 1 (512 × 512)
Scenario 2 (512 × 512)
Scenario 3 (1024 × 1024)
✗
✗
24.4
20.6
25.9
✓
✗
24.7
21.5
26.5
✗
✓
25.5
21.0
27.1
✓
✓
25.7
21.7
27.4
Table 3: Ablation of our optimization helpers: soft rasterization ( Sec. 3.2.1 ) and structure-aware initialization ( Sec. 3.2.2 ). We report PSNR on three targets with indicating whether each component is enabled. Soft rasterization enriches gradients and yields consistent gains, while structure-aware initialization further boosts fidelity; enabling both gives the best PSNR across all scenarios.
Figure 6: Uniform noise ( Sec. 3.2.3 ) makes canvas fully covered by primitives, as shown in (c). (b) Conversely, using the canvas as white removes the need for white primitives to be positioned.
Init. Θf−1⋆
Rem. Stk.
Freez. Unch.
Frame-wise Fidelity
Anti-flicker
PSNR ↑
SSIM ↑
tLP ↓
tOF ↓
✗
✗
✗
24.19 ± 2.36
0.616 ± 0.106
7.41 ± 8.89
2.23 ± 1.10
✓
✗
✗
24.26 ± 1.73
0.629 ± 0.073
5.39 ± 4.64
1.88 ± 1.13
✓
✓
✗
24.66 ± 2.03
0.647 ± 0.088
4.98 ± 4.93
1.89 ± 1.11
✓
✗
✓
24.23 ± 2.13
0.617 ± 0.099
3.50 ± 2.52
1.91 ± 1.32
✓
✓
✓
24.38 ± 2.23
0.630 ± 0.069
3.49 ± 2.26
1.84 ± 1.19
Table 4: Dynamic DiffBMP ablations. We observed that improvements in flicker suppression can trade off with per-frame fidelity; using all three of our heuristics in Sec. 3.3.1 targets a balanced solution, having competitive fidelity and the best anti-flicker.
Figure 7: Comparison of rendered output I and primitives with spatial constraint under different settings: (a) Ours (default), (b) Ours with opacity loss, and (c) Ours with both opacity loss and re-initialization. Applying both opacity loss and re-initialization produces the best results.
Figure 8: DiffBMP can also be combined with CLIP for creation. Each caption shows the text prompt and the primitive used.
Figure S1 : Coordinate transformation and primitive sampling. Color and opacity from i -th primitive at (x,y) in canvas (black dot) is sampled from (U,V) in the primitive’s coordinate (red dot). Since U and V are not integers, bilinear interpolation from four nearest lattice points (green dots).
Figure S2 : DiffBMP computation tree (forward/backward). Forward uses premultiplied-alpha Over in front-to-back order; per-primitive opacity is a sigmoid-scaled value modulated by a template mask sampled at rotated/scaled coordinates. Learnable leaves (gray) are ci,νi,xi,yi,si,θi . Red dashed arrows indicate gradient flow. See Sec. 3.1.1 for equations.
Figure S3 : Frame-wise Fidelity Heuristic of Dynamic DiffBMP. Warm-starting from Θf−1⋆ can leave an over-dominant primitive sitting over a high-change area; rather than relocating, it gets recolored and suppresses local detail, as in b . We apply Removing Stuck Primitives : adaptively decaying the opacity of large, opaque, front-ordered strokes so finer primitives behind them take over. This restores facial detail and improves fidelity under the same budget.
Figure S4 : Anti-flicker via freezing unchanged regions. We visualize inter-frame change with an error map E=5⋅(I1−I17)+127 , where I1 is the first frame and I17 the last frame. Mid-gray ( ≈127 ) indicates no change; brighter/darker values denote larger differences. If all primitives are freely optimized, spurious updates appear even in static regions, producing widespread flicker, as seen in b . Our remedy c freezes primitives, concentrating updates only where the video truly changes.
Category
Parameter
Value / Description
Initialization
initializer
structure_aware (default for most; random for Fig. 8)
v_init_bias
−4.0 (yields σ(−4)≈1.8% initial opacity)
std_c_init†
0.02 (color initialization noise std)
variance_window_size†
7 (local variance computation window)
variance_base_prob†
0.1 (base sampling probability for low-variance areas)
max_prims_per_pixel†
100 (200 for spatially constrained cases)
Table S1 : Common hyperparameters used across experiments. These settings are applied to all experiments unless explicitly overridden in figure-specific configurations. Values marked with † come from constants.py when not specified in config files.
Table S2 : Figure-specific experimental configurations. This table shows parameters that differ across experiments, including primitive details, number of primitives ( N ), image resolution, scale range, iterations, and special settings.
Aspect
Naive PyTorch
Our CUDA
Spatial culling
None
Tile-based binning
Primitive loop
Sequential ( N )
Parallel per-pixel
Memory per iteration
O(N×HW)
O(k×HW) , k≪N
Precision
FP32 only
FP16 + FP32 mixed
Intermediate tensors
(H,W) per primitive
Small per-pixel cache
Atomic operations
Many (unoptimized)
Packed __half2
Table S3 : Comparison of naive PyTorch vs. our CUDA implementation
Figure S5 : Additional scaling statistics for the Seurat composition in (a). To expose a broader primitive size distribution, this analysis widens the allowed scale range to [2,50] while sweeping the primitive count N . Fingerprint primitives retain radial transparency as in (a). From left to right, the panels show the CDF of the normalized primitive footprint Ai/(HW) for fingerprint , the CDF of Ai/(HW) for autograph_seurat , the CDF of the primitive tile-hit degree τi for fingerprint , the CDF of τi for autograph_seurat , and the measured runtime versus N . Here, Ai denotes the area of the padded screen-space bounding box of primitive i , normalized by the image area HW . τi denotes the number of tiles intersected by that primitive.
Figure S6 : Spatial distribution of per-tile primitive density dt for the same scaling analysis setting as Fig. S5 , with scale range [2,50] and increasing primitive count N . Each heatmap visualizes the number of primitives assigned to tile t during CPU binning. The top row shows fingerprint , and the bottom row shows autograph_seurat . In each row, N∈{1000,2000,3000,4000,5000} increases from left to right. Each panel uses its own color scale for readability, so absolute density values should be interpreted using the corresponding colorbar.
Figure S7: Optimization progress across iterations for three different examples. Each row shows the evolution from iteration 1 (left) to iteration 100 (right), illustrating how coarse structure emerges early and fine details are refined in later iterations. All three rows reuse the same primitive sets and target images as the ablation study in Table 3 of the main paper, enabling direct visual comparison with the quantitative results.
Figure S8: Effect of primitive count on reconstruction quality across diverse targets and primitive types. Each row uses a different primitive set (left) to approximate a different target image (right), while columns sweep the number of primitives N from 1000 to 4000. As N increases, our optimizer consistently sharpens details and improves PSNR across movie posters, portraits, and natural scenes, demonstrating robust approximation capability over varied image content and primitive shapes.
Point-based differentiable rendering underpins modern 3D reconstruction, novel-view synthesis, and learning-based graphics pipelines, but developing new rendering methods often requires extensive low-level implementation, hardware-specific kernels, and manually written backward passes. This limits rapid prototyping, reproducibility, exploration, and deployment, especially across diverse hardware platforms. This paper presents XPR, an extensible cross-platform framework for point-based differentiable rendering. XPR introduces a high-level programming interface that separates method-specific logic from the shared rendering pipeline, allowing users to implement new methods in a few lines of code. Its pipeline decomposes rendering into modular, statically shaped parallel operations that can be lowered by a cross-platform compiler to GPUs, TPUs, CPUs, and other ML accelerators. We demonstrate implementations of 3DGS, 3DGUT, and LinPrim, with only a few 100s lines of Python code, each of which can be compiled to a range of hardware platforms with the XLA compiler. These results show that XPR enables fast experimentation and portable execution for emerging point-based differentiable rendering systems.
Steve Rhyner, Sankeerth Durvasula, Aleksandr Kovalev +7
University of Toronto · 2Vector Institute · 3Intel +1
Radiance field reconstruction aims to recover high-quality 3D representations from multi-view RGB images. Recent advances, such as 3D Gaussian splatting, enable real-time rendering with high visual fidelity on sufficiently powerful graphics hardware. However, efficient online transmission and rendering across diverse platforms requires drastic model simplification, reducing the number of primitives by several orders of magnitude. We introduce DiffSoup, a radiance field representation that employs a soup (i.e., a highly unstructured set) of a small number of triangles with neural textures and binary opacity. We show that this binary opacity representation is directly differentiable via stochastic opacity masking, enabling stable training without a mollifier (i.e., smooth rasterization). DiffSoup can be rasterized using standard depth testing, enabling seamless integration into traditional graphics pipelines and interactive rendering on consumer-grade laptops and mobile devices. Code is available at https://github.com/kenji-tojo/diffsoup.
3D Gaussian Splatting (3DGS) has enabled high-fidelity virtualization with fast rendering and optimization for novel view synthesis. On the other hand, triangle mesh models still remain a popular choice for surface reconstruction but suffer from slow or heavy optimization in traditional mesh-based differentiable renderers. To address this problem, we propose a new lightweight differentiable mesh renderer leveraging the efficient rasterization process of 3DGS, named Gaussian Mesh Renderer (GMR), which tightly integrates the Gaussian and mesh representations. Each Gaussian primitive is analytically derived from the corresponding mesh triangle, preserving structural fidelity and enabling the gradient flow. Compared to the traditional mesh renderers, our method achieves smoother gradients, which especially contributes to better optimization using smaller batch sizes with limited memory. Our implementation is available in the public GitHub repository at https://github.com/huntorochi/Gaussian-Mesh-Renderer.