Lib3d Version 0.1.7 - Fast, Free 3D

Overview

Lib3d is a high performance 3d library for X windows and DOS. Lib3d implements Gouraud shading and Z-buffer rasterization, with support for 8, 16 and 32 bit graphics modes. Lib3d will make 160,000 lit, z-buffered, Gouraud shaded triangles per second on a standard Pentium 100.

Compared to other renderers, this makes Lib3d about 3.5 times faster than TAGL v22, many times faster than Mesa, and perhaps half as fast as a good commercial renderer.

Lib3d is distributed under the GNU Library General Public License, which allows use in commercial products subject to some quite reasonable conditions.

Development of lib3d is ongoing and contributions are invited. Lib3d has been developed under Linux and is also known to compile and run under Solaris. Ports to other 32 bit architectures and operating systems should be very simple. A contributed DOS port is included starting at version 0.1.5.

Any comments, patches, contributions, bug fixes, etc. are more than welcome. Email me at keithw@ozemail.com.au.

Mailing List

There is now a mailing list for Lib3d. To subscribe, send a message body containing the word 'subscribe' to: lib3d-users-request@hermetica.com To send a message to the list: lib3d-users@hermetica.com The mailing list is archived here.

Links

Alligator Descarte has a page with some sample images: http://www.hermetica.com/technologia/lib3d/

Getting It

The latest distribution (source only) is available as a .tar.gz archive, or as a zip file.

There is a mirror site in the US: ftp://ftp.mcqueen.com/pub/graphics/lib3d

Timings

Timed on a Pentium 100 running Linux 1.3.93, DGA interface, 300x250 viewport, 8bpp dithered visual, full Z buffer, single light, ambient+diffuse lighting, no precalculated lighting or other dirty tricks:

