SLProject  4.3.020
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  // As the CPU SLPathtracer does. Without this the inherited value is the
26  // gamma(1.0) of SLRaytracer, which is right for a ray tracer and leaves a
27  // path traced image uncorrected.
28  gamma(2.2f);
29 }
30 //-----------------------------------------------------------------------------
31 SLOptixPathtracer::~SLOptixPathtracer()
32 {
33  SL_LOG("Destructor : ~SLOptixPathtracer");
34 
35  try
36  {
37  OPTIX_CHECK(optixDenoiserDestroy(_optixDenoiser));
38  }
39  catch (exception e)
40  {
41  Utils::log("SLProject",
42  "Exception in ~SLOptixRaytracer: %s",
43  e.what());
44  }
45 }
46 //-----------------------------------------------------------------------------
47 void SLOptixPathtracer::setupOptix()
48 {
49  _cameraModule = createModule("SLOptixPathtracerCamera.cu");
50  _shadingModule = createModule("SLOptixPathtracerShading.cu");
51 
52  OptixProgramGroupDesc sample_raygen_desc = {};
53  sample_raygen_desc.kind = OPTIX_PROGRAM_GROUP_KIND_RAYGEN;
54  sample_raygen_desc.raygen.module = _cameraModule;
55  sample_raygen_desc.raygen.entryFunctionName = "__raygen__sample_camera";
56  _pinhole_raygen_prog_group = createProgram(sample_raygen_desc);
57 
58  OptixProgramGroupDesc sample_miss_desc = {};
59  sample_miss_desc.kind = OPTIX_PROGRAM_GROUP_KIND_MISS;
60  sample_miss_desc.miss.module = _shadingModule;
61  sample_miss_desc.miss.entryFunctionName = "__miss__sample";
62  _radiance_miss_group = createProgram(sample_miss_desc);
63 
64  OptixProgramGroupDesc sample_hitgroup_desc = {};
65  sample_hitgroup_desc.kind = OPTIX_PROGRAM_GROUP_KIND_HITGROUP;
66  sample_hitgroup_desc.hitgroup.moduleAH = _shadingModule;
67  sample_hitgroup_desc.hitgroup.entryFunctionNameAH = "__anyhit__radiance";
68  sample_hitgroup_desc.hitgroup.moduleCH = _shadingModule;
69  sample_hitgroup_desc.hitgroup.entryFunctionNameCH = "__closesthit__radiance";
70  _radiance_hit_group = createProgram(sample_hitgroup_desc);
71 
72  OptixProgramGroupDesc occlusion_miss_desc = {};
73  occlusion_miss_desc.kind = OPTIX_PROGRAM_GROUP_KIND_MISS;
74  occlusion_miss_desc.miss.module = nullptr;
75  occlusion_miss_desc.miss.entryFunctionName = nullptr;
76  _occlusion_miss_group = createProgram(occlusion_miss_desc);
77 
78  OptixProgramGroupDesc occlusion_hitgroup_desc = {};
79  occlusion_hitgroup_desc.kind = OPTIX_PROGRAM_GROUP_KIND_HITGROUP;
80  occlusion_hitgroup_desc.hitgroup.moduleAH = nullptr;
81  occlusion_hitgroup_desc.hitgroup.entryFunctionNameAH = nullptr;
82  occlusion_hitgroup_desc.hitgroup.moduleCH = nullptr;
83  occlusion_hitgroup_desc.hitgroup.entryFunctionNameCH = nullptr;
84  _occlusion_hit_group = createProgram(occlusion_hitgroup_desc);
85 
86  OptixProgramGroup path_tracer_program_groups[] = {
87  _pinhole_raygen_prog_group,
88  _radiance_miss_group,
89  _occlusion_miss_group,
90  _radiance_hit_group,
91  _occlusion_hit_group,
92  };
93 
94  _pipeline = createPipeline(path_tracer_program_groups, 5);
95 
96  OptixDenoiserOptions denoiserOptions;
97  denoiserOptions.inputKind = OPTIX_DENOISER_INPUT_RGB;
98  denoiserOptions.pixelFormat = OPTIX_PIXEL_FORMAT_FLOAT4;
99 
100  OPTIX_CHECK(optixDenoiserCreate(SLOptix::context,
101  &denoiserOptions,
102  &_optixDenoiser));
103 
104  OPTIX_CHECK(optixDenoiserSetModel(_optixDenoiser,
105  OPTIX_DENOISER_MODEL_KIND_LDR,
106  nullptr,
107  0));
108 }
109 //-----------------------------------------------------------------------------
110 void SLOptixPathtracer::setupScene(SLSceneView* sv, SLAssetManager* am)
111 {
112  SLVMesh meshes = am->meshes();
113  _sv = sv;
114 
115  _imageBuffer.resize(_sv->scrW() * _sv->scrH() * sizeof(float4));
116  _curandBuffer.resize(_sv->scrW() * _sv->scrH() * sizeof(curandState));
117 
118  _params.image = reinterpret_cast<float4*>(_imageBuffer.devicePointer());
119  _params.states = reinterpret_cast<curandState*>(_curandBuffer.devicePointer());
120  _params.width = _sv->scrW();
121  _params.height = _sv->scrH();
122  _params.max_depth = _maxDepth;
123  _params.samples = _samples;
124 
125  // Iterate over all meshes
126  SLMesh::meshIndex = 0;
127  for (auto mesh : meshes)
128  mesh->createMeshAccelerationStructure();
129 
130  _sbtClassic = createShaderBindingTable(meshes, false);
131 
132  OPTIX_CHECK(optixDenoiserComputeMemoryResources(_optixDenoiser,
133  _sv->scrW(),
134  _sv->scrW(),
135  &_denoiserSizes));
136 
137  _denoserState.resize(_denoiserSizes.stateSizeInBytes);
138  _scratch.resize(_denoiserSizes.recommendedScratchSizeInBytes);
139 
140  OPTIX_CHECK(optixDenoiserSetup(
141  _optixDenoiser,
142  SLOptix::stream,
143  _sv->scrW(),
144  _sv->scrH(),
145  _denoserState.devicePointer(),
146  _denoiserSizes.stateSizeInBytes,
147  _scratch.devicePointer(),
148  _denoiserSizes.recommendedScratchSizeInBytes));
149 }
150 //-----------------------------------------------------------------------------
151 void SLOptixPathtracer::updateScene(SLSceneView* sv)
152 {
153  SLScene* scene = sv->s();
154  SLCamera* camera = sv->camera();
155  _sv = sv;
156 
158  scene->root3D()->createInstanceAccelerationStructureFlat();
159 
160  _params.handle = scene->root3D()->optixTraversableHandle();
161 
162  SLVec3f eye, u, v, w;
163  camera->UVWFrame(eye, u, v, w);
164  ortCamera cameraData{};
165  cameraData.eye = make_float3(eye);
166  cameraData.U = make_float3(u);
167  cameraData.V = make_float3(v);
168  cameraData.W = make_float3(w);
169 
170  RayGenClassicSbtRecord rayGenSbtRecord;
171  _rayGenClassicBuffer.download(&rayGenSbtRecord);
172  OPTIX_CHECK(optixSbtRecordPackHeader(_pinhole_raygen_prog_group,
173  &rayGenSbtRecord));
174  rayGenSbtRecord.data = cameraData;
175  _rayGenClassicBuffer.upload(&rayGenSbtRecord);
176 
177  _params.seed = (SLuint)time(nullptr);
178  _params.oneOverGamma = _oneOverGamma;
179 
180  _paramsBuffer.upload(&_params);
181 }
182 //-----------------------------------------------------------------------------
183 SLbool SLOptixPathtracer::render()
184 {
185  _renderSec = 0.0f; // reset time
186  // Measure time
187  double t1 = GlobalTimer::timeMS();
188  double tStart = t1;
189  _state = rtBusy; // From here we state the RT as busy
190 
191  // Todo: Bugfix needed for Optix needs some work for newer shader models
192  //OPTIX_CHECK(
193  optixLaunch(
194  _pipeline,
195  SLOptix::stream,
196  _paramsBuffer.devicePointer(),
197  _paramsBuffer.size(),
198  &_sbtClassic,
199  _sv->scrW(),
200  _sv->scrH(),
201  /*depth=*/1);
202  //);
203  CUDA_SYNC_CHECK(SLOptix::stream);
204 
205  _renderSec = (SLfloat)(GlobalTimer::timeMS() - tStart) / 1000;
206 
207  // Measure denoiser time
208  double t2 = GlobalTimer::timeMS();
209 
210  if (_denoiserEnabled)
211  {
212  OptixImage2D optixImage2D;
213  optixImage2D.data = _imageBuffer.devicePointer();
214  optixImage2D.width = _sv->scrW();
215  optixImage2D.height = _sv->scrH();
216  optixImage2D.rowStrideInBytes = _sv->scrW() * sizeof(float4);
217  optixImage2D.pixelStrideInBytes = 0;
218  optixImage2D.format = OPTIX_PIXEL_FORMAT_FLOAT4;
219 
220  OptixDenoiserParams denoiserParams;
221  denoiserParams.denoiseAlpha = 0;
222  denoiserParams.blendFactor = 0.0f;
223  denoiserParams.hdrIntensity = 0;
224 
225  OPTIX_CHECK(optixDenoiserInvoke(
226  _optixDenoiser,
227  SLOptix::stream,
228  &denoiserParams,
229  _denoserState.devicePointer(),
230  _denoiserSizes.stateSizeInBytes,
231  &optixImage2D,
232  1,
233  0,
234  0,
235  &optixImage2D,
236  _scratch.devicePointer(),
237  _denoiserSizes.recommendedScratchSizeInBytes));
238  CUDA_SYNC_CHECK(SLOptix::stream);
239  }
240 
241  _denoiserMS = (SLfloat)(GlobalTimer::timeMS() - t2);
242 
243  // Ready and not finished, so that draw3DOptixPT() renders again on the next
244  // frame and the image follows the camera. rtFinished froze it after a single
245  // render: nothing ever resets an OptiX renderer, because the mouse handlers
246  // of SLSceneView reset only the CPU _raytracer and _pathtracer. The OptiX
247  // ray tracer looks like it updates by design, but only because
248  // SLOptixRaytracer::renderDistrib never assigns _state at all and so leaves
249  // it at the rtReady of the constructor.
250  //
251  // Note that leaving this assignment out altogether would freeze the image
252  // even harder, since render() sets _state to rtBusy on entry and the guard
253  // in draw3DOptixPT() only ever renders in the rtReady state.
254  //
255  // The cost is one full render of _samples samples per displayed frame,
256  // which is comfortable at 10 and sluggish at 1000.
257  _state = rtReady;
258  return true;
259 }
260 //-----------------------------------------------------------------------------
261 #endif // SL_HAS_OPTIX
float SLfloat
analog to GLfloat
Definition: SL.h:200
#define SL_LOG(...)
Some debugging and error handling macros.
Definition: SL.h:279
unsigned int SLuint
analog to GLuint
Definition: SL.h:198
bool SLbool
analog to GLbool
Definition: SL.h:202
SLSceneView * sv
Definition: SLGLImGui.h:28
vector< SLMesh * > SLVMesh
Definition: SLMesh.h:263
@ rtBusy
Definition: SLRaytracer.h:30
@ rtReady
Definition: SLRaytracer.h:29
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:322
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:149
void scrW(SLint scrW)
Definition: SLSceneView.h:151
SLScene * s()
Definition: SLSceneView.h:171
void log(const char *tag, const char *format,...)
logs a formatted string platform independently
Definition: Utils.cpp:1100