1OSPRay
2======
3
4This is release v2.8.0 of Intel® OSPRay. For changes and new features
5see the [changelog](CHANGELOG.md). Visit http://www.ospray.org for more
6information.
7
8OSPRay Overview
9===============
10
11Intel OSPRay is an **o**pen source, **s**calable, and **p**ortable
12**ray** tracing engine for high-performance, high-fidelity visualization
13on Intel Architecture CPUs. OSPRay is part of the [Intel oneAPI
14Rendering Toolkit](https://software.intel.com/en-us/rendering-framework)
15and is released under the permissive [Apache 2.0
16license](http://www.apache.org/licenses/LICENSE-2.0).
17
18The purpose of OSPRay is to provide an open, powerful, and easy-to-use
19rendering library that allows one to easily build applications that use
20ray tracing based rendering for interactive applications (including both
21surface- and volume-based visualizations). OSPRay is completely
22CPU-based, and runs on anything from laptops, to workstations, to
23compute nodes in HPC systems.
24
25OSPRay internally builds on top of [Intel
26Embree](https://www.embree.org/) and [Intel ISPC (Implicit SPMD Program
27Compiler)](https://ispc.github.io/), and fully exploits modern
28instruction sets like Intel SSE4, AVX, AVX2, AVX-512 and NEON to achieve
29high rendering performance, thus a CPU with support for at least SSE4.1
30is required to run OSPRay on x86_64 architectures. A CPU with support
31for NEON is required to run OSPRay on ARM64 architectures.
32
33OSPRay Support and Contact
34--------------------------
35
36OSPRay is under active development, and though we do our best to
37guarantee stable release versions a certain number of bugs,
38as-yet-missing features, inconsistencies, or any other issues are still
39possible. Should you find any such issues please report them immediately
40via [OSPRay’s GitHub Issue
41Tracker](https://github.com/ospray/OSPRay/issues) (or, if you should
42happen to have a fix for it,you can also send us a pull request); for
43missing features please contact us via email at
44<ospray@googlegroups.com>.
45
46To receive release announcements simply [“Watch” the OSPRay
47repository](https://github.com/ospray/OSPRay) on GitHub.
48
49[![Join the chat at
50https://gitter.im/ospray/ospray](https://ospray.github.io/images/gitter_badge.svg)](https://gitter.im/ospray/ospray?utm_source=badge&utm_medium=badge&utm_content=badge)
51
52Building and Finding OSPRay
53===========================
54
55The latest OSPRay sources are always available at the [OSPRay GitHub
56repository](http://github.com/ospray/ospray). The default `master`
57branch should always point to the latest bugfix release.
58
59Prerequisites
60-------------
61
62OSPRay currently supports Linux, Mac OS X, and Windows. In addition,
63before you can build OSPRay you need the following prerequisites:
64
65-   You can clone the latest OSPRay sources via:
66
67    ``` sh
68    git clone https://github.com/ospray/ospray.git
69    ```
70
71-   To build OSPRay you need [CMake](http://www.cmake.org), any form of
72    C++11 compiler (we recommend using GCC, but also support Clang,
73    MSVC, and [Intel® C++ Compiler
74    (icc)](https://software.intel.com/en-us/c-compilers)), and standard
75    Linux development tools.
76
77-   Additionally you require a copy of the [Intel® Implicit SPMD Program
78    Compiler (ISPC)](http://ispc.github.io), version 1.16.0 or later.
79    Please obtain a release of ISPC from the [ISPC downloads
80    page](https://ispc.github.io/downloads.html). The build system looks
81    for ISPC in the `PATH` and in the directory right “next to” the
82    checked-out OSPRay sources.[1] Alternatively set the CMake variable
83    `ISPC_EXECUTABLE` to the location of the ISPC compiler.
84
85-   OSPRay builds on top of the [Intel oneAPI Rendering Toolkit common
86    library (rkcommon)](https://www.github.com/ospray/rkcommon). The
87    library provides abstractions for tasking, aligned memory
88    allocation, vector math types, among others. For users who also need
89    to build rkcommon, we recommend the default the Intel [Threading
90    Building Blocks (TBB)](https://www.threadingbuildingblocks.org/) as
91    tasking system for performance and flexibility reasons. TBB must be
92    built from source when targeting ARM CPUs, or can be built from
93    source as part of the [superbuild](#cmake-superbuild). Alternatively
94    you can set CMake variable `RKCOMMON_TASKING_SYSTEM` to `OpenMP` or
95    `Internal`.
96
97-   OSPRay also heavily uses Intel [Embree](https://www.embree.org/),
98    installing version 3.13.1 or newer is required. If Embree is not
99    found by CMake its location can be hinted with the variable
100    `embree_DIR`.
101
102-   OSPRay also heavily uses Intel [Open VKL](https://www.openvkl.org/),
103    installing version 1.0.1 or newer is required. If Open VKL is not
104    found by CMake its location can be hinted with the variable
105    `openvkl_DIR`.
106
107-   OSPRay also provides an optional module implementing the `denoiser`
108    image operation, which is enabled by `OSPRAY_MODULE_DENOISER`. This
109    module requires Intel [Open Image
110    Denoise](https://openimagedenoise.github.io/) in version 1.2.3 or
111    newer. You may need to hint the location of the library with the
112    CMake variable `OpenImageDenoise_DIR`.
113
114-   For the optional MPI module (enabled by `OSPRAY_MODULE_MPI`), which
115    provides the `mpiOffload` and `mpiDistributed` devices, you need an
116    MPI library and [Google Snappy](https://github.com/google/snappy).
117
118-   The optional example application, the test suit and benchmarks need
119    some version of OpenGL and GLFW as well as
120    [GoogleTest](https://github.com/google/googletest) and [Google
121    Benchmark](https://github.com/google/benchmark/)
122
123Depending on your Linux distribution you can install these dependencies
124using `yum` or `apt-get`. Some of these packages might already be
125installed or might have slightly different names.
126
127Type the following to install the dependencies using `yum`:
128
129``` sh
130sudo yum install cmake.x86_64
131sudo yum install tbb.x86_64 tbb-devel.x86_64
132```
133
134Type the following to install the dependencies using `apt-get`:
135
136``` sh
137sudo apt-get install cmake-curses-gui
138sudo apt-get install libtbb-dev
139```
140
141Under Mac OS X these dependencies can be installed using
142[MacPorts](http://www.macports.org/):
143
144``` sh
145sudo port install cmake tbb
146```
147
148Under Windows please directly use the appropriate installers for
149[CMake](https://cmake.org/download/),
150[TBB](https://github.com/oneapi-src/oneTBB/releases),
151[ISPC](https://ispc.github.io/downloads.html) (for your Visual Studio
152version) and [Embree](https://github.com/embree/embree/releases/).
153
154CMake Superbuild
155----------------
156
157For convenience, OSPRay provides a CMake Superbuild script which will
158pull down OSPRay’s dependencies and build OSPRay itself. By default, the
159result is an install directory, with each dependency in its own
160directory.
161
162Run with:
163
164``` sh
165mkdir build
166cd build
167cmake [<OSPRAY_SOURCE_LOC>/scripts/superbuild]
168cmake --build .
169```
170
171On Windows make sure to select the non-default 64bit generator, e.g.
172
173``` sh
174cmake -G "Visual Studio 15 2017 Win64" [<OSPRAY_SOURCE_LOC>/scripts/superbuild]
175```
176
177The resulting `install` directory (or the one set with
178`CMAKE_INSTALL_PREFIX`) will have everything in it, with one
179subdirectory per dependency.
180
181CMake options to note (all have sensible defaults):
182
183CMAKE_INSTALL_PREFIX
184will be the root directory where everything gets installed.
185
186BUILD_JOBS
187sets the number given to `make -j` for parallel builds.
188
189INSTALL_IN_SEPARATE_DIRECTORIES
190toggles installation of all libraries in separate or the same directory.
191
192BUILD_EMBREE_FROM_SOURCE
193set to OFF will download a pre-built version of Embree.
194
195BUILD_OIDN_FROM_SOURCE
196set to OFF will download a pre-built version of Open Image Denoise.
197
198OIDN_VERSION
199determines which version of Open Image Denoise to pull down.
200
201BUILD_OSPRAY_MODULE_MPI
202set to ON to build OSPRay’s MPI module for data-replicated and
203distributed parallel rendering on multiple nodes.
204
205BUILD_TBB_FROM_SOURCE
206set to ON to build TBB from source (required for ARM support). The
207default setting is OFF.
208
209For the full set of options, run:
210
211``` sh
212ccmake [<OSPRAY_SOURCE_LOC>/scripts/superbuild]
213```
214
215or
216
217``` sh
218cmake-gui [<OSPRAY_SOURCE_LOC>/scripts/superbuild]
219```
220
221Standard CMake build
222--------------------
223
224### Compiling OSPRay on Linux and Mac OS X
225
226Assuming the above requisites are all fulfilled, building OSPRay through
227CMake is easy:
228
229-   Create a build directory, and go into it
230
231    ``` sh
232    mkdir ospray/build
233    cd ospray/build
234    ```
235
236    (We do recommend having separate build directories for different
237    configurations such as release, debug, etc.).
238
239-   The compiler CMake will use will default to whatever the `CC` and
240    `CXX` environment variables point to. Should you want to specify a
241    different compiler, run cmake manually while specifying the desired
242    compiler. The default compiler on most linux machines is `gcc`, but
243    it can be pointed to `clang` instead by executing the following:
244
245    ``` sh
246    cmake -DCMAKE_CXX_COMPILER=clang++ -DCMAKE_C_COMPILER=clang ..
247    ```
248
249    CMake will now use Clang instead of GCC. If you are OK with using
250    the default compiler on your system, then simply skip this step.
251    Note that the compiler variables cannot be changed after the first
252    `cmake` or `ccmake` run.
253
254-   Open the CMake configuration dialog
255
256    ``` sh
257    ccmake ..
258    ```
259
260-   Make sure to properly set build mode and enable the components you
261    need, etc.; then type ’c’onfigure and ’g’enerate. When back on the
262    command prompt, build it using
263
264    ``` sh
265    make
266    ```
267
268-   You should now have `libospray.[so,dylib]` as well as a set of
269    [example applications](#tutorials).
270
271### Compiling OSPRay on Windows
272
273On Windows using the CMake GUI (`cmake-gui.exe`) is the most convenient
274way to configure OSPRay and to create the Visual Studio solution files:
275
276-   Browse to the OSPRay sources and specify a build directory (if it
277    does not exist yet CMake will create it).
278
279-   Click “Configure” and select as generator the Visual Studio version
280    you have (OSPRay needs Visual Studio 15 2017 or newer), for Win64
281    (32 bit builds are not supported by OSPRay), e.g., “Visual Studio 15
282    2017 Win64”.
283
284-   If the configuration fails because some dependencies could not be
285    found then follow the instructions given in the error message, e.g.,
286    set the variable `embree_DIR` to the folder where Embree was
287    installed and `openvkl_DIR` to where Open VKL was installed.
288
289-   Optionally change the default build options, and then click
290    “Generate” to create the solution and project files in the build
291    directory.
292
293-   Open the generated `OSPRay.sln` in Visual Studio, select the build
294    configuration and compile the project.
295
296Alternatively, OSPRay can also be built without any GUI, entirely on the
297console. In the Visual Studio command prompt type:
298
299``` sh
300cd path\to\ospray
301mkdir build
302cd build
303cmake -G "Visual Studio 15 2017 Win64" [-D VARIABLE=value] ..
304cmake --build . --config Release
305```
306
307Use `-D` to set variables for CMake, e.g., the path to Embree with
308“`-D embree_DIR=\path\to\embree`”.
309
310You can also build only some projects with the `--target` switch.
311Additional parameters after “`--`” will be passed to `msbuild`. For
312example, to build in parallel only the OSPRay library without the
313example applications use
314
315``` sh
316cmake --build . --config Release --target ospray -- /m
317```
318
319Finding an OSPRay Install with CMake
320------------------------------------
321
322Client applications using OSPRay can find it with CMake’s
323`find_package()` command. For example,
324
325``` sh
326find_package(ospray 2.0.0 REQUIRED)
327```
328
329finds OSPRay via OSPRay’s configuration file `osprayConfig.cmake`[2].
330Once found, the following is all that is required to use OSPRay:
331
332``` sh
333target_link_libraries(${client_target} ospray::ospray)
334```
335
336This will automatically propagate all required include paths, linked
337libraries, and compiler definitions to the client CMake target (either
338an executable or library).
339
340Advanced users may want to link to additional targets which are exported
341in OSPRay’s CMake config, which includes all installed modules. All
342targets built with OSPRay are exported in the `ospray::` namespace,
343therefore all targets locally used in the OSPRay source tree can be
344accessed from an install. For example, `ospray_module_ispc` can be
345consumed directly via the `ospray::ospray_module_ispc` target. All
346targets have their libraries, includes, and definitions attached to them
347for public consumption (please [report
348bugs](#ospray-support-and-contact) if this is broken!).
349
350Documentation
351=============
352
353The following [API
354documentation](http://www.sdvis.org/ospray/download/OSPRay_readme.pdf "OSPRay Documentation")
355of OSPRay can also be found as a [pdf
356document](http://www.sdvis.org/ospray/download/OSPRay_readme.pdf "OSPRay Documentation").
357
358For a deeper explanation of the concepts, design, features and
359performance of OSPRay also have a look at the IEEE Vis 2016 paper
360“[OSPRay – A CPU Ray Tracing Framework for Scientific
361Visualization](http://www.sdvis.org/ospray/download/talks/IEEEVis2016_OSPRay_paper.pdf)362(49MB, or get the [smaller
363version](http://www.sdvis.org/ospray/download/talks/IEEEVis2016_OSPRay_paper_small.pdf)
3641.8MB). The [slides of the
365talk](http://www.sdvis.org/ospray/download/talks/IEEEVis2016_OSPRay_talk.pdf)
366(5.2MB) are also available.
367
368OSPRay API
369==========
370
371To access the OSPRay API you first need to include the OSPRay header
372
373``` cpp
374#include "ospray/ospray.h"
375```
376
377where the API is compatible with C99 and C++.
378
379Initialization and Shutdown
380---------------------------
381
382To use the API, OSPRay must be initialized with a “device”. A device is
383the object which implements the API. Creating and initializing a device
384can be done in either of two ways: command line arguments using
385`ospInit` or manually instantiating a device and setting parameters on
386it.
387
388### Command Line Arguments
389
390The first is to do so by giving OSPRay the command line from `main()` by
391calling
392
393``` cpp
394OSPError ospInit(int *argc, const char **argv);
395```
396
397OSPRay parses (and removes) its known command line parameters from your
398application’s `main` function. For an example see the
399[tutorial](#osptutorial). For possible error codes see section [Error
400Handling and Status Messages](#error-handling-and-status-messages). It
401is important to note that the arguments passed to `ospInit()` are
402processed in order they are listed. The following parameters (which are
403prefixed by convention with “`--osp:`”) are understood:
404
405| Parameter                                   | Description                                                                                                                                                                                                                  |
406|:--------------------------------------------|:-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
407| `--osp:debug`                               | enables various extra checks and debug output, and disables multi-threading                                                                                                                                                  |
408| `--osp:num-threads=<n>`                     | use `n` threads instead of per default using all detected hardware threads                                                                                                                                                   |
409| `--osp:log-level=<str>`                     | set logging level; valid values (in order of severity) are `none`, `error`, `warning`, `info`, and `debug`                                                                                                                   |
410| `--osp:warn-as-error`                       | send `warning` and `error` messages through the error callback, otherwise send `warning` messages through the message callback; must have sufficient `logLevel` to enable warnings                                           |
411| `--osp:verbose`                             | shortcut for `--osp:log-level=info` and enable debug output on `cout`, error output on `cerr`                                                                                                                                |
412| `--osp:vv`                                  | shortcut for `--osp:log-level=debug` and enable debug output on `cout`, error output on `cerr`                                                                                                                               |
413| `--osp:load-modules=<name>[,...]`           | load one or more modules during initialization; equivalent to calling `ospLoadModule(name)`                                                                                                                                  |
414| `--osp:log-output=<dst>`                    | convenience for setting where status messages go; valid values for `dst` are `cerr` and `cout`                                                                                                                               |
415| `--osp:error-output=<dst>`                  | convenience for setting where error messages go; valid values for `dst` are `cerr` and `cout`                                                                                                                                |
416| `--osp:device=<name>`                       | use `name` as the type of device for OSPRay to create; e.g., `--osp:device=cpu` gives you the default `cpu` device; Note if the device to be used is defined in a module, remember to pass `--osp:load-modules=<name>` first |
417| `--osp:set-affinity=<n>`                    | if `1`, bind software threads to hardware threads; `0` disables binding; default is `1` on KNL and `0` otherwise                                                                                                             |
418| `--osp:device-params=<param>:<value>[,...]` | set one or more other device parameters; equivalent to calling `ospDeviceSet*(param, value)`                                                                                                                                 |
419
420Command line parameters accepted by OSPRay’s `ospInit`.
421
422### Manual Device Instantiation
423
424The second method of initialization is to explicitly create the device
425and possibly set parameters. This method looks almost identical to how
426other [objects](#objects) are created and used by OSPRay (described in
427later sections). The first step is to create the device with
428
429``` cpp
430OSPDevice ospNewDevice(const char *type);
431```
432
433where the `type` string maps to a specific device implementation. OSPRay
434always provides the “`cpu`” device, which maps to a fast, local CPU
435implementation. Other devices can also be added through additional
436modules, such as distributed MPI device implementations.
437
438Once a device is created, you can call
439
440``` cpp
441void ospDeviceSetParam(OSPObject, const char *id, OSPDataType type, const void *mem);
442```
443
444to set parameters on the device. The semantics of setting parameters is
445exactly the same as `ospSetParam`, which is documented below in the
446[parameters](#parameters) section. The following parameters can be set
447on all devices:
448
449| Type   | Name        | Description                                                                                                                                                                        |
450|:-------|:------------|:-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
451| int    | numThreads  | number of threads which OSPRay should use                                                                                                                                          |
452| int    | logLevel    | logging level; valid values (in order of severity) are `OSP_LOG_NONE`, `OSP_LOG_ERROR`, `OSP_LOG_WARNING`, `OSP_LOG_INFO`, and `OSP_LOG_DEBUG`                                     |
453| string | logOutput   | convenience for setting where status messages go; valid values are `cerr` and `cout`                                                                                               |
454| string | errorOutput | convenience for setting where error messages go; valid values are `cerr` and `cout`                                                                                                |
455| bool   | debug       | set debug mode; equivalent to `logLevel=debug` and `numThreads=1`                                                                                                                  |
456| bool   | warnAsError | send `warning` and `error` messages through the error callback, otherwise send `warning` messages through the message callback; must have sufficient `logLevel` to enable warnings |
457| bool   | setAffinity | bind software threads to hardware threads if set to 1; 0 disables binding omitting the parameter will let OSPRay choose                                                            |
458
459Parameters shared by all devices.
460
461Once parameters are set on the created device, the device must be
462committed with
463
464``` cpp
465void ospDeviceCommit(OSPDevice);
466```
467
468To use the newly committed device, you must call
469
470``` cpp
471void ospSetCurrentDevice(OSPDevice);
472```
473
474This then sets the given device as the object which will respond to all
475other OSPRay API calls.
476
477Device handle lifetimes are managed with two calls, the first which
478increments the internal reference count to the given `OSPDevice`
479
480``` cpp
481void ospDeviceRetain(OSPDevice)
482```
483
484and the second which decrements the reference count
485
486``` cpp
487void ospDeviceRelease(OSPDevice)
488```
489
490Users can change parameters on the device after initialization (from
491either method above), by calling
492
493``` cpp
494OSPDevice ospGetCurrentDevice();
495```
496
497This function returns the handle to the device currently used to respond
498to OSPRay API calls, where users can set/change parameters and recommit
499the device. If changes are made to the device that is already set as the
500current device, it does not need to be set as current again. Note this
501API call will increment the ref count of the returned device handle, so
502applications must use `ospDeviceRelease` when finished using the handle
503to avoid leaking the underlying device object. If there is no current
504device set, this will return an invalid `NULL` handle.
505
506When a device is created, its reference count is initially `1`. When a
507device is set as the current device, it internally has its reference
508count incremented. Note that `ospDeviceRetain` and `ospDeviceRelease`
509should only be used with reference counts that the application tracks:
510removing reference held by the current set device should be handled by
511`ospShutdown`. Thus, `ospDeviceRelease` should only decrement the
512reference counts that come from `ospNewDevice`, `ospGetCurrentDevice`,
513and the number of explicit calls to `ospDeviceRetain`.
514
515OSPRay allows applications to query runtime properties of a device in
516order to do enhanced validation of what device was loaded at runtime.
517The following function can be used to get these device-specific
518properties (attributes about the device, not parameter values)
519
520``` cpp
521int64_t ospDeviceGetProperty(OSPDevice, OSPDeviceProperty);
522```
523
524It returns an integer value of the queried property and the following
525properties can be provided as parameter:
526
527``` cpp
528OSP_DEVICE_VERSION
529OSP_DEVICE_VERSION_MAJOR
530OSP_DEVICE_VERSION_MINOR
531OSP_DEVICE_VERSION_PATCH
532OSP_DEVICE_SO_VERSION
533```
534
535### Environment Variables
536
537OSPRay’s generic device parameters can be overridden via environment
538variables for easy changes to OSPRay’s behavior without needing to
539change the application (variables are prefixed by convention with
540“`OSPRAY_`”):
541
542| Variable             | Description                                                                                                |
543|:---------------------|:-----------------------------------------------------------------------------------------------------------|
544| OSPRAY_NUM_THREADS   | equivalent to `--osp:num-threads`                                                                          |
545| OSPRAY_LOG_LEVEL     | equivalent to `--osp:log-level`                                                                            |
546| OSPRAY_LOG_OUTPUT    | equivalent to `--osp:log-output`                                                                           |
547| OSPRAY_ERROR_OUTPUT  | equivalent to `--osp:error-output`                                                                         |
548| OSPRAY_DEBUG         | equivalent to `--osp:debug`                                                                                |
549| OSPRAY_WARN_AS_ERROR | equivalent to `--osp:warn-as-error`                                                                        |
550| OSPRAY_SET_AFFINITY  | equivalent to `--osp:set-affinity`                                                                         |
551| OSPRAY_LOAD_MODULES  | equivalent to `--osp:load-modules`, can be a comma separated list of modules which will be loaded in order |
552| OSPRAY_DEVICE        | equivalent to `--osp:device:`                                                                              |
553
554Environment variables interpreted by OSPRay.
555
556Note that these environment variables take precedence over values
557specified through `ospInit` or manually set device parameters.
558
559### Error Handling and Status Messages
560
561The following errors are currently used by OSPRay:
562
563| Name                  | Description                                                                  |
564|:----------------------|:-----------------------------------------------------------------------------|
565| OSP_NO_ERROR          | no error occurred                                                            |
566| OSP_UNKNOWN_ERROR     | an unknown error occurred                                                    |
567| OSP_INVALID_ARGUMENT  | an invalid argument was specified                                            |
568| OSP_INVALID_OPERATION | the operation is not allowed for the specified object                        |
569| OSP_OUT_OF_MEMORY     | there is not enough memory to execute the command                            |
570| OSP_UNSUPPORTED_CPU   | the CPU is not supported (minimum ISA is SSE4.1 on x86_64 and NEON on ARM64) |
571| OSP_VERSION_MISMATCH  | a module could not be loaded due to mismatching version                      |
572
573Possible error codes, i.e., valid named constants of type `OSPError`.
574
575These error codes are either directly return by some API functions, or
576are recorded to be later queried by the application via
577
578``` cpp
579OSPError ospDeviceGetLastErrorCode(OSPDevice);
580```
581
582A more descriptive error message can be queried by calling
583
584``` cpp
585const char* ospDeviceGetLastErrorMsg(OSPDevice);
586```
587
588Alternatively, the application can also register a callback function of
589type
590
591``` cpp
592typedef void (*OSPErrorCallback)(void *userData, OSPError, const char* errorDetails);
593```
594
595via
596
597``` cpp
598void ospDeviceSetErrorCallback(OSPDevice, OSPErrorCallback, void *userData);
599```
600
601to get notified when errors occur.
602
603Applications may be interested in messages which OSPRay emits, whether
604for debugging or logging events. Applications can call
605
606``` cpp
607void ospDeviceSetStatusCallback(OSPDevice, OSPStatusCallback, void *userData);
608```
609
610in order to register a callback function of type
611
612``` cpp
613typedef void (*OSPStatusCallback)(void *userData, const char* messageText);
614```
615
616which OSPRay will use to emit status messages. By default, OSPRay uses a
617callback which does nothing, so any output desired by an application
618will require that a callback is provided. Note that callbacks for C++
619`std::cout` and `std::cerr` can be alternatively set through `ospInit()`
620or the `OSPRAY_LOG_OUTPUT` environment variable.
621
622Applications can clear either callback by passing `NULL` instead of an
623actual function pointer.
624
625### Loading OSPRay Extensions at Runtime
626
627OSPRay’s functionality can be extended via plugins (which we call
628“modules”), which are implemented in shared libraries. To load module
629`name` from `libospray_module_<name>.so` (on Linux and Mac OS X) or
630`ospray_module_<name>.dll` (on Windows) use
631
632``` cpp
633OSPError ospLoadModule(const char *name);
634```
635
636Modules are searched in OS-dependent paths. `ospLoadModule` returns
637`OSP_NO_ERROR` if the plugin could be successfully loaded.
638
639### Shutting Down OSPRay
640
641When the application is finished using OSPRay (typically on application
642exit), the OSPRay API should be finalized with
643
644``` cpp
645void ospShutdown();
646```
647
648This API call ensures that the current device is cleaned up
649appropriately. Due to static object allocation having non-deterministic
650ordering, it is recommended that applications call `ospShutdown()`
651before the calling application process terminates.
652
653Objects
654-------
655
656All entities of OSPRay (the [renderer](#renderers), [volumes](#volumes),
657[geometries](#geometries), [lights](#lights), [cameras](#cameras), …)
658are a logical specialization of `OSPObject` and share common mechanism
659to deal with parameters and lifetime.
660
661An important aspect of object parameters is that parameters do not get
662passed to objects immediately. Instead, parameters are not visible at
663all to objects until they get explicitly committed to a given object via
664a call to
665
666``` cpp
667void ospCommit(OSPObject);
668```
669
670at which time all previously additions or changes to parameters are
671visible at the same time. If a user wants to change the state of an
672existing object (e.g., to change the origin of an already existing
673camera) it is perfectly valid to do so, as long as the changed
674parameters are recommitted.
675
676The commit semantic allow for batching up multiple small changes, and
677specifies exactly when changes to objects will occur. This can impact
678performance and consistency for devices crossing a PCI bus or across a
679network.
680
681Note that OSPRay uses reference counting to manage the lifetime of all
682objects, so one cannot explicitly “delete” any object. Instead, to
683indicate that the application does not need and does not access the
684given object anymore, call
685
686``` cpp
687void ospRelease(OSPObject);
688```
689
690This decreases its reference count and if the count reaches `0` the
691object will automatically get deleted. Passing `NULL` is not an error.
692Note that every handle returned via the API needs to be released when
693the object is no longer needed, to avoid memory leaks.
694
695Sometimes applications may want to have more than one reference to an
696object, where it is desirable for the application to increment the
697reference count of an object. This is done with
698
699``` cpp
700void ospRetain(OSPObject);
701```
702
703It is important to note that this is only necessary if the application
704wants to call `ospRelease` on an object more than once: objects which
705contain other objects as parameters internally increment/decrement ref
706counts and should not be explicitly done by the application.
707
708### Parameters
709
710Parameters allow to configure the behavior of and to pass data to
711objects. However, objects do *not* have an explicit interface for
712reasons of high flexibility and a more stable compile-time API. Instead,
713parameters are passed separately to objects in an arbitrary order, and
714unknown parameters will simply be ignored (though a warning message will
715be posted). The following function allows adding various types of
716parameters with name `id` to a given object:
717
718``` cpp
719void ospSetParam(OSPObject, const char *id, OSPDataType type, const void *mem);
720```
721
722The valid parameter names for all `OSPObject`s and what types are valid
723are discussed in future sections.
724
725Note that `mem` must always be a pointer *to* the object, otherwise
726accidental type casting can occur. This is especially true for pointer
727types (`OSP_VOID_PTR` and `OSPObject` handles), as they will implicitly
728cast to `void *`, but be incorrectly interpreted. To help with some of
729these issues, there also exist variants of `ospSetParam` for specific
730types, such as `ospSetInt` and `ospSetVec3f` in the OSPRay utility
731library (found in `ospray_util.h`). Note that half precision float
732parameters `OSP_HALF, OSP_VEC[234]H` are not supported.
733
734Users can also remove parameters that have been explicitly set from
735`ospSetParam`. Any parameters which have been removed will go back to
736their default value during the next commit unless a new parameter was
737set after the parameter was removed. To remove a parameter, use
738
739``` cpp
740void ospRemoveParam(OSPObject, const char *id);
741```
742
743### Data
744
745OSPRay consumes data arrays from the application using a specific object
746type, `OSPData`. There are several components to describing a data
747array: element type, 1/2/3 dimensional striding, and whether the array
748is shared with the application or copied into opaque, OSPRay-owned
749memory.
750
751Shared data arrays require that the application’s array memory outlives
752the lifetime of the created `OSPData`, as OSPRay is referring to
753application memory. Where this is not preferable, applications use
754opaque arrays to allow the `OSPData` to own the lifetime of the array
755memory. However, opaque arrays dictate the cost of copying data into it,
756which should be kept in mind.
757
758Thus, the most efficient way to specify a data array from the
759application is to created a shared data array, which is done with
760
761``` cpp
762OSPData ospNewSharedData(const void *sharedData,
763    OSPDataType,
764    uint64_t numItems1,
765    int64_t byteStride1 = 0,
766    uint64_t numItems2 = 1,
767    int64_t byteStride2 = 0,
768    uint64_t numItems3 = 1,
769    int64_t byteStride3 = 0);
770```
771
772The call returns an `OSPData` handle to the created array. The calling
773program guarantees that the `sharedData` pointer will remain valid for
774the duration that this data array is being used. The number of elements
775`numItems` must be positive (there cannot be an empty data object). The
776data is arranged in three dimensions, with specializations to two or one
777dimension (if some `numItems` are 1). The distance between consecutive
778elements (per dimension) is given in bytes with `byteStride` and can
779also be negative. If `byteStride` is zero it will be determined
780automatically (e.g., as `sizeof(type)`). Strides do not need to be
781ordered, i.e., `byteStride2` can be smaller than `byteStride1`, which is
782equivalent to a transpose. However, if the stride should be calculated,
783then an ordering in dimensions is assumed to disambiguate, i.e.,
784`byteStride1 < byteStride2 < byteStride3`.
785
786The enum type `OSPDataType` describes the different element types that
787can be represented in OSPRay; valid constants are listed in the table
788below.
789
790| Type/Name                    | Description                                                                                  |
791|:-----------------------------|:---------------------------------------------------------------------------------------------|
792| OSP_DEVICE                   | API device object reference                                                                  |
793| OSP_DATA                     | data reference                                                                               |
794| OSP_OBJECT                   | generic object reference                                                                     |
795| OSP_CAMERA                   | camera object reference                                                                      |
796| OSP_FRAMEBUFFER              | framebuffer object reference                                                                 |
797| OSP_LIGHT                    | light object reference                                                                       |
798| OSP_MATERIAL                 | material object reference                                                                    |
799| OSP_TEXTURE                  | texture object reference                                                                     |
800| OSP_RENDERER                 | renderer object reference                                                                    |
801| OSP_WORLD                    | world object reference                                                                       |
802| OSP_GEOMETRY                 | geometry object reference                                                                    |
803| OSP_VOLUME                   | volume object reference                                                                      |
804| OSP_TRANSFER_FUNCTION        | transfer function object reference                                                           |
805| OSP_IMAGE_OPERATION          | image operation object reference                                                             |
806| OSP_STRING                   | C-style zero-terminated character string                                                     |
807| OSP_CHAR, OSP_VEC\[234\]C    | 8 bit signed character scalar and \[234\]-element vector                                     |
808| OSP_UCHAR, OSP_VEC\[234\]UC  | 8 bit unsigned character scalar and \[234\]-element vector                                   |
809| OSP_SHORT, OSP_VEC\[234\]S   | 16 bit unsigned integer scalar and \[234\]-element vector                                    |
810| OSP_USHORT, OSP_VEC\[234\]US | 16 bit unsigned integer scalar and \[234\]-element vector                                    |
811| OSP_INT, OSP_VEC\[234\]I     | 32 bit signed integer scalar and \[234\]-element vector                                      |
812| OSP_UINT, OSP_VEC\[234\]UI   | 32 bit unsigned integer scalar and \[234\]-element vector                                    |
813| OSP_LONG, OSP_VEC\[234\]L    | 64 bit signed integer scalar and \[234\]-element vector                                      |
814| OSP_ULONG, OSP_VEC\[234\]UL  | 64 bit unsigned integer scalar and \[234\]-element vector                                    |
815| OSP_HALF, OSP_VEC\[234\]H    | 16 bit half precision floating-point scalar and \[234\]-element vector (IEEE 754 `binary16`) |
816| OSP_FLOAT, OSP_VEC\[234\]F   | 32 bit single precision floating-point scalar and \[234\]-element vector                     |
817| OSP_DOUBLE, OSP_VEC\[234\]D  | 64 bit double precision floating-point scalar and \[234\]-element vector                     |
818| OSP_BOX\[1234\]I             | 32 bit integer box (lower + upper bounds)                                                    |
819| OSP_BOX\[1234\]F             | 32 bit single precision floating-point box (lower + upper bounds)                            |
820| OSP_LINEAR\[23\]F            | 32 bit single precision floating-point linear transform (\[23\] vectors)                     |
821| OSP_AFFINE\[23\]F            | 32 bit single precision floating-point affine transform (linear transform plus translation)  |
822| OSP_QUATF                    | 32 bit single precision floating-point quaternion, in (*i*,*j*,*k*,*w*) layout               |
823| OSP_VOID_PTR                 | raw memory address (only found in module extensions)                                         |
824
825Valid named constants for `OSPDataType`.
826
827If the elements of the array are handles to objects, then their
828reference counter is incremented.
829
830An opaque `OSPData` with memory allocated by OSPRay is created with
831
832``` cpp
833OSPData ospNewData(OSPDataType,
834    uint64_t numItems1,
835    uint64_t numItems2 = 1,
836    uint64_t numItems3 = 1);
837```
838
839To allow for (partial) copies or updates of data arrays use
840
841``` cpp
842void ospCopyData(const OSPData source,
843    OSPData destination,
844    uint64_t destinationIndex1 = 0,
845    uint64_t destinationIndex2 = 0,
846    uint64_t destinationIndex3 = 0);
847```
848
849which will copy the whole[3] content of the `source` array into
850`destination` at the given location `destinationIndex`. The
851`OSPDataType`s of the data objects must match. The region to be copied
852must be valid inside the destination, i.e., in all dimensions,
853`destinationIndex + sourceSize <= destinationSize`. The affected region
854`[destinationIndex, destinationIndex + sourceSize)` is marked as dirty,
855which may be used by OSPRay to only process or update that sub-region
856(e.g., updating an acceleration structure). If the destination array is
857shared with OSPData by the application (created with
858`ospNewSharedData`), then
859
860-   the source array must be shared as well (thus `ospCopyData` cannot
861    be used to read opaque data)
862-   if source and destination memory overlaps (aliasing), then behavior
863    is undefined
864-   except if source and destination regions are identical (including
865    matching strides), which can be used by application to mark that
866    region as dirty (instead of the whole `OSPData`)
867
868To add a data array as parameter named `id` to another object call also
869use
870
871``` cpp
872void ospSetObject(OSPObject, const char *id, OSPData);
873```
874
875Volumes
876-------
877
878Volumes are volumetric data sets with discretely sampled values in 3D
879space, typically a 3D scalar field. To create a new volume object of
880given type `type` use
881
882``` cpp
883OSPVolume ospNewVolume(const char *type);
884```
885
886Note that OSPRay’s implementation forwards `type` directly to Open VKL,
887allowing new Open VKL volume types to be usable within OSPRay without
888the need to change (or even recompile) OSPRay.
889
890### Structured Regular Volume
891
892Structured volumes only need to store the values of the samples, because
893their addresses in memory can be easily computed from a 3D position. A
894common type of structured volumes are regular grids.
895
896Structured regular volumes are created by passing the type string
897“`structuredRegular`” to `ospNewVolume`. Structured volumes are
898represented through an `OSPData` 3D array `data` (which may or may not
899be shared with the application). The voxel data must be laid out in
900xyz-order[4] and can be compact (best for performance) or can have a
901stride between voxels, specified through the `byteStride1` parameter
902when creating the `OSPData`. Only 1D strides are supported, additional
903strides between scanlines (2D, `byteStride2`) and slices (3D,
904`byteStride3`) are not.
905
906The parameters understood by structured volumes are summarized in the
907table below.
908
909| Type    | Name           |                       Default | Description                                                                                                            |
910|:--------|:---------------|------------------------------:|:-----------------------------------------------------------------------------------------------------------------------|
911| vec3f   | gridOrigin     |                       (0,0,0) | origin of the grid in object-space                                                                                     |
912| vec3f   | gridSpacing    |                       (1,1,1) | size of the grid cells in object-space                                                                                 |
913| OSPData | data           |                               | the actual voxel 3D [data](#data)                                                                                      |
914| int     | filter         | `OSP_VOLUME_FILTER_TRILINEAR` | filter used for reconstructing the field, also allowed is `OSP_VOLUME_FILTER_NEAREST` and `OSP_VOLUME_FILTER_TRICUBIC` |
915| int     | gradientFilter |              same as `filter` | filter used during gradient computations                                                                               |
916| float   | background     |                         `NaN` | value that is used when sampling an undefined region outside the volume domain                                         |
917
918Configuration parameters for structured regular volumes.
919
920The size of the volume is inferred from the size of the 3D array `data`,
921as is the type of the voxel values (currently supported are:
922`OSP_UCHAR`, `OSP_SHORT`, `OSP_USHORT`, `OSP_HALF`, `OSP_FLOAT`, and
923`OSP_DOUBLE`).
924
925### Structured Spherical Volume
926
927Structured spherical volumes are also supported, which are created by
928passing a type string of “`structuredSpherical`” to `ospNewVolume`. The
929grid dimensions and parameters are defined in terms of radial distance
930*r*, inclination angle *θ*, and azimuthal angle *ϕ*, conforming with the
931ISO convention for spherical coordinate systems. The coordinate system
932and parameters understood by structured spherical volumes are summarized
933below.
934
935<figure>
936<img src="https://ospray.github.io/images/structured_spherical_coords.svg" width="60.0%" alt="Coordinate system of structured spherical volumes." /><figcaption aria-hidden="true">Coordinate system of structured spherical volumes.</figcaption>
937</figure>
938
939
940
941| Type    | Name           |                       Default | Description                                                                           |
942|:--------|:---------------|------------------------------:|:--------------------------------------------------------------------------------------|
943| vec3f   | gridOrigin     |                       (0,0,0) | origin of the grid in units of (*r*,*θ*,*ϕ*); angles in degrees                       |
944| vec3f   | gridSpacing    |                       (1,1,1) | size of the grid cells in units of (*r*,*θ*,*ϕ*); angles in degrees                   |
945| OSPData | data           |                               | the actual voxel 3D [data](#data)                                                     |
946| int     | filter         | `OSP_VOLUME_FILTER_TRILINEAR` | filter used for reconstructing the field, also allowed is `OSP_VOLUME_FILTER_NEAREST` |
947| int     | gradientFilter |              same as `filter` | filter used during gradient computations                                              |
948| float   | background     |                         `NaN` | value that is used when sampling an undefined region outside the volume domain        |
949
950Configuration parameters for structured spherical volumes.
951
952The dimensions (*r*,*θ*,*ϕ*) of the volume are inferred from the size of
953the 3D array `data`, as is the type of the voxel values (currently
954supported are: `OSP_UCHAR`, `OSP_SHORT`, `OSP_USHORT`, `OSP_HALF`,
955`OSP_FLOAT`, and `OSP_DOUBLE`).
956
957These grid parameters support flexible specification of spheres,
958hemispheres, spherical shells, spherical wedges, and so forth. The grid
959extents (computed as
960`[gridOrigin, gridOrigin + (dimensions - 1) * gridSpacing]`) however
961must be constrained such that:
962
963-   *r* ≥ 0
964-   0 ≤ *θ* ≤ 180
965-   0 ≤ *ϕ* ≤ 360
966
967### Adaptive Mesh Refinement (AMR) Volume
968
969OSPRay currently supports block-structured (Berger-Colella) AMR volumes.
970Volumes are specified as a list of blocks, which exist at levels of
971refinement in potentially overlapping regions. Blocks exist in a tree
972structure, with coarser refinement level blocks containing finer blocks.
973The cell width is equal for all blocks at the same refinement level,
974though blocks at a coarser level have a larger cell width than finer
975levels.
976
977There can be any number of refinement levels and any number of blocks at
978any level of refinement. An AMR volume type is created by passing the
979type string “`amr`” to `ospNewVolume`.
980
981Blocks are defined by three parameters: their bounds, the refinement
982level in which they reside, and the scalar data contained within each
983block.
984
985Note that cell widths are defined *per refinement level*, not per block.
986
987| Type           | Name         |           Default | Description                                                                                                            |
988|:---------------|:-------------|------------------:|:-----------------------------------------------------------------------------------------------------------------------|
989| `OSPAMRMethod` | method       | `OSP_AMR_CURRENT` | `OSPAMRMethod` sampling method. Supported methods are:                                                                 |
990|                |              |                   | `OSP_AMR_CURRENT`                                                                                                      |
991|                |              |                   | `OSP_AMR_FINEST`                                                                                                       |
992|                |              |                   | `OSP_AMR_OCTANT`                                                                                                       |
993| float\[\]      | cellWidth    |              NULL | array of each level’s cell width                                                                                       |
994| box3i\[\]      | block.bounds |              NULL | [data](#data) array of grid sizes (in voxels) for each AMR block                                                       |
995| int\[\]        | block.level  |              NULL | array of each block’s refinement level                                                                                 |
996| OSPData\[\]    | block.data   |              NULL | [data](#data) array of OSPData containing the actual scalar voxel data, only `OSP_FLOAT` is supported as `OSPDataType` |
997| vec3f          | gridOrigin   |           (0,0,0) | origin of the grid                                                                                                     |
998| vec3f          | gridSpacing  |           (1,1,1) | size of the grid cells                                                                                                 |
999| float          | background   |             `NaN` | value that is used when sampling an undefined region outside the volume domain                                         |
1000
1001Configuration parameters for AMR volumes.
1002
1003Lastly, note that the `gridOrigin` and `gridSpacing` parameters act just
1004like the structured volume equivalent, but they only modify the root
1005(coarsest level) of refinement.
1006
1007In particular, OSPRay’s / Open VKL’s AMR implementation was designed to
1008cover Berger-Colella \[1\] and Chombo \[2\] AMR data. The `method`
1009parameter above determines the interpolation method used when sampling
1010the volume.
1011
1012OSP_AMR_CURRENT
1013finds the finest refinement level at that cell and interpolates through
1014this “current” level
1015
1016OSP_AMR_FINEST
1017will interpolate at the closest existing cell in the volume-wide finest
1018refinement level regardless of the sample cell’s level
1019
1020OSP_AMR_OCTANT
1021interpolates through all available refinement levels at that cell. This
1022method avoids discontinuities at refinement level boundaries at the cost
1023of performance
1024
1025Details and more information can be found in the publication for the
1026implementation \[3\].
1027
10281.  M.J. Berger and P. Colella, “Local adaptive mesh refinement for
1029    shock hydrodynamics.” Journal of Computational Physics 82.1 (1989):
1030    64-84. DOI: 10.1016/0021-9991(89)90035-1
10312.  M. Adams, P. Colella, D.T. Graves, J.N. Johnson, N.D. Keen, T.J.
1032    Ligocki, D.F. Martin. P.W. McCorquodale, D. Modiano. P.O. Schwartz,
1033    T.D. Sternberg, and B. Van Straalen, “Chombo Software Package for
1034    AMR Applications – Design Document”, Lawrence Berkeley National
1035    Laboratory Technical Report LBNL-6616E.
10363.  I. Wald, C. Brownlee, W. Usher, and A. Knoll, “CPU volume rendering
1037    of adaptive mesh refinement data”. SIGGRAPH Asia 2017 Symposium on
1038    Visualization – SA ’17, 18(8), 1–8. DOI: 10.1145/3139295.3139305
1039
1040### Unstructured Volume
1041
1042Unstructured volumes can have their topology and geometry freely
1043defined. Geometry can be composed of tetrahedral, hexahedral, wedge or
1044pyramid cell types. The data format used is compatible with VTK and
1045consists of multiple arrays: vertex positions and values, vertex
1046indices, cell start indices, cell types, and cell values. An
1047unstructured volume type is created by passing the type string
1048“`unstructured`” to `ospNewVolume`.
1049
1050Sampled cell values can be specified either per-vertex (`vertex.data`)
1051or per-cell (`cell.data`). If both arrays are set, `cell.data` takes
1052precedence.
1053
1054Similar to a mesh, each cell is formed by a group of indices into the
1055vertices. For each vertex, the corresponding (by array index) data value
1056will be used for sampling when rendering, if specified. The index order
1057for a tetrahedron is the same as `VTK_TETRA`: bottom triangle
1058counterclockwise, then the top vertex.
1059
1060For hexahedral cells, each hexahedron is formed by a group of eight
1061indices into the vertices and data values. Vertex ordering is the same
1062as `VTK_HEXAHEDRON`: four bottom vertices counterclockwise, then top
1063four counterclockwise.
1064
1065For wedge cells, each wedge is formed by a group of six indices into the
1066vertices and data values. Vertex ordering is the same as `VTK_WEDGE`:
1067three bottom vertices counterclockwise, then top three counterclockwise.
1068
1069For pyramid cells, each cell is formed by a group of five indices into
1070the vertices and data values. Vertex ordering is the same as
1071`VTK_PYRAMID`: four bottom vertices counterclockwise, then the top
1072vertex.
1073
1074To maintain VTK data compatibility, the `index` array may be specified
1075with cell sizes interleaved with vertex indices in the following format:
1076*n*, *i**d*<sub>1</sub>, ..., *i**d*<sub>*n*</sub>, *m*, *i**d*<sub>1</sub>, ..., *i**d*<sub>*m*</sub>.
1077This alternative `index` array layout can be enabled through the
1078`indexPrefixed` flag (in which case, the `cell.type` parameter must be
1079omitted).
1080
1081| Type                    | Name               | Default | Description                                                                                                                                             |
1082|:------------------------|:-------------------|--------:|:--------------------------------------------------------------------------------------------------------------------------------------------------------|
1083| vec3f\[\]               | vertex.position    |         | [data](#data) array of vertex positions                                                                                                                 |
1084| float\[\]               | vertex.data        |         | [data](#data) array of vertex data values to be sampled                                                                                                 |
1085| uint32\[\] / uint64\[\] | index              |         | [data](#data) array of indices (into the vertex array(s)) that form cells                                                                               |
1086| bool                    | indexPrefixed      |   false | indicates that the `index` array is compatible to VTK, where the indices of each cell are prefixed with the number of vertices                          |
1087| uint32\[\] / uint64\[\] | cell.index         |         | [data](#data) array of locations (into the index array), specifying the first index of each cell                                                        |
1088| float\[\]               | cell.data          |         | [data](#data) array of cell data values to be sampled                                                                                                   |
1089| uint8\[\]               | cell.type          |         | [data](#data) array of cell types (VTK compatible), only set if `indexPrefixed = false` false. Supported types are:                                     |
1090|                         |                    |         | `OSP_TETRAHEDRON`                                                                                                                                       |
1091|                         |                    |         | `OSP_HEXAHEDRON`                                                                                                                                        |
1092|                         |                    |         | `OSP_WEDGE`                                                                                                                                             |
1093|                         |                    |         | `OSP_PYRAMID`                                                                                                                                           |
1094| bool                    | hexIterative       |   false | hexahedron interpolation method, defaults to fast non-iterative version which could have rendering inaccuracies may appear if hex is not parallelepiped |
1095| bool                    | precomputedNormals |   false | whether to accelerate by precomputing, at a cost of 12 bytes/face                                                                                       |
1096| float                   | background         |   `NaN` | value that is used when sampling an undefined region outside the volume domain                                                                          |
1097
1098Configuration parameters for unstructured volumes.
1099
1100### VDB Volume
1101
1102VDB volumes implement a data structure that is very similar to the data
1103structure outlined in Museth \[1\], they are created by passing the type
1104string “`vdb`” to `ospNewVolume`.
1105
1106The data structure is a hierarchical regular grid at its core: Nodes are
1107regular grids, and each grid cell may either store a constant value
1108(this is called a tile), or child pointers. Nodes in VDB trees are wide:
1109Nodes on the first level have a resolution of 32<sup>3</sup> voxels, on
1110the next level 16<sup>3</sup>, and on the leaf level 8<sup>3</sup>
1111voxels. All nodes on a given level have the same resolution. This makes
1112it easy to find the node containing a coordinate using shift operations
1113(see \[1\]). VDB leaf nodes are implicit in OSPRay / Open VKL: they are
1114stored as pointers to user-provided data.
1115
1116<figure>
1117<img src="https://ospray.github.io/images/vdb_structure.png" width="80.0%" alt="Topology of VDB volumes." /><figcaption aria-hidden="true">Topology of VDB volumes.</figcaption>
1118</figure>
1119
1120
1121
1122VDB volumes interpret input data as constant cells (which are then
1123potentially filtered). This is in contrast to `structuredRegular`
1124volumes, which have a vertex-centered interpretation.
1125
1126The VDB implementation in OSPRay / Open VKL follows the following goals:
1127
1128-   Efficient data structure traversal on vector architectures.
1129-   Enable the use of industry-standard `.vdb` files created through the
1130    OpenVDB library.
1131-   Compatibility with OpenVDB on a leaf data level, so that `.vdb` file
1132    may be loaded with minimal overhead.
1133
1134VDB volumes have the following parameters:
1135
1136| Type        | Name             | Description                                                                                                                                                                                                                                                                                                                          |
1137|:------------|:-----------------|:-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
1138| int         | maxSamplingDepth | do not descend further than to this depth during sampling, the maximum value and the default is 3                                                                                                                                                                                                                                    |
1139| uint32\[\]  | node.level       | level on which each input node exists, may be 1, 2 or 3 (levels are counted from the root level = 0 down)                                                                                                                                                                                                                            |
1140| vec3i\[\]   | node.origin      | the node origin index (per input node)                                                                                                                                                                                                                                                                                               |
1141| OSPData\[\] | node.data        | [data](#data) arrays with the node data (per input node). Nodes that are tiles are expected to have single-item arrays. Leaf-nodes with grid data expected to have compact 3D arrays in zyx layout (z changes most quickly) with the correct number of voxels for the `level`. Only `OSP_FLOAT` is supported as field `OSPDataType`. |
1142| int         | filter           | filter used for reconstructing the field, default is `OSP_VOLUME_FILTER_TRILINEAR`, alternatively `OSP_VOLUME_FILTER_NEAREST`, or `OSP_VOLUME_FILTER_TRICUBIC`.                                                                                                                                                                      |
1143| int         | gradientFilter   | filter used for reconstructing the field during gradient computations, default same as `filter`                                                                                                                                                                                                                                      |
1144| float       | background       | value that is used when sampling an undefined region outside the volume domain, default `NaN`                                                                                                                                                                                                                                        |
1145
1146Configuration parameters for VDB volumes.
1147
11481.  Museth, K. VDB: High-Resolution Sparse Volumes with Dynamic
1149    Topology. ACM Transactions on Graphics 32(3), 2013. DOI:
1150    10.1145/2487228.2487235
1151
1152### Particle Volume
1153
1154Particle volumes consist of a set of points in space. Each point has a
1155position, a radius, and a weight typically associated with an attribute.
1156Particle volumes are created by passing the type string “`particle`” to
1157`ospNewVolume`.
1158
1159A radial basis function defines the contribution of that particle.
1160Currently, we use the Gaussian radial basis function
1161$$\\phi(P) = w \\exp\\left(-\\frac{(P - p)^2}{2 r^2}\\right),$$
1162where *P* is the particle position, *p* is the sample position, *r* is
1163the radius and *w* is the weight. At each sample, the scalar field value
1164is then computed as the sum of each radial basis function *ϕ*, for each
1165particle that overlaps it.
1166
1167The OSPRay / Open VKL implementation is similar to direct evaluation of
1168samples in Reda et al. \[2\]. It uses an Embree-built BVH with a custom
1169traversal, similar to the method in \[1\].
1170
1171| Type      | Name                    | Default | Description                                                                                                                                                                                                                                                                                                                                                                                                    |
1172|:----------|:------------------------|--------:|:---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
1173| vec3f\[\] | particle.position       |         | [data](#data) array of particle positions                                                                                                                                                                                                                                                                                                                                                                      |
1174| float\[\] | particle.radius         |         | [data](#data) array of particle radii                                                                                                                                                                                                                                                                                                                                                                          |
1175| float\[\] | particle.weight         |    NULL | optional [data](#data) array of particle weights, specifying the height of the kernel.                                                                                                                                                                                                                                                                                                                         |
1176| float     | radiusSupportFactor     |     3.0 | The multiplier of the particle radius required for support. Larger radii ensure smooth results at the cost of performance. In the Gaussian kernel, the radius is one standard deviation (*σ*), so a value of 3 corresponds to 3*σ*.                                                                                                                                                                            |
1177| float     | clampMaxCumulativeValue |       0 | The maximum cumulative value possible, set by user. All cumulative values will be clamped to this, and further traversal (RBF summation) of particle contributions will halt when this value is reached. A value of zero or less turns this off.                                                                                                                                                               |
1178| bool      | estimateValueRanges     |    true | Enable heuristic estimation of value ranges which are used in internal acceleration structures as well as for determining the volume’s overall value range. When set to `false`, the user *must* specify `clampMaxCumulativeValue`, and all value ranges will be assumed \[0–`clampMaxCumulativeValue`\]. Disabling this switch may improve volume commit time, but will make volume rendering less efficient. |
1179
1180Configuration parameters for particle volumes.
1181
11821.  A. Knoll, I. Wald, P. Navratil, A. Bowen, K. Reda, M.E., Papka,
1183    and K. Gaither, “RBF Volume Ray Casting on Multicore and Manycore
1184    CPUs”, 2014, Computer Graphics Forum, 33: 71–80.
1185    doi:10.1111/cgf.12363
1186
11872.  K. Reda, A. Knoll, K. Nomura, M. E. Papka, A. E. Johnson and J.
1188    Leigh, “Visualizing large-scale atomistic simulations in
1189    ultra-resolution immersive environments”, 2013 IEEE Symposium on
1190    Large-Scale Data Analysis and Visualization (LDAV), Atlanta, GA,
1191    2013, pp. 59–65.
1192
1193### Transfer Function
1194
1195Transfer functions map the scalar values of volumes to color and opacity
1196and thus they can be used to visually emphasize certain features of the
1197volume. To create a new transfer function of given type `type` use
1198
1199``` cpp
1200OSPTransferFunction ospNewTransferFunction(const char *type);
1201```
1202
1203The returned handle can be assigned to a volumetric model (described
1204below) as parameter “`transferFunction`” using `ospSetObject`.
1205
1206One type of transfer function that is supported by OSPRay is the linear
1207transfer function, which interpolates between given equidistant colors
1208and opacities. It is create by passing the string “`piecewiseLinear`” to
1209`ospNewTransferFunction` and it is controlled by these parameters:
1210
1211| Type      | Name       | Description                                   |
1212|:----------|:-----------|:----------------------------------------------|
1213| vec3f\[\] | color      | [data](#data) array of colors (linear RGB)    |
1214| float\[\] | opacity    | [data](#data) array of opacities              |
1215| vec2f     | valueRange | domain (scalar range) this function maps from |
1216
1217Parameters accepted by the linear transfer function.
1218
1219The arrays `color` and `opacity` can be of different length.
1220
1221### VolumetricModels
1222
1223Volumes in OSPRay are given volume rendering appearance information
1224through VolumetricModels. This decouples the physical representation of
1225the volume (and possible acceleration structures it contains) to
1226rendering-specific parameters (where more than one set may exist
1227concurrently). To create a volume instance, call
1228
1229``` cpp
1230OSPVolumetricModel ospNewVolumetricModel(OSPVolume volume);
1231```
1232
1233The passed volume can be `NULL` as long as the volume to be used is
1234passed as a parameter. If both a volume is specified on object creation
1235and as a parameter, the parameter value is used. If the parameter value
1236is later removed, the volume object passed on object creation is again
1237used.
1238
1239| Type                | Name             | Default | Description                                                                                                                          |
1240|:--------------------|:-----------------|--------:|:-------------------------------------------------------------------------------------------------------------------------------------|
1241| OSPTransferFunction | transferFunction |         | [transfer function](#transfer-function) to use                                                                                       |
1242| float               | densityScale     |     1.0 | makes volumes uniformly thinner or thicker                                                                                           |
1243| float               | anisotropy       |     0.0 | anisotropy of the (Henyey-Greenstein) phase function in \[-1–1\] ([path tracer](#path-tracer) only), default to isotropic scattering |
1244| OSPVolume           | volume           |         | optional [volume](#volumes) object this model references                                                                             |
1245
1246Parameters understood by VolumetricModel.
1247
1248Geometries
1249----------
1250
1251Geometries in OSPRay are objects that describe intersectable surfaces.
1252To create a new geometry object of given type `type` use
1253
1254``` cpp
1255OSPGeometry ospNewGeometry(const char *type);
1256```
1257
1258Note that in the current implementation geometries are limited to a
1259maximum of 2<sup>32</sup> primitives.
1260
1261### Mesh
1262
1263A mesh consisting of either triangles or quads is created by calling
1264`ospNewGeometry` with type string “`mesh`”. Once created, a mesh
1265recognizes the following parameters:
1266
1267| Type                    | Name            | Description                                                                         |
1268|:------------------------|:----------------|:------------------------------------------------------------------------------------|
1269| vec3f\[\]               | vertex.position | [data](#data) array of vertex positions                                             |
1270| vec3f\[\]               | vertex.normal   | [data](#data) array of vertex normals                                               |
1271| vec4f\[\] / vec3f\[\]   | vertex.color    | [data](#data) array of vertex colors (linear RGBA/RGB)                              |
1272| vec2f\[\]               | vertex.texcoord | [data](#data) array of vertex texture coordinates                                   |
1273| vec3ui\[\] / vec4ui\[\] | index           | [data](#data) array of (either triangle or quad) indices (into the vertex array(s)) |
1274
1275Parameters defining a mesh geometry.
1276
1277The data type of index arrays differentiates between the underlying
1278geometry, triangles are used for a index with `vec3ui` type and quads
1279for `vec4ui` type. Quads are internally handled as a pair of two
1280triangles, thus mixing triangles and quads is supported by encoding some
1281triangle as a quad with the last two vertex indices being identical
1282(`w=z`).
1283
1284The `vertex.position` and `index` arrays are mandatory to create a valid
1285mesh.
1286
1287### Subdivision
1288
1289A mesh consisting of subdivision surfaces, created by specifying a
1290geometry of type “`subdivision`”. Once created, a subdivision recognizes
1291the following parameters:
1292
1293| Type      | Name                | Description                                                                                                           |
1294|:----------|:--------------------|:----------------------------------------------------------------------------------------------------------------------|
1295| vec3f\[\] | vertex.position     | [data](#data) array of vertex positions                                                                               |
1296| vec4f\[\] | vertex.color        | optional [data](#data) array of vertex colors (linear RGBA)                                                           |
1297| vec2f\[\] | vertex.texcoord     | optional [data](#data) array of vertex texture coordinates                                                            |
1298| float     | level               | global level of tessellation, default 5                                                                               |
1299| uint\[\]  | index               | [data](#data) array of indices (into the vertex array(s))                                                             |
1300| float\[\] | index.level         | optional [data](#data) array of per-edge levels of tessellation, overrides global level                               |
1301| uint\[\]  | face                | optional [data](#data) array holding the number of indices/edges (3 to 15) per face, defaults to 4 (a pure quad mesh) |
1302| vec2i\[\] | edgeCrease.index    | optional [data](#data) array of edge crease indices                                                                   |
1303| float\[\] | edgeCrease.weight   | optional [data](#data) array of edge crease weights                                                                   |
1304| uint\[\]  | vertexCrease.index  | optional [data](#data) array of vertex crease indices                                                                 |
1305| float\[\] | vertexCrease.weight | optional [data](#data) array of vertex crease weights                                                                 |
1306| uchar     | mode                | subdivision edge boundary mode, supported modes are:                                                                  |
1307|           |                     | `OSP_SUBDIVISION_NO_BOUNDARY`                                                                                         |
1308|           |                     | `OSP_SUBDIVISION_SMOOTH_BOUNDARY` (default)                                                                           |
1309|           |                     | `OSP_SUBDIVISION_PIN_CORNERS`                                                                                         |
1310|           |                     | `OSP_SUBDIVISION_PIN_BOUNDARY`                                                                                        |
1311|           |                     | `OSP_SUBDIVISION_PIN_ALL`                                                                                             |
1312
1313Parameters defining a Subdivision geometry.
1314
1315The `vertex` and `index` arrays are mandatory to create a valid
1316subdivision surface. If no `face` array is present then a pure quad mesh
1317is assumed (the number of indices must be a multiple of 4). Optionally
1318supported are edge and vertex creases.
1319
1320### Spheres
1321
1322A geometry consisting of individual spheres, each of which can have an
1323own radius, is created by calling `ospNewGeometry` with type string
1324“`sphere`”. The spheres will not be tessellated but rendered
1325procedurally and are thus perfectly round. To allow a variety of sphere
1326representations in the application this geometry allows a flexible way
1327of specifying the data of center position and radius within a
1328[data](#data) array:
1329
1330| Type      | Name            | Default | Description                                                               |
1331|:----------|:----------------|--------:|:--------------------------------------------------------------------------|
1332| vec3f\[\] | sphere.position |         | [data](#data) array of center positions                                   |
1333| float\[\] | sphere.radius   |    NULL | optional [data](#data) array of the per-sphere radius                     |
1334| vec2f\[\] | sphere.texcoord |    NULL | optional [data](#data) array of texture coordinates (constant per sphere) |
1335| float     | radius          |    0.01 | default radius for all spheres (if `sphere.radius` is not set)            |
1336
1337Parameters defining a spheres geometry.
1338
1339### Curves
1340
1341A geometry consisting of multiple curves is created by calling
1342`ospNewGeometry` with type string “`curve`”. The parameters defining
1343this geometry are listed in the table below.
1344
1345| Type       | Name                   | Description                                                                      |
1346|:-----------|:-----------------------|:---------------------------------------------------------------------------------|
1347| vec4f\[\]  | vertex.position_radius | [data](#data) array of vertex position and per-vertex radius                     |
1348| vec2f\[\]  | vertex.texcoord        | [data](#data) array of per-vertex texture coordinates                            |
1349| vec4f\[\]  | vertex.color           | [data](#data) array of corresponding vertex colors (linear RGBA)                 |
1350| vec3f\[\]  | vertex.normal          | [data](#data) array of curve normals (only for “ribbon” curves)                  |
1351| vec4f\[\]  | vertex.tangent         | [data](#data) array of curve tangents (only for “hermite” curves)                |
1352| uint32\[\] | index                  | [data](#data) array of indices to the first vertex or tangent of a curve segment |
1353| uchar      | type                   | `OSPCurveType` for rendering the curve. Supported types are:                     |
1354|            |                        | `OSP_FLAT`                                                                       |
1355|            |                        | `OSP_ROUND`                                                                      |
1356|            |                        | `OSP_RIBBON`                                                                     |
1357|            |                        | `OSP_DISJOINT`                                                                   |
1358| uchar      | basis                  | `OSPCurveBasis` for defining the curve. Supported bases are:                     |
1359|            |                        | `OSP_LINEAR`                                                                     |
1360|            |                        | `OSP_BEZIER`                                                                     |
1361|            |                        | `OSP_BSPLINE`                                                                    |
1362|            |                        | `OSP_HERMITE`                                                                    |
1363|            |                        | `OSP_CATMULL_ROM`                                                                |
1364
1365Parameters defining a curves geometry.
1366
1367Positions in `vertex.position_radius` parameter supports per-vertex
1368varying radii with data type `vec4f[]` and instantiate Embree curves
1369internally for the relevant type/basis mapping.
1370
1371The following section describes the properties of different curve basis’
1372and how they use the data provided in data buffers:
1373
1374OSP_LINEAR
1375The indices point to the first of 2 consecutive control points in the
1376vertex buffer. The first control point is the start and the second
1377control point the end of the line segment. The curve goes through all
1378control points listed in the vertex buffer.
1379
1380OSP_BEZIER
1381The indices point to the first of 4 consecutive control points in the
1382vertex buffer. The first control point represents the start point of the
1383curve, and the 4th control point the end point of the curve. The Bézier
1384basis is interpolating, thus the curve does go exactly through the first
1385and fourth control vertex.
1386
1387OSP_BSPLINE
1388The indices point to the first of 4 consecutive control points in the
1389vertex buffer. This basis is not interpolating, thus the curve does in
1390general not go through any of the control points directly. Using this
1391basis, 3 control points can be shared for two continuous neighboring
1392curve segments, e.g., the curves (*p*0,*p*1,*p*2,*p*3) and
1393(*p*1,*p*2,*p*3,*p*4) are C1 continuous. This feature make this basis a
1394good choice to construct continuous multi-segment curves, as memory
1395consumption can be kept minimal.
1396
1397OSP_HERMITE
1398It is necessary to have both vertex buffer and tangent buffer for using
1399this basis. The indices point to the first of 2 consecutive points in
1400the vertex buffer, and the first of 2 consecutive tangents in the
1401tangent buffer. This basis is interpolating, thus does exactly go
1402through the first and second control point, and the first order
1403derivative at the begin and end matches exactly the value specified in
1404the tangent buffer. When connecting two segments continuously, the end
1405point and tangent of the previous segment can be shared.
1406
1407OSP_CATMULL_ROM
1408The indices point to the first of 4 consecutive control points in the
1409vertex buffer. If (*p*0,*p*1,*p*2,*p*3) represent the points then this
1410basis goes through *p*1 and *p*2, with tangents as (*p*2−*p*0)/2 and
1411(*p*3−*p*1)/2.
1412
1413The following section describes the properties of different curve types’
1414and how they define the geometry of a curve:
1415
1416OSP_FLAT
1417This type enables faster rendering as the curve is rendered as a
1418connected sequence of ray facing quads.
1419
1420OSP_ROUND
1421This type enables rendering a real geometric surface for the curve which
1422allows closeup views. This mode renders a sweep surface by sweeping a
1423varying radius circle tangential along the curve.
1424
1425OSP_RIBBON
1426The type enables normal orientation of the curve and requires a normal
1427buffer be specified along with vertex buffer. The curve is rendered as a
1428flat band whose center approximately follows the provided vertex buffer
1429and whose normal orientation approximately follows the provided normal
1430buffer. Not supported for basis `OSP_LINEAR`.
1431
1432OSP_DISJOINT
1433Only supported for basis `OSP_LINEAR`; the segments are open and not
1434connected at the joints, i.e., the curve segments are either individual
1435cones or cylinders.
1436
1437### Boxes
1438
1439OSPRay can directly render axis-aligned bounding boxes without the need
1440to convert them to quads or triangles. To do so create a boxes geometry
1441by calling `ospNewGeometry` with type string “`box`”.
1442
1443| Type      | Name | Description                  |
1444|:----------|:-----|:-----------------------------|
1445| box3f\[\] | box  | [data](#data) array of boxes |
1446
1447Parameters defining a boxes geometry.
1448
1449### Planes
1450
1451OSPRay can directly render planes defined by plane equation coefficients
1452in its implicit form *a**x* + *b**y* + *c**z* + *d* = 0. By default
1453planes are infinite but their extents can be limited by defining
1454optional bounding boxes. A planes geometry can be created by calling
1455`ospNewGeometry` with type string “`plane`”.
1456
1457| Type      | Name               | Description                                                 |
1458|:----------|:-------------------|:------------------------------------------------------------|
1459| vec4f\[\] | plane.coefficients | [data](#data) array of plane coefficients (*a*,*b*,*c*,*d*) |
1460| box3f\[\] | plane.bounds       | optional [data](#data) array of bounding boxes              |
1461
1462Parameters defining a planes geometry.
1463
1464### Isosurfaces
1465
1466OSPRay can directly render multiple isosurfaces of a volume without
1467first tessellating them. To do so create an isosurfaces geometry by
1468calling `ospNewGeometry` with type string “`isosurface`”. The appearance
1469information of the surfaces is set through the Geometric Model.
1470Per-isosurface colors can be set by passing per-primitive colors to the
1471Geometric Model, in order of the isosurface array.
1472
1473| Type      | Name     | Description                                        |
1474|:----------|:---------|:---------------------------------------------------|
1475| float     | isovalue | single isovalues                                   |
1476| float\[\] | isovalue | [data](#data) array of isovalues                   |
1477| OSPVolume | volume   | handle of the [Volume](#volumes) to be isosurfaced |
1478
1479Parameters defining an isosurfaces geometry.
1480
1481### GeometricModels
1482
1483Geometries are matched with surface appearance information through
1484GeometricModels. These take a geometry, which defines the surface
1485representation, and applies either full-object or per-primitive color
1486and material information. To create a geometric model, call
1487
1488``` cpp
1489OSPGeometricModel ospNewGeometricModel(OSPGeometry geometry);
1490```
1491
1492The passed geometry can be `NULL` as long as the geometry to be used is
1493passed as a parameter. If both a geometry is specified on object
1494creation and as a parameter, the parameter value is used. If the
1495parameter value is later removed, the geometry object passed on object
1496creation is again used.
1497
1498Color and material are fetched with the primitive ID of the hit (clamped
1499to the valid range, thus a single color or material is fine), or mapped
1500first via the `index` array (if present). All parameters are optional,
1501however, some renderers (notably the [path tracer](#path-tracer))
1502require a material to be set. Materials are either handles of
1503`OSPMaterial`, or indices into the `material` array on the
1504[renderer](#renderers), which allows to build a [world](#world) which
1505can be used by different types of renderers.
1506
1507An `invertNormals` flag allows to invert (shading) normal vectors of the
1508rendered geometry. That is particularly useful for clipping. By changing
1509normal vectors orientation one can control whether inside or outside of
1510the clipping geometry is being removed. For example, a clipping geometry
1511with normals oriented outside clips everything what’s inside.
1512
1513| Type                         | Name          | Description                                                                                                                                         |
1514|:-----------------------------|:--------------|:----------------------------------------------------------------------------------------------------------------------------------------------------|
1515| OSPMaterial / uint32         | material      | optional [material](#materials) applied to the geometry, may be an index into the `material` parameter on the [renderer](#renderers) (if it exists) |
1516| vec4f                        | color         | optional color assigned to the geometry (linear RGBA)                                                                                               |
1517| OSPMaterial\[\] / uint32\[\] | material      | optional [data](#data) array of (per-primitive) materials, may be an index into the `material` parameter on the renderer (if it exists)             |
1518| vec4f\[\]                    | color         | optional [data](#data) array of (per-primitive) colors (linear RGBA)                                                                                |
1519| uint8\[\]                    | index         | optional [data](#data) array of per-primitive indices into `color` and `material`                                                                   |
1520| bool                         | invertNormals | inverts all shading normals (Ns), default false                                                                                                     |
1521| OSPGeometry                  | geometry      | optional \[geometry\] object this model references                                                                                                  |
1522
1523Parameters understood by GeometricModel.
1524
1525Lights
1526------
1527
1528To create a new light source of given type `type` use
1529
1530``` cpp
1531OSPLight ospNewLight(const char *type);
1532```
1533
1534All light sources accept the following parameters:
1535
1536| Type  | Name              | Default | Description                                                                                                                       |
1537|:------|:------------------|--------:|:----------------------------------------------------------------------------------------------------------------------------------|
1538| vec3f | color             |   white | color of the light (linear RGB)                                                                                                   |
1539| float | intensity         |       1 | intensity of the light (a factor)                                                                                                 |
1540| uchar | intensityQuantity |         | `OSPIntensityQuantity` to set the radiometric quantity represented by `intensity`. The default value depends on the light source. |
1541| bool  | visible           |    true | whether the light can be directly seen                                                                                            |
1542
1543Parameters accepted by all lights.
1544
1545In OSPRay the `intensity` parameter of a light source can correspond to
1546different types of radiometric quantities. The type of the value
1547represented by a light’s `intensity` parameter is set using
1548`intensityQuantity`, which accepts values from the enum type
1549`OSPIntensityQuantity`. The supported types of `OSPIntensityQuantity`
1550differ between the different light sources (see documentation of each
1551specific light source).
1552
1553| Name                              | Description                                                                                                                     |
1554|:----------------------------------|:--------------------------------------------------------------------------------------------------------------------------------|
1555| OSP_INTENSITY_QUANTITY_POWER      | the overall amount of light energy emitted by the light source into the scene, unit is W                                        |
1556| OSP_INTENSITY_QUANTITY_INTENSITY  | the overall amount of light emitted by the light in a given direction, unit is W/sr                                             |
1557| OSP_INTENSITY_QUANTITY_RADIANCE   | the amount of light emitted by a point on the light source in a given direction, unit is W/sr/m<sup>2</sup>                     |
1558| OSP_INTENSITY_QUANTITY_IRRADIANCE | the amount of light arriving at a surface point, assuming the light is oriented towards to the surface, unit is W/m<sup>2</sup> |
1559| OSP_INTENSITY_QUANTITY_SCALE      | a linear scaling factor for light sources with a built-in quantity (e.g., `HDRI`, or `sunSky`).                                 |
1560
1561Types of radiometric quantities used to interpret a light’s `intensity`
1562parameter.
1563
1564The following light types are supported by most OSPRay renderers.
1565
1566### Directional Light / Distant Light
1567
1568The distant light (or traditionally the directional light) is thought to
1569be far away (outside of the scene), thus its light arrives (almost) as
1570parallel rays. It is created by passing the type string “`distant`” to
1571`ospNewLight`. The distant light supports
1572`OSP_INTENSITY_QUANTITY_RADIANCE` and
1573`OSP_INTENSITY_QUANTITY_IRRADIANCE` (default) as `intensityQuantity`
1574parameter value. In addition to the [general parameters](#lights)
1575understood by all lights the distant light supports the following
1576special parameters:
1577
1578| Type  | Name            | Default | Description                                  |
1579|:------|:----------------|--------:|:---------------------------------------------|
1580| vec3f | direction       | (0,0,1) | main emission direction of the distant light |
1581| float | angularDiameter |       0 | apparent size (angle in degree) of the light |
1582
1583Special parameters accepted by the distant light.
1584
1585Setting the angular diameter to a value greater than zero will result in
1586soft shadows when the renderer uses stochastic sampling (like the [path
1587tracer](#path-tracer)). For instance, the apparent size of the sun is
1588about 0.53°.
1589
1590### Point Light / Sphere Light
1591
1592The sphere light (or the special case point light) is a light emitting
1593uniformly in all directions from the surface toward the outside. It does
1594not emit any light toward the inside of the sphere. It is created by
1595passing the type string “`sphere`” to `ospNewLight`. The point light
1596supports `OSP_INTENSITY_QUANTITY_POWER`,
1597`OSP_INTENSITY_QUANTITY_INTENSITY` (default) and
1598`OSP_INTENSITY_QUANTITY_RADIANCE` as `intensityQuantity` parameter
1599value. In addition to the [general parameters](#lights) understood by
1600all lights the sphere light supports the following special parameters:
1601
1602| Type  | Name     | Default | Description                    |
1603|:------|:---------|--------:|:-------------------------------|
1604| vec3f | position | (0,0,0) | the center of the sphere light |
1605| float | radius   |       0 | the size of the sphere light   |
1606
1607Special parameters accepted by the sphere light.
1608
1609Setting the radius to a value greater than zero will result in soft
1610shadows when the renderer uses stochastic sampling (like the [path
1611tracer](#path-tracer)).
1612
1613### Spotlight / Photometric Light
1614
1615The spotlight is a light emitting into a cone of directions. It is
1616created by passing the type string “`spot`” to `ospNewLight`. The
1617spotlight supports `OSP_INTENSITY_QUANTITY_POWER`,
1618`OSP_INTENSITY_QUANTITY_INTENSITY` (default) and
1619`OSP_INTENSITY_QUANTITY_RADIANCE` as `intensityQuantity` parameter
1620value. In addition to the [general parameters](#lights) understood by
1621all lights the spotlight supports the special parameters listed in the
1622table.
1623
1624| Type      | Name                  | Default | Description                                                                                                                                                                   |
1625|:----------|:----------------------|--------:|:------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
1626| vec3f     | position              | (0,0,0) | the center of the spotlight                                                                                                                                                   |
1627| vec3f     | direction             | (0,0,1) | main emission direction of the spot                                                                                                                                           |
1628| float     | openingAngle          |     180 | full opening angle (in degree) of the spot; outside of this cone is no illumination                                                                                           |
1629| float     | penumbraAngle         |       5 | size (angle in degree) of the “penumbra”, the region between the rim (of the illumination cone) and full intensity of the spot; should be smaller than half of `openingAngle` |
1630| float     | radius                |       0 | the size of the spotlight, the radius of a disk with normal `direction`                                                                                                       |
1631| float     | innerRadius           |       0 | in combination with `radius` turns the disk into a ring                                                                                                                       |
1632| float\[\] | intensityDistribution |         | luminous intensity distribution for photometric lights; can be 2D for asymmetric illumination; values are assumed to be uniformly distributed                                 |
1633| vec3f     | c0                    |         | orientation, i.e., direction of the C0-(half)plane (only needed if illumination via `intensityDistribution` is asymmetric)                                                    |
1634
1635Special parameters accepted by the spotlight.
1636
1637![Angles used by the
1638spotlight.](https://ospray.github.io/images/spot_light.png)
1639
1640Setting the radius to a value greater than zero will result in soft
1641shadows when the renderer uses stochastic sampling (like the [path
1642tracer](#path-tracer)). Additionally setting the inner radius will
1643result in a ring instead of a disk emitting the light.
1644
1645Measured light sources (IES, EULUMDAT, …) are supported by providing an
1646`intensityDistribution` [data](#data) array to modulate the intensity
1647per direction. The mapping is using the C-γ coordinate system (see also
1648below figure): the values of the first (or only) dimension of
1649`intensityDistribution` are uniformly mapped to γ in \[0–π\]; the first
1650intensity value to 0, the last value to π, thus at least two values need
1651to be present. If the array has a second dimension then the intensities
1652are not rotational symmetric around `direction`, but are accordingly
1653mapped to the C-halfplanes in \[0–2π\]; the first “row” of values to 0
1654and 2π, the other rows such that they have uniform distance to its
1655neighbors. The orientation of the C0-plane is specified via `c0`. A
1656combination of using an `intensityDistribution` and
1657`OSP_INTENSITY_QUANTITY_POWER` as `intensityQuantity` is not supported
1658at the moment.
1659
1660![C-γ coordinate system for the mapping of `intensityDistribution` to
1661the spotlight.](https://ospray.github.io/images/spot_coords.png)
1662
1663### Quad Light
1664
1665The quad[5] light is a planar, procedural area light source emitting
1666uniformly on one side into the half-space. It is created by passing the
1667type string “`quad`” to `ospNewLight`. The quad light supports
1668`OSP_INTENSITY_QUANTITY_POWER`, `OSP_INTENSITY_QUANTITY_INTENSITY` and
1669`OSP_INTENSITY_QUANTITY_RADIANCE` (default) as `intensityQuantity`
1670parameter. In addition to the [general parameters](#lights) understood
1671by all lights the quad light supports the following special parameters:
1672
1673| Type  | Name     | Default | Description                              |
1674|:------|:---------|--------:|:-----------------------------------------|
1675| vec3f | position | (0,0,0) | position of one vertex of the quad light |
1676| vec3f | edge1    | (1,0,0) | vector to one adjacent vertex            |
1677| vec3f | edge2    | (0,1,0) | vector to the other adjacent vertex      |
1678
1679Special parameters accepted by the quad light.
1680
1681![Defining a quad light which emits toward the
1682reader.](https://ospray.github.io/images/quad_light.png)
1683
1684The emission side is determined by the cross product of `edge1`×`edge2`.
1685Note that only renderers that use stochastic sampling (like the path
1686tracer) will compute soft shadows from the quad light. Other renderers
1687will just sample the center of the quad light, which results in hard
1688shadows.
1689
1690### Cylinder Light
1691
1692The cylinder light is a cylinderical, procedural area light source
1693emitting uniformly outwardly into the space beyond the boundary. It is
1694created by passing the type string “`cylinder`” to `ospNewLight`. The
1695cylinder light supports `OSP_INTENSITY_QUANTITY_POWER`,
1696`OSP_INTENSITY_QUANTITY_INTENSITY` and `OSP_INTENSITY_QUANTITY_RADIANCE`
1697(default) as `intensityQuantity` parameter. In addition to the [general
1698parameters](#lights) understood by all lights the cylinder light
1699supports the following special parameters:
1700
1701| Type  | Name      | Default | Description                           |
1702|:------|:----------|--------:|:--------------------------------------|
1703| vec3f | position0 | (0,0,0) | position of the start of the cylinder |
1704| vec3f | position1 | (0,0,1) | position of the end of the cylinder   |
1705| float | radius    |       1 | radius of the cylinder                |
1706
1707Special parameters accepted by the cylinder light.
1708
1709Note that only renderers that use stochastic sampling (like the path
1710tracer) will compute soft shadows from the cylinder light. Other
1711renderers will just sample the closest point on the cylinder light,
1712which results in hard shadows.
1713
1714### HDRI Light
1715
1716The HDRI light is a textured light source surrounding the scene and
1717illuminating it from infinity. It is created by passing the type string
1718“`hdri`” to `ospNewLight`. The values of the HDRI correspond to radiance
1719and therefore the HDRI light only accepts `OSP_INTENSITY_QUANTITY_SCALE`
1720as `intensityQuantity` parameter value. In addition to the [general
1721parameters](#lights) the HDRI light supports the following special
1722parameters:
1723
1724| Type       | Name      | Default | Description                                                                                                      |
1725|:-----------|:----------|--------:|:-----------------------------------------------------------------------------------------------------------------|
1726| vec3f      | up        | (0,1,0) | up direction of the light                                                                                        |
1727| vec3f      | direction | (0,0,1) | direction to which the center of the texture will be mapped to (analog to [panoramic camera](#panoramic-camera)) |
1728| OSPTexture | map       |         | environment map in latitude / longitude format                                                                   |
1729
1730Special parameters accepted by the HDRI light.
1731
1732![Orientation and Mapping of an HDRI
1733Light.](https://ospray.github.io/images/hdri_light.png)
1734
1735Note that the [SciVis renderer](#scivis-renderer) only shows the HDRI
1736light in the background (like an environment map) without computing
1737illumination of the scene.
1738
1739### Ambient Light
1740
1741The ambient light surrounds the scene and illuminates it from infinity
1742with constant radiance (determined by combining the [parameters `color`
1743and `intensity`](#lights)). It is created by passing the type string
1744“`ambient`” to `ospNewLight`. The ambient light supports
1745`OSP_INTENSITY_QUANTITY_RADIANCE` and
1746`OSP_INTENSITY_QUANTITY_IRRADIANCE` (default) as `intensityQuantity`
1747parameter value.
1748
1749Note that the [SciVis renderer](#scivis-renderer) uses ambient lights to
1750control the color and intensity of the computed ambient occlusion (AO).
1751
1752### Sun-Sky Light
1753
1754The sun-sky light is a combination of a `distant` light for the sun and
1755a procedural `hdri` light for the sky. It is created by passing the type
1756string “`sunSky`” to `ospNewLight`. The sun-sky light surrounds the
1757scene and illuminates it from infinity and can be used for rendering
1758outdoor scenes. The radiance values are calculated using the
1759Hošek-Wilkie sky model and solar radiance function. The underlying model
1760of the sun-sky light returns radiance values and therefore the light
1761only accepts `OSP_INTENSITY_QUANTITY_SCALE` as `intensityQuantity`
1762parameter value. To rescale the returned radiance of the sky model the
1763default value for the `intensity` parameter is set to `0.025`. In
1764addition to the [general parameters](#lights) the following special
1765parameters are supported:
1766
1767| Type  | Name             |  Default | Description                                                                                          |
1768|:------|:-----------------|---------:|:-----------------------------------------------------------------------------------------------------|
1769| vec3f | up               |  (0,1,0) | zenith of sky                                                                                        |
1770| vec3f | direction        | (0,−1,0) | main emission direction of the sun                                                                   |
1771| float | turbidity        |        3 | atmospheric turbidity due to particles, in \[1–10\]                                                  |
1772| float | albedo           |      0.3 | ground reflectance, in \[0–1\]                                                                       |
1773| float | horizonExtension |     0.01 | extend the sky dome by stretching the horizon, fraction of the lower hemisphere to cover, in \[0–1\] |
1774
1775Special parameters accepted by the `sunSky` light.
1776
1777The lowest elevation for the sun is restricted to the horizon.
1778
1779Note that the [SciVis renderer](#scivis-renderer) only computes
1780illumination from the sun (yet the sky is still shown in the background,
1781like an environment map).
1782
1783### Emissive Objects
1784
1785The [path tracer](#path-tracer) will consider illumination by
1786[geometries](#geometries) which have a light emitting material assigned
1787(for example the [Luminous](#luminous) material).
1788
1789Scene Hierarchy
1790---------------
1791
1792### Groups
1793
1794Groups in OSPRay represent collections of GeometricModels,
1795VolumetricModels and Lights which share a common local-space coordinate
1796system. To create a group call
1797
1798``` cpp
1799OSPGroup ospNewGroup();
1800```
1801
1802Groups take arrays of geometric models, volumetric models, clipping
1803geometric models and lights, but they are all optional. In other words,
1804there is no need to create empty arrays if there are no geometries,
1805volumes or lights in the group.
1806
1807By adding `OSPGeometricModel`s to the `clippingGeometry` array a
1808clipping geometry feature is enabled. Geometries assigned to this
1809parameter will be used as clipping geometries. Any supported geometry
1810can be used for clipping[6], the only requirement is that it has to
1811distinctly partition space into clipping and non-clipping one. The use
1812of clipping geometry that is not closed or infinite could result in
1813rendering artifacts. User can decide which part of space is clipped by
1814changing shading normals orientation with the `invertNormals` flag of
1815the [GeometricModel](#geometricmodels). All geometries and volumes
1816assigned to `geometry` or `volume` will be clipped. All clipping
1817geometries from all groups and [Instances](#instances) will be combined
1818together – a union of these areas will be applied to all other objects
1819in the [world](#world).
1820
1821| Type                   | Name             | Default | Description                                                                                                                                                 |
1822|:-----------------------|:-----------------|--------:|:------------------------------------------------------------------------------------------------------------------------------------------------------------|
1823| OSPGeometricModel\[\]  | geometry         |    NULL | [data](#data) array of [GeometricModels](#geometricmodels)                                                                                                  |
1824| OSPVolumetricModel\[\] | volume           |    NULL | [data](#data) array of [VolumetricModels](#volumetricmodels)                                                                                                |
1825| OSPGeometricModel\[\]  | clippingGeometry |    NULL | [data](#data) array of [GeometricModels](#geometricmodels) used for clipping                                                                                |
1826| OSPLight\[\]           | light            |    NULL | [data](#data) array of [lights](#lights)                                                                                                                    |
1827| bool                   | dynamicScene     |   false | use RTC_SCENE_DYNAMIC flag (faster BVH build, slower ray traversal), otherwise uses RTC_SCENE_STATIC flag (faster ray traversal, slightly slower BVH build) |
1828| bool                   | compactMode      |   false | tell Embree to use a more compact BVH in memory by trading ray traversal performance                                                                        |
1829| bool                   | robustMode       |   false | tell Embree to enable more robust ray intersection code paths (slightly slower)                                                                             |
1830
1831Parameters understood by groups.
1832
1833### Instances
1834
1835Instances in OSPRay represent a single group’s placement into the world
1836via a transform. To create and instance call
1837
1838``` cpp
1839OSPInstance ospNewInstance(OSPGroup);
1840```
1841
1842| Type         | Name               |  Default | Description                                                                                                                                           |
1843|:-------------|:-------------------|---------:|:------------------------------------------------------------------------------------------------------------------------------------------------------|
1844| affine3f     | transform          | identity | world-space transform for all attached geometries and volumes, overridden by `motion.*` arrays                                                        |
1845| affine3f\[\] | motion.transform   |          | uniformly distributed world-space transforms                                                                                                          |
1846| vec3f\[\]    | motion.scale       |          | uniformly distributed world-space scale, overridden by `motion.transform`                                                                             |
1847| vec3f\[\]    | motion.pivot       |          | uniformly distributed world-space translation which is applied before `motion.rotation` (i.e., the rotation center), overridden by `motion.transform` |
1848| quatf\[\]    | motion.rotation    |          | uniformly distributed world-space quaternion rotation, overridden by `motion.transform`                                                               |
1849| vec3f\[\]    | motion.translation |          | uniformly distributed world-space translation, overridden by `motion.transform`                                                                       |
1850| box1f        | time               | \[0, 1\] | time associated with first and last key in `motion.*` arrays (for motion blur)                                                                        |
1851
1852Parameters understood by instances.
1853
1854### World
1855
1856Worlds are a container of scene data represented by
1857[instances](#instances). To create an (empty) world call
1858
1859``` cpp
1860OSPWorld ospNewWorld();
1861```
1862
1863Objects are placed in the world through an array of instances. Similar
1864to [groups](#groups), the array of instances is optional: there is no
1865need to create empty arrays if there are no instances (though there will
1866be nothing to render).
1867
1868Applications can query the world (axis-aligned) bounding box after the
1869world has been committed. To get this information, call
1870
1871``` cpp
1872OSPBounds ospGetBounds(OSPObject);
1873```
1874
1875The result is returned in the provided `OSPBounds`[7] struct:
1876
1877``` cpp
1878typedef struct {
1879    float lower[3];
1880    float upper[3];
1881} OSPBounds;
1882```
1883
1884This call can also take `OSPGroup` and `OSPInstance` as well: all other
1885object types will return an empty bounding box.
1886
1887Finally, Worlds can be configured with parameters for making various
1888feature/performance trade-offs (similar to groups).
1889
1890| Type            | Name         | Default | Description                                                                                                                                                 |
1891|:----------------|:-------------|--------:|:------------------------------------------------------------------------------------------------------------------------------------------------------------|
1892| OSPInstance\[\] | instance     |    NULL | [data](#data) array with handles of the [instances](#instances)                                                                                             |
1893| OSPLight\[\]    | light        |    NULL | [data](#data) array with handles of the [lights](#lights)                                                                                                   |
1894| bool            | dynamicScene |   false | use RTC_SCENE_DYNAMIC flag (faster BVH build, slower ray traversal), otherwise uses RTC_SCENE_STATIC flag (faster ray traversal, slightly slower BVH build) |
1895| bool            | compactMode  |   false | tell Embree to use a more compact BVH in memory by trading ray traversal performance                                                                        |
1896| bool            | robustMode   |   false | tell Embree to enable more robust ray intersection code paths (slightly slower)                                                                             |
1897
1898Parameters understood by worlds.
1899
1900Renderers
1901---------
1902
1903A renderer is the central object for rendering in OSPRay. Different
1904renderers implement different features and support different materials.
1905To create a new renderer of given type `type` use
1906
1907``` cpp
1908OSPRenderer ospNewRenderer(const char *type);
1909```
1910
1911General parameters of all renderers are
1912
1913| Type                  | Name              |                 Default | Description                                                                                                                                 |
1914|:----------------------|:------------------|------------------------:|:--------------------------------------------------------------------------------------------------------------------------------------------|
1915| int                   | pixelSamples      |                       1 | samples per pixel                                                                                                                           |
1916| int                   | maxPathLength     |                      20 | maximum ray recursion depth                                                                                                                 |
1917| float                 | minContribution   |                   0.001 | sample contributions below this value will be neglected to speedup rendering                                                                |
1918| float                 | varianceThreshold |                       0 | threshold for adaptive accumulation                                                                                                         |
1919| float / vec3f / vec4f | backgroundColor   |      black, transparent | background color and alpha (linear A/RGB/RGBA), if no `map_backplate` is set                                                                |
1920| OSPTexture            | map_backplate     |                         | optional [texture](#texture) image used as background (use texture type `texture2d`)                                                        |
1921| OSPTexture            | map_maxDepth      |                         | optional screen-sized float [texture](#texture) with maximum far distance per pixel (use texture type `texture2d`)                          |
1922| OSPMaterial\[\]       | material          |                         | optional [data](#data) array of [materials](#materials) which can be indexed by a [GeometricModel](#geometricmodels)’s `material` parameter |
1923| uchar                 | pixelFilter       | `OSP_PIXELFILTER_GAUSS` | `OSPPixelFilterType` to select the pixel filter used by the renderer for antialiasing. Possible pixel filters are listed below.             |
1924
1925Parameters understood by all renderers.
1926
1927OSPRay’s renderers support a feature called adaptive accumulation, which
1928accelerates progressive [rendering](#rendering) by stopping the
1929rendering and refinement of image regions that have an estimated
1930variance below the `varianceThreshold`. This feature requires a
1931[framebuffer](#framebuffer) with an `OSP_FB_VARIANCE` channel.
1932
1933Per default the background of the rendered image will be transparent
1934black, i.e., the alpha channel holds the opacity of the rendered
1935objects. This eases transparency-aware blending of the image with an
1936arbitrary background image by the application. The parameter
1937`backgroundColor` or `map_backplate` can be used to already blend with a
1938constant background color or backplate texture, respectively, (and
1939alpha) during rendering.
1940
1941OSPRay renderers support depth composition with images of other
1942renderers, for example to incorporate help geometries of a 3D UI that
1943were rendered with OpenGL. The screen-sized [texture](#texture)
1944`map_maxDepth` must have format `OSP_TEXTURE_R32F` and flag
1945`OSP_TEXTURE_FILTER_NEAREST`. The fetched values are used to limit the
1946distance of primary rays, thus objects of other renderers can hide
1947objects rendered by OSPRay.
1948
1949OSPRay supports antialiasing in image space by using pixel filters,
1950which are centered around the center of a pixel. The size *w* × *w* of
1951the filter depends on the selected filter type. The types of supported
1952pixel filters are defined by the `OSPPixelFilterType` enum and can be
1953set using the `pixelFilter` parameter.
1954
1955| Name                            | Description                                                                                              |
1956|:--------------------------------|:---------------------------------------------------------------------------------------------------------|
1957| OSP_PIXELFILTER_POINT           | a point filter only samples the center of the pixel, therefore the filter width is *w* = 0               |
1958| OSP_PIXELFILTER_BOX             | a uniform box filter with a width of *w* = 1                                                             |
1959| OSP_PIXELFILTER_GAUSS           | a truncated, smooth Gaussian filter with a standard deviation of *σ* = 0.5 and a filter width of *w* = 3 |
1960| OSP_PIXELFILTER_MITCHELL        | the Mitchell-Netravali filter with a width of *w* = 4                                                    |
1961| OSP_PIXELFILTER_BLACKMAN_HARRIS | the Blackman-Harris filter with a width of *w* = 3                                                       |
1962
1963Pixel filter types supported by OSPRay for antialiasing in image space.
1964
1965### SciVis Renderer
1966
1967The SciVis renderer is a fast ray tracer for scientific visualization
1968which supports volume rendering and ambient occlusion (AO). It is
1969created by passing the type string “`scivis`” to `ospNewRenderer`. In
1970addition to the [general parameters](#renderer) understood by all
1971renderers, the SciVis renderer supports the following parameters:
1972
1973| Type  | Name               |         Default | Description                                                                                                             |
1974|:------|:-------------------|----------------:|:------------------------------------------------------------------------------------------------------------------------|
1975| bool  | shadows            |           false | whether to compute (hard) shadows                                                                                       |
1976| int   | aoSamples          |               0 | number of rays per sample to compute ambient occlusion                                                                  |
1977| float | aoDistance         | 10<sup>20</sup> | maximum distance to consider for ambient occlusion                                                                      |
1978| float | volumeSamplingRate |               1 | sampling rate for volumes                                                                                               |
1979| bool  | visibleLights      |           false | whether light sources are potentially visible (as in the [path tracer](#path-tracer), regarding each light’s `visible`) |
1980
1981Special parameters understood by the SciVis renderer.
1982
1983Note that the intensity (and color) of AO is deduced from an [ambient
1984light](#ambient-light) in the `lights` array.[8] If `aoSamples` is zero
1985(the default) then ambient lights cause ambient illumination (without
1986occlusion).
1987
1988### Ambient Occlusion Renderer
1989
1990This renderer supports only a subset of the features of the [SciVis
1991renderer](#scivis-renderer) to gain performance. As the name suggest its
1992main shading method is ambient occlusion (AO), [lights](#lights) are
1993*not* considered at all and , Volume rendering is supported. The Ambient
1994Occlusion renderer is created by passing the type string “`ao`” to
1995`ospNewRenderer`. In addition to the [general parameters](#renderer)
1996understood by all renderers the following parameters are supported as
1997well:
1998
1999| Type  | Name               |         Default | Description                                            |
2000|:------|:-------------------|----------------:|:-------------------------------------------------------|
2001| int   | aoSamples          |               1 | number of rays per sample to compute ambient occlusion |
2002| float | aoDistance         | 10<sup>20</sup> | maximum distance to consider for ambient occlusion     |
2003| float | aoIntensity        |               1 | ambient occlusion strength                             |
2004| float | volumeSamplingRate |               1 | sampling rate for volumes                              |
2005
2006Special parameters understood by the Ambient Occlusion renderer.
2007
2008### Path Tracer
2009
2010The path tracer supports soft shadows, indirect illumination and
2011realistic materials. This renderer is created by passing the type string
2012“`pathtracer`” to `ospNewRenderer`. In addition to the [general
2013parameters](#renderer) understood by all renderers the path tracer
2014supports the following special parameters:
2015
2016| Type  | Name                 | Default | Description                                                                               |
2017|:------|:---------------------|--------:|:------------------------------------------------------------------------------------------|
2018| int   | lightSamples         |     all | number of random light samples per path vertex, per default all light sources are sampled |
2019| int   | roulettePathLength   |       5 | ray recursion depth at which to start Russian roulette termination                        |
2020| float | maxContribution      |       ∞ | samples are clamped to this value before they are accumulated into the framebuffer        |
2021| bool  | backgroundRefraction |   false | allow for alpha blending even if background is seen through refractive objects like glass |
2022
2023Special parameters understood by the path tracer.
2024
2025The path tracer requires that [materials](#materials) are assigned to
2026[geometries](#geometries), otherwise surfaces are treated as completely
2027black.
2028
2029The path tracer supports [volumes](#volumes) with multiple scattering.
2030The scattering albedo can be specified using the [transfer
2031function](#transfer-function). Extinction is assumed to be spectrally
2032constant.
2033
2034### Materials
2035
2036Materials describe how light interacts with surfaces, they give objects
2037their distinctive look. To let the given renderer create a new material
2038of given type `type` call
2039
2040``` cpp
2041OSPMaterial ospNewMaterial(const char *, const char *material_type);
2042```
2043
2044Please note that the first argument is ignored.
2045
2046The returned handle can then be used to assign the material to a given
2047geometry with
2048
2049``` cpp
2050void ospSetObject(OSPGeometricModel, "material", OSPMaterial);
2051```
2052
2053#### OBJ Material
2054
2055The OBJ material is the workhorse material supported by both the [SciVis
2056renderer](#scivis-renderer) and the [path tracer](#path-tracer) (the
2057[Ambient Occlusion renderer](#ambient-occlusion-renderer) only uses the
2058`kd` and `d` parameter). It offers widely used common properties like
2059diffuse and specular reflection and is based on the [MTL material
2060format](http://paulbourke.net/dataformats/mtl/) of Lightwave’s OBJ scene
2061files. To create an OBJ material pass the type string “`obj`” to
2062`ospNewMaterial`. Its main parameters are
2063
2064| Type       | Name     |   Default | Description                                                 |
2065|:-----------|:---------|----------:|:------------------------------------------------------------|
2066| vec3f      | kd       | white 0.8 | diffuse color (linear RGB)                                  |
2067| vec3f      | ks       |     black | specular color (linear RGB)                                 |
2068| float      | ns       |        10 | shininess (Phong exponent), usually in \[2–10<sup>4</sup>\] |
2069| float      | d        |    opaque | opacity                                                     |
2070| vec3f      | tf       |     black | transparency filter color (linear RGB)                      |
2071| OSPTexture | map_bump |      NULL | normal map                                                  |
2072
2073Main parameters of the OBJ material.
2074
2075In particular when using the path tracer it is important to adhere to
2076the principle of energy conservation, i.e., that the amount of light
2077reflected by a surface is not larger than the light arriving. Therefore
2078the path tracer issues a warning and renormalizes the color parameters
2079if the sum of `Kd`, `Ks`, and `Tf` is larger than one in any color
2080channel. Similarly important to mention is that almost all materials of
2081the real world reflect at most only about 80% of the incoming light. So
2082even for a white sheet of paper or white wall paint do better not set
2083`Kd` larger than 0.8; otherwise rendering times are unnecessary long and
2084the contrast in the final images is low (for example, the corners of a
2085white room would hardly be discernible, as can be seen in the figure
2086below).
2087
2088<figure>
2089<img src="https://ospray.github.io/images/diffuse_rooms.png" width="80.0%" alt="Comparison of diffuse rooms with 100% reflecting white paint (left) and realistic 80% reflecting white paint (right), which leads to higher overall contrast. Note that exposure has been adjusted to achieve similar brightness levels." /><figcaption aria-hidden="true">Comparison of diffuse rooms with 100% reflecting white paint (left) and realistic 80% reflecting white paint (right), which leads to higher overall contrast. Note that exposure has been adjusted to achieve similar brightness levels.</figcaption>
2090</figure>
2091
2092
2093
2094If present, the color component of [geometries](#geometries) is also
2095used for the diffuse color `Kd` and the alpha component is also used for
2096the opacity `d`.
2097
2098Normal mapping can simulate small geometric features via the texture
2099`map_Bump`. The normals *n* in the normal map are with respect to the
2100local tangential shading coordinate system and are encoded as ½(*n*+1),
2101thus a texel (0.5,0.5,1)[9] represents the unperturbed shading normal
2102(0,0,1). Because of this encoding an sRGB gamma [texture](#texture)
2103format is ignored and normals are always fetched as linear from a normal
2104map. Note that the orientation of normal maps is important for a
2105visually consistent look: by convention OSPRay uses a coordinate system
2106with the origin in the lower left corner; thus a convexity will look
2107green toward the top of the texture image (see also the example image of
2108a normal map). If this is not the case flip the normal map vertically or
2109invert its green channel.
2110
2111<figure>
2112<img src="https://ospray.github.io/images/normalmap_frustum.png" width="60.0%" alt="Normal map representing an exalted square pyramidal frustum." /><figcaption aria-hidden="true">Normal map representing an exalted square pyramidal frustum.</figcaption>
2113</figure>
2114
2115
2116
2117Note that `Tf` colored transparency is implemented in the SciVis and the
2118path tracer but normal mapping with `map_Bump` is currently supported in
2119the path tracer only.
2120
2121All parameters (except `Tf`) can be textured by passing a
2122[texture](#texture) handle, prefixed with “`map_`”. The fetched texels
2123are multiplied by the respective parameter value. If only the texture is
2124given (but not the corresponding parameter), only the texture is used
2125(the default value of the parameter is *not* multiplied). The color
2126textures `map_Kd` and `map_Ks` are typically in one of the sRGB gamma
2127encoded formats, whereas textures `map_Ns` and `map_d` are usually in a
2128linear format (and only the first component is used). Additionally, all
2129textures support [texture transformations](#texture-transformations).
2130
2131<figure>
2132<img src="https://ospray.github.io/images/material_OBJ.jpg" width="60.0%" alt="Rendering of a OBJ material with wood textures." /><figcaption aria-hidden="true">Rendering of a OBJ material with wood textures.</figcaption>
2133</figure>
2134
2135
2136
2137#### Principled
2138
2139The Principled material is the most complex material offered by the
2140[path tracer](#path-tracer), which is capable of producing a wide
2141variety of materials (e.g., plastic, metal, wood, glass) by combining
2142multiple different layers and lobes. It uses the GGX microfacet
2143distribution with approximate multiple scattering for dielectrics and
2144metals, uses the Oren-Nayar model for diffuse reflection, and is energy
2145conserving. To create a Principled material, pass the type string
2146“`principled`” to `ospNewMaterial`. Its parameters are listed in the
2147table below.
2148
2149| Type  | Name              |   Default | Description                                                                                                             |
2150|:------|:------------------|----------:|:------------------------------------------------------------------------------------------------------------------------|
2151| vec3f | baseColor         | white 0.8 | base reflectivity (diffuse and/or metallic, linear RGB)                                                                 |
2152| vec3f | edgeColor         |     white | edge tint (metallic only, linear RGB)                                                                                   |
2153| float | metallic          |         0 | mix between dielectric (diffuse and/or specular) and metallic (specular only with complex IOR) in \[0–1\]               |
2154| float | diffuse           |         1 | diffuse reflection weight in \[0–1\]                                                                                    |
2155| float | specular          |         1 | specular reflection/transmission weight in \[0–1\]                                                                      |
2156| float | ior               |         1 | dielectric index of refraction                                                                                          |
2157| float | transmission      |         0 | specular transmission weight in \[0–1\]                                                                                 |
2158| vec3f | transmissionColor |     white | attenuated color due to transmission (Beer’s law, linear RGB)                                                           |
2159| float | transmissionDepth |         1 | distance at which color attenuation is equal to transmissionColor                                                       |
2160| float | roughness         |         0 | diffuse and specular roughness in \[0–1\], 0 is perfectly smooth                                                        |
2161| float | anisotropy        |         0 | amount of specular anisotropy in \[0–1\]                                                                                |
2162| float | rotation          |         0 | rotation of the direction of anisotropy in \[0–1\], 1 is going full circle                                              |
2163| float | normal            |         1 | default normal map/scale for all layers                                                                                 |
2164| float | baseNormal        |         1 | base normal map/scale (overrides default normal)                                                                        |
2165| bool  | thin              |     false | flag specifying whether the material is thin or solid                                                                   |
2166| float | thickness         |         1 | thickness of the material (thin only), affects the amount of color attenuation due to specular transmission             |
2167| float | backlight         |         0 | amount of diffuse transmission (thin only) in \[0–2\], 1 is 50% reflection and 50% transmission, 2 is transmission only |
2168| float | coat              |         0 | clear coat layer weight in \[0–1\]                                                                                      |
2169| float | coatIor           |       1.5 | clear coat index of refraction                                                                                          |
2170| vec3f | coatColor         |     white | clear coat color tint (linear RGB)                                                                                      |
2171| float | coatThickness     |         1 | clear coat thickness, affects the amount of color attenuation                                                           |
2172| float | coatRoughness     |         0 | clear coat roughness in \[0–1\], 0 is perfectly smooth                                                                  |
2173| float | coatNormal        |         1 | clear coat normal map/scale (overrides default normal)                                                                  |
2174| float | sheen             |         0 | sheen layer weight in \[0–1\]                                                                                           |
2175| vec3f | sheenColor        |     white | sheen color tint (linear RGB)                                                                                           |
2176| float | sheenTint         |         0 | how much sheen is tinted from sheenColor toward baseColor                                                               |
2177| float | sheenRoughness    |       0.2 | sheen roughness in \[0–1\], 0 is perfectly smooth                                                                       |
2178| float | opacity           |         1 | cut-out opacity/transparency, 1 is fully opaque                                                                         |
2179
2180Parameters of the Principled material.
2181
2182All parameters can be textured by passing a [texture](#texture) handle,
2183prefixed with “`map_`” (e.g., “`map_baseColor`”). [texture
2184transformations](#texture-transformations) are supported as well.
2185
2186<figure>
2187<img src="https://ospray.github.io/images/material_Principled.jpg" width="60.0%" alt="Rendering of a Principled coated brushed metal material with textured anisotropic rotation and a dust layer (sheen) on top." /><figcaption aria-hidden="true">Rendering of a Principled coated brushed metal material with textured anisotropic rotation and a dust layer (sheen) on top.</figcaption>
2188</figure>
2189
2190
2191
2192#### CarPaint
2193
2194The CarPaint material is a specialized version of the Principled
2195material for rendering different types of car paints. To create a
2196CarPaint material, pass the type string “`carPaint`” to
2197`ospNewMaterial`. Its parameters are listed in the table below.
2198
2199| Type  | Name            |   Default | Description                                                                                                            |
2200|:------|:----------------|----------:|:-----------------------------------------------------------------------------------------------------------------------|
2201| vec3f | baseColor       | white 0.8 | diffuse base reflectivity (linear RGB)                                                                                 |
2202| float | roughness       |         0 | diffuse roughness in \[0–1\], 0 is perfectly smooth                                                                    |
2203| float | normal          |         1 | normal map/scale                                                                                                       |
2204| vec3f | flakeColor      | Aluminium | color of metallic flakes (linear RGB)                                                                                  |
2205| float | flakeDensity    |         0 | density of metallic flakes in \[0–1\], 0 disables flakes, 1 fully covers the surface with flakes                       |
2206| float | flakeScale      |       100 | scale of the flake structure, higher values increase the amount of flakes                                              |
2207| float | flakeSpread     |       0.3 | flake spread in \[0–1\]                                                                                                |
2208| float | flakeJitter     |      0.75 | flake randomness in \[0–1\]                                                                                            |
2209| float | flakeRoughness  |       0.3 | flake roughness in \[0–1\], 0 is perfectly smooth                                                                      |
2210| float | coat            |         1 | clear coat layer weight in \[0–1\]                                                                                     |
2211| float | coatIor         |       1.5 | clear coat index of refraction                                                                                         |
2212| vec3f | coatColor       |     white | clear coat color tint (linear RGB)                                                                                     |
2213| float | coatThickness   |         1 | clear coat thickness, affects the amount of color attenuation                                                          |
2214| float | coatRoughness   |         0 | clear coat roughness in \[0–1\], 0 is perfectly smooth                                                                 |
2215| float | coatNormal      |         1 | clear coat normal map/scale                                                                                            |
2216| vec3f | flipflopColor   |     white | reflectivity of coated flakes at grazing angle, used together with coatColor produces a pearlescent paint (linear RGB) |
2217| float | flipflopFalloff |         1 | flip flop color falloff, 1 disables the flip flop effect                                                               |
2218
2219Parameters of the CarPaint material.
2220
2221All parameters can be textured by passing a [texture](#texture) handle,
2222prefixed with “`map_`” (e.g., “`map_baseColor`”). [texture
2223transformations](#texture-transformations) are supported as well.
2224
2225<figure>
2226<img src="https://ospray.github.io/images/material_CarPaint.jpg" width="60.0%" alt="Rendering of a pearlescent CarPaint material." /><figcaption aria-hidden="true">Rendering of a pearlescent CarPaint material.</figcaption>
2227</figure>
2228
2229
2230
2231#### Metal
2232
2233The [path tracer](#path-tracer) offers a physical metal, supporting
2234changing roughness and realistic color shifts at edges. To create a
2235Metal material pass the type string “`metal`” to `ospNewMaterial`. Its
2236parameters are
2237
2238| Type      | Name      |   Default | Description                                                                                                                                              |
2239|:----------|:----------|----------:|:---------------------------------------------------------------------------------------------------------------------------------------------------------|
2240| vec3f\[\] | ior       | Aluminium | [data](#data) array of spectral samples of complex refractive index, each entry in the form (wavelength, eta, k), ordered by wavelength (which is in nm) |
2241| vec3f     | eta       |           | RGB complex refractive index, real part                                                                                                                  |
2242| vec3f     | k         |           | RGB complex refractive index, imaginary part                                                                                                             |
2243| float     | roughness |       0.1 | roughness in \[0–1\], 0 is perfect mirror                                                                                                                |
2244
2245Parameters of the Metal material.
2246
2247The main appearance (mostly the color) of the Metal material is
2248controlled by the physical parameters `eta` and `k`, the
2249wavelength-dependent, complex index of refraction. These coefficients
2250are quite counter-intuitive but can be found in [published
2251measurements](https://refractiveindex.info/). For accuracy the index of
2252refraction can be given as an array of spectral samples in `ior`, each
2253sample a triplet of wavelength (in nm), eta, and k, ordered
2254monotonically increasing by wavelength; OSPRay will then calculate the
2255Fresnel in the spectral domain. Alternatively, `eta` and `k` can also be
2256specified as approximated RGB coefficients; some examples are given in
2257below table.
2258
2259| Metal         |          eta          |        k        |
2260|:--------------|:---------------------:|:---------------:|
2261| Ag, Silver    | (0.051, 0.043, 0.041) | (5.3, 3.6, 2.3) |
2262| Al, Aluminium |   (1.5, 0.98, 0.6)    | (7.6, 6.6, 5.4) |
2263| Au, Gold      |   (0.07, 0.37, 1.5)   | (3.7, 2.3, 1.7) |
2264| Cr, Chromium  |    (3.2, 3.1, 2.3)    | (3.3, 3.3, 3.1) |
2265| Cu, Copper    |    (0.1, 0.8, 1.1)    | (3.5, 2.5, 2.4) |
2266
2267Index of refraction of selected metals as approximated RGB coefficients,
2268based on data from https://refractiveindex.info/.
2269
2270The `roughness` parameter controls the variation of microfacets and thus
2271how polished the metal will look. The roughness can be modified by a
2272[texture](#texture) `map_roughness` ([texture
2273transformations](#texture-transformations) are supported as well) to
2274create notable edging effects.
2275
2276<figure>
2277<img src="https://ospray.github.io/images/material_Metal.jpg" width="60.0%" alt="Rendering of golden Metal material with textured roughness." /><figcaption aria-hidden="true">Rendering of golden Metal material with textured roughness.</figcaption>
2278</figure>
2279
2280
2281
2282#### Alloy
2283
2284The [path tracer](#path-tracer) offers an alloy material, which behaves
2285similar to [Metal](#metal), but allows for more intuitive and flexible
2286control of the color. To create an Alloy material pass the type string
2287“`alloy`” to `ospNewMaterial`. Its parameters are
2288
2289| Type  | Name      |   Default | Description                                             |
2290|:------|:----------|----------:|:--------------------------------------------------------|
2291| vec3f | color     | white 0.9 | reflectivity at normal incidence (0 degree, linear RGB) |
2292| vec3f | edgeColor |     white | reflectivity at grazing angle (90 degree, linear RGB)   |
2293| float | roughness |       0.1 | roughness, in \[0–1\], 0 is perfect mirror              |
2294
2295Parameters of the Alloy material.
2296
2297The main appearance of the Alloy material is controlled by the parameter
2298`color`, while `edgeColor` influences the tint of reflections when seen
2299at grazing angles (for real metals this is always 100% white). If
2300present, the color component of [geometries](#geometries) is also used
2301for reflectivity at normal incidence `color`. As in [Metal](#metal) the
2302`roughness` parameter controls the variation of microfacets and thus how
2303polished the alloy will look. All parameters can be textured by passing
2304a [texture](#texture) handle, prefixed with “`map_`”; [texture
2305transformations](#texture-transformations) are supported as well.
2306
2307<figure>
2308<img src="https://ospray.github.io/images/material_Alloy.jpg" width="60.0%" alt="Rendering of a fictional Alloy material with textured color." /><figcaption aria-hidden="true">Rendering of a fictional Alloy material with textured color.</figcaption>
2309</figure>
2310
2311
2312
2313#### Glass
2314
2315The [path tracer](#path-tracer) offers a realistic a glass material,
2316supporting refraction and volumetric attenuation (i.e., the transparency
2317color varies with the geometric thickness). To create a Glass material
2318pass the type string “`glass`” to `ospNewMaterial`. Its parameters are
2319
2320| Type  | Name                | Default | Description                                     |
2321|:------|:--------------------|--------:|:------------------------------------------------|
2322| float | eta                 |     1.5 | index of refraction                             |
2323| vec3f | attenuationColor    |   white | resulting color due to attenuation (linear RGB) |
2324| float | attenuationDistance |       1 | distance affecting attenuation                  |
2325
2326Parameters of the Glass material.
2327
2328For convenience, the rather counter-intuitive physical attenuation
2329coefficients will be calculated from the user inputs in such a way, that
2330the `attenuationColor` will be the result when white light traveled
2331trough a glass of thickness `attenuationDistance`.
2332
2333<figure>
2334<img src="https://ospray.github.io/images/material_Glass.jpg" width="60.0%" alt="Rendering of a Glass material with orange attenuation." /><figcaption aria-hidden="true">Rendering of a Glass material with orange attenuation.</figcaption>
2335</figure>
2336
2337
2338
2339#### ThinGlass
2340
2341The [path tracer](#path-tracer) offers a thin glass material useful for
2342objects with just a single surface, most prominently windows. It models
2343a thin, transparent slab, i.e., it behaves as if a second, virtual
2344surface is parallel to the real geometric surface. The implementation
2345accounts for multiple internal reflections between the interfaces
2346(including attenuation), but neglects parallax effects due to its
2347(virtual) thickness. To create a such a thin glass material pass the
2348type string “`thinGlass`” to `ospNewMaterial`. Its parameters are
2349
2350| Type  | Name                | Default | Description                                     |
2351|:------|:--------------------|--------:|:------------------------------------------------|
2352| float | eta                 |     1.5 | index of refraction                             |
2353| vec3f | attenuationColor    |   white | resulting color due to attenuation (linear RGB) |
2354| float | attenuationDistance |       1 | distance affecting attenuation                  |
2355| float | thickness           |       1 | virtual thickness                               |
2356
2357Parameters of the ThinGlass material.
2358
2359For convenience the attenuation is controlled the same way as with the
2360[Glass](#glass) material. Additionally, the color due to attenuation can
2361be modulated with a [texture](#texture) `map_attenuationColor` ([texture
2362transformations](#texture-transformations) are supported as well). If
2363present, the color component of [geometries](#geometries) is also used
2364for the attenuation color. The `thickness` parameter sets the (virtual)
2365thickness and allows for easy exchange of parameters with the (real)
2366[Glass](#glass) material; internally just the ratio between
2367`attenuationDistance` and `thickness` is used to calculate the resulting
2368attenuation and thus the material appearance.
2369
2370<figure>
2371<img src="https://ospray.github.io/images/material_ThinGlass.jpg" width="60.0%" alt="Rendering of a ThinGlass material with red attenuation." /><figcaption aria-hidden="true">Rendering of a ThinGlass material with red attenuation.</figcaption>
2372</figure>
2373
2374
2375
2376<figure>
2377<img src="https://ospray.github.io/images/ColoredWindow.jpg" width="60.0%" alt="Example image of a colored window made with textured attenuation of the ThinGlass material." /><figcaption aria-hidden="true">Example image of a colored window made with textured attenuation of the ThinGlass material.</figcaption>
2378</figure>
2379
2380
2381
2382#### MetallicPaint
2383
2384The [path tracer](#path-tracer) offers a metallic paint material,
2385consisting of a base coat with optional flakes and a clear coat. To
2386create a MetallicPaint material pass the type string “`metallicPaint`”
2387to `ospNewMaterial`. Its parameters are listed in the table below.
2388
2389| Type  | Name        |   Default | Description                           |
2390|:------|:------------|----------:|:--------------------------------------|
2391| vec3f | baseColor   | white 0.8 | color of base coat (linear RGB)       |
2392| float | flakeAmount |       0.3 | amount of flakes, in \[0–1\]          |
2393| vec3f | flakeColor  | Aluminium | color of metallic flakes (linear RGB) |
2394| float | flakeSpread |       0.5 | spread of flakes, in \[0–1\]          |
2395| float | eta         |       1.5 | index of refraction of clear coat     |
2396
2397Parameters of the MetallicPaint material.
2398
2399The color of the base coat `baseColor` can be textured by a
2400[texture](#texture) `map_baseColor`, which also supports [texture
2401transformations](#texture-transformations). If present, the color
2402component of [geometries](#geometries) is also used for the color of the
2403base coat. Parameter `flakeAmount` controls the proportion of flakes in
2404the base coat, so when setting it to 1 the `baseColor` will not be
2405visible. The shininess of the metallic component is governed by
2406`flakeSpread`, which controls the variation of the orientation of the
2407flakes, similar to the `roughness` parameter of [Metal](#metal). Note
2408that the effect of the metallic flakes is currently only computed on
2409average, thus individual flakes are not visible.
2410
2411<figure>
2412<img src="https://ospray.github.io/images/material_MetallicPaint.jpg" width="60.0%" alt="Rendering of a MetallicPaint material." /><figcaption aria-hidden="true">Rendering of a MetallicPaint material.</figcaption>
2413</figure>
2414
2415
2416
2417#### Luminous
2418
2419The [path tracer](#path-tracer) supports the Luminous material which
2420emits light uniformly in all directions and which can thus be used to
2421turn any geometric object into a light source. It is created by passing
2422the type string “`luminous`” to `ospNewMaterial`. The amount of constant
2423radiance that is emitted is determined by combining the general
2424parameters of lights: [`color` and `intensity`](#lights) (which
2425essentially means that parameter `intensityQuantity` is not needed
2426because it is always `OSP_INTENSITY_QUANTITY_RADIANCE`).
2427
2428| Type  | Name         | Default | Description                             |
2429|:------|:-------------|--------:|:----------------------------------------|
2430| vec3f | color        |   white | color of the emitted light (linear RGB) |
2431| float | intensity    |       1 | intensity of the light (a factor)       |
2432| float | transparency |       1 | material transparency                   |
2433
2434Parameters accepted by the Luminous material.
2435
2436<figure>
2437<img src="https://ospray.github.io/images/material_Luminous.jpg" width="60.0%" alt="Rendering of a yellow Luminous material." /><figcaption aria-hidden="true">Rendering of a yellow Luminous material.</figcaption>
2438</figure>
2439
2440
2441
2442### Texture
2443
2444OSPRay currently implements two texture types (`texture2d` and `volume`)
2445and is open for extension to other types by applications. More types may
2446be added in future releases.
2447
2448To create a new texture use
2449
2450``` cpp
2451OSPTexture ospNewTexture(const char *type);
2452```
2453
2454#### Texture2D
2455
2456The `texture2d` texture type implements an image-based texture, where
2457its parameters are as follows
2458
2459| Type    | Name   | Description                                                                       |
2460|:--------|:-------|:----------------------------------------------------------------------------------|
2461| int     | format | `OSPTextureFormat` for the texture                                                |
2462| int     | filter | default `OSP_TEXTURE_FILTER_BILINEAR`, alternatively `OSP_TEXTURE_FILTER_NEAREST` |
2463| OSPData | data   | the actual texel 2D [data](#data)                                                 |
2464
2465Parameters of `texture2d` texture type.
2466
2467The supported texture formats for `texture2d` are:
2468
2469| Name                | Description                                                                |
2470|:--------------------|:---------------------------------------------------------------------------|
2471| OSP_TEXTURE_RGBA8   | 8 bit \[0–255\] linear components red, green, blue, alpha                  |
2472| OSP_TEXTURE_SRGBA   | 8 bit sRGB gamma encoded color components, and linear alpha                |
2473| OSP_TEXTURE_RGBA32F | 32 bit float components red, green, blue, alpha                            |
2474| OSP_TEXTURE_RGB8    | 8 bit \[0–255\] linear components red, green, blue                         |
2475| OSP_TEXTURE_SRGB    | 8 bit sRGB gamma encoded components red, green, blue                       |
2476| OSP_TEXTURE_RGB32F  | 32 bit float components red, green, blue                                   |
2477| OSP_TEXTURE_R8      | 8 bit \[0–255\] linear single component red                                |
2478| OSP_TEXTURE_RA8     | 8 bit \[0–255\] linear two components red, alpha                           |
2479| OSP_TEXTURE_L8      | 8 bit \[0–255\] gamma encoded luminance (replicated into red, green, blue) |
2480| OSP_TEXTURE_LA8     | 8 bit \[0–255\] gamma encoded luminance, and linear alpha                  |
2481| OSP_TEXTURE_R32F    | 32 bit float single component red                                          |
2482| OSP_TEXTURE_RGBA16  | 16 bit \[0–65535\] linear components red, green, blue, alpha               |
2483| OSP_TEXTURE_RGB16   | 16 bit \[0–65535\] linear components red, green, blue                      |
2484| OSP_TEXTURE_RA16    | 16 bit \[0–65535\] linear two components red, alpha                        |
2485| OSP_TEXTURE_R16     | 16 bit \[0–65535\] linear single component red                             |
2486
2487Supported texture formats by `texture2d`, i.e., valid constants of type
2488`OSPTextureFormat`.
2489
2490The size of the texture is inferred from the size of the 2D array
2491`data`, which also needs have a compatible type to `format`. The texel
2492data in `data` starts with the texels in the lower left corner of the
2493texture image, like in OpenGL. Per default a texture fetch is filtered
2494by performing bi-linear interpolation of the nearest 2×2 texels; if
2495instead fetching only the nearest texel is desired (i.e., no filtering)
2496then pass the `OSP_TEXTURE_FILTER_NEAREST` flag.
2497
2498Texturing with `texture2d` image textures requires
2499[geometries](#geometries) with texture coordinates, e.g., a
2500[mesh](#mesh) with `vertex.texcoord` provided.
2501
2502#### Volume Texture
2503
2504The `volume` texture type implements texture lookups based on 3D object
2505coordinates of the surface hit point on the associated geometry. If the
2506given hit point is within the attached volume, the volume is sampled and
2507classified with the transfer function attached to the volume. This
2508implements the ability to visualize volume values (as colored by a
2509transfer function) on arbitrary surfaces inside the volume (as opposed
2510to an isosurface showing a particular value in the volume). Its
2511parameters are as follows
2512
2513| Type                | Name             | Description                                                 |
2514|:--------------------|:-----------------|:------------------------------------------------------------|
2515| OSPVolume           | volume           | [Volume](#volumes) used to generate color lookups           |
2516| OSPTransferFunction | transferFunction | [transfer function](#transfer-function) applied to `volume` |
2517
2518Parameters of `volume` texture type.
2519
2520TextureVolume can be used for implementing slicing of volumes with any
2521geometry type. It enables coloring of the slicing geometry with a
2522different transfer function than that of the sliced volume.
2523
2524#### Texture Transformations
2525
2526All materials with textures also offer to manipulate the placement of
2527these textures with the help of texture transformations. If so, this
2528convention shall be used: the following parameters are prefixed with
2529“`texture_name.*`”).
2530
2531| Type     | Name        | Description                                      |
2532|:---------|:------------|:-------------------------------------------------|
2533| linear2f | transform   | linear transformation (rotation, scale)          |
2534| float    | rotation    | angle in degree, counterclockwise, around center |
2535| vec2f    | scale       | enlarge texture, relative to center (0.5,0.5)    |
2536| vec2f    | translation | move texture in positive direction (right/up)    |
2537
2538Parameters to define 2D texture coordinate transformations.
2539
2540Above parameters are combined into a single `affine2d` transformation
2541matrix and the transformations are applied in the given order. Rotation,
2542scale and translation are interpreted “texture centric”, i.e., their
2543effect seen by an user are relative to the texture (although the
2544transformations are applied to the texture coordinates).
2545
2546| Type     | Name      | Description                                              |
2547|:---------|:----------|:---------------------------------------------------------|
2548| affine3f | transform | linear transformation (rotation, scale) plus translation |
2549
2550Parameter to define 3D volume texture transformations.
2551
2552Similarly, volume texture placement can also be modified by an
2553`affine3f` transformation matrix.
2554
2555### Cameras
2556
2557To create a new camera of given type `type` use
2558
2559``` cpp
2560OSPCamera ospNewCamera(const char *type);
2561```
2562
2563All cameras accept these parameters:
2564
2565| Type         | Name                   |              Default | Description                                                                                                                                                      |
2566|:-------------|:-----------------------|---------------------:|:-----------------------------------------------------------------------------------------------------------------------------------------------------------------|
2567| vec3f        | position               |              (0,0,0) | position of the camera                                                                                                                                           |
2568| vec3f        | direction              |              (0,0,1) | main viewing direction of the camera                                                                                                                             |
2569| vec3f        | up                     |              (0,1,0) | up direction of the camera                                                                                                                                       |
2570| affine3f     | transform              |             identity | additional world-space transform, overridden by `motion.*` arrays                                                                                                |
2571| float        | nearClip               |      10<sup>-6</sup> | near clipping distance                                                                                                                                           |
2572| vec2f        | imageStart             |                (0,0) | start of image region (lower left corner)                                                                                                                        |
2573| vec2f        | imageEnd               |                (1,1) | end of image region (upper right corner)                                                                                                                         |
2574| affine3f\[\] | motion.transform       |                      | additional uniformly distributed world-space transforms                                                                                                          |
2575| vec3f\[\]    | motion.scale           |                      | additional uniformly distributed world-space scale, overridden by `motion.transform`                                                                             |
2576| vec3f\[\]    | motion.pivot           |                      | additional uniformly distributed world-space translation which is applied before `motion.rotation` (i.e., the rotation center), overridden by `motion.transform` |
2577| quatf\[\]    | motion.rotation        |                      | additional uniformly distributed world-space quaternion rotation, overridden by `motion.transform`                                                               |
2578| vec3f\[\]    | motion.translation     |                      | additional uniformly distributed world-space translation, overridden by `motion.transform`                                                                       |
2579| box1f        | time                   |             \[0, 1\] | time associated with first and last key in `motion.*` arrays                                                                                                     |
2580| box1f        | shutter                |         \[0.5, 0.5\] | start and end of shutter time (for motion blur), in \[0, 1\]                                                                                                     |
2581| uchar        | shutterType            | `OSP_SHUTTER_GLOBAL` | `OSPShutterType` for motion blur, also allowed are:                                                                                                              |
2582|              |                        |                      | `OSP_SHUTTER_ROLLING_RIGHT`                                                                                                                                      |
2583|              |                        |                      | `OSP_SHUTTER_ROLLING_LEFT`                                                                                                                                       |
2584|              |                        |                      | `OSP_SHUTTER_ROLLING_DOWN`                                                                                                                                       |
2585|              |                        |                      | `OSP_SHUTTER_ROLLING_UP`                                                                                                                                         |
2586| float        | rollingShutterDuration |                    0 | for a rolling shutter (see `shutterType`) the “open” time per line, in \[0, `shutter`.upper-`shutter`.lower\]                                                    |
2587
2588Parameters accepted by all cameras.
2589
2590The camera is placed and oriented in the world with `position`,
2591`direction` and `up`. Additionally, an extra transformation `transform`
2592can be specified, which will only be applied to 3D vectors (i.e.
2593`position`, `direction` and `up`), but does *not* affect any sizes
2594(e.g., `nearClip`, `apertureRadius`, or `height`). The same holds for
2595the array of transformations `motion.transform` to achieve camera motion
2596blur (in combination with `time` and `shutter`).
2597
2598OSPRay uses a right-handed coordinate system. The region of the camera
2599sensor that is rendered to the image can be specified in normalized
2600screen-space coordinates with `imageStart` (lower left corner) and
2601`imageEnd` (upper right corner). This can be used, for example, to crop
2602the image, to achieve asymmetrical view frusta, or to horizontally flip
2603the image to view scenes which are specified in a left-handed coordinate
2604system. Note that values outside the default range of \[0–1\] are valid,
2605which is useful to easily realize overscan or film gate, or to emulate a
2606shifted sensor.
2607
2608#### Perspective Camera
2609
2610The perspective camera implements a simple thin lens camera for
2611perspective rendering, supporting optionally depth of field and stereo
2612rendering (with the [path tracer](#path-tracer)). It is created by
2613passing the type string “`perspective`” to `ospNewCamera`. In addition
2614to the [general parameters](#cameras) understood by all cameras the
2615perspective camera supports the special parameters listed in the table
2616below.
2617
2618| Type  | Name                   |           Default | Description                                                            |
2619|:------|:-----------------------|------------------:|:-----------------------------------------------------------------------|
2620| float | fovy                   |                60 | the field of view (angle in degree) of the frame’s height              |
2621| float | aspect                 |                 1 | ratio of width by height of the frame (and image region)               |
2622| float | apertureRadius         |                 0 | size of the aperture, controls the depth of field                      |
2623| float | focusDistance          |                 1 | distance at where the image is sharpest when depth of field is enabled |
2624| bool  | architectural          |             false | vertical edges are projected to be parallel                            |
2625| uchar | stereoMode             | `OSP_STEREO_NONE` | `OSPStereoMode` for stereo rendering, also allowed are:                |
2626|       |                        |                   | `OSP_STEREO_LEFT`                                                      |
2627|       |                        |                   | `OSP_STEREO_RIGHT`                                                     |
2628|       |                        |                   | `OSP_STEREO_SIDE_BY_SIDE`                                              |
2629|       |                        |                   | `OSP_STEREO_TOP_BOTTOM` (left eye at top half)                         |
2630| float | interpupillaryDistance |            0.0635 | distance between left and right eye when stereo is enabled             |
2631
2632Additional parameters accepted by the perspective camera.
2633
2634Note that when computing the `aspect` ratio a potentially set image
2635region (using `imageStart` & `imageEnd`) needs to be regarded as well.
2636
2637In architectural photography it is often desired for aesthetic reasons
2638to display the vertical edges of buildings or walls vertically in the
2639image as well, regardless of how the camera is tilted. Enabling the
2640`architectural` mode achieves this by internally leveling the camera
2641parallel to the ground (based on the `up` direction) and then shifting
2642the lens such that the objects in direction `dir` are centered in the
2643image. If finer control of the lens shift is needed use `imageStart` &
2644`imageEnd`. Because the camera is now effectively leveled its image
2645plane and thus the plane of focus is oriented parallel to the front of
2646buildings, the whole façade appears sharp, as can be seen in the example
2647images below. The resolution of the [framebuffer](#framebuffer) is not
2648altered by `imageStart`/`imageEnd`.
2649
2650<figure>
2651<img src="https://ospray.github.io/images/camera_perspective.jpg" width="60.0%" alt="Example image created with the perspective camera, featuring depth of field." /><figcaption aria-hidden="true">Example image created with the perspective camera, featuring depth of field.</figcaption>
2652</figure>
2653
2654
2655
2656<figure>
2657<img src="https://ospray.github.io/images/camera_architectural.jpg" width="60.0%" alt="Enabling the architectural flag corrects the perspective projection distortion, resulting in parallel vertical edges." /><figcaption aria-hidden="true">Enabling the <code>architectural</code> flag corrects the perspective projection distortion, resulting in parallel vertical edges.</figcaption>
2658</figure>
2659
2660
2661
2662<figure>
2663<img src="https://ospray.github.io/images/camera_stereo.jpg" width="90.0%" alt="Example 3D stereo image using stereoMode = OSP_STEREO_SIDE_BY_SIDE." /><figcaption aria-hidden="true">Example 3D stereo image using <code>stereoMode = OSP_STEREO_SIDE_BY_SIDE</code>.</figcaption>
2664</figure>
2665
2666
2667
2668#### Orthographic Camera
2669
2670The orthographic camera implements a simple camera with orthographic
2671projection, without support for depth. It is created by passing the type
2672string “`orthographic`” to `ospNewCamera`. In addition to the [general
2673parameters](#cameras) understood by all cameras the orthographic camera
2674supports the following special parameters:
2675
2676| Type  | Name   | Description                                                 |
2677|:------|:-------|:------------------------------------------------------------|
2678| float | height | size of the camera’s image plane in y, in world coordinates |
2679| float | aspect | ratio of width by height of the frame                       |
2680
2681Additional parameters accepted by the orthographic camera.
2682
2683For convenience the size of the camera sensor, and thus the extent of
2684the scene that is captured in the image, can be controlled with the
2685`height` parameter. The same effect can be achieved with `imageStart`
2686and `imageEnd`, and both methods can be combined. In any case, the
2687`aspect` ratio needs to be set accordingly to get an undistorted image.
2688
2689<figure>
2690<img src="https://ospray.github.io/images/camera_orthographic.jpg" width="60.0%" alt="Example image created with the orthographic camera." /><figcaption aria-hidden="true">Example image created with the orthographic camera.</figcaption>
2691</figure>
2692
2693
2694
2695#### Panoramic Camera
2696
2697The panoramic camera implements a simple camera with support for stereo
2698rendering. It captures the complete surrounding with a latitude /
2699longitude mapping and thus the rendered images should best have a ratio
2700of 2:1. A panoramic camera is created by passing the type string
2701“`panoramic`” to `ospNewCamera`. It is placed and oriented in the scene
2702by using the [general parameters](#cameras) understood by all cameras.
2703
2704| Type  | Name                   | Description                                                                |
2705|:------|:-----------------------|:---------------------------------------------------------------------------|
2706| uchar | stereoMode             | `OSPStereoMode` for stereo rendering, possible values are:                 |
2707|       |                        | `OSP_STEREO_NONE` (default)                                                |
2708|       |                        | `OSP_STEREO_LEFT`                                                          |
2709|       |                        | `OSP_STEREO_RIGHT`                                                         |
2710|       |                        | `OSP_STEREO_SIDE_BY_SIDE`                                                  |
2711|       |                        | `OSP_STEREO_TOP_BOTTOM` (left eye at top half)                             |
2712| float | interpupillaryDistance | distance between left and right eye when stereo is enabled, default 0.0635 |
2713
2714Additional parameters accepted by the panoramic camera.
2715
2716<figure>
2717<img src="https://ospray.github.io/images/camera_panoramic.jpg" width="90.0%" alt="Latitude / longitude map created with the panoramic camera." /><figcaption aria-hidden="true">Latitude / longitude map created with the panoramic camera.</figcaption>
2718</figure>
2719
2720
2721
2722### Picking
2723
2724To get the world-space position of the geometry (if any) seen at \[0–1\]
2725normalized screen-space pixel coordinates `screenPos_x` and
2726`screenPos_y` use
2727
2728``` cpp
2729void ospPick(OSPPickResult *,
2730    OSPFrameBuffer,
2731    OSPRenderer,
2732    OSPCamera,
2733    OSPWorld,
2734    float screenPos_x,
2735    float screenPos_y);
2736```
2737
2738The result is returned in the provided `OSPPickResult` struct:
2739
2740``` cpp
2741typedef struct {
2742    int hasHit;
2743    float worldPosition[3];
2744    OSPInstance instance;
2745    OSPGeometricModel model;
2746    uint32_t primID;
2747} OSPPickResult;
2748```
2749
2750Note that `ospPick` considers exactly the same camera of the given
2751renderer that is used to render an image, thus matching results can be
2752expected. If the camera supports depth of field then the center of the
2753lens and thus the center of the circle of confusion is used for picking.
2754Note that the caller needs to `ospRelease` the `instance` and `model`
2755handles of `OSPPickResult` once the information is not needed anymore.
2756
2757Framebuffer
2758-----------
2759
2760The framebuffer holds the rendered 2D image (and optionally auxiliary
2761information associated with pixels). To create a new framebuffer object
2762of given size `size` (in pixels), color format, and channels use
2763
2764``` cpp
2765OSPFrameBuffer ospNewFrameBuffer(int size_x, int size_y,
2766    OSPFrameBufferFormat format = OSP_FB_SRGBA,
2767    uint32_t frameBufferChannels = OSP_FB_COLOR);
2768```
2769
2770The parameter `format` describes the format the color buffer has *on the
2771host*, and the format that `ospMapFrameBuffer` will eventually return.
2772Valid values are:
2773
2774| Name           | Description                                                 |
2775|:---------------|:------------------------------------------------------------|
2776| OSP_FB_NONE    | framebuffer will not be mapped by the application           |
2777| OSP_FB_RGBA8   | 8 bit \[0–255\] linear component red, green, blue, alpha    |
2778| OSP_FB_SRGBA   | 8 bit sRGB gamma encoded color components, and linear alpha |
2779| OSP_FB_RGBA32F | 32 bit float components red, green, blue, alpha             |
2780
2781Supported color formats of the framebuffer that can be passed to
2782`ospNewFrameBuffer`, i.e., valid constants of type
2783`OSPFrameBufferFormat`.
2784
2785The parameter `frameBufferChannels` specifies which channels the
2786framebuffer holds, and can be combined together by bitwise OR from the
2787values of `OSPFrameBufferChannel` listed in the table below.
2788
2789| Name            | Description                                                                                                                                |
2790|:----------------|:-------------------------------------------------------------------------------------------------------------------------------------------|
2791| OSP_FB_COLOR    | RGB color including alpha                                                                                                                  |
2792| OSP_FB_DEPTH    | euclidean distance to the camera (*not* to the image plane), as linear 32 bit float; for multiple samples per pixel their minimum is taken |
2793| OSP_FB_ACCUM    | accumulation buffer for progressive refinement                                                                                             |
2794| OSP_FB_VARIANCE | for estimation of the current noise level if OSP_FB_ACCUM is also present, see [rendering](#rendering)                                     |
2795| OSP_FB_NORMAL   | accumulated world-space normal of the first non-specular hit, as vec3f                                                                     |
2796| OSP_FB_ALBEDO   | accumulated material albedo (color without illumination) at the first hit, as vec3f                                                        |
2797
2798Framebuffer channels constants (of type `OSPFrameBufferChannel`), naming
2799optional information the framebuffer can store. These values can be
2800combined by bitwise OR when passed to `ospNewFrameBuffer`.
2801
2802If a certain channel value is *not* specified, the given buffer channel
2803will not be present. Note that OSPRay makes a clear distinction between
2804the *external* format of the framebuffer and the internal one: The
2805external format is the format the user specifies in the `format`
2806parameter; it specifies what color format OSPRay will eventually
2807*return* the framebuffer to the application (when calling
2808`ospMapFrameBuffer`): no matter what OSPRay uses internally, it will
2809simply return a 2D array of pixels of that format, with possibly all
2810kinds of reformatting, compression/decompression, etc., going on
2811in-between the generation of the *internal* framebuffer and the mapping
2812of the externally visible one.
2813
2814In particular, `OSP_FB_NONE` is a perfectly valid pixel format for a
2815framebuffer that an application will never map. For example, an
2816application driving a display wall may well generate an intermediate
2817framebuffer and eventually transfer its pixel to the individual displays
2818using an `OSPImageOperation` [image operation](#image-operation).
2819
2820The application can map the given channel of a framebuffer – and thus
2821access the stored pixel information – via
2822
2823``` cpp
2824const void *ospMapFrameBuffer(OSPFrameBuffer, OSPFrameBufferChannel = OSP_FB_COLOR);
2825```
2826
2827Note that `OSP_FB_ACCUM` or `OSP_FB_VARIANCE` cannot be mapped. The
2828origin of the screen coordinate system in OSPRay is the lower left
2829corner (as in OpenGL), thus the first pixel addressed by the returned
2830pointer is the lower left pixel of the image.
2831
2832A previously mapped channel of a framebuffer can be unmapped by passing
2833the received pointer `mapped` to
2834
2835``` cpp
2836void ospUnmapFrameBuffer(const void *mapped, OSPFrameBuffer);
2837```
2838
2839The individual channels of a framebuffer can be cleared with
2840
2841``` cpp
2842void ospResetAccumulation(OSPFrameBuffer);
2843```
2844
2845This function will clear *all* accumulating buffers (`OSP_FB_VARIANCE`,
2846`OSP_FB_NORMAL`, and `OSP_FB_ALBEDO`, if present) and resets the
2847accumulation counter `accumID`. It is unspecified if the existing color
2848and depth buffers are physically cleared when `ospResetAccumulation` is
2849called.
2850
2851If `OSP_FB_VARIANCE` is specified, an estimate of the variance of the
2852last accumulated frame can be queried with
2853
2854``` cpp
2855float ospGetVariance(OSPFrameBuffer);
2856```
2857
2858Note this value is only updated after synchronizing with
2859`OSP_FRAME_FINISHED`, as further described in [asynchronous
2860rendering](#asynchronous-rendering). The estimated variance can be used
2861by the application as a quality indicator and thus to decide whether to
2862stop or to continue progressive rendering.
2863
2864The framebuffer takes a list of pixel operations to be applied to the
2865image in sequence as an `OSPData`. The pixel operations will be run in
2866the order they are in the array.
2867
2868| Type                  | Name           | Description                          |
2869|:----------------------|:---------------|:-------------------------------------|
2870| OSPImageOperation\[\] | imageOperation | ordered sequence of image operations |
2871
2872Parameters accepted by the framebuffer.
2873
2874### Image Operation
2875
2876Image operations are functions that are applied to every pixel of a
2877frame. Examples include post-processing, filtering, blending, tone
2878mapping, or sending tiles to a display wall. To create a new pixel
2879operation of given type `type` use
2880
2881``` cpp
2882OSPImageOperation ospNewImageOperation(const char *type);
2883```
2884
2885#### Tone Mapper
2886
2887The tone mapper is a pixel operation which implements a generic filmic
2888tone mapping operator. Using the default parameters it approximates the
2889Academy Color Encoding System (ACES). The tone mapper is created by
2890passing the type string “`tonemapper`” to `ospNewImageOperation`. The
2891tone mapping curve can be customized using the parameters listed in the
2892table below.
2893
2894| Type  | Name      | Default | Description                                                              |
2895|:------|:----------|--------:|:-------------------------------------------------------------------------|
2896| float | exposure  |     1.0 | amount of light per unit area                                            |
2897| float | contrast  |  1.6773 | contrast (toe of the curve); typically is in \[1–2\]                     |
2898| float | shoulder  |  0.9714 | highlight compression (shoulder of the curve); typically is in \[0.9–1\] |
2899| float | midIn     |    0.18 | mid-level anchor input; default is 18% gray                              |
2900| float | midOut    |    0.18 | mid-level anchor output; default is 18% gray                             |
2901| float | hdrMax    | 11.0785 | maximum HDR input that is not clipped                                    |
2902| bool  | acesColor |    true | apply the ACES color transforms                                          |
2903
2904Parameters accepted by the tone mapper.
2905
2906To use the popular “Uncharted 2” filmic tone mapping curve instead, set
2907the parameters to the values listed in the table below.
2908
2909| Name      | Value  |
2910|:----------|:-------|
2911| contrast  | 1.1759 |
2912| shoulder  | 0.9746 |
2913| midIn     | 0.18   |
2914| midOut    | 0.18   |
2915| hdrMax    | 6.3704 |
2916| acesColor | false  |
2917
2918Filmic tone mapping curve parameters. Note that the curve includes an
2919exposure bias to match 18% middle gray.
2920
2921#### Denoiser
2922
2923OSPRay comes with a module that adds support for Intel® Open Image
2924Denoise. This is provided as an optional module as it creates an
2925additional project dependency at compile time. The module implements a
2926“`denoiser`” frame operation, which denoises the entire frame before the
2927frame is completed.
2928
2929Rendering
2930---------
2931
2932### Asynchronous Rendering
2933
2934Rendering is by default asynchronous (non-blocking), and is done by
2935combining a framebuffer, renderer, camera, and world.
2936
2937What to render and how to render it depends on the renderer’s
2938parameters. If the framebuffer supports accumulation (i.e., it was
2939created with `OSP_FB_ACCUM`) then successive calls to `ospRenderFrame`
2940will progressively refine the rendered image.
2941
2942To start an render task, use
2943
2944``` cpp
2945OSPFuture ospRenderFrame(OSPFrameBuffer, OSPRenderer, OSPCamera, OSPWorld);
2946```
2947
2948This returns an `OSPFuture` handle, which can be used to synchronize
2949with the application, cancel, or query for progress of the running task.
2950When `ospRenderFrame` is called, there is no guarantee when the
2951associated task will begin execution.
2952
2953Progress of a running frame can be queried with the following API
2954function
2955
2956``` cpp
2957float ospGetProgress(OSPFuture);
2958```
2959
2960This returns the approximated progress of the task in \[0-1\].
2961
2962Applications can cancel a currently running asynchronous operation via
2963
2964``` cpp
2965void ospCancel(OSPFuture);
2966```
2967
2968Applications can wait on the result of an asynchronous operation, or
2969choose to only synchronize with a specific event. To synchronize with an
2970`OSPFuture` use
2971
2972``` cpp
2973void ospWait(OSPFuture, OSPSyncEvent = OSP_TASK_FINISHED);
2974```
2975
2976The following are values which can be synchronized with the application
2977
2978| Name                | Description                                                                                                                                     |
2979|:--------------------|:------------------------------------------------------------------------------------------------------------------------------------------------|
2980| OSP_NONE_FINISHED   | Do not wait for anything to be finished (immediately return from `ospWait`)                                                                     |
2981| OSP_WORLD_COMMITTED | Wait for the world to be committed (not yet implemented)                                                                                        |
2982| OSP_WORLD_RENDERED  | Wait for the world to be rendered, but not post-processing operations (Pixel/Tile/Frame Op)                                                     |
2983| OSP_FRAME_FINISHED  | Wait for all rendering operations to complete                                                                                                   |
2984| OSP_TASK_FINISHED   | Wait on full completion of the task associated with the future. The underlying task may involve one or more of the above synchronization events |
2985
2986Supported events that can be passed to `ospWait`.
2987
2988Currently only rendering can be invoked asynchronously. However, future
2989releases of OSPRay may add more asynchronous versions of API calls (and
2990thus return `OSPFuture`).
2991
2992Applications can query whether particular events are complete with
2993
2994``` cpp
2995int ospIsReady(OSPFuture, OSPSyncEvent = OSP_TASK_FINISHED);
2996```
2997
2998As the given running task runs (as tracked by the `OSPFuture`),
2999applications can query a boolean \[0, 1\] result if the passed event has
3000been completed.
3001
3002Applications can query how long an async task ran with
3003
3004``` cpp
3005float ospGetTaskDuration(OSPFuture);
3006```
3007
3008This returns the wall clock execution time of the task in seconds. If
3009the task is still running, this will block until the task is completed.
3010This is useful for applications to query exactly how long an
3011asynchronous task executed without the overhead of measuring both task
3012execution + synchronization by the calling application.
3013
3014### Asynchronously Rendering and ospCommit()
3015
3016The use of either `ospRenderFrame` or `ospRenderFrame` requires that all
3017objects in the scene being rendered have been committed before rendering
3018occurs. If a call to `ospCommit()` happens while a frame is rendered,
3019the result is undefined behavior and should be avoided.
3020
3021### Synchronous Rendering
3022
3023For convenience in certain use cases, `ospray_util.h` provides a
3024synchronous version of `ospRenderFrame`:
3025
3026``` cpp
3027float ospRenderFrameBlocking(OSPFrameBuffer, OSPRenderer, OSPCamera, OSPWorld);
3028```
3029
3030This version is the equivalent of:
3031
3032``` cpp
3033ospRenderFrame
3034ospWait(f, OSP_TASK_FINISHED)
3035return ospGetVariance(fb)
3036```
3037
3038This version is closest to `ospRenderFrame` from OSPRay v1.x.
3039
3040Distributed Rendering with MPI
3041==============================
3042
3043The purpose of the MPI module for OSPRay is to provide distributed
3044rendering capabilities for OSPRay. The module enables image- and
3045data-parallel rendering across HPC clusters using MPI, allowing
3046applications to transparently distribute rendering work, or to render
3047data sets which are too large to fit in memory on a single machine.
3048
3049The MPI module provides two OSPRay devices to allow applications to
3050leverage distributed rendering capabilities. The `mpiOffload` device
3051provides transparent image-parallel rendering, where the same OSPRay
3052application written for local rendering can be replicated across
3053multiple nodes to distribute the rendering work. The `mpiDistributed`
3054device allows MPI distributed applications to use OSPRay for distributed
3055rendering, where each rank can render and independent piece of a global
3056data set, or hybrid rendering where ranks partially or completely share
3057data.
3058
3059MPI Offload Rendering
3060---------------------
3061
3062The `mpiOffload` device can be used to distribute image rendering tasks
3063across a cluster without requiring modifications to the application
3064itself. Existing applications using OSPRay for local rendering simply be
3065passed command line arguments to load the module and indicate that the
3066`mpiOffload` device should be used for image-parallel rendering. To load
3067the module, pass `--osp:load-modules=mpi`, to select the
3068MPIOffloadDevice, pass `--osp:device=mpiOffload`. For example, the
3069`ospExamples` application can be run as:
3070
3071``` sh
3072mpirun -n <N> ./ospExamples --osp:load-modules=mpi --osp:device=mpiOffload
3073```
3074
3075and will automatically distribute the image rendering tasks among the
3076corresponding `N` nodes. Note that in this configuration rank 0 will act
3077as a master/application rank, and will run the user application code but
3078not perform rendering locally. Thus, a minimum of 2 ranks are required,
3079one master to run the application and one worker to perform the
3080rendering. Running with 3 ranks for example would now distribute half
3081the image rendering work to rank 1 and half to rank 2.
3082
3083If more control is required over the placement of ranks to nodes, or you
3084want to run a worker rank on the master node as well you can run the
3085application and the `ospray_mpi_worker` program through MPI’s MPMD mode.
3086The `ospray_mpi_worker` will load the MPI module and select the offload
3087device by default.
3088
3089``` sh
3090mpirun -n 1 ./ospExamples --osp:load-modules=mpi --osp:device=mpiOffload \
3091  : -n <N> ./ospray_mpi_worker
3092```
3093
3094If initializing the `mpiOffload` device manually, or passing parameters
3095through the command line, the following parameters can be set:
3096
3097| Type   | Name                    | Default | Description                                                                                                                                                                                       |
3098|:-------|:------------------------|--------:|:--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
3099| string | mpiMode                 |     mpi | The mode to communicate with the worker ranks. `mpi` will assume you’re launching the application and workers in the same mpi command (or split launch command). `mpi` is the only supported mode |
3100| uint   | maxCommandBufferEntries |    8192 | Set the max number of commands to buffer before submitting the command buffer to the workers                                                                                                      |
3101| uint   | commandBufferSize       | 512 MiB | Set the max command buffer size to allow. Units are in MiB. Max size is 1.8 GiB                                                                                                                   |
3102| uint   | maxInlineDataSize       |  32 MiB | Set the max size of an OSPData which can be inline’d into the command buffer instead of being sent separately. Max size is half the commandBufferSize. Units are in MiB                           |
3103
3104Parameters specific to the `mpiOffload` Device.
3105
3106The `maxCommandBufferEntries`, `commandBufferSize`, and
3107`maxInlineDataSize` can also be set via the environment variables:
3108`OSPRAY_MPI_MAX_COMMAND_BUFFER_ENTRIES`,
3109`OSPRAY_MPI_COMMAND_BUFFER_SIZE`, and `OSPRAY_MPI_MAX_INLINE_DATA_SIZE`,
3110respectively.
3111
3112The `mpiOffload` device does not support multiple init/shutdown cycles.
3113Thus, to run `ospBenchmark` for this device make sure to exclude the
3114init/shutdown test by passing `--benchmark_filter=-ospInit_ospShutdown`
3115through the command line.
3116
3117MPI Distributed Rendering
3118-------------------------
3119
3120While MPI Offload rendering is used to transparently distribute
3121rendering work without requiring modification to the application, MPI
3122Distributed rendering is targeted at use of OSPRay within MPI-parallel
3123applications. The MPI distributed device can be selected by loading the
3124`mpi` module, and manually creating and using an instance of the
3125`mpiDistributed` device:
3126
3127``` cpp
3128ospLoadModule("mpi");
3129
3130OSPDevice mpiDevice = ospNewDevice("mpiDistributed");
3131ospDeviceCommit(mpiDevice);
3132ospSetCurrentDevice(mpiDevice);
3133```
3134
3135Your application can either initialize MPI before-hand, ensuring that
3136`MPI_THREAD_SERIALIZED` or higher is supported, or allow the device to
3137initialize MPI on commit. Thread multiple support is required if your
3138application will make MPI calls while rendering asynchronously with
3139OSPRay. When using the distributed device each rank can specify
3140independent local data using the OSPRay API, as if rendering locally.
3141However, when calling `ospRenderFrameAsync` the ranks will work
3142collectively to render the data. The distributed device supports both
3143image-parallel, where the data is replicated, and data-parallel, where
3144the data is distributed, rendering modes. The `mpiDistributed` device
3145will by default use each rank in `MPI_COMM_WORLD` as a render worker;
3146however, it can also take a specific MPI communicator to use as the
3147world communicator. Only those ranks in the specified communicator will
3148participate in rendering.
3149
3150| Type    | Name              |        Default | Description                                                               |
3151|:--------|:------------------|---------------:|:--------------------------------------------------------------------------|
3152| void \* | worldCommunicator | MPI_COMM_WORLD | The MPI communicator which the OSPRay workers should treat as their world |
3153
3154Parameters specific to the distributed `mpiDistributed` Device.
3155
3156| Type      | Name   | Default | Description                                                                          |
3157|:----------|:-------|--------:|:-------------------------------------------------------------------------------------|
3158| box3f\[\] | region |    NULL | A list of bounding boxes which bound the owned local data to be rendered by the rank |
3159
3160Parameters specific to the distributed `OSPWorld`.
3161
3162| Type  | Name       |         Default | Description                                                                                                                                                              |
3163|:------|:-----------|----------------:|:-------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
3164| int   | aoSamples  |               0 | The number of AO samples to take per-pixel                                                                                                                               |
3165| float | aoDistance | 10<sup>20</sup> | The AO ray length to use. Note that if the AO ray would have crossed a rank boundary and ghost geometry is not available, there will be visible artifacts in the shading |
3166
3167Parameters specific to the `mpiRaycast` renderer.
3168
3169### Image Parallel Rendering in the MPI Distributed Device
3170
3171If all ranks specify exactly the same data, the distributed device can
3172be used for image-parallel rendering. This works identical to the
3173offload device, except that the MPI-aware application is able to load
3174data in parallel on each rank rather than loading on the master and
3175shipping data out to the workers. When a parallel file system is
3176available, this can improve data load times. Image-parallel rendering is
3177selected by specifying the same data on each rank, and using any of the
3178existing local renderers (e.g., `scivis`, `pathtracer`). See
3179[ospMPIDistribTutorialReplicated](https://github.com/ospray/ospray/blob/master/modules/mpi/tutorials/ospMPIDistribTutorialReplicated.cpp)
3180for an example.
3181
3182### Data Parallel Rendering in the MPI Distributed Device
3183
3184The MPI Distributed device also supports data-parallel rendering with
3185sort-last compositing. Each rank can specify a different piece of data,
3186as long as the bounding boxes of each rank’s data are non-overlapping.
3187The rest of the scene setup is similar to local rendering; however, for
3188distributed rendering only the `mpiRaycast` renderer is supported. This
3189renderer implements a subset of the `scivis` rendering features which
3190are suitable for implementation in a distributed environment.
3191
3192By default the aggregate bounding box of the instances in the local
3193world will be used as the bounds of that rank’s data. However, when
3194using ghost zones for volume interpolation, geometry or ambient
3195occlusion, each rank’s data can overlap. To clip these non-owned overlap
3196regions out a set of regions (the `region` parameter) can pass as a
3197parameter to the `OSPWorld` being rendered. Each rank can specify one or
3198more non-overlapping `box3f`’s which bound the portions of its local
3199data which it is responsible for rendering. See the
3200[ospMPIDistribTutorialVolume](https://github.com/ospray/ospray/blob/master/modules/mpi/tutorials/ospMPIDistribTutorialVolume.cpp)
3201for an example.
3202
3203Finally, the MPI distributed device also supports hybrid-parallel
3204rendering, where multiple ranks can share a single piece of data. For
3205each shared piece of data the rendering work will be assigned
3206image-parallel among the ranks. Partially-shared regions are determined
3207by finding those ranks specifying data with the same bounds (matching
3208regions) and merging them. See the
3209[ospMPIDistribTutorialPartialRepl](https://github.com/ospray/ospray/blob/master/modules/mpi/tutorials/ospMPIDistribTutorialPartialRepl.cpp)
3210for an example.
3211
3212#### Picking on Distributed Data in the MPI Distributed Device
3213
3214Calling `ospPick` in the distributed device will find and return the
3215closest global object at the screen position on the rank that owns that
3216object. The other ranks will report no hit. Picking in the distributed
3217device takes into account data clipping applied through the `regions`
3218parameter to avoid picking ghost data.
3219
3220Interaction with User Modules
3221-----------------------------
3222
3223The MPI Offload rendering mode trivially supports user modules, with the
3224caveat that attempting to share data directly with the application
3225(e.g., passing a `void *` or other tricks to the module) will not work
3226in a distributed environment. Instead, use the `ospNewSharedData` API to
3227share data from the application with OSPRay, which will in turn be
3228copied over the network to the workers.
3229
3230The MPI Distributed device also supports user modules, as all that is
3231required for compositing the distributed data are the bounds of each
3232rank’s local data.
3233
3234MultiDevice Rendering
3235=====================
3236
3237The multidevice module is an experimental OSPRay device type that
3238renders images by delegating off pixel tiles to a number of internal
3239delegate OSPRay devices. Multidevice is in still in an development stage
3240and is currently limited to automatically creating ISPCDevice delegates.
3241
3242If you wish to try it set the OSPRAY_NUM_SUBDEVICES environmental
3243variable to the number of subdevices you want to create and tell OSPRay
3244to both load the multidevice extension and create a multidevice for
3245rendering instead of the default ISPCDevice.
3246
3247One example in a bash like shell is as follows:
3248
3249``` sh
3250OSPRAY_NUM_SUBDEVICES=6 ./ospTutorial --osp:load-modules=multidevice --osp:device=multidevice
3251```
3252
3253Tutorials
3254=========
3255
3256ospTutorial
3257-----------
3258
3259A minimal working example demonstrating how to use OSPRay can be found
3260at
3261[`apps/tutorials/ospTutorial.c`](https://github.com/ospray/ospray/blob/master/apps/ospTutorial/ospTutorial.c)[10].
3262
3263An example of building `ospTutorial.c` with CMake can be found in
3264[`apps/tutorials/ospTutorialFindospray/`](https://github.com/ospray/ospray/tree/master/apps/ospTutorial/ospTutorialFindospray).
3265
3266To build the tutorial on Linux, build it in a build directory with
3267
3268``` sh
3269gcc -std=c99 ../apps/ospTutorial/ospTutorial.c \
3270-I ../ospray/include -L . -lospray -Wl,-rpath,. -o ospTutorial
3271```
3272
3273On Windows build it can be build manually in a
3274“build_directory\\$Configuration” directory with
3275
3276``` sh
3277cl ..\..\apps\ospTutorial\ospTutorial.c -I ..\..\ospray\include -I ..\.. ospray.lib
3278```
3279
3280Running `ospTutorial` will create two images of two triangles, rendered
3281with the Scientific Visualization renderer with full Ambient Occlusion.
3282The first image `firstFrame.ppm` shows the result after one call to
3283`ospRenderFrame` – jagged edges and noise in the shadow can be seen.
3284Calling `ospRenderFrame` multiple times enables progressive refinement,
3285resulting in antialiased edges and converged shadows, shown after ten
3286frames in the second image `accumulatedFrames.ppm`.
3287
3288![First frame.](https://ospray.github.io/images/tutorial_firstframe.png)
3289
3290![After accumulating ten
3291frames.](https://ospray.github.io/images/tutorial_accumulatedframe.png)
3292
3293ospExamples
3294-----------
3295
3296Apart from tutorials, `OSPRay` comes with a C++ app called
3297[`ospExamples`](https://github.com/ospray/ospray/tree/master/apps/ospExamples)
3298which is an elaborate easy-to-use tutorial, with a single interface to
3299try various `OSPRay` features. It is aimed at providing users with
3300multiple simple scenes composed of basic geometry types, lights, volumes
3301etc. to get started with OSPRay quickly.
3302
3303`ospExamples` app runs a `GLFWOSPRayWindow` instance that manages
3304instances of the camera, framebuffer, renderer and other OSPRay objects
3305necessary to render an interactive scene. The scene is rendered on a
3306`GLFW` window with an `imgui` GUI controls panel for the user to
3307manipulate the scene at runtime.
3308
3309The application is located in
3310[`apps/ospExamples/`](https://github.com/ospray/ospray/tree/master/apps/ospExamples)
3311directory and can be built with CMake. It can be run from the build
3312directory via:
3313
3314    ./ospExamples <command-line-parameter>
3315
3316The command line parameter is optional however.
3317
3318<figure>
3319<img src="https://ospray.github.io/images/ospExamples.png" width="90.0%" alt="ospExamples application with default boxes scene." /><figcaption aria-hidden="true"><code>ospExamples</code> application with default <code>boxes</code> scene.</figcaption>
3320</figure>
3321
3322
3323
3324### Scenes
3325
3326Different scenes can be selected from the `scenes` dropdown and each
3327scene corresponds to an instance of a special `detail::Builder` struct.
3328Example builders are located in
3329[`apps/common/ospray_testing/builders/`](https://github.com/ospray/ospray/tree/master/apps/common/ospray_testing/builders).
3330These builders provide a usage guide for the OSPRay scene hierarchy and
3331OSPRay API in the form of `cpp` wrappers. They instantiate and manage
3332objects for the specific scene like `cpp::Geometry`, `cpp::Volume`,
3333`cpp::Light` etc.
3334
3335The `detail::Builder` base struct is mostly responsible for setting up
3336OSPRay `world` and objects common in all scenes (for example lighting
3337and ground plane), which can be conveniently overridden in the derived
3338builders.
3339
3340Given below are different scenes listed with their string identifiers:
3341
3342boxes
3343A simple scene with `box` geometry type.
3344
3345cornell_box
3346A scene depicting a classic cornell box with `quad` mesh geometry type
3347for rendering two cubes and a `quad` light type.
3348
3349curves
3350A simple scene with `curve` geometry type and options to change
3351`curveBasis`. For details on different basis’ please check documentation
3352of [curves](#curves).
3353
3354gravity_spheres_volume
3355A scene with `structuredRegular` type of [volume](#volumes).
3356
3357gravity_spheres_isosurface
3358A scene depicting iso-surface rendering of `gravity_spheres_volume`
3359using geometry type `isosurface`.
3360
3361perlin_noise_volumes
3362An example scene with `structuredRegular` volume type depicting perlin
3363noise.
3364
3365random_spheres
3366A simple scene depicting `sphere` geometry type.
3367
3368streamlines
3369A scene showcasing streamlines geometry derived from `curve` geometry
3370type.
3371
3372subdivision_cube
3373A scene with a cube of `subdivision` geometry type to showcase
3374subdivision surfaces.
3375
3376unstructured_volume
3377A simple scene with a volume of `unstructured` volume type.
3378
3379### Renderer
3380
3381This app comes with four [renderer](#renderers) options: `scivis`,
3382`pathtracer`, `ao` and `debug`. The app provides some common rendering
3383controls like `pixelSamples` and other more specific to the renderer
3384type like `aoSamples` for the `scivis` and `ao` renderer or
3385`maxPathLength` for the `pathtracer`.
3386
3387The sun-sky lighting can be used in a sample scene by enabling the
3388`renderSunSky` option of the `pathtracer` renderer. It allows the user
3389to change `turbidity` and `sunDirection`.
3390
3391<figure>
3392<img src="https://ospray.github.io/images/renderSunSky.png" width="90.0%" alt="Rendering an evening sky with the renderSunSky option." /><figcaption aria-hidden="true">Rendering an evening sky with the <code>renderSunSky</code> option.</figcaption>
3393</figure>
3394
3395
3396
3397MPI Distributed Tutorials
3398=========================
3399
3400The MPI Distributed tutorials demonstrate various ways that distributed
3401applications using MPI can leverage OSPRay’s distributed rendering
3402capabilities to render distributed, replicated, and partially replicated
3403data across the processes. The tutorials will be built as part of OSPRay
3404when running cmake with
3405
3406``` sh
3407cmake \
3408  -DOSPRAY_ENABLE_APPS=ON \
3409  -DOSPRAY_APPS_TUTORIALS=ON \
3410  -DOSPRAY_MODULE_MPI=ON \
3411  -DOSPRAY_MPI_BUILD_TUTORIALS=ON \
3412  <other args>
3413```
3414
3415ospMPIDistribTutorial
3416---------------------
3417
3418A minimal working example demonstrating how to use OSPRay for rendering
3419distributed data can be found at
3420[`modules/mpi/tutorials/ospMPIDistribTutorial.c`](https://github.com/ospray/ospray/blob/master/modules/mpi/tutorials/ospMPIDistribTutorial.c)[11].
3421
3422The compilation process via CMake is the similar to
3423[`apps/tutorials/ospTutorialFindospray/`](https://github.com/ospray/ospray/tree/master/apps/ospTutorial/ospTutorialFindospray),
3424with the addition of finding and linking MPI.
3425
3426To build the tutorial on Linux, build it in a build directory with
3427
3428``` sh
3429mpicc -std=c99 ../modules/mpi/tutorials/ospMPIDistribTutorial.c \
3430-I ../ospray/include -L . -lospray -Wl,-rpath,. -o ospMPIDistribTutorial
3431```
3432
3433On Windows build it can be build manually in a
3434“build_directory\\$Configuration” directory with
3435
3436``` sh
3437cl ..\..\modules\mpi\tutorials\ospMPIDistribTutorial.c -I ..\..\ospray\include -I ..\.. ospray.lib
3438```
3439
3440The MPI module does not need to be linked explicitly, as it is loaded as
3441a module at runtime.
3442
3443<figure>
3444<img src="https://ospray.github.io/images/ospMPIDistribTutorial_firstFrame.jpg" width="60.0%" alt="The first frame output by the ospMPIDistribTutorial or C++ tutorial with 4 ranks." /><figcaption aria-hidden="true">The first frame output by the <code>ospMPIDistribTutorial</code> or C++ tutorial with 4 ranks.</figcaption>
3445</figure>
3446
3447
3448
3449<figure>
3450<img src="https://ospray.github.io/images/ospMPIDistribTutorial_accumulatedFrame.jpg" width="60.0%" alt="The accumulated frame output by the ospMPIDistribTutorial or C++ tutorial with 4 ranks." /><figcaption aria-hidden="true">The accumulated frame output by the <code>ospMPIDistribTutorial</code> or C++ tutorial with 4 ranks.</figcaption>
3451</figure>
3452
3453
3454
3455ospMPIDistribTutorialSpheres and ospMPIDistribTutorialVolume
3456------------------------------------------------------------
3457
3458The spheres and volume distributed tutorials are built as part of the
3459MPI tutorials when building OSPRay with the MPI module and tutorials
3460enabled. These tutorials demonstrate using OSPRay to render distributed
3461data sets where each rank owns some subregion of the data, and
3462displaying the output in an interactive window. The domain is
3463distributed in a grid among the processes, each of which will generate a
3464subset of the data corresponding to its subdomain.
3465
3466In `ospMPIDistribTutorialSpheres`, each process generates a set of
3467spheres within its assigned domain. The spheres are colored from dark to
3468light blue, where lighter colors correspond to higher ranks.
3469
3470<figure>
3471<img src="https://ospray.github.io/images/ospMPIDistribTutorialSpheres.jpg" width="60.0%" alt="Running ospMPIDistribTutorialSpheres on 4 ranks." /><figcaption aria-hidden="true">Running <code>ospMPIDistribTutorialSpheres</code> on 4 ranks.</figcaption>
3472</figure>
3473
3474
3475
3476In `ospMPIDistribTutorialVolume`, each process generates a subbrick of
3477volume data, which is colored by its rank.
3478
3479<figure>
3480<img src="https://ospray.github.io/images/ospMPIDistribTutorialVolume.jpg" width="60.0%" alt="Running ospMPIDistribTutorialVolume on 4 ranks." /><figcaption aria-hidden="true">Running <code>ospMPIDistribTutorialVolume</code> on 4 ranks.</figcaption>
3481</figure>
3482
3483
3484
3485ospMPIDistribTutorialPartialRepl
3486--------------------------------
3487
3488The partially replicated MPI tutorial demonstrates how to use OSPRay’s
3489distributed rendering capabilities to render data sets that are
3490partially replicated among the processes. Each pair of ranks generates
3491the same volume brick, allowing them to subdivide the rendering workload
3492between themselves. For example, when run with two ranks, each will
3493generate the same brick and be responsible for rendering half of the
3494image tiles it projects to. When run with four ranks, the pairs of ranks
34950,1 and 2,3 will generate the same data and divide the rendering
3496workload for that data among themselves.
3497
3498The image work subdivision happens automatically, based on which ranks
3499specify the same bounding box for their data, as demonstrated in the
3500tutorial.
3501
3502The partially replicated distribution is useful to support load-balanced
3503rendering of data sets that are too large to be fully replicated among
3504the processes, but are small enough to be partially replicated among
3505them.
3506
3507ospMPIDistribTutorialReplicated
3508-------------------------------
3509
3510The replicated MPI tutorial demonstrates how OSPRay’s distributed
3511rendering capabilities can be used to render data sets that are fully
3512replicated among the ranks with advanced illumination effects. In this
3513case, although the processes are run MPI parallel, each rank specifies
3514the exact same data. OSPRay’s MPI parallel renderer will detect that the
3515data is replicated in this case and use the same image-parallel
3516rendering algorithms employed in the MPI offload rendering configuration
3517to render the data. This image-parallel rendering algorithm supports all
3518rendering configurations that are used in local rendering, e.g., path
3519tracing, to provide high-quality images.
3520
3521The replicated MPI tutorial supports the same scenes and parameters as
3522the [`ospExamples`](#ospexamples) app described above.
3523
3524This mode can be useful when high-quality rendering is desired and it is
3525possible to copy the entire data set on to each rank, or to accelerate
3526loading of a large model by leveraging a parallel file system.
3527
3528[1] For example, if OSPRay is in `~/Projects/ospray`, ISPC will also be
3529searched in `~/Projects/ispc-v1.16.1-linux`.
3530
3531[2] This file is usually in
3532`${install_location}/[lib|lib64]/cmake/ospray-${version}/`. If CMake
3533does not find it automatically, then specify its location in variable
3534`ospray_DIR` (either an environment variable or CMake variable).
3535
3536[3] The number of items to be copied is defined by the size of the
3537source array.
3538
3539[4] For consecutive memory addresses the x-index of the corresponding
3540voxel changes the quickest.
3541
3542[5] actually a parallelogram
3543
3544[6] including spheres, boxes, infinite planes, closed meshes, closed
3545subdivisions and curves
3546
3547[7] `OSPBounds` has essentially the same layout as the `OSP_BOX3F`
3548[`OSPDataType`](#data).
3549
3550[8] If there are multiple ambient lights then their contribution is
3551added.
3552
3553[9] respectively (127,127,255) for 8 bit textures and
3554(32767,32767,65535) for 16 bit textures
3555
3556[10] A C++ version that uses the C++ convenience wrappers of OSPRay’s
3557C99 API via
3558[`include/ospray/ospray_cpp.h`](https://github.com/ospray/ospray/blob/master/ospray/include/ospray/ospray_cpp.h)
3559is available at
3560[`apps/tutorials/ospTutorial.cpp`](https://github.com/ospray/ospray/blob/master/apps/ospTutorial/ospTutorial.cpp).
3561
3562[11] A C++ version that uses the C++ convenience wrappers of OSPRay’s
3563C99 API via
3564[`include/ospray/ospray_cpp.h`](https://github.com/ospray/ospray/blob/master/ospray/include/ospray/ospray_cpp.h)
3565is available at
3566[`modules/mpi/tutorials/ospMPIDistribTutorial.cpp`](https://github.com/ospray/ospray/blob/master/modules/mpi/tutorials/ospMPIDistribTutorial.cpp).
3567