RT wrapper, VisRTX backend

nightly-master
Tim Biedert 4 years ago committed by Utkarsh Ayachit
parent 24f213c304
commit bae8e7b47c

4
.gitignore vendored

@ -15,3 +15,7 @@ project.xcworkspace
# Exclude VSCode settings and configuration folder
*.vscode*
# Exclude Visual Studio stuff
.vs*
CMakeSettings.json

@ -1,5 +1,5 @@
#
# Copyright (c) 2016, NVIDIA CORPORATION. All rights reserved.
# Copyright (c) 2019, NVIDIA CORPORATION. All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
@ -26,14 +26,10 @@
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
# Locate the OptiX distribution. Search relative to the SDK first, then look in the system.
# Our initial guess will be within the SDK.
set(OptiX_INSTALL_DIR "${CMAKE_SOURCE_DIR}/../" CACHE PATH "Path to OptiX installed location.")
# The distribution contains both 32 and 64 bit libraries. Adjust the library
# search path based on the bit-ness of the build. (i.e. 64: bin64, lib64; 32:
# bin, lib). Note that on Mac, the OptiX library is a universal binary, so we
# Adjust the library search path based on the bit-ness of the build.
# (i.e. 64: bin64, lib64; 32: bin, lib).
# Note that on Mac, the OptiX library is a universal binary, so we
# only need to look in lib and not lib64 for 64 bit builds.
if(CMAKE_SIZEOF_VOID_P EQUAL 8 AND NOT APPLE)
set(bit_dest "64")
@ -41,6 +37,8 @@ else()
set(bit_dest "")
endif()
set(OptiX_INSTALL_DIR "" CACHE PATH "Path to OptiX installed location.")
macro(OPTIX_find_api_library name version)
find_library(${name}_LIBRARY
NAMES ${name}.${version} ${name}
@ -62,9 +60,42 @@ macro(OPTIX_find_api_library name version)
endif()
endmacro()
OPTIX_find_api_library(optix 1)
OPTIX_find_api_library(optixu 1)
OPTIX_find_api_library(optix_prime 1)
# OptiX SDKs before 5.1.0 named the library optix.1.lib
# Linux handles this via symlinks and doesn't need changes to the library name.
set(OptiX_version "1")
# The OptiX library is named with the major and minor digits since OptiX 5.1.0.
# Dynamically find the matching library name by parsing the OptiX_INSTALL_DIR.
# This only works if the installation retained the original folder format "OptiX SDK major.minor.micro".
# We want the concatenated major and minor numbers if the version is greater or equal to 5.1.0.
if(WIN32)
if(OptiX_INSTALL_DIR)
string(REGEX REPLACE " |-" ";" OptiX_install_dir_list ${OptiX_INSTALL_DIR})
list(LENGTH OptiX_install_dir_list OptiX_install_dir_list_length)
if(${OptiX_install_dir_list_length} GREATER 0)
# Get the last list element, something like "5.1.0".
list(GET OptiX_install_dir_list -1 OptiX_version_string)
# Component-wise integer version number comparison (version format is major[.minor[.patch[.tweak]]]).
# Starting with OptiX 6.0.0, the full version number is used to avoid the Windows DLL hell.
if(${OptiX_version_string} VERSION_GREATER_EQUAL "6.0.0")
set(OptiX_version ${OptiX_version_string})
elseif(${OptiX_version_string} VERSION_GREATER_EQUAL "5.1.0")
set(OptiX_version "")
string(REPLACE "." ";" OptiX_major_minor_micro_list ${OptiX_version_string})
foreach(index RANGE 0 1)
list(GET OptiX_major_minor_micro_list ${index} number)
string(APPEND OptiX_version ${number})
endforeach()
endif()
endif()
endif()
endif(WIN32)
OPTIX_find_api_library(optix ${OptiX_version})
OPTIX_find_api_library(optixu ${OptiX_version})
OPTIX_find_api_library(optix_prime ${OptiX_version})
# Include
find_path(OptiX_INCLUDE
@ -88,13 +119,13 @@ function(OptiX_report_error error_message required)
endfunction()
if(NOT optix_LIBRARY)
OptiX_report_error("optix library not found. Please locate before proceeding." TRUE)
OptiX_report_error("OptiX library not found. Please set OptiX_INSTALL_DIR to locate it automatically." TRUE)
endif()
if(NOT OptiX_INCLUDE)
OptiX_report_error("OptiX headers (optix.h and friends) not found. Please locate before proceeding." TRUE)
OptiX_report_error("OptiX headers (optix.h and friends) not found. Please set OptiX_INSTALL_DIR to locate them automatically." TRUE)
endif()
if(NOT optix_prime_LIBRARY)
OptiX_report_error("optix Prime library not found. Please locate before proceeding." FALSE)
OptiX_report_error("OptiX Prime library not found. Please set OptiX_INSTALL_DIR to locate it automatically." FALSE)
endif()
# Macro for setting up dummy targets
@ -135,8 +166,8 @@ endfunction()
# Sets up a dummy target
OptiX_add_imported_library(optix "${optix_LIBRARY}" "${optix_DLL}" "${OPENGL_LIBRARIES}")
OptiX_add_imported_library(optixu "${optixu_LIBRARY}" "${optixu_DLL}" "")
OptiX_add_imported_library(optix_prime "${optix_prime_LIBRARY}" "${optix_prime_DLL}" "")
OptiX_add_imported_library(optixu "${optixu_LIBRARY}" "${optixu_DLL}" "")
OptiX_add_imported_library(optix_prime "${optix_prime_LIBRARY}" "${optix_prime_DLL}" "")
macro(OptiX_check_same_path libA libB)
if(_optix_path_to_${libA})

@ -16,6 +16,12 @@ set(classes
vtkOSPRayVolumeNode
vtkOSPRayWindowNode)
set(RTWrapper_sources
RTWrapper/RTWrapper.cxx)
set(RTWrapper_headers
RTWrapper/RTWrapper.h)
vtk_object_factory_declare(
BASE vtkOSPRayVolumeInterface
OVERRIDE vtkOSPRayVolumeMapper)
@ -25,36 +31,66 @@ vtk_object_factory_configure(
HEADER_FILE vtk_object_factory_header
EXPORT_MACRO "VTKRENDERINGOSPRAY_EXPORT")
# OSPRay
option(VTK_ENABLE_OSPRAY "Enable OSPRay rendering backend" ON)
set(OSPRAY_INSTALL_DIR "" CACHE PATH "Install location of OSPRay")
mark_as_advanced(OSPRAY_INSTALL_DIR)
if (VTK_ENABLE_OSPRAY)
# TODO: Send patches upstream to export targets from ospray.
find_package(ospray 1.8 REQUIRED HINTS ${OSPRAY_INSTALL_DIR})
option(VTKOSPRAY_ENABLE_DENOISER "Build OSPRay Renderer using OpenImageDenoise")
if (VTKOSPRAY_ENABLE_DENOISER)
find_package(OpenImageDenoise 0.8 REQUIRED)
add_definitions(-DVTKOSPRAY_ENABLE_DENOISER)
set(OPENIMAGEDENIOSE OpenImageDenoise)
endif()
endif()
# VisRTX
option(VTK_ENABLE_VISRTX "Enable VisRTX rendering backend" ON)
set(VISRTX_INSTALL_DIR "" CACHE PATH "Install location of VisRTX")
mark_as_advanced(VISRTX_INSTALL_DIR)
if (VTK_ENABLE_VISRTX)
find_package(VisRTX CONFIG REQUIRED HINTS ${VISRTX_INSTALL_DIR})
endif()
if (VisRTX_FOUND)
list(APPEND RTWrapper_sources RTWrapper/VisRTX/VisRTXBackend.cxx)
endif()
if (NOT ospray_FOUND AND NOT VisRTX_FOUND)
message("Warning: Ray tracing requires OSPRay and/or VisRTX, turn VTK_ENABLE_OSPRAY and/or VTK_ENABLE_VISRTX ON.")
endif()
vtk_module_add_module(VTK::RenderingOSPRay
CLASSES ${classes}
SOURCES ${vtk_object_factory_source}
PRIVATE_HEADERS ${vtk_object_factory_header})
option(VTKOSPRAY_ENABLE_DENOISER "build OSPRay Renderer using OpenImageDenoise")
if (VTKOSPRAY_ENABLE_DENOISER)
find_package(OpenImageDenoise 0.8 REQUIRED)
add_definitions(-DVTKOSPRAY_ENABLE_DENOISER)
set(OPENIMAGEDENIOSE OpenImageDenoise)
endif()
SOURCES ${vtk_object_factory_source} ${RTWrapper_sources}
PRIVATE_HEADERS ${vtk_object_factory_header} ${RTWrapper_headers})
# TODO: Send patches upstream to export targets from ospray.
find_package(ospray 1.8 REQUIRED)
vtk_module_link(VTK::RenderingOSPRay
PUBLIC
${OSPRAY_LIBRARIES}
PRIVATE
${OPENIMAGEDENIOSE}
)
vtk_module_include(VTK::RenderingOSPRay
PUBLIC
${OSPRAY_INCLUDE_DIRS}
)
# TODO: FindOSPRay should do this.
# OSPRay_Core uses MMTime which is in it's own special library.
if (WIN32)
if (ospray_FOUND)
vtk_module_link(VTK::RenderingOSPRay
PUBLIC
${OSPRAY_LIBRARIES}
PRIVATE
Winmm)
endif ()
${OPENIMAGEDENIOSE})
vtk_module_include(VTK::RenderingOSPRay
PUBLIC
${OSPRAY_INCLUDE_DIRS})
# TODO: FindOSPRay should do this.
# OSPRay_Core uses MMTime which is in it's own special library.
if (WIN32)
vtk_module_link(VTK::RenderingOSPRay
PRIVATE
Winmm)
endif ()
vtk_module_definitions(VTK::RenderingOSPRay PRIVATE VTK_ENABLE_OSPRAY)
endif()
if (VisRTX_FOUND)
vtk_module_link(VTK::RenderingOSPRay PUBLIC VisRTX_DynLoad)
vtk_module_definitions(VTK::RenderingOSPRay PRIVATE VTK_ENABLE_VISRTX)
endif()

