Cheap Pixelless Textures With 2D SDFs
August 19, 2025

Images generated from geometry, functions, and material logic instead of bitmap texture assets.

This page preserves a render and source-code PDF for a self-contained Python scanline renderer: UV-space 2D SDF material tests, point-cloud foliage speckles, triangle trunks and branches, and a UV-SDF deer sprite.

Rendered source artifactOriginally posted 2025-08-19; expanded with the rendered frame, source-code PDF, and a short reading guide.

Included: the rendered forest frame, source-code PDF, row-fill rendering structure, UV-SDF material path, generated scene geometry, and links to the original posts.

Renderer focus: geometry, material logic, UV-space signed-distance fields, scanlines, and source code that produces the frame.

Rendered Artifact

This is a small graphics renderer, not just an image prompt. The source document describes a self-contained Python program using NumPy and Pillow. It projects a corridor-like forest scene, fills rows with front-to-back painter ordering, and uses procedural materials instead of bitmap texture art for the important surfaces.

Scanline-rendered forest corridor with procedural SDF textures, triangle foliage, tree forms, and a deer sprite
Rendered frame from the procedural UV-SDF scanline renderer. Open the image to inspect the full-size artifact.

The Claim

The useful idea is narrow and practical: if the visible detail belongs to a surface, a 2D SDF in that surface's UV or texel space can be much cheaper than treating the same detail as a 3D signed-distance scene. The renderer evaluates a material at the projected surface point and gets pixelless detail without a texture atlas.

The image uses several cheap representations at once: UV-SDF ground material, block-noise wall textures, point-cloud speckles for distant foliage, shaded or solid triangles for trunks, branches, and ferns, and a deer billboard whose silhouette is tested as an SDF in its own UV square.

Implementation Record

The source listing is a complete Python renderer, not a sketch around an external graphics engine.

Output
640x480 rendered frames in the source listing.
Dependencies
numpy and pillow.
Projection
Camera-space projection, quad homographies, and edge equations for row fills.
Materials
Procedural side and back textures, UV-SDF ground material, and palette-driven generated color.
Geometry
Triangle trunks, branches, ferns, leaf spans, point-cloud foliage, and a billboard deer.
Row discipline
A per-row filled mask prevents later background passes from overwriting closer triangles, points, or the deer sprite.
Source PDF
19 pages containing the self-contained renderer listing.

What The Source Does

The source code is organized around projection, palette generation, procedural textures, scene construction, SDF primitives, row renderers, and a camera path. The row renderer is the important part: each scanline carries a filled mask, draws closer triangles and the deer sprite first, then paints background planes and the ground only into pixels that are still uncovered.

The deer is not a bitmap pasted into the scene. The source builds it from rounded boxes and capsules in UV space. Each pixel inside the billboard quad is mapped back to u, v; deer_sdf(u, v) decides whether that pixel is inside the silhouette; then a small albedo and shading function colors only the filled pixels.

The ground material follows the same philosophy. The renderer maps the screen row back through a homography into ground UV coordinates, evaluates procedural field functions, and blends trail, duff, line, and fleck components. The result is texture-like detail that remains analytic rather than stored as a finite source bitmap.

Source Code PDF

The source artifact is preserved as sdf_texture_scanline_renderer.pdf. The PDF is 19 pages and contains the self-contained renderer listing.

Open sdf_texture_scanline_renderer.pdf

Reading Excerpt

This excerpt shows where the artifact stops being a flat picture and becomes a renderer. It is a short reading excerpt from the PDF, not a regenerated replacement for the source document.

# Source excerpt from sdf_texture_scanline_renderer.pdf
# Dependencies: numpy, pillow

def draw_plane_row_sdf(img, filled, y, invH, edges, material_fn, palette):
    fy = y + 0.5
    inside = np.ones(W, dtype=bool)
    for (A,B,C) in edges:
        inside &= (A*fx + B*fy + C) >= 0.0
    m = (~filled) & inside
    if not m.any(): return
    a_u, b_u, c_u = invH[0,0], invH[0,1], invH[0,2]
    a_v, b_v, c_v = invH[1,0], invH[1,1], invH[1,2]
    a_w, b_w, c_w = invH[2,0], invH[2,1], invH[2,2]
    ru = a_u*fx[m] + b_u*fy + c_u
    rv = a_v*fx[m] + b_v*fy + c_v
    rw = a_w*fx[m] + b_w*fy + c_w
    invrw = inv_nr3(rw)
    u = ru * invrw; v = rv * invrw
    col = material_fn(u, v, PALETTE)
    idx = np.where(m)[0]
    img[y, idx, :] = col
    filled[m] = True

def draw_sprite_row_deer(img, filled, y, invH, edges):
    fy = y + 0.5
    inside = np.ones(W, dtype=bool)
    for (A,B,C) in edges:
        inside &= (A*fx + B*fy + C) >= 0.0
    m = (~filled) & inside
    if not m.any(): return
    a_u, b_u, c_u = invH[0,0], invH[0,1], invH[0,2]
    a_v, b_v, c_v = invH[1,0], invH[1,1], invH[1,2]
    a_w, b_w, c_w = invH[2,0], invH[2,1], invH[2,2]
    ru = a_u*fx[m] + b_u*fy + c_u
    rv = a_v*fx[m] + b_v*fy + c_v
    rw = a_w*fx[m] + b_w*fy + c_w
    invrw = inv_nr3(rw)
    u = ru * invrw; v = rv * invrw
    d = deer_sdf(u, v)
    inside_sprite = d <= 0.0
    if not np.any(inside_sprite): return
    idx_all = np.where(m)[0]
    idx = idx_all[inside_sprite]
    if idx.size == 0: return
    uu = u[inside_sprite]
    vv = v[inside_sprite]
    albedo = deer_albedo(uu, vv)
    shade = deer_shade(uu, vv)
    col = np.clip(albedo * shade, 0.0, 1.0)
    img[y, idx, :] = col
    filled[idx] = True

Original Post Context

The original updates introduced two connected artifacts: the rendered forest frame and the source listing. The important technical point is the renderer structure: UV-space SDF tests for surface detail, procedural scene geometry, point speckles for distant foliage, row-based filled masks, and a compact self-contained Python implementation.

The posts also recorded the model-assisted generation context for the prototype. That context matters because the source is published with the rendered output: the article does not ask the image to stand alone as a prompt result.

Implementation Boundary

This is a compact Python prototype with front-to-back painter ordering and scanline row functions. It is not a production GPU renderer. The useful result is narrower: procedural 2D SDF texture logic can carry visible surface detail without turning every surface into a stored image.

Porting Boundary

The natural first ports are the UV-SDF material path, the deer sprite SDF, and the scanline filled-mask discipline. Those pieces are separable enough to move into a browser renderer or GPU path without preserving the whole Python prototype.