Re: Factor

Factor: the language, the theory, and the practice.

PBRT

Tuesday, February 3, 2026

PBRT is an impressive photorealistic rendering system:

From movies to video games, computer-rendered images are pervasive today. Physically Based Rendering introduces the concepts and theory of photorealistic rendering hand in hand with the source code for a sophisticated renderer.

The fourth edition of their book is now available on Amazon as well as freely available online.

I thought it would be fun to explore the PBRT v4 file format using Factor.

Here’s a short example pbrt file from their website:

LookAt 3 4 1.5  # eye
       .5 .5 0  # look at point
       0 0 1    # up vector
Camera "perspective" "float fov" 45

Sampler "halton" "integer pixelsamples" 128
Integrator "volpath"
Film "rgb" "string filename" "simple.png"
     "integer xresolution" [400] "integer yresolution" [400]

WorldBegin

# uniform blue-ish illumination from all directions
LightSource "infinite" "rgb L" [ .4 .45 .5 ]

# approximate the sun
LightSource "distant"  "point3 from" [ -30 40  100 ]
   "blackbody L" 3000 "float scale" 1.5

AttributeBegin
  Material "dielectric"
  Shape "sphere" "float radius" 1
AttributeEnd

AttributeBegin
  Texture "checks" "spectrum" "checkerboard"
          "float uscale" [16] "float vscale" [16]
          "rgb tex1" [.1 .1 .1] "rgb tex2" [.8 .8 .8]
  Material "diffuse" "texture reflectance" "checks"
  Translate 0 0 -1
  Shape "bilinearmesh"
      "point3 P" [ -20 -20 0   20 -20 0   -20 20 0   20 20 0 ]
      "point2 uv" [ 0 0   1 0    1 1   0 1 ]
AttributeEnd

And this is what it might look like:

Using our new pbrt vocabulary, we can convert that text into a set of tuples that we could do computations on, or potentially look into rendering or processing. And, of course, it also supports round-tripping back and forth from text to tuples.

{
    T{ pbrt-look-at
        { eye-x 3 }
        { eye-y 4 }
        { eye-z 1.5 }
        { look-x 0.5 }
        { look-y 0.5 }
        { look-z 0 }
        { up-x 0 }
        { up-y 0 }
        { up-z 1 }
    }
    T{ pbrt-camera
        { type "perspective" }
        { params
            {
                T{ pbrt-param
                    { type "float" }
                    { name "fov" }
                    { values { 45 } }
                }
            }
        }
    }
    T{ pbrt-sampler
        { type "halton" }
        { params
            {
                T{ pbrt-param
                    { type "integer" }
                    { name "pixelsamples" }
                    { values { 128 } }
                }
            }
        }
    }
    T{ pbrt-integrator { type "volpath" } { params { } } }
    T{ pbrt-film
        { type "rgb" }
        { params
            {
                T{ pbrt-param
                    { type "string" }
                    { name "filename" }
                    { values { "simple.png" } }
                }
                T{ pbrt-param
                    { type "integer" }
                    { name "xresolution" }
                    { values { 400 } }
                }
                T{ pbrt-param
                    { type "integer" }
                    { name "yresolution" }
                    { values { 400 } }
                }
            }
        }
    }
    T{ pbrt-world-begin }
    T{ pbrt-light-source
        { type "infinite" }
        { params
            {
                T{ pbrt-param
                    { type "rgb" }
                    { name "L" }
                    { values { 0.4 0.45 0.5 } }
                }
            }
        }
    }
    T{ pbrt-light-source
        { type "distant" }
        { params
            {
                T{ pbrt-param
                    { type "point3" }
                    { name "from" }
                    { values { -30 40 100 } }
                }
                T{ pbrt-param
                    { type "blackbody" }
                    { name "L" }
                    { values { 3000 } }
                }
                T{ pbrt-param
                    { type "float" }
                    { name "scale" }
                    { values { 1.5 } }
                }
            }
        }
    }
    T{ pbrt-attribute-begin }
    T{ pbrt-material { type "dielectric" } { params { } } }
    T{ pbrt-shape
        { type "sphere" }
        { params
            {
                T{ pbrt-param
                    { type "float" }
                    { name "radius" }
                    { values { 1 } }
                }
            }
        }
    }
    T{ pbrt-attribute-end }
    T{ pbrt-attribute-begin }
    T{ pbrt-texture
        { name "checks" }
        { value-type "spectrum" }
        { class "checkerboard" }
        { params
            {
                T{ pbrt-param
                    { type "float" }
                    { name "uscale" }
                    { values { 16 } }
                }
                T{ pbrt-param
                    { type "float" }
                    { name "vscale" }
                    { values { 16 } }
                }
                T{ pbrt-param
                    { type "rgb" }
                    { name "tex1" }
                    { values { 0.1 0.1 0.1 } }
                }
                T{ pbrt-param
                    { type "rgb" }
                    { name "tex2" }
                    { values { 0.8 0.8 0.8 } }
                }
            }
        }
    }
    T{ pbrt-material
        { type "diffuse" }
        { params
            {
                T{ pbrt-param
                    { type "texture" }
                    { name "reflectance" }
                    { values { "checks" } }
                }
            }
        }
    }
    T{ pbrt-translate { x 0 } { y 0 } { z -1 } }
    T{ pbrt-shape
        { type "bilinearmesh" }
        { params
            {
                T{ pbrt-param
                    { type "point3" }
                    { name "P" }
                    { values
                        { -20 -20 0 20 -20 0 -20 20 0 20 20 0 }
                    }
                }
                T{ pbrt-param
                    { type "point2" }
                    { name "uv" }
                    { values { 0 0 1 0 1 1 0 1 } }
                }
            }
        }
    }
    T{ pbrt-attribute-end }
}

This is available now in the development version of Factor!