@ -0,0 +1,82 @@
#pragma once
#include "Types.h"
namespace RTW
{
class Backend
{
public:
virtual ~Backend() = default;
public:
virtual RTWError Init(int *argc, const char **argv) = 0;
virtual void Shutdown() = 0;
virtual bool IsSupported(RTWFeature feature) const = 0;
virtual RTWData NewData(size_t numItems, RTWDataType, const void *source, const uint32_t dataCreationFlags = 0) = 0;
virtual RTWGeometry NewGeometry(const char *type) = 0;
virtual RTWTexture NewTexture(const char* type) = 0;
virtual RTWLight NewLight(RTWRenderer, const char *type) = 0;
virtual RTWLight NewLight2(const char *renderer_type, const char *light_type) = 0;
virtual RTWLight NewLight3(const char *light_type) = 0;
virtual RTWMaterial NewMaterial(RTWRenderer, const char *material_type) = 0;
virtual RTWMaterial NewMaterial2(const char *renderer_type, const char *material_type) = 0;
virtual RTWVolume NewVolume(const char *type) = 0;
virtual RTWTransferFunction NewTransferFunction(const char *type) = 0;
virtual RTWRenderer NewRenderer(const char *type) = 0;
virtual RTWCamera NewCamera(const char *type) = 0;
virtual RTWModel NewModel() = 0;
virtual RTWGeometry NewInstance(RTWModel modelToInstantiate, const rtw::affine3f &transform) = 0;
virtual RTWFrameBuffer NewFrameBuffer(const rtw::vec2i &size, const RTWFrameBufferFormat format, const uint32_t frameBufferChannels) = 0;
virtual void Release(RTWObject) = 0;
virtual void AddGeometry(RTWModel, RTWGeometry) = 0;
virtual void AddVolume(RTWModel, RTWVolume) = 0;
virtual void SetString(RTWObject, const char *id, const char *s) = 0;
virtual void SetObject(RTWObject, const char *id, RTWObject other) = 0;
virtual void SetData(RTWObject, const char *id, RTWData) = 0;
virtual void SetMaterial(RTWGeometry, RTWMaterial) = 0;
virtual void Set1i(RTWObject, const char *id, int32_t x) = 0;
virtual void Set2i(RTWObject, const char *id, int32_t x, int32_t y) = 0;
virtual void Set1f(RTWObject, const char *id, float x) = 0;
virtual void Set2f(RTWObject, const char *id, float x, float y) = 0;
virtual void Set3i(RTWObject, const char *id, int x, int y, int z) = 0;
virtual void Set3f(RTWObject, const char *id, float x, float y, float z) = 0;
virtual void Set4f(RTWObject, const char *id, float x, float y, float z, float w) = 0;
virtual RTWError SetRegion(RTWVolume, void *source, const rtw::vec3i &regionCoords, const rtw::vec3i &regionSize) = 0;
virtual void Commit(RTWObject) = 0;
virtual float RenderFrame(RTWFrameBuffer, RTWRenderer, const uint32_t frameBufferChannels) = 0;
virtual void FrameBufferClear(RTWFrameBuffer, const uint32_t frameBufferChannels) = 0;
virtual const void* MapFrameBuffer(RTWFrameBuffer, const RTWFrameBufferChannel) = 0;
virtual void UnmapFrameBuffer(const void *mapped, RTWFrameBuffer) = 0;
virtual void SetDepthNormalizationGL(RTWFrameBuffer frameBuffer, float clipMin, float clipMax) = 0;
virtual int GetColorTextureGL(RTWFrameBuffer frameBuffer) = 0;
virtual int GetDepthTextureGL(RTWFrameBuffer frameBuffer) = 0;
// Convenience functions (TODO remove)
inline void Setf(RTWObject object, const char *id, float x)
{
Set1f(object, id, x);
}
inline void Set3fv(RTWObject object, const char *id, const float *xyz)
{
Set3f(object, id, xyz[0], xyz[1], xyz[2]);
}
inline void SetVec2f(RTWObject object, const char *id, const rtw::vec2f &v)
{
Set2f(object, id, v.x, v.y);
}
};
}

