├── .gitattributes ├── .gitignore ├── .gitmodules ├── CMakeLists.txt ├── HostProgram ├── CMakeLists.txt ├── HostProgram.args.json ├── HostProgram.vcxproj ├── HostProgram.vcxproj.filters ├── StopWatch.h ├── c_compile_test.c ├── common.h ├── cpp_compile_test.cpp ├── dds_loader.cpp ├── dds_loader.h ├── desktop.ini ├── gl_util.cpp ├── gl_util.h ├── image.cpp ├── image.h ├── imgui.ini ├── main.cpp ├── parameter.h ├── resources │ ├── 2x2_heightmap.png │ ├── checkerboard_line.png │ ├── environments │ │ └── WhiteOne.exr │ ├── material_test │ │ ├── grid_80p_white_18p_gray.DDS │ │ ├── grid_80p_white_18p_gray.png │ │ ├── jumping_colors.png │ │ ├── paper.mtl │ │ └── paper.obj │ └── sphere │ │ ├── sphere.mtl │ │ └── sphere.obj ├── scene.cpp ├── scene.h └── shaders │ ├── drawOptiXResult.frag │ ├── drawOptiXResult.vert │ ├── scale.frag │ └── scale.vert ├── README.md ├── README_TOP.jpg ├── README_TOP.png ├── VLR.sln ├── gallery ├── CornellBox_var.jpg ├── CornellBox_var.png ├── Rungholt_view1.jpg ├── Rungholt_view1.png ├── Rungholt_view2.jpg ├── Rungholt_view2.png ├── UE4LikeBRDF.jpg ├── UE4LikeBRDF.png ├── dispersive_caustics_closeup.jpg └── dispersive_caustics_closeup.png └── libVLR ├── CMakeLists.txt ├── GPU_kernels ├── aux_buffer_generator.cu ├── cameras.cu ├── debug_rendering.cu ├── infinite_sphere.cu ├── light_tracing.cu ├── lvc_bpt.cu ├── materials.cu ├── path_tracing.cu ├── point.cu ├── post_process.cu ├── setup_scene.cu ├── shader_nodes.cu └── triangle.cu ├── common.cpp ├── context.cpp ├── context.h ├── image.cpp ├── image.h ├── include └── vlr │ ├── basic_types.h │ ├── common.h │ ├── public_types.h │ ├── vlr.h │ └── vlrcpp.h ├── libVLR.vcxproj ├── libVLR.vcxproj.filters ├── materials.cpp ├── materials.h ├── queryable.cpp ├── queryable.h ├── scene.cpp ├── scene.h ├── shader_nodes.cpp ├── shader_nodes.h ├── shared ├── basic_types_internal.h ├── common_internal.h ├── kernel_common.h ├── light_transport_common.h ├── random_distributions.h ├── renderer_common.h ├── rgb_spectrum_types.h ├── shared.h ├── spectrum_base.cpp ├── spectrum_base.h ├── spectrum_types.cpp └── spectrum_types.h ├── slot_finder.cpp ├── slot_finder.h ├── spectral_upsampling_tables ├── sRGB_D65.coeff └── sRGB_E.coeff ├── utils ├── cuda_util.cpp ├── cuda_util.h ├── optix_util.cpp ├── optix_util.h ├── optix_util_private.h └── optixu_on_cudau.h └── vlr.cpp /.gitattributes: -------------------------------------------------------------------------------- 1 | ############################################################################### 2 | # Set default behavior to automatically normalize line endings. 3 | ############################################################################### 4 | * text=auto 5 | 6 | ############################################################################### 7 | # Set default behavior for command prompt diff. 8 | # 9 | # This is need for earlier builds of msysgit that does not have it on by 10 | # default for csharp files. 11 | # Note: This is only used by command line 12 | ############################################################################### 13 | #*.cs diff=csharp 14 | 15 | ############################################################################### 16 | # Set the merge driver for project and solution files 17 | # 18 | # Merging from the command prompt will add diff markers to the files if there 19 | # are conflicts (Merging from VS is not affected by the settings below, in VS 20 | # the diff markers are never inserted). Diff markers may cause the following 21 | # file extensions to fail to load in VS. An alternative would be to treat 22 | # these files as binary and thus will always conflict and require user 23 | # intervention with every merge. To do so, just uncomment the entries below 24 | ############################################################################### 25 | #*.sln merge=binary 26 | #*.csproj merge=binary 27 | #*.vbproj merge=binary 28 | #*.vcxproj merge=binary 29 | #*.vcproj merge=binary 30 | #*.dbproj merge=binary 31 | #*.fsproj merge=binary 32 | #*.lsproj merge=binary 33 | #*.wixproj merge=binary 34 | #*.modelproj merge=binary 35 | #*.sqlproj merge=binary 36 | #*.wwaproj merge=binary 37 | 38 | ############################################################################### 39 | # behavior for image files 40 | # 41 | # image files are treated as binary by default. 42 | ############################################################################### 43 | #*.jpg binary 44 | #*.png binary 45 | #*.gif binary 46 | 47 | ############################################################################### 48 | # diff behavior for common document formats 49 | # 50 | # Convert binary document formats to text before diffing them. This feature 51 | # is only available from the command line. Turn it on by uncommenting the 52 | # entries below. 53 | ############################################################################### 54 | #*.doc diff=astextplain 55 | #*.DOC diff=astextplain 56 | #*.docx diff=astextplain 57 | #*.DOCX diff=astextplain 58 | #*.dot diff=astextplain 59 | #*.DOT diff=astextplain 60 | #*.pdf diff=astextplain 61 | #*.PDF diff=astextplain 62 | #*.rtf diff=astextplain 63 | #*.RTF diff=astextplain 64 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ## Ignore Visual Studio temporary files, build results, and 2 | ## files generated by popular Visual Studio add-ons. 3 | 4 | # User-specific files 5 | *.suo 6 | *.user 7 | *.userosscache 8 | *.sln.docstates 9 | 10 | # User-specific files (MonoDevelop/Xamarin Studio) 11 | *.userprefs 12 | 13 | # Build results 14 | [Dd]ebug/ 15 | [Dd]ebugPublic/ 16 | [Rr]elease/ 17 | [Rr]eleases/ 18 | x64/ 19 | x86/ 20 | bld/ 21 | [Bb]in/ 22 | [Oo]bj/ 23 | [Ll]og/ 24 | 25 | # Visual Studio 2015 cache/options directory 26 | .vs/ 27 | # Uncomment if you have tasks that create the project's static files in wwwroot 28 | #wwwroot/ 29 | 30 | # MSTest test Results 31 | [Tt]est[Rr]esult*/ 32 | [Bb]uild[Ll]og.* 33 | 34 | # NUNIT 35 | *.VisualState.xml 36 | TestResult.xml 37 | 38 | # Build Results of an ATL Project 39 | [Dd]ebugPS/ 40 | [Rr]eleasePS/ 41 | dlldata.c 42 | 43 | # DNX 44 | project.lock.json 45 | project.fragment.lock.json 46 | artifacts/ 47 | 48 | *_i.c 49 | *_p.c 50 | *_i.h 51 | *.ilk 52 | *.meta 53 | *.obj 54 | *.pch 55 | *.pdb 56 | *.pgc 57 | *.pgd 58 | *.rsp 59 | *.sbr 60 | *.tlb 61 | *.tli 62 | *.tlh 63 | *.tmp 64 | *.tmp_proj 65 | *.log 66 | *.vspscc 67 | *.vssscc 68 | .builds 69 | *.pidb 70 | *.svclog 71 | *.scc 72 | 73 | # Chutzpah Test files 74 | _Chutzpah* 75 | 76 | # Visual C++ cache files 77 | ipch/ 78 | *.aps 79 | *.ncb 80 | *.opendb 81 | *.opensdf 82 | *.sdf 83 | *.cachefile 84 | *.VC.db 85 | *.VC.VC.opendb 86 | 87 | # Visual Studio profiler 88 | *.psess 89 | *.vsp 90 | *.vspx 91 | *.sap 92 | 93 | # TFS 2012 Local Workspace 94 | $tf/ 95 | 96 | # Guidance Automation Toolkit 97 | *.gpState 98 | 99 | # ReSharper is a .NET coding add-in 100 | _ReSharper*/ 101 | *.[Rr]e[Ss]harper 102 | *.DotSettings.user 103 | 104 | # JustCode is a .NET coding add-in 105 | .JustCode 106 | 107 | # TeamCity is a build add-in 108 | _TeamCity* 109 | 110 | # DotCover is a Code Coverage Tool 111 | *.dotCover 112 | 113 | # NCrunch 114 | _NCrunch_* 115 | .*crunch*.local.xml 116 | nCrunchTemp_* 117 | 118 | # MightyMoose 119 | *.mm.* 120 | AutoTest.Net/ 121 | 122 | # Web workbench (sass) 123 | .sass-cache/ 124 | 125 | # Installshield output folder 126 | [Ee]xpress/ 127 | 128 | # DocProject is a documentation generator add-in 129 | DocProject/buildhelp/ 130 | DocProject/Help/*.HxT 131 | DocProject/Help/*.HxC 132 | DocProject/Help/*.hhc 133 | DocProject/Help/*.hhk 134 | DocProject/Help/*.hhp 135 | DocProject/Help/Html2 136 | DocProject/Help/html 137 | 138 | # Click-Once directory 139 | publish/ 140 | 141 | # Publish Web Output 142 | *.[Pp]ublish.xml 143 | *.azurePubxml 144 | # TODO: Comment the next line if you want to checkin your web deploy settings 145 | # but database connection strings (with potential passwords) will be unencrypted 146 | #*.pubxml 147 | *.publishproj 148 | 149 | # Microsoft Azure Web App publish settings. Comment the next line if you want to 150 | # checkin your Azure Web App publish settings, but sensitive information contained 151 | # in these scripts will be unencrypted 152 | PublishScripts/ 153 | 154 | # NuGet Packages 155 | *.nupkg 156 | # The packages folder can be ignored because of Package Restore 157 | **/packages/* 158 | # except build/, which is used as an MSBuild target. 159 | !**/packages/build/ 160 | # Uncomment if necessary however generally it will be regenerated when needed 161 | #!**/packages/repositories.config 162 | # NuGet v3's project.json files produces more ignoreable files 163 | *.nuget.props 164 | *.nuget.targets 165 | 166 | # Microsoft Azure Build Output 167 | csx/ 168 | *.build.csdef 169 | 170 | # Microsoft Azure Emulator 171 | ecf/ 172 | rcf/ 173 | 174 | # Windows Store app package directories and files 175 | AppPackages/ 176 | BundleArtifacts/ 177 | Package.StoreAssociation.xml 178 | _pkginfo.txt 179 | 180 | # Visual Studio cache files 181 | # files ending in .cache can be ignored 182 | *.[Cc]ache 183 | # but keep track of directories ending in .cache 184 | !*.[Cc]ache/ 185 | 186 | # Others 187 | ClientBin/ 188 | ~$* 189 | *~ 190 | *.dbmdl 191 | *.dbproj.schemaview 192 | *.jfm 193 | *.pfx 194 | *.publishsettings 195 | node_modules/ 196 | orleans.codegen.cs 197 | 198 | # Since there are multiple workflows, uncomment next line to ignore bower_components 199 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) 200 | #bower_components/ 201 | 202 | # RIA/Silverlight projects 203 | Generated_Code/ 204 | 205 | # Backup & report files from converting an old project file 206 | # to a newer Visual Studio version. Backup files are not needed, 207 | # because we have git ;-) 208 | _UpgradeReport_Files/ 209 | Backup*/ 210 | UpgradeLog*.XML 211 | UpgradeLog*.htm 212 | 213 | # SQL Server files 214 | *.mdf 215 | *.ldf 216 | 217 | # Business Intelligence projects 218 | *.rdl.data 219 | *.bim.layout 220 | *.bim_*.settings 221 | 222 | # Microsoft Fakes 223 | FakesAssemblies/ 224 | 225 | # GhostDoc plugin setting file 226 | *.GhostDoc.xml 227 | 228 | # Node.js Tools for Visual Studio 229 | .ntvs_analysis.dat 230 | 231 | # Visual Studio 6 build log 232 | *.plg 233 | 234 | # Visual Studio 6 workspace options file 235 | *.opt 236 | 237 | # Visual Studio LightSwitch build output 238 | **/*.HTMLClient/GeneratedArtifacts 239 | **/*.DesktopClient/GeneratedArtifacts 240 | **/*.DesktopClient/ModelManifest.xml 241 | **/*.Server/GeneratedArtifacts 242 | **/*.Server/ModelManifest.xml 243 | _Pvt_Extensions 244 | 245 | # Paket dependency manager 246 | .paket/paket.exe 247 | paket-files/ 248 | 249 | # FAKE - F# Make 250 | .fake/ 251 | 252 | # JetBrains Rider 253 | .idea/ 254 | *.sln.iml 255 | 256 | # CodeRush 257 | .cr/ 258 | 259 | # Python Tools for Visual Studio (PTVS) 260 | __pycache__/ 261 | *.pyc -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "ext/gl3w"] 2 | path = ext/gl3w 3 | url = https://github.com/skaslev/gl3w.git 4 | [submodule "ext/imgui"] 5 | path = ext/imgui 6 | url = https://github.com/ocornut/imgui.git 7 | [submodule "ext/glfw"] 8 | path = ext/glfw 9 | url = https://github.com/glfw/glfw.git 10 | [submodule "ext/tinyexr"] 11 | path = ext/tinyexr 12 | url = https://github.com/syoyo/tinyexr.git 13 | [submodule "ext/assimp"] 14 | path = ext/assimp 15 | url = https://github.com/assimp/assimp.git 16 | [submodule "ext/half"] 17 | path = ext/half 18 | url = https://github.com/melowntech/half.git 19 | [submodule "ext/stb"] 20 | path = ext/stb 21 | url = https://github.com/nothings/stb.git 22 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # Current CMakeLists has been tested only on Windows/MSVC. 2 | # Manual copying executables and other files are required for other platforms. 3 | 4 | cmake_minimum_required(VERSION 3.26) 5 | project( 6 | VLR_cmake 7 | VERSION 1.0 8 | DESCRIPTION "GPU Monte Carlo Ray Tracing Renderer" 9 | LANGUAGES C CXX CUDA) 10 | 11 | set_property(GLOBAL PROPERTY USE_FOLDERS ON) 12 | 13 | set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin") 14 | set(CMAKE_RUNTIME_LIBRARY_DIRECTORY "${CMAKE_BINARY_DIR}/bin") 15 | 16 | set( 17 | CMAKE_MODULE_PATH 18 | "${CMAKE_SOURCE_DIR}/cmake" 19 | ${CMAKE_MODULE_PATH}) 20 | find_package(CUDAToolkit 12.5 REQUIRED) 21 | find_package(OptiX80) 22 | include("copy_files") 23 | include("nvcuda_compile_ptx") 24 | 25 | if (OptiX80_FOUND) 26 | set(OPTIX_INCLUDE_DIR "${OPTIX80_INCLUDE_DIR}") 27 | else() 28 | message(FATAL_ERROR "OptiX SDK 8.0 not found.") 29 | endif() 30 | 31 | 32 | 33 | # ---------------------------------------------------------------- 34 | # JP: CMakeLists.txtのあるサブディレクトリ内のターゲット全てにフォルダーを設定する。 35 | # https://stackoverflow.com/questions/45092198/cmake-how-do-i-change-properties-on-subdirectory-project-targets 36 | 37 | # _dir以下の(CMakeが有効な)サブディレクトリにあるターゲットを再帰的に取得する。 38 | function(get_all_targets _result _dir) 39 | get_property(_subdirs DIRECTORY "${_dir}" PROPERTY SUBDIRECTORIES) 40 | foreach(_subdir IN LISTS _subdirs) 41 | get_all_targets(${_result} "${_subdir}") 42 | endforeach() 43 | get_property(_sub_targets DIRECTORY "${_dir}" PROPERTY BUILDSYSTEM_TARGETS) 44 | set(${_result} ${${_result}} ${_sub_targets} PARENT_SCOPE) 45 | endfunction() 46 | 47 | # _dir以下の(CMakeが有効な)サブディレクトリにあるターゲットにフォルダーを設定する。 48 | function(set_project_group _folder_name _dir) 49 | get_all_targets(_targets "${_dir}") 50 | foreach(_target IN LISTS _targets) 51 | # message(${_target}) 52 | set_target_properties( 53 | ${_target} 54 | PROPERTIES FOLDER "${_folder_name}" 55 | ) 56 | endforeach() 57 | endfunction() 58 | 59 | # END: JP: CMakeLists.txtのあるサブディレクトリ内のターゲット全てにフォルダーを設定する。 60 | # ---------------------------------------------------------------- 61 | 62 | 63 | 64 | # gl3w 65 | add_subdirectory(ext/gl3w) 66 | set_project_group("External" "ext/gl3w") 67 | 68 | # GLFW 69 | option(GLFW_BUILD_EXAMPLES "Build the GLFW example programs" OFF) 70 | option(GLFW_BUILD_TESTS "Build the GLFW test programs" OFF) 71 | option(GLFW_BUILD_DOCS "Build the GLFW documentation" OFF) 72 | option(GLFW_INSTALL "Generate installation target" OFF) 73 | add_subdirectory(ext/glfw) 74 | set_project_group("External" "ext/GLFW") 75 | 76 | # Assimp 77 | option(ASSIMP_BUILD_ASSIMP_TOOLS "If the supplementary tools for Assimp are built in addition to the library." OFF) 78 | option(ASSIMP_BUILD_SAMPLES "If the official samples are built as well (needs Glut)." OFF) 79 | option(ASSIMP_BUILD_TESTS "If the test suite for Assimp is built in addition to the library." OFF) 80 | option(ASSIMP_INSTALL "Disable this if you want to use assimp as a submodule." OFF) 81 | if(MSVC) 82 | option(ASSIMP_BUILD_ASSIMP_VIEW "If the Assimp view tool is built. (requires DirectX)" OFF) 83 | endif() 84 | add_subdirectory(ext/assimp) 85 | set_project_group("External" "ext/assimp") 86 | 87 | 88 | 89 | add_subdirectory(libVLR) 90 | add_subdirectory(HostProgram) 91 | -------------------------------------------------------------------------------- /HostProgram/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | set(TARGET_NAME "HostProgram") 2 | 3 | file( 4 | GLOB_RECURSE SOURCES 5 | *.h *.hpp *.c *.cpp) 6 | file( 7 | GLOB_RECURSE SHADERS 8 | *.vert *.frag) 9 | 10 | source_group( 11 | "" REGULAR_EXPRESSION 12 | "${CMAKE_CURRENT_SOURCE_DIR}/[^/]*\.(h|hpp|c|cpp)$") 13 | source_group( 14 | "shaders" REGULAR_EXPRESSION 15 | "${CMAKE_CURRENT_SOURCE_DIR}/shaders/[^/]*\.(vert|frag)$") 16 | 17 | file( 18 | GLOB_RECURSE EXT_SOURCES 19 | "../ext/glfw/include/*" 20 | "../ext/imgui/*" 21 | "../ext/tinyexr/*" 22 | "../ext/stb/stb_image.h" 23 | "../ext/stb/stb_image_write.h" 24 | ) 25 | list( 26 | FILTER EXT_SOURCES INCLUDE REGEX 27 | ".*\.(h|hpp|cuh|c|cc|cpp|cu|vert|frag)$") 28 | list( 29 | FILTER EXT_SOURCES EXCLUDE REGEX 30 | "../ext/prebuilt/.*") 31 | list( 32 | FILTER EXT_SOURCES EXCLUDE REGEX 33 | "../ext/imgui/imgui_demo\.cpp$") 34 | list( 35 | FILTER EXT_SOURCES EXCLUDE REGEX 36 | "../ext/imgui/(backends|misc|examples)/.*") 37 | list( 38 | FILTER EXT_SOURCES EXCLUDE REGEX 39 | "../ext/tinyexr/deps/miniz/examples/.*") 40 | list( 41 | FILTER EXT_SOURCES EXCLUDE REGEX 42 | "../ext/tinyexr/deps/ZFP/.*") 43 | list( 44 | FILTER EXT_SOURCES EXCLUDE REGEX 45 | "../ext/tinyexr/(examples|experimental|test)/.*") 46 | list( 47 | FILTER EXT_SOURCES EXCLUDE REGEX 48 | "../ext/tinyexr/test_tinyexr.cc$") 49 | file( 50 | GLOB IMGUI_BACKEND_SOURCES 51 | "../ext/imgui/backends/imgui_impl_glfw*" 52 | "../ext/imgui/backends/imgui_impl_opengl3*" 53 | ) 54 | set( 55 | EXT_SOURCES 56 | ${EXT_SOURCES} 57 | ${IMGUI_BACKEND_SOURCES} 58 | ) 59 | 60 | source_group( 61 | "ext/gl3w" REGULAR_EXPRESSION 62 | "../ext/gl3w/.*$") 63 | source_group( 64 | "ext/glfw" REGULAR_EXPRESSION 65 | "../ext/glfw/.*\.h$") 66 | source_group( 67 | "ext/imgui/core" REGULAR_EXPRESSION 68 | "../ext/imgui/[^/]*\.(h|cpp)$") 69 | source_group( 70 | "ext/imgui" REGULAR_EXPRESSION 71 | "../ext/imgui/backends/.*\.(h|cpp)$") 72 | source_group( 73 | "ext/tinyexr" REGULAR_EXPRESSION 74 | "../ext/tinyexr/[^/]*\.(h|hpp|c|cpp)$") 75 | source_group( 76 | "ext/tinyexr/miniz" REGULAR_EXPRESSION 77 | "../ext/tinyexr/deps/miniz/[^/]*\.(h|hpp|c|cpp)$") 78 | source_group( 79 | "ext/tinyexr/nanozlib" REGULAR_EXPRESSION 80 | "../ext/tinyexr/deps/nanozlib/[^/]*\.(h|hpp|c|cpp)$") 81 | source_group( 82 | "ext/stb" REGULAR_EXPRESSION 83 | "../ext/stb/[^/]*\.(h|hpp|c|cpp)$") 84 | source_group( 85 | "ext" REGULAR_EXPRESSION 86 | "../ext/[^/]*\.(h|hpp|c|cc|cpp)$") 87 | 88 | 89 | 90 | copy_files( 91 | SOURCES ${SHADERS} 92 | TARGET_PATH "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${CMAKE_CFG_INTDIR}/${TARGET_NAME}/shaders" 93 | GENERATED_FILES COPIED_SHADERS 94 | ) 95 | 96 | 97 | 98 | add_executable( 99 | "${TARGET_NAME}" 100 | ${EXT_SOURCES} 101 | ${SOURCES} 102 | ${SHADERS} 103 | ) 104 | target_compile_features("${TARGET_NAME}" PRIVATE cxx_std_20) 105 | set_target_properties("${TARGET_NAME}" PROPERTIES CXX_EXTENSIONS OFF) 106 | target_compile_definitions( 107 | "${TARGET_NAME}" PRIVATE 108 | "$<$:_DEBUG=1>" 109 | ) 110 | target_compile_options( 111 | "${TARGET_NAME}" PRIVATE 112 | # if (compilerID == MSVC && compilerLanguage != CUDA) set(/MP); 113 | "$<$,$>>:/MP>" 114 | "$<$,$>>:/MP>" 115 | # if (compilerID == MSVC && compilerLanguage != CUDA) set(/Zc:__cplusplus); 116 | "$<$,$>>:/Zc:__cplusplus>" 117 | ) 118 | target_include_directories( 119 | "${TARGET_NAME}" PRIVATE 120 | "../ext/tinyexr" 121 | "../ext/tinyexr/deps/miniz" 122 | "../ext/glfw/include" 123 | "../ext/imgui" 124 | "../ext/assimp/include" 125 | "../ext/stb" 126 | "${CMAKE_BINARY_DIR}/ext/assimp/include" 127 | "${CMAKE_BINARY_DIR}/ext/gl3w/include" 128 | "${CMAKE_SOURCE_DIR}/libVLR/include" 129 | ) 130 | target_link_libraries( 131 | "${TARGET_NAME}" 132 | CUDA::cuda_driver 133 | opengl32 134 | gl3w 135 | glfw 136 | assimp::assimp 137 | libvlr 138 | ) 139 | -------------------------------------------------------------------------------- /HostProgram/HostProgram.args.json: -------------------------------------------------------------------------------- 1 | { 2 | "FileVersion": 2, 3 | "Id": "6430930f-4932-457f-ac9c-aed74facc5c7", 4 | "Items": [ 5 | { 6 | "Id": "ef680aae-1129-4f34-9da3-9621b4c4274b", 7 | "Command": "--nodisplay" 8 | }, 9 | { 10 | "Id": "0594cc28-c876-4c2b-81f9-eca8aaaedcb4", 11 | "Command": "--list" 12 | }, 13 | { 14 | "Id": "5099f6ab-3338-4428-b1d1-5c3752cb46b0", 15 | "Command": "--disableRTX" 16 | }, 17 | { 18 | "Id": "02bd491c-9d1e-4857-960f-1401190fc5f0", 19 | "Command": "--stacksize 4096" 20 | }, 21 | { 22 | "Id": "8ebe06c6-cad8-4178-a939-eade53b301d0", 23 | "Command": "--stacksize 3072" 24 | }, 25 | { 26 | "Id": "655fa978-c650-49aa-9eca-1623800adb13", 27 | "Command": "--stacksize 2560" 28 | }, 29 | { 30 | "Id": "a99c0bd0-4300-45b5-b15c-8cfddf6c2e3e", 31 | "Command": "--maxcallabledepth 8" 32 | }, 33 | { 34 | "Id": "d388d70f-0e7c-4182-b62b-714ef2401f4a", 35 | "Command": "--maxcallabledepth 5" 36 | }, 37 | { 38 | "Id": "7608790c-38ee-4ab4-9c61-f35c81248674", 39 | "Command": "--logging" 40 | } 41 | ] 42 | } -------------------------------------------------------------------------------- /HostProgram/HostProgram.vcxproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | x64 7 | 8 | 9 | Release 10 | x64 11 | 12 | 13 | 14 | 15.0 15 | {6430930F-4932-457F-AC9C-AED74FACC5C7} 16 | HostProgram 17 | 10.0 18 | 19 | 20 | 21 | Application 22 | true 23 | MultiByte 24 | v143 25 | 26 | 27 | Application 28 | false 29 | true 30 | MultiByte 31 | v143 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | $(ExecutablePath) 48 | C:\Users\shocker_0x15\repos\VLR\ext\half;C:\Users\shocker_0x15\repos\VLR\ext\stb;C:\Users\shocker_0x15\repos\VLR\ext\prebuilt\include;C:\Users\shocker_0x15\repos\VLR\ext\imgui;C:\Users\shocker_0x15\repos\VLR\ext\glfw\include;C:\Users\shocker_0x15\repos\VLR\ext\tinyexr\deps\miniz;C:\Users\shocker_0x15\repos\VLR\ext\tinyexr;$(SolutionDir)libVLR\include;$(VC_IncludePath);$(WindowsSDK_IncludePath) 49 | C:\Users\shocker_0x15\repos\VLR\ext\prebuilt\lib;$(LibraryPath) 50 | 51 | 52 | $(ExecutablePath) 53 | C:\Users\shocker_0x15\repos\VLR\ext\half;C:\Users\shocker_0x15\repos\VLR\ext\stb;C:\Users\shocker_0x15\repos\VLR\ext\prebuilt\include;C:\Users\shocker_0x15\repos\VLR\ext\imgui;C:\Users\shocker_0x15\repos\VLR\ext\glfw\include;C:\Users\shocker_0x15\repos\VLR\ext\tinyexr\deps\miniz;C:\Users\shocker_0x15\repos\VLR\ext\tinyexr;$(SolutionDir)libVLR\include;$(VC_IncludePath);$(WindowsSDK_IncludePath) 54 | C:\Users\shocker_0x15\repos\VLR\ext\prebuilt\lib;$(LibraryPath) 55 | 56 | 57 | 58 | Level3 59 | Disabled 60 | true 61 | true 62 | C:\Users\shocker_0x15\Applications\vdb-win;$(ProjectDir)ext\include;$(ProjectDir)ext\include\imGui;%(AdditionalIncludeDirectories) 63 | DEBUG;IMATH_DLL;_CRT_SECURE_NO_WARNINGS;_MBCS;%(PreprocessorDefinitions) 64 | true 65 | stdcpp20 66 | 67 | 68 | cuda.lib;cudart_static.lib;$(OutDir)libvlr.lib;opengl32.lib;zlibstaticd.lib;assimp-vc143-mtd.lib;glfw3d.lib;%(AdditionalDependencies) 69 | msvcrt.lib 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | Level3 79 | MaxSpeed 80 | true 81 | true 82 | true 83 | true 84 | C:\Users\shocker_0x15\Applications\vdb-win;$(ProjectDir)ext\include;$(ProjectDir)ext\include\imGui;%(AdditionalIncludeDirectories) 85 | true 86 | IMATH_DLL;_CRT_SECURE_NO_WARNINGS;_MBCS;%(PreprocessorDefinitions) 87 | stdcpp20 88 | 89 | 90 | true 91 | true 92 | cuda.lib;cudart_static.lib;$(OutDir)libvlr.lib;opengl32.lib;zlibstatic.lib;assimp-vc143-mt.lib;glfw3.lib;%(AdditionalDependencies) 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | Document 149 | $(OutDir)HostProgram\shaders 150 | $(OutDir)HostProgram\shaders 151 | 152 | 153 | Document 154 | $(OutDir)HostProgram\shaders 155 | $(OutDir)HostProgram\shaders 156 | 157 | 158 | Document 159 | $(OutDir)HostProgram\shaders 160 | $(OutDir)HostProgram\shaders 161 | 162 | 163 | Document 164 | $(OutDir)HostProgram\shaders 165 | $(OutDir)HostProgram\shaders 166 | 167 | 168 | 169 | 170 | 171 | 172 | -------------------------------------------------------------------------------- /HostProgram/HostProgram.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | helpers 10 | 11 | 12 | helpers 13 | 14 | 15 | helpers 16 | 17 | 18 | ext\imgui\core 19 | 20 | 21 | ext\imgui\core 22 | 23 | 24 | ext\imgui\core 25 | 26 | 27 | ext\imgui\core 28 | 29 | 30 | ext\imgui 31 | 32 | 33 | ext\imgui 34 | 35 | 36 | ext\gl3w 37 | 38 | 39 | ext\tinyexr 40 | 41 | 42 | ext\tinyexr\miniz 43 | 44 | 45 | ext\tinyexr\nanozlib 46 | 47 | 48 | helpers 49 | 50 | 51 | 52 | 53 | {b1ba1065-1607-4b70-8c86-9c1535ae2b93} 54 | 55 | 56 | {079c8b79-02fc-414e-b18d-35ee05d2185f} 57 | 58 | 59 | {1dea447f-c586-4af4-9fcc-07446eaf5302} 60 | 61 | 62 | {6497c07d-c3f7-4fb5-93de-b585feebf71b} 63 | 64 | 65 | {43e601ba-e170-4f1d-a2f8-bf59df727ea2} 66 | 67 | 68 | {31dd1e9f-aa48-4946-be58-14b0af22f884} 69 | 70 | 71 | {af65f80e-df32-4b70-b046-f63a5ac93235} 72 | 73 | 74 | {1f9ebec8-34bb-4d1c-92d1-07450937107e} 75 | 76 | 77 | {6cf3b058-ea32-4e6e-8fdf-96bfbbe9abaf} 78 | 79 | 80 | {2c013ec0-e674-4ab5-a3f3-ecbbd1f11323} 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | helpers 90 | 91 | 92 | helpers 93 | 94 | 95 | helpers 96 | 97 | 98 | ext\imgui\core 99 | 100 | 101 | ext\imgui\core 102 | 103 | 104 | ext\imgui\core 105 | 106 | 107 | ext\imgui\core 108 | 109 | 110 | ext\imgui\core 111 | 112 | 113 | ext\imgui\core 114 | 115 | 116 | ext\imgui 117 | 118 | 119 | ext\imgui 120 | 121 | 122 | ext\imgui 123 | 124 | 125 | ext\glfw 126 | 127 | 128 | ext\glfw 129 | 130 | 131 | ext\gl3w 132 | 133 | 134 | ext\gl3w 135 | 136 | 137 | ext\gl3w 138 | 139 | 140 | ext\tinyexr 141 | 142 | 143 | ext\tinyexr\miniz 144 | 145 | 146 | ext\tinyexr\nanozlib 147 | 148 | 149 | helpers 150 | 151 | 152 | 153 | 154 | shaders 155 | 156 | 157 | shaders 158 | 159 | 160 | shaders 161 | 162 | 163 | shaders 164 | 165 | 166 | -------------------------------------------------------------------------------- /HostProgram/StopWatch.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | using namespace std::chrono; 8 | 9 | template 10 | class StopWatchTemplate { 11 | std::vector m_startTPStack; 12 | public: 13 | typedef enum { 14 | Nanoseconds, 15 | Microseconds, 16 | Milliseconds, 17 | Seconds, 18 | } EDurationType; 19 | 20 | typename res::time_point start() { 21 | typename res::time_point startTimePoint = res::now(); 22 | m_startTPStack.push_back(startTimePoint); 23 | return startTimePoint; 24 | } 25 | 26 | inline uint64_t durationCast(const typename res::duration &duration, EDurationType dt) const { 27 | switch (dt) { 28 | case Nanoseconds: 29 | return duration_cast(duration).count(); 30 | case Microseconds: 31 | return duration_cast(duration).count(); 32 | case Milliseconds: 33 | return duration_cast(duration).count(); 34 | case Seconds: 35 | return duration_cast(duration).count(); 36 | default: 37 | break; 38 | } 39 | return UINT64_MAX; 40 | } 41 | 42 | uint64_t stop(EDurationType dt = EDurationType::Milliseconds) { 43 | typename res::duration duration = res::now() - m_startTPStack.back(); 44 | m_startTPStack.pop_back(); 45 | return durationCast(duration, dt); 46 | } 47 | 48 | uint64_t elapsed(EDurationType dt = EDurationType::Milliseconds) { 49 | typename res::duration duration = res::now() - m_startTPStack.back(); 50 | return durationCast(duration, dt); 51 | } 52 | 53 | uint64_t elapsedFromRoot(EDurationType dt = EDurationType::Milliseconds) { 54 | typename res::duration duration = res::now() - m_startTPStack.front(); 55 | return durationCast(duration, dt); 56 | } 57 | }; 58 | 59 | typedef StopWatchTemplate StopWatch; 60 | typedef StopWatchTemplate StopWatchHiRes; 61 | -------------------------------------------------------------------------------- /HostProgram/c_compile_test.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | #include 7 | 8 | // Just for compile test for C language. 9 | 10 | static void C_CompileTest() { 11 | #define CHECK(call) \ 12 | do { \ 13 | VLRResult res = call; \ 14 | assert(res == VLRResult_NoError); \ 15 | } while (0) 16 | 17 | CUcontext cuContext; 18 | int32_t cuDeviceCount; 19 | cuInit(0); 20 | cuDeviceGetCount(&cuDeviceCount); 21 | cuCtxCreate(&cuContext, 0, 0); 22 | cuCtxSetCurrent(cuContext); 23 | 24 | VLRContext context; 25 | CHECK(vlrCreateContext( 26 | cuContext, true, 8, &context)); 27 | 28 | VLRLinearImage2D imageA; 29 | CHECK(vlrLinearImage2DCreate( 30 | context, 31 | NULL, 128, 128, "RGBA8x4", "Reflectance", "Rec709(D65) sRGB Gamma", 32 | &imageA)); 33 | 34 | uint32_t width; 35 | CHECK(vlrImage2DGetWidth(imageA, &width)); 36 | 37 | VLRShaderNode imageNode; 38 | CHECK(vlrShaderNodeCreate(context, "Image2DTexture", &imageNode)); 39 | CHECK(vlrQueryableSetImage2D(imageNode, "image", imageA)); 40 | 41 | VLRSurfaceMaterial ue4Mat; 42 | CHECK(vlrSurfaceMaterialCreate(context, "UE4", &ue4Mat)); 43 | 44 | VLRShaderNodePlug plugImageNodeSpectrum; 45 | CHECK(vlrShaderNodeGetPlug(imageNode, VLRShaderNodePlugType_Spectrum, 0, &plugImageNodeSpectrum)); 46 | CHECK(vlrQueryableSetShaderNodePlug(ue4Mat, "base color", plugImageNodeSpectrum)); 47 | } 48 | -------------------------------------------------------------------------------- /HostProgram/common.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | // Platform defines 4 | #if defined(_WIN32) || defined(_WIN64) 5 | # define HP_Platform_Windows 6 | # if defined(_MSC_VER) 7 | # define HP_Platform_Windows_MSVC 8 | # endif 9 | #elif defined(__APPLE__) 10 | # define HP_Platform_macOS 11 | #endif 12 | 13 | #if defined(HP_Platform_Windows_MSVC) 14 | # define NOMINMAX 15 | # define _USE_MATH_DEFINES 16 | # if defined(VLR_API_EXPORTS) 17 | # define VLR_API __declspec(dllexport) 18 | # else 19 | # define VLR_API __declspec(dllimport) 20 | # endif 21 | # include 22 | # undef near 23 | # undef far 24 | # undef RGB 25 | #else 26 | # define VLR_API 27 | #endif 28 | 29 | #include 30 | #include 31 | #include 32 | #include 33 | #include 34 | #include 35 | #include 36 | #include 37 | #include 38 | #include 39 | #include 40 | #include 41 | 42 | 43 | 44 | #ifdef DEBUG 45 | # define ENABLE_ASSERT 46 | #endif 47 | 48 | #ifdef HP_Platform_Windows_MSVC 49 | static void devPrintf(const char* fmt, ...) { 50 | va_list args; 51 | va_start(args, fmt); 52 | char str[1024]; 53 | vsprintf_s(str, fmt, args); 54 | va_end(args); 55 | OutputDebugString(str); 56 | } 57 | #else 58 | # define devPrintf(fmt, ...) printf(fmt, ##__VA_ARGS__); 59 | #endif 60 | 61 | #if 1 62 | # define hpprintf(fmt, ...) do { devPrintf(fmt, ##__VA_ARGS__); printf(fmt, ##__VA_ARGS__); } while (0) 63 | #else 64 | # define hpprintf(fmt, ...) printf(fmt, ##__VA_ARGS__) 65 | #endif 66 | 67 | #ifdef ENABLE_ASSERT 68 | # define Assert(expr, fmt, ...) if (!(expr)) { devPrintf("%s @%s: %u:\n", #expr, __FILE__, __LINE__); devPrintf(fmt"\n", ##__VA_ARGS__); abort(); } 0 69 | #else 70 | # define Assert(expr, fmt, ...) 71 | #endif 72 | 73 | #define Assert_ShouldNotBeCalled() Assert(false, "Should not be called!") 74 | #define Assert_NotImplemented() Assert(false, "Not implemented yet!") 75 | 76 | template 77 | constexpr size_t lengthof(const T(&array)[size]) { 78 | return size; 79 | } 80 | -------------------------------------------------------------------------------- /HostProgram/cpp_compile_test.cpp: -------------------------------------------------------------------------------- 1 | #include "common.h" 2 | #include 3 | 4 | // Just for compile test for C++ language. 5 | 6 | #define CUDADRV_CHECK(call) \ 7 | do { \ 8 | CUresult error = call; \ 9 | if (error != CUDA_SUCCESS) { \ 10 | const char* errMsg = "failed to get an error message."; \ 11 | cuGetErrorString(error, &errMsg); \ 12 | fprintf(stderr, "CUDA call (" ## #call ## " ) failed with error: %s (%s:%u)\n", \ 13 | errMsg, __FILE__, __LINE__); \ 14 | exit(-1); \ 15 | } \ 16 | } while (0) 17 | 18 | static vlr::Image2DRef loadImage2D(const vlr::ContextRef& context, const std::string& filepath, const std::string& spectrumType, const std::string& colorSpace) { 19 | return nullptr; 20 | } 21 | 22 | static void Cpp_CompileTest() { 23 | bool enableLogging = true; 24 | int32_t renderTargetSizeX = 512; 25 | int32_t renderTargetSizeY = 512; 26 | bool firstFrame = true; 27 | uint32_t numAccumFrames; 28 | 29 | using namespace vlr; 30 | 31 | CUcontext cuContext; 32 | int32_t cuDeviceCount; 33 | CUstream cuStream; 34 | CUDADRV_CHECK(cuInit(0)); 35 | CUDADRV_CHECK(cuDeviceGetCount(&cuDeviceCount)); 36 | CUDADRV_CHECK(cuCtxCreate(&cuContext, 0, 0)); 37 | CUDADRV_CHECK(cuCtxSetCurrent(cuContext)); 38 | CUDADRV_CHECK(cuStreamCreate(&cuStream, 0)); 39 | 40 | ContextRef context = Context::create(cuContext, enableLogging); 41 | 42 | // Construct a scene by defining meshes and materials. 43 | 44 | SceneRef scene = context->createScene(); 45 | 46 | TriangleMeshSurfaceNodeRef mesh = context->createTriangleMeshSurfaceNode("My Mesh 1"); 47 | { 48 | Vertex vertices[] = { 49 | Vertex{ Point3D(-1.5f, 0.0f, -1.5f), Normal3D(0, 1, 0), Vector3D(1, 0, 0), TexCoord2D(0.0f, 5.0f) }, 50 | // ... 51 | }; 52 | // ... 53 | mesh->setVertices(vertices, lengthof(vertices)); 54 | 55 | { 56 | Image2DRef imgAlbedo = loadImage2D(context, "checkerboard.png", "Reflectance", "Rec709(D65) sRGB Gamma"); 57 | Image2DRef imgNormalAlpha = loadImage2D(context, "normal_alpha.png", "NA", "Rec709(D65)"); 58 | 59 | ShaderNodeRef nodeAlbedo = context->createShaderNode("Image2DTexture"); 60 | nodeAlbedo->set("image", imgAlbedo); 61 | nodeAlbedo->set("min filter", "Nearest"); 62 | nodeAlbedo->set("mag filter", "Nearest"); 63 | 64 | ShaderNodeRef nodeNormalAlpha = context->createShaderNode("Image2DTexture"); 65 | nodeNormalAlpha->set("image", imgNormalAlpha); 66 | 67 | // You can flexibly define a material by connecting shader nodes. 68 | SurfaceMaterialRef mat = context->createSurfaceMaterial("Matte"); 69 | mat->set("albedo", nodeAlbedo->getPlug(VLRShaderNodePlugType_Spectrum, 0)); 70 | 71 | ShaderNodeRef nodeTangent = context->createShaderNode("Tangent"); 72 | nodeTangent->set("tangent type", "Radial Y"); 73 | 74 | uint32_t matGroup[] = { 0, 1, 2, 0, 2, 3 }; 75 | mesh->addMaterialGroup(matGroup, lengthof(matGroup), mat, 76 | nodeNormalAlpha->getPlug(VLRShaderNodePlugType_Normal3D, 0), // normal map 77 | nodeTangent->getPlug(VLRShaderNodePlugType_Vector3D, 0), // tangent 78 | nodeNormalAlpha->getPlug(VLRShaderNodePlugType_Alpha, 0)); // alpha map 79 | } 80 | 81 | // ... 82 | } 83 | 84 | // You can construct a scene graph with transforms 85 | InternalNodeRef transformNode = context->createInternalNode("trf A"); 86 | transformNode->setTransform(context->createStaticTransform(scale(2.0f))); 87 | transformNode->addChild(mesh); 88 | scene->addChild(transformNode); 89 | 90 | // Setup a camera 91 | CameraRef camera = context->createCamera("Perspective"); 92 | camera->set("position", Point3D(0, 1.5f, 6.0f)); 93 | camera->set("aspect", static_cast(renderTargetSizeX) / renderTargetSizeY); 94 | camera->set("sensitivity", 1.0f); 95 | camera->set("fovy", 40 * M_PI / 180); 96 | camera->set("lens radius", 0.0f); 97 | 98 | // Setup the output buffer (OpenGL buffer can also be attached) 99 | context->bindOutputBuffer(1024, 1024, 0); 100 | 101 | // Let's render the scene! 102 | context->setScene(scene); 103 | context->render(cuStream, camera, true, 1, firstFrame, 0, &numAccumFrames); 104 | } 105 | -------------------------------------------------------------------------------- /HostProgram/dds_loader.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Copyright 2024 Shin Watanabe 4 | 5 | Licensed under the Apache License, Version 2.0 (the "License"); 6 | you may not use this file except in compliance with the License. 7 | You may obtain a copy of the License at 8 | 9 | http://www.apache.org/licenses/LICENSE-2.0 10 | 11 | Unless required by applicable law or agreed to in writing, software 12 | distributed under the License is distributed on an "AS IS" BASIS, 13 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | See the License for the specific language governing permissions and 15 | limitations under the License. 16 | 17 | */ 18 | 19 | // Platform defines 20 | #if defined(_WIN32) || defined(_WIN64) 21 | # define Platform_Windows 22 | # if defined(_MSC_VER) 23 | # define Platform_Windows_MSVC 24 | # endif // if defined(_MSC_VER) 25 | #elif defined(__APPLE__) 26 | # define Platform_macOS 27 | #endif // if defined(_WIN32) || defined(_WIN64) 28 | 29 | #if defined(Platform_Windows_MSVC) 30 | # define NOMINMAX 31 | # define _USE_MATH_DEFINES 32 | # include 33 | # undef near 34 | # undef far 35 | # undef RGB 36 | #endif // if defined(Platform_Windows_MSVC) 37 | 38 | #include "dds_loader.h" 39 | 40 | #include 41 | #include 42 | #include 43 | 44 | #if defined(_DEBUG) 45 | # define ENABLE_ASSERT 1 46 | # define DEBUG_SELECT(A, B) A 47 | #else // if defined(_DEBUG) 48 | # define ENABLE_ASSERT 0 49 | # define DEBUG_SELECT(A, B) B 50 | #endif // if defined(_DEBUG) 51 | 52 | #if defined(Platform_Windows_MSVC) 53 | static void devPrintf(const char* fmt, ...) { 54 | va_list args; 55 | va_start(args, fmt); 56 | const int32_t reqStrSize = _vscprintf(fmt, args) + 1; 57 | va_end(args); 58 | 59 | static std::vector str; 60 | if (reqStrSize > str.size()) 61 | str.resize(reqStrSize); 62 | 63 | va_start(args, fmt); 64 | vsnprintf_s(str.data(), str.size(), _TRUNCATE, fmt, args); 65 | va_end(args); 66 | 67 | OutputDebugStringA(str.data()); 68 | } 69 | #else // if defined(Platform_Windows_MSVC) 70 | # define devPrintf(fmt, ...) printf(fmt, ##__VA_ARGS__); 71 | #endif // if defined(Platform_Windows_MSVC) 72 | 73 | #if 1 74 | # define hpprintf(fmt, ...) do { devPrintf(fmt, ##__VA_ARGS__); printf(fmt, ##__VA_ARGS__); } while (0) 75 | #else 76 | # define hpprintf(fmt, ...) printf(fmt, ##__VA_ARGS__) 77 | #endif 78 | 79 | #if ENABLE_ASSERT 80 | # define Assert(expr, fmt, ...) if (!(expr)) { devPrintf("%s @%s: %u:\n", #expr, __FILE__, __LINE__); devPrintf(fmt"\n", ##__VA_ARGS__); abort(); } 0 81 | #else // if ENABLE_ASSERT 82 | # define Assert(expr, fmt, ...) 83 | #endif // if ENABLE_ASSERT 84 | 85 | #define Assert_ShouldNotBeCalled() Assert(false, "Should not be called!") 86 | #define Assert_NotImplemented() Assert(false, "Not implemented yet!") 87 | 88 | template 89 | constexpr size_t lengthof(const T(&array)[size]) { 90 | return size; 91 | } 92 | 93 | namespace dds { 94 | struct Header { 95 | struct Flags { 96 | enum Value : uint32_t { 97 | Caps = 1 << 0, 98 | Height = 1 << 1, 99 | Width = 1 << 2, 100 | Pitch = 1 << 3, 101 | PixelFormat = 1 << 12, 102 | MipMapCount = 1 << 17, 103 | LinearSize = 1 << 19, 104 | Depth = 1 << 23 105 | } value; 106 | 107 | Flags() : value((Value)0) {} 108 | Flags(Value v) : value(v) {} 109 | 110 | Flags operator&(Flags v) const { 111 | return (Value)(value & v.value); 112 | } 113 | Flags operator|(Flags v) const { 114 | return (Value)(value | v.value); 115 | } 116 | bool operator==(uint32_t v) const { 117 | return value == v; 118 | } 119 | bool operator!=(uint32_t v) const { 120 | return value != v; 121 | } 122 | }; 123 | 124 | struct PFFlags { 125 | enum Value : uint32_t { 126 | AlphaPixels = 1 << 0, 127 | Alpha = 1 << 1, 128 | FourCC = 1 << 2, 129 | PaletteIndexed4 = 1 << 3, 130 | PaletteIndexed8 = 1 << 5, 131 | RGB = 1 << 6, 132 | Luminance = 1 << 17, 133 | BumpDUDV = 1 << 19, 134 | } value; 135 | 136 | PFFlags() : value((Value)0) {} 137 | PFFlags(Value v) : value(v) {} 138 | 139 | PFFlags operator&(PFFlags v) const { 140 | return (Value)(value & v.value); 141 | } 142 | PFFlags operator|(PFFlags v) const { 143 | return (Value)(value | v.value); 144 | } 145 | bool operator==(uint32_t v) const { 146 | return value == v; 147 | } 148 | bool operator!=(uint32_t v) const { 149 | return value != v; 150 | } 151 | }; 152 | 153 | struct Caps { 154 | enum Value : uint32_t { 155 | Alpha = 1 << 1, 156 | Complex = 1 << 3, 157 | Texture = 1 << 12, 158 | MipMap = 1 << 22, 159 | } value; 160 | 161 | Caps() : value((Value)0) {} 162 | Caps(Value v) : value(v) {} 163 | 164 | Caps operator&(Caps v) const { 165 | return (Value)(value & v.value); 166 | } 167 | Caps operator|(Caps v) const { 168 | return (Value)(value | v.value); 169 | } 170 | bool operator==(uint32_t v) const { 171 | return value == v; 172 | } 173 | bool operator!=(uint32_t v) const { 174 | return value != v; 175 | } 176 | }; 177 | 178 | struct Caps2 { 179 | enum Value : uint32_t { 180 | CubeMap = 1 << 9, 181 | CubeMapPositiveX = 1 << 10, 182 | CubeMapNegativeX = 1 << 11, 183 | CubeMapPositiveY = 1 << 12, 184 | CubeMapNegativeY = 1 << 13, 185 | CubeMapPositiveZ = 1 << 14, 186 | CubeMapNegativeZ = 1 << 15, 187 | Volume = 1 << 22, 188 | } value; 189 | 190 | Caps2() : value((Value)0) {} 191 | Caps2(Value v) : value(v) {} 192 | 193 | Caps2 operator&(Caps2 v) const { 194 | return (Value)(value & v.value); 195 | } 196 | Caps2 operator|(Caps2 v) const { 197 | return (Value)(value | v.value); 198 | } 199 | bool operator==(uint32_t v) const { 200 | return value == v; 201 | } 202 | bool operator!=(uint32_t v) const { 203 | return value != v; 204 | } 205 | }; 206 | 207 | uint32_t m_magic; 208 | uint32_t m_size; 209 | Flags m_flags; 210 | uint32_t m_height; 211 | uint32_t m_width; 212 | uint32_t m_pitchOrLinearSize; 213 | uint32_t m_depth; 214 | uint32_t m_mipmapCount; 215 | uint32_t m_reserved1[11]; 216 | uint32_t m_PFSize; 217 | PFFlags m_PFFlags; 218 | uint32_t m_fourCC; 219 | uint32_t m_RGBBitCount; 220 | uint32_t m_RBitMask; 221 | uint32_t m_GBitMask; 222 | uint32_t m_BBitMask; 223 | uint32_t m_RGBAlphaBitMask; 224 | Caps m_caps; 225 | Caps2 m_caps2; 226 | uint32_t m_reservedCaps[2]; 227 | uint32_t m_reserved2; 228 | }; 229 | static_assert(sizeof(Header) == 128, "sizeof(Header) must be 128."); 230 | 231 | struct HeaderDX10 { 232 | Format m_format; 233 | uint32_t m_dimension; 234 | uint32_t m_miscFlag; 235 | uint32_t m_arraySize; 236 | uint32_t m_miscFlag2; 237 | }; 238 | static_assert(sizeof(HeaderDX10) == 20, "sizeof(HeaderDX10) must be 20."); 239 | 240 | 241 | 242 | uint8_t** load(const char* filepath, int32_t* width, int32_t* height, int32_t* mipCount, size_t** sizes, Format* format) { 243 | std::ifstream ifs(filepath, std::ios::in | std::ios::binary); 244 | if (!ifs.is_open()) { 245 | hpprintf("Not found: %s\n", filepath); 246 | return nullptr; 247 | } 248 | 249 | ifs.seekg(0, std::ios::end); 250 | size_t fileSize = ifs.tellg(); 251 | 252 | ifs.clear(); 253 | ifs.seekg(0, std::ios::beg); 254 | 255 | Header header; 256 | ifs.read((char*)&header, sizeof(Header)); 257 | if (header.m_magic != 0x20534444) { 258 | hpprintf("Non dds (dx10) file: %s", filepath); 259 | return nullptr; 260 | } 261 | *width = header.m_width; 262 | *height = header.m_height; 263 | 264 | size_t headerSize = sizeof(Header); 265 | if (header.m_fourCC == 0x30315844) { 266 | HeaderDX10 dx10Header; 267 | ifs.read((char*)&dx10Header, sizeof(HeaderDX10)); 268 | *format = static_cast(dx10Header.m_format); 269 | headerSize += sizeof(HeaderDX10); 270 | } 271 | else { 272 | const auto makeFourCC = [](uint32_t B0, uint32_t B1, uint32_t B2, uint32_t B3) { 273 | return ((B0 << 0) | (B1 << 8) | (B2 << 16) | (B3 << 24)); 274 | }; 275 | if (header.m_fourCC == makeFourCC('D', 'X', 'T', '1')) 276 | *format = Format::BC1_UNorm; 277 | else if (header.m_fourCC == makeFourCC('D', 'X', 'T', '3')) 278 | *format = Format::BC2_UNorm; 279 | else if (header.m_fourCC == makeFourCC('D', 'X', 'T', '5')) 280 | *format = Format::BC3_UNorm; 281 | else if (header.m_fourCC == makeFourCC('B', 'C', '4', 'U')) 282 | *format = Format::BC4_UNorm; 283 | else if (header.m_fourCC == makeFourCC('B', 'C', '4', 'S')) 284 | *format = Format::BC4_SNorm; 285 | else if (header.m_fourCC == makeFourCC('B', 'C', '5', 'U') || 286 | header.m_fourCC == makeFourCC('A', 'T', 'I', '2')) 287 | *format = Format::BC5_UNorm; 288 | else if (header.m_fourCC == makeFourCC('B', 'C', '5', 'S')) 289 | *format = Format::BC5_SNorm; 290 | else 291 | Assert_NotImplemented(); 292 | } 293 | 294 | if (*format != Format::BC1_UNorm && *format != Format::BC1_UNorm_sRGB && 295 | *format != Format::BC2_UNorm && *format != Format::BC2_UNorm_sRGB && 296 | *format != Format::BC3_UNorm && *format != Format::BC3_UNorm_sRGB && 297 | *format != Format::BC4_UNorm && *format != Format::BC4_SNorm && 298 | *format != Format::BC5_UNorm && *format != Format::BC5_SNorm && 299 | *format != Format::BC6H_UF16 && *format != Format::BC6H_SF16 && 300 | *format != Format::BC7_UNorm && *format != Format::BC7_UNorm_sRGB) { 301 | hpprintf("No support for non block compressed formats: %s", filepath); 302 | return nullptr; 303 | } 304 | 305 | const size_t dataSize = fileSize - headerSize; 306 | 307 | *mipCount = 1; 308 | if ((header.m_flags & Header::Flags::MipMapCount) != 0) 309 | *mipCount = header.m_mipmapCount; 310 | 311 | uint8_t* singleData = new uint8_t[dataSize]; 312 | ifs.read((char*)singleData, dataSize); 313 | 314 | uint8_t** data = new uint8_t*[*mipCount]; 315 | *sizes = new size_t[*mipCount]; 316 | int32_t mipWidth = *width; 317 | int32_t mipHeight = *height; 318 | uint32_t blockSize = 16; 319 | if (*format == Format::BC1_UNorm || *format == Format::BC1_UNorm_sRGB || 320 | *format == Format::BC4_UNorm || *format == Format::BC4_SNorm) 321 | blockSize = 8; 322 | size_t accDataSize = 0; 323 | for (int i = 0; i < *mipCount; ++i) { 324 | int32_t bw = (mipWidth + 3) / 4; 325 | int32_t bh = (mipHeight + 3) / 4; 326 | size_t mipDataSize = bw * bh * blockSize; 327 | 328 | data[i] = singleData + accDataSize; 329 | (*sizes)[i] = mipDataSize; 330 | accDataSize += mipDataSize; 331 | 332 | mipWidth = std::max(1, mipWidth / 2); 333 | mipHeight = std::max(1, mipHeight / 2); 334 | } 335 | Assert(accDataSize == dataSize, "Data size mismatch."); 336 | 337 | return data; 338 | } 339 | 340 | void free(uint8_t** data, size_t* sizes) { 341 | void* singleData = data[0]; 342 | delete[] sizes; 343 | delete[] data; 344 | delete singleData; 345 | } 346 | } 347 | -------------------------------------------------------------------------------- /HostProgram/dds_loader.h: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Copyright 2024 Shin Watanabe 4 | 5 | Licensed under the Apache License, Version 2.0 (the "License"); 6 | you may not use this file except in compliance with the License. 7 | You may obtain a copy of the License at 8 | 9 | http://www.apache.org/licenses/LICENSE-2.0 10 | 11 | Unless required by applicable law or agreed to in writing, software 12 | distributed under the License is distributed on an "AS IS" BASIS, 13 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | See the License for the specific language governing permissions and 15 | limitations under the License. 16 | 17 | */ 18 | 19 | #pragma once 20 | 21 | #include 22 | 23 | // For DDS image read (block compressed format) 24 | namespace dds { 25 | enum class Format : uint32_t { 26 | BC1_UNorm = 71, 27 | BC1_UNorm_sRGB = 72, 28 | BC2_UNorm = 74, 29 | BC2_UNorm_sRGB = 75, 30 | BC3_UNorm = 77, 31 | BC3_UNorm_sRGB = 78, 32 | BC4_UNorm = 80, 33 | BC4_SNorm = 81, 34 | BC5_UNorm = 83, 35 | BC5_SNorm = 84, 36 | BC6H_UF16 = 95, 37 | BC6H_SF16 = 96, 38 | BC7_UNorm = 98, 39 | BC7_UNorm_sRGB = 99, 40 | }; 41 | 42 | [[nodiscard]] 43 | uint8_t** load(const char* filepath, int32_t* width, int32_t* height, int32_t* mipCount, size_t** sizes, Format* format); 44 | void free(uint8_t** data, size_t* sizes); 45 | } 46 | -------------------------------------------------------------------------------- /HostProgram/desktop.ini: -------------------------------------------------------------------------------- 1 | [ViewState] 2 | Mode= 3 | Vid= 4 | FolderType=Generic 5 | -------------------------------------------------------------------------------- /HostProgram/gl_util.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shocker-0x15/VLR/8dad615a0f82c8599c6c59998278ab90b0c56f70/HostProgram/gl_util.cpp -------------------------------------------------------------------------------- /HostProgram/image.cpp: -------------------------------------------------------------------------------- 1 | #include "image.h" 2 | 3 | #include 4 | 5 | #define STB_IMAGE_IMPLEMENTATION 6 | #include "stb_image.h" 7 | 8 | #define STB_IMAGE_WRITE_IMPLEMENTATION 9 | #define STBI_MSC_SECURE_CRT 10 | #include "stb_image_write.h" 11 | 12 | #include "dds_loader.h" 13 | #include "tinyexr.h" 14 | 15 | #include "half/half.hpp" 16 | 17 | 18 | 19 | static std::map, vlr::Image2DRef> s_image2DCache; 20 | 21 | // TODO: Should colorSpace be determined from the read image? 22 | vlr::Image2DRef loadImage2D(const vlr::ContextRef &context, const std::string &filepath, const std::string &spectrumType, const std::string &colorSpace) { 23 | using namespace vlr; 24 | 25 | Image2DRef ret; 26 | 27 | const auto tolower = [](std::string str) { 28 | const auto tolower = [](unsigned char c) { return std::tolower(c); }; 29 | std::transform(str.cbegin(), str.cend(), str.begin(), tolower); 30 | return str; 31 | }; 32 | 33 | auto key = std::make_tuple(filepath, tolower(spectrumType), tolower(colorSpace)); 34 | if (s_image2DCache.count(key)) 35 | return s_image2DCache.at(key); 36 | 37 | hpprintf("Read image: %s...", filepath.c_str()); 38 | 39 | bool fileExists = false; 40 | { 41 | std::ifstream ifs(filepath); 42 | fileExists = ifs.is_open(); 43 | } 44 | if (!fileExists) { 45 | hpprintf("Not found.\n"); 46 | return ret; 47 | } 48 | 49 | std::string ext = filepath.substr(filepath.find_last_of('.') + 1); 50 | std::transform(ext.begin(), ext.end(), ext.begin(), [](unsigned char c) { return std::tolower(c); }); 51 | 52 | //#define OVERRIDE_BY_DDS 53 | 54 | #if defined(OVERRIDE_BY_DDS) 55 | std::string ddsFilepath = filepath; 56 | ddsFilepath = filepath.substr(0, filepath.find_last_of('.')); 57 | ddsFilepath += ".dds"; 58 | { 59 | std::ifstream ifs(ddsFilepath); 60 | if (ifs.is_open()) 61 | ext = "dds"; 62 | } 63 | #endif 64 | 65 | if (ext == "exr") { 66 | int32_t width, height; 67 | float* fp32Data; 68 | const char* errMsg = nullptr; 69 | int exrRet; 70 | EXRVersion exrVersion; 71 | exrRet = ParseEXRVersionFromFile(&exrVersion, filepath.c_str()); 72 | VLRAssert(exrRet == TINYEXR_SUCCESS, "failed to parse the exr version."); 73 | EXRHeader exrHeader; 74 | exrRet = ParseEXRHeaderFromFile(&exrHeader, &exrVersion, filepath.c_str(), &errMsg); 75 | VLRAssert(exrRet == TINYEXR_SUCCESS, "failed to parse the exr header."); 76 | exrRet = LoadEXR(&fp32Data, &width, &height, filepath.c_str(), &errMsg); 77 | VLRAssert(exrRet == TINYEXR_SUCCESS, "failed to read the exr."); // TODO: error handling. 78 | 79 | std::vector fp16Data(width * height * 4); 80 | for (uint32_t y = 0; y < height; ++y) { 81 | for (uint32_t x = 0; x < width; ++x) { 82 | uint32_t idx = y * width + x; 83 | fp16Data[4 * idx + 0] = static_cast(fp32Data[4 * idx + 0]); 84 | fp16Data[4 * idx + 1] = static_cast(fp32Data[4 * idx + 1]); 85 | fp16Data[4 * idx + 2] = static_cast(fp32Data[4 * idx + 2]); 86 | fp16Data[4 * idx + 3] = static_cast(fp32Data[4 * idx + 3]); 87 | } 88 | } 89 | free(fp32Data); 90 | 91 | ret = context->createLinearImage2D( 92 | reinterpret_cast(fp16Data.data()), width, height, "RGBA16Fx4", 93 | spectrumType.c_str(), colorSpace.c_str()); 94 | } 95 | else if (ext == "dds") { 96 | int32_t width, height, mipCount; 97 | size_t* sizes; 98 | dds::Format format; 99 | #if defined(OVERRIDE_BY_DDS) 100 | uint8_t** data = dds::load(ddsFilepath.c_str(), &width, &height, &mipCount, &sizes, &format); 101 | #else 102 | uint8_t** data = dds::load(filepath.c_str(), &width, &height, &mipCount, &sizes, &format); 103 | #endif 104 | 105 | const auto translate = [](dds::Format ddsFormat, const char** vlrFormat, bool* needsDegamma) { 106 | *needsDegamma = false; 107 | switch (ddsFormat) { 108 | case dds::Format::BC1_UNorm: 109 | *vlrFormat = "BC1"; 110 | break; 111 | case dds::Format::BC1_UNorm_sRGB: 112 | *vlrFormat = "BC1"; 113 | *needsDegamma = true; 114 | break; 115 | case dds::Format::BC2_UNorm: 116 | *vlrFormat = "BC2"; 117 | break; 118 | case dds::Format::BC2_UNorm_sRGB: 119 | *vlrFormat = "BC2"; 120 | *needsDegamma = true; 121 | break; 122 | case dds::Format::BC3_UNorm: 123 | *vlrFormat = "BC3"; 124 | break; 125 | case dds::Format::BC3_UNorm_sRGB: 126 | *vlrFormat = "BC3"; 127 | *needsDegamma = true; 128 | break; 129 | case dds::Format::BC4_UNorm: 130 | *vlrFormat = "BC4"; 131 | break; 132 | case dds::Format::BC4_SNorm: 133 | *vlrFormat = "BC4_Signed"; 134 | break; 135 | case dds::Format::BC5_UNorm: 136 | *vlrFormat = "BC5"; 137 | break; 138 | case dds::Format::BC5_SNorm: 139 | *vlrFormat = "BC5_Signed"; 140 | break; 141 | case dds::Format::BC6H_UF16: 142 | *vlrFormat = "BC6H"; 143 | break; 144 | case dds::Format::BC6H_SF16: 145 | *vlrFormat = "BC6H_Signed"; 146 | break; 147 | case dds::Format::BC7_UNorm: 148 | *vlrFormat = "BC7"; 149 | break; 150 | case dds::Format::BC7_UNorm_sRGB: 151 | *vlrFormat = "BC7"; 152 | *needsDegamma = true; 153 | break; 154 | default: 155 | break; 156 | } 157 | }; 158 | 159 | const char* vlrFormat; 160 | bool needsDegamma; 161 | translate(format, &vlrFormat, &needsDegamma); 162 | 163 | ret = context->createBlockCompressedImage2D( 164 | data, sizes, mipCount, width, height, vlrFormat, 165 | spectrumType.c_str(), colorSpace.c_str()); 166 | Assert(ret, "failed to load a block compressed texture."); 167 | 168 | dds::free(data, sizes); 169 | } 170 | else { 171 | int32_t width, height, n; 172 | uint8_t* linearImageData = stbi_load(filepath.c_str(), &width, &height, &n, 0); 173 | if (n == 4) 174 | ret = context->createLinearImage2D(linearImageData, width, height, "RGBA8x4", spectrumType.c_str(), colorSpace.c_str()); 175 | else if (n == 3) 176 | ret = context->createLinearImage2D(linearImageData, width, height, "RGB8x3", spectrumType.c_str(), colorSpace.c_str()); 177 | else if (n == 2) 178 | ret = context->createLinearImage2D(linearImageData, width, height, "GrayA8x2", spectrumType.c_str(), colorSpace.c_str()); 179 | else if (n == 1) 180 | ret = context->createLinearImage2D(linearImageData, width, height, "Gray8", spectrumType.c_str(), colorSpace.c_str()); 181 | else 182 | Assert_ShouldNotBeCalled(); 183 | stbi_image_free(linearImageData); 184 | } 185 | 186 | hpprintf("done.\n"); 187 | 188 | s_image2DCache[key] = ret; 189 | 190 | return ret; 191 | } 192 | 193 | void writePNG(const std::filesystem::path &filePath, uint32_t width, uint32_t height, const uint32_t* data) { 194 | stbi_write_png(filePath.string().c_str(), width, height, 4, data, width * 4); 195 | } 196 | 197 | void writeEXR(const std::filesystem::path &filePath, uint32_t width, uint32_t height, const float* data) { 198 | EXRHeader header; 199 | InitEXRHeader(&header); 200 | 201 | EXRImage image; 202 | InitEXRImage(&image); 203 | 204 | image.num_channels = 4; 205 | 206 | std::vector images[4]; 207 | images[0].resize(width * height); 208 | images[1].resize(width * height); 209 | images[2].resize(width * height); 210 | images[3].resize(width * height); 211 | 212 | bool flipY = false; 213 | float brightnessScale = 1.0f; 214 | for (uint32_t y = 0; y < height; ++y) { 215 | for (uint32_t x = 0; x < width; ++x) { 216 | uint32_t srcIdx = 4 * (y * width + x); 217 | uint32_t dstIdx = (flipY ? (height - 1 - y) : y) * width + x; 218 | images[0][dstIdx] = brightnessScale * data[srcIdx + 0]; 219 | images[1][dstIdx] = brightnessScale * data[srcIdx + 1]; 220 | images[2][dstIdx] = brightnessScale * data[srcIdx + 2]; 221 | images[3][dstIdx] = brightnessScale * data[srcIdx + 3]; 222 | } 223 | } 224 | 225 | float* image_ptr[4]; 226 | image_ptr[0] = &(images[3].at(0)); // A 227 | image_ptr[1] = &(images[2].at(0)); // B 228 | image_ptr[2] = &(images[1].at(0)); // G 229 | image_ptr[3] = &(images[0].at(0)); // R 230 | 231 | image.images = (unsigned char**)image_ptr; 232 | image.width = width; 233 | image.height = height; 234 | 235 | header.num_channels = 4; 236 | header.channels = (EXRChannelInfo *)malloc(sizeof(EXRChannelInfo) * header.num_channels); 237 | // Must be (A)BGR order, since most of EXR viewers expect this channel order. 238 | strncpy(header.channels[0].name, "A", 255); header.channels[0].name[strlen("A")] = '\0'; 239 | strncpy(header.channels[1].name, "B", 255); header.channels[1].name[strlen("B")] = '\0'; 240 | strncpy(header.channels[2].name, "G", 255); header.channels[2].name[strlen("G")] = '\0'; 241 | strncpy(header.channels[3].name, "R", 255); header.channels[3].name[strlen("R")] = '\0'; 242 | 243 | header.pixel_types = (int32_t*)malloc(sizeof(int32_t) * header.num_channels); 244 | header.requested_pixel_types = (int32_t*)malloc(sizeof(int32_t) * header.num_channels); 245 | for (int i = 0; i < header.num_channels; i++) { 246 | header.pixel_types[i] = TINYEXR_PIXELTYPE_FLOAT; // pixel type of input image 247 | header.requested_pixel_types[i] = TINYEXR_PIXELTYPE_HALF; // pixel type of output image to be stored in .EXR 248 | } 249 | 250 | const char* err = nullptr; 251 | int32_t ret = SaveEXRImageToFile(&image, &header, filePath.string().c_str(), &err); 252 | if (ret != TINYEXR_SUCCESS) { 253 | fprintf(stderr, "Save EXR err: %s\n", err); 254 | FreeEXRErrorMessage(err); 255 | } 256 | 257 | free(header.channels); 258 | free(header.pixel_types); 259 | free(header.requested_pixel_types); 260 | } 261 | -------------------------------------------------------------------------------- /HostProgram/image.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "common.h" 4 | #include 5 | 6 | vlr::Image2DRef loadImage2D(const vlr::ContextRef &context, const std::string &filepath, const std::string &spectrumType, const std::string &colorSpace); 7 | 8 | void writePNG(const std::filesystem::path &filePath, uint32_t width, uint32_t height, const uint32_t* data); 9 | void writeEXR(const std::filesystem::path &filePath, uint32_t width, uint32_t height, const float* data); 10 | -------------------------------------------------------------------------------- /HostProgram/imgui.ini: -------------------------------------------------------------------------------- 1 | [Window][Debug##Default] 2 | Pos=60,60 3 | Size=400,400 4 | Collapsed=0 5 | 6 | [Window][Misc] 7 | Pos=17,390 8 | Size=305,100 9 | Collapsed=0 10 | 11 | [Window][Camera] 12 | Pos=17,13 13 | Size=326,364 14 | Collapsed=0 15 | 16 | [Window][Scene] 17 | Pos=1534,11 18 | Size=367,205 19 | Collapsed=0 20 | 21 | -------------------------------------------------------------------------------- /HostProgram/parameter.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "common.h" 4 | 5 | #define NOMINMAX 6 | #include "imgui.h" 7 | 8 | #include 9 | 10 | class Parameter { 11 | protected: 12 | VLRCpp::QueryableRef m_parent; 13 | VLRCpp::ParameterInfo m_info; 14 | 15 | public: 16 | Parameter(const VLRCpp::QueryableRef parent, const VLRCpp::ParameterInfo &info) : 17 | m_parent(parent), m_info(info) {} 18 | virtual ~Parameter() {} 19 | 20 | virtual void draw() const = 0; 21 | }; 22 | 23 | class FloatTupleParameter : public Parameter { 24 | float* m_values; 25 | uint32_t m_tupleSize; 26 | 27 | public: 28 | FloatTupleParameter(const VLRCpp::QueryableRef parent, const VLRCpp::ParameterInfo& info) : 29 | Parameter(parent, info) { 30 | m_tupleSize = m_info.getTupleSize(); 31 | Assert(m_tupleSize > 0, "Tuple size must be greater than 0."); 32 | m_values = new float[m_tupleSize]; 33 | 34 | parent->get(m_info.getName(), m_values, m_tupleSize); 35 | } 36 | ~FloatTupleParameter() { 37 | delete m_values; 38 | } 39 | 40 | void draw() const override { 41 | if (m_tupleSize == 1) { 42 | ImGui::InputFloat(m_info.getName(), &m_values[0]); 43 | } 44 | else { 45 | const char* param = m_info.getName(); 46 | ImGui::LabelText("%s", param); 47 | ImGui::PushID(param); 48 | for (int i = 0; i < m_info.getTupleSize(); ++i) { 49 | ImGui::InputFloat("", &m_values[i]); 50 | } 51 | ImGui::PopID(); 52 | } 53 | } 54 | }; 55 | 56 | 57 | 58 | class ShaderNode { 59 | VLRCpp::ShaderNodeRef m_shaderNode; 60 | uint32_t m_numParams; 61 | 62 | public: 63 | ShaderNode(const VLRCpp::ShaderNodeRef& shaderNode) : m_shaderNode(shaderNode) { 64 | m_numParams = m_shaderNode->getNumParameters(); 65 | for (int i = 0; i < m_numParams; ++i) { 66 | 67 | } 68 | } 69 | ~ShaderNode() { 70 | 71 | } 72 | 73 | void draw() const { 74 | 75 | } 76 | }; 77 | -------------------------------------------------------------------------------- /HostProgram/resources/2x2_heightmap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shocker-0x15/VLR/8dad615a0f82c8599c6c59998278ab90b0c56f70/HostProgram/resources/2x2_heightmap.png -------------------------------------------------------------------------------- /HostProgram/resources/checkerboard_line.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shocker-0x15/VLR/8dad615a0f82c8599c6c59998278ab90b0c56f70/HostProgram/resources/checkerboard_line.png -------------------------------------------------------------------------------- /HostProgram/resources/environments/WhiteOne.exr: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shocker-0x15/VLR/8dad615a0f82c8599c6c59998278ab90b0c56f70/HostProgram/resources/environments/WhiteOne.exr -------------------------------------------------------------------------------- /HostProgram/resources/material_test/grid_80p_white_18p_gray.DDS: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shocker-0x15/VLR/8dad615a0f82c8599c6c59998278ab90b0c56f70/HostProgram/resources/material_test/grid_80p_white_18p_gray.DDS -------------------------------------------------------------------------------- /HostProgram/resources/material_test/grid_80p_white_18p_gray.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shocker-0x15/VLR/8dad615a0f82c8599c6c59998278ab90b0c56f70/HostProgram/resources/material_test/grid_80p_white_18p_gray.png -------------------------------------------------------------------------------- /HostProgram/resources/material_test/jumping_colors.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shocker-0x15/VLR/8dad615a0f82c8599c6c59998278ab90b0c56f70/HostProgram/resources/material_test/jumping_colors.png -------------------------------------------------------------------------------- /HostProgram/resources/material_test/paper.mtl: -------------------------------------------------------------------------------- 1 | # Blender MTL File: 'material_test_scene.blend' 2 | # Material Count: 1 3 | 4 | newmtl Material.002 5 | Ns 96.078431 6 | Ka 1.000000 1.000000 1.000000 7 | Kd 0.640000 0.640000 0.640000 8 | Ks 0.500000 0.500000 0.500000 9 | Ke 0.000000 0.000000 0.000000 10 | Ni 1.000000 11 | d 1.000000 12 | illum 2 13 | -------------------------------------------------------------------------------- /HostProgram/resources/sphere/sphere.mtl: -------------------------------------------------------------------------------- 1 | # Blender MTL File: 'None' 2 | # Material Count: 1 3 | 4 | newmtl None 5 | Ns 0 6 | Ka 0.000000 0.000000 0.000000 7 | Kd 0.8 0.8 0.8 8 | Ks 0.8 0.8 0.8 9 | d 1 10 | illum 2 11 | -------------------------------------------------------------------------------- /HostProgram/scene.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "common.h" 4 | 5 | #include 6 | 7 | #include "image.h" 8 | 9 | #include 10 | #include 11 | #include 12 | 13 | struct SurfaceMaterialAttributeTuple { 14 | vlr::SurfaceMaterialRef material; 15 | vlr::ShaderNodePlug nodeNormal; 16 | vlr::ShaderNodePlug nodeTangent; 17 | vlr::ShaderNodePlug nodeAlpha; 18 | 19 | SurfaceMaterialAttributeTuple(const vlr::SurfaceMaterialRef &_material, 20 | const vlr::ShaderNodePlug &_nodeNormal, 21 | const vlr::ShaderNodePlug &_nodeTangent, 22 | const vlr::ShaderNodePlug &_nodeAlpha) : 23 | material(_material), nodeNormal(_nodeNormal), nodeTangent(_nodeTangent), nodeAlpha(_nodeAlpha) {} 24 | }; 25 | 26 | struct MeshAttributeTuple { 27 | bool visible; 28 | 29 | MeshAttributeTuple(bool _visible) : visible(_visible) {} 30 | }; 31 | 32 | typedef SurfaceMaterialAttributeTuple(*CreateMaterialFunction)(const vlr::ContextRef &context, const aiMaterial* aiMat, const std::string &); 33 | typedef MeshAttributeTuple(*PerMeshFunction)(const aiMesh* mesh); 34 | 35 | SurfaceMaterialAttributeTuple createMaterialDefaultFunction(const vlr::ContextRef &context, const aiMaterial* aiMat, const std::string &pathPrefix); 36 | 37 | MeshAttributeTuple perMeshDefaultFunction(const aiMesh* mesh); 38 | 39 | static void construct(const vlr::ContextRef &context, const std::string &filePath, bool flipWinding, bool flipV, vlr::InternalNodeRef* nodeOut, 40 | CreateMaterialFunction matFunc = createMaterialDefaultFunction, PerMeshFunction meshFunc = perMeshDefaultFunction); 41 | 42 | 43 | 44 | struct Shot { 45 | vlr::SceneRef scene; 46 | 47 | uint32_t renderTargetSizeX; 48 | uint32_t renderTargetSizeY; 49 | 50 | float brightnessCoeff; 51 | float environmentRotation; 52 | 53 | std::vector viewpoints; 54 | }; 55 | 56 | void createScene(const vlr::ContextRef &context, Shot* shot); 57 | -------------------------------------------------------------------------------- /HostProgram/shaders/drawOptiXResult.frag: -------------------------------------------------------------------------------- 1 | #version 400 2 | #extension GL_ARB_explicit_uniform_location : enable // required in version lower 4.3 3 | #extension GL_ARB_shading_language_420pack : enable // required in version lower 4.2 4 | 5 | layout(location = 0) uniform int srcFullWidth; 6 | layout(location = 1) uniform float shrinkCoeff; 7 | layout(location = 2) uniform float brightness; 8 | layout(location = 3) uniform int enableDebugRendering; 9 | layout(location = 4, binding = 0) uniform sampler2D srcTexture; 10 | 11 | layout(origin_upper_left) in vec4 gl_FragCoord; 12 | 13 | out vec4 color; 14 | 15 | vec3 sRGB_gamma(vec3 v) { 16 | vec3 ret; 17 | ret.r = v.r < 0.0031308 ? (12.92 * v.r) : (1.055 * pow(v.r, 1 / 2.4) - 0.055); 18 | ret.g = v.g < 0.0031308 ? (12.92 * v.g) : (1.055 * pow(v.g, 1 / 2.4) - 0.055); 19 | ret.b = v.b < 0.0031308 ? (12.92 * v.b) : (1.055 * pow(v.b, 1 / 2.4) - 0.055); 20 | return ret; 21 | } 22 | 23 | void main(void) { 24 | vec2 srcPixel = gl_FragCoord.xy / shrinkCoeff; 25 | vec4 opResult = texelFetch(srcTexture, ivec2(srcPixel), 0); 26 | opResult.rgb = max(opResult.rgb, 0.0f); 27 | if (bool(enableDebugRendering)) { 28 | opResult.rgb = min(opResult.rgb, 1.0f); 29 | } 30 | else { 31 | opResult.rgb *= brightness; 32 | opResult.rgb = 1 - exp(-opResult.rgb); 33 | // opResult.rgb = sRGB_gamma(opResult.rgb); 34 | } 35 | color = opResult; 36 | } -------------------------------------------------------------------------------- /HostProgram/shaders/drawOptiXResult.vert: -------------------------------------------------------------------------------- 1 | #version 400 2 | 3 | void main(void) { 4 | // 0: -3.0, -1.0 5 | // 1: 1.0, -1.0 6 | // 2: 1.0, 3.0 7 | gl_Position = vec4(-3.0 + 4 * ((gl_VertexID + 1) / 2), 8 | -1.0 + 4 * (gl_VertexID / 2), 9 | 0.0, 1.0); 10 | } 11 | -------------------------------------------------------------------------------- /HostProgram/shaders/scale.frag: -------------------------------------------------------------------------------- 1 | #version 400 2 | #extension GL_ARB_explicit_uniform_location : enable // required in version lower4.3 3 | #extension GL_ARB_shading_language_420pack : enable // required in version lower 4.2 4 | 5 | layout(location = 0) uniform float scale; 6 | layout(location = 1, binding = 0) uniform sampler2D srcTexture; 7 | 8 | /* layout(origin_upper_left) */in vec4 gl_FragCoord; 9 | 10 | out vec4 color; 11 | 12 | void main(void) { 13 | color = texelFetch(srcTexture, ivec2(gl_FragCoord.xy / scale), 0); 14 | } -------------------------------------------------------------------------------- /HostProgram/shaders/scale.vert: -------------------------------------------------------------------------------- 1 | #version 400 2 | 3 | void main(void) { 4 | // 0: -3.0, -1.0 5 | // 1: 1.0, -1.0 6 | // 2: 1.0, 3.0 7 | gl_Position = vec4(-3.0 + 4 * ((gl_VertexID + 1) / 2), 8 | -1.0 + 4 * (gl_VertexID / 2), 9 | 0.0, 1.0); 10 | } 11 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # VLR: 2 | 3 | ![VLR](README_TOP.jpg)\ 4 | IBL image: [sIBL Archive](http://www.hdrlabs.com/sibl/archive.html) 5 | 6 | VLRはNVIDIA OptiX 7を使用したGPUモンテカルロレイトレーシングレンダラーです。\ 7 | VLR is a GPU Monte Carlo ray tracing renderer using NVIDIA OptiX 7. 8 | 9 | ## 特徴 / Features 10 | * GPU Renderer using NVIDIA OptiX 7 11 | * Full Spectral Rendering (Monte Carlo Spectral Sampling)\ 12 | (For RGB resources, RGB->Spectrum conversion is performed using Meng-Simon's method \[Meng2015\]) 13 | * RGB Rendering (built by default) 14 | * BSDFs 15 | * Ideal Diffuse (Lambert) BRDF 16 | * Ideal Specular BRDF/BSDF 17 | * Microfacet (GGX) BRDF/BSDF 18 | * Fresnel-blended Lambertian BSDF 19 | * UE4- or Frostbite-like BRDF \[Karis2013, Lagarde2014\]\ 20 | Parameters can be specified using UE4 style (base color, roughness/metallic) or old style (diffuse, specular, glossiness). 21 | * Mixed BSDF 22 | * Shader Node System 23 | * Bump Mapping (Normal Map / Height Map) 24 | * Alpha Texture 25 | * Light Source Types 26 | * Area (Polygonal) Light 27 | * Point Light 28 | * Image Based Environmental Light 29 | * Camera Types 30 | * Perspective Camera with Depth of Field (thin-lens model) 31 | * Environment (Equirectangular) Camera 32 | * Geometry Instancing 33 | * Light Transport Algorithms 34 | * Path Tracing \[Kajiya1986\] with MIS 35 | * Light Tracing 36 | * Light Vertex Cache Bidirectional Path Tracing (LVC-BPT) \[Davidovič2014\] 37 | * Correct handling of non-symmetric scattering due to shading normals \[Veach1997\] 38 | 39 | ## 構成要素 / Components 40 | * libVLR - Renderer Library based on OptiX\ 41 | CのAPIを定義しています。\ 42 | Exposes C API. 43 | * vlrcpp.h - Single file wrapper for C++\ 44 | std::shared_ptrを用いてオブジェクトの寿命管理を自動化しています。\ 45 | Automatically manages lifetime of objects via std::shared_ptr. 46 | * HostProgram - A program to demonstrate how to use VLR 47 | 48 | ## API 49 | Code Example using VLRCpp (C++ wrapper) 50 | 51 | ```cpp 52 | using namespace vlr; 53 | 54 | ContextRef context = Context::create(cuContext, enableLogging, maxCallableDepth); 55 | 56 | // Construct a scene by defining meshes and materials. 57 | 58 | SceneRef scene = context->createScene(); 59 | 60 | TriangleMeshSurfaceNodeRef mesh = context->createTriangleMeshSurfaceNode("My Mesh 1"); 61 | { 62 | Vertex vertices[] = { 63 | Vertex{ Point3D(-1.5f, 0.0f, -1.5f), Normal3D(0, 1, 0), Vector3D(1, 0, 0), TexCoord2D(0.0f, 5.0f) }, 64 | // ... 65 | }; 66 | // ... 67 | mesh->setVertices(vertices, lengthof(vertices)); 68 | 69 | { 70 | Image2DRef imgAlbedo = loadImage2D(context, "checkerboard.png", "Reflectance", "Rec709(D65) sRGB Gamma"); 71 | Image2DRef imgNormalAlpha = loadImage2D(context, "normal_alpha.png", "NA", "Rec709(D65)"); 72 | 73 | ShaderNodeRef nodeAlbedo = context->createShaderNode("Image2DTexture"); 74 | nodeAlbedo->set("image", imgAlbedo); 75 | nodeAlbedo->set("min filter", "Nearest"); 76 | nodeAlbedo->set("mag filter", "Nearest"); 77 | 78 | ShaderNodeRef nodeNormalAlpha = context->createShaderNode("Image2DTexture"); 79 | nodeNormalAlpha->set("image", imgNormalAlpha); 80 | 81 | // You can flexibly define a material by connecting shader nodes. 82 | SurfaceMaterialRef mat = context->createSurfaceMaterial("Matte"); 83 | mat->set("albedo", nodeAlbedo->getPlug(VLRShaderNodePlugType_Spectrum, 0)); 84 | 85 | ShaderNodeRef nodeTangent = context->createShaderNode("Tangent"); 86 | nodeTangent->set("tangent type", "Radial Y"); 87 | 88 | uint32_t matGroup[] = { 0, 1, 2, 0, 2, 3 }; 89 | mesh->addMaterialGroup(matGroup, lengthof(matGroup), mat, 90 | nodeNormalAlpha->getPlug(VLRShaderNodePlugType_Normal3D, 0), // normal map 91 | nodeTangent->getPlug(VLRShaderNodePlugType_Vector3D, 0), // tangent 92 | nodeNormalAlpha->getPlug(VLRShaderNodePlugType_Alpha, 0)); // alpha map 93 | } 94 | 95 | // ... 96 | } 97 | 98 | // You can construct a scene graph with transforms 99 | InternalNodeRef transformNode = context->createInternalNode("trf A"); 100 | transformNode->setTransform(context->createStaticTransform(scale(2.0f))); 101 | transformNode->addChild(mesh); 102 | scene->addChild(transformNode); 103 | 104 | // Setup a camera 105 | CameraRef camera = context->createCamera("Perspective"); 106 | camera->set("position", Point3D(0, 1.5f, 6.0f)); 107 | camera->set("aspect", (float)renderTargetSizeX / renderTargetSizeY); 108 | camera->set("sensitivity", 1.0f); 109 | camera->set("fovy", 40 * M_PI / 180); 110 | camera->set("lens radius", 0.0f); 111 | 112 | // Setup the output buffer (OpenGL buffer can also be attached) 113 | context->bindOutputBuffer(1024, 1024, 0); 114 | 115 | // Let's render the scene! 116 | context->setScene(scene); 117 | context->render(cuStream, camera, enableDenoiser, 1, firstFrame, &numAccumFrames); 118 | ``` 119 | 120 | ## TODO 121 | - [ ] Make the rendering properly asynchronous. 122 | - [ ] Python Binding 123 | - [ ] Simple Scene Editor 124 | - [ ] Compile shader node at runtime using NVRTC to remove overhead of callable programs. 125 | 126 | ## 動作環境 / Confirmed Environment 127 | 現状以下の環境で動作を確認しています。\ 128 | I've confirmed that the program runs correctly on the following environment. 129 | 130 | * Windows 10 (21H2) & Visual Studio 2022 (17.2.4) 131 | * Core i9-9900K, 32GB, RTX 3080 10GB 132 | * NVIDIA Driver 516.40 (Note that versions around 510-512 had several OptiX issues.) 133 | 134 | 動作させるにあたっては以下のライブラリが必要です。\ 135 | It requires the following libraries. 136 | 137 | * libVLR 138 | * CUDA 12.5 139 | * OptiX 8.0.0 (requires Maxwell or later generation NVIDIA GPU) 140 | * Host Program 141 | * OpenEXR 3.1 142 | * assimp 5.0 143 | 144 | ## 注意 / Note 145 | モデルデータやテクスチャーを読み込むシーンファイルがありますが、それらアセットはリポジトリには含まれていません。\ 146 | There are some scene files loading model data and textures, but those assets are NOT included in this repository. 147 | 148 | ## 参考文献 / References 149 | [Davidovič2014] "Progressive Light Transport Simulation on the GPU: Survey and Improvements"\ 150 | [Kajiya1986] "THE RENDERING EQUATION"\ 151 | [Karis2013] "Real Shading in Unreal Engine 4"\ 152 | [Lagarde2014] "Moving Frostbite to Physically Based Rendering 3.0"\ 153 | [Meng2015] "Physically Meaningful Rendering using Tristimulus Colours"\ 154 | [Veach1997] "ROBUST MONTE CARLO METHODS FOR LIGHT TRANSPORT SIMULATION" 155 | 156 | ## ギャラリー / Gallery 157 | CornellBox_var.jpg
158 | A variant of the famous Cornell box scene. The left box has anisotropic BRDF with circular tangents along its local Y axis (roughness is smoother along tangent, rougher along bitangent). 159 |