Rotating a teapot on its vertical axis:

  • 3751 poly teapot, no clipping: 160k poly/sec flat, 138k/sec smooth.
  • 3751 poly teapot, clipping: 112k poly/sec flat, 95k/sec smooth.
  • 240 poly teapot, no clipping: 50k poly/sec, 41k/sec smooth.
  • 240 poly teapot, clipping: 23k poly/sec, 20k/sec smooth.

    Timings for a 16 bpp visual are about 10% below these results.

    Comparision with Other Renderers

    Mesa and commercial renderers provide additional functionality, particularly texture mapping, and hardware support which isn't present in lib3d as yet. Mesa is unique amongst the free renderers in having a comprehensive, stable and well-documented API.

    Much has been made of Mesa's relatively poor performance. Lib3d originated from work I was doing looking at improving Mesa's performance in the case where display lists are used. In that situation, Mesa holds internally all of the information required to construct a Lib3d-style optimized representation, and perform rendering at comparable rates. The task of performing this unification is left as an exercise for the reader.

    Changes:

    A DOS port has been contributed by Markus Oberhumer (markus.oberhumer@jk.uni-linz.ac.at), and is included starting with v0.1.5. Here is his description:

    
    In the meanwhile I've ported lib3d to MSDOS using djgpp v2 + gcc
    2.7.2. [...] It uses the free Allegro graphics library for low-level
    video management. Allegro is available from many places, e.g. ftp://x2ftp.oulu.fi/pub/msdos/programming/djgpp2
    
    

    Versions 0.1.7 and 0.1.6:

  • Fixes for the DOS port.
  • Fix for DGA support at higher bit depths. Version 0.1.5:
  • DOS port contributed by Markus Oberhumer (markus.oberhumer@jk.uni-linz.ac.at)
  • Support for mulitple pixel depth X servers, contributed by Tim Rowley (tor@cs.brown.edu)
  • Xlib interface - render into a window/widget of your choice, bypassing the standard, platform independent interface. Based on work by Alligator Descartes (descarte@hermetica.com)
  • Experimental DGA support under XFree86.
  • Directory structure reorganization.
  • Changes to try to help compilation with earlier versions of g++.
  • Removed the private classes from FlatPipeline and SmoothPipeline, which were giving problems with even quite recent g++'s.
  • Sundry bugfixes, particularly with regards to colour ramps.
  • Fix the Pipeline pointer initialization bug in v0.1.4.

    Version 0.1.4:

  • Gouraud shading.
  • Calculation of vertex normals in ModelBuilder to support gouraud shading.
  • Swapped parameter names in Camera::setParameters() to concur with usage and functionality. Reported by Alligator Descartes (descarte@hermetica.com)

    Version 0.1.3:

  • Bugfix for XShm detection, contributed by Oleg Girko (ol@niif.ru).
  • Bugfix for HrTimer initialization, contributed by Frank M. Siegert (frank@miranda.tue.schwaben.de)
  • Fix for clipping bug, reported by Henning Schmiedehausen (barnard@forge.franken.de)
  • Fix for z interpolation of single pixel height polygons in flatPolygonZb().
  • Partially implemented 8Bpp colourIndex visual, with i386 assembly inner loops.
  • Ongoing tuning in DitherVisual.C. Slight (5%) improvement on v0.1.2.
  • Fix to object space culling which eliminates most of the above performance gain (sigh).
  • First hints of documentation (see doc/*)

    Version 0.1.2:

  • 40-50% speed improvement on version 0.1.1. (138k poly/sec on a P100)
  • A reader for TAGL-style .geom files.
  • Some bug fixes.

    Current Status

    lib3d is currently implemented in a conservative subset of C++, allowing scope for an easy C api or even a future port back to C.

    Most of the compulsory optimizations are present, including:

  • Bounding box culling and clip plane selection.
  • Backface culling in object space.
  • Lighting calculations in object space.
  • Model optimization including shared vertex, shared normal and shared material detection.
  • Culling and lighting per normal and per light rather than per polygon.
  • 8+24bit Zbuffer which need only be cleared once every 256 frames.
  • Dirty region support for swapBuffer(), clearBuffer() and clearZBuffer().

    All maths is floating point (except for rasterization), and there is no assembly (yet).

    Technical Overview

    Lib3d is a high level, retained-mode API with a similar flavor to the commercial renderers which have appeared recently. Retained-mode describes a system dictated by the requirements of efficient software implementation, and describes a system where the full geometry of the rendered environment is retained by the renderer from scene to scene. The scene geometry is described by a hierarchy of fixed-geometry nodes with arcs at the points of potentially free movement.

    The nodes in this tree include the models (objects), lights and cameras. The top of the tree is just a placeholder, called World in lib3d. The tree must contain a camera and at least one model in order for meaningful rendering to proceed.

    The three dimensional space of each node is transformed to the space of the parent node by the child's transformation matrix. Because the transformations accumulate, when a node's transformation matrix is changed, the change affects all of that node's children. As an example, consider the following tree:

      	World	
    	  |
    	  +-----Model: racetrack.nff
    	  |
    	  +-----Model: car.nff
    		  |
    		  +-----Light: headlight
    		  |
    		  +-----Camera: driver
    
    The car is positioned on the track with the driver inside the car and the lights at the head of the car, both pointing forwards. By changing the car's transformation matrix, the car, the camera and headlights all move together as a single unit. The camera gives a view of the track as if from inside a moving car.

    As well as being convenient for the programmer, this is a good structure for software implementation of a 3d renderer. The largely static nature of the tree allows large scale optimization of the model structure (recognition of shared vertices, normals, materials etc), the application of techniques such as bounding-box culling as well as caching of tranformation information from scene to scene.

    Device Handling

    Framebuffer handling is split into Devices, which handle the allocation of a back buffer for drawing and for performing the swapBuffer() method, and Visuals, which draw the actual polygons to the back buffer and must be aware of the pixel layout.

    Thus there are devices to handle X, DGA and DOS, which all interact with the 8bpp dithered visual.

    The following have been implemented:

  • Blitting Dga Device. (fastest of the X devices)
  • XShmImage Device.
  • Pageflipping Dga Device.
  • XImage Device.
  • DOS/Allegro Device.
  • 8bpp visual with 2x2 ordered dithering.
  • 16bpp visual for rgb:565 pixels.
  • 32bpp visual for rgb:0888 pixels.

    Pipelines

    There is now support for multiple pipelines. Three are implemented; wireframe, flat and smooth (gouraud) shading, all with an ambient+directional lighting model.

    The smooth pipeline has the restriction of a single diffuse colour over all active lights. If there is more than one diffuse colour, white is used instead. This is due to use of the 'ramp' lighting technique, the advantage of which is that only a single value, intensity, needs to be calculated at each vertex. Thus, theoretically, smooth shading requires only a single additional add per pixel.

    Maths

    All maths is done in floating point so far. And I seem to have used the opposite matrix formation to everyone else.

    Utilities

    The program testworld.C demonstrates a near finished NFF reader.

    The API is a little short on functionality to manipulate the hierarchy once it has been built. This is a reflection of the limited use the library has had so far.

    Future Work, Request for Contributions

    The following would be much appreciated:
  • An svgalib device.
  • Ports to Windows and other Unixes.
  • Assembly implementations of the polygon rasterization functions.
  • Visuals for other pixel layouts.
  • Texture mapping.
  • Programmers documentation.
  • Platform-independent mouse and keyboard API's.