====================
Drawing the Database
====================

As shown below, when your application wants to draw a picture, the HOOPS database walker walks the database tree and sends graphics primitives to the appropriate renderer. The renderer sends its output to the device driver. The device driver is the interface between the renderer and your system's graphics hardware. Drawing of a picture in HOOPS is a cooperative effort among the database walker, a renderer, a device driver, and an output device. 

.. image:: images/014a_driver_and_renderer.gif

*Driver instance and the rendering pipeline.*


HOOPS/3dGS device interface
===========================

To be portable to many different hardware platforms, HOOPS must be flexible. Many workstations provide dedicated 3D rendering hardware, typically via the OpenGL API. In this case, the goal of HOOPS is to feed the 3D graphics primitives from the database directly to the hardware, as fast as possible. Some platforms have 2D hardware that can draw simple lines and flat-shaded polygons. In this case, the device driver uses a HOOPS renderer to do all the 3D transformations and hidden-surface calculations, but uses the hardware to draw the 2D primitives. At the low end, some platforms may only provide a simple frame buffer. In this case, the device driver has to do everything itself. 

Ignoring differences across platforms, even on a single platform, HOOPS must be flexible. For example, an application might sometimes want fast rendering at the expense of realism, and at other times want perfect photo-realistic images, no matter how much time they take. So HOOPS must be able to use different rendering algorithms (even in the same scene), some of which might be supported in hardware. HOOPS also supports hardcopy devices in addition to a normal, frame-buffer-based display. 

In addition, even on platforms with 3D hardware, there are circumstances under which the HOOPS renderer will have to do all the work, because rendering hardware by its very nature has fixed limitations. For example, most 3D shading hardware allows only a fixed number of light sources in a scene (typically a small number, such as three or eight). If you want to draw a scene with more light sources than the hardware allows, then HOOPS has to abandon the shading hardware and to do the lighting calculations itself. 

HOOPS accomplishes its goal of flexibility by using a layered device interface called the HOOPS Device Interface (HDI). HDI is the interface between the renderer and the device driver. If a platform provides graphics hardware (and it is faster than HOOPS is at performing the same function in software), then HOOPS takes advantage of that hardware. If it does not, HOOPS fills in with software. Even on a system with graphics hardware, in some cases, the HOOPS software can be faster than the hardware. 


Options
=======

As we have seen, almost all information in HOOPS is stored as attributes (even device drivers). To draw a scene, the device driver and the renderer need to be supplied with information, such as what rendering algorithm or kind of lighting to use. Naturally, that information also is stored as attributes. Information used to control how the HOOPS/3dGS database is drawn is called an option. Options that are stored as attributes come in three flavors: driver options, rendering options, and heuristics. 


Driver options
--------------

Driver options are commands to a particular device driver. For example, if your system can support double buffering, you can turn on that option with ``Set_Driver_Options("double buffering")``. While driver options behave like a normal attribute (where then could in theory be set on any segment), generally, they only affect drivers, so it does not make sense to set them on a segment below a driver instance. However, there are a set of frame buffer effects ("ambient occlusion", "fast silhouettes", and "bloom") that can be enabled either at the driver level or can be toggled on and off *en masse* at the segment level by switching the "frame buffer effects" flag when calling ``Set_Rendering_Options``. 


Driver options should generally be set on a driver instance (such as /driver/opengl/window0). Alternatively, you can set a driver option on a driver segment (such as "/driver/msw"), so that the option is inherited by all instances of that driver, or you can set a driver option on "/driver" (or equivalently, on "/"), so that it is inherited by all drivers (and their instances). Like those for all attributes, default values for all the driver options are set by HOOPS on the root segment. The :doc:`HOOPS/3dGS Device Guide </general/device_guide>` contains details on the list of driver options supported for each HOOPS/3dGS device driver.
		
Rendering options
-----------------

``Set_Rendering_Options`` allow the developer to control how geometry is going to be rendered. These options typically enable algorithms or rendering techniques which perform additional preprocessing/sorting of geometry prior to drawing, or affect the visual appearance/quality of the resulting picture. Options include "lighting algorithms", "hidden surface removal algorithms", and "level of detail". For example, the following program renders the same object twice, once using the painter's algorithm and once using the hardware z-buffer algorithm:

.. tabs::

	.. group-tab:: C++
	
		.. literalinclude:: ../../../../hoops_3df/demo/common/sanity/0700_docs_0003.cpp
		   :start-after: //! [rendering_options]
		   :end-before: //! [rendering_options]
		   
*Creation of a new window.*
  
These rendering options are a normal attribute and can be set anywhere in the database tree.


Heuristics
----------

"Heuristics" are hints that HOOPS Visualize can use to speed up rendering (or take extra steps to handle special cases). For example:
  
.. tabs::

	.. group-tab:: C++
	
		.. literalinclude:: ../../../../hoops_3df/demo/common/sanity/0700_docs_0003.cpp
		   :start-after: //! [set_heuristics1]
		   :end-before: //! [set_heuristics1]
		   
...tells HOOPS to remove back-facing polygons. If your scene is only 2D or wireframe, you can use:

.. tabs::

	.. group-tab:: C++
	
		.. literalinclude:: ../../../../hoops_3df/demo/common/sanity/0700_docs_0003.cpp
		   :start-after: //! [set_heuristics2]
		   :end-before: //! [set_heuristics2]
		   
to turn off hidden-surface removal, which will significantly speed up rendering on most platforms. Like rendering options, heuristics can be set anywhere in the database tree. 


Use of options
--------------

