Cheap Pixelless Textures With 2D SDFs
August 19, 2025

Rich animated scenery can emerge from about 500 lines of Python without texture images or a heavyweight 3D renderer. Brian Greenforest’s scanline engine uses two-dimensional signed-distance functions in UV space to create continuous materials and shapes.

GPT-5 selected the cedar geometry, texture forms, and exact color palette, then wrote the end-to-end renderer around those artistic decisions.

Make the Texture a Function

A 2D SDF evaluates each texel once and returns distance to a procedural boundary. Thresholds and smooth bands turn that value into bark, foliage, ground, shadows, and silhouettes without pixel-art assets.

Point-cloud speckles create foliage at distance. Shaded or solid triangles form trunks, branches, and ferns, while a UV-SDF deer sprite carries a recognizable figure through the same mathematical material system.

Animate a Complete World in Plain Python

The scanline architecture keeps every decision inspectable: project the geometry, evaluate material functions, shade spans, compose depth, and emit each frame.

Graphics programmers, educators, and artists can run the engine, alter the SDFs and palette, and use this compact world as a starting point for new procedural scenes.

Inspect The Render

Scanline-rendered forest corridor with procedural SDF textures, triangle foliage, tree forms, and a deer sprite
The procedural UV-SDF scanline renderer creates this forest frame without bitmap texture art.

Read The Implementation At One Glance

Output
640x480 rendered frames.
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
The 19-page source PDF contains the complete self-contained renderer.

Follow One Scanline Through The Machine

The program projects scene geometry, generates its palette, evaluates procedural textures and SDF primitives, constructs the scene, and advances a camera path. Each scanline carries a filled mask: closer triangles and the deer occupy their pixels first, then background planes and ground material fill only uncovered positions.

The deer comes from rounded boxes and capsules in UV space. The billboard maps each candidate pixel back to u, v; deer_sdf(u, v) selects the silhouette; then albedo and shading functions color the occupied pixels.

The ground follows the same analytic path. A homography maps each screen row into ground UV coordinates, procedural fields create trail, duff, line, and fleck components, and the material function blends them without a stored source bitmap.

Open The Complete Source

Open sdf_texture_scanline_renderer.pdf for the complete 19-page Python listing.

Open the source-code PDF in a separate viewer.

See The Two Decisive Row Functions

The plane function maps uncovered pixels into UV space and calls a material function. The deer function uses the same projection path, tests an analytic silhouette, then shades only the pixels inside it.

# 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

Carry The Reusable Parts Into New Renderers

The UV-SDF material path, analytic deer sprite, and scanline filled-mask discipline form three separable techniques. Port them into a browser or GPU renderer, replace the scene and palette, and keep the same direct path from mathematical surface to visible material.

Originally posted on LinkedIn

Brian Greenforest · (2025-08-19 01:56:00 UTC)

Open the original LinkedIn post · LinkedIn activity 7363388235273687042

LinkedIn status when archived: Visible to anyone on or off LinkedIn.

Procedurally-generated textures allow cheap pixelless textures. SDF in 2D is 1 eval, much cheaper than in 3D. So we use UV-SDF in texel space. Sprinkle speckles of point cloud in distance to emulate foliage. Use shaded or solid triangles for mid-field trunks, branches, fern. GPT-5 made decisions on the shapes and the geometries of the cedar trees, texture shapes, exact color palette, all on its own, and wrote an end-to-end SotA scanline rendering engine from scratch. All in ~500 lines of Python. Animated.

Original LinkedIn media

Media shown with Brian Greenforest's original LinkedIn post
Photo attached to the original LinkedIn post. Open the saved full-resolution image.

Comments added by Brian Greenforest on LinkedIn

This comment was also preserved verbatim from Brian Greenforest’s LinkedIn data export or the public post page.

Code: https://www.linkedin.com/posts/ivanb-cpp_gpt-5-generated-3d-rendering-engine-and-scene-activity-7363395008340643842-Hg0L?utm_source=share&utm_medium=member_desktop&rcm=ACoAABKUCNUBsJCgKID4KDilYEHgUGp0SWVDy78

View the LinkedIn post