Welcome to mirror list, hosted at ThFree Co, Russian Federation.

sobol_burley.h « sample « kernel « cycles « intern - git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
blob: 47796ae799812ffdc30b7dc67b2c7f1a85719f4b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
/* SPDX-License-Identifier: Apache-2.0
 * Copyright 2011-2022 Blender Foundation */

/*
 * A shuffled, Owen-scrambled Sobol sampler, implemented with the
 * techniques from the paper "Practical Hash-based Owen Scrambling"
 * by Brent Burley, 2020, Journal of Computer Graphics Techniques.
 *
 * Note that unlike a standard high-dimensional Sobol sequence, this
 * Sobol sampler uses padding to achieve higher dimensions, as described
 * in Burley's paper.
 */

#pragma once

#include "kernel/sample/util.h"
#include "util/hash.h"
#include "util/math.h"
#include "util/types.h"

CCL_NAMESPACE_BEGIN

/*
 * Computes a single dimension of a sample from an Owen-scrambled
 * Sobol sequence.  This is used in the main sampling functions,
 * sobol_burley_sample_#D(), below.
 *
 * - rev_bit_index: the sample index, with reversed order bits.
 * - dimension:     the sample dimension.
 * - scramble_seed: the Owen scrambling seed.
 *
 * Note that the seed must be well randomized before being
 * passed to this function.
 */
ccl_device_forceinline float sobol_burley(uint rev_bit_index,
                                          const uint dimension,
                                          const uint scramble_seed)
{
  uint result = 0;

  if (dimension == 0) {
    /* Fast-path for dimension 0, which is just Van der corput.
     * This makes a notable difference in performance since we reuse
     * dimensions for padding, and dimension 0 is reused the most. */
    result = reverse_integer_bits(rev_bit_index);
  }
  else {
    uint i = 0;
    while (rev_bit_index != 0) {
      uint j = count_leading_zeros(rev_bit_index);
      result ^= sobol_burley_table[dimension][i + j];
      i += j + 1;

      /* We can't do "<<= j + 1" because that can overflow the shift
       * operator, which doesn't do what we need on at least x86. */
      rev_bit_index <<= j;
      rev_bit_index <<= 1;
    }
  }

  /* Apply Owen scrambling. */
  result = reverse_integer_bits(reversed_bit_owen(result, scramble_seed));

  return uint_to_float_excl(result);
}

/*
 * Computes a 1D Owen-scrambled and shuffled Sobol sample.
 */
ccl_device float sobol_burley_sample_1D(uint index, uint const dimension, uint seed)
{
  /* Include the dimension in the seed, so we get decorrelated
   * sequences for different dimensions via shuffling. */
  seed ^= hash_hp_uint(dimension);

  /* Shuffle. */
  index = reversed_bit_owen(reverse_integer_bits(index), seed ^ 0xbff95bfe);

  return sobol_burley(index, 0, seed ^ 0x635c77bd);
}

/*
 * Computes a 2D Owen-scrambled and shuffled Sobol sample.
 */
ccl_device float2 sobol_burley_sample_2D(uint index, const uint dimension_set, uint seed)
{
  /* Include the dimension set in the seed, so we get decorrelated
   * sequences for different dimension sets via shuffling. */
  seed ^= hash_hp_uint(dimension_set);

  /* Shuffle. */
  index = reversed_bit_owen(reverse_integer_bits(index), seed ^ 0xf8ade99a);

  return make_float2(sobol_burley(index, 0, seed ^ 0xe0aaaf76),
                     sobol_burley(index, 1, seed ^ 0x94964d4e));
}

/*
 * Computes a 3D Owen-scrambled and shuffled Sobol sample.
 */
ccl_device float3 sobol_burley_sample_3D(uint index, const uint dimension_set, uint seed)
{
  /* Include the dimension set in the seed, so we get decorrelated
   * sequences for different dimension sets via shuffling. */
  seed ^= hash_hp_uint(dimension_set);

  /* Shuffle. */
  index = reversed_bit_owen(reverse_integer_bits(index), seed ^ 0xcaa726ac);

  return make_float3(sobol_burley(index, 0, seed ^ 0x9e78e391),
                     sobol_burley(index, 1, seed ^ 0x67c33241),
                     sobol_burley(index, 2, seed ^ 0x78c395c5));
}

/*
 * Computes a 4D Owen-scrambled and shuffled Sobol sample.
 */
ccl_device float4 sobol_burley_sample_4D(uint index, const uint dimension_set, uint seed)
{
  /* Include the dimension set in the seed, so we get decorrelated
   * sequences for different dimension sets via shuffling. */
  seed ^= hash_hp_uint(dimension_set);

  /* Shuffle. */
  index = reversed_bit_owen(reverse_integer_bits(index), seed ^ 0xc2c1a055);

  return make_float4(sobol_burley(index, 0, seed ^ 0x39468210),
                     sobol_burley(index, 1, seed ^ 0xe9d8a845),
                     sobol_burley(index, 2, seed ^ 0x5f32b482),
                     sobol_burley(index, 3, seed ^ 0x1524cc56));
}

CCL_NAMESPACE_END