drtk.interpolate#

drtk.interpolate module provides functions for differentiable interpolation of vertex attributes across the fragments, e.i. pixels covered by the primitive.

interpolate

Performs a linear interpolation of the vertex attributes given the barycentric coordinates

interpolation_matrix

Build the sparse pixel-to-vertex interpolation matrix.

interpolation_normal_matrix

Assemble the sparse normal matrix for barycentric interpolation.

interpolate_ref

Pure PyTorch reference implementation used by tests.

drtk.interpolate(vert_attributes, vi, index_img, bary_img)[source]#

Performs a linear interpolation of the vertex attributes given the barycentric coordinates

Parameters:
  • vert_attributes (th.Tensor) – vertex attribute tensor N x V x C

  • vi (th.Tensor) – face vertex index list tensor F x 3 or N x F x 3

  • index_img (th.Tensor) – index image tensor N x H x W

  • bary_img (th.Tensor) – 3D barycentric coordinate image tensor N x 3 x H x W

Returns:

A tensor with interpolated vertex attributes with a shape [N, C, H, W]

Warning

The returned tensor has only valid values for pixels which have a valid index in index_img. For all other pixels, which had index -1 in index_img, the returned tensor will have non-zero values which should be ignored.

drtk.interpolation_matrix(vi, index_img, bary_img, num_vertices)[source]#

Build the sparse pixel-to-vertex interpolation matrix.

This returns the matrix A that maps per-vertex attributes X to the foreground raster pixels produced by a fixed rasterization:

pixel_values = A @ X

Each valid pixel contributes exactly one row. That row contains three non-zero entries: the pixel barycentric weights at the three vertex columns of the rasterized triangle. Columns are sorted within each CSR row, so the value order may differ from the triangle corner order. Pixels with index_img == -1 are omitted entirely, so the row order is the flattened [N, H, W] pixel order with background pixels skipped.

index_img is expected to come from DRTK rasterization and contain only background -1 or triangle indices in [0, F). num_vertices is expected to be larger than every vertex index in vi. The native kernels do not add extra range-validation work for those contracts; in particular, checking vi.max() on CUDA would add a synchronization only for defensive validation before constructing the sparse tensor with check_invariants=False. Faces must also have three distinct vertex indices; degenerate faces with duplicate corners are unsupported and can produce invalid CSR rows with duplicate column entries.

Differentiability:

The CSR row/column indices are discrete rasterization/topology data and are intentionally non-differentiable. The sparse values are the barycentric coordinates, so gradients through operations that support sparse CSR values propagate back to bary_img. No gradients are produced for vi or index_img.

Parameters:
  • vi – Face vertex index tensor, shape [F, 3], [1, F, 3], or [N, F, 3]. Singleton 3D batches are broadcast to N.

  • index_img – Rasterized triangle index image, shape [N, H, W].

  • bary_img – Barycentric image, shape [N, 3, H, W].

  • num_vertices – Number of vertex unknowns, i.e. the number of CSR columns.

Returns:

A sparse CSR tensor with shape [num_valid_pixels, num_vertices] and 3 * num_valid_pixels non-zero values.

drtk.interpolation_normal_matrix(vi, index_img, bary_img, num_vertices)[source]#

Assemble the sparse normal matrix for barycentric interpolation.

Let A be the matrix returned by interpolation_matrix() for the same vi, index_img and bary_img. This function returns A.T @ A directly, without materializing A. For every foreground pixel, the CUDA/CPU kernel accumulates the nine products bary_i * bary_j into the CSR entry corresponding to the owning triangle’s directed vertex pair (vi[i], vi[j]).

The sparsity pattern depends only on topology, not on image resolution or barycentric values. The C++ op caches that CSR structure and the per-face pair lookup per output device for repeated calls with the same face-index tensor, so iterative solvers can reuse both the expensive topology analysis and the device-resident CSR buffers while still updating numeric values every rasterization.

index_img is expected to come from DRTK rasterization and contain only background -1 or triangle indices in [0, F). The normal-matrix CUDA value kernel does not validate that range because host-side validation would synchronize the rasterization result in this hot path. Faces must also have three distinct vertex indices; degenerate faces with duplicate corners are unsupported.

Differentiability:

The normal-matrix structure and rasterized triangle indices are discrete and non-differentiable. The returned sparse values are differentiable with respect to bary_img via the product rule for bary_i * bary_j. No gradients are produced for vi or index_img. Visibility changes remain outside this op’s derivative; they are represented only through the supplied index_img.

Parameters:
  • vi – Face vertex index tensor, shape [F, 3], [1, F, 3], or [N, F, 3]. Singleton 3D batches are broadcast to N.

  • index_img – Rasterized triangle index image, shape [N, H, W].

  • bary_img – Barycentric image, shape [N, 3, H, W].

  • num_vertices – Number of vertex unknowns, i.e. the normal-matrix size.

Returns:

A sparse CSR tensor with shape [num_vertices, num_vertices].

drtk.interpolate_ref(vert_attributes, vi, index_img, bary_img)[source]#

Pure PyTorch reference implementation used by tests.

This helper is intentionally not part of the documented public API. See drtk.interpolate() for the supported implementation.