dwww Home | Manual pages | Find package

Pamtris User Manual(1)      General Commands Manual      Pamtris User Manual(1)

NAME
       pamtris  -  triangle rasterizer featuring perspective-correct interpola-
       tion of generic vertex attributes and depth buffering

SYNOPSIS
       pamtris

       -width=width

       -height=height

       { -num_attribs=attributes_per_vertex [ -tupletype=tupletype ] |  -rgb  |
       -grayscale }

       [ -maxval=maxval ]

       All options can be abbreviated to their shortest unique prefix.  You may
       use  two hyphens instead of one to designate an option.  You may use ei-
       ther white space or an equals sign between an option name and its value.

DESCRIPTION
       This program is part of Netpbm(1).

       pamtris can be used to draw a great variety of 2D  and  3D  graphics  by
       composing arbitrarily complex pictures out of separate triangles, trian-
       gle  strips and triangle fans. The program reads instructions written in
       a simple command script notation from Standard Input and outputs its re-
       sults as a (potentially multi-image) PAM stream on Standard Output.

       For example, the following input

             mode fan
             attribs 0 128 0
             vertex 0 0 1
             attribs 0 0 128
             vertex 200 0 1
             attribs 50 20 103
             vertex 190 61 1
             attribs 100 40 78
             vertex 161 117 1
             attribs 150 60 53
             vertex 117 161 1
             attribs 200 80 28
             vertex 61 190 1
             attribs 250 100 3
             vertex 0 200 1
             print

       produces this:

       Example pamtris output for FAN mode

       The input file gives triangle data by setting  the  appropriate  drawing
       mode,  if  necessary, and then providing a list of vertices. Each vertex
       is also associated with a list of up to 20 "attributes," which are inte-
       ger values between 0 and a given maxval. In the most common  usage,  you
       use  pamtris  to  draw a visual image and a vertex has three attributes,
       which are an RGB specification of a color.  Such attribute lists may  be
       provided on a per-vertex basis.

       Prior  to  effectively  writing  a PAM image to Standard Output, pamtris
       first rasterizes it onto an internal frame buffer, which consists of  an
       "image  buffer" and a "depth buffer." The image buffer consists of a se-
       quence of height rows containing a sequence of width  tuples.  There  is
       one sample for each vertex attribute in every tuple plus an opacity (al-
       pha)  sample.  Each tuple in the image buffer is also associated with an
       integer depth in the depth buffer, which determines  whether  subsequent
       drawing  operations affect that particular tuple or not. This provides a
       way of depth-sorting graphical objects which is adequate for  many  pur-
       poses  in 2D and 3D computer graphics. One prominent shortcoming of such
       an approach to depth-sorting, however, is that it does not automatically
       work with objects which are intended to appear "translucent,"  therefore
       requiring  more  elaborate  strategies  to incorporate said objects into
       pictures generated using this technique.

       The opacity sample is the last sample of the tuple.  pamtris manipulates
       opacity internally and for any tuple it is always either 0 or  the  max-
       val.   The program does not provide the user direct control over the al-
       pha image plane.

       pamtris rasterizes triangles by approximating their visible  area  as  a
       collection of tuples at particular positions in the frame buffer, and to
       each  sample  of every such tuple it assigns a value which is a perspec-
       tive-correct interpolation between the values of the  corresponding  at-
       tribute  for  each  vertex  of the triangle. Whenever a tuple within the
       area of the frame buffer is produced, it is written to the corresponding
       position in the frame buffer if and only if  it  passes  a  depth  test.
       This  test  works  as  follows:  the depth value of every incoming tuple
       (which is itself an interpolation between the Z-coordinates of the  ver-
       tices  of  the  corresponding triangle) is compared against the value in
       the corresponding position in the depth buffer. If the  depth  value  of
       the  incoming  tuple  equals  or is smaller than the depth value already
       present in said position in the depth buffer, the following happens.

       •      Every sample i, where 0 &#8804; i < num_attribs, of the tuple  in
              the  corresponding  position  in the image buffer is set to equal
              the value of the respective sample of the incoming tuple; and the
              alpha sample (the last one) is updated to the maxval;

       •      The depth value in the corresponding position in the depth buffer
              is updated to a depth value directly proportional to that of  the
              incoming tuple.

       Otherwise,  that  particular tuple effects no change at all in the frame
       buffer.

       The frame buffer is initially set so that all samples in every tuple  of
       the  image  buffer  contain  the  value  0, and all entries in the depth
       buffer contain the maximum permitted depth value.

       The attributes' values, and therefore the samples in the output PAM  im-
       ages, have no fixed interpretation ascribed to them (except for the last
       image  plane,  which is deliberately supposed to represent tuple opacity
       information); one may ascribe any suitable meaning to them, such as that
       of colors, texture coordinates, surface normals, light interaction char-
       acteristics, texture influence coefficients for multi-texturing, etc.