You can set more than one option of the same type with the same command by separating the options with commas (spaces before or after commas are optional). For full details on all the possible options, refer to the entries in the HOOPS Visualize Reference Manual for ``Set_Driver_Options``, ``Set_Rendering_Options``, and ``Set_Heuristics``. The "Rendering" and "Performance guidelines" sections of this guide will also provide more details of how and when to use many of the most important rendering options and heuristics. 

  
System options
--------------

Not every option in HOOPS can be treated as an attribute; options that affect the entire HOOPS system (rather than being set on an individual segment) are called system options. System options are set with the ``Define_System_Options`` command and are returned with the ``Show_System_Options`` command (note the use of the verb "Define", instead of "Set"). 

System options affect all of HOOPS. For example, many of the samples in this guide (and most HOOPS programs in general) use HOOPS commands that return information in an array of characters. We guess how big to make the array, but because HOOPS does not know the array's length, it could easily overflow it with potentially disastrous consequences. An alternative is to choose a fixed array size - say, 256 bytes - and to call ``Define_System_Options("C string length = 256")``. If the C string length is set and HOOPS tries to return information that is larger than the specified string length, it will fail and signal an error. 


Info
====

In addition to options, there is a separate kind of information that HOOPS calls 'info'. The difference between an option and info is that an option can be changed, whereas info is fixed information about a specific device or feature that cannot be changed. There are three types of info in HOOPS: system info, device info, and font info. 
 

System info
-----------

Returned with the ``Show_System_Info`` command, system info is information about the specific HOOPS library you are using. For example, you can ask what the version number of HOOPS is, whether intermediate mode is available, which renderers are available, and whether this version of HOOPS supports the Kanji Japanese character set. 


Device info
-----------

Returned with the ``Show_Device_Info`` command, device info is information about a driver or a device. For example, you can find out whether your hardware is capable of double buffering by using the command ``Show_Device_Info("?Picture", "double buffer", answer)``, where answer is a character array that returns the answer "copy", "swap", or "none" (see the HOOPS 3DGS Reference Manual for information on what these values mean). You can also find out the resolution of the display, the number of colors, the depth of the Z-buffer, and more. The ``Show_Device_Info`` command takes a driver instance as an argument, since device info will be different for different drivers. 

  
Font info
---------

Returned with the ``Show_Font_Info`` command, font info is information about a specific text font on a specific device. For example, you can find out whether a specified font is proportionally spaced, and in what sizes it is available. Or you can find out whether a font is available on both the display and a hardcopy device.


Setting options at runtime
==============================

Since options (including heuristics) are character strings, they can be interpreted at run time. A big advantage of this ability is that they can be changed at run time without requiring a recompilation of your program. HOOPS provides a simple way to change them. When a HOOPS application starts up, HOOPS checks several environment variables to see whether they are defined. 

* HOOPS_DRIVER_OPTIONS. The value of this variable is passed to ``Set_Driver_Options``, applied to the root segment.
  
* HOOPS_RENDERING_OPTIONS. The value of this environment variable is passed to ``Set_Rendering_Options``, applied to the root segment.
  
* HOOPS_HEURISTICS. The value of this variable is passed to ``Set_Heuristics``, applied to the root segment.
  
* HOOPS_SYSTEM_OPTIONS. The value of this variable is passed to ``Define_System_Options``. 
    
These environment variables make it easy to tune your application. In addition, these variables allow you to tune your graphics application for a specific platform without making the application less portable. Your application passes in the tuning parameters through environment variables, which can be set by an installation script or manually by an advanced user. 

Passing in information through environment variables is so useful that HOOPS uses several other environment variables. One of these is ``HOOPS_PICTURE``, which is used to set the value of the "?Picture" alias. Other useful environment variables are ``HOOPS_APPLICATION``, ``HOOPS_COLORS``, ``HOOPS_TEXT_FONT``, ``HOOPS_FONT_DIRECTORY``, ``HOOPS_VISIBILITY``, ``HOOPS_PICTURE_OPTIONS``, and ``HOOPS_LICENSE``.

How you set environment variables depends on your platform. For example, on UNIX systems, environment variables are set with the ``set`` or ``setenv`` commands, (depending on your shell). On Windows systems, you can set environment variables using the System control panel or the Registry editor. Refer to the appropriate platforms sections of the :doc:`HOOPS/3dGS Platform and Device Guide </general/device_guide>` for information about setting environment variables on your platform. 


HOOPS_PICTURE environment variable
==================================

As reviewed previously, HOOPS assigns the alias "?Picture" to the segment name of the driver instance used to display the HOOPS database. You can modify this programmatically by assigning a new value to the "?Picture" alias, or from the command line by setting the value of the ``HOOPS_PICTURE`` environment variable. 

If ``HOOPS_PICTURE`` is set, then its value is appended onto the alias "?driver", and the result assigned to the alias "?Picture". For example, if ``HOOPS_PICTURE`` has the value "opengl/window0", then the HOOPS scene underneath the "?Picture" segment is rendered to a GUI screen window associated with the 'window0' segment, using the OpenGL driver.
  
The ``HOOPS_PICTURE`` alias is useful if the default value of "?Picture" does not take advantage of special graphics hardware or software that you have available on your computer. For example, on many UNIX systems, the default driver is "x11", but if you have special graphics hardware, you might be better off using the OpenGL driver. For more information, see the section of the :doc:`HOOPS/3dGS Platform and Device Guide </general/device_guide>` for your system.
  
On a system running X11, ``HOOPS_PICTURE`` can be used to reroute the display output to a remote X display. For example, if ``HOOPS_PICTURE`` is set to "x11/ralph:0.0", then HOOPS output is sent to the display on the machine named "ralph" (the string "ralph:0.0" is X syntax; for more information, see your documentation for X11). 