@ -0,0 +1,321 @@
#pragma once
#include <ospray/ospray.h>
#include "../Backend.h"
#include <stdlib.h>
#include <sstream>
#include <stdexcept>
#include <vector>
namespace RTW
{
OSPFrameBufferFormat convert(RTWFrameBufferFormat format)
{
switch (format)
{
case RTW_FB_RGBA8:
return OSP_FB_RGBA8;
default:
return OSP_FB_NONE;
}
}
OSPTextureFormat convert(RTWTextureFormat format)
{
switch (format)
{
case RTW_TEXTURE_RGBA8:
return OSP_TEXTURE_RGBA8;
case RTW_TEXTURE_RGBA32F:
return OSP_TEXTURE_RGBA32F;
case RTW_TEXTURE_RGB8:
return OSP_TEXTURE_RGB8;
case RTW_TEXTURE_RGB32F:
return OSP_TEXTURE_RGB32F;
case RTW_TEXTURE_R8:
return OSP_TEXTURE_R8;
case RTW_TEXTURE_R32F:
return OSP_TEXTURE_R32F;
}
}
/*
* Simple pass-through backend for OSPRay.
*/
class OSPRayBackend : public Backend
{
public:
RTWError Init(int *, const char **)
{
RTWError ret = RTW_UNKNOWN_ERROR;
int ac = 1;
const char* envArgs = getenv("VTKOSPRAY_ARGS");
if (envArgs)
{
std::stringstream ss(envArgs);
std::string arg;
std::vector<std::string> args;
while (ss >> arg)
{
args.push_back(arg);
}
ac = static_cast<int>(args.size() + 1);
const char** av = new const char*[ac];
av[0] = "pvOSPRay";
for (int i = 1; i < ac; i++)
{
av[i] = args[i - 1].c_str();
}
try
{
ret = static_cast<RTWError>(ospInit(&ac, av));
}
catch (std::runtime_error &)
{
Shutdown();
}
delete[] av;
}
else
{
const char* av[] = { "pvOSPRay\0" };
try
{
ret = static_cast<RTWError>(ospInit(&ac, av));
}
catch (std::runtime_error &)
{
Shutdown();
}
}
return ret;
}
void Shutdown()
{
ospShutdown();
}
bool IsSupported(RTWFeature feature) const
{
switch (feature)
{
case RTW_DEPTH_NORMALIZATION:
return false;
case RTW_OPENGL_INTEROP:
return false;
case RTW_ANIMATED_PARAMETERIZATION:
return false;
case RTW_INSTANCING:
return true;
case RTW_DENOISER:
return false; // OpenImageDenoise is an external lib outside of the backend
case RTW_DEPTH_COMPOSITING:
return true;
}
return false;
}
RTWData NewData(size_t numElements, RTWDataType dataType, const void *source, const uint32_t dataCreationFlags)
{
return reinterpret_cast<RTWData>(ospNewData(numElements, static_cast<OSPDataType>(dataType), source, dataCreationFlags));
}
RTWGeometry NewGeometry(const char *type)
{
return reinterpret_cast<RTWGeometry>(ospNewGeometry(type));
}
RTWTexture NewTexture(const char* type)
{
return reinterpret_cast<RTWTexture>(ospNewTexture(type));
}
RTWLight NewLight(RTWRenderer renderer, const char *type)
{
return reinterpret_cast<RTWLight>(ospNewLight(reinterpret_cast<OSPRenderer>(renderer), type));
}
RTWLight NewLight2(const char *renderer_type, const char *light_type)
{
return reinterpret_cast<RTWLight>(ospNewLight2(renderer_type, light_type));
}
RTWLight NewLight3(const char *light_type)
{
return reinterpret_cast<RTWLight>(ospNewLight3(light_type));
}
RTWMaterial NewMaterial(RTWRenderer renderer, const char *material_type)
{
return reinterpret_cast<RTWMaterial>(ospNewMaterial(reinterpret_cast<OSPRenderer>(renderer), material_type));
}
RTWMaterial NewMaterial2(const char *renderer_type, const char *material_type)
{
return reinterpret_cast<RTWMaterial>(ospNewMaterial2(renderer_type, material_type));
}
RTWVolume NewVolume(const char *type)
{
return reinterpret_cast<RTWVolume>(ospNewVolume(type));
}
RTWTransferFunction NewTransferFunction(const char *type)
{
return reinterpret_cast<RTWTransferFunction>(ospNewTransferFunction(type));
}
RTWRenderer NewRenderer(const char *type)
{
return reinterpret_cast<RTWRenderer>(ospNewRenderer(type));
}
RTWCamera NewCamera(const char *type)
{
return reinterpret_cast<RTWCamera>(ospNewCamera(type));
}
RTWModel NewModel()
{
return reinterpret_cast<RTWModel>(ospNewModel());
}
RTWGeometry NewInstance(RTWModel modelToInstantiate, const rtw::affine3f &transform)
{
osp::affine3f xfm;
memcpy(&xfm, &transform, sizeof(osp::affine3f));
return reinterpret_cast<RTWGeometry>(ospNewInstance(reinterpret_cast<OSPModel>(modelToInstantiate), xfm));
}
RTWFrameBuffer NewFrameBuffer(const rtw::vec2i &size, const RTWFrameBufferFormat format, const uint32_t frameBufferChannels)
{
return reinterpret_cast<RTWFrameBuffer>(ospNewFrameBuffer(osp::vec2i{ size.x, size.y }, convert(format), frameBufferChannels));
}
void Release(RTWObject object)
{
ospRelease(reinterpret_cast<OSPObject>(object));
}
void AddGeometry(RTWModel model, RTWGeometry geometry)
{
ospAddGeometry(reinterpret_cast<OSPModel>(model), reinterpret_cast<OSPGeometry>(geometry));
}
void AddVolume(RTWModel model, RTWVolume volume)
{
ospAddVolume(reinterpret_cast<OSPModel>(model), reinterpret_cast<OSPVolume>(volume));
}
void SetString(RTWObject object, const char *id, const char *s)
{
ospSetString(reinterpret_cast<OSPObject>(object), id, s);
}
void SetObject(RTWObject object, const char *id, RTWObject other)
{
ospSetObject(reinterpret_cast<OSPObject>(object), id, reinterpret_cast<OSPObject>(other));
}
void SetData(RTWObject object, const char *id, RTWData data)
{
ospSetData(reinterpret_cast<OSPObject>(object), id, reinterpret_cast<OSPData>(data));
}
void SetMaterial(RTWGeometry geometry, RTWMaterial material)
{
ospSetMaterial(reinterpret_cast<OSPGeometry>(geometry), reinterpret_cast<OSPMaterial>(material));
}
void Set1i(RTWObject object, const char *id, int32_t x)
{
ospSet1i(reinterpret_cast<OSPObject>(object), id, x);
}
void Set1f(RTWObject object, const char *id, float x)
{
ospSet1f(reinterpret_cast<OSPObject>(object), id, x);
}
void Set2f(RTWObject object, const char *id, float x, float y)
{
ospSet2f(reinterpret_cast<OSPObject>(object), id, x, y);
}
void Set2i(RTWObject object, const char *id, int x, int y)
{
ospSet2i(reinterpret_cast<OSPObject>(object), id, x, y);
}
void Set3i(RTWObject object, const char *id, int x, int y, int z)
{
ospSet3i(reinterpret_cast<OSPObject>(object), id, x, y, z);
}
void Set3f(RTWObject object, const char *id, float x, float y, float z)
{
ospSet3f(reinterpret_cast<OSPObject>(object), id, x, y, z);
}
void Set4f(RTWObject object, const char *id, float x, float y, float z, float w)
{
ospSet4f(reinterpret_cast<OSPObject>(object), id, x, y, z, w);
}
RTWError SetRegion(RTWVolume volume, void *source, const rtw::vec3i &regionCoords, const rtw::vec3i &regionSize)
{
return static_cast<RTWError>(ospSetRegion(reinterpret_cast<OSPVolume>(volume), source,
osp::vec3i{ regionCoords.x, regionCoords.y, regionCoords.z },
osp::vec3i{ regionSize.x, regionSize.y, regionSize.z }));
}
void Commit(RTWObject object)
{
ospCommit(reinterpret_cast<OSPObject>(object));
}
float RenderFrame(RTWFrameBuffer frameBuffer, RTWRenderer renderer, const uint32_t frameBufferChannels)
{
return ospRenderFrame(reinterpret_cast<OSPFrameBuffer>(frameBuffer), reinterpret_cast<OSPRenderer>(renderer), frameBufferChannels);
}
void FrameBufferClear(RTWFrameBuffer frameBuffer, const uint32_t frameBufferChannels)
{
ospFrameBufferClear(reinterpret_cast<OSPFrameBuffer>(frameBuffer), frameBufferChannels);
}
const void* MapFrameBuffer(RTWFrameBuffer frameBuffer, const RTWFrameBufferChannel channel)
{
return ospMapFrameBuffer(reinterpret_cast<OSPFrameBuffer>(frameBuffer), static_cast<OSPFrameBufferChannel>(channel));
}
void UnmapFrameBuffer(const void *mapped, RTWFrameBuffer frameBuffer)
{
ospUnmapFrameBuffer(mapped, reinterpret_cast<OSPFrameBuffer>(frameBuffer));
}
void SetDepthNormalizationGL(RTWFrameBuffer /*frameBuffer*/, float /*clipMin*/, float /*clipMax*/)
{
// not supported
}
int GetColorTextureGL(RTWFrameBuffer /*frameBuffer*/)
{
// not supported
return 0;
}
int GetDepthTextureGL(RTWFrameBuffer /*frameBuffer*/)
{
// not supported
return 0;
}
};
}