EXAMPLES
   Fan Mode
       The following command generates the image from the fan mode  example  at
       the  top of the ]8;;#description\DESCRIPTION]8;;\  section. If the file fan.tris contains that
       code, you could process it with:

           $ pamtris -height=200 -width=200 -rgb <fan.tris >fan.pam

   Strip Mode
       The following is an example of strip mode:

             mode strip
             attribs 255 0 0   # red
             vertex   0 200 1
             vertex  50   0 1
             attribs 0 0 0     # black
             vertex 100 200 1
             attribs 0 205 205 # cyan
             vertex 150 0 1
             attribs 0 0 255   # blue
             vertex 200 200 1
             vertex 250   0 1
             print

       Save the above code in  a  file  named  strip.tris  (for  instance)  and
       process it with:

           $ pamtris -height=200 -width=200 -rgb <strip.tris >strip.pam

       to yield:

       Example pamtris output for STRIP mode

   Triangle Mode
       The following is an example of triangle mode:

             # yellow square
             mode strip
             attrib 155 155 0
             vertex 50  50 100
             vertex 50 200 100
             vertex 200 50 100
             vertex 200 200 100

             # blue triangle
             mode triangles
             attrib 0 205 205
             vertex 20 125 70
             attrib 0 0 140
             vertex 230  70 120 # Change "120" and see what happens
             vertex 230 180 120 #
             print

       Save  the  above  code  in  a  file named pierce.tris (for instance) and
       process it with:

           $ pamtris -height=200 -width=200 -rgb <pierce.tris >pierce.pam

       to yield:

       Example pamtris output for TRIANGLES mode

   Meta-programming
       The pamtris command language is much too rudimentary to be used directly
       for any serious drawing; you will probably want to use a general purpose
       programming language to generate a temporary pamtris command file.

       For example, the draw_polygon procedure in the C program  below  outputs
       pamtris instructions to draw a regular polygon. It does this by generat-
       ing  a number of vertex instructions tracing around the perimeter of the
       corresponding circumscribed circle. (Note: The  PAM  image  produced  by
       piping  the  output  of  the below program into pamtris was subsequently
       downscaled through pamscale -linear -xscale 0.25 -yscale 0.25 to achieve
       an ]8;;#antialias\anti-aliased]8;;\  effect.)

       Regular Polygons

       /* ----------------------- *
        * width       = 512       *
        * height      = 512       *
        * num_attribs = 3         *
        * tupletype   = RGB_ALPHA *
        * ----------------------- */

       #include <math.h>
       #include <stdio.h>
       #include <stdlib.h>

       #define PI 3.14159265358979323844

       void draw_polygon
       (int const center_x, int const center_y, int const radius, int const sides)
       {
           printf("mode fan\n"
                  "vertex %d %d 0\n", center_x, center_y);

           for(int i = 0; i <= sides; i++)
           {
               int const x = round(center_x + radius * cos(i*2.0*PI / sides));
               int const y = round(center_y - radius * sin(i*2.0*PI / sides));

               printf("vertex %d %d 0\n", x, y);
           }
       }

       int main(void)
       {
           puts("attribs 0 185 80");       /* color: green   */
           draw_polygon(300, 210, 150, 5); /* draws pentagon */

           puts("attribs 255 15 240");     /* color: magenta */
           draw_polygon(150, 320, 100, 7); /* draws heptagon */

           puts("!");
       }

