Viewports

Rendering specifications for visualizing geometry

Fields are Utomata's units of computation: strictly numerical entities with fixed topology and operational mechanics. Formations project field data into geometry. For that geometry to become visible, it must be rendered. Viewports are Utomata's rendering specifications — well-defined windows into the three-dimensional space in which formations reside.

A viewport is a specification of a point of view. It contains a position from which to look and a target position to look at, and additionally specifies near and far clipping, field of view, lighting, and background color.

A viewport is declared with the ^ sigil:

^main {
  pos = (0, 0, 2.4142); // camera position
  look = (0, 0, 0);     // target position
  up = (0, 1, 0);       // orientation
}

pos places the camera in world space, look selects the point it faces, and up orients the view around that axis.

Unlike fields and formations, viewports are not spatial entities. They are invisible: they have no dimension, no geometry, and no inherent width, height, or aspect ratio. A viewport becomes a rendered image with a concrete resolution only once it is sampled by a field. The dimensions of that field then determine the output resolution and aspect ratio.

Evaluation

Viewport properties are single configuration vectors rather than expressions evaluated across a spatial domain. In this they resemble the formation-level transforms of the previous chapter, and differ from computed field properties such as set and run: each property resolves to one vector for the viewport as a whole.

A viewport property may be a static vector or an explicit absolute lookup of a field value:

^main {
  pos = (0, 0, 4);
  look = #vpSettings[0.25, 0];
}

More complex control over a viewport remains possible, but the calculation must first be performed in a designated field cell, whose value the viewport property then reads.

Rendering into Fields

A viewport is rendered by sampling it in a field expression:

#A {
  dim = (256, 256, 1);
  run = ^main;
}

The field's dimensions determine the output resolution and aspect ratio. Because the viewport itself has no resolution, the same viewport can be rendered at many different resolutions without changing the viewport: sampling ^main into a 256 × 256 field produces a square image, while sampling it into a 640 × 320 field produces the same view at a 2:1 aspect ratio.

On its own, a viewport offers only the most rudimentary rendering capabilities. It is the combination of viewports and fields that enables arbitrary post-processing: once sampled, a rendered view is ordinary field data, and the sampling field's run expression can transform it like any other value.

Sampled viewport data can subsequently be projected onto formation geometry, which can in turn become visible to other viewports — or be fed back into the same one:

#A {
  dim = (256, 256, 1);
  run = ^main; // feedback loop
}

~A {
  col = #A;
  pos = (0, 0, 0); // place at origin
}

^main {
  pos = (0, 0, 4);
  look = (0, 0, 0); // look at origin
}

Here ^main looks at the origin, where ~A displays the contents of #A — and #A stores whatever ^main renders, closing the loop.

Projection

The proj property packs three projection parameters into a single vector: the near and far clipping planes in world units, and a normalized field-of-view parameter.

Component Role
x near clipping plane, in world units
y far clipping plane, in world units
z field of view, normalized 0 to 1

A field of view of 0 selects an orthographic projection. Values above 0 produce perspective projections of increasing width:

proj = (1, 100, 0.5);    // perspective; clips geometry nearer than 1 or farther than 100
proj = (0.1, 10, 0.0);   // orthographic projection, tighter clipping
proj = (0.1, 100, 0.99); // extreme wide angle (fisheye)

Background and Lighting

bg sets the background color of the rendered view, in the UNIT domain:

^main {
  bg = (0.05, 0.05, 0.15);
}

light specifies the color of the directional key light, while light_dir specifies its direction vector. fill provides additive ambient illumination, independent of the directional light.

^main {
  fill = (0.2, 0.2, 0.2);  // soft ambient lighting
  light = (1, 1, 1);       // white key light
  light_dir = (1, -1, -0.5);
}

Setting light to zero disables the directional contribution, while fill can still illuminate the scene uniformly. Both properties accept channel values above 1.0 to increase lighting intensity.

Reference

Viewport properties are declared inside a ^viewport { ... } block.

Property Type Default Description
pos vec (0, 0, 2.4142) camera position in world space
look vec (0, 0, 0) camera look-at point
up vec (0, 1, 0) camera up vector
proj vec (0.1, 100, 0.5) (near, far, fov) projection parameters; fov = 0 selects orthographic projection
bg vec (0.05, 0.05, 0.15) background color
light vec (0, 0, 0) directional/key light color
fill vec (1, 1, 1) ambient/fill light color
light_dir vec (1, -1, -0.5) directional light direction