@ -0,0 +1,92 @@
#include "Backend.h"
#ifdef VTK_ENABLE_OSPRAY
#include "OSPRay/OSPRayBackend.h"
#endif
#ifdef VTK_ENABLE_VISRTX
#include "VisRTX/VisRTXBackend.h"
#endif
#include "RTWrapper.h"
#include <iostream>
#include <sstream>
#include <algorithm>
#include <map>
#include <cassert>
#include <cstdlib>
#include <cstring>
#include <set>
#ifdef VTK_ENABLE_VISRTX
RTW::VisRTXBackend* rtwVisRTXBackend = nullptr;
#endif
#ifdef VTK_ENABLE_OSPRAY
RTW::OSPRayBackend* rtwOSPRayBackend = nullptr;
#endif
RTW::Backend *rtwInit(int *argc, const char **argv)
{
if (!strcmp(argv[0], "optix pathtracer"))
{
#ifdef VTK_ENABLE_VISRTX
if (!rtwVisRTXBackend)
{
rtwVisRTXBackend = new RTW::VisRTXBackend();
if (rtwVisRTXBackend->Init(argc, argv) != RTW_NO_ERROR)
{
std::cerr << "WARNING: Failed to initialize RTW VisRTX backend.\n";
rtwVisRTXBackend->Shutdown();
delete rtwVisRTXBackend;
rtwVisRTXBackend = nullptr;
}
}
return rtwVisRTXBackend;
#endif
}
else
{
#ifdef VTK_ENABLE_OSPRAY
if (!rtwOSPRayBackend)
{
rtwOSPRayBackend = new RTW::OSPRayBackend();
if (rtwOSPRayBackend->Init(argc, argv) != RTW_NO_ERROR)
{
std::cerr << "WARNING: Failed to initialize RTW OSPRay backend.\n";
rtwOSPRayBackend->Shutdown();
delete rtwOSPRayBackend;
rtwOSPRayBackend = nullptr;
}
}
return rtwOSPRayBackend;
#endif
}
return nullptr;
}
std::set<RTWBackendType> rtwGetAvailableBackends()
{
std::set<RTWBackendType> result;
#ifdef VTK_ENABLE_VISRTX
{
int ac = 1;
const char* av[] = { "optix pathtracer\0" };
if (rtwInit(&ac, av) != nullptr)
result.insert(RTW_BACKEND_VISRTX);
}
#endif
#ifdef VTK_ENABLE_OSPRAY
{
int ac = 1;
const char* av[] = { "scivis\0" };
if (rtwInit(&ac, av) != nullptr)
result.insert(RTW_BACKEND_OSPRAY);
}
#endif
return result;
}