OPTIONS
       In addition to the options common to all  programs  based  on  libnetpbm
       (most notably -quiet, see ]8;;index.html#commonoptions\ Common Options]8;;\ ), pamtris recognizes the fol-
       lowing command line options:

       <dl compact="compact">

       -width=width
              Sets the width of the internal frame buffer and, by extension, of
              the  output  PAM images, given in number of columns. This must be
              an integer in the closed range [1, 8192].

              This option is mandatory.

       -height=height
              This is the height of the internal frame buffer  and,  by  exten-
              sion,  of  the  output  PAM images, given in number of rows. This
              must be an integer in the closed range [1, 8192].

              This option is mandatory.

       -num_attribs=attributes_per_vertex
              This is the number of attributes per vertex.  The  depth  of  the
              output  PAM images equals this value plus one (to accommodate the
              alpha plane). The argument must be an integer in the closed range
              [1, 20].

              The input instruction stream may override this with a reset  com-
              mand.

              You   must   specify  exactly  one  of  -num_attribs,  -rgb,  and
              -grayscale.

       -tupletype=tupletype
              This is the tuple type for the output PAM images. The argument is
              a string which may be no longer than 255 characters.

              The input instruction stream may override this with a reset  com-
              mand.

              The default is a null string.

              This   option   cannot   be  specified  together  with   -rgb  or
              -grayscale.

       -rgb   This is a convenience option which simply serves as an alias  for
              -num_attribs=3  -tupletype=RGB_ALPHA. In other words, this option
              is a quick way to specify that you are going to  use  pamtris  to
              draw  RGB(_ALPHA) color images directly, and the three vertex at-
              tributes are the red, green and blue levels of the color  associ-
              ated with the vertex, in that order.

              The  input instruction stream may override this with a reset com-
              mand.

              You  must  specify  exactly  one  of  -num_attribs,   -rgb,   and
              -grayscale.

              This option was new in Netpbm 10.85 (December 2018).

       -grayscale
              Another  convenience  option, similar to -rgb; except this one is
              an alias for -num_attribs=1 -tupletype=GRAYSCALE_ALPHA.  The  one
              vertex attribute is the gray level associated with the vertex.

              The  input instruction stream may override this with a reset com-
              mand.

              You  must  specify  exactly  one  of  -num_attribs,   -rgb,   and
              -grayscale.

              This option was new in Netpbm 10.85 (December 2018).

       -maxval=maxval
              Sets the maxval of the output PAM images, which is also the maxi-
              mum  permitted  value  for each vertex attribute. This must be an
              integer in the closed range [1, 65535].

              The default value is 255.

              The input instruction stream may override this with a reset  com-
              mand.

