Blender V2.61 - r43446
|
00001 /* 00002 * Copyright 2011, Blender Foundation. 00003 * 00004 * This program is free software; you can redistribute it and/or 00005 * modify it under the terms of the GNU General Public License 00006 * as published by the Free Software Foundation; either version 2 00007 * of the License, or (at your option) any later version. 00008 * 00009 * This program is distributed in the hope that it will be useful, 00010 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00012 * GNU General Public License for more details. 00013 * 00014 * You should have received a copy of the GNU General Public License 00015 * along with this program; if not, write to the Free Software Foundation, 00016 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 00017 */ 00018 00019 CCL_NAMESPACE_BEGIN 00020 00021 typedef uint RNG; 00022 00023 #ifdef __SOBOL__ 00024 00025 /* skip initial numbers that are not as well distributed, especially the 00026 first sequence is just 0 everywhere, which can be problematic for e.g. 00027 path termination */ 00028 #define SOBOL_SKIP 64 00029 00030 /* High Dimensional Sobol */ 00031 00032 /* van der corput radical inverse */ 00033 __device uint van_der_corput(uint bits) 00034 { 00035 bits = (bits << 16) | (bits >> 16); 00036 bits = ((bits & 0x00ff00ff) << 8) | ((bits & 0xff00ff00) >> 8); 00037 bits = ((bits & 0x0f0f0f0f) << 4) | ((bits & 0xf0f0f0f0) >> 4); 00038 bits = ((bits & 0x33333333) << 2) | ((bits & 0xcccccccc) >> 2); 00039 bits = ((bits & 0x55555555) << 1) | ((bits & 0xaaaaaaaa) >> 1); 00040 return bits; 00041 } 00042 00043 /* sobol radical inverse */ 00044 __device uint sobol(uint i) 00045 { 00046 uint r = 0; 00047 00048 for(uint v = 1U << 31; i; i >>= 1, v ^= v >> 1) 00049 if(i & 1) 00050 r ^= v; 00051 00052 return r; 00053 } 00054 00055 /* inverse of sobol radical inverse */ 00056 __device uint sobol_inverse(uint i) 00057 { 00058 const uint msb = 1U << 31; 00059 uint r = 0; 00060 00061 for(uint v = 1; i; i <<= 1, v ^= v << 1) 00062 if(i & msb) 00063 r ^= v; 00064 00065 return r; 00066 } 00067 00068 /* multidimensional sobol with generator matrices 00069 dimension 0 and 1 are equal to van_der_corput() and sobol() respectively */ 00070 __device uint sobol_dimension(KernelGlobals *kg, int index, int dimension) 00071 { 00072 uint result = 0; 00073 uint i = index; 00074 00075 for(uint j = 0; i; i >>= 1, j++) 00076 if(i & 1) 00077 result ^= kernel_tex_fetch(__sobol_directions, 32*dimension + j); 00078 00079 return result; 00080 } 00081 00082 /* lookup index and x/y coordinate, assumes m is a power of two */ 00083 __device uint sobol_lookup(const uint m, const uint frame, const uint ex, const uint ey, uint *x, uint *y) 00084 { 00085 /* shift is constant per frame */ 00086 const uint shift = frame << (m << 1); 00087 const uint sobol_shift = sobol(shift); 00088 /* van der Corput is its own inverse */ 00089 const uint lower = van_der_corput(ex << (32 - m)); 00090 /* need to compensate for ey difference and shift */ 00091 const uint sobol_lower = sobol(lower); 00092 const uint mask = ~-(1 << m) << (32 - m); /* only m upper bits */ 00093 const uint delta = ((ey << (32 - m)) ^ sobol_lower ^ sobol_shift) & mask; 00094 /* only use m upper bits for the index (m is a power of two) */ 00095 const uint sobol_result = delta | (delta >> m); 00096 const uint upper = sobol_inverse(sobol_result); 00097 const uint index = shift | upper | lower; 00098 *x = van_der_corput(index); 00099 *y = sobol_shift ^ sobol_result ^ sobol_lower; 00100 return index; 00101 } 00102 00103 __device_inline float path_rng(KernelGlobals *kg, RNG *rng, int sample, int dimension) 00104 { 00105 #ifdef __SOBOL_FULL_SCREEN__ 00106 uint result = sobol_dimension(kg, *rng, dimension); 00107 float r = (float)result * (1.0f/(float)0xFFFFFFFF); 00108 return r; 00109 #else 00110 /* compute sobol sequence value using direction vectors */ 00111 uint result = sobol_dimension(kg, sample + SOBOL_SKIP, dimension); 00112 float r = (float)result * (1.0f/(float)0xFFFFFFFF); 00113 00114 /* Cranly-Patterson rotation using rng seed */ 00115 float shift; 00116 00117 if(dimension & 1) 00118 shift = (*rng >> 16)/((float)0xFFFF); 00119 else 00120 shift = (*rng & 0xFFFF)/((float)0xFFFF); 00121 00122 return r + shift - floor(r + shift); 00123 #endif 00124 } 00125 00126 __device_inline void path_rng_init(KernelGlobals *kg, __global uint *rng_state, int sample, RNG *rng, int x, int y, int offset, int stride, float *fx, float *fy) 00127 { 00128 #ifdef __SOBOL_FULL_SCREEN__ 00129 uint px, py; 00130 uint bits = 16; /* limits us to 65536x65536 and 65536 samples */ 00131 uint size = 1 << bits; 00132 uint frame = sample; 00133 00134 *rng = sobol_lookup(bits, frame, x, y, &px, &py); 00135 00136 *rng ^= kernel_data.integrator.seed; 00137 00138 *fx = size * (float)px * (1.0f/(float)0xFFFFFFFF) - x; 00139 *fy = size * (float)py * (1.0f/(float)0xFFFFFFFF) - y; 00140 #else 00141 *rng = rng_state[offset + x + y*stride]; 00142 00143 *rng ^= kernel_data.integrator.seed; 00144 00145 *fx = path_rng(kg, rng, sample, PRNG_FILTER_U); 00146 *fy = path_rng(kg, rng, sample, PRNG_FILTER_V); 00147 #endif 00148 } 00149 00150 __device void path_rng_end(KernelGlobals *kg, __global uint *rng_state, RNG rng, int x, int y, int offset, int stride) 00151 { 00152 /* nothing to do */ 00153 } 00154 00155 #else 00156 00157 /* Linear Congruential Generator */ 00158 00159 __device float path_rng(KernelGlobals *kg, RNG *rng, int sample, int dimension) 00160 { 00161 /* implicit mod 2^32 */ 00162 *rng = (1103515245*(*rng) + 12345); 00163 return (float)*rng * (1.0f/(float)0xFFFFFFFF); 00164 } 00165 00166 __device void path_rng_init(KernelGlobals *kg, __global uint *rng_state, int sample, RNG *rng, int x, int y, int offset, int stride, float *fx, float *fy) 00167 { 00168 /* load state */ 00169 *rng = rng_state[offset + x + y*stride]; 00170 00171 *rng ^= kernel_data.integrator.seed; 00172 00173 *fx = path_rng(kg, rng, sample, PRNG_FILTER_U); 00174 *fy = path_rng(kg, rng, sample, PRNG_FILTER_V); 00175 } 00176 00177 __device void path_rng_end(KernelGlobals *kg, __global uint *rng_state, RNG rng, int x, int y, int offset, int stride) 00178 { 00179 /* store state for next sample */ 00180 rng_state[offset + x + y*stride] = rng; 00181 } 00182 00183 #endif 00184 00185 CCL_NAMESPACE_END 00186