@ -0,0 +1,116 @@
#pragma once
#include "Backend.h"
#include "Types.h"
#include <set>
RTW::Backend *rtwInit(int *argc, const char **argv);
std::set<RTWBackendType> rtwGetAvailableBackends();
// TODO
// - Fix code depending on OSPRay version
// - Remove these defines
// - Version-specific code should be hidden within backend
#define OSPRAY_VERSION_MAJOR 1
#define OSPRAY_VERSION_MINOR 6
#define OSPRAY_VERSION_PATCH 1
#define OSPRAY_VERSION_GITHASH "91f9ad96af0cf28c4de56813d9f6be24fea7e42b"
#define OSPRAY_VERSION "1.6.1"
// --- Define-based mapping from OSPRay to RTWrapper ----
#define OSPObject RTWObject
#define OSPRenderer RTWRenderer
#define OSPModel RTWModel
#define OSPData RTWData
#define OSPCamera RTWCamera
#define OSPLight RTWLight
#define OSPTexture2D RTWTexture2D
#define OSPTexture RTWTexture2D
#define OSPTextureFormat RTWTextureFormat
#define OSPMaterial RTWMaterial
#define OSPGeometry RTWGeometry
#define OSPFrameBuffer RTWFrameBuffer
#define OSPVolume RTWVolume
#define OSPTransferFunction RTWTransferFunction
#define OSPDataType RTWDataType
#define OSP_FLOAT RTW_FLOAT
#define OSP_FLOAT2 RTW_FLOAT2
#define OSP_FLOAT3 RTW_FLOAT3
#define OSP_FLOAT4 RTW_FLOAT4
#define OSP_INT RTW_INT
#define OSP_INT2 RTW_INT2
#define OSP_INT3 RTW_INT3
#define OSP_INT4 RTW_INT4
#define OSP_UCHAR RTW_UCHAR
#define OSP_USHORT RTW_USHORT
#define OSP_SHORT RTW_SHORT
#define OSP_DOUBLE RTW_DOUBLE
#define OSP_OBJECT RTW_OBJECT
#define OSP_RAW RTW_RAW
#define OSP_UNKNOWN RTW_UNKNOWN
#define OSP_DATA_SHARED_BUFFER RTW_DATA_SHARED_BUFFER
#define OSP_TEXTURE_FILTER_NEAREST RTW_TEXTURE_FILTER_NEAREST
#define OSP_TEXTURE_SHARED_BUFFER RTW_TEXTURE_SHARED_BUFFER
#define OSP_TEXTURE_RGB8 RTW_TEXTURE_RGB8
#define OSP_TEXTURE_R32F RTW_TEXTURE_R32F
#define OSP_TEXTURE_RGB32F RTW_TEXTURE_RGB32F
#define OSP_TEXTURE_RGBA32F RTW_TEXTURE_RGBA32F
#define OSP_TEXTURE_R8 RTW_TEXTURE_R8
#define OSP_TEXTURE_RGB8 RTW_TEXTURE_RGB8
#define OSP_TEXTURE_RGBA8 RTW_TEXTURE_RGBA8
#define OSP_FB_RGBA8 RTW_FB_RGBA8
#define OSP_FB_COLOR RTW_FB_COLOR
#define OSP_FB_DEPTH RTW_FB_DEPTH
#define OSP_FB_ACCUM RTW_FB_ACCUM
#define ospSet1f backend->Set1f
#define ospSetf backend->Setf
#define ospSet1i backend->Set1i
#define ospSet2i backend->Set2i
#define ospSet3i backend->Set3i
#define ospSet2f backend->Set2f
#define ospSetVec2f backend->SetVec2f
#define ospSet3f backend->Set3f
#define ospSet3fv backend->Set3fv
#define ospSet4f backend->Set4f
#define ospSetString backend->SetString
#define ospSetData backend->SetData
#define ospSetObject backend->SetObject
#define ospSetMaterial backend->SetMaterial
#define ospSetRegion backend->SetRegion
#define ospCommit backend->Commit
#define ospRelease backend->Release
#define ospNewData backend->NewData
#define ospNewCamera backend->NewCamera
#define ospNewLight2 backend->NewLight2
#define ospNewLight3 backend->NewLight3
#define ospNewTexture backend->NewTexture
#define ospNewMaterial backend->NewMaterial
#define ospNewMaterial2 backend->NewMaterial2
#define ospNewTransferFunction backend->NewTransferFunction
#define ospNewVolume backend->NewVolume
#define ospNewGeometry backend->NewGeometry
#define ospNewModel backend->NewModel
#define ospNewInstance backend->NewInstance
#define ospNewFrameBuffer backend->NewFrameBuffer
#define ospNewRenderer backend->NewRenderer
#define ospFrameBufferClear backend->FrameBufferClear
#define ospRenderFrame backend->RenderFrame
#define ospMapFrameBuffer backend->MapFrameBuffer
#define ospUnmapFrameBuffer backend->UnmapFrameBuffer
#define ospAddGeometry backend->AddGeometry
#define ospAddVolume backend->AddVolume
#define ospcommon rtw
#define osp rtw