INSTRUCTION CODE
       The input for pamtris consists of a stream of text lines read from Stan-
       dard Input.

       Empty lines or lines that contain only white space characters are called
       blank lines and are ignored.

       When  a # occurs anywhere in a line, pamtris ignores it along with every
       character after it. In other words, everything from the # until the  end
       of the line receives the same treatment as white space.

       Lines which are not blank must contain a sequence of strings, called to-
       kens, separated by white space.  The first such token must be one of the
       commands  recognized  by pamtris, and all further tokens are interpreted
       as the arguments for that command, if it takes any. When an insufficient
       number of arguments is provided for a command, the  line  is  considered
       invalid  and  is given the same treatment as a blank line. The same hap-
       pens when an out of range argument or one of a kind different of what is
       expected is given (for example, when you give a string of letters  where
       a numerical value is expected), or when an unrecognized command/argument
       is  found.  When  a number of arguments greater than that required for a
       particular command is provided, only the portion of the line up  to  the
       last required argument is considered and any further tokens are ignored.

       pamtris  is  case-insensitive.  That  is, mode, MODE, mODe, etc. are all
       treated the same way.

       The commands recognized by pamtris are:

       mode

       attribs

       vertex

       print

       clear

       reset

       quit

       You may use a minimum unique abbreviation of a command  name.   You  may
       use  an  exclamation  mark (!) in place of the print command name and an
       asterisk (*) in place of clear.

       The functions of the commands are as follows.

       mode { triangles | strip | fan }

              This makes pamtris enter a new drawing mode. The  argument  is  a
              word which specifies the mode to change to. Instead of a full ar-
              gument name, it is permissible to provide a minimum unique abbre-
              viation,  which has the same effect. The drawing mode will remain
              the same until the next mode command is given.

              This command also  resets  the  current  vertex  list,  which  is
              (re)initialized  to an empty state after the command is executed.
              One may add new vertices to this list through successive  invoca-
              tions of the vertex command (see below). You do not have to worry
              about  providing  "too  many"  vertices, since the vertex list is
              virtualized: pamtris maintains only the state pertaining to three
              vertices at any one time. The current vertex  list  is  initially
              empty.

              It  is permissible to give pamtris a mode command which instructs
              it to enter a drawing mode it is currently already in. One  might
              use this approach to reset the current vertex list without chang-
              ing the current drawing mode.

              Regardless  of  the current drawing mode, the program immediately
              rasterizes a new triangle into the frame buffer as  soon  as  you
              provide  the necessary vertices for it through the current vertex
              list. (If you reset the vertex list before giving  all  the  ver-
              tices  necessary  to draw a new triangle, the program effectively
              discards from the list any vertices that might have  been  pushed
              into  the vertex list up to that point without using them to draw
              any new triangles.)

              In the following descriptions of each  drawing  mode,  triangles'
              and vertices' indices (ordinal numbers) are 0-based.

              The triangles argument instructs pamtris to enter the "TRIANGLES"
              drawing  mode. While in this mode, a series of separate triangles
              is constructed. Every three vertices pushed into the current ver-
              tex list specify a new triangle.  Formally, this means that every
              Nth triangle is specified by vertices 3*N, 3*N + 1, and  3*N + 2.
              This is the default initial mode and is therefore not required to
              be set explicitly before drawing any triangles.

              The strip argument instructs pamtris to enter the "STRIP" drawing
              mode.  While in this mode, pamtris constructs a "triangle strip."
              That  is, the first three vertices pushed into the current vertex
              list specify the first triangle, and every new vertex pushed  af-
              ter that specifies, together with the previous two, the next tri-
              angle.  Formally, this means that every Nth triangle is specified
              by vertices N, N + 1, and N + 2.

              The fan argument instructs pamtris to  enter  the  "FAN"  drawing
              mode.   While  in  this  mode, a so-called "triangle fan" is con-
              structed.  That is, the first three vertices pushed into the cur-
              rent vertex list specify the first triangle, and every new vertex
              pushed after that specifies, together with  the  previous  vertex
              and  the  first one, the next triangle. Formally, this means that
              every Nth triangle is specified by vertices 0, N + 1, and N + 2.

       attribs a<sub>0 a<sub>1
              a<sub>2 ... a<sub>num_attribs - 1

              This updates the current  attribute  values  list.  This  command
              takes  as arguments a sequence of num_attribs integers which rep-
              resent the values of the attributes to  be  associated  with  the
              next  vertex. This sequence of values is the just mentioned "cur-
              rent attribute values list."

              Each ith argument, where 0 &#8804; i < num_attribs, indicates the
              value to be assigned to the ith  attribute  of  the  current  at-
              tribute  values list. All arguments must be integer values in the
              closed range [0, maxval].  If a number of arguments less than the
              current value of num_attribs is given, the command is  considered
              invalid and is therefore ignored.

              The  current  attribute  values  list remains unchanged until the
              next valid attribs or reset command is given. The attribs command
              allows one to change the values of each  attribute  individually,
              while  the  reset  command  is not specifically designed for that
              function, but it has the side effect of setting all values in the
              current attribute values list to the maxval (see below).

              All values in the current attribute values list are initially set
              to the maxval.

              <dt id="cmd_vertex">vertex x y z [w]

              Adds a new vertex to the current vertex list (see the  mode  com-
              mand above), assigning the values of the arguments to its respec-
              tive  coordinates, and the values in the current attribute values
              list (see the attribs command above) to the respective entries in
              the attribute list associated with the vertex.

              x, y and z must be integer values in the  closed  range  [-32767,
              32767].   x  and y represent, respectively, the column and row of
              the tuple which corresponds to the location of the  vertex.  Such
              values  may  correspond to tuples outside the limits of the frame
              buffer. The origin of the coordinate system is  at  the  top-left
              tuple  of  the  frame buffer. The X-axis goes from left to right,
              and the Y-axis from top to bottom. A negative value for  x  indi-
              cates  a column that many tuples to the left of the leftmost col-
              umn of the frame buffer.  Likewise, a negative value for y  indi-
              cates a row that many tuples above the uppermost row of the frame
              buffer.  Observe  that those coordinates correspond directly to a
              particular point in the coordinate system delineated  above,  re-
              gardless of whether you are trying to draw an image which is sup-
              posed  to look as if viewed "in perspective" or not; pamtris does
              not "warp" the coordinates you give in any  way.   Therefore,  if
              you  want  to draw images in perspective, you must compute values
              for x and y already projected  into  pamtris'  coordinate  system
              yourself,  using an external perspective projection method, prior
              to giving them to the program.

              The z parameter represents the  Z-coordinate of the vertex, which
              is used to compute depth values for tuples within  the  areas  of
              rasterized  triangles.  Intuitively,  smaller  values  for z mean
              "closer to the viewer," and larger ones mean "farther  away  from
              the viewer" (but remember: as said above, the x and y coordinates
              are  not  warped  in any way, which implies that they are not af-
              fected by z; neither by the next parameter, for that matter).

              Optionally, you may provide a  w  parameter  which  represents  a
              "perspective correction factor" used to properly interpolate ver-
              tex  attributes  across  the  area of the corresponding triangle.
              This must be an integer value in the closed range  [1,  1048575].
              If  you  don't  provide a value for it, the default value of 1 is
              used (hence, if you want to nullify the  effects  of  perspective
              correction on a triangle so the output samples are computed as if
              just  linearly  interpolated, simply do not provide a value for w
              for any vertex of the triangle). If, however, you intend to  draw
              3D geometry in perspective, you must provide an appropriate value
              for  this  parameter, otherwise the output images might look very
              wrong.  w was new in Netpbm 10.85 (December 2018).

              Consider the ]8;;https://en.wikipedia.org/wiki/Viewing_frustum\ typical model]8;;\  of the so-called  "viewing  frustum"
              used to project vertices in 3D "world space" onto a planar "image
              space."  If  we  adopt  the convention that a "z-plane" means any
              plane parallel to the view-plane (a.k.a.  picture  plane,  a.k.a.
              near  plane),  the  value  of  w  for a vertex should then be the
              (smallest/euclidean/orthogonal) distance in  pixels  between  the
              projection  reference  point (PRP, or "eye") and the z-plane con-
              taining the vertex. One way to compute this value amounts to sim-
              ply taking the dot product between the 3D vector  r  and  the  3D
              unit  vector n, where r is the vector which goes from the projec-
              tion reference point (PRP, or "eye") to the vertex, and  n  is  a
              view-plane normal (VPN) of unit length which points away from the
              PRP.  In other words, this is equal to the length of the orthogo-
              nal projection of r on the line "determined" by n.

              (Note: For any two 3D vectors  a  and  b,  with  respective  real
              scalar components a<sub>x, a<sub>y, a<sub>z and b<sub>x, b<sub>y,
              b<sub>z,   the   dot   product   between   a   and  b  is  simply
              a<sub>x*b<sub>x + a<sub>y*b<sub>y + a<sub>z*b<sub>z.)

       print

              This writes a PAM image to Standard Output whose raster is a copy
              of the current contents of the image buffer. The  values  of  the
              WIDTH and HEIGHT fields are the same as the width and height, re-
              spectively,  of the frame buffer, which were given on the command
              line during program invocation. The MAXVAL field is equal to  the
              current  maxval; the DEPTH field is equal to the current value of
              num_attribs + 1; and the TUPLTYPE field is equal to  the  current
              tupletype.

              This  command has no effect upon the current drawing state. E. g.
              it does not modify the current drawing mode, the  current  vertex
              list, etc.

              One  may issue an arbitrary number of print commands at different
              positions in the input instruction sequence to produce  a  multi-
              image PAM stream.

       clear [ image | depth ]

              Clears the frame buffer. That is, all samples in the image buffer
              are  once again set to 0, and all entries in the depth buffer are
              once again set to the maximum permitted depth value.

              Optionally, one may provide an argument to only clear either  the
              image  buffer or the depth buffer individually, while leaving the
              other intact. With the image argument, only the image  buffer  is
              cleared;  with  the  depth  argument,  only  the  depth buffer is
              cleared. Instead of full argument names, one may provide a  mini-
              mum  unique  abbreviation,  which has the same effect. The single
              character z is also accepted as an alias for depth.

              Like the print command, this command has no effect upon the  cur-
              rent drawing state either.

       reset maxval num_attribs [tupletype]

              This updates the current maxval and number of attributes per ver-
              tex  (num_attribs),  resetting the <u>image</u> buffer with a new
              maxval and number of samples per tuple while at it. The parameter
              maxval must be an integer in the closed  range  [1,  65535],  and
              num_attribs must be an integer in the closed range [1, 20].

              Optionally,  after  the second argument, one may provide a string
              to be assigned to the current tupletype. The string goes from the
              first character after the second  argument  which  is  not  white
              space  and continues until (and including) the last character be-
              fore the end of the line which is not white space.  If a new  tu-
              pletype  is  not  provided, or the provided string is longer than
              255 characters, the empty string is assigned to the  current  tu-
              pletype.

              The side effects of running this command are

       •      The  new  image  buffer is completely cleared once the command is
              executed.

       •      All values in the current attribute values list are  set  to  the
              new maxval.

       •      The current vertex list is reset.

              However,  it does not touch the depth buffer: it is left the same
              way as it was found before the command. Also the drawing mode re-
              mains the same (e. g. if pamtris was in FAN mode,  it  will  con-
              tinue in that same mode, etc.).

              If  this  command  is  given  with an invalid value for maxval or
              num_attribs, it is ignored and therefore none of the  above  side
              effects  apply,  nor do the current maxval, num_attribs or tuple-
              type change at all.

              It is permissible to give a  value  for  maxval  and  num_attribs
              equal  to  the  current maxval and num_attribs, respectively, al-
              though the above side effects  will  still  apply  even  in  such
              cases.

              Since  this  command deals with memory allocation, it may fail to
              execute successfully. If that happens, no lines of input will  be
              read  anymore  and pamtris will be terminated as if the quit com-
              mand was given.

       quit

              This terminates pamtris. It will not read any more lines of input
              after this command.

