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