Fermat
bpt_impl.h
1 /*
2  * Fermat
3  *
4  * Copyright (c) 2016-2019, NVIDIA CORPORATION. All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions are met:
8  * * Redistributions of source code must retain the above copyright
9  * notice, this list of conditions and the following disclaimer.
10  * * Redistributions in binary form must reproduce the above copyright
11  * notice, this list of conditions and the following disclaimer in the
12  * documentation and/or other materials provided with the distribution.
13  * * Neither the name of the NVIDIA CORPORATION nor the
14  * names of its contributors may be used to endorse or promote products
15  * derived from this software without specific prior written permission.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
18  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20  * DISCLAIMED. IN NO EVENT SHALL NVIDIA CORPORATION BE LIABLE FOR ANY
21  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
24  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
26  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27  */
28 
29 #pragma once
30 
31 #include <bpt.h>
32 #include <renderer.h>
33 #include <cugar/basic/timer.h>
34 #include <cugar/basic/primitives.h>
35 #include <bsdf.h>
36 #include <edf.h>
37 #include <bpt_utils.h>
38 #include <bpt_context.h>
39 #include <bpt_kernels.h>
40 #include <bpt_control.h>
41 #include <bpt_samplers.h>
42 
43 #define SHIFT_RES 256u
44 
45 #define DEBUG_PIXEL (723 + 90*1600)
46 
49 
52 
55 struct BPTContext : BPTContextBase<BPTOptions>
56 {
57  BPTContext(
58  BPT& _bpt,
59  const RenderingContextView& _renderer) :
61  _renderer,
62  _bpt.m_light_vertices.view(),
63  _bpt.m_queues.view(_renderer.res_x * _renderer.res_y, _bpt.m_n_light_subpaths),
64  _bpt.m_options),
65  sequence(_bpt.m_sequence.view()) {}
66 
67  TiledSequenceView sequence;
68 };
69 
72 
73 namespace { // anonymous namespace
74 
77 
80 
85  struct BPTConfig : public BPTConfigBase
86  {
87  FERMAT_HOST_DEVICE FERMAT_FORCEINLINE
88  BPTConfig(BPTContext& _context) :
90  _context.options,
91  VertexSampling::kAll,
92  _context.options.single_connection ? VertexOrdering::kRandomOrdering : VertexOrdering::kPathOrdering,
93  VertexSampling::kAll,
94  _context.options.rr)
95  {}
96 
97  FERMAT_HOST_DEVICE FERMAT_FORCEINLINE
98  void visit_eye_vertex(
99  const uint32 path_id,
100  const uint32 depth,
101  const VertexGeometryId v_id,
102  const EyeVertex& v,
103  BPTContext& context,
104  RenderingContextView& renderer) const
105  {
106  // write out gbuffer information
107  if (depth == 1)
108  {
109  renderer.fb.gbuffer.geo(path_id) = GBufferView::pack_geometry(v.geom.position, v.geom.normal_s);
110  renderer.fb.gbuffer.uv(path_id) = make_float4(v_id.uv.x, v_id.uv.y, v.geom.texture_coords.x, v.geom.texture_coords.y);
111  renderer.fb.gbuffer.tri(path_id) = v_id.prim_id;
112  }
113  }
114  };
116 
122  template <bool USE_ATOMICS>
123  struct ConnectionsSink : SampleSinkBase
124  {
125  FERMAT_HOST_DEVICE
126  ConnectionsSink() {}
127 
128  // accumulate a bidirectional sample
129  //
130  FERMAT_HOST_DEVICE
131  void sink(
132  const uint32 channel,
133  const cugar::Vector4f value,
134  const uint32 light_path_id,
135  const uint32 eye_path_id,
136  const uint32 s,
137  const uint32 t,
138  BPTContext& context,
139  RenderingContextView& renderer)
140  {
141  const float frame_weight = 1.0f / float(renderer.instance + 1);
142 
143  if (USE_ATOMICS)
144  {
145  cugar::atomic_add(&renderer.fb(FBufferDesc::COMPOSITED_C, eye_path_id).x, value.x * frame_weight);
146  cugar::atomic_add(&renderer.fb(FBufferDesc::COMPOSITED_C, eye_path_id).y, value.y * frame_weight);
147  cugar::atomic_add(&renderer.fb(FBufferDesc::COMPOSITED_C, eye_path_id).z, value.z * frame_weight);
148 
149  if (channel != FBufferDesc::COMPOSITED_C)
150  {
151  cugar::atomic_add(&renderer.fb(channel, eye_path_id).x, value.x * frame_weight);
152  cugar::atomic_add(&renderer.fb(channel, eye_path_id).y, value.y * frame_weight);
153  cugar::atomic_add(&renderer.fb(channel, eye_path_id).z, value.z * frame_weight);
154  }
155  }
156  else
157  {
158  renderer.fb(FBufferDesc::COMPOSITED_C, eye_path_id) += value * frame_weight;
159 
160  if (channel != FBufferDesc::COMPOSITED_C)
161  renderer.fb(channel, eye_path_id) += value * frame_weight;
162  }
163  }
164 
165  // record an eye scattering event
166  //
167  FERMAT_HOST_DEVICE
168  void sink_eye_scattering_event(
169  const Bsdf::ComponentType component,
170  const cugar::Vector4f value,
171  const uint32 eye_path_id,
172  const uint32 t,
173  BPTContext& context,
174  RenderingContextView& renderer)
175  {
176  if (t == 2) // accumulate the albedo of visible surfaces
177  {
178  const float frame_weight = 1.0f / float(renderer.instance + 1);
179 
180  if (component == Bsdf::kDiffuseReflection)
181  renderer.fb(FBufferDesc::DIFFUSE_A, eye_path_id) += value * frame_weight;
182  else if (component == Bsdf::kGlossyReflection)
183  renderer.fb(FBufferDesc::SPECULAR_A, eye_path_id) += value * frame_weight;
184  }
185  }
186  };
188 
191 
192 } // anonymous namespace
193 
194 
196 void BPT::render(const uint32 instance, RenderingContext& renderer)
197 {
198  // pre-multiply the previous frame for blending
199  renderer.multiply_frame(float(instance) / float(instance + 1));
200 
201  cugar::Timer timer;
202  timer.start();
203 
204  // get a view of the renderer
205  RenderingContextView renderer_view = renderer.view(instance);
206 
207  // initialize the sampling sequence for this frame
208  m_sequence.set_instance(instance);
209 
210  // setup our BPT context
211  BPTContext context(*this,renderer_view);
212 
213  // setup our BPT configuration
214  BPTConfig config(context);
215 
216  // sample a set of bidirectional paths corresponding to our current primary coordinates
217  TiledLightSubpathPrimaryCoords light_primary_coords(context.sequence);
218 
219  PerPixelEyeSubpathPrimaryCoords eye_primary_coords(context.sequence, renderer.res().x, renderer.res().y);
220 
221  ConnectionsSink<false> sink;
222 
223  // debug only: regenerate the VPLs
224  //regenerate_primary_light_vertices(instance, renderer);
225 
227  m_n_eye_subpaths,
228  m_n_light_subpaths,
229  eye_primary_coords,
230  light_primary_coords,
231  sink,
232  context,
233  config,
234  renderer,
235  renderer_view);
236 
237  // solve pure light tracing occlusions
238  {
239  ConnectionsSink<true> atomic_sink;
240 
242  m_n_light_subpaths,
243  atomic_sink,
244  context,
245  config,
246  renderer,
247  renderer_view);
248  }
249 
250  timer.stop();
251  const float time = timer.seconds();
252 
253  // clear the global timer at instance zero
254  m_time = (instance == 0) ? time : time + m_time;
255 
256  fprintf(stderr, "\r %.1fs (%.1fms) ",
257  m_time,
258  time * 1000.0f);
259 }
Definition: bpt_impl.h:55
void sample_paths(const uint32 n_eye_paths, const uint32 n_light_paths, TEyePrimaryCoordinates eye_primary_coords, TLightPrimaryCoordinates light_primary_coords, TSampleSink sample_sink, TBPTContext &context, const TBPTConfig &config, RenderingContext &renderer, RenderingContextView &renderer_view, const bool lazy_shadows=false)
Definition: bpt_control.h:529
void stop()
stop timing
Definition: timer.cpp:123
Definition: vertex.h:105
void start()
start timing
Definition: timer.cpp:116
CUGAR_FORCEINLINE CUGAR_HOST_DEVICE float atomic_add(float *value, const float op)
Definition: atomics.h:100
ComponentType
Definition: bsdf.h:139
Definition: timer.h:83
Definition: tiled_sequence.h:53
Definition: bpt.h:83
Definition: bpt_utils.h:583
Definition: bpt_samplers.h:59
Definition: bpt_samplers.h:43
RenderingContextView view(const uint32 instance)
Definition: bpt_context.h:54
void light_tracing(const uint32 n_light_paths, TSampleSink sample_sink, TBPTContext &context, const TBPTConfig &config, RenderingContext &renderer, RenderingContextView &renderer_view)
Definition: bpt_control.h:576
Definition: bpt_kernels.h:216
uint2 res() const
Definition: renderer.h:52
void render(const uint32 instance, RenderingContext &renderer)
[BPT::render]
Definition: bpt_impl.h:196
Definition: bpt_kernels.h:56
void multiply_frame(const float scale)
Definition: renderer_view.h:80