160 | UE4LikeBRDF.jpg
161 | An object with UE4- or Frostbite 3.0-like BRDF (Textures are exported from Substance Painter) illuminated by an area light and an environmental light. 162 | 163 | Model: Substance Painter\ 164 | IBL image: [sIBL Archive](http://www.hdrlabs.com/sibl/archive.html) 165 |

166 | dispersive_caustics_closeup.jpg
167 | Caustics generated from Stanford bunny model illuminated by directional area light.\ 168 | The renderer uses spectral rendering for this. 169 | 170 | Model: [Stanford Bunny](http://graphics.stanford.edu/data/3Dscanrep/) 171 |

172 | Rungholt_view1.jpg
173 | Rungholt_view2.jpg
174 | Rungholt model illuminated by outdoor environment light. 175 | 176 | Model: Rungholt from Morgan McGuire's [Computer Graphics Archive](https://casual-effects.com/data)\ 177 | IBL image 1: [Direct HDR Capture of the Sun and Sky](https://vgl.ict.usc.edu/Data/SkyProbes/)\ 178 | IBL image 2: [sIBL Archive](http://www.hdrlabs.com/sibl/archive.html) 179 | 180 | ---- 181 | 2022 [@Shocker_0x15](https://twitter.com/Shocker_0x15) 182 | -------------------------------------------------------------------------------- /README_TOP.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shocker-0x15/VLR/8dad615a0f82c8599c6c59998278ab90b0c56f70/README_TOP.jpg -------------------------------------------------------------------------------- /README_TOP.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shocker-0x15/VLR/8dad615a0f82c8599c6c59998278ab90b0c56f70/README_TOP.png -------------------------------------------------------------------------------- /VLR.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 16 4 | VisualStudioVersion = 16.0.28803.452 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libVLR", "libVLR\libVLR.vcxproj", "{776A3F3D-83C8-4421-8CF4-13D6FF36C808}" 7 | EndProject 8 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "HostProgram", "HostProgram\HostProgram.vcxproj", "{6430930F-4932-457F-AC9C-AED74FACC5C7}" 9 | ProjectSection(ProjectDependencies) = postProject 10 | {776A3F3D-83C8-4421-8CF4-13D6FF36C808} = {776A3F3D-83C8-4421-8CF4-13D6FF36C808} 11 | EndProjectSection 12 | EndProject 13 | Global 14 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 15 | Debug|x64 = Debug|x64 16 | Release|x64 = Release|x64 17 | EndGlobalSection 18 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 19 | {776A3F3D-83C8-4421-8CF4-13D6FF36C808}.Debug|x64.ActiveCfg = Debug|x64 20 | {776A3F3D-83C8-4421-8CF4-13D6FF36C808}.Debug|x64.Build.0 = Debug|x64 21 | {776A3F3D-83C8-4421-8CF4-13D6FF36C808}.Release|x64.ActiveCfg = Release|x64 22 | {776A3F3D-83C8-4421-8CF4-13D6FF36C808}.Release|x64.Build.0 = Release|x64 23 | {6430930F-4932-457F-AC9C-AED74FACC5C7}.Debug|x64.ActiveCfg = Debug|x64 24 | {6430930F-4932-457F-AC9C-AED74FACC5C7}.Debug|x64.Build.0 = Debug|x64 25 | {6430930F-4932-457F-AC9C-AED74FACC5C7}.Release|x64.ActiveCfg = Release|x64 26 | {6430930F-4932-457F-AC9C-AED74FACC5C7}.Release|x64.Build.0 = Release|x64 27 | EndGlobalSection 28 | GlobalSection(SolutionProperties) = preSolution 29 | HideSolutionNode = FALSE 30 | EndGlobalSection 31 | GlobalSection(ExtensibilityGlobals) = postSolution 32 | SolutionGuid = {A7646774-B440-49D9-8617-92D17883F2C0} 33 | EndGlobalSection 34 | EndGlobal 35 | -------------------------------------------------------------------------------- /gallery/CornellBox_var.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shocker-0x15/VLR/8dad615a0f82c8599c6c59998278ab90b0c56f70/gallery/CornellBox_var.jpg -------------------------------------------------------------------------------- /gallery/CornellBox_var.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shocker-0x15/VLR/8dad615a0f82c8599c6c59998278ab90b0c56f70/gallery/CornellBox_var.png -------------------------------------------------------------------------------- /gallery/Rungholt_view1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shocker-0x15/VLR/8dad615a0f82c8599c6c59998278ab90b0c56f70/gallery/Rungholt_view1.jpg -------------------------------------------------------------------------------- /gallery/Rungholt_view1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shocker-0x15/VLR/8dad615a0f82c8599c6c59998278ab90b0c56f70/gallery/Rungholt_view1.png -------------------------------------------------------------------------------- /gallery/Rungholt_view2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shocker-0x15/VLR/8dad615a0f82c8599c6c59998278ab90b0c56f70/gallery/Rungholt_view2.jpg -------------------------------------------------------------------------------- /gallery/Rungholt_view2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shocker-0x15/VLR/8dad615a0f82c8599c6c59998278ab90b0c56f70/gallery/Rungholt_view2.png -------------------------------------------------------------------------------- /gallery/UE4LikeBRDF.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shocker-0x15/VLR/8dad615a0f82c8599c6c59998278ab90b0c56f70/gallery/UE4LikeBRDF.jpg -------------------------------------------------------------------------------- /gallery/UE4LikeBRDF.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shocker-0x15/VLR/8dad615a0f82c8599c6c59998278ab90b0c56f70/gallery/UE4LikeBRDF.png -------------------------------------------------------------------------------- /gallery/dispersive_caustics_closeup.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shocker-0x15/VLR/8dad615a0f82c8599c6c59998278ab90b0c56f70/gallery/dispersive_caustics_closeup.jpg -------------------------------------------------------------------------------- /gallery/dispersive_caustics_closeup.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shocker-0x15/VLR/8dad615a0f82c8599c6c59998278ab90b0c56f70/gallery/dispersive_caustics_closeup.png -------------------------------------------------------------------------------- /libVLR/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | set(TARGET_NAME "libvlr") 2 | 3 | file( 4 | GLOB_RECURSE SOURCES 5 | *.h *.hpp *.c *.cpp) 6 | 7 | set( 8 | GL3W_SOURCES 9 | "${CMAKE_BINARY_DIR}/ext/gl3w/include/GL/gl3w.h" 10 | "${CMAKE_BINARY_DIR}/ext/gl3w/include/GL/glcorearb.h" 11 | "${CMAKE_BINARY_DIR}/ext/gl3w/include/KHR/khplatform.h" 12 | "${CMAKE_BINARY_DIR}/ext/gl3w/src/gl3w.c" 13 | ) 14 | set_source_files_properties( 15 | ${GL3W_SOURCES} PROPERTIES 16 | GENERATED TRUE 17 | ) 18 | 19 | set( 20 | CUDA_KERNELS 21 | "GPU_kernels/aux_buffer_generator.cu" 22 | "GPU_kernels/post_process.cu" 23 | "GPU_kernels/setup_scene.cu" 24 | ) 25 | 26 | set( 27 | OPTIX_KERNELS 28 | "GPU_kernels/materials.cu" 29 | "GPU_kernels/shader_nodes.cu" 30 | "GPU_kernels/triangle.cu" 31 | "GPU_kernels/point.cu" 32 | "GPU_kernels/infinite_sphere.cu" 33 | "GPU_kernels/cameras.cu" 34 | "GPU_kernels/debug_rendering.cu" 35 | "GPU_kernels/path_tracing.cu" 36 | "GPU_kernels/light_tracing.cu" 37 | "GPU_kernels/lvc_bpt.cu" 38 | ) 39 | 40 | set( 41 | GPU_KERNEL_DEPENDENCIES 42 | "utils/cuda_util.h" 43 | "utils/optix_util.h" 44 | "utils/optixu_on_cudau.h" 45 | "include/vlr/common.h" 46 | "include/vlr/basic_types.h" 47 | "shared/common_internal.h" 48 | "shared/basic_types_internal.h" 49 | "shared/spectrum_base.h" 50 | "shared/rgb_spectrum_types.h" 51 | "shared/spectrum_types.h" 52 | "shared/random_distributions.h" 53 | "shared/shared.h" 54 | "shared/kernel_common.h" 55 | "shared/renderer_common.h" 56 | "shared/light_transport_common.h" 57 | ) 58 | 59 | nvcuda_compile_ptx( 60 | SOURCES ${CUDA_KERNELS} 61 | DEPENDENCIES ${GPU_KERNEL_DEPENDENCIES} 62 | TARGET_PATH "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${CMAKE_CFG_INTDIR}/${TARGET_NAME}/ptxes" 63 | GENERATED_FILES CUDA_PTXES 64 | NVCC_OPTIONS 65 | "-Xcompiler" "\"/wd 4819 /Zc:__cplusplus\"" 66 | "$<$:-D_DEBUG=1>" 67 | "$<$:-G>" 68 | "--gpu-architecture=compute_52" 69 | "-std=c++20" 70 | "-cudart" "shared" 71 | "--use_fast_math" 72 | "--relocatable-device-code=true" 73 | "-I${OPTIX_INCLUDE_DIR}" 74 | "-I\"include/vlr\"" 75 | ) 76 | 77 | nvcuda_compile_ptx( 78 | SOURCES ${OPTIX_KERNELS} 79 | DEPENDENCIES ${GPU_KERNEL_DEPENDENCIES} 80 | TARGET_PATH "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${CMAKE_CFG_INTDIR}/${TARGET_NAME}/ptxes" 81 | GENERATED_FILES OPTIX_PTXES 82 | NVCC_OPTIONS 83 | "-Xcompiler" "\"/wd 4819 /Zc:__cplusplus\"" 84 | "$<$:-D_DEBUG=1>" 85 | "$<$:-lineinfo>" 86 | "--gpu-architecture=compute_52" 87 | "-std=c++20" 88 | "-cudart" "shared" 89 | "--use_fast_math" 90 | "--relocatable-device-code=true" 91 | "-I${OPTIX_INCLUDE_DIR}" 92 | "-I\"include/vlr\"" 93 | ) 94 | 95 | 96 | 97 | source_group( 98 | "Host" REGULAR_EXPRESSION 99 | ".*\.(h|c|hpp|cpp)") 100 | source_group( 101 | "include" REGULAR_EXPRESSION 102 | "include/vlr/.*\.(h|c|hpp|cpp)") 103 | source_group( 104 | "Shared" REGULAR_EXPRESSION 105 | "shared/.*\.(h|c|hpp|cpp)") 106 | source_group( 107 | "GPU Kernels" REGULAR_EXPRESSION 108 | "GPU_kernels/.*\.(cuh|cu)") 109 | source_group( 110 | "Utilities" REGULAR_EXPRESSION 111 | "utils/.*\.(h|c|hpp|cpp)") 112 | source_group( 113 | "ext/gl3w" REGULAR_EXPRESSION 114 | "../ext/gl3w/.*$") 115 | 116 | 117 | file( 118 | GLOB_RECURSE SPECTRAL_UPSAMPLING_TABLES 119 | "spectral_upsampling_tables/*" 120 | ) 121 | 122 | copy_files( 123 | SOURCES ${SPECTRAL_UPSAMPLING_TABLES} 124 | TARGET_PATH "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${CMAKE_CFG_INTDIR}/${TARGET_NAME}/spectral_upsampling_tables" 125 | GENERATED_FILES COPIED_SPECTRAL_UPSAMPLING_TABLES 126 | ) 127 | 128 | 129 | 130 | add_library( 131 | "${TARGET_NAME}" SHARED 132 | ${SOURCES} 133 | ${CUDA_KERNELS} 134 | ${OPTIX_KERNELS} 135 | ${SPECTRAL_UPSAMPLING_TABLES} 136 | ) 137 | target_compile_definitions( 138 | "${TARGET_NAME}" PRIVATE 139 | "$<$:_DEBUG=1>" 140 | "VLR_API_EXPORTS" 141 | ) 142 | target_compile_options( 143 | "${TARGET_NAME}" PRIVATE 144 | # if (compilerID == MSVC && compilerLanguage != CUDA) set(/MP); 145 | "$<$,$>>:/MP>" 146 | "$<$,$>>:/MP>" 147 | # if (compilerID == MSVC && compilerLanguage != CUDA) set(/Zc:__cplusplus); 148 | "$<$,$>>:/Zc:__cplusplus>" 149 | ) 150 | target_include_directories( 151 | "${TARGET_NAME}" PRIVATE 152 | "include/vlr" 153 | "${CMAKE_BINARY_DIR}/ext/gl3w/include" 154 | "${CMAKE_SOURCE_DIR}/ext/half" 155 | "${OPTIX_INCLUDE_DIR}" 156 | ) 157 | target_link_libraries( 158 | "${TARGET_NAME}" PRIVATE 159 | CUDA::cuda_driver 160 | gl3w 161 | ) 162 | target_compile_features("${TARGET_NAME}" PRIVATE cxx_std_20) 163 | set_target_properties("${TARGET_NAME}" PROPERTIES CXX_EXTENSIONS OFF) 164 | -------------------------------------------------------------------------------- /libVLR/GPU_kernels/aux_buffer_generator.cu: -------------------------------------------------------------------------------- 1 | #include "../shared/light_transport_common.h" 2 | 3 | namespace vlr { 4 | using namespace shared; 5 | 6 | CUDA_DEVICE_KERNEL void RT_AH_NAME(auxBufferGeneratorAnyHitWithAlpha)() { 7 | WavelengthSamples wls; 8 | KernelRNG rng; 9 | AuxBufGenPayloadSignature::get(&wls, &rng, nullptr, nullptr); 10 | 11 | float alpha = getAlpha(wls); 12 | 13 | // Stochastic Alpha Test 14 | if (rng.getFloat0cTo1o() >= alpha) 15 | optixIgnoreIntersection(); 16 | 17 | AuxBufGenPayloadSignature::set(nullptr, &rng, nullptr, nullptr); 18 | } 19 | 20 | 21 | 22 | CUDA_DEVICE_KERNEL void RT_RG_NAME(auxBufferGenerator)() { 23 | uint2 launchIndex = make_uint2(optixGetLaunchIndex().x, optixGetLaunchIndex().y); 24 | 25 | KernelRNG rng = plp.rngBuffer.read(launchIndex); 26 | 27 | float2 p = make_float2(launchIndex.x + rng.getFloat0cTo1o(), 28 | launchIndex.y + rng.getFloat0cTo1o()); 29 | 30 | float selectWLPDF; 31 | WavelengthSamples wls = WavelengthSamples::createWithEqualOffsets(rng.getFloat0cTo1o(), rng.getFloat0cTo1o(), &selectWLPDF); 32 | 33 | Camera camera(static_cast(plp.progSampleLensPosition)); 34 | LensPosSample We0Sample(rng.getFloat0cTo1o(), rng.getFloat0cTo1o()); 35 | LensPosQueryResult We0Result; 36 | camera.sample(We0Sample, &We0Result); 37 | 38 | IDF idf(plp.cameraDescriptor, We0Result.surfPt, wls); 39 | 40 | idf.evaluateSpatialImportance(); 41 | 42 | IDFSample We1Sample(p.x / plp.imageSize.x, p.y / plp.imageSize.y); 43 | IDFQueryResult We1Result; 44 | idf.sample(IDFQuery(), We1Sample, &We1Result); 45 | 46 | Point3D rayOrg = We0Result.surfPt.position; 47 | Vector3D rayDir = We0Result.surfPt.fromLocal(We1Result.dirLocal); 48 | 49 | SampledSpectrum firstHitAlbedo; 50 | Normal3D firstHitNormal; 51 | AuxBufGenPayloadSignature::trace( 52 | plp.topGroup, asOptiXType(rayOrg), asOptiXType(rayDir), 0.0f, FLT_MAX, 0.0f, 53 | VisibilityGroup_Everything, OPTIX_RAY_FLAG_NONE, 54 | AuxBufGenRayType::Primary, MaxNumRayTypes, AuxBufGenRayType::Primary, 55 | wls, rng, firstHitAlbedo, firstHitNormal); 56 | 57 | uint32_t linearIndex = launchIndex.y * plp.imageStrideInPixels + launchIndex.x; 58 | DiscretizedSpectrum &accumAlbedo = plp.accumAlbedoBuffer[linearIndex]; 59 | Normal3D &accumNormal = plp.accumNormalBuffer[linearIndex]; 60 | if (plp.numAccumFrames == 1) { 61 | accumAlbedo = DiscretizedSpectrum::Zero(); 62 | accumNormal = Normal3D(0.0f, 0.0f, 0.0f); 63 | } 64 | TripletSpectrum whitePoint = createTripletSpectrum(SpectrumType::LightSource, ColorSpace::Rec709_D65, 65 | 1, 1, 1); 66 | accumAlbedo += DiscretizedSpectrum(wls, firstHitAlbedo * whitePoint.evaluate(wls) / selectWLPDF); 67 | accumNormal += firstHitNormal; 68 | 69 | plp.rngBuffer.write(launchIndex, rng); 70 | } 71 | 72 | 73 | 74 | CUDA_DEVICE_KERNEL void RT_CH_NAME(auxBufferGeneratorFirstHit)() { 75 | const auto hp = HitPointParameter::get(); 76 | 77 | WavelengthSamples wls; 78 | AuxBufGenPayloadSignature::get(&wls, nullptr, nullptr, nullptr); 79 | 80 | SurfacePoint surfPt; 81 | float hypAreaPDF; 82 | calcSurfacePoint(hp, wls, &surfPt, &hypAreaPDF); 83 | 84 | const SurfaceMaterialDescriptor matDesc = plp.materialDescriptorBuffer[hp.sbtr->geomInst.materialIndex]; 85 | constexpr TransportMode transportMode = TransportMode::Radiance; 86 | BSDF bsdf(matDesc, surfPt, wls); 87 | 88 | SampledSpectrum firstHitAlbedo = bsdf.getBaseColor(); 89 | Normal3D firstHitNormal = surfPt.shadingFrame.z; 90 | AuxBufGenPayloadSignature::set(nullptr, nullptr, &firstHitAlbedo, &firstHitNormal); 91 | } 92 | 93 | 94 | 95 | CUDA_DEVICE_KERNEL void RT_MS_NAME(auxBufferGeneratorMiss)() { 96 | SampledSpectrum firstHitAlbedo = SampledSpectrum::Zero(); 97 | Normal3D firstHitNormal = Normal3D(0.0f, 0.0f, 0.0f); 98 | AuxBufGenPayloadSignature::set(nullptr, nullptr, &firstHitAlbedo, &firstHitNormal); 99 | } 100 | } 101 | -------------------------------------------------------------------------------- /libVLR/GPU_kernels/debug_rendering.cu: -------------------------------------------------------------------------------- 1 | #include "../shared/renderer_common.h" 2 | 3 | namespace vlr { 4 | using namespace shared; 5 | 6 | // for debug rendering 7 | CUDA_DEVICE_FUNCTION CUDA_INLINE TripletSpectrum debugRenderingAttributeToSpectrum( 8 | const SurfacePoint &surfPt, const Vector3D &dirOut, DebugRenderingAttribute attribute) { 9 | TripletSpectrum value; 10 | 11 | switch (attribute) { 12 | case DebugRenderingAttribute::GeometricNormal: 13 | value = createTripletSpectrum(SpectrumType::LightSource, ColorSpace::Rec709_D65, 14 | std::fmax(0.0f, 0.5f + 0.5f * surfPt.geometricNormal.x), 15 | std::fmax(0.0f, 0.5f + 0.5f * surfPt.geometricNormal.y), 16 | std::fmax(0.0f, 0.5f + 0.5f * surfPt.geometricNormal.z)); 17 | break; 18 | case DebugRenderingAttribute::ShadingTangent: 19 | value = createTripletSpectrum(SpectrumType::LightSource, ColorSpace::Rec709_D65, 20 | std::fmax(0.0f, 0.5f + 0.5f * surfPt.shadingFrame.x.x), 21 | std::fmax(0.0f, 0.5f + 0.5f * surfPt.shadingFrame.x.y), 22 | std::fmax(0.0f, 0.5f + 0.5f * surfPt.shadingFrame.x.z)); 23 | break; 24 | case DebugRenderingAttribute::ShadingBitangent: 25 | value = createTripletSpectrum(SpectrumType::LightSource, ColorSpace::Rec709_D65, 26 | std::fmax(0.0f, 0.5f + 0.5f * surfPt.shadingFrame.y.x), 27 | std::fmax(0.0f, 0.5f + 0.5f * surfPt.shadingFrame.y.y), 28 | std::fmax(0.0f, 0.5f + 0.5f * surfPt.shadingFrame.y.z)); 29 | break; 30 | case DebugRenderingAttribute::ShadingNormal: 31 | value = createTripletSpectrum(SpectrumType::LightSource, ColorSpace::Rec709_D65, 32 | std::fmax(0.0f, 0.5f + 0.5f * surfPt.shadingFrame.z.x), 33 | std::fmax(0.0f, 0.5f + 0.5f * surfPt.shadingFrame.z.y), 34 | std::fmax(0.0f, 0.5f + 0.5f * surfPt.shadingFrame.z.z)); 35 | break; 36 | case DebugRenderingAttribute::TextureCoordinates: 37 | value = createTripletSpectrum(SpectrumType::LightSource, ColorSpace::Rec709_D65, 38 | surfPt.texCoord.u - ::vlr::floor(surfPt.texCoord.u), 39 | surfPt.texCoord.v - ::vlr::floor(surfPt.texCoord.v), 40 | 0.0f); 41 | break; 42 | case DebugRenderingAttribute::ShadingNormalViewCos: { 43 | float cos = dot(normalize(dirOut), normalize(surfPt.shadingFrame.z)); 44 | bool opposite = cos < 0; 45 | cos = std::fabs(cos); 46 | float sValue = 1 - cos; 47 | sValue = clamp(sValue, 0.0f, 1.0f); 48 | value = createTripletSpectrum(SpectrumType::LightSource, ColorSpace::Rec709_D65, 49 | sValue, opposite ? 0 : sValue, opposite ? 0 : sValue); 50 | break; 51 | } 52 | case DebugRenderingAttribute::GeometricVsShadingNormal: { 53 | float sim = dot(surfPt.geometricNormal, surfPt.shadingFrame.z); 54 | bool opposite = sim < 0.0f; 55 | sim = std::fabs(sim); 56 | constexpr float coeff = 5.0f; 57 | float sValue = 0.5f + coeff * (sim - 1); 58 | sValue = clamp(sValue, 0.0f, 1.0f); 59 | value = createTripletSpectrum(SpectrumType::LightSource, ColorSpace::Rec709_D65, 60 | sValue, opposite ? 0 : sValue, opposite ? 0 : sValue); 61 | break; 62 | } 63 | case DebugRenderingAttribute::ShadingFrameLengths: 64 | value = createTripletSpectrum(SpectrumType::LightSource, ColorSpace::Rec709_D65, 65 | clamp(0.5f + 10 * (surfPt.shadingFrame.x.length() - 1), 0.0f, 1.0f), 66 | clamp(0.5f + 10 * (surfPt.shadingFrame.y.length() - 1), 0.0f, 1.0f), 67 | clamp(0.5f + 10 * (surfPt.shadingFrame.z.length() - 1), 0.0f, 1.0f)); 68 | break; 69 | case DebugRenderingAttribute::ShadingFrameOrthogonality: 70 | value = createTripletSpectrum(SpectrumType::LightSource, ColorSpace::Rec709_D65, 71 | clamp(0.5f + 100 * dot(surfPt.shadingFrame.x, surfPt.shadingFrame.y), 0.0f, 1.0f), 72 | clamp(0.5f + 100 * dot(surfPt.shadingFrame.y, surfPt.shadingFrame.z), 0.0f, 1.0f), 73 | clamp(0.5f + 100 * dot(surfPt.shadingFrame.z, surfPt.shadingFrame.x), 0.0f, 1.0f)); 74 | break; 75 | default: 76 | break; 77 | } 78 | 79 | return value; 80 | } 81 | 82 | 83 | 84 | 85 | // Common Any Hit Program for All Primitive Types and Materials 86 | CUDA_DEVICE_KERNEL void RT_AH_NAME(debugRenderingAnyHitWithAlpha)() { 87 | KernelRNG rng; 88 | WavelengthSamples wls; 89 | DebugPayloadSignature::get(&rng, &wls, nullptr); 90 | 91 | float alpha = getAlpha(wls); 92 | 93 | // Stochastic Alpha Test 94 | if (rng.getFloat0cTo1o() >= alpha) 95 | optixIgnoreIntersection(); 96 | 97 | DebugPayloadSignature::set(&rng, nullptr, nullptr); 98 | } 99 | 100 | 101 | 102 | // Common Closest Hit Program for All Primitive Types and Materials 103 | CUDA_DEVICE_KERNEL void RT_CH_NAME(debugRenderingClosestHit)() { 104 | const auto hp = HitPointParameter::get(); 105 | 106 | WavelengthSamples wls; 107 | DebugPayloadSignature::get(nullptr, &wls, nullptr); 108 | 109 | SurfacePoint surfPt; 110 | float hypAreaPDF; 111 | calcSurfacePoint(hp, wls, &surfPt, &hypAreaPDF); 112 | 113 | //if (!surfPt.shadingFrame.x.allFinite() || 114 | // !surfPt.shadingFrame.y.allFinite() || 115 | // !surfPt.shadingFrame.z.allFinite()) 116 | // vlrprintf("(%g, %g, %g), (%g, %g, %g), (%g, %g, %g)\n", 117 | // surfPt.shadingFrame.x.x, surfPt.shadingFrame.x.y, surfPt.shadingFrame.x.z, 118 | // surfPt.shadingFrame.y.x, surfPt.shadingFrame.y.y, surfPt.shadingFrame.y.z, 119 | // surfPt.shadingFrame.z.x, surfPt.shadingFrame.z.y, surfPt.shadingFrame.z.z); 120 | 121 | SampledSpectrum value; 122 | if (plp.debugRenderingAttribute == DebugRenderingAttribute::BaseColor) { 123 | const SurfaceMaterialDescriptor matDesc = plp.materialDescriptorBuffer[hp.sbtr->geomInst.materialIndex]; 124 | BSDF bsdf(matDesc, surfPt, wls); 125 | 126 | TripletSpectrum whitePoint = createTripletSpectrum(SpectrumType::LightSource, ColorSpace::Rec709_D65, 127 | 1, 1, 1); 128 | value = bsdf.getBaseColor() * whitePoint.evaluate(wls); 129 | } 130 | else { 131 | value = debugRenderingAttributeToSpectrum( 132 | surfPt, -asVector3D(optixGetWorldRayDirection()), plp.debugRenderingAttribute).evaluate(wls); 133 | } 134 | 135 | DebugPayloadSignature::set(nullptr, nullptr, &value); 136 | } 137 | 138 | 139 | 140 | // JP: 本当は無限大の球のIntersection/Bounding Box Programを使用して環境光に関する処理もClosest Hit Programで統一的に行いたい。 141 | // が、OptiXのBVHビルダーがLBVHベースなので無限大のAABBを生成するのは危険。 142 | // 仕方なくMiss Programで環境光を処理する。 143 | CUDA_DEVICE_KERNEL void RT_MS_NAME(debugRenderingMiss)() { 144 | WavelengthSamples wls; 145 | DebugPayloadSignature::get(nullptr, &wls, nullptr); 146 | 147 | const Instance &inst = plp.instBuffer[plp.envLightInstIndex]; 148 | //const GeometryInstance &geomInst = plp.geomInstBuffer[inst.geomInstIndices[0]]; 149 | 150 | Vector3D direction = asVector3D(optixGetWorldRayDirection()); 151 | float phi, theta; 152 | direction.toPolarYUp(&theta, &phi); 153 | 154 | float sinPhi, cosPhi; 155 | ::vlr::sincos(phi, &sinPhi, &cosPhi); 156 | Vector3D texCoord0Dir = normalize(Vector3D(-cosPhi, 0.0f, -sinPhi)); 157 | ReferenceFrame shadingFrame; 158 | shadingFrame.x = texCoord0Dir; 159 | shadingFrame.z = -direction; 160 | shadingFrame.y = cross(shadingFrame.z, shadingFrame.x); 161 | 162 | SurfacePoint surfPt; 163 | surfPt.position = Point3D(direction.x, direction.y, direction.z); 164 | surfPt.shadingFrame = shadingFrame; 165 | surfPt.isPoint = false; 166 | surfPt.atInfinity = true; 167 | 168 | surfPt.geometricNormal = -direction; 169 | surfPt.u = phi; 170 | surfPt.v = theta; 171 | phi += inst.rotationPhi; 172 | phi = phi - ::vlr::floor(phi / (2 * VLR_M_PI)) * 2 * VLR_M_PI; 173 | surfPt.texCoord = TexCoord2D(phi / (2 * VLR_M_PI), theta / VLR_M_PI); 174 | 175 | SampledSpectrum value; 176 | if (plp.debugRenderingAttribute == DebugRenderingAttribute::BaseColor) 177 | value = SampledSpectrum::Zero(); 178 | else 179 | value = debugRenderingAttributeToSpectrum( 180 | surfPt, -direction, plp.debugRenderingAttribute).evaluate(wls); 181 | 182 | DebugPayloadSignature::set(nullptr, nullptr, &value); 183 | } 184 | 185 | 186 | 187 | // Common Ray Generation Program for All Camera Types 188 | CUDA_DEVICE_KERNEL void RT_RG_NAME(debugRenderingRayGeneration)() { 189 | uint2 launchIndex = make_uint2(optixGetLaunchIndex().x, optixGetLaunchIndex().y); 190 | 191 | KernelRNG rng = plp.rngBuffer.read(launchIndex); 192 | 193 | float2 p = make_float2(launchIndex.x + rng.getFloat0cTo1o(), 194 | launchIndex.y + rng.getFloat0cTo1o()); 195 | 196 | float selectWLPDF; 197 | WavelengthSamples wls = WavelengthSamples::createWithEqualOffsets(rng.getFloat0cTo1o(), rng.getFloat0cTo1o(), &selectWLPDF); 198 | 199 | Camera camera(static_cast(plp.progSampleLensPosition)); 200 | LensPosSample We0Sample(rng.getFloat0cTo1o(), rng.getFloat0cTo1o()); 201 | LensPosQueryResult We0Result; 202 | camera.sample(We0Sample, &We0Result); 203 | 204 | IDF idf(plp.cameraDescriptor, We0Result.surfPt, wls); 205 | 206 | idf.evaluateSpatialImportance(); 207 | 208 | IDFSample We1Sample(p.x / plp.imageSize.x, p.y / plp.imageSize.y); 209 | IDFQueryResult We1Result; 210 | idf.sample(IDFQuery(), We1Sample, &We1Result); 211 | Vector3D rayDir = We0Result.surfPt.fromLocal(We1Result.dirLocal); 212 | 213 | SampledSpectrum value; 214 | DebugPayloadSignature::trace( 215 | plp.topGroup, asOptiXType(We0Result.surfPt.position), asOptiXType(rayDir), 0.0f, FLT_MAX, 0.0f, 216 | VisibilityGroup_Everything, OPTIX_RAY_FLAG_NONE, 217 | DebugRayType::Primary, MaxNumRayTypes, DebugRayType::Primary, 218 | rng, wls, value); 219 | 220 | plp.rngBuffer.write(launchIndex, rng); 221 | 222 | if (!value.allFinite()) { 223 | vlrprintf("Pass %u, (%u, %u): Not a finite value.\n", plp.numAccumFrames, launchIndex.x, launchIndex.y); 224 | return; 225 | } 226 | 227 | if (plp.numAccumFrames == 1) 228 | plp.accumBuffer[launchIndex].reset(); 229 | plp.accumBuffer[launchIndex].add(wls, value / selectWLPDF); 230 | } 231 | } 232 | -------------------------------------------------------------------------------- /libVLR/GPU_kernels/infinite_sphere.cu: -------------------------------------------------------------------------------- 1 | #include "../shared/kernel_common.h" 2 | 3 | namespace vlr { 4 | using namespace shared; 5 | 6 | // Intersection Program for Infinite Sphere 7 | CUDA_DEVICE_KERNEL void RT_IS_NAME(intersectInfiniteSphere)(int32_t primIdx) { 8 | Vector3D direction = asVector3D(optixGetObjectRayDirection()); 9 | float phi, theta; 10 | direction.toPolarYUp(&theta, &phi); 11 | 12 | InfiniteSphereAttributeSignature::reportIntersection(INFINITY, 0, phi, theta); 13 | } 14 | 15 | 16 | 17 | RT_CALLABLE_PROGRAM void RT_DC_NAME(decodeHitPointForInfiniteSphere)( 18 | uint32_t instIndex, uint32_t geomInstIndex, uint32_t primIndex, 19 | float u, float v, 20 | SurfacePoint* surfPt) { 21 | const Instance &inst = plp.instBuffer[instIndex]; 22 | //const GeometryInstance &geomInst = plp.geomInstBuffer[geomInstIndex]; 23 | 24 | float posPhi = u; 25 | float theta = v; 26 | float phi = posPhi + inst.rotationPhi; 27 | phi = phi - ::vlr::floor(phi / (2 * VLR_M_PI)) * 2 * VLR_M_PI; 28 | 29 | Vector3D direction = Vector3D::fromPolarYUp(posPhi, theta); 30 | Point3D position = Point3D(direction.x, direction.y, direction.z); 31 | 32 | float sinPhi, cosPhi; 33 | ::vlr::sincos(posPhi, &sinPhi, &cosPhi); 34 | Vector3D texCoord0Dir = normalize(Vector3D(-cosPhi, 0.0f, -sinPhi)); 35 | 36 | Normal3D geometricNormal = -static_cast(position); 37 | 38 | ReferenceFrame shadingFrame; 39 | shadingFrame.x = texCoord0Dir; 40 | shadingFrame.z = geometricNormal; 41 | shadingFrame.y = cross(shadingFrame.z, shadingFrame.x); 42 | VLRAssert(absDot(shadingFrame.z, shadingFrame.x) < 0.01f, "shading normal and tangent must be orthogonal."); 43 | 44 | surfPt->instIndex = instIndex; 45 | surfPt->geomInstIndex = geomInstIndex; 46 | surfPt->primIndex = 0; 47 | 48 | surfPt->position = position; 49 | surfPt->shadingFrame = shadingFrame; 50 | surfPt->isPoint = false; 51 | surfPt->atInfinity = true; 52 | surfPt->geometricNormal = geometricNormal; 53 | surfPt->u = posPhi; 54 | surfPt->v = theta; 55 | surfPt->texCoord = TexCoord2D(phi / (2 * VLR_M_PI), theta / VLR_M_PI); 56 | } 57 | 58 | 59 | 60 | RT_CALLABLE_PROGRAM void RT_DC_NAME(sampleInfiniteSphere)( 61 | uint32_t instIndex, uint32_t geomInstIndex, 62 | const SurfaceLightPosSample &sample, const Point3D &shadingPoint, 63 | SurfaceLightPosQueryResult* result) { 64 | (void)shadingPoint; 65 | 66 | const Instance &inst = plp.instBuffer[instIndex]; 67 | const GeometryInstance &geomInst = plp.geomInstBuffer[geomInstIndex]; 68 | 69 | float u, v; 70 | float uvPDF; 71 | geomInst.asInfSphere.importanceMap.sample(sample.uPos[0], sample.uPos[1], &u, &v, &uvPDF); 72 | float phi = 2 * VLR_M_PI * u; 73 | float theta = VLR_M_PI * v; 74 | 75 | float posPhi = phi - inst.rotationPhi; 76 | posPhi = posPhi - ::vlr::floor(posPhi / (2 * VLR_M_PI)) * 2 * VLR_M_PI; 77 | 78 | Vector3D direction = Vector3D::fromPolarYUp(posPhi, theta); 79 | Point3D position = Point3D(direction.x, direction.y, direction.z); 80 | 81 | float sinPhi, cosPhi; 82 | ::vlr::sincos(posPhi, &sinPhi, &cosPhi); 83 | Vector3D texCoord0Dir = normalize(Vector3D(-cosPhi, 0.0f, -sinPhi)); 84 | 85 | Normal3D geometricNormal = -static_cast(position); 86 | 87 | ReferenceFrame shadingFrame; 88 | shadingFrame.x = texCoord0Dir; 89 | shadingFrame.z = geometricNormal; 90 | shadingFrame.y = cross(shadingFrame.z, shadingFrame.x); 91 | VLRAssert(absDot(shadingFrame.z, shadingFrame.x) < 0.01f, "shading normal and tangent must be orthogonal."); 92 | 93 | SurfacePoint &surfPt = result->surfPt; 94 | 95 | surfPt.instIndex = instIndex; 96 | surfPt.geomInstIndex = geomInstIndex; 97 | surfPt.primIndex = 0; 98 | 99 | surfPt.position = position; 100 | surfPt.shadingFrame = shadingFrame; 101 | surfPt.isPoint = false; 102 | surfPt.atInfinity = true; 103 | surfPt.geometricNormal = geometricNormal; 104 | surfPt.u = posPhi; 105 | surfPt.v = theta; 106 | surfPt.texCoord = TexCoord2D(phi / (2 * VLR_M_PI), theta / VLR_M_PI); 107 | 108 | // JP: テクスチャー空間中のPDFを面積に関するものに変換する。 109 | // EN: convert the PDF in texture space to one with respect to area. 110 | // The true value is: lim_{l to inf} uvPDF / (2 * M_PI * M_PI * std::sin(theta)) / l^2 111 | result->areaPDF = uvPDF / (2 * VLR_M_PI * VLR_M_PI * std::sin(theta)); 112 | result->posType = DirectionType::Emission() | DirectionType::LowFreq(); 113 | result->materialIndex = geomInst.materialIndex; 114 | } 115 | } 116 | -------------------------------------------------------------------------------- /libVLR/GPU_kernels/point.cu: -------------------------------------------------------------------------------- 1 | #include "../shared/kernel_common.h" 2 | 3 | namespace vlr { 4 | using namespace shared; 5 | 6 | RT_CALLABLE_PROGRAM void RT_DC_NAME(decodeHitPointForPoint)( 7 | uint32_t instIndex, uint32_t geomInstIndex, uint32_t primIndex, 8 | float u, float v, 9 | SurfacePoint* surfPt) { 10 | const Instance &inst = plp.instBuffer[instIndex]; 11 | const GeometryInstance &geomInst = plp.geomInstBuffer[geomInstIndex]; 12 | 13 | uint32_t pointIndex = geomInst.asPoints.indexBuffer[primIndex]; 14 | const Vertex &vertex = geomInst.asTriMesh.vertexBuffer[pointIndex]; 15 | 16 | const StaticTransform &transform = inst.transform; 17 | 18 | Point3D position = transform * vertex.position; 19 | Normal3D shadingNormal = normalize(transform * vertex.normal); 20 | Vector3D tc0Direction = normalize(transform * vertex.tc0Direction); 21 | 22 | surfPt->instIndex = instIndex; 23 | surfPt->geomInstIndex = geomInstIndex; 24 | surfPt->primIndex = primIndex; 25 | 26 | surfPt->position = position; 27 | surfPt->shadingFrame = ReferenceFrame(tc0Direction, shadingNormal); 28 | surfPt->isPoint = true; 29 | surfPt->atInfinity = false; 30 | surfPt->geometricNormal = shadingNormal; 31 | surfPt->u = u; 32 | surfPt->v = v; 33 | surfPt->texCoord = TexCoord2D(0.0f, 0.0f); 34 | } 35 | 36 | 37 | 38 | RT_CALLABLE_PROGRAM void RT_DC_NAME(samplePoint)( 39 | uint32_t instIndex, uint32_t geomInstIndex, 40 | const SurfaceLightPosSample &sample, const Point3D &shadingPoint, 41 | SurfaceLightPosQueryResult* result) { 42 | (void)shadingPoint; 43 | 44 | const Instance &inst = plp.instBuffer[instIndex]; 45 | const GeometryInstance &geomInst = plp.geomInstBuffer[geomInstIndex]; 46 | 47 | float primProb; 48 | uint32_t primIdx = geomInst.asPoints.primDistribution.sample(sample.uElem, &primProb); 49 | //printf("%g, %u, %g\n", sample.uElem, primIdx, primProb); 50 | 51 | uint32_t pointIndex = geomInst.asPoints.indexBuffer[primIdx]; 52 | const Vertex &v = geomInst.asPoints.vertexBuffer[pointIndex]; 53 | 54 | const StaticTransform &transform = inst.transform; 55 | 56 | // area = 4 * pi * r^2 57 | constexpr float area = 4 * VLR_M_PI/* * pow2(0.0f)*/; 58 | result->areaPDF = primProb / area; 59 | result->posType = DirectionType::Emission() | DirectionType::Delta0D(); 60 | result->materialIndex = geomInst.materialIndex; 61 | 62 | Point3D position = transform * v.position; 63 | Normal3D shadingNormal = normalize(transform * v.normal); 64 | Vector3D tc0Direction = normalize(transform * v.tc0Direction); 65 | 66 | SurfacePoint &surfPt = result->surfPt; 67 | 68 | surfPt.instIndex = instIndex; 69 | surfPt.geomInstIndex = geomInstIndex; 70 | surfPt.primIndex = primIdx; 71 | 72 | surfPt.position = position; 73 | surfPt.shadingFrame = ReferenceFrame(tc0Direction, shadingNormal); 74 | surfPt.isPoint = true; 75 | surfPt.atInfinity = false; 76 | surfPt.geometricNormal = shadingNormal; 77 | surfPt.u = 0.0f; 78 | surfPt.v = 0.0f; 79 | surfPt.texCoord = TexCoord2D(0.0f, 0.0f); 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /libVLR/GPU_kernels/post_process.cu: -------------------------------------------------------------------------------- 1 | #define RT_PIPELINE_LAUNCH_PARAMETERS extern "C" __constant__ 2 | #include "../shared/kernel_common.h" 3 | 4 | namespace vlr { 5 | using namespace shared; 6 | 7 | CUDA_DEVICE_KERNEL void resetAtomicAccumBuffer( 8 | DiscretizedSpectrum* atomicAccumBuffer, 9 | uint2 imageSize, uint32_t imageStrideInPixels) { 10 | uint2 launchIndex = make_uint2(blockDim.x * blockIdx.x + threadIdx.x, 11 | blockDim.y * blockIdx.y + threadIdx.y); 12 | if (launchIndex.x >= imageSize.x || launchIndex.y >= imageSize.y) 13 | return; 14 | uint32_t linearIndex = launchIndex.y * imageStrideInPixels + launchIndex.x; 15 | atomicAccumBuffer[linearIndex] = DiscretizedSpectrum::Zero(); 16 | } 17 | 18 | CUDA_DEVICE_KERNEL void accumulateFromAtomicAccumBuffer( 19 | const DiscretizedSpectrum* atomicAccumBuffer, 20 | optixu::BlockBuffer2D accumBuffer, 21 | uint2 imageSize, uint32_t imageStrideInPixels, uint32_t reset) { 22 | uint2 launchIndex = make_uint2(blockDim.x * blockIdx.x + threadIdx.x, 23 | blockDim.y * blockIdx.y + threadIdx.y); 24 | if (launchIndex.x >= imageSize.x || launchIndex.y >= imageSize.y) 25 | return; 26 | uint32_t linearIndex = launchIndex.y * imageStrideInPixels + launchIndex.x; 27 | const DiscretizedSpectrum &srcValue = atomicAccumBuffer[linearIndex]; 28 | if (reset) 29 | accumBuffer[launchIndex].reset(); 30 | accumBuffer[launchIndex].add(srcValue); 31 | } 32 | 33 | CUDA_DEVICE_KERNEL void copyBuffers(const optixu::BlockBuffer2D accumBuffer, 34 | const DiscretizedSpectrum* accumAlbedoBuffer, 35 | const Normal3D* accumNormalBuffer, 36 | Quaternion invOrientation, 37 | uint2 imageSize, uint32_t imageStrideInPixels, 38 | uint32_t numAccumFrames, 39 | float4* linearColorBuffer, 40 | float4* linearAlbedoBuffer, 41 | float4* linearNormalBuffer) { 42 | uint2 launchIndex = make_uint2(blockDim.x * blockIdx.x + threadIdx.x, 43 | blockDim.y * blockIdx.y + threadIdx.y); 44 | uint32_t linearIndex = launchIndex.y * imageStrideInPixels + launchIndex.x; 45 | 46 | if (launchIndex.x >= imageSize.x || launchIndex.y >= imageSize.y) 47 | return; 48 | 49 | float recNumAccums = 1.0f / numAccumFrames; 50 | const DiscretizedSpectrum &color = accumBuffer[launchIndex].getValue().result; 51 | float colorXYZ[3]; 52 | color.toXYZ(colorXYZ); 53 | colorXYZ[0] *= recNumAccums; 54 | colorXYZ[1] *= recNumAccums; 55 | colorXYZ[2] *= recNumAccums; 56 | VLRAssert(colorXYZ[0] >= 0.0f && colorXYZ[1] >= 0.0f && colorXYZ[2] >= 0.0f, 57 | "each value of color XYZ must not be negative."); 58 | float colorRGB[3]; 59 | transformTristimulus(mat_XYZ_to_Rec709_D65, colorXYZ, colorRGB); 60 | // JP: 同じセンサーサイズ設定で解像度を変えるとピクセル辺りの積分値の大きさが変わって(=明るさが変わって) 61 | // 使いづらいのでキャンセルする補正項をかける。 62 | // EN: Changing the resolution while keeping the sensor size causes difference in the magnitude of 63 | // per-pixel integrated value (i.e. difference in brightness), making it difficult to use, 64 | // so multiply a correction factor. 65 | float resCorrection = imageSize.x * imageSize.y; 66 | colorRGB[0] *= resCorrection; 67 | colorRGB[1] *= resCorrection; 68 | colorRGB[2] *= resCorrection; 69 | 70 | const DiscretizedSpectrum &albedo = accumAlbedoBuffer[linearIndex]; 71 | float albedoXYZ[3]; 72 | albedo.toXYZ(albedoXYZ); 73 | albedoXYZ[0] *= recNumAccums; 74 | albedoXYZ[1] *= recNumAccums; 75 | albedoXYZ[2] *= recNumAccums; 76 | VLRAssert(albedoXYZ[0] >= 0.0f && albedoXYZ[1] >= 0.0f && albedoXYZ[2] >= 0.0f, 77 | "Pixel %u, %u: (%g, %g, %g), each value of albedo XYZ must not be negative.", 78 | launchIndex.x, launchIndex.y, albedoXYZ[0], albedoXYZ[1], albedoXYZ[2]); 79 | float albedoRGB[3]; 80 | transformTristimulus(mat_XYZ_to_Rec709_D65, albedoXYZ, albedoRGB); 81 | 82 | Normal3D normal = accumNormalBuffer[linearIndex]; 83 | normal = invOrientation.toMatrix3x3() * normal; 84 | normal.x *= -1; 85 | if (normal.x != 0 || normal.y != 0 || normal.z != 0) 86 | normal.normalize(); 87 | 88 | linearColorBuffer[linearIndex] = make_float4(colorRGB[0], colorRGB[1], colorRGB[2], 1.0f); 89 | linearAlbedoBuffer[linearIndex] = make_float4(albedoRGB[0], albedoRGB[1], albedoRGB[2], 1.0f); 90 | linearNormalBuffer[linearIndex] = make_float4(normal.x, normal.y, normal.z, 1.0f); 91 | } 92 | 93 | CUDA_DEVICE_KERNEL void convertToRGB(const optixu::BlockBuffer2D accumBuffer, 94 | const float4* linearDenoisedColorBuffer, 95 | const float4* linearAlbedoBuffer, 96 | const float4* linearNormalBuffer, 97 | bool useDenoiser, bool debugRender, DebugRenderingAttribute debugAttr, 98 | uint2 imageSize, uint32_t imageStrideInPixels, uint32_t numAccumFrames, 99 | optixu::NativeBlockBuffer2D outputBuffer) { 100 | uint2 launchIndex = make_uint2(blockDim.x * blockIdx.x + threadIdx.x, 101 | blockDim.y * blockIdx.y + threadIdx.y); 102 | if (launchIndex.x >= imageSize.x || launchIndex.y >= imageSize.y) 103 | return; 104 | 105 | float RGB[3]; 106 | if (debugRender && 107 | (debugAttr == DebugRenderingAttribute::DenoiserAlbedo || 108 | debugAttr == DebugRenderingAttribute::DenoiserNormal)) { 109 | uint32_t linearIndex = launchIndex.y * imageStrideInPixels + launchIndex.x; 110 | float4 value; 111 | switch (debugAttr) { 112 | case DebugRenderingAttribute::DenoiserAlbedo: 113 | value = linearAlbedoBuffer[linearIndex]; 114 | break; 115 | case DebugRenderingAttribute::DenoiserNormal: 116 | value = linearNormalBuffer[linearIndex]; 117 | value = make_float4(0.5f * value.x + 0.5f, 118 | 0.5f * value.y + 0.5f, 119 | 0.5f * value.z + 0.5f, 120 | value.w); 121 | break; 122 | } 123 | RGB[0] = value.x; 124 | RGB[1] = value.y; 125 | RGB[2] = value.z; 126 | } 127 | else { 128 | if (useDenoiser) { 129 | uint32_t linearIndex = launchIndex.y * imageStrideInPixels + launchIndex.x; 130 | float4 value = linearDenoisedColorBuffer[linearIndex]; 131 | RGB[0] = value.x; 132 | RGB[1] = value.y; 133 | RGB[2] = value.z; 134 | } 135 | else { 136 | const DiscretizedSpectrum &spectrum = accumBuffer[launchIndex].getValue().result; 137 | float XYZ[3]; 138 | spectrum.toXYZ(XYZ); 139 | float recNumAccums = 1.0f / numAccumFrames; 140 | XYZ[0] *= recNumAccums; 141 | XYZ[1] *= recNumAccums; 142 | XYZ[2] *= recNumAccums; 143 | VLRAssert(XYZ[0] >= 0.0f && XYZ[1] >= 0.0f && XYZ[2] >= 0.0f, 144 | "each value of XYZ must not be negative (%g, %g, %g).", 145 | XYZ[0], XYZ[1], XYZ[2]); 146 | transformTristimulus(mat_XYZ_to_Rec709_D65, XYZ, RGB); 147 | 148 | if (!debugRender) { 149 | // JP: 同じセンサーサイズ設定で解像度を変えるとピクセル辺りの積分値の大きさが変わって(=明るさが変わって) 150 | // 使いづらいのでキャンセルする補正項をかける。 151 | // EN: Changing the resolution while keeping the sensor size causes difference in the magnitude of 152 | // per-pixel integrated value (i.e. difference in brightness), making it difficult to use, 153 | // so multiply a correction factor. 154 | float resCorrection = imageSize.x * imageSize.y; 155 | RGB[0] *= resCorrection; 156 | RGB[1] *= resCorrection; 157 | RGB[2] *= resCorrection; 158 | } 159 | } 160 | } 161 | 162 | outputBuffer.write(launchIndex, make_float4(RGB[0], RGB[1], RGB[2], 1.0f)); // not clamp out of gamut color. 163 | } 164 | } 165 | -------------------------------------------------------------------------------- /libVLR/GPU_kernels/setup_scene.cu: -------------------------------------------------------------------------------- 1 | #define RT_PIPELINE_LAUNCH_PARAMETERS extern "C" __constant__ 2 | #include "../shared/kernel_common.h" 3 | 4 | namespace vlr { 5 | using namespace shared; 6 | 7 | CUDA_DEVICE_KERNEL void computeInstanceAABBs( 8 | const uint32_t* instIndices, const uint32_t* itemOffsets, 9 | Instance* instances, const GeometryInstance* geomInsts, uint32_t numItems) { 10 | uint32_t globalIndex = blockDim.x * blockIdx.x + threadIdx.x; 11 | if (globalIndex >= numItems) 12 | return; 13 | 14 | uint32_t instIndex = instIndices[globalIndex]; 15 | Instance &inst = instances[instIndex]; 16 | VLRAssert(inst.isActive, "This instance is inactive and should not be assigned to a thread."); 17 | uint32_t geomInstIndexInInst = globalIndex - itemOffsets[globalIndex]; 18 | uint32_t geomInstIndex = inst.geomInstIndices[geomInstIndexInInst]; 19 | const GeometryInstance &geomInst = geomInsts[geomInstIndex]; 20 | if (geomInst.geomType != GeometryType_TriangleMesh) 21 | return; 22 | //BoundingBox3D aabb = geomInst.asTriMesh.aabb; 23 | //printf("%u: Inst %u-%u: GeomInst %u: (%g, %g, %g) - (%g, %g, %g)\n", 24 | // globalIndex, instIndex, geomInstIndexInInst, geomInstIndex, 25 | // aabb.minP.x, aabb.minP.y, aabb.minP.z, 26 | // aabb.maxP.x, aabb.maxP.y, aabb.maxP.z); 27 | BoundingBox3DAsOrderedInt geomInstAabbAsInt(geomInst.asTriMesh.aabb); 28 | 29 | auto &instAabbAsInt = reinterpret_cast(inst.childAabb); 30 | atomicUnifyBoundingBox3D(&instAabbAsInt, geomInstAabbAsInt); 31 | } 32 | 33 | CUDA_DEVICE_KERNEL void finalizeInstanceAABBs(Instance* instances, uint32_t numInstances) { 34 | uint32_t globalIndex = blockDim.x * blockIdx.x + threadIdx.x; 35 | if (globalIndex >= numInstances) 36 | return; 37 | 38 | uint32_t instIndex = globalIndex; 39 | Instance &inst = instances[instIndex]; 40 | if (inst.isActive && inst.aabbIsDirty) { 41 | auto aabbAsInt = reinterpret_cast(inst.childAabb); 42 | inst.childAabb = static_cast(aabbAsInt); 43 | inst.aabbIsDirty = false; 44 | //printf("Inst %u: (%g, %g, %g) - (%g, %g, %g)\n", 45 | // instIndex, 46 | // inst.childAabb.minP.x, inst.childAabb.minP.y, inst.childAabb.minP.z, 47 | // inst.childAabb.maxP.x, inst.childAabb.maxP.y, inst.childAabb.maxP.z); 48 | } 49 | } 50 | 51 | CUDA_DEVICE_KERNEL void computeSceneAABB(const Instance* instances, uint32_t numInstances, 52 | SceneBounds* sceneBounds) { 53 | uint32_t globalIndex = blockDim.x * blockIdx.x + threadIdx.x; 54 | if (globalIndex >= numInstances) 55 | return; 56 | 57 | CUDA_SHARED_MEM uint32_t b_mem[sizeof(BoundingBox3DAsOrderedInt) / 4]; 58 | auto &b_AabbAsInt = reinterpret_cast(b_mem); 59 | if (threadIdx.x == 0) 60 | b_AabbAsInt = BoundingBox3DAsOrderedInt(); 61 | 62 | uint32_t instIndex = globalIndex; 63 | const Instance &inst = instances[instIndex]; 64 | BoundingBox3DAsOrderedInt aabbAsInt; 65 | if (inst.isActive) { 66 | //printf("Pre Xfm Inst %u: (%g, %g, %g) - (%g, %g, %g)\n", 67 | // instIndex, 68 | // inst.childAabb.minP.x, inst.childAabb.minP.y, inst.childAabb.minP.z, 69 | // inst.childAabb.maxP.x, inst.childAabb.maxP.y, inst.childAabb.maxP.z); 70 | BoundingBox3D aabb = inst.transform * inst.childAabb; 71 | aabbAsInt = aabb; 72 | } 73 | 74 | __syncthreads(); 75 | atomicUnifyBoundingBox3D_block(&b_AabbAsInt, aabbAsInt); 76 | __syncthreads(); 77 | if (threadIdx.x == 0) { 78 | atomicUnifyBoundingBox3D(&sceneBounds->aabbAsInt, b_AabbAsInt); 79 | } 80 | } 81 | 82 | CUDA_DEVICE_KERNEL void finalizeSceneBounds(SceneBounds* sceneBounds) { 83 | uint32_t globalIndex = blockDim.x * blockIdx.x + threadIdx.x; 84 | if (globalIndex >= 1) 85 | return; 86 | 87 | BoundingBox3D sceneAabb = static_cast(sceneBounds->aabbAsInt); 88 | sceneBounds->aabb = sceneAabb; 89 | sceneBounds->center = sceneAabb.centroid(); 90 | sceneBounds->worldRadius = (sceneAabb.maxP - sceneBounds->center).length(); 91 | sceneBounds->worldDiscArea = VLR_M_PI * pow2(sceneBounds->worldRadius); 92 | } 93 | } 94 | -------------------------------------------------------------------------------- /libVLR/GPU_kernels/triangle.cu: -------------------------------------------------------------------------------- 1 | #include "../shared/kernel_common.h" 2 | 3 | namespace vlr { 4 | using namespace shared; 5 | 6 | RT_CALLABLE_PROGRAM void RT_DC_NAME(decodeLocalHitPointForTriangle)( 7 | const HitPointParameter ¶m, SurfacePoint* surfPt, float* hypAreaPDF) { 8 | const GeometryInstance &geomInst = param.sbtr->geomInst; 9 | 10 | const Triangle &triangle = geomInst.asTriMesh.triangleBuffer[param.primIndex]; 11 | const Vertex &v0 = geomInst.asTriMesh.vertexBuffer[triangle.index0]; 12 | const Vertex &v1 = geomInst.asTriMesh.vertexBuffer[triangle.index1]; 13 | const Vertex &v2 = geomInst.asTriMesh.vertexBuffer[triangle.index2]; 14 | 15 | Vector3D e1 = v1.position - v0.position; 16 | Vector3D e2 = v2.position - v0.position; 17 | Normal3D geometricNormal = cross(e1, e2); 18 | float area = geometricNormal.length() / 2; // TODO: スケーリングの考慮。 19 | geometricNormal /= 2 * area; 20 | 21 | // JP: プログラムがこの点を光源としてサンプルする場合の面積に関する(仮想的な)PDFを求める。 22 | // EN: calculate a hypothetical area PDF value in the case where the program sample this point as light. 23 | float probLightPrim = area / geomInst.asTriMesh.primDistribution.integral(); 24 | *hypAreaPDF = probLightPrim / area; 25 | 26 | float b0 = 1 - param.b1 - param.b2, b1 = param.b1, b2 = param.b2; 27 | Point3D position = b0 * v0.position + b1 * v1.position + b2 * v2.position; 28 | Normal3D shadingNormal = normalize(b0 * v0.normal + b1 * v1.normal + b2 * v2.normal); 29 | Vector3D tc0Direction = b0 * v0.tc0Direction + b1 * v1.tc0Direction + b2 * v2.tc0Direction; 30 | if (!shadingNormal.allFinite() || !tc0Direction.allFinite()) { 31 | Vector3D bitangent; 32 | shadingNormal = geometricNormal; 33 | shadingNormal.makeCoordinateSystem(&tc0Direction, &bitangent); 34 | } 35 | TexCoord2D texCoord = b0 * v0.texCoord + b1 * v1.texCoord + b2 * v2.texCoord; 36 | 37 | // JP: 法線と接線が直交することを保証する。 38 | // 直交性の消失は重心座標補間によっておこる? 39 | // EN: guarantee the orthogonality between the normal and tangent. 40 | // Orthogonality break might be caused by barycentric interpolation? 41 | float dotNT = dot(shadingNormal, tc0Direction); 42 | tc0Direction = tc0Direction - dotNT * shadingNormal; 43 | 44 | surfPt->position = position; 45 | surfPt->shadingFrame.x = tc0Direction; 46 | surfPt->shadingFrame.z = shadingNormal; 47 | surfPt->isPoint = false; 48 | surfPt->atInfinity = false; 49 | surfPt->geometricNormal = geometricNormal; 50 | surfPt->u = b0; 51 | surfPt->v = b1; 52 | surfPt->texCoord = texCoord; 53 | } 54 | 55 | RT_CALLABLE_PROGRAM void RT_DC_NAME(decodeHitPointForTriangle)( 56 | uint32_t instIndex, uint32_t geomInstIndex, uint32_t primIndex, 57 | float u, float v, 58 | SurfacePoint* surfPt) { 59 | const Instance &inst = plp.instBuffer[instIndex]; 60 | const GeometryInstance &geomInst = plp.geomInstBuffer[geomInstIndex]; 61 | 62 | const Triangle &triangle = geomInst.asTriMesh.triangleBuffer[primIndex]; 63 | const Vertex &v0 = geomInst.asTriMesh.vertexBuffer[triangle.index0]; 64 | const Vertex &v1 = geomInst.asTriMesh.vertexBuffer[triangle.index1]; 65 | const Vertex &v2 = geomInst.asTriMesh.vertexBuffer[triangle.index2]; 66 | 67 | const StaticTransform &transform = inst.transform; 68 | 69 | Vector3D e1 = transform * (v1.position - v0.position); 70 | Vector3D e2 = transform * (v2.position - v0.position); 71 | Normal3D geometricNormal = cross(e1, e2); 72 | float area = geometricNormal.length() / 2; // TODO: スケーリングの考慮。 73 | geometricNormal /= 2 * area; 74 | 75 | float b0 = u, b1 = v, b2 = 1.0f - u - v; 76 | Point3D position = b0 * v0.position + b1 * v1.position + b2 * v2.position; 77 | Normal3D shadingNormal = b0 * v0.normal + b1 * v1.normal + b2 * v2.normal; 78 | Vector3D tc0Direction = b0 * v0.tc0Direction + b1 * v1.tc0Direction + b2 * v2.tc0Direction; 79 | TexCoord2D texCoord = b0 * v0.texCoord + b1 * v1.texCoord + b2 * v2.texCoord; 80 | 81 | position = transform * position; 82 | shadingNormal = normalize(transform * shadingNormal); 83 | tc0Direction = transform * tc0Direction; 84 | if (!shadingNormal.allFinite() || !tc0Direction.allFinite()) { 85 | Vector3D bitangent; 86 | shadingNormal = geometricNormal; 87 | shadingNormal.makeCoordinateSystem(&tc0Direction, &bitangent); 88 | } 89 | 90 | // JP: 法線と接線が直交することを保証する。 91 | // 直交性の消失は重心座標補間によっておこる? 92 | // EN: guarantee the orthogonality between the normal and tangent. 93 | // Orthogonality break might be caused by barycentric interpolation? 94 | float dotNT = dot(shadingNormal, tc0Direction); 95 | tc0Direction = normalize(tc0Direction - dotNT * shadingNormal); 96 | 97 | surfPt->instIndex = instIndex; 98 | surfPt->geomInstIndex = geomInstIndex; 99 | surfPt->primIndex = primIndex; 100 | 101 | surfPt->position = position; 102 | surfPt->shadingFrame = ReferenceFrame(tc0Direction, shadingNormal); 103 | surfPt->isPoint = false; 104 | surfPt->atInfinity = false; 105 | surfPt->geometricNormal = geometricNormal; 106 | surfPt->u = b0; 107 | surfPt->v = b1; 108 | surfPt->texCoord = texCoord; 109 | } 110 | 111 | 112 | 113 | RT_CALLABLE_PROGRAM void RT_DC_NAME(sampleTriangleMesh)( 114 | uint32_t instIndex, uint32_t geomInstIndex, 115 | const SurfaceLightPosSample &sample, const Point3D &shadingPoint, 116 | SurfaceLightPosQueryResult* result) { 117 | (void)shadingPoint; 118 | 119 | const Instance &inst = plp.instBuffer[instIndex]; 120 | const GeometryInstance &geomInst = plp.geomInstBuffer[geomInstIndex]; 121 | 122 | float primProb; 123 | uint32_t primIdx = geomInst.asTriMesh.primDistribution.sample(sample.uElem, &primProb); 124 | //printf("%g, %u, %g\n", sample.uElem, primIdx, primProb); 125 | 126 | const Triangle &triangle = geomInst.asTriMesh.triangleBuffer[primIdx]; 127 | const Vertex &v0 = geomInst.asTriMesh.vertexBuffer[triangle.index0]; 128 | const Vertex &v1 = geomInst.asTriMesh.vertexBuffer[triangle.index1]; 129 | const Vertex &v2 = geomInst.asTriMesh.vertexBuffer[triangle.index2]; 130 | 131 | const StaticTransform &transform = inst.transform; 132 | 133 | Vector3D e1 = transform * (v1.position - v0.position); 134 | Vector3D e2 = transform * (v2.position - v0.position); 135 | Normal3D geometricNormal = cross(e1, e2); 136 | float area = geometricNormal.length() / 2; 137 | geometricNormal /= 2 * area; 138 | 139 | result->areaPDF = primProb / area; 140 | result->posType = DirectionType::Emission() | DirectionType::LowFreq(); 141 | result->materialIndex = geomInst.materialIndex; 142 | 143 | float b0, b1, b2; 144 | uniformSampleTriangle(sample.uPos[0], sample.uPos[1], &b0, &b1); 145 | b2 = 1.0f - b0 - b1; 146 | 147 | Point3D position = b0 * v0.position + b1 * v1.position + b2 * v2.position; 148 | Normal3D shadingNormal = b0 * v0.normal + b1 * v1.normal + b2 * v2.normal; 149 | Vector3D tc0Direction = b0 * v0.tc0Direction + b1 * v1.tc0Direction + b2 * v2.tc0Direction; 150 | TexCoord2D texCoord = b0 * v0.texCoord + b1 * v1.texCoord + b2 * v2.texCoord; 151 | 152 | position = transform * position; 153 | shadingNormal = normalize(transform * shadingNormal); 154 | tc0Direction = transform * tc0Direction; 155 | 156 | // JP: 法線と接線が直交することを保証する。 157 | // 直交性の消失は重心座標補間によっておこる? 158 | // EN: guarantee the orthogonality between the normal and tangent. 159 | // Orthogonality break might be caused by barycentric interpolation? 160 | float dotNT = dot(shadingNormal, tc0Direction); 161 | tc0Direction = normalize(tc0Direction - dotNT * shadingNormal); 162 | 163 | SurfacePoint &surfPt = result->surfPt; 164 | 165 | surfPt.instIndex = instIndex; 166 | surfPt.geomInstIndex = geomInstIndex; 167 | surfPt.primIndex = primIdx; 168 | 169 | surfPt.position = position; 170 | surfPt.shadingFrame = ReferenceFrame(tc0Direction, shadingNormal); 171 | surfPt.isPoint = false; 172 | surfPt.atInfinity = false; 173 | surfPt.geometricNormal = geometricNormal; 174 | surfPt.u = b0; 175 | surfPt.v = b1; 176 | surfPt.texCoord = texCoord; 177 | } 178 | } 179 | -------------------------------------------------------------------------------- /libVLR/common.cpp: -------------------------------------------------------------------------------- 1 | #include "shared/common_internal.h" 2 | 3 | #if defined(VLR_Platform_Windows_MSVC) 4 | VLR_CPP_API void vlrDevPrintf(const char* fmt, ...) { 5 | va_list args; 6 | va_start(args, fmt); 7 | char str[4096]; 8 | vsprintf_s(str, fmt, args); 9 | va_end(args); 10 | OutputDebugString(str); 11 | } 12 | #endif 13 | 14 | VLR_CPP_API void vlrprintf(const char* fmt, ...) { 15 | va_list args; 16 | va_start(args, fmt); 17 | char str[4096]; 18 | vsprintf_s(str, fmt, args); 19 | va_end(args); 20 | 21 | # if defined(VLR_USE_DEVPRINTF) && defined(VLR_Platform_Windows_MSVC) 22 | vlrDevPrintf("%s", str); 23 | # endif 24 | printf("%s", str); 25 | } 26 | 27 | namespace vlr { 28 | // TODO: Make this function thread-safe. 29 | std::filesystem::path getExecutableDirectory() { 30 | static std::filesystem::path ret; 31 | 32 | static bool done = false; 33 | if (!done) { 34 | #if defined(VLR_Platform_Windows_MSVC) 35 | TCHAR filepath[1024]; 36 | auto length = GetModuleFileName(NULL, filepath, 1024); 37 | VLRAssert(length > 0, "Failed to query the executable path."); 38 | 39 | ret = filepath; 40 | #else 41 | static_assert(false, "Not implemented"); 42 | #endif 43 | ret = ret.remove_filename(); 44 | 45 | done = true; 46 | } 47 | 48 | return ret; 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /libVLR/image.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "queryable.h" 4 | 5 | namespace vlr { 6 | struct RGB8x3 { uint8_t r, g, b; }; 7 | struct RGB_8x4 { uint8_t r, g, b, dummy; }; 8 | struct RGBA8x4 { uint8_t r, g, b, a; }; 9 | struct RGBA16Fx4 { half r, g, b, a; }; 10 | struct RGBA32Fx4 { float r, g, b, a; }; 11 | struct RG32Fx2 { float r, g; }; 12 | struct Gray32F { float v; }; 13 | struct Gray8 { uint8_t v; }; 14 | struct GrayA8x2 { uint8_t v; uint8_t a; }; 15 | struct uvsA8x4 { uint8_t u, v, s, a; }; 16 | struct uvsA16Fx4 { half u, v, s, a; }; 17 | 18 | extern const size_t sizesOfDataFormats[static_cast(DataFormat::NumFormats)]; 19 | 20 | uint32_t getComponentStartIndex(DataFormat dataFormat, BumpType bumpType, ShaderNodePlugType ptype, uint32_t index); 21 | 22 | class Image2D : public Queryable { 23 | uint32_t m_width, m_height; 24 | DataFormat m_originalDataFormat; 25 | DataFormat m_dataFormat; 26 | bool m_needsHW_sRGB_degamma; 27 | SpectrumType m_spectrumType; 28 | ColorSpace m_colorSpace; 29 | 30 | protected: 31 | mutable cudau::Array m_optixDataBuffer; 32 | 33 | public: 34 | VLR_DECLARE_TYPE_AWARE_CLASS_INTERFACE(); 35 | 36 | static void initialize(Context &context); 37 | static void finalize(Context &context); 38 | 39 | static DataFormat getInternalFormat(DataFormat inputFormat, SpectrumType spectrumType); 40 | 41 | Image2D(Context &context, uint32_t width, uint32_t height, 42 | DataFormat originalDataFormat, SpectrumType spectrumType, ColorSpace colorSpace); 43 | virtual ~Image2D(); 44 | 45 | virtual Image2D* createShrinkedImage2D(uint32_t width, uint32_t height) const = 0; 46 | virtual Image2D* createLuminanceImage2D() const = 0; 47 | virtual void* createLinearImageData() const = 0; 48 | 49 | uint32_t getWidth() const { 50 | return m_width; 51 | } 52 | uint32_t getHeight() const { 53 | return m_height; 54 | } 55 | uint32_t getStride() const { 56 | return static_cast(sizesOfDataFormats[static_cast(m_dataFormat)]); 57 | } 58 | DataFormat getDataFormat() const { 59 | return m_dataFormat; 60 | } 61 | DataFormat getOriginalDataFormat() const { 62 | return m_originalDataFormat; 63 | } 64 | bool originalHasAlpha() const { 65 | return (m_originalDataFormat == DataFormat::RGBA8x4 || 66 | m_originalDataFormat == DataFormat::RGBA16Fx4 || 67 | m_originalDataFormat == DataFormat::RGBA32Fx4 || 68 | m_originalDataFormat == DataFormat::GrayA8x2 || 69 | m_originalDataFormat == DataFormat::BC1 || 70 | m_originalDataFormat == DataFormat::BC2 || 71 | m_originalDataFormat == DataFormat::BC3 || 72 | m_originalDataFormat == DataFormat::BC7); 73 | } 74 | bool needsHW_sRGB_degamma() const { 75 | return m_needsHW_sRGB_degamma; 76 | } 77 | SpectrumType getSpectrumType() const { 78 | return m_spectrumType; 79 | } 80 | ColorSpace getColorSpace() const { 81 | return m_colorSpace; 82 | } 83 | 84 | virtual const cudau::Array &getOptiXObject() const; 85 | }; 86 | 87 | 88 | 89 | class LinearImage2D : public Image2D { 90 | VLR_DECLARE_QUERYABLE_INTERFACE(); 91 | 92 | std::vector m_data; 93 | mutable bool m_copyDone; 94 | 95 | public: 96 | VLR_DECLARE_TYPE_AWARE_CLASS_INTERFACE(); 97 | 98 | static void initialize(Context &context); 99 | static void finalize(Context &context); 100 | 101 | // JP: "linearData" はメモリ上のレイアウトがリニアであることを意味しており、ガンマカーブ云々を表しているのではない。 102 | // EN: "linearData" means data layout is linear, it doesn't mean gamma curve. 103 | LinearImage2D(Context &context, const uint8_t* linearData, uint32_t width, uint32_t height, 104 | DataFormat dataFormat, SpectrumType spectrumType, ColorSpace colorSpace); 105 | 106 | template 107 | PixelType get(uint32_t x, uint32_t y) const { 108 | return *reinterpret_cast(m_data.data() + (y * getWidth() + x) * getStride()); 109 | } 110 | 111 | Image2D* createShrinkedImage2D(uint32_t width, uint32_t height) const override; 112 | Image2D* createLuminanceImage2D() const override; 113 | void* createLinearImageData() const override; 114 | 115 | const cudau::Array &getOptiXObject() const override; 116 | }; 117 | 118 | 119 | 120 | class BlockCompressedImage2D : public Image2D { 121 | VLR_DECLARE_QUERYABLE_INTERFACE(); 122 | 123 | std::vector> m_data; 124 | mutable bool m_copyDone; 125 | 126 | public: 127 | VLR_DECLARE_TYPE_AWARE_CLASS_INTERFACE(); 128 | 129 | static void initialize(Context &context); 130 | static void finalize(Context &context); 131 | 132 | BlockCompressedImage2D(Context &context, const uint8_t* const* data, const size_t* sizes, uint32_t mipCount, uint32_t width, uint32_t height, 133 | DataFormat dataFormat, SpectrumType spectrumType, ColorSpace colorSpace); 134 | 135 | Image2D* createShrinkedImage2D(uint32_t width, uint32_t height) const override; 136 | Image2D* createLuminanceImage2D() const override; 137 | void* createLinearImageData() const override; 138 | 139 | const cudau::Array &getOptiXObject() const override; 140 | }; 141 | } 142 | -------------------------------------------------------------------------------- /libVLR/include/vlr/common.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #if !defined(VLR_Device) 4 | # define VLR_Host 5 | #endif 6 | 7 | // Platform defines 8 | #if defined(VLR_Host) 9 | # if defined(_WIN32) || defined(_WIN64) 10 | # define VLR_Platform_Windows 11 | # if defined(_MSC_VER) 12 | # define VLR_Platform_Windows_MSVC 13 | # endif 14 | # elif defined(__APPLE__) 15 | # define VLR_Platform_macOS 16 | # endif 17 | #endif 18 | 19 | #if defined(VLR_Platform_Windows_MSVC) 20 | # define NOMINMAX 21 | # define _USE_MATH_DEFINES 22 | # include 23 | # undef near 24 | # undef far 25 | # undef RGB 26 | # if defined(VLR_API_EXPORTS) 27 | # define VLR_CPP_API __declspec(dllexport) 28 | # else 29 | # define VLR_CPP_API __declspec(dllimport) 30 | # endif 31 | #else 32 | # define VLR_CPP_API 33 | #endif 34 | 35 | #define VLR_M_PI 3.14159265358979323846f 36 | #ifndef VLR_HUGE_ENUF 37 | # define VLR_HUGE_ENUF 1e+300 // VLR_HUGE_ENUF*VLR_HUGE_ENUF must overflow 38 | #endif 39 | #define VLR_INFINITY ((float)(VLR_HUGE_ENUF * VLR_HUGE_ENUF)) 40 | #define VLR_NAN ((float)(VLR_INFINITY * 0.0f)) 41 | 42 | #define VLR_USE_DEVPRINTF 43 | 44 | #if defined(VLR_Host) 45 | 46 | #include 47 | #include 48 | #include 49 | 50 | #endif 51 | 52 | #include 53 | #include 54 | #include 55 | #include 56 | 57 | #if defined(DEBUG) 58 | # define ENABLE_ASSERT 59 | #endif 60 | 61 | // vlrDevPrintf / vlrprintf 62 | #if defined(VLR_Host) 63 | # if defined(VLR_Platform_Windows_MSVC) 64 | VLR_CPP_API void vlrDevPrintf(const char* fmt, ...); 65 | # else 66 | # define vlrDevPrintf(fmt, ...) printf(fmt, ##__VA_ARGS__) 67 | # endif 68 | 69 | VLR_CPP_API void vlrprintf(const char* fmt, ...); 70 | #endif 71 | 72 | #if defined(ENABLE_ASSERT) 73 | # if defined(VLR_Host) 74 | # define VLRAssert(expr, fmt, ...) do { if (!(expr)) { vlrDevPrintf("%s @%s: %u:\n", #expr, __FILE__, __LINE__); vlrDevPrintf(fmt"\n", ##__VA_ARGS__); abort(); } } while (0) 75 | # else 76 | # define VLRAssert(expr, fmt, ...) do { if (!(expr)) { vlrDevPrintf("%s @%s: %u:\n", #expr, __FILE__, __LINE__); vlrDevPrintf(fmt"\n", ##__VA_ARGS__); assert(false); } } while (0) 77 | # endif 78 | #else 79 | # define VLRAssert(expr, fmt, ...) 80 | #endif 81 | 82 | #define VLRUnused(var) (void)var 83 | 84 | #define VLRAssert_ShouldNotBeCalled() VLRAssert(false, "Should not be called!") 85 | #define VLRAssert_NotImplemented() VLRAssert(false, "Not implemented yet!") 86 | 87 | #define VLR3DPrint(v) v.x, v.y, v.z 88 | 89 | 90 | 91 | #if defined(VLR_Host) 92 | # define CUDA_DEVICE_FUNCTION inline 93 | # define HOST_STATIC_CONSTEXPR static constexpr 94 | #else 95 | # define CUDA_DEVICE_FUNCTION __device__ __forceinline__ 96 | # define HOST_STATIC_CONSTEXPR 97 | #endif 98 | 99 | namespace vlr { 100 | // Naming this function as "swap" causes a weird MSVC error C2668 (MSVC 16.11.8). 101 | template 102 | CUDA_DEVICE_FUNCTION constexpr void _swap(T &a, T &b) { 103 | T temp = std::move(a); 104 | a = std::move(b); 105 | b = std::move(temp); 106 | } 107 | 108 | template 109 | CUDA_DEVICE_FUNCTION constexpr T min(const T a, const T b) { 110 | return a < b ? a : b; 111 | } 112 | 113 | template 114 | CUDA_DEVICE_FUNCTION constexpr T max(const T a, const T b) { 115 | return a > b ? a : b; 116 | } 117 | 118 | template 119 | CUDA_DEVICE_FUNCTION constexpr T clamp(const T v, const T minv, const T maxv) { 120 | return ::vlr::min(::vlr::max(v, minv), maxv); 121 | } 122 | 123 | template 124 | CUDA_DEVICE_FUNCTION T floor(T x) { 125 | return std::floor(x); 126 | } 127 | 128 | template 129 | CUDA_DEVICE_FUNCTION T isinf(T x) { 130 | return std::isinf(x); 131 | } 132 | 133 | template 134 | CUDA_DEVICE_FUNCTION T isnan(T x) { 135 | return std::isnan(x); 136 | } 137 | 138 | template 139 | CUDA_DEVICE_FUNCTION T isfinite(T x) { 140 | return std::isfinite(x); 141 | } 142 | 143 | template 144 | CUDA_DEVICE_FUNCTION void sincos(T angle, T* s, T* c) { 145 | *s = std::sin(angle); 146 | *c = std::cos(angle); 147 | } 148 | 149 | #if defined(VLR_Device) || defined(__INTELLISENSE__) 150 | template <> 151 | CUDA_DEVICE_FUNCTION float floor(float x) { 152 | return ::floorf(x); 153 | } 154 | 155 | template <> 156 | CUDA_DEVICE_FUNCTION float isinf(float x) { 157 | return ::isinf(x); 158 | } 159 | 160 | template <> 161 | CUDA_DEVICE_FUNCTION float isnan(float x) { 162 | return ::isnan(x); 163 | } 164 | 165 | template <> 166 | CUDA_DEVICE_FUNCTION float isfinite(float x) { 167 | return ::isfinite(x); 168 | } 169 | 170 | template <> 171 | CUDA_DEVICE_FUNCTION void sincos(float angle, float* s, float* c) { 172 | ::sincosf(angle, s, c); 173 | } 174 | #endif 175 | } -------------------------------------------------------------------------------- /libVLR/include/vlr/public_types.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #if defined(__cplusplus) 4 | #include 5 | #else 6 | #include 7 | #include 8 | #endif 9 | 10 | enum VLRParameterFormFlag { 11 | VLRParameterFormFlag_ImmediateValue = 1 << 0, 12 | VLRParameterFormFlag_Node = 1 << 1, 13 | VLRParameterFormFlag_Both = (VLRParameterFormFlag_ImmediateValue | VLRParameterFormFlag_Node) 14 | }; 15 | 16 | enum VLRShaderNodePlugType { 17 | VLRShaderNodePlugType_float1 = 0, 18 | VLRShaderNodePlugType_float2, 19 | VLRShaderNodePlugType_float3, 20 | VLRShaderNodePlugType_float4, 21 | VLRShaderNodePlugType_Point3D, 22 | VLRShaderNodePlugType_Vector3D, 23 | VLRShaderNodePlugType_Normal3D, 24 | VLRShaderNodePlugType_Spectrum, 25 | VLRShaderNodePlugType_Alpha, 26 | VLRShaderNodePlugType_TextureCoordinates, 27 | NumVLRShaderNodePlugTypes 28 | }; 29 | 30 | struct VLRShaderNodePlug { 31 | uintptr_t nodeRef; 32 | uint32_t info; 33 | }; 34 | 35 | 36 | 37 | enum VLRRenderer { 38 | VLRRenderer_PathTracing = 0, 39 | VLRRenderer_LightTracing, 40 | VLRRenderer_BPT, 41 | VLRRenderer_DebugRendering, 42 | }; 43 | 44 | enum VLRDebugRenderingMode { 45 | VLRDebugRenderingMode_BaseColor = 0, 46 | VLRDebugRenderingMode_GeometricNormal, 47 | VLRDebugRenderingMode_ShadingTangent, 48 | VLRDebugRenderingMode_ShadingBitangent, 49 | VLRDebugRenderingMode_ShadingNormal, 50 | VLRDebugRenderingMode_TextureCoordinates, 51 | VLRDebugRenderingMode_ShadingNormalViewCos, 52 | VLRDebugRenderingMode_GeometricVsShadingNormal, 53 | VLRDebugRenderingMode_ShadingFrameLengths, 54 | VLRDebugRenderingMode_ShadingFrameOrthogonality, 55 | VLRDebugRenderingMode_DenoiserAlbedo, 56 | VLRDebugRenderingMode_DenoiserNormal, 57 | }; 58 | 59 | #if !defined(__cplusplus) 60 | typedef enum VLRParameterFormFlag VLRParameterFormFlag; 61 | typedef enum VLRShaderNodePlugType VLRShaderNodePlugType; 62 | typedef struct VLRShaderNodePlug VLRShaderNodePlug; 63 | typedef enum VLRDebugRenderingMode VLRDebugRenderingMode; 64 | typedef enum VLRRenderer VLRRenderer; 65 | #endif 66 | 67 | 68 | 69 | struct VLRImmediateSpectrum { 70 | const char* colorSpace; 71 | float e0; 72 | float e1; 73 | float e2; 74 | }; 75 | 76 | struct VLRPoint3D { 77 | float x, y, z; 78 | }; 79 | 80 | struct VLRNormal3D { 81 | float x, y, z; 82 | }; 83 | 84 | struct VLRVector3D { 85 | float x, y, z; 86 | }; 87 | 88 | struct VLRTexCoord2D { 89 | float u, v; 90 | }; 91 | 92 | struct VLRQuaternion { 93 | float x, y, z, w; 94 | }; 95 | 96 | #if !defined(__cplusplus) 97 | typedef struct VLRImmediateSpectrum VLRImmediateSpectrum; 98 | typedef struct VLRPoint3D VLRPoint3D; 99 | typedef struct VLRNormal3D VLRNormal3D; 100 | typedef struct VLRVector3D VLRVector3D; 101 | typedef struct VLRTexCoord2D VLRTexCoord2D; 102 | typedef struct VLRQuaternion VLRQuaternion; 103 | #endif 104 | 105 | 106 | 107 | struct VLRVertex { 108 | VLRPoint3D position; 109 | VLRNormal3D normal; 110 | VLRVector3D tc0Direction; 111 | VLRTexCoord2D texCoord; 112 | }; 113 | 114 | #if !defined(__cplusplus) 115 | typedef struct VLRVertex VLRVertex; 116 | #endif 117 | 118 | 119 | 120 | #define VLR_PROCESS_CLASS_LIST() \ 121 | VLR_PROCESS_CLASS(Object); \ 122 | \ 123 | VLR_PROCESS_CLASS(ParameterInfo); \ 124 | \ 125 | VLR_PROCESS_CLASS(Queryable); \ 126 | \ 127 | VLR_PROCESS_CLASS(Image2D); \ 128 | VLR_PROCESS_CLASS(LinearImage2D); \ 129 | VLR_PROCESS_CLASS(BlockCompressedImage2D); \ 130 | \ 131 | VLR_PROCESS_CLASS(ShaderNode); \ 132 | \ 133 | VLR_PROCESS_CLASS(SurfaceMaterial); \ 134 | \ 135 | VLR_PROCESS_CLASS(Transform); \ 136 | VLR_PROCESS_CLASS(StaticTransform); \ 137 | \ 138 | VLR_PROCESS_CLASS(Node); \ 139 | VLR_PROCESS_CLASS(SurfaceNode); \ 140 | VLR_PROCESS_CLASS(TriangleMeshSurfaceNode); \ 141 | VLR_PROCESS_CLASS(PointSurfaceNode); \ 142 | VLR_PROCESS_CLASS(ParentNode); \ 143 | VLR_PROCESS_CLASS(InternalNode); \ 144 | VLR_PROCESS_CLASS(Scene); \ 145 | \ 146 | VLR_PROCESS_CLASS(Camera); 147 | -------------------------------------------------------------------------------- /libVLR/libVLR.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | Shared 10 | 11 | 12 | Shared 13 | 14 | 15 | 16 | 17 | 18 | 19 | Utilities 20 | 21 | 22 | Utilities 23 | 24 | 25 | API 26 | 27 | 28 | ext\gl3w 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | API 38 | 39 | 40 | Shared 41 | 42 | 43 | Shared 44 | 45 | 46 | Shared 47 | 48 | 49 | Shared 50 | 51 | 52 | Shared 53 | 54 | 55 | Shared 56 | 57 | 58 | Shared 59 | 60 | 61 | Shared 62 | 63 | 64 | 65 | 66 | 67 | Utilities 68 | 69 | 70 | Utilities 71 | 72 | 73 | Utilities 74 | 75 | 76 | Utilities 77 | 78 | 79 | Shared 80 | 81 | 82 | API 83 | 84 | 85 | API 86 | 87 | 88 | Shared 89 | 90 | 91 | Shared 92 | 93 | 94 | Shared 95 | 96 | 97 | ext\gl3w 98 | 99 | 100 | ext\gl3w 101 | 102 | 103 | ext\gl3w 104 | 105 | 106 | 107 | 108 | {cd8adf6e-4acf-43fa-89da-8cff4a35f48b} 109 | 110 | 111 | {e2341fa3-8b02-4d88-bd27-8911d42f9713} 112 | 113 | 114 | {5b29098c-54b2-455f-a988-5afcf02f08ea} 115 | 116 | 117 | {626b6b12-ff56-4992-a1bc-68f887ae2bc8} 118 | 119 | 120 | {a77135d7-bb62-437c-ab23-139546fd8996} 121 | 122 | 123 | {e05f5822-db6a-49c1-9039-5b4c30e5f0c7} 124 | 125 | 126 | {1a6a3f67-18ee-4950-82f9-85e1c1ce1c1d} 127 | 128 | 129 | 130 | 131 | GPU Kernels 132 | 133 | 134 | GPU Kernels 135 | 136 | 137 | GPU Kernels 138 | 139 | 140 | GPU Kernels 141 | 142 | 143 | GPU Kernels 144 | 145 | 146 | GPU Kernels 147 | 148 | 149 | GPU Kernels 150 | 151 | 152 | GPU Kernels 153 | 154 | 155 | GPU Kernels 156 | 157 | 158 | GPU Kernels 159 | 160 | 161 | GPU Kernels 162 | 163 | 164 | GPU Kernels 165 | 166 | 167 | GPU Kernels 168 | 169 | 170 | 171 | 172 | files to copy 173 | 174 | 175 | files to copy 176 | 177 | 178 | -------------------------------------------------------------------------------- /libVLR/queryable.cpp: -------------------------------------------------------------------------------- 1 | #include "queryable.h" 2 | 3 | namespace vlr { 4 | bool testParamName(const std::string& paramNameA, const std::string& paramNameB) { 5 | return tolower(paramNameA) == tolower(paramNameB); 6 | } 7 | 8 | 9 | 10 | const char* ParameterFloat = "Float"; 11 | const char* ParameterPoint3D = "Point3D"; 12 | const char* ParameterVector3D = "Vector3D"; 13 | const char* ParameterNormal3D = "Normal3D"; 14 | const char* ParameterQuaternion = "Quaternion"; 15 | const char* ParameterSpectrum = "Spectrum"; 16 | const char* ParameterAlpha = "Alpha"; 17 | const char* ParameterTextureCoordinates = "TextureCoordinates"; 18 | 19 | const char* ParameterImage = "Image"; 20 | const char* ParameterSurfaceMaterial = "SurfaceMaterial"; 21 | 22 | const char* EnumSpectrumType = "SpectrumType"; 23 | const char* EnumColorSpace = "ColorSpace"; 24 | const char* EnumDataFormat = "DataFormat"; 25 | const char* EnumBumpType = "BumpType"; 26 | const char* EnumTextureFilter = "TextureFilter"; 27 | const char* EnumTextureWrapMode = "TextureWrapMode"; 28 | const char* EnumTangentType = "TangentType"; 29 | 30 | static bool s_enumTableInitialized = false; 31 | static const std::unordered_map>> s_enumTables = { 32 | { 33 | EnumSpectrumType, { 34 | {"Reflectance", static_cast(SpectrumType::Reflectance)}, 35 | {"Transmittance", static_cast(SpectrumType::Transmittance)}, 36 | {"Light Source", static_cast(SpectrumType::LightSource)}, 37 | {"NA", static_cast(SpectrumType::NA)}, 38 | } 39 | }, 40 | { 41 | EnumColorSpace, { 42 | {"Rec709(D65) sRGB Gamma", static_cast(ColorSpace::Rec709_D65_sRGBGamma)}, 43 | {"Rec709(D65)", static_cast(ColorSpace::Rec709_D65)}, 44 | {"XYZ", static_cast(ColorSpace::XYZ)}, 45 | {"xyY", static_cast(ColorSpace::xyY)}, 46 | } 47 | }, 48 | { 49 | EnumDataFormat, { 50 | {"RGB8x3", static_cast(DataFormat::RGB8x3)}, 51 | {"RGB_8x4", static_cast(DataFormat::RGB_8x4)}, 52 | {"RGBA8x4", static_cast(DataFormat::RGBA8x4)}, 53 | {"RGBA16Fx4", static_cast(DataFormat::RGBA16Fx4)}, 54 | {"RGBA32Fx4", static_cast(DataFormat::RGBA32Fx4)}, 55 | {"RG32Fx2", static_cast(DataFormat::RG32Fx2)}, 56 | {"Gray32F", static_cast(DataFormat::Gray32F)}, 57 | {"Gray8", static_cast(DataFormat::Gray8)}, 58 | {"GrayA8x2", static_cast(DataFormat::GrayA8x2)}, 59 | {"BC1", static_cast(DataFormat::BC1)}, 60 | {"BC2", static_cast(DataFormat::BC2)}, 61 | {"BC3", static_cast(DataFormat::BC3)}, 62 | {"BC4", static_cast(DataFormat::BC4)}, 63 | {"BC4_Signed", static_cast(DataFormat::BC4_Signed)}, 64 | {"BC5", static_cast(DataFormat::BC5)}, 65 | {"BC5_Signed", static_cast(DataFormat::BC5_Signed)}, 66 | {"BC6H", static_cast(DataFormat::BC6H)}, 67 | {"BC6H_Signed", static_cast(DataFormat::BC6H_Signed)}, 68 | {"BC7", static_cast(DataFormat::BC7)}, 69 | } 70 | }, 71 | { 72 | EnumBumpType, { 73 | {"Normal Map (DirectX)", static_cast(BumpType::NormalMap_DirectX)}, 74 | {"Normal Map (OpenGL)", static_cast(BumpType::NormalMap_OpenGL)}, 75 | {"Height Map", static_cast(BumpType::HeightMap)}, 76 | } 77 | }, 78 | { 79 | EnumTextureFilter, { 80 | {"Nearest", static_cast(TextureFilter::Nearest)}, 81 | {"Linear", static_cast(TextureFilter::Linear)}, 82 | {"None", static_cast(TextureFilter::None)}, 83 | } 84 | }, 85 | { 86 | EnumTextureWrapMode, { 87 | {"Repeat", static_cast(TextureWrapMode::Repeat)}, 88 | {"Clamp to Edge", static_cast(TextureWrapMode::ClampToEdge)}, 89 | {"Mirror", static_cast(TextureWrapMode::Mirror)}, 90 | {"Clamp to Border", static_cast(TextureWrapMode::ClampToBorder)}, 91 | } 92 | }, 93 | { 94 | EnumTangentType, { 95 | {"TC0 Direction", static_cast(TangentType::TC0Direction)}, 96 | {"Radial X", static_cast(TangentType::RadialX)}, 97 | {"Radial Y", static_cast(TangentType::RadialY)}, 98 | {"Radial Z", static_cast(TangentType::RadialZ)}, 99 | } 100 | }, 101 | }; 102 | static std::unordered_map> s_enumNameToIntTables; 103 | static std::unordered_map> s_enumIntToNameTables; 104 | 105 | 106 | 107 | static void initializeEnumTables() { 108 | for (auto i : s_enumTables) { 109 | auto &enumNameToIntMap = s_enumNameToIntTables[i.first]; 110 | auto &enumIntToNameMap = s_enumIntToNameTables[i.first]; 111 | 112 | for (auto j : i.second) { 113 | std::string member = j.first; 114 | uint32_t value = j.second; 115 | enumNameToIntMap[member] = value; 116 | enumIntToNameMap[value] = member; 117 | } 118 | } 119 | 120 | s_enumTableInitialized = true; 121 | } 122 | 123 | uint32_t getNumEnumMembers(const char* typeName) { 124 | if (!s_enumTableInitialized) 125 | initializeEnumTables(); 126 | 127 | if (s_enumTables.count(typeName) == 0) 128 | return 0; 129 | 130 | const auto &table = s_enumTables.at(typeName); 131 | return static_cast(table.size()); 132 | } 133 | 134 | const char* getEnumMemberAt(const char* typeName, uint32_t index) { 135 | if (!s_enumTableInitialized) 136 | initializeEnumTables(); 137 | 138 | if (s_enumTables.count(typeName) == 0) 139 | return nullptr; 140 | 141 | const auto &table = s_enumTables.at(typeName); 142 | if (index >= table.size()) 143 | return nullptr; 144 | 145 | return table[index].first; 146 | } 147 | 148 | template 149 | static EnumType getEnumValueFromMember(const std::string &enumStr, const char* member) { 150 | if (!s_enumTableInitialized) 151 | initializeEnumTables(); 152 | 153 | if (s_enumNameToIntTables.count(enumStr) == 0) 154 | return static_cast(0xFFFFFFFF); 155 | 156 | const auto& table = s_enumNameToIntTables.at(enumStr); 157 | if (table.count(member) == 0) 158 | return static_cast(0xFFFFFFFF); 159 | 160 | return static_cast(table.at(member)); 161 | } 162 | template 163 | static const char* getEnumMemberFromValue(const std::string &enumStr, EnumType value) { 164 | if (!s_enumTableInitialized) 165 | initializeEnumTables(); 166 | 167 | if (s_enumIntToNameTables.count(enumStr) == 0) 168 | return nullptr; 169 | 170 | const auto& table = s_enumIntToNameTables.at(enumStr); 171 | if (table.count(static_cast(value)) == 0) 172 | return nullptr; 173 | 174 | return table.at(static_cast(value)).c_str(); 175 | } 176 | 177 | template 178 | EnumType getEnumValueFromMember(const char* member) { 179 | VLRAssert_ShouldNotBeCalled(); 180 | return static_cast(0xFFFFFFFF); 181 | } 182 | template 183 | const char* getEnumMemberFromValue(EnumType value) { 184 | VLRAssert_ShouldNotBeCalled(); 185 | return nullptr; 186 | } 187 | 188 | #define VLR_DEFINE_GET_ENUM_VALUE_FROM_MEMBER(EnumType) \ 189 | template <> \ 190 | EnumType getEnumValueFromMember(const char* member) { \ 191 | return getEnumValueFromMember(Enum ## EnumType, member); \ 192 | } \ 193 | template EnumType getEnumValueFromMember(const char* member) 194 | 195 | #define VLR_DEFINE_GET_ENUM_MEMBER_FROM_VALUE(EnumType) \ 196 | template <> \ 197 | const char* getEnumMemberFromValue(EnumType value) { \ 198 | return getEnumMemberFromValue(Enum ## EnumType, value); \ 199 | } \ 200 | template const char* getEnumMemberFromValue(EnumType value) 201 | 202 | VLR_DEFINE_GET_ENUM_VALUE_FROM_MEMBER(SpectrumType); 203 | VLR_DEFINE_GET_ENUM_VALUE_FROM_MEMBER(ColorSpace); 204 | VLR_DEFINE_GET_ENUM_VALUE_FROM_MEMBER(DataFormat); 205 | VLR_DEFINE_GET_ENUM_VALUE_FROM_MEMBER(BumpType); 206 | VLR_DEFINE_GET_ENUM_VALUE_FROM_MEMBER(TextureFilter); 207 | VLR_DEFINE_GET_ENUM_VALUE_FROM_MEMBER(TextureWrapMode); 208 | VLR_DEFINE_GET_ENUM_VALUE_FROM_MEMBER(TangentType); 209 | 210 | VLR_DEFINE_GET_ENUM_MEMBER_FROM_VALUE(SpectrumType); 211 | VLR_DEFINE_GET_ENUM_MEMBER_FROM_VALUE(ColorSpace); 212 | VLR_DEFINE_GET_ENUM_MEMBER_FROM_VALUE(DataFormat); 213 | VLR_DEFINE_GET_ENUM_MEMBER_FROM_VALUE(BumpType); 214 | VLR_DEFINE_GET_ENUM_MEMBER_FROM_VALUE(TextureFilter); 215 | VLR_DEFINE_GET_ENUM_MEMBER_FROM_VALUE(TextureWrapMode); 216 | VLR_DEFINE_GET_ENUM_MEMBER_FROM_VALUE(TangentType); 217 | 218 | #undef VLR_DEFINE_GET_ENUM_MEMBER_FROM_VALUE 219 | #undef VLR_DEFINE_GET_ENUM_VALUE_FROM_MEMBER 220 | } 221 | -------------------------------------------------------------------------------- /libVLR/queryable.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "context.h" 4 | 5 | namespace vlr { 6 | bool testParamName(const std::string ¶mNameA, const std::string ¶mNameB); 7 | 8 | 9 | 10 | enum class TextureFilter { 11 | Nearest = 0, 12 | Linear, 13 | None 14 | }; 15 | 16 | enum class TextureWrapMode { 17 | Repeat = 0, 18 | ClampToEdge, 19 | Mirror, 20 | ClampToBorder, 21 | }; 22 | 23 | 24 | 25 | struct ParameterInfo { 26 | const char* name; 27 | VLRParameterFormFlag formFlags; 28 | const char* typeName; 29 | uint32_t tupleSize; // 0 means variable sized array 30 | 31 | ParameterInfo() : 32 | name(nullptr), 33 | formFlags((VLRParameterFormFlag)0), 34 | typeName(nullptr), tupleSize(0) {} 35 | ParameterInfo(const char* _name, 36 | VLRParameterFormFlag _formFlags, 37 | const char* _typeName, uint32_t _tupleSize = 1) : 38 | name(_name), 39 | formFlags(_formFlags), 40 | typeName(_typeName), tupleSize(_tupleSize) {} 41 | }; 42 | 43 | extern const char* ParameterFloat; 44 | extern const char* ParameterPoint3D; 45 | extern const char* ParameterVector3D; 46 | extern const char* ParameterNormal3D; 47 | extern const char* ParameterQuaternion; 48 | extern const char* ParameterSpectrum; 49 | extern const char* ParameterAlpha; 50 | extern const char* ParameterTextureCoordinates; 51 | 52 | extern const char* ParameterImage; 53 | extern const char* ParameterSurfaceMaterial; 54 | 55 | extern const char* EnumSpectrumType; 56 | extern const char* EnumColorSpace; 57 | extern const char* EnumDataFormat; 58 | extern const char* EnumBumpType; 59 | extern const char* EnumTextureFilter; 60 | extern const char* EnumTextureWrapMode; 61 | extern const char* EnumTangentType; 62 | 63 | uint32_t getNumEnumMembers(const char* typeName); 64 | const char* getEnumMemberAt(const char* typeName, uint32_t index); 65 | template 66 | EnumType getEnumValueFromMember(const char* member); 67 | template 68 | const char* getEnumMemberFromValue(EnumType value); 69 | 70 | 71 | 72 | class Image2D; 73 | struct ImmediateSpectrum; 74 | class SurfaceMaterial; 75 | struct ShaderNodePlug; 76 | 77 | class Queryable : public Object { 78 | virtual const std::vector& getParamInfos() const = 0; 79 | 80 | public: 81 | VLR_DECLARE_TYPE_AWARE_CLASS_INTERFACE(); 82 | 83 | Queryable(Context& context) : Object(context) {} 84 | 85 | virtual bool get(const char* paramName, const char** enumValue) const { 86 | return false; 87 | } 88 | virtual bool get(const char* paramName, Point3D* value) const { 89 | return false; 90 | } 91 | virtual bool get(const char* paramName, Vector3D* value) const { 92 | return false; 93 | } 94 | virtual bool get(const char* paramName, Normal3D* value) const { 95 | return false; 96 | } 97 | virtual bool get(const char* paramName, Quaternion* value) const { 98 | return false; 99 | } 100 | virtual bool get(const char* paramName, float* values, uint32_t length) const { 101 | return false; 102 | } 103 | virtual bool get(const char* paramName, const float** values, uint32_t* length) const { 104 | return false; 105 | } 106 | virtual bool get(const char* paramName, const Image2D** image) const { 107 | return false; 108 | } 109 | virtual bool get(const char* paramName, ImmediateSpectrum* spectrum) const { 110 | return false; 111 | } 112 | virtual bool get(const char* paramName, const SurfaceMaterial** material) const { 113 | return false; 114 | } 115 | virtual bool get(const char* paramName, ShaderNodePlug* plug) const { 116 | return false; 117 | } 118 | 119 | virtual bool set(const char* paramName, const char* enumValue) { 120 | return false; 121 | } 122 | virtual bool set(const char* paramName, const Point3D &value) { 123 | return false; 124 | } 125 | virtual bool set(const char* paramName, const Vector3D &value) { 126 | return false; 127 | } 128 | virtual bool set(const char* paramName, const Normal3D &value) { 129 | return false; 130 | } 131 | virtual bool set(const char* paramName, const Quaternion& value) { 132 | return false; 133 | } 134 | virtual bool set(const char* paramName, const float* values, uint32_t length) { 135 | return false; 136 | } 137 | virtual bool set(const char* paramName, const Image2D* image) { 138 | return false; 139 | } 140 | virtual bool set(const char* paramName, const ImmediateSpectrum& spectrum) { 141 | return false; 142 | } 143 | virtual bool set(const char* paramName, const SurfaceMaterial* material) { 144 | return false; 145 | } 146 | virtual bool set(const char* paramName, const ShaderNodePlug& plug) { 147 | return false; 148 | } 149 | 150 | uint32_t getNumParameters() const { 151 | const auto ¶mInfos = getParamInfos(); 152 | return static_cast(paramInfos.size()); 153 | } 154 | const ParameterInfo* getParameterInfo(uint32_t index) const { 155 | const auto ¶mInfos = getParamInfos(); 156 | if (index < paramInfos.size()) 157 | return ¶mInfos[index]; 158 | return nullptr; 159 | } 160 | }; 161 | 162 | #define VLR_DECLARE_QUERYABLE_INTERFACE() \ 163 | static std::vector ParameterInfos; \ 164 | const std::vector &getParamInfos() const override { \ 165 | return ParameterInfos; \ 166 | } 167 | } 168 | -------------------------------------------------------------------------------- /libVLR/shared/basic_types_internal.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "common_internal.h" 4 | #include "../include/VLR/basic_types.h" 5 | 6 | namespace vlr { 7 | //template struct VLR_API Vector3DTemplate; 8 | //template struct VLR_API Vector4DTemplate; 9 | //template struct VLR_API Normal3DTemplate; 10 | //template struct VLR_API Point3DTemplate; 11 | //template struct VLR_API TexCoord2DTemplate; 12 | //template struct VLR_API BoundingBox3DTemplate; 13 | //template struct VLR_API Matrix3x3Template; 14 | //template struct VLR_API Matrix4x4Template; 15 | //template struct VLR_API QuaternionTemplate; 16 | //template struct VLR_API RGBTemplate; 17 | 18 | 19 | 20 | CUDA_DEVICE_FUNCTION CUDA_INLINE constexpr Vector3D asVector3D(const float3 &v) { 21 | return Vector3D(v.x, v.y, v.z); 22 | } 23 | CUDA_DEVICE_FUNCTION CUDA_INLINE float3 asOptiXType(const Vector3D &v) { 24 | return make_float3(v.x, v.y, v.z); 25 | } 26 | CUDA_DEVICE_FUNCTION CUDA_INLINE constexpr Vector4D asVector4D(const float4 &v) { 27 | return Vector4D(v.x, v.y, v.z, v.w); 28 | } 29 | CUDA_DEVICE_FUNCTION CUDA_INLINE float4 asOptiXType(const Vector4D &v) { 30 | return make_float4(v.x, v.y, v.z, v.w); 31 | } 32 | CUDA_DEVICE_FUNCTION CUDA_INLINE constexpr Normal3D asNormal3D(const float3 &v) { 33 | return Normal3D(v.x, v.y, v.z); 34 | } 35 | CUDA_DEVICE_FUNCTION CUDA_INLINE float3 asOptiXType(const Normal3D &n) { 36 | return make_float3(n.x, n.y, n.z); 37 | } 38 | CUDA_DEVICE_FUNCTION CUDA_INLINE constexpr Point3D asPoint3D(const float3 &v) { 39 | return Point3D(v.x, v.y, v.z); 40 | } 41 | CUDA_DEVICE_FUNCTION CUDA_INLINE float3 asOptiXType(const Point3D &p) { 42 | return make_float3(p.x, p.y, p.z); 43 | } 44 | CUDA_DEVICE_FUNCTION CUDA_INLINE constexpr TexCoord2D asTexCoord2D(const float2 &v) { 45 | return TexCoord2D(v.x, v.y); 46 | } 47 | CUDA_DEVICE_FUNCTION CUDA_INLINE float2 asOptiXType(const TexCoord2D &p) { 48 | return make_float2(p.u, p.v); 49 | } 50 | 51 | 52 | 53 | CUDA_DEVICE_FUNCTION CUDA_INLINE int32_t floatToOrderedInt(float fVal) { 54 | #if defined(VLR_Host) 55 | int32_t iVal = *reinterpret_cast(&fVal); 56 | #else 57 | int32_t iVal = __float_as_int(fVal); 58 | #endif 59 | return (iVal >= 0) ? iVal : iVal ^ 0x7FFFFFFF; 60 | } 61 | 62 | CUDA_DEVICE_FUNCTION CUDA_INLINE float orderedIntToFloat(int32_t iVal) { 63 | int32_t orgVal = (iVal >= 0) ? iVal : iVal ^ 0x7FFFFFFF; 64 | #if defined(VLR_Host) 65 | return *reinterpret_cast(&orgVal); 66 | #else 67 | return __int_as_float(orgVal); 68 | #endif 69 | } 70 | 71 | CUDA_DEVICE_FUNCTION CUDA_INLINE uint32_t floatToOrderedUInt(float fVal) { 72 | #if defined(VLR_Host) 73 | int32_t iVal = *reinterpret_cast(&fVal); 74 | #else 75 | int32_t iVal = __float_as_int(fVal); 76 | #endif 77 | return iVal ^ (iVal >= 0 ? 0x80000000 : 0xFFFFFFFF); 78 | } 79 | 80 | struct Point3DAsOrderedInt { 81 | int32_t x, y, z; 82 | 83 | CUDA_DEVICE_FUNCTION CUDA_INLINE Point3DAsOrderedInt() : x(0), y(0), z(0) { 84 | } 85 | CUDA_DEVICE_FUNCTION CUDA_INLINE Point3DAsOrderedInt(const Point3D &v) : 86 | x(floatToOrderedInt(v.x)), y(floatToOrderedInt(v.y)), z(floatToOrderedInt(v.z)) { 87 | } 88 | 89 | CUDA_DEVICE_FUNCTION CUDA_INLINE Point3DAsOrderedInt& operator=(const Point3DAsOrderedInt &v) { 90 | x = v.x; 91 | y = v.y; 92 | z = v.z; 93 | return *this; 94 | } 95 | CUDA_DEVICE_FUNCTION CUDA_INLINE Point3DAsOrderedInt& operator=(const volatile Point3DAsOrderedInt &v) { 96 | x = v.x; 97 | y = v.y; 98 | z = v.z; 99 | return *this; 100 | } 101 | CUDA_DEVICE_FUNCTION CUDA_INLINE volatile Point3DAsOrderedInt& operator=(const Point3DAsOrderedInt &v) volatile { 102 | x = v.x; 103 | y = v.y; 104 | z = v.z; 105 | return *this; 106 | } 107 | CUDA_DEVICE_FUNCTION CUDA_INLINE volatile Point3DAsOrderedInt& operator=(const volatile Point3DAsOrderedInt &v) volatile { 108 | x = v.x; 109 | y = v.y; 110 | z = v.z; 111 | return *this; 112 | } 113 | 114 | CUDA_DEVICE_FUNCTION CUDA_INLINE explicit operator Point3D() const { 115 | return Point3D(orderedIntToFloat(x), orderedIntToFloat(y), orderedIntToFloat(z)); 116 | } 117 | CUDA_DEVICE_FUNCTION CUDA_INLINE explicit operator Point3D() const volatile { 118 | return Point3D(orderedIntToFloat(x), orderedIntToFloat(y), orderedIntToFloat(z)); 119 | } 120 | }; 121 | 122 | CUDA_DEVICE_FUNCTION CUDA_INLINE Point3DAsOrderedInt min(const Point3DAsOrderedInt &a, const Point3DAsOrderedInt &b) { 123 | Point3DAsOrderedInt ret; 124 | ret.x = vlr::min(a.x, b.x); 125 | ret.y = vlr::min(a.y, b.y); 126 | ret.z = vlr::min(a.z, b.z); 127 | return ret; 128 | } 129 | 130 | CUDA_DEVICE_FUNCTION CUDA_INLINE Point3DAsOrderedInt max(const Point3DAsOrderedInt &a, const Point3DAsOrderedInt &b) { 131 | Point3DAsOrderedInt ret; 132 | ret.x = vlr::max(a.x, b.x); 133 | ret.y = vlr::max(a.y, b.y); 134 | ret.z = vlr::max(a.z, b.z); 135 | return ret; 136 | } 137 | 138 | struct BoundingBox3DAsOrderedInt { 139 | Point3DAsOrderedInt minP; 140 | Point3DAsOrderedInt maxP; 141 | 142 | CUDA_DEVICE_FUNCTION CUDA_INLINE BoundingBox3DAsOrderedInt() : 143 | minP(Point3D(INFINITY)), maxP(Point3D(-INFINITY)) { 144 | } 145 | CUDA_DEVICE_FUNCTION CUDA_INLINE BoundingBox3DAsOrderedInt(const BoundingBox3D &v) : 146 | minP(v.minP), maxP(v.maxP) { 147 | } 148 | 149 | CUDA_DEVICE_FUNCTION CUDA_INLINE BoundingBox3DAsOrderedInt& operator=(const BoundingBox3DAsOrderedInt &v) { 150 | minP = v.minP; 151 | maxP = v.maxP; 152 | return *this; 153 | } 154 | CUDA_DEVICE_FUNCTION CUDA_INLINE BoundingBox3DAsOrderedInt& operator=(const volatile BoundingBox3DAsOrderedInt &v) { 155 | minP = v.minP; 156 | maxP = v.maxP; 157 | return *this; 158 | } 159 | CUDA_DEVICE_FUNCTION CUDA_INLINE volatile BoundingBox3DAsOrderedInt& operator=(const BoundingBox3DAsOrderedInt &v) volatile { 160 | minP = v.minP; 161 | maxP = v.maxP; 162 | return *this; 163 | } 164 | CUDA_DEVICE_FUNCTION CUDA_INLINE volatile BoundingBox3DAsOrderedInt& operator=(const volatile BoundingBox3DAsOrderedInt &v) volatile { 165 | minP = v.minP; 166 | maxP = v.maxP; 167 | return *this; 168 | } 169 | 170 | CUDA_DEVICE_FUNCTION CUDA_INLINE explicit operator BoundingBox3D() const { 171 | return BoundingBox3D(static_cast(minP), static_cast(maxP)); 172 | } 173 | CUDA_DEVICE_FUNCTION CUDA_INLINE explicit operator BoundingBox3D() const volatile { 174 | return BoundingBox3D(static_cast(minP), static_cast(maxP)); 175 | } 176 | 177 | struct unify { 178 | CUDA_DEVICE_FUNCTION CUDA_INLINE BoundingBox3DAsOrderedInt operator()(const BoundingBox3DAsOrderedInt &a, const BoundingBox3DAsOrderedInt &b) { 179 | BoundingBox3DAsOrderedInt ret; 180 | ret.minP = min(a.minP, b.minP); 181 | ret.maxP = max(a.maxP, b.maxP); 182 | return ret; 183 | } 184 | }; 185 | }; 186 | 187 | #if defined(VLR_Device) || defined(OPTIXU_Platform_CodeCompletion) 188 | #if __CUDA_ARCH__ < 600 189 | # define atomicOr_block atomicOr 190 | # define atomicAnd_block atomicAnd 191 | # define atomicAdd_block atomicAdd 192 | # define atomicMin_block atomicMin 193 | # define atomicMax_block atomicMax 194 | #endif 195 | 196 | CUDA_DEVICE_FUNCTION CUDA_INLINE void atomicMinPoint3D(Point3DAsOrderedInt* dst, const Point3DAsOrderedInt &v) { 197 | atomicMin(&dst->x, v.x); 198 | atomicMin(&dst->y, v.y); 199 | atomicMin(&dst->z, v.z); 200 | } 201 | 202 | CUDA_DEVICE_FUNCTION CUDA_INLINE void atomicMaxPoint3D(Point3DAsOrderedInt* dst, const Point3DAsOrderedInt &v) { 203 | atomicMax(&dst->x, v.x); 204 | atomicMax(&dst->y, v.y); 205 | atomicMax(&dst->z, v.z); 206 | } 207 | 208 | CUDA_DEVICE_FUNCTION CUDA_INLINE void atomicMinPoint3D_block(Point3DAsOrderedInt* dst, const Point3DAsOrderedInt &v) { 209 | atomicMin_block(&dst->x, v.x); 210 | atomicMin_block(&dst->y, v.y); 211 | atomicMin_block(&dst->z, v.z); 212 | } 213 | 214 | CUDA_DEVICE_FUNCTION CUDA_INLINE void atomicMaxPoint3D_block(Point3DAsOrderedInt* dst, const Point3DAsOrderedInt &v) { 215 | atomicMax_block(&dst->x, v.x); 216 | atomicMax_block(&dst->y, v.y); 217 | atomicMax_block(&dst->z, v.z); 218 | } 219 | 220 | CUDA_DEVICE_FUNCTION CUDA_INLINE void atomicUnifyBoundingBox3D(BoundingBox3DAsOrderedInt* dst, const BoundingBox3DAsOrderedInt &v) { 221 | atomicMinPoint3D(&dst->minP, v.minP); 222 | atomicMaxPoint3D(&dst->maxP, v.maxP); 223 | } 224 | 225 | CUDA_DEVICE_FUNCTION CUDA_INLINE void atomicUnifyBoundingBox3D(BoundingBox3DAsOrderedInt* dst, const Point3DAsOrderedInt &v) { 226 | atomicMinPoint3D(&dst->minP, v); 227 | atomicMaxPoint3D(&dst->maxP, v); 228 | } 229 | 230 | CUDA_DEVICE_FUNCTION CUDA_INLINE void atomicUnifyBoundingBox3D_block(BoundingBox3DAsOrderedInt* dst, const BoundingBox3DAsOrderedInt &v) { 231 | atomicMinPoint3D_block(&dst->minP, v.minP); 232 | atomicMaxPoint3D_block(&dst->maxP, v.maxP); 233 | } 234 | 235 | CUDA_DEVICE_FUNCTION CUDA_INLINE void atomicUnifyBoundingBox3D_block(BoundingBox3DAsOrderedInt* dst, const Point3DAsOrderedInt &v) { 236 | atomicMinPoint3D_block(&dst->minP, v); 237 | atomicMaxPoint3D_block(&dst->maxP, v); 238 | } 239 | #endif 240 | } 241 | -------------------------------------------------------------------------------- /libVLR/shared/light_transport_common.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "renderer_common.h" 4 | 5 | namespace vlr::shared { 6 | struct PTReadOnlyPayload { 7 | float initImportance; 8 | WavelengthSamples wls; 9 | float prevDirPDF; 10 | DirectionType prevSampledType; 11 | unsigned int pathLength : 16; 12 | unsigned int maxLengthTerminate : 1; 13 | }; 14 | 15 | struct PTWriteOnlyPayload { 16 | Point3D nextOrigin; 17 | Vector3D nextDirection; 18 | float dirPDF; 19 | DirectionType sampledType; 20 | unsigned int terminate : 1; 21 | }; 22 | 23 | struct PTReadWritePayload { 24 | KernelRNG rng; 25 | SampledSpectrum alpha; 26 | SampledSpectrum contribution; 27 | }; 28 | 29 | struct PTExtraPayload { 30 | SampledSpectrum firstHitAlbedo; 31 | Normal3D firstHitNormal; 32 | }; 33 | 34 | using PTPayloadSignature = optixu::PayloadSignature< 35 | PTReadOnlyPayload*, PTWriteOnlyPayload*, PTReadWritePayload*, PTExtraPayload*>; 36 | 37 | struct LTReadOnlyPayload { 38 | WavelengthSamples wls; 39 | float prevDirPDF; 40 | DirectionType prevSampledType; 41 | unsigned int pathLength : 16; 42 | unsigned int maxLengthTerminate : 1; 43 | }; 44 | 45 | struct LTWriteOnlyPayload { 46 | Point3D nextOrigin; 47 | Vector3D nextDirection; 48 | float dirPDF; 49 | DirectionType sampledType; 50 | unsigned int terminate : 1; 51 | }; 52 | 53 | struct LTReadWritePayload { 54 | KernelRNG rng; 55 | SampledSpectrum alpha; 56 | }; 57 | 58 | using LTPayloadSignature = optixu::PayloadSignature< 59 | LTReadOnlyPayload*, LTWriteOnlyPayload*, LTReadWritePayload*>; 60 | 61 | struct LVCBPTLightPathReadOnlyPayload { 62 | float dirPDF; 63 | float cosTerm; 64 | float prevRevAreaPDF; 65 | DirectionType sampledType; 66 | unsigned int prevDeltaSampled : 1; 67 | unsigned int secondPrevDeltaSampled : 1; 68 | }; 69 | 70 | struct LVCBPTLightPathWriteOnlyPayload { 71 | Point3D nextOrigin; 72 | Vector3D nextDirection; 73 | float dirPDF; 74 | float cosTerm; 75 | float revAreaPDF; 76 | DirectionType sampledType; 77 | }; 78 | 79 | struct LVCBPTLightPathReadWritePayload { 80 | KernelRNG rng; 81 | SampledSpectrum alpha; 82 | float probDensity; 83 | float prevProbDensity; 84 | float secondPrevPartialDenomMisWeight; 85 | float secondPrevProbRatioToFirst; 86 | unsigned int singleIsSelected : 1; 87 | unsigned int originIsPoint : 1; 88 | unsigned int originIsInfinity : 1; 89 | unsigned int pathLength : 16; 90 | unsigned int terminate : 1; 91 | }; 92 | 93 | struct LVCBPTEyePathReadOnlyPayload { 94 | float dirPDF; 95 | float cosTerm; 96 | float prevRevAreaPDF; 97 | DirectionType sampledType; 98 | unsigned int prevDeltaSampled : 1; 99 | unsigned int secondPrevDeltaSampled : 1; 100 | }; 101 | 102 | struct LVCBPTEyePathWriteOnlyPayload { 103 | Point3D nextOrigin; 104 | Vector3D nextDirection; 105 | float dirPDF; 106 | float cosTerm; 107 | float revAreaPDF; 108 | DirectionType sampledType; 109 | }; 110 | 111 | struct LVCBPTEyePathReadWritePayload { 112 | KernelRNG rng; 113 | SampledSpectrum alpha; 114 | SampledSpectrum contribution; 115 | float probDensity; 116 | float prevProbDensity; 117 | float secondPrevPartialDenomMisWeight; 118 | unsigned int singleIsSelected : 1; 119 | unsigned int pathLength : 16; 120 | unsigned int terminate : 1; 121 | }; 122 | 123 | struct LVCBPTEyePathExtraPayload { 124 | SampledSpectrum firstHitAlbedo; 125 | Normal3D firstHitNormal; 126 | }; 127 | 128 | using LVCBPTLightPathPayloadSignature = optixu::PayloadSignature< 129 | LVCBPTLightPathReadOnlyPayload*, LVCBPTLightPathWriteOnlyPayload*, LVCBPTLightPathReadWritePayload*>; 130 | using LVCBPTEyePathPayloadSignature = optixu::PayloadSignature< 131 | LVCBPTEyePathReadOnlyPayload*, LVCBPTEyePathWriteOnlyPayload*, LVCBPTEyePathReadWritePayload*, LVCBPTEyePathExtraPayload*>; 132 | 133 | using AuxBufGenPayloadSignature = optixu::PayloadSignature< 134 | WavelengthSamples, KernelRNG, SampledSpectrum, Normal3D>; 135 | 136 | using ShadowPayloadSignature = optixu::PayloadSignature< 137 | WavelengthSamples, float>; 138 | 139 | 140 | 141 | #if defined(VLR_Device) || defined(OPTIXU_Platform_CodeCompletion) 142 | 143 | // ---------------------------------------------------------------- 144 | // Light 145 | 146 | template 147 | CUDA_DEVICE_FUNCTION CUDA_INLINE bool testVisibility( 148 | const SurfacePoint &shadingSurfacePoint, const SurfacePoint &lightSurfacePoint, const WavelengthSamples &wls, 149 | Vector3D* shadowRayDir, float* squaredDistance, float* fractionalVisibility) { 150 | VLRAssert(shadingSurfacePoint.atInfinity == false, "Shading point must be in finite region."); 151 | 152 | *shadowRayDir = lightSurfacePoint.calcDirectionFrom(shadingSurfacePoint.position, squaredDistance); 153 | 154 | const Normal3D &spGeomNormal = shadingSurfacePoint.geometricNormal; 155 | bool isFrontSide = dot(spGeomNormal, *shadowRayDir) > 0; 156 | Point3D shadingPoint = offsetRayOrigin( 157 | shadingSurfacePoint.position, isFrontSide ? spGeomNormal : -spGeomNormal); 158 | const Normal3D &lpGeomNormal = lightSurfacePoint.geometricNormal; 159 | isFrontSide = -dot(lpGeomNormal, *shadowRayDir) > 0; 160 | Point3D lightPoint = offsetRayOrigin( 161 | lightSurfacePoint.position, isFrontSide ? lpGeomNormal : -lpGeomNormal); 162 | 163 | float tmax = FLT_MAX; 164 | if (!lightSurfacePoint.atInfinity) 165 | tmax = distance(lightPoint, shadingPoint) * 0.9999f; // TODO: アドホックな調整ではなくoffsetRayOriginと一貫性のある形に。 166 | 167 | WavelengthSamples plWls = wls; 168 | float plFracVis = 1.0f; 169 | ShadowPayloadSignature::trace( 170 | plp.topGroup, asOptiXType(shadingPoint), asOptiXType(*shadowRayDir), 0.0f, tmax, 0.0f, 171 | VisibilityGroup_Everything, OPTIX_RAY_FLAG_NONE, rayType, MaxNumRayTypes, rayType, 172 | plWls, plFracVis); 173 | 174 | *fractionalVisibility = plFracVis; 175 | 176 | return *fractionalVisibility > 0; 177 | } 178 | 179 | CUDA_DEVICE_FUNCTION CUDA_INLINE void selectSurfaceLight( 180 | float uLight, SurfaceLight* light, float* lightProb, float* uPrim) { 181 | float uInst; 182 | float instProb; 183 | uint32_t instIndex = plp.instIndices[plp.lightInstDist.sample(uLight, &instProb, &uInst)]; 184 | const Instance &inst = plp.instBuffer[instIndex]; 185 | float geomInstProb; 186 | uint32_t geomInstIndex = inst.geomInstIndices[inst.lightGeomInstDistribution.sample(uInst, &geomInstProb, uPrim)]; 187 | //printf("%u, %g, %u, %g\n", instIndex, instProb, geomInstIndex, geomInstProb); 188 | const GeometryInstance &geomInst = plp.geomInstBuffer[geomInstIndex]; 189 | *light = SurfaceLight(instIndex, geomInstIndex, 190 | ProgSigSurfaceLight_sample(geomInst.progSample)); 191 | *lightProb = instProb * geomInstProb; 192 | } 193 | 194 | // END: Light 195 | // ---------------------------------------------------------------- 196 | 197 | 198 | 199 | CUDA_DEVICE_KERNEL void RT_AH_NAME(shadowAnyHitDefault)() { 200 | float fractionalVisibility = 0.0f; 201 | ShadowPayloadSignature::set(nullptr, &fractionalVisibility); 202 | optixTerminateRay(); 203 | } 204 | 205 | // Common Any Hit Program for All Primitive Types and Materials for shadow rays 206 | CUDA_DEVICE_KERNEL void RT_AH_NAME(shadowAnyHitWithAlpha)() { 207 | WavelengthSamples wls; 208 | float fractionalVisibility; 209 | ShadowPayloadSignature::get(&wls, &fractionalVisibility); 210 | 211 | float alpha = getAlpha(wls); 212 | 213 | fractionalVisibility *= (1 - alpha); 214 | ShadowPayloadSignature::set(nullptr, &fractionalVisibility); 215 | if (fractionalVisibility == 0.0f) 216 | optixTerminateRay(); 217 | else 218 | optixIgnoreIntersection(); 219 | } 220 | 221 | #endif // #if defined(VLR_Device) || defined(OPTIXU_Platform_CodeCompletion) 222 | } 223 | -------------------------------------------------------------------------------- /libVLR/shared/random_distributions.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "basic_types_internal.h" 4 | 5 | namespace vlr { 6 | class PCG32RNG { 7 | uint64_t m_state; 8 | 9 | public: 10 | CUDA_DEVICE_FUNCTION CUDA_INLINE PCG32RNG() {} 11 | CUDA_DEVICE_FUNCTION CUDA_INLINE PCG32RNG(uint64_t seed) : m_state(seed) {} 12 | 13 | CUDA_DEVICE_FUNCTION CUDA_INLINE uint32_t operator()() { 14 | uint64_t oldstate = m_state; 15 | // Advance internal state 16 | m_state = oldstate * 6364136223846793005ULL + 1; 17 | // Calculate output function (XSH RR), uses old state for max ILP 18 | uint32_t xorshifted = static_cast(((oldstate >> 18u) ^ oldstate) >> 27u); 19 | uint32_t rot = oldstate >> 59u; 20 | return (xorshifted >> rot) | (xorshifted << ((-static_cast(rot)) & 31)); 21 | } 22 | 23 | CUDA_DEVICE_FUNCTION CUDA_INLINE float getFloat0cTo1o() { 24 | uint32_t fractionBits = ((*this)() >> 9) | 0x3f800000; 25 | return *reinterpret_cast(&fractionBits) - 1.0f; 26 | } 27 | }; 28 | 29 | 30 | 31 | class XORShiftRNG { 32 | uint32_t m_state[4]; 33 | 34 | public: 35 | CUDA_DEVICE_FUNCTION CUDA_INLINE XORShiftRNG() {} 36 | CUDA_DEVICE_FUNCTION CUDA_INLINE uint32_t operator()() { 37 | uint32_t* a = m_state; 38 | uint32_t t(a[0] ^ (a[0] << 11)); 39 | a[0] = a[1]; 40 | a[1] = a[2]; 41 | a[2] = a[3]; 42 | return a[3] = (a[3] ^ (a[3] >> 19)) ^ (t ^ (t >> 8)); 43 | } 44 | 45 | CUDA_DEVICE_FUNCTION CUDA_INLINE float getFloat0cTo1o() { 46 | uint32_t fractionBits = ((*this)() >> 9) | 0x3f800000; 47 | return *reinterpret_cast(&fractionBits) - 1.0f; 48 | } 49 | }; 50 | 51 | 52 | 53 | template 54 | CUDA_DEVICE_FUNCTION CUDA_INLINE uint32_t sampleDiscrete( 55 | const RealType* importances, uint32_t numImportances, RealType u, 56 | RealType* prob, RealType* sumImportances, RealType* remapped) { 57 | RealType sum = 0; 58 | for (int i = 0; i < numImportances; ++i) 59 | sum += importances[i]; 60 | *sumImportances = sum; 61 | 62 | RealType base = 0; 63 | RealType su = u * sum; 64 | RealType cum = 0; 65 | for (int i = 0; i < numImportances; ++i) { 66 | base = cum; 67 | cum += importances[i]; 68 | if (su < cum) { 69 | *prob = importances[i] / sum; 70 | *remapped = (su - base) / importances[i]; 71 | return i; 72 | } 73 | } 74 | *prob = importances[0] / sum; 75 | return 0; 76 | } 77 | 78 | 79 | 80 | template 81 | CUDA_DEVICE_FUNCTION CUDA_INLINE void concentricSampleDisk(RealType u0, RealType u1, RealType* dx, RealType* dy) { 82 | RealType r, theta; 83 | RealType sx = 2 * u0 - 1; 84 | RealType sy = 2 * u1 - 1; 85 | 86 | if (sx == 0 && sy == 0) { 87 | *dx = 0; 88 | *dy = 0; 89 | return; 90 | } 91 | if (sx >= -sy) { // region 1 or 2 92 | if (sx > sy) { // region 1 93 | r = sx; 94 | theta = sy / sx; 95 | } 96 | else { // region 2 97 | r = sy; 98 | theta = 2 - sx / sy; 99 | } 100 | } 101 | else { // region 3 or 4 102 | if (sx > sy) {/// region 4 103 | r = -sy; 104 | theta = 6 + sx / sy; 105 | } 106 | else {// region 3 107 | r = -sx; 108 | theta = 4 + sy / sx; 109 | } 110 | } 111 | theta *= VLR_M_PI / 4; 112 | *dx = r * cos(theta); 113 | *dy = r * sin(theta); 114 | } 115 | 116 | template 117 | CUDA_DEVICE_FUNCTION CUDA_INLINE Vector3DTemplate cosineSampleHemisphere(RealType u0, RealType u1) { 118 | // RealType phi = 2 * M_PI * u1; 119 | // RealType theta = std::asin(std::sqrt(u0)); 120 | // return Vector3DTemplate(std::cos(phi) * std::sin(theta), std::sin(phi) * std::sin(theta), std::cos(theta)); 121 | RealType x, y; 122 | concentricSampleDisk(u0, u1, &x, &y); 123 | return Vector3DTemplate(x, y, std::sqrt(std::fmax(0.0f, 1.0f - x * x - y * y))); 124 | } 125 | 126 | template 127 | CUDA_DEVICE_FUNCTION CUDA_INLINE Vector3DTemplate cosNSampleHemisphere(RealType u0, RealType u1) { 128 | RealType phi = 2 * VLR_M_PI * u1; 129 | RealType theta = std::acos(std::pow(u0, 1.0f / (1 + N))); 130 | return Vector3DTemplate::fromPolarZUp(phi, theta); 131 | } 132 | 133 | template 134 | CUDA_DEVICE_FUNCTION CUDA_INLINE Vector3DTemplate uniformSampleHemisphere(RealType u0, RealType u1) { 135 | RealType phi = 2 * VLR_M_PI * u1; 136 | RealType theta = std::acos(1 - u0); 137 | return Vector3DTemplate::fromPolarZUp(phi, theta); 138 | } 139 | 140 | template 141 | CUDA_DEVICE_FUNCTION CUDA_INLINE Vector3DTemplate uniformSampleSphere(RealType u0, RealType u1) { 142 | RealType phi = 2 * VLR_M_PI * u1; 143 | RealType theta = std::acos(1 - 2 * u0); 144 | return Vector3DTemplate::fromPolarZUp(phi, theta); 145 | } 146 | 147 | template 148 | CUDA_DEVICE_FUNCTION CUDA_INLINE Vector3DTemplate uniformSampleCone(RealType u0, RealType u1, RealType cosThetaMax) { 149 | RealType phi = 2 * VLR_M_PI * u1; 150 | RealType theta = std::acos(1 - (1 - cosThetaMax) * u0); 151 | return Vector3DTemplate::fromPolarZUp(phi, theta); 152 | } 153 | 154 | template 155 | CUDA_DEVICE_FUNCTION CUDA_INLINE void uniformSampleTriangle(RealType u0, RealType u1, RealType* b0, RealType* b1) { 156 | // Square-Root Parameterization 157 | //RealType su1 = std::sqrt(u0); 158 | //*b0 = 1.0f - su1; 159 | //*b1 = u1 * su1; 160 | 161 | // Reference 162 | // A Low-Distortion Map Between Triangle and Square 163 | *b0 = 0.5f * u0; 164 | *b1 = 0.5f * u1; 165 | RealType offset = *b1 - *b0; 166 | if (offset > 0) 167 | *b1 += offset; 168 | else 169 | *b0 -= offset; 170 | } 171 | } 172 | -------------------------------------------------------------------------------- /libVLR/shared/spectrum_base.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "common_internal.h" 4 | 5 | namespace vlr { 6 | static constexpr float WavelengthLowBound = 360.0f; 7 | static constexpr float WavelengthHighBound = 830.0f; 8 | static constexpr uint32_t NumCMFSamples = 471; 9 | 10 | #if defined(VLR_Host) 11 | extern const float xbar_CIE1931_2deg[NumCMFSamples]; 12 | extern const float ybar_CIE1931_2deg[NumCMFSamples]; 13 | extern const float zbar_CIE1931_2deg[NumCMFSamples]; 14 | extern float integralCMF; 15 | 16 | void initializeColorSystem(); 17 | void finalizeColorSystem(); 18 | #endif 19 | 20 | enum class SpectrumType { 21 | Reflectance = 0, 22 | Transmittance = Reflectance, 23 | LightSource, 24 | IndexOfRefraction, 25 | NA, 26 | NumTypes 27 | }; 28 | 29 | enum class ColorSpace { 30 | Rec709_D65_sRGBGamma = 0, 31 | Rec709_D65, 32 | XYZ, 33 | xyY, 34 | NumSpaces 35 | }; 36 | 37 | template 38 | CUDA_DEVICE_FUNCTION CUDA_INLINE constexpr RealType sRGB_gamma(RealType value) { 39 | VLRAssert(value >= 0, "Input value must be equal to or greater than 0: %g", value); 40 | if (value <= static_cast(0.0031308)) 41 | return static_cast(12.92) * value; 42 | return static_cast(1.055) * std::pow(value, static_cast(1.0 / 2.4)) - static_cast(0.055); 43 | } 44 | 45 | template 46 | CUDA_DEVICE_FUNCTION CUDA_INLINE constexpr RealType sRGB_degamma(RealType value) { 47 | VLRAssert(value >= 0, "Input value must be equal to or greater than 0: %g", value); 48 | if (value <= static_cast(0.04045)) 49 | return value / static_cast(12.92); 50 | return std::pow(static_cast(value + static_cast(0.055)) / static_cast(1.055), static_cast(2.4)); 51 | } 52 | 53 | template 54 | static constexpr void calcInverse3x3Matrix(const RealType mat[9], RealType invMat[9]) { 55 | RealType det = (mat[3 * 0 + 0] * mat[3 * 1 + 1] * mat[3 * 2 + 2] + 56 | mat[3 * 1 + 0] * mat[3 * 2 + 1] * mat[3 * 0 + 2] + 57 | mat[3 * 2 + 0] * mat[3 * 0 + 1] * mat[3 * 1 + 2]) - 58 | (mat[3 * 2 + 0] * mat[3 * 1 + 1] * mat[3 * 0 + 2] + 59 | mat[3 * 1 + 0] * mat[3 * 0 + 1] * mat[3 * 2 + 2] + 60 | mat[3 * 0 + 0] * mat[3 * 2 + 1] * mat[3 * 1 + 2]); 61 | RealType recDet = 1 / det; 62 | invMat[3 * 0 + 0] = recDet * (mat[3 * 1 + 1] * mat[3 * 2 + 2] - mat[3 * 2 + 1] * mat[3 * 1 + 2]); 63 | invMat[3 * 0 + 1] = -recDet * (mat[3 * 0 + 1] * mat[3 * 2 + 2] - mat[3 * 2 + 1] * mat[3 * 0 + 2]); 64 | invMat[3 * 0 + 2] = recDet * (mat[3 * 0 + 1] * mat[3 * 1 + 2] - mat[3 * 1 + 1] * mat[3 * 0 + 2]); 65 | invMat[3 * 1 + 0] = -recDet * (mat[3 * 1 + 0] * mat[3 * 2 + 2] - mat[3 * 2 + 0] * mat[3 * 1 + 2]); 66 | invMat[3 * 1 + 1] = recDet * (mat[3 * 0 + 0] * mat[3 * 2 + 2] - mat[3 * 2 + 0] * mat[3 * 0 + 2]); 67 | invMat[3 * 1 + 2] = -recDet * (mat[3 * 0 + 0] * mat[3 * 1 + 2] - mat[3 * 1 + 0] * mat[3 * 0 + 2]); 68 | invMat[3 * 2 + 0] = recDet * (mat[3 * 1 + 0] * mat[3 * 2 + 1] - mat[3 * 2 + 0] * mat[3 * 1 + 1]); 69 | invMat[3 * 2 + 1] = -recDet * (mat[3 * 0 + 0] * mat[3 * 2 + 1] - mat[3 * 2 + 0] * mat[3 * 0 + 1]); 70 | invMat[3 * 2 + 2] = recDet * (mat[3 * 0 + 0] * mat[3 * 1 + 1] - mat[3 * 1 + 0] * mat[3 * 0 + 1]); 71 | } 72 | 73 | template 74 | static constexpr void multiply3x3Matrix(const RealType matA[9], const RealType matB[9], RealType matC[9]) { 75 | matC[3 * 0 + 0] = matA[3 * 0 + 0] * matB[3 * 0 + 0] + matA[3 * 1 + 0] * matB[3 * 0 + 1] + matA[3 * 2 + 0] * matB[3 * 0 + 2]; 76 | matC[3 * 0 + 1] = matA[3 * 0 + 1] * matB[3 * 0 + 0] + matA[3 * 1 + 1] * matB[3 * 0 + 1] + matA[3 * 2 + 1] * matB[3 * 0 + 2]; 77 | matC[3 * 0 + 2] = matA[3 * 0 + 2] * matB[3 * 0 + 0] + matA[3 * 1 + 2] * matB[3 * 0 + 1] + matA[3 * 2 + 2] * matB[3 * 0 + 2]; 78 | matC[3 * 1 + 0] = matA[3 * 0 + 0] * matB[3 * 1 + 0] + matA[3 * 1 + 0] * matB[3 * 1 + 1] + matA[3 * 2 + 0] * matB[3 * 1 + 2]; 79 | matC[3 * 1 + 1] = matA[3 * 0 + 1] * matB[3 * 1 + 0] + matA[3 * 1 + 1] * matB[3 * 1 + 1] + matA[3 * 2 + 1] * matB[3 * 1 + 2]; 80 | matC[3 * 1 + 2] = matA[3 * 0 + 2] * matB[3 * 1 + 0] + matA[3 * 1 + 2] * matB[3 * 1 + 1] + matA[3 * 2 + 2] * matB[3 * 1 + 2]; 81 | matC[3 * 2 + 0] = matA[3 * 0 + 0] * matB[3 * 2 + 0] + matA[3 * 1 + 0] * matB[3 * 2 + 1] + matA[3 * 2 + 0] * matB[3 * 2 + 2]; 82 | matC[3 * 2 + 1] = matA[3 * 0 + 1] * matB[3 * 2 + 0] + matA[3 * 1 + 1] * matB[3 * 2 + 1] + matA[3 * 2 + 1] * matB[3 * 2 + 2]; 83 | matC[3 * 2 + 2] = matA[3 * 0 + 2] * matB[3 * 2 + 0] + matA[3 * 1 + 2] * matB[3 * 2 + 1] + matA[3 * 2 + 2] * matB[3 * 2 + 2]; 84 | } 85 | 86 | // http://www.brucelindbloom.com/index.html?Eqn_RGB_XYZ_Matrix.html 87 | template 88 | static constexpr void calc_mat_RGB_to_XYZ(RealType xr, RealType yr, RealType xg, RealType yg, RealType xb, RealType yb, RealType xw, RealType yw, 89 | RealType mat[9]) { 90 | RealType Xr = xr / yr, Yr = 1, Zr = (1 - xr - yr) / yr; 91 | RealType Xg = xg / yg, Yg = 1, Zg = (1 - xg - yg) / yg; 92 | RealType Xb = xb / yb, Yb = 1, Zb = (1 - xb - yb) / yb; 93 | 94 | RealType Xw = xw / yw, Yw = 1, Zw = (1 - xw - yw) / yw; 95 | 96 | RealType m[] = { Xr, Yr, Zr, Xg, Yg, Zg, Xb, Yb, Zb }; 97 | RealType invM[9]; 98 | calcInverse3x3Matrix(m, invM); 99 | RealType Sr = invM[3 * 0 + 0] * Xw + invM[3 * 1 + 0] * Yw + invM[3 * 2 + 0] * Zw; 100 | RealType Sg = invM[3 * 0 + 1] * Xw + invM[3 * 1 + 1] * Yw + invM[3 * 2 + 1] * Zw; 101 | RealType Sb = invM[3 * 0 + 2] * Xw + invM[3 * 1 + 2] * Yw + invM[3 * 2 + 2] * Zw; 102 | 103 | mat[0] = Sr * Xr; mat[3] = Sg * Xg; mat[6] = Sb * Xb; 104 | mat[1] = Sr * Yr; mat[4] = Sg * Yg; mat[7] = Sb * Yb; 105 | mat[2] = Sr * Zr; mat[5] = Sg * Zg; mat[8] = Sb * Zb; 106 | } 107 | 108 | // These matrices are column-major. 109 | CUDA_CONSTANT_MEM HOST_STATIC_CONSTEXPR float mat_Rec709_D65_to_XYZ[] = { 110 | 0.4124564f, 0.2126729f, 0.0193339f, 111 | 0.3575761f, 0.7151522f, 0.1191920f, 112 | 0.1804375f, 0.0721750f, 0.9503041f, 113 | }; 114 | CUDA_CONSTANT_MEM HOST_STATIC_CONSTEXPR float mat_XYZ_to_Rec709_D65[] = { 115 | 3.2404542f, -0.9692660f, 0.0556434f, 116 | -1.5371385f, 1.8760108f, -0.2040259f, 117 | -0.4985314f, 0.0415560f, 1.0572252f, 118 | }; 119 | CUDA_CONSTANT_MEM HOST_STATIC_CONSTEXPR float mat_Rec709_E_to_XYZ[] = { 120 | 0.4969f, 0.2562f, 0.0233f, 121 | 0.3391f, 0.6782f, 0.1130f, 122 | 0.1640f, 0.0656f, 0.8637f, 123 | }; 124 | CUDA_CONSTANT_MEM HOST_STATIC_CONSTEXPR float mat_XYZ_to_Rec709_E[] = { 125 | 2.6897f, -1.0221f, 0.0612f, 126 | -1.2759f, 1.9783f, -0.2245f, 127 | -0.4138f, 0.0438f, 1.1633f, 128 | }; 129 | 130 | template 131 | CUDA_DEVICE_FUNCTION CUDA_INLINE constexpr void transformTristimulus(const float matColMajor[9], const RealType src[3], RealType dst[3]) { 132 | dst[0] = matColMajor[0] * src[0] + matColMajor[3] * src[1] + matColMajor[6] * src[2]; 133 | dst[1] = matColMajor[1] * src[0] + matColMajor[4] * src[1] + matColMajor[7] * src[2]; 134 | dst[2] = matColMajor[2] * src[0] + matColMajor[5] * src[1] + matColMajor[8] * src[2]; 135 | } 136 | 137 | template 138 | CUDA_DEVICE_FUNCTION CUDA_INLINE constexpr void transformToRenderingRGB(SpectrumType spectrumType, const RealType XYZ[3], RealType RGB[3]) { 139 | switch (spectrumType) { 140 | case SpectrumType::Reflectance: 141 | case SpectrumType::IndexOfRefraction: 142 | case SpectrumType::NA: 143 | transformTristimulus(mat_XYZ_to_Rec709_E, XYZ, RGB); 144 | break; 145 | case SpectrumType::LightSource: 146 | transformTristimulus(mat_XYZ_to_Rec709_D65, XYZ, RGB); 147 | break; 148 | default: 149 | VLRAssert_ShouldNotBeCalled(); 150 | break; 151 | } 152 | } 153 | 154 | template 155 | CUDA_DEVICE_FUNCTION CUDA_INLINE constexpr void transformFromRenderingRGB(SpectrumType spectrumType, const RealType RGB[3], RealType XYZ[3]) { 156 | switch (spectrumType) { 157 | case SpectrumType::Reflectance: 158 | case SpectrumType::IndexOfRefraction: 159 | case SpectrumType::NA: 160 | transformTristimulus(mat_Rec709_E_to_XYZ, RGB, XYZ); 161 | break; 162 | case SpectrumType::LightSource: 163 | transformTristimulus(mat_Rec709_D65_to_XYZ, RGB, XYZ); 164 | break; 165 | default: 166 | VLRAssert_ShouldNotBeCalled(); 167 | break; 168 | } 169 | } 170 | 171 | template 172 | inline constexpr void transformToRenderingRGB(SpectrumType spectrumType, ColorSpace srcSpace, const RealType src[3], RealType dstRGB[3]) { 173 | RealType srcTriplet[3] = { src[0], src[1], src[2] }; 174 | switch (srcSpace) { 175 | case ColorSpace::Rec709_D65_sRGBGamma: 176 | dstRGB[0] = sRGB_degamma(srcTriplet[0]); 177 | dstRGB[1] = sRGB_degamma(srcTriplet[1]); 178 | dstRGB[2] = sRGB_degamma(srcTriplet[2]); 179 | break; 180 | case ColorSpace::Rec709_D65: 181 | dstRGB[0] = srcTriplet[0]; 182 | dstRGB[1] = srcTriplet[1]; 183 | dstRGB[2] = srcTriplet[2]; 184 | break; 185 | case ColorSpace::xyY: { 186 | if (srcTriplet[1] == 0) { 187 | dstRGB[0] = dstRGB[1] = dstRGB[2] = 0.0f; 188 | break; 189 | } 190 | RealType z = 1 - (srcTriplet[0] + srcTriplet[1]); 191 | RealType b = srcTriplet[2] / srcTriplet[1]; 192 | srcTriplet[0] = srcTriplet[0] * b; 193 | srcTriplet[1] = srcTriplet[2]; 194 | srcTriplet[2] = z * b; 195 | // pass to XYZ 196 | } 197 | case ColorSpace::XYZ: 198 | switch (spectrumType) { 199 | case SpectrumType::Reflectance: 200 | case SpectrumType::IndexOfRefraction: 201 | case SpectrumType::NA: 202 | transformTristimulus(mat_XYZ_to_Rec709_E, srcTriplet, dstRGB); 203 | break; 204 | case SpectrumType::LightSource: 205 | transformTristimulus(mat_XYZ_to_Rec709_D65, srcTriplet, dstRGB); 206 | break; 207 | default: 208 | VLRAssert_ShouldNotBeCalled(); 209 | break; 210 | } 211 | break; 212 | default: 213 | break; 214 | } 215 | } 216 | 217 | template 218 | CUDA_DEVICE_FUNCTION CUDA_INLINE constexpr void XYZ_to_xyY(const RealType xyz[3], RealType xyY[3]) { 219 | RealType b = xyz[0] + xyz[1] + xyz[2]; 220 | if (b == 0) { 221 | xyY[0] = xyY[1] = static_cast(1.0 / 3.0); 222 | xyY[2] = 0; 223 | return; 224 | } 225 | xyY[0] = xyz[0] / b; 226 | xyY[1] = xyz[1] / b; 227 | xyY[2] = xyz[1]; 228 | } 229 | 230 | template 231 | CUDA_DEVICE_FUNCTION CUDA_INLINE constexpr void xyY_to_XYZ(const RealType xyY[3], RealType xyz[3]) { 232 | RealType b = xyY[2] / xyY[1]; 233 | xyz[0] = xyY[0] * b; 234 | xyz[1] = xyY[2]; 235 | xyz[2] = (1 - xyY[0] - xyY[1]) * b; 236 | } 237 | 238 | template 239 | constexpr RealType calcLuminance(ColorSpace colorSpace, RealType e0, RealType e1, RealType e2) { 240 | switch (colorSpace) { 241 | case ColorSpace::Rec709_D65_sRGBGamma: 242 | VLRAssert_NotImplemented(); 243 | break; 244 | case ColorSpace::Rec709_D65: 245 | VLRAssert_NotImplemented(); 246 | break; 247 | case ColorSpace::XYZ: 248 | return e1; 249 | case ColorSpace::xyY: 250 | return e2; 251 | default: 252 | VLRAssert_ShouldNotBeCalled(); 253 | break; 254 | } 255 | return 0.0f; 256 | } 257 | } 258 | -------------------------------------------------------------------------------- /libVLR/slot_finder.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "shared/common_internal.h" 4 | 5 | namespace vlr { 6 | class SlotFinder { 7 | uint32_t m_numLayers; 8 | uint32_t m_numLowestFlagBins; 9 | uint32_t m_numTotalCompiledFlagBins; 10 | uint32_t* m_flagBins; 11 | uint32_t* m_offsetsToOR_AND; 12 | uint32_t* m_numUsedFlagsUnderBinList; 13 | uint32_t* m_offsetsToNumUsedFlags; 14 | uint32_t* m_numFlagsInLayerList; 15 | 16 | SlotFinder(const SlotFinder &) = delete; 17 | SlotFinder &operator=(const SlotFinder &) = delete; 18 | 19 | void aggregate(); 20 | 21 | uint32_t getNumLayers() const { 22 | return m_numLayers; 23 | } 24 | 25 | const uint32_t* getOffsetsToOR_AND() const { 26 | return m_offsetsToOR_AND; 27 | } 28 | 29 | const uint32_t* getOffsetsToNumUsedFlags() const { 30 | return m_offsetsToNumUsedFlags; 31 | } 32 | 33 | const uint32_t* getNumFlagsInLayerList() const { 34 | return m_numFlagsInLayerList; 35 | } 36 | 37 | public: 38 | static constexpr uint32_t InvalidSlotIndex = 0xFFFFFFFF; 39 | 40 | SlotFinder() : 41 | m_numLayers(0), m_numLowestFlagBins(0), m_numTotalCompiledFlagBins(0), 42 | m_flagBins(nullptr), m_offsetsToOR_AND(nullptr), 43 | m_numUsedFlagsUnderBinList(nullptr), m_offsetsToNumUsedFlags(nullptr), 44 | m_numFlagsInLayerList(nullptr) { 45 | } 46 | ~SlotFinder() { 47 | } 48 | 49 | void initialize(uint32_t numSlots); 50 | 51 | void finalize(); 52 | 53 | SlotFinder &operator=(SlotFinder &&inst) { 54 | finalize(); 55 | 56 | m_numLayers = inst.m_numLayers; 57 | m_numLowestFlagBins = inst.m_numLowestFlagBins; 58 | m_numTotalCompiledFlagBins = inst.m_numTotalCompiledFlagBins; 59 | m_flagBins = inst.m_flagBins; 60 | m_offsetsToOR_AND = inst.m_offsetsToOR_AND; 61 | m_numUsedFlagsUnderBinList = inst.m_numUsedFlagsUnderBinList; 62 | m_offsetsToNumUsedFlags = inst.m_offsetsToNumUsedFlags; 63 | m_numFlagsInLayerList = inst.m_numFlagsInLayerList; 64 | inst.m_flagBins = nullptr; 65 | inst.m_offsetsToOR_AND = nullptr; 66 | inst.m_numUsedFlagsUnderBinList = nullptr; 67 | inst.m_offsetsToNumUsedFlags = nullptr; 68 | inst.m_numFlagsInLayerList = nullptr; 69 | 70 | return *this; 71 | } 72 | SlotFinder(SlotFinder &&inst) { 73 | *this = std::move(inst); 74 | } 75 | 76 | void resize(uint32_t numSlots); 77 | 78 | void reset() { 79 | std::fill_n(m_flagBins, m_numLowestFlagBins + m_numTotalCompiledFlagBins, 0); 80 | std::fill_n(m_numUsedFlagsUnderBinList, m_numLowestFlagBins + m_numTotalCompiledFlagBins / 2, 0); 81 | } 82 | 83 | 84 | 85 | void setInUse(uint32_t slotIdx); 86 | 87 | void setNotInUse(uint32_t slotIdx); 88 | 89 | bool getUsage(uint32_t slotIdx) const { 90 | uint32_t binIdx = slotIdx / 32; 91 | uint32_t flagIdxInBin = slotIdx % 32; 92 | uint32_t flagBin = m_flagBins[binIdx]; 93 | 94 | return (bool)((flagBin >> flagIdxInBin) & 0x1); 95 | } 96 | 97 | uint32_t getFirstAvailableSlot() const; 98 | 99 | uint32_t getFirstUsedSlot() const; 100 | 101 | uint32_t find_nthUsedSlot(uint32_t n) const; 102 | 103 | uint32_t getNumSlots() const { 104 | return m_numFlagsInLayerList[0]; 105 | } 106 | 107 | uint32_t getNumUsed() const { 108 | return m_numUsedFlagsUnderBinList[m_offsetsToNumUsedFlags[m_numLayers - 1]]; 109 | } 110 | 111 | void debugPrint() const; 112 | }; 113 | } 114 | -------------------------------------------------------------------------------- /libVLR/spectral_upsampling_tables/sRGB_D65.coeff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shocker-0x15/VLR/8dad615a0f82c8599c6c59998278ab90b0c56f70/libVLR/spectral_upsampling_tables/sRGB_D65.coeff -------------------------------------------------------------------------------- /libVLR/spectral_upsampling_tables/sRGB_E.coeff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shocker-0x15/VLR/8dad615a0f82c8599c6c59998278ab90b0c56f70/libVLR/spectral_upsampling_tables/sRGB_E.coeff --------------------------------------------------------------------------------