XGL is structured hierarchically through a series of abstract data types called classes. Applications can create instances of classes, where an instance of a class is an object. The class of an object determines the attributes it possesses and which operators can act on it. A class defined hierarchically below an existing one is known as a subclass (child) of the existing (parent) class. Although XGL is class-based, an application can only define instances of predefined classes (objects), and cannot extend the hierarchy by creating new classes. Figure 3.1 illustrates XGL's Class hierarchy.
In XGL, an object is an abstraction of a graphics resource. Objects consist of state information (known as attributes in XGL) and a set of operators. Operators perform predefined actions on objects of their related class.
The primary XGL objects available for the manipulation of 2-D and 3-D data are System State, Context, Device, Gcache, Color Map, Dmap Texture, MipMap Texture, Transform, Stroke Font, Line Pattern, Light, and Markers. The following paragraphs provide a brief discussion of XGL objects.
The XGL System State object maintains information pertaining to all operations occurring during a single XGL session. Operators of the System State object open and close XGL and adjust the degree of error checking XGL performs. The open and close operators, respectively, are always the first and last XGL operators executed from within an application.
The 2D and 3D Context objects provide 2-D and 3-D drawing primitives and graphics attributes for basic rendering. They are the most complex XGL objects. Several Context objects can exist simultaneously and can share resources associated with other XGL objects. 2D Context and 3D Context objects are separate, distinct objects designed to meet the dual goals of performance and dimension.
The Context object maintains both graphic and environment information on Coordinate Systems. The View Model, part of the environment information, performs general and specialized transformation and clipping operations, such as for lines and markers, 2-D and 3-D curve and surface tessellation, and stroke text rendering.
The XGL Device object retains information directly related to the drawing surface. The XGL Device object can be either a raster or non-raster device. If the device belongs to the raster class, it can be either a Window Raster (displayed on a screen) or a Memory Raster (consisting of an off-screen array stored in system memory).
Stream devices provide protocol-independent stream-I/O pipelines, for creating formatted output such as PostScript or Computer Graphics Metafile (CGM). The XGL Stream device maintains no protocol itself, but instead relies on an instantiated user or system-defined non-raster device pipeline to implement the appropriate output protocol data format.
Device objects can be attached to one or more Context objects, as the destination of drawing operations executed on the Context(s).
The Window and Memory Raster Devices are configured using the Raster Device attributes. For Window Raster Devices, the Device object maintains the connection to the windowing system, OpenWindows, or another X11 Windows server.
The XGL Gcache Object reduces the complexity of application geometry by allowing XGL to process the geometry into simpler forms. It reduces single complex primitives into many simple primitives, storing the relevant attribute values. The Gcache object additionally provides a mechanism to store graphics primitives that are rendered frequently, thus yielding higher performance
XGL Color Map objects specify colors in a device-independent manner. The XGL application can work within its own color space, even if the hardware employs a different one. The Color Map object attached to the device ensures optimal correspondence between the application's color model and the color model of the device. XGL supports both indexed and RGB color models.
The XGL Transform Object provides attributes and operators for geometric transformations performed on graphics primitives. These include translation, scaling, and rotation, as well as conversion from one coordinate system to another. A single 2D Context or 3D Context typically uses several Transform objects, which in turn can be shared (as defined by the application) between several Context objects.
The XGL Library supports both single and double precision floating point representations for applications requiring very large dynamic range or extra precision for transform operations.
The XGL Library provides Stroke Font objects that may be shared between Contexts. An XGL application may use Stroke Fonts to render stroke text in a variety of font types on Devices attached via Context operations. The XGL Library provides applications with high-quality fonts through improved interspacing of characters. This has the effect of making fonts more readable, particularly when text is small.
The XGL Library provides a Line Pattern object that is sharable between Contexts. Line Pattern objects allow non-solid lines to be rendered on a Device. The application may explicitly define the Line Pattern or may use one of several predefined Line Patterns XGL creates internally.
The Light object allows a 3D Context to render graphical primitives with ambient, positional, directional, and spot light sources. Light objects can be shared by different Contexts while remaining independently controllable on a per-context basis. This provides flexibility to the application, permitting individual Contexts to share some lighting attributes (such as position) but not others (such as light types enabled).
The Marker object allows applications to describe their own markers or symbols and share them between different Contexts. A user-defined Marker can contain as many as 128 vectors.
The Dmap Texture object allows an application to specify the control parameters needed to do texturing of 3-D surface primitives when rendering through a 3D Context. A Dmap Texture object can have many MipMap Texture objects and each 3D Context can have many Dmap Texture objects.
When an application opens the XGL Library, XGL automatically creates the System State object and other internal objects that handle interactions between the loadable pipelines and the device independent parts of XGL. To set up a framework for rendering, the application must create a Context object, which controls all rendering actions on an associated device, and a Device object, which enables a Context object to render geometric primitives to a drawing surface. These objects are created using the xgl_object_create() operator.
The xgl_object_create() operator creates an instance of an XGL class. It takes attributes describing the object as arguments and returns a handle to the object. Before geometry can be rendered, the application program must associate the Context object and the Device object. These objects are associated by assigning the handle of the Device object to a Context object attribute, either when the Context object is created or at any time before rendering occurs. Other objects, such as multiple Stroke Font objects or new Line Pattern objects, can be created as needed by the application and then associated with the Context object. Multiple Device objects, such as Window Raster and Memory Raster devices can be associated and disassociated with the Context object as needed for rendering. Figure 3.2 illustrates object instantiation through the XGL Library.
Other relationships are managed internally by XGL object management functions. When an application has created a new object, it can establish an association between the new object and an existing object using the xgl_object_set() operator, a connecting attribute, and the handles of the two objects. Figure 3.3 lists objects that are associated with the Context and Device objects as graphics resources.
Attributes control much of the functionality of XGL, such as the appearance of rendered geometry, the way picking is handled, and the orientation of Virtual Device Coordinate (VDC) space. While some attributes are read-only, an application can change the value of most attributes at any time. Attributes are input as arguments to XGL operators, some of which take an attribute-value list as one of the input parameters. Each attribute-value pair in the list consists of an attribute name followed by its value. The attribute-value list may have as few as zero attribute-value pairs or as many as the total number of the object's possible attributes. NULL is used to terminate the attribute-value list.
The xgl_object_create() operator is one of a set of operators that XGL uses to create objects and to modify the attributes of objects. XGL includes three types of operators: generic operators used with all API objects, geometry rendering operators, and object-specific operators. The generic operators, listed in Figure 3.4, provide a consistent method of working with all XGL objects.
The rendering operators are the XGL drawing primitives. XGL provides a broad range of drawing primitives, including polylines, text, and filled areas such as rectangles, quadrilateral meshes, multiple single-boundary polygons, and multiple-boundary polygons. Drawing primitives are available to an application as operators of the Context object. At execution time, a primitive gets the attributes it needs by rendering from the Context object. Figure 4.1 illustrates the XGL rendering operators and their associate primitives.
The XGL interface renders onto the graphical display through the device object and 2D or 3D Context objects. The display device is generally an X11 window, linked to the XGL application through a window "handle". The XGL application links the on-screen window to an XGL raster when the raster is created with the generic XGL creation operator xgl_object_create().
The XGL Library requires a window system in which to run when rendering to a framebuffer or other raster graphics device associated witha CRT screen; it does not work with a raw screen. However, rednering to a memory raster or system device does not require a window system. An XGL application may also utilize hardware double-buffering capability when it is available. A flexible buffer-switching mechanism is provided as part of the implementation.
The XGL Library accepts a large number of different representations of geometrical data, providing applications with flexibility in choosing an appropriate implementation. Data representation includes coordinate type and attributes associated with the rendered geometry. Figure 4.1 illustrates the most commonly used XGL primitives (rendering operators) and some of their associated attributes. Most primitives are renderable through both 2-D and 3-D pipelines.
The XGL interface includes several advanced primitives such as triangle strips, quadrilateral meshes, Non-Uniform Rational B-Spline (NURBS) curves and surfaces with dynamic tessellation, and annotation text functions. Such primitives are a powerful complement to the simpler primitives because they allow data compaction, utilize optimal clipping algorithms, and provide the best possible hardware rendering performance.
Geometric transformations specify a linear mapping of one coordinate space to another. A transformation can be applied to the x,y, and z coordinates of geometric primitives using Transform objects. Included in the graphics state of a Context are various modeling, viewing, and windowing transformations, which are defined by transform objects in a view model. Some graphics accelerators have a hardware matrix multiplier and storage for one or more transformation matrices. The XGL Library caches transform objects within the graphics accelerator whenever possible.
Any linear transformation of coordinates (e.g. scaling, translation, or rotation) can be described as a sequence of 3-D matrix operations. A sequence of operations can be concatenated to form a single transformation that embodies all operations in combination. Transforming any point by a concatenated transformation produces the same result as applying the original transformations in sequence.
Like coordinates, transform objects may be specified as single or double precision floating point or 32-bit integer. Data may be associated with a transform explicitly by directly loading a 4x4 matrix for a 3-D transform, or a 3x2 matrix for a 2-D transform. An application can also specify the contents of a transform object in terms of a sequence of rotations, translations, and scalings. Figure 4.2 illustrates the common set of transformations applied to geometrical data.
A colormap object is used to define color value conversions from one color space to another. The conversion is done using a color table or a color mapping function. The color table is generally used for mapping an index into a color value in the true-color or RGB (red, green, and blue) space, and the color mapping function is employed when mapping the color values from true-color space to an index.
Since colormaps are XGL objects, they can be shared among several XGL rasters. The current version of XGL supports indexed, gray, and RGB color models. In the indexed color model, indexes are mapped to RGB settings through integer offsets into a color map. The mapping is defined by a table of RGB values that the application constructs and passes to XGL.
The gray color model requires a single floating point value between 0 and 1 to define the intensity value.
The RGB color model requires that the application specify RGB settings directly as the intensity of the three primary colors (red, green, and blue). The application indicates the intensity value of each primary as a floating-point number between zero and one. Depending upon the intensity value of each primary, the application can represent any color that is a combination of the primaries.
An XGL application associates a colormap with a device (raster). When the colormap is created, the XGL graphics library uses a default colormap with two indexes. All raster devices are created with this default. If the device does not support true color, and the application is using a RGB color model, the XGL graphics interface simulates the specified RGB color as closely as possible.
Figure 4.3 illustrates the XGL color models.
The XGL interface supports flat and Gouraud shading. Lights are XGL objects and can be ambient, directional, positional, or spot. Lighting computations utilize the ambient, diffuse, and specular components to produce more realistic rendering. For true-color rendering, the RGB components of the light and object color are used for lighting and shading computations.
The XGL interface introduces a special element to ensure correct computations with an index model: color_map ramps. Users can define a set of ramps of different colors in the color map. The XGL Library automatically uses these ramps to evaluate the lighting and shading, while performing all computations in index mode. This reduces by a factor of three the number of computations involved in lighting and shading when rendering on index rasters.
XGL includes advanced features which provide powerful capabilities to 3-D MCAD, animation and simulation applications. These features include advanced primitives such as triangle strips, quadrilateral meshes and NURBS curves and surfaces. Additionally, XGL provides support for depth cueing, transparency, antialiasing, accumulation buffers, and texture mapping of surface primitives.
XGL additionally includes a triangle list primitive to provide flexibility for applications rendering triangle-based geometry where the triangle data must be unconstrained in terms of vertex sharing.
Strips and meshes are optimized to give the fastest possible rendering speed. The XGL Library provides users with an optimal clipping method for triangle strips that takes advantage of the intrinsic structure of the primitive while continuing to maintain this structure after clipping. This approach limits the number of computations to a strict minimum, yielding maximum performance in rendering. Quadrilateral meshes are not restricted to planar geometry and are rendered row by row, using the triangle strip pipeline. In this manner, they can take advantage of the same optimizations as triangle strips.
NURBS curves and surfaces are concise, yet powerful and general representations of a wide variety of simple and complex geometries. Trimmed NURBS are becoming increasingly more prominent in both informal and formal industry standards for geometric modeling and computer graphics. NURBS are effective for representing both simple and complex shapes, and include powerful mathematical properties which provide ease of manipulation and processing.
From a high-level mathematical description, a graphics system tessellates curved geometry into lines (in the case of curves) or triangles (in the case of surfaces), whose sizes depend on the spatial resolution of the curve or surface to the eye, and on the complexity of the geometry.
XGL NURBS curves are general enough for users to generate uniform curves such as Bezier curves, or uniform B-Splines. The order of the curves can be up to twenty-five (most CAD applications use three or four). XGL attributes offer complete control of the precision associated with the curve rendering such as dynamic tessellation to optimize the trade-off between number of points computed and rendering time. The XGL Library also offers a constant subdivision attribute to control the distance between two consecutive knots.
The XGL Raster object can provide antialiasing of images through the use of an accumulation buffer. An accumulation buffer is a buffer containing an array of pixels where the contents of the accumulation process is stored. The accumulation process takes a series of images (from multiple renderings) and combines them together.
With each successive rendering, the resulting image is moved or jittered a subpixel distance relative to the previous pass. It is then combined with the previously rendered images in the accumulation buffer. The combining of images in the accumulation buffer takes place through the weighted addition of the rendered image. The resulting image is effectively antialiased. XGL calculates the resulting contents of the accumulation buffer with the formula:
(source buffer * source weight + destination buffer * accumulation buffer weight)
Typically, an application program writes to the accumulation buffer multiple times to produce a desired image, and this image is then copied to the display buffer. Accumulation buffering can also be used to render motion blur, depth of field or soft shadows.
Applications requiring an accumulation buffer must use the xgl_context_accumulate operator. Figure 4.4 lists the accumulation buffer attributes associated with the XGL primitive call.
XGL provides a basic buffering mechanism to cache the geometric representation of data that will be rendered repeatedly. Known as Gcache, it is an XGL object that caches the underlying geometry for a particular primitive. For example, a Gcache could contain the polylines that comprise a string of stroke text, or triangles that make up a polygon.
A Gcache can be used to break down complex primitives into simpler forms, resulting in increased rendering performance (assuming the underlying accelerator is optimized for the resulting decomposed primitive). A Gcache also enables an application to instruct XGL to model clip, or decompose a primitive once, and then render the result many times.
Once a Gcache object is created, an application can use Gcache operators to store a primitive into the Gcache. For example, xgl_gcache_polygon(), which is used to store a polygon in a Gcache, is the Gcache counterpart of xgl_polygon(). The primitive can be displayed repeatedly, usually with better performance than its non-Gcache counterpart, by calling xgl_context_display_gcache().
Whenever an object is stored in a Gcache, certain Context attributes (which depend upon the primitive being stored) will be saved in the Gcache. If a primitive is stored in a Gcache, and any relevant Context attribute changes, the properties of the cached primitive will be outdated. When this happens, the application can decide if the primitive should still be displayed. Many Context attributes can be changed after a primitive has been stored in a Gcache without outdating the primitive. For example, view clipping attributes can be changed and the primitive will still be rendered correctly.
Many graphics hardware accelerators are efficient with simple geometries. For example, an accelerator may draw triangles very fast. If an application wants to render the same complex polygon several times, it is worthwhile to use a Gcache to break the polygon into triangles (known as tessellation) and send the triangles to the accelerator for rendering. If a Gcache was not used, then tessellation would have to be done each time the polygon was rendered.
For stroke text, a Gcache uses the character attributes (character spacing, height, etc.) to convert the text to a set of polylines for faster rendering. For NURBS curves and surfaces, much of the processing time is absorbed during Gcache creation time. This substantially speeds up display of NURBS curves and surfaces. Figure 4.5 illustrates the creation and manipulation of NURBS primitives using a Gcache.
XGL supports several transparency methods for 3-D surfaces, including screen-door transparency and blended (two-pass) transparency. Transparency can be invoked through 3D Context attributes assigned to the primitive to be rendered.
Screen door transparency allows a device-dependent screen door to render the object using a mesh through which some of the primitives pixels are rendered. If the blended method is used, blending equations determine how the surface pixel values are blended with the background color or existing pixel values. Transparency may be achieved in a number of ways, dependent upon available display hardware. For example, transparency may be directly supported on some devices or may use stipple patterns on others.
Transparent surfaces are subject to hidden line and surface removal as defined by the XGL_3D_CTX_HLHSR_MODE attribute. Figure 4.6 lists the surface transparency attributes that can be assigned to a primitive prior to rendering.
Depth cueing assists observers with perception of depth by fading the primitive's colors by an amount that corresponds with the distance of the primitive from the observer. Typically the amount of fading increases with the distance.
Applications that employ depth cueing often combine this effect with motion through animation. Two common applications which use depth cueing are molecular modeling and flight simulation. In the case of molecular modeling, the background color is usually black. Depth perception can be enhanced by fading the more distant parts of the molecule to black, making them appear dimmer. Oscillation of the molecule about a vertical axis enhances the depth perception of the object.
XGL supports two methods for depth-cueing known as linear and scaled. In linear depth-cueing, the colors of the primitives are the same as the non-depth cued colors at the front of the Virtual Device Coordinate (VDC) viewport. At the back of the viewport, the colors completely change to the specified depth cue color (RGB) or the color at the bottom of the color ramp (for indexed color). Between these two boundaries, all colors modulate to a linear combination of the original color and the depth cue color.
Scaled depth-cueing is a superset of linear depth cueing. Scaled depth-cueing is linear between two predefined reference planes, which can be placed at arbitrary depths in virtual device coordinates. The scale factors for the front and back planes must fall within values between 0.0 and 1.0. The scale factors outside the linear region are clamped at the values of the reference planes closest to them.
Depth-cueing in XGL is achieved through the assignment of attributes for the primitive to be depth-cued. Figure 4.7 lists the depth-cueing attributes and their description.
The XGL Library supports 2-D texturing of 3-D surface primitives using a texturing raster image specified by the MipMap_texture object. Textures are defined in a normalized texture space {u,v}, with both the u and v coordinates defined in the range 0.0 to 1.0.
Mapping of the texture onto a polygon is accomplished by listing {u,v} values in the data fields of the polygon vertices. For example, if a texture image is mapped completely onto a four-sided polygon (in a simple manner with no wrapping), the lower vertex of the polygon would be represented by the {u,v} coordinate pair {0.0,0.0}, the upper left vertex by {0.0,1.0}, the upper right by {1.0,1.0} and the lower right by {1.0,0.0}. Figure 4.8 illustrates the texture mapping space and the example described here. Figures 4.9 and 4.10 list the DMap and MipMap object texture attributes respectively.
Texturing is achieved in XGL through attributes which allow a great deal of flexibility. XGL allows the result of the texturing operation to be applied to different stages of the rendering pipeline (see Figure 4.11). It also supports sampling methods such as point, bilinear and trilinear to obtain texture value and several color composition techniques such as blend, decal and modulate. XGL additionally has the capability of applying several textures to individual primitives.
The XGL Library rendering and transformation pipeline manages the rendering and transformation of geometric data from the API to the underlying display hardware. From an application's perspective, the pipeline provides individual stages for the manipulation of geometric properties such as coordinate transformation, lighting, depth cueing, shading and transparency. Figure 4.11 illustrates XGL's rendering pipeline.
For flexibility and performance reasons, the XGL Library employs separate viewing pipelines for 2-D and 3-D graphics. Figure 4.12 shows both the 2-D and 3-D transformation pipelines. The 2-D viewing model is an affine model, whereas the 3-D viewing is a homogeneous model. A viewing model allows the application to describe the portion of a scene that should be displayed. To achieve this goal, a set of attributes define the transformations and clipping operations to perform between the application's space and the display space.
Like many graphics interfaces, XGL provides several local model transforms. The local transform can be used to map an element of the graphic scene with respect to the complete scene. The global model transform can be used to map the complete scene to an arbitrary world coordinate system. The view matrix typically represents the set of transformations done to map the users' viewing direction and perspective to the virtual device space.
A set of attributes, Virtual Device Coordinate (VDC) window, VDC mapping, VDC orientation, and Device Coordinate (DC) viewport specify the mapping from the VDC space to the display area.
Clipping is conceptually performed in three places; optional model clipping may take place in World Space, optional clipping may take place in VDC coordinates, and clipping to DC limits is always applied to ensure the correctness of the drawings in a window. The 3-D viewing pipeline has some extra steps due to its homogeneous characteristics. Figure 4.12 illustrates the stages of rendering for 3-D primitives. In this figure, local and global transforms are represented by a single model transform for compactness.
XGL supports internationalized character sets through its stroke font object facilities. A string of text may be composed of distinct fonts built from different character sets. An XGL Context object offers two text encoding (Extended UNIX Coding and ISO) schemes and four attributes which are utilized to select up to four active, simultaneous character sets. Extended Unix Coding (EUC) defines an encoding for characters that allows multi-byte characters. EUC uses bit patterns and control characters to select different character sets within a string. Mono encoding represents a string as an array of ASCII elements.
The motivation for allowing different encoding schemes and up to four fonts per Context object is to support internationalization extensions by providing the ability to switch between different languages (character sets). XGL supplies a number of text fonts, as listed below.
Cartographic Cartographic_M English_G
Headline Italic_C.phont Italic_T
Miscellaneous Miscellaneous_M Roman
The fonts listed above include a `.font' extension as part of their name. Additional fonts to be utilized by XGL must be placed in the XGL font subdirectory ($XGLHOME/lib/xglfonts/stroke usually defined as /opt/SUNWits/Graphics-sw/xgl-3.0/lib/xglfonts/stroke)).
New XGL fonts may be created using the Vector Font Editor (vfe), which is provided as part of Developers Version of XGL. Vfe provides a visual interface for the modification of existing fonts or the creation of new ones. Vfe works with the extended ASCII representation of a font file. Fonts however are stored in a binary format, and must be converted to their extended ASCII representation prior to being edited. When font creation or modification is complete, the font is reconverted back into its native binary format.
Within an XGL application, text font attributes allow the control of character rendering. Figure 4.13 lists the text font attributes and their description.
In addition to normal stroke text, which is subject to orientation based upon transformations of the primitives relative to the viewer's position, XGL also supports annotated text. Annotated text maintains a constant orientation, typically parallel to the display surface. Annotated text is often useful in applications where text is an important descriptive part of the geometry being rendered. Examples include molecular modeling, MCAD, and flight simulation.
XGL Reference Manual
XGL Programmer's Manual
OpenWindows User's Guide
OpenWindows Programmers Guide
X Protocol Reference Manual, O'Reilly & Associates. Inc.
PEX Protocol Specification, MIT
Xlib Reference Manual, O'Reilly & Associates. Inc.
Xlib Programming Manual, O'Reilly & Associates. Inc.
An Introduction to Computer Graphics Concepts, Addison-Wesley