@ -0,0 +1,113 @@
#pragma once
#include <sys/types.h>
#include <stdint.h>
typedef enum : uint32_t
{
RTW_NO_ERROR = 0,
RTW_UNKNOWN_ERROR = 1,
RTW_INVALID_ARGUMENT = 2,
RTW_INVALID_OPERATION = 3,
RTW_OUT_OF_MEMORY = 4,
RTW_UNSUPPORTED_DEVICE = 5,
} RTWError;
typedef enum : uint32_t
{
RTW_FB_RGBA8,
RTW_FB_RGBA32F,
} RTWFrameBufferFormat;
typedef enum : uint32_t
{
RTW_FB_COLOR = (1 << 0),
RTW_FB_DEPTH = (1 << 1),
RTW_FB_ACCUM = (1 << 2),
} RTWFrameBufferChannel;
typedef enum : uint32_t
{
RTW_DATA_SHARED_BUFFER = (1 << 0),
} RTWDataCreationFlags;
typedef enum : uint32_t
{
RTW_TEXTURE_RGBA8,
RTW_TEXTURE_SRGBA,
RTW_TEXTURE_RGBA32F,
RTW_TEXTURE_RGB8,
RTW_TEXTURE_SRGB,
RTW_TEXTURE_RGB32F,
RTW_TEXTURE_R8,
RTW_TEXTURE_R32F,
RTW_TEXTURE_L8,
RTW_TEXTURE_RA8,
RTW_TEXTURE_LA8,
RTW_TEXTURE_FORMAT_INVALID = 0xff,
} RTWTextureFormat;
typedef enum : uint32_t
{
RTW_TEXTURE_SHARED_BUFFER = (1 << 0),
RTW_TEXTURE_FILTER_NEAREST = (1 << 1)
} RTWTextureCreationFlags;
typedef enum : uint32_t
{
RTW_OBJECT = 1000,
RTW_UCHAR = 2500, RTW_UCHAR2, RTW_UCHAR3, RTW_UCHAR4,
RTW_SHORT = 3000,
RTW_USHORT = 3500,
RTW_INT = 4000, RTW_INT2, RTW_INT3, RTW_INT4,
RTW_FLOAT = 6000, RTW_FLOAT2, RTW_FLOAT3, RTW_FLOAT4, RTW_FLOAT3A,
RTW_DOUBLE = 7000,
RTW_UNKNOWN = 22222,
RTW_RAW = 2500
} RTWDataType;
typedef enum : uint32_t
{
RTW_BACKEND_OSPRAY = 1,
RTW_BACKEND_VISRTX = 2
} RTWBackendType;
namespace rtw
{
struct vec2f { float x, y; };
struct vec2i { int x, y; };
struct vec3i { int x, y, z; };
struct vec3f { float x, y, z; };
struct vec4f { float x, y, z, w; };
struct box3i { vec3i lower, upper; };
struct linear3f { vec3f vx, vy, vz; };
struct affine3f { linear3f l; vec3f p; };
}
typedef struct RTWHandle
*RTWFrameBuffer,
*RTWRenderer,
*RTWCamera,
*RTWModel,
*RTWData,
*RTWGeometry,
*RTWMaterial,
*RTWLight,
*RTWVolume,
*RTWTransferFunction,
*RTWTexture,
*RTWObject;
typedef RTWTexture RTWTexture2D;
typedef enum : uint32_t
{
RTW_DEPTH_NORMALIZATION = 0,
RTW_OPENGL_INTEROP = 1,
RTW_ANIMATED_PARAMETERIZATION = 2,
RTW_INSTANCING = 3,
RTW_DENOISER = 4,
RTW_DEPTH_COMPOSITING = 5,
//RTW_MDL,
} RTWFeature;