TIPS
   Texturing
       It is possible to apply so-called "textures"  to  images  produced  with
       pamtris  by  using  a  pair of vertex attributes as texture coordinates,
       then using pamchannel(1) to select the appropriate channels in the  out-
       put  image(s),  and  finally processing the result through pamlookup(1),
       providing the desired texture file as a  "lookup  table."   If  you  are
       drawing  pictures  in  perspective, make sure to provide adequate values
       for the w parameter to your vertex commands ( ]8;;#cmd_vertex\see above]8;;\ )  so  that  the
       resulting samples in the images produced by pamtris are perspective-cor-
       rect. You might want to consider using pnmtile(1) to make textures which
       are inteded to be "repeated" along triangle meshes.

        The  animated GIF below is an example of what can be achieved using the
       technique described above (Earth texture from ]8;;https://visibleearth.nasa.gov/view.php?id=73580\nasa.gov]8;;\ ).

       Rotating Earth

   Anti-aliased edges
       pamtris performs no anti-aliasing on triangle edges by itself.  However,
       it is possible to obtain anti-aliased images through a  "super-sampling"
       approach:  draw  your  image(s)  at a size larger than the desired final
       size, and then, when all postprocessing is done, downscale the final im-
       age(s) to the desired size. Drawing images with twice the desired  width
       and  height, then downscaling them to the intended size while disregard-
       ing gamma (i.e. what pamscale -linear does) often produces  good  enough
       results;    but    the    larger    the    ratio   "size of original im-
       age" / "size of downscaled  image" , the better the quality of the anti-
       aliasing effect.

SEE ALSO
       pampick(1)  pamchannel(1)  pamstack(1)  pamlookup(1)  pamarith(1)   pam-
       scale(1) pamdepth(1) pamexec(1) pam(1)

HISTORY
       pamtris was new in Netpbm 10.84 (September 2018).

DOCUMENT SOURCE
       This  manual  page  was generated by the Netpbm tool 'makeman' from HTML
       source.  The master documentation is at

              http://netpbm.sourceforge.net/doc/pamtris.html

netpbm documentation             15 April 2021           Pamtris User Manual(1)

Generated by dwww version 1.16 on Tue Dec 16 05:55:16 CET 2025.