SLProject  4.2.000
A platform independent 3D computer graphics framework for desktop OS, Android, iOS and online in web browsers
SLOptixPathtracer.cpp
Go to the documentation of this file.
1 /**
2  * \file SLOptixPathtracer.cpp
3  * \authors Nic Dorner
4  * \date Dezember 2019
5  * \authors Nic Dorner
6  * \copyright http://opensource.org/licenses/GPL-3.0
7  * \remarks Please use clangformat to format the code. See more code style on
8  * https://github.com/cpvrlab/SLProject4/wiki/SLProject-Coding-Style
9 */
10 
11 #ifdef SL_HAS_OPTIX
12 # include <SLAssetManager.h>
13 # include <SLScene.h>
14 # include <SLSceneView.h>
15 # include <SLOptix.h>
16 # include <SLOptixRaytracer.h>
17 # include <SLOptixPathtracer.h>
18 # include <GlobalTimer.h>
19 
20 //-----------------------------------------------------------------------------
21 SLOptixPathtracer::SLOptixPathtracer()
22 {
23  name("OptiX path tracer");
24 }
25 //-----------------------------------------------------------------------------
26 SLOptixPathtracer::~SLOptixPathtracer()
27 {
28  SL_LOG("Destructor : ~SLOptixPathtracer");
29 
30  try
31  {
32  OPTIX_CHECK(optixDenoiserDestroy(_optixDenoiser));
33  }
34  catch (exception e)
35  {
36  Utils::log("SLProject",
37  "Exception in ~SLOptixRaytracer: %s",
38  e.what());
39  }
40 }
41 //-----------------------------------------------------------------------------
42 void SLOptixPathtracer::setupOptix()
43 {
44  _cameraModule = createModule("SLOptixPathtracerCamera.cu");
45  _shadingModule = createModule("SLOptixPathtracerShading.cu");
46 
47  OptixProgramGroupDesc sample_raygen_desc = {};
48  sample_raygen_desc.kind = OPTIX_PROGRAM_GROUP_KIND_RAYGEN;
49  sample_raygen_desc.raygen.module = _cameraModule;
50  sample_raygen_desc.raygen.entryFunctionName = "__raygen__sample_camera";
51  _pinhole_raygen_prog_group = createProgram(sample_raygen_desc);
52 
53  OptixProgramGroupDesc sample_miss_desc = {};
54  sample_miss_desc.kind = OPTIX_PROGRAM_GROUP_KIND_MISS;
55  sample_miss_desc.miss.module = _shadingModule;
56  sample_miss_desc.miss.entryFunctionName = "__miss__sample";
57  _radiance_miss_group = createProgram(sample_miss_desc);
58 
59  OptixProgramGroupDesc sample_hitgroup_desc = {};
60  sample_hitgroup_desc.kind = OPTIX_PROGRAM_GROUP_KIND_HITGROUP;
61  sample_hitgroup_desc.hitgroup.moduleAH = _shadingModule;
62  sample_hitgroup_desc.hitgroup.entryFunctionNameAH = "__anyhit__radiance";
63  sample_hitgroup_desc.hitgroup.moduleCH = _shadingModule;
64  sample_hitgroup_desc.hitgroup.entryFunctionNameCH = "__closesthit__radiance";
65  _radiance_hit_group = createProgram(sample_hitgroup_desc);
66 
67  OptixProgramGroupDesc occlusion_miss_desc = {};
68  occlusion_miss_desc.kind = OPTIX_PROGRAM_GROUP_KIND_MISS;
69  occlusion_miss_desc.miss.module = nullptr;
70  occlusion_miss_desc.miss.entryFunctionName = nullptr;
71  _occlusion_miss_group = createProgram(occlusion_miss_desc);
72 
73  OptixProgramGroupDesc occlusion_hitgroup_desc = {};
74  occlusion_hitgroup_desc.kind = OPTIX_PROGRAM_GROUP_KIND_HITGROUP;
75  occlusion_hitgroup_desc.hitgroup.moduleAH = nullptr;
76  occlusion_hitgroup_desc.hitgroup.entryFunctionNameAH = nullptr;
77  occlusion_hitgroup_desc.hitgroup.moduleCH = nullptr;
78  occlusion_hitgroup_desc.hitgroup.entryFunctionNameCH = nullptr;
79  _occlusion_hit_group = createProgram(occlusion_hitgroup_desc);
80 
81  OptixProgramGroup path_tracer_program_groups[] = {
82  _pinhole_raygen_prog_group,
83  _radiance_miss_group,
84  _occlusion_miss_group,
85  _radiance_hit_group,
86  _occlusion_hit_group,
87  };
88 
89  _pipeline = createPipeline(path_tracer_program_groups, 5);
90 
91  OptixDenoiserOptions denoiserOptions;
92  denoiserOptions.inputKind = OPTIX_DENOISER_INPUT_RGB;
93  denoiserOptions.pixelFormat = OPTIX_PIXEL_FORMAT_FLOAT4;
94 
95  OPTIX_CHECK(optixDenoiserCreate(SLOptix::context,
96  &denoiserOptions,
97  &_optixDenoiser));
98 
99  OPTIX_CHECK(optixDenoiserSetModel(_optixDenoiser,
100  OPTIX_DENOISER_MODEL_KIND_LDR,
101  nullptr,
102  0));
103 }
104 //-----------------------------------------------------------------------------
105 void SLOptixPathtracer::setupScene(SLSceneView* sv, SLAssetManager* am)
106 {
107  SLVMesh meshes = am->meshes();
108  _sv = sv;
109 
110  _imageBuffer.resize(_sv->scrW() * _sv->scrH() * sizeof(float4));
111  _curandBuffer.resize(_sv->scrW() * _sv->scrH() * sizeof(curandState));
112 
113  _params.image = reinterpret_cast<float4*>(_imageBuffer.devicePointer());
114  _params.states = reinterpret_cast<curandState*>(_curandBuffer.devicePointer());
115  _params.width = _sv->scrW();
116  _params.height = _sv->scrH();
117  _params.max_depth = _maxDepth;
118  _params.samples = _samples;
119 
120  // Iterate over all meshes
121  SLMesh::meshIndex = 0;
122  for (auto mesh : meshes)
123  mesh->createMeshAccelerationStructure();
124 
125  _sbtClassic = createShaderBindingTable(meshes, false);
126 
127  OPTIX_CHECK(optixDenoiserComputeMemoryResources(_optixDenoiser,
128  _sv->scrW(),
129  _sv->scrW(),
130  &_denoiserSizes));
131 
132  _denoserState.resize(_denoiserSizes.stateSizeInBytes);
133  _scratch.resize(_denoiserSizes.recommendedScratchSizeInBytes);
134 
135  OPTIX_CHECK(optixDenoiserSetup(
136  _optixDenoiser,
137  SLOptix::stream,
138  _sv->scrW(),
139  _sv->scrH(),
140  _denoserState.devicePointer(),
141  _denoiserSizes.stateSizeInBytes,
142  _scratch.devicePointer(),
143  _denoiserSizes.recommendedScratchSizeInBytes));
144 }
145 //-----------------------------------------------------------------------------
146 void SLOptixPathtracer::updateScene(SLSceneView* sv)
147 {
148  SLScene* scene = sv->s();
149  SLCamera* camera = sv->camera();
150  _sv = sv;
151 
153  scene->root3D()->createInstanceAccelerationStructureFlat();
154 
155  _params.handle = scene->root3D()->optixTraversableHandle();
156 
157  SLVec3f eye, u, v, w;
158  camera->UVWFrame(eye, u, v, w);
159  ortCamera cameraData{};
160  cameraData.eye = make_float3(eye);
161  cameraData.U = make_float3(u);
162  cameraData.V = make_float3(v);
163  cameraData.W = make_float3(w);
164 
165  RayGenClassicSbtRecord rayGenSbtRecord;
166  _rayGenClassicBuffer.download(&rayGenSbtRecord);
167  OPTIX_CHECK(optixSbtRecordPackHeader(_pinhole_raygen_prog_group,
168  &rayGenSbtRecord));
169  rayGenSbtRecord.data = cameraData;
170  _rayGenClassicBuffer.upload(&rayGenSbtRecord);
171 
172  _params.seed = (SLuint)time(nullptr);
173 
174  _paramsBuffer.upload(&_params);
175 }
176 //-----------------------------------------------------------------------------
177 SLbool SLOptixPathtracer::render()
178 {
179  _renderSec = 0.0f; // reset time
180  // Measure time
181  double t1 = GlobalTimer::timeMS();
182  double tStart = t1;
183  _state = rtBusy; // From here we state the RT as busy
184 
185  // Todo: Bugfix needed for Optix needs some work for newer shader models
186  //OPTIX_CHECK(
187  optixLaunch(
188  _pipeline,
189  SLOptix::stream,
190  _paramsBuffer.devicePointer(),
191  _paramsBuffer.size(),
192  &_sbtClassic,
193  _sv->scrW(),
194  _sv->scrH(),
195  /*depth=*/1);
196  //);
197  CUDA_SYNC_CHECK(SLOptix::stream);
198 
199  _renderSec = (SLfloat)(GlobalTimer::timeMS() - tStart) / 1000;
200 
201  // Measure denoiser time
202  double t2 = GlobalTimer::timeMS();
203 
204  if (_denoiserEnabled)
205  {
206  OptixImage2D optixImage2D;
207  optixImage2D.data = _imageBuffer.devicePointer();
208  optixImage2D.width = _sv->scrW();
209  optixImage2D.height = _sv->scrH();
210  optixImage2D.rowStrideInBytes = _sv->scrW() * sizeof(float4);
211  optixImage2D.pixelStrideInBytes = 0;
212  optixImage2D.format = OPTIX_PIXEL_FORMAT_FLOAT4;
213 
214  OptixDenoiserParams denoiserParams;
215  denoiserParams.denoiseAlpha = 0;
216  denoiserParams.blendFactor = 0.0f;
217  denoiserParams.hdrIntensity = 0;
218 
219  OPTIX_CHECK(optixDenoiserInvoke(
220  _optixDenoiser,
221  SLOptix::stream,
222  &denoiserParams,
223  _denoserState.devicePointer(),
224  _denoiserSizes.stateSizeInBytes,
225  &optixImage2D,
226  1,
227  0,
228  0,
229  &optixImage2D,
230  _scratch.devicePointer(),
231  _denoiserSizes.recommendedScratchSizeInBytes));
232  CUDA_SYNC_CHECK(SLOptix::stream);
233  }
234 
235  _denoiserMS = (SLfloat)(GlobalTimer::timeMS() - t2);
236 
237  _state = rtFinished;
238  return true;
239 }
240 //-----------------------------------------------------------------------------
241 #endif // SL_HAS_OPTIX
float SLfloat
Definition: SL.h:173
#define SL_LOG(...)
Definition: SL.h:233
unsigned int SLuint
Definition: SL.h:171
bool SLbool
Definition: SL.h:175
SLSceneView * sv
Definition: SLGLImGui.h:28
vector< SLMesh * > SLVMesh
Definition: SLMesh.h:263
@ rtBusy
Definition: SLRaytracer.h:30
@ rtFinished
Definition: SLRaytracer.h:31
static float timeMS()
Definition: GlobalTimer.cpp:25
Toplevel holder of the assets meshes, materials, textures and shaders.
SLVMesh & meshes()
Active or visible camera node class.
Definition: SLCamera.h:54
void UVWFrame(SLVec3f &EYE, SLVec3f &U, SLVec3f &V, SLVec3f &W)
Definition: SLCamera.cpp:1578
static unsigned int instanceIndex
???
Definition: SLNode.h:321
The SLScene class represents the top level instance holding the scene structure.
Definition: SLScene.h:47
void root3D(SLNode *root3D)
Definition: SLScene.h:78
SceneView class represents a dynamic real time 3D view onto the scene.
Definition: SLSceneView.h:69
void camera(SLCamera *camera)
Definition: SLSceneView.h:145
void scrW(SLint scrW)
Definition: SLSceneView.h:147
SLScene * s()
Definition: SLSceneView.h:167
void log(const char *tag, const char *format,...)
logs a formatted string platform independently
Definition: Utils.cpp:1103