Fermat
multijitter.h
1 /*
2  * Copyright (c) 2010-2018, NVIDIA Corporation
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are met:
7  * * Redistributions of source code must retain the above copyright
8  * notice, this list of conditions and the following disclaimer.
9  * * Redistributions in binary form must reproduce the above copyright
10  * notice, this list of conditions and the following disclaimer in the
11  * documentation and/or other materials provided with the distribution.
12  * * Neither the name of NVIDIA Corporation nor the
13  * names of its contributors may be used to endorse or promote products
14  * derived from this software without specific prior written permission.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
17  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19  * DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
20  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26  */
27 
39 #pragma once
40 
41 #include <cugar/linalg/vector.h>
42 #include <cugar/sampling/random.h>
43 #include <vector>
44 #include <algorithm>
45 
46 
47 namespace cugar {
48 
59 CUGAR_FORCEINLINE CUGAR_HOST_DEVICE
63 float2 correlated_multijitter(uint32 s, const uint32 m, const uint32 n, const uint32 p, bool ordered = false)
64 {
65  if (ordered)
66  {
67  const uint32 sx = permute(s % m, m, p * 0xa511e9b3);
68  const uint32 sy = permute(s / m, n, p * 0x63d83595);
69  const float jx = randfloat(s, p * 0xa399d265);
70  const float jy = randfloat(s, p * 0x711ad6a5);
71  return make_float2(
72  (s % m + (sy + jx) / n) / m,
73  (s / m + (sx + jy) / m) / n );
74  }
75  else
76  {
77  s = permute(s, m * n, p * 0x51633e2d);
78  const uint32 x = s % m;
79  const uint32 y = s / m;
80  const uint32 sx = permute(x, m, p * 0x68bc21eb);
81  const uint32 sy = permute(y, n, p * 0x02e5be93);
82  float jx = randfloat(s, p * 0x967a889b);
83  float jy = randfloat(s, p * 0x368cc8b7);
84  return make_float2(
85  (sx + (sy + jx) / n) / m,
86  (y + (x + jy) / m) / n );
87  }
88 }
89 
94 {
95  CUGAR_FORCEINLINE CUGAR_HOST_DEVICE
96  CorrelatedMJSampler(const uint32 _s, const uint32 _m, const uint32 _n, const uint32 _p) :
97  s(_s), m(_m), n(_n), p(_p), c(-1.0f) {}
98 
99  CUGAR_FORCEINLINE CUGAR_HOST_DEVICE
100  float next()
101  {
102  if (c != -1.0f)
103  {
104  const float r = c; c = -1.0f;
105  return r;
106  }
107  else
108  {
109  const float2 r = correlated_multijitter( s, m, n, p++ );
110  c = r.y;
111  return r.x;
112  }
113  }
114 
115  uint32 s;
116  uint32 m;
117  uint32 n;
118  uint32 p;
119  float c;
120 };
121 
126 CUGAR_FORCEINLINE CUGAR_HOST_DEVICE
127 float3 correlated_multijitter_3d(uint32 s, const uint32 X, const uint32 Y, const uint32 Z, const uint32 p)
128 {
129 #if 0
130  const uint32 x = s % X;
131  const uint32 y = (s / X) % Y;
132  const uint32 z = (s / X) / Y;
133 
134  const uint32 ss = permute(s, X * Y * Z, p * 0x68bc21eb); // globally permute the sample
135  //const uint32 x = ss % X;
136  //const uint32 y = (ss / X) % Y;
137  //const uint32 z = (ss / X) / Y;
138 
139  const uint32 sz = (ss / X) / Y; // pick the globally permuted Z
140  const uint32 sx = permute(x, X, p * 0xa511e9b3 + (z+1) * 0x02e5be93); // permute the local X
141  const uint32 sy = permute(y, Y, p * 0x63d83595 + (z+1) * 0x51633e2d); // permute the local Y
142  const float jx = randfloat(s, p * 0xa399d265);
143  const float jy = randfloat(s, p * 0x711ad6a5);
144  const float jz = randfloat(s, p * 0x368cc8b7);
145 
146  const uint32 ssz = permute(sz, Z, p * 0x63d83595 + (sx + sy*X) * 19236698399u);
147  //const uint32 ssx = permute(sx, Z, p * 0x63d83595 + (sy + sz*Y) * 19021525571u);
148  const uint32 ssx = ss % X;
149  const uint32 ssy = (ss / X) % Y;
150  return make_float3(
151  #if 0
152  // completely correlated in time
153  (x + (sy + (sz + jx) / Z) / Y) / X,
154  (y + (sz + (sx + jy) / X) / Z) / Y,
155  #elif 0
156  // much more uniform, but strongly correlated in time (i.e. along s)
157  (sx + (y + (sz + jx) / Z) / Y) / X,
158  (sy + (sz + (x + jy) / X) / Z) / Y,
159  #elif 1
160  (sx + (sy + (sz + jx) / Z) / Y) / X,
161  (ssy + (sz + (x + jy) / X) / Z) / Y,
162  #endif
163  (ssz + (ssx + (ssy + jz) / Y) / X) / Z );
164 #elif 0
165  const uint32 z = (s / X) / Y;
166  const uint32 sxy = permute(s % (X * Y), X * Y, p * 0x51633e2d + z * 0x63d83595); // permute x and y within each z slice
167  const uint32 x = (sxy % X);
168  const uint32 y = (sxy / X) % Y;
169  const uint32 sx = permute(x, X, p * 0x68bc21eb); // permute x locally
170  const uint32 sy = permute(y, Y, p * 0x02e5be93); // permute y locally
171  const uint32 sz = permute(z, Z, p * 0x51633e2d); // permute z locally
172  const float jx = randfloat(s, p * 0x967a889b);
173  const float jy = randfloat(s, p * 0x368cc8b7);
174  const float jz = randfloat(s, p * 0x711ad6a5);
175  const uint32 ssz = permute(sz, Z, p * 0x63d83595 + (sx + sy*X) * 19236698399u);
176  const uint32 ssx = permute(sx, Z, p * 0x63d83595 + (sy + sz*Y) * 19021525571u);
177  return make_float3(
178  (sx + (sy + (sz + jx) / Z) / Y) / X,
179  ( y + ( x + (ssz + jy) / Z) / X) / Y,
180  (ssz + (ssx + (sy + jz) / Y) / X) / Z );
181 #elif 1
182  const uint32 z = (s / X) / Y;
183  const uint32 sxy = permute(s % (X * Y), X * Y, p * 0x51633e2d + z * 0x63d83595); // permute x and y within each z slice
184  const uint32 x = (sxy % X);
185  const uint32 y = (sxy / X) % Y;
186 
187  const uint32 sxz = permute((s % X) + z * X, X * Z, p * 0x63d83595 + ((s / X) % Y) * 3000004171u); // permute x and z within each y slice
188  const uint32 ssx = (sxz % X);
189  const uint32 ssz = (sxz / X);
190 
191  const uint32 sx = permute(x, X, p * 0x68bc21eb); // permute x locally
192  const uint32 sy = permute(y, Y, p * 0x02e5be93); // permute y locally
193  const uint32 sz = permute(z, Z, p * 0x51633e2d); // permute z locally
194 
195  const float jx = randfloat(s, p * 0x967a889b);
196  const float jy = randfloat(s, p * 0x368cc8b7);
197  const float jz = randfloat(s, p * 0x711ad6a5);
198 
199  return make_float3(
200  (sx + (sy + (sz + jx) / Z) / Y) / X,
201  ( y + ( x + (ssz + jy) / Z) / X) / Y,
202  (ssz + (ssx + (sy + jz) / Y) / X) / Z );
203 #endif
204 }
205 
209 struct MJSampler
210 {
211  enum Ordering
212  {
213  kXY,
214  kRandom
215  };
216 
219  MJSampler(const uint32 seed = 0) : m_random(seed) {}
220 
223  template <typename T>
224  void sample(
225  const uint32 samples_x,
226  const uint32 samples_y,
227  Vector<T,2>* samples,
228  Ordering ordering = kRandom);
229 
233  template <typename T>
234  void sample(
235  const uint32 samples_x,
236  const uint32 samples_y,
237  Vector<T,3>* samples);
238 
241  template <typename T>
242  void sample(
243  const uint32 samples_x,
244  const uint32 samples_y,
245  Vector<T,4>* samples,
246  Ordering ordering = kRandom);
247 
248  struct Sample
249  {
250  uint32 x;
251  uint32 y;
252  };
253  std::vector<Sample> m_sample_xy;
254  Random m_random;
255 };
256 
263 } // namespace cugar
264 
265 #include <cugar/sampling/multijitter_inline.h>
Definition: multijitter.h:209
CUGAR_FORCEINLINE CUGAR_HOST_DEVICE uint32 permute(uint32 i, uint32 l, uint32 p)
Definition: numbers.h:836
Definition: vector.h:130
MJSampler(const uint32 seed=0)
Definition: multijitter.h:219
Definition: random.h:79
Definition: multijitter.h:248
CUGAR_FORCEINLINE CUGAR_HOST_DEVICE float3 correlated_multijitter_3d(uint32 s, const uint32 X, const uint32 Y, const uint32 Z, const uint32 p)
Definition: multijitter.h:127
Define a vector_view POD type and plain_view() for std::vector.
Definition: diff.h:38
Definition: vector.h:264
Defines several random samplers.
Definition: multijitter.h:93
Definition: vector.h:187
CUGAR_FORCEINLINE CUGAR_HOST_DEVICE float2 correlated_multijitter(uint32 s, const uint32 m, const uint32 n, const uint32 p, bool ordered=false)
Definition: multijitter.h:63
CUGAR_FORCEINLINE CUGAR_HOST_DEVICE float randfloat(unsigned i, unsigned p)
Definition: numbers.h:753