@ -0,0 +1,91 @@
#pragma once
#include "../Types.h"
#include <VisRTX.h>
#include <cassert>
#include <string>
namespace RTW
{
class Camera : public Object
{
friend class Renderer;
public:
Camera(const std::string& type)
{
VisRTX::Context* rtx = VisRTX_GetContext();
if (type == "perspective")
this->camera = rtx->CreatePerspectiveCamera();
else if (type == "orthographic")
this->camera = rtx->CreateOrthographicCamera();
else
assert(false);
}
~Camera()
{
this->camera->Release();
}
void Commit() override
{
VisRTX::Vec3f pos;
if (this->Get3f({ "pos" }, &pos))
this->camera->SetPosition(pos);
VisRTX::Vec3f dir;
if (this->Get3f({ "dir" }, &dir))
this->camera->SetDirection(dir);
VisRTX::Vec3f up;
if (this->Get3f({ "up" }, &up))
this->camera->SetUp(up);
if (this->camera->GetType() == VisRTX::CameraType::PERSPECTIVE)
{
VisRTX::PerspectiveCamera* pc = dynamic_cast<VisRTX::PerspectiveCamera*>(this->camera);
float fovy;
if (this->Get1f({ "fovy" }, &fovy))
pc->SetFovY(fovy);
float aspect;
if (this->Get1f({ "aspect" }, &aspect))
pc->SetAspect(aspect);
float focalDistance;
if (this->Get1f({ "focusDistance" }, &focalDistance))
pc->SetFocalDistance(focalDistance);
float apertureRadius;
if (this->Get1f({ "apertureRadius" }, &apertureRadius))
pc->SetApertureRadius(apertureRadius);
}
else if (this->camera->GetType() == VisRTX::CameraType::ORTHOGRAPHIC)
{
VisRTX::OrthographicCamera* oc = dynamic_cast<VisRTX::OrthographicCamera*>(this->camera);
float height;
if (this->Get1f({ "height" }, &height))
oc->SetHeight(height);
float aspect;
if (this->Get1f({ "aspect" }, &aspect))
oc->SetAspect(aspect);
}
else
{
assert(false);
}
}
private:
VisRTX::Camera* camera = nullptr;
};
}

@ -0,0 +1,143 @@
#pragma once
#include "../Types.h"
#include <cstring>
namespace RTW
{
class Data : public Object
{
public:
static size_t GetElementSize(RTWDataType type)
{
switch (type)
{
case RTW_OBJECT:
return sizeof(Object*);
case RTW_UCHAR:
return 1;
case RTW_UCHAR2:
case RTW_SHORT:
case RTW_USHORT:
return 2;
case RTW_UCHAR3:
return 3;
case RTW_UCHAR4:
case RTW_INT:
case RTW_FLOAT:
return 4;
case RTW_INT2:
case RTW_FLOAT2:
case RTW_DOUBLE:
return 8;
case RTW_INT3:
case RTW_FLOAT3:
return 12;
case RTW_INT4:
case RTW_FLOAT4:
case RTW_FLOAT3A:
return 16;
default:
return 0;
}
}
public:
Data(size_t numElements, RTWDataType type, const void *source, const uint32_t dataCreationFlags = 0)
{
this->numElements = numElements;
this->type = type;
this->elementSize = GetElementSize(type);
this->shared = dataCreationFlags & RTW_DATA_SHARED_BUFFER;
if (this->shared)
{
this->data = reinterpret_cast<uint8_t*>(const_cast<void*>(source));
}
else
{
size_t size = numElements * this->elementSize;
this->data = new uint8_t[size];
memcpy(this->data, source, size);
}
// Increase references
if (type == RTW_OBJECT)
{
for (size_t i = 0; i < this->numElements; ++i)
{
Object* obj = reinterpret_cast<Object**>(this->data)[i];
if (obj)
obj->AddRef();
}
}
this->dirty = true;
}
~Data()
{
// Release references
if (type == RTW_OBJECT)
{
for (size_t i = 0; i < this->numElements; ++i)
{
Object* obj = reinterpret_cast<Object**>(this->data)[i];
if (obj)
obj->Release();
}
}
if (!this->shared)
delete[] this->data;
}
void Commit()
{
// Committing data marks it as dirty (useful for shared memory)
this->dirty = true;
}
size_t GetNumElements() const
{
return this->numElements;
}
RTWDataType GetDataType() const
{
return this->type;
}
size_t GetElementSize() const
{
return GetElementSize(this->type);
}
void* GetData() const
{
return reinterpret_cast<void*>(this->data);
}
bool IsShared() const
{
return this->shared;
}
bool CheckDirty()
{
bool d = this->dirty;
this->dirty = false;
return d;
}
private:
size_t numElements = 0;
RTWDataType type;
size_t elementSize = 0;
uint8_t* data = nullptr;
bool shared = false;
bool dirty = true;
};
}

@ -0,0 +1,80 @@
#pragma once
#include "../Types.h"
#include <VisRTX.h>
#include <cassert>
namespace RTW
{
class FrameBuffer : public Object
{
friend class Renderer;
public:
FrameBuffer(const rtw::vec2i &size, const RTWFrameBufferFormat format, const uint32_t frameBufferChannels)
{
VisRTX::Context* rtx = VisRTX_GetContext();
if (format == RTW_FB_RGBA8)
this->frameBuffer = rtx->CreateFrameBuffer(VisRTX::FrameBufferFormat::RGBA8, VisRTX::Vec2ui(size.x, size.y));
else if (format == RTW_FB_RGBA32F)
this->frameBuffer = rtx->CreateFrameBuffer(VisRTX::FrameBufferFormat::RGBA32F, VisRTX::Vec2ui(size.x, size.y));
else
assert(false);
this->format = format;
this->channels = frameBufferChannels;
}
~FrameBuffer()
{
this->frameBuffer->Release();
}
void Commit() override
{
}
void Clear(const uint32_t frameBufferChannels)
{
this->frameBuffer->Clear();
}
const void* Map(const RTWFrameBufferChannel channel)
{
if (channel == RTW_FB_COLOR)
return this->frameBuffer->MapColorBuffer();
if (channel == RTW_FB_DEPTH)
return this->frameBuffer->MapDepthBuffer();
assert(false);
return nullptr;
}
void Unmap(const void *mapped)
{
this->frameBuffer->Unmap(mapped);
}
void SetDepthNormalizationGL(float clipMin, float clipMax)
{
this->frameBuffer->SetDepthNormalization(clipMin, clipMax);
}
int GetColorTextureGL()
{
return this->frameBuffer->GetColorTextureGL();
}
int GetDepthtextureGL()
{
return this->frameBuffer->GetDepthTextureGL();
}
private:
VisRTX::FrameBuffer* frameBuffer = nullptr;
RTWFrameBufferFormat format;
uint32_t channels;
};
}

@ -0,0 +1,339 @@
#pragma once
#include "../Types.h"
#include "Material.h"
#include <VisRTX.h>
#include <cassert>
namespace RTW
{
class Geometry : public Object
{
friend class Model;
public:
Geometry(const std::string& type)
{
VisRTX::Context* rtx = VisRTX_GetContext();
if (type == "triangles" || type == "trianglemesh")
this->geometry = rtx->CreateTriangleGeometry();
else if (type == "spheres")
this->geometry = rtx->CreateSphereGeometry();
else if (type == "cylinders")
this->geometry = rtx->CreateCylinderGeometry();
else if (type == "isosurfaces")
; // not implemented
else
{
std::cerr << "Error: Unhandled geometry type \"" << type << "\"" << std::endl;
assert(false);
}
}
~Geometry()
{
this->geometry->Release();
}
void Commit() override
{
if (!this->geometry)
return;
/*
* Triangles
*/
if (this->geometry->GetType() == VisRTX::GeometryType::TRIANGLES)
{
VisRTX::TriangleGeometry* tri = dynamic_cast<VisRTX::TriangleGeometry*>(this->geometry);
Data* vertex = this->GetObject<Data>({ "position", "vertex" });
Data* index = this->GetObject<Data>({ "index" });
if (vertex && index)
{
uint32_t numTriangles = static_cast<uint32_t>(index->GetNumElements());
VisRTX::Vec3ui* triangles = reinterpret_cast<VisRTX::Vec3ui*>(index->GetData());
assert(index->GetDataType() == RTW_INT3);
uint32_t numVertices = static_cast<uint32_t>(vertex->GetNumElements());
VisRTX::Vec3f* vertices = reinterpret_cast<VisRTX::Vec3f*>(vertex->GetData());
assert(vertex->GetDataType() == RTW_FLOAT3);
VisRTX::Vec3f* normals = nullptr;
Data* normal = this->GetObject<Data>({ "vertex.normal" });
if (normal)
{
normals = reinterpret_cast<VisRTX::Vec3f*>(normal->GetData());
assert(normal->GetDataType() == RTW_FLOAT3);
}
tri->SetTriangles(numTriangles, triangles, numVertices, vertices, normals);
Data* color = this->GetObject<Data>({ "vertex.color" });
if (color)
{
VisRTX::Vec4f* colors = reinterpret_cast<VisRTX::Vec4f*>(color->GetData());
assert(color->GetDataType() == RTW_FLOAT4);
tri->SetColors(colors);
}
else
{
tri->SetColors(nullptr);
}
Data* texcoord = GetObject<Data>({ "vertex.texcoord" });
if (texcoord)
{
VisRTX::Vec2f* texcoords = reinterpret_cast<VisRTX::Vec2f*>(texcoord->GetData());
assert(texcoord->GetDataType() == RTW_FLOAT2);
tri->SetTexCoords(texcoords);
}
else
{
tri->SetTexCoords(nullptr);
}
Data* materialList = GetObject<Data>({ "materialList" });
Data* materialIndices = GetObject<Data>({ "prim.materialID" });
if (materialList && materialIndices)
{
assert(materialList->GetDataType() == RTW_OBJECT);
assert(materialIndices->GetDataType() == RTW_INT);
std::vector<VisRTX::Material*> triangleMaterials;
triangleMaterials.resize(numTriangles);
Material** materials = reinterpret_cast<Material**>(materialList->GetData());
int* indices = reinterpret_cast<int*>(materialIndices->GetData());
for (uint32_t i = 0; i < numTriangles; ++i)
{
int index = indices[i];
if (index >= 0)
{
Material* materialHandle = materials[index];
if (materialHandle)
triangleMaterials[i] = materialHandle->material;
}
}
tri->SetMaterials(triangleMaterials.data());
}
else
{
tri->SetMaterials(nullptr);
}