Fermat
bpt_samplers.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 <tiled_sequence.h>
33 
36 
39 
44 {
45  FERMAT_HOST_DEVICE FERMAT_FORCEINLINE
46  TiledLightSubpathPrimaryCoords(const TiledSequenceView _sequence) : sequence(_sequence) {}
47 
48  FERMAT_HOST_DEVICE FERMAT_FORCEINLINE
49  float sample(const uint32 idx, const uint32 vertex, const uint32 dim) const { return sequence.sample(idx, vertex * 3 + dim); }
50 
51  const TiledSequenceView sequence;
52 };
53 
60 {
61  FERMAT_HOST_DEVICE FERMAT_FORCEINLINE
62  PerPixelEyeSubpathPrimaryCoords(const TiledSequenceView _sequence, const uint32 _res_x, const uint32 _res_y) :
63  sequence(_sequence), res_x(_res_x), res_y(_res_y) {}
64 
65  FERMAT_HOST_DEVICE FERMAT_FORCEINLINE
66  float sample(const uint32 idx, const uint32 vertex, const uint32 dim) const
67  {
68  const uint32 pixel_x = idx % res_x;
69  const uint32 pixel_y = idx / res_x;
70 
71  if (vertex == 1 && dim < 2)
72  {
73  // use an optimized sampling pattern to rotate a Halton sequence
74  return dim == 0 ?
75  (pixel_x + sequence.sample_2d(pixel_x, pixel_y, dim)) / float(res_x) :
76  (pixel_y + sequence.sample_2d(pixel_x, pixel_y, dim)) / float(res_y);
77  }
78  else
79  return sequence.sample_2d(pixel_x, pixel_y, (vertex - 1) * 6 + dim);
80  }
81 
82  const TiledSequenceView sequence;
83  const uint32 res_x;
84  const uint32 res_y;
85 };
86 
91 {
92  enum Type
93  {
94  Null = 0x0,
95  CauchyPerturbation = 0x1,
96  IndependentSample = 0x2
97  };
98 
99  FERMAT_HOST_DEVICE FERMAT_FORCEINLINE
100  uint32 chain_coordinate_index(const uint32 idx, const uint32 dim) const
101  {
102  return dim*n_chains + idx;
103  }
104 
105  FERMAT_HOST_DEVICE FERMAT_FORCEINLINE
107  const uint32 _n_chains,
108  float* _path_u,
109  const uint32 _path_vertex_offset,
110  float* _mut_u,
111  const uint32 _mut_vertex_offset,
112  const Type _type,
113  const float _radius = 0.01f) :
114  path_u(_path_u + _path_vertex_offset * 3 * _n_chains),
115  mut_u(_mut_u + _mut_vertex_offset * 3 * _n_chains),
116  n_chains(_n_chains),
117  type(_type),
118  radius(_radius)
119  {}
120 
121  FERMAT_HOST_DEVICE FERMAT_FORCEINLINE
122  float sample(const uint32 idx, const uint32 vertex, const uint32 dim) const { return perturbed_u(idx, vertex * 3 + dim); }
123 
124  FERMAT_HOST_DEVICE FERMAT_FORCEINLINE
125  float u_m(const uint32 chain_id, const uint32 dim) const { return mut_u[chain_coordinate_index(chain_id, dim)]; }
126 
127  FERMAT_HOST_DEVICE FERMAT_FORCEINLINE
128  float& u(const uint32 chain_id, const uint32 dim) { return path_u[chain_coordinate_index(chain_id, dim)]; }
129 
130  FERMAT_HOST_DEVICE FERMAT_FORCEINLINE
131  const float& u(const uint32 chain_id, const uint32 dim) const { return path_u[chain_coordinate_index(chain_id, dim)]; }
132 
133  FERMAT_HOST_DEVICE FERMAT_FORCEINLINE
134  float perturbed_u(const uint32 chain_id, const uint32 dim) const
135  {
136  if (type == CauchyPerturbation)
137  {
138  cugar::Cauchy_distribution cauchy(radius);
139 
140  return cugar::mod(u(chain_id, dim) + cauchy.map(u_m(chain_id, dim)), 1.0f);
141  }
142  else if (type == IndependentSample)
143  {
144  return u_m(chain_id, dim);
145  }
146  else
147  return u(chain_id, dim);
148  }
149 
150  float* path_u;
151  float* mut_u;
152  uint32 n_chains;
153  Type type;
154  float radius;
155 };
156 
Defines various distributions.
float CUGAR_HOST_DEVICE mod(const float x, const float m)
Definition: numbers.h:606
Definition: tiled_sequence.h:53
Definition: bpt_samplers.h:90
Definition: bpt_samplers.h:59
Definition: bpt_samplers.h:43
Definition: distributions.h:295
CUGAR_HOST_DEVICE float map(const float U) const
Definition: distributions.h:306