test_ssf_utils.h (6927B)
1 /* Copyright (C) 2016-2018, 2021-2025 |Méso|Star> (contact@meso-star.com) 2 * 3 * This program is free software: you can redistribute it and/or modify 4 * it under the terms of the GNU General Public License as published by 5 * the Free Software Foundation, either version 3 of the License, or 6 * (at your option) any later version. 7 * 8 * This program is distributed in the hope that it will be useful, 9 * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 * GNU General Public License for more details. 12 * 13 * You should have received a copy of the GNU General Public License 14 * along with this program. If not, see <http://www.gnu.org/licenses/>. */ 15 16 #ifndef TEST_SSF_UTILS_H 17 #define TEST_SSF_UTILS_H 18 19 #include <rsys/double33.h> 20 #include <rsys/math.h> 21 #include <rsys/mem_allocator.h> 22 23 #include <star/ssp.h> 24 25 #include <stdio.h> 26 27 #ifdef COMPILER_CL 28 #pragma warning(disable:4324) /* Structre was padded due to alignment */ 29 #endif 30 31 /******************************************************************************* 32 * Dummy BSDF type 33 ******************************************************************************/ 34 static res_T 35 bsdf_dummy_init(struct mem_allocator* allocator, void* bsdf) 36 { 37 (void)allocator, (void)bsdf; 38 return RES_OK; 39 } 40 41 static void 42 bsdf_dummy_release(void* bsdf) 43 { 44 (void)bsdf; 45 } 46 47 static double 48 bsdf_dummy_sample 49 (void* bsdf, 50 struct ssp_rng* rng, 51 const double w[3], 52 const double N[3], 53 double dir[3], 54 int* type, 55 double* pdf) 56 { 57 (void)bsdf, (void)rng, (void)w, (void)N, (void)dir, (void)type, (void)pdf; 58 return 0.0; 59 } 60 61 static double 62 bsdf_dummy_eval 63 (void* bsdf, 64 const double wo[3], 65 const double N[3], 66 const double wi[3]) 67 { 68 (void)bsdf, (void)wo, (void)N, (void)wi; 69 return 0.0; 70 } 71 72 static double 73 bsdf_dummy_pdf 74 (void* bsdf, 75 const double wo[3], 76 const double N[3], 77 const double wi[3]) 78 { 79 (void)bsdf, (void)wo, (void)N, (void)wi; 80 return 0.0; 81 } 82 83 static const struct ssf_bsdf_type bsdf_dummy = { 84 bsdf_dummy_init, 85 bsdf_dummy_release, 86 bsdf_dummy_sample, 87 bsdf_dummy_eval, 88 bsdf_dummy_pdf, 89 0, 1 90 }; 91 92 /******************************************************************************* 93 * Dummy Fresnel type 94 ******************************************************************************/ 95 static res_T 96 fresnel_dummy_init(struct mem_allocator* allocator, void* fresnel) 97 { 98 (void)allocator, (void)fresnel; 99 return RES_OK; 100 } 101 102 static void 103 fresnel_dummy_release(void* fresnel) 104 { 105 (void)fresnel; 106 } 107 108 static double 109 fresnel_dummy_eval 110 (void* fresnel, 111 const double cos_theta_i) 112 { 113 (void)fresnel, (void)cos_theta_i; 114 return 0.0; 115 } 116 117 static const struct ssf_fresnel_type fresnel_dummy = { 118 fresnel_dummy_init, 119 fresnel_dummy_release, 120 fresnel_dummy_eval, 121 0, 1 122 }; 123 124 /******************************************************************************* 125 * Dummy microfacet distribution type 126 ******************************************************************************/ 127 static res_T 128 microfacet_dummy_init(struct mem_allocator* allocator, void* distrib) 129 { 130 (void)allocator, (void)distrib; 131 return RES_OK; 132 } 133 134 static void 135 microfacet_dummy_release(void* distrib) 136 { 137 (void)distrib; 138 } 139 140 static void 141 microfacet_dummy_sample 142 (void* distrib, 143 struct ssp_rng* rng, 144 const double N[3], 145 double dir[3], 146 double* pdf) 147 { 148 (void)distrib, (void)rng, (void)N, (void)dir, (void)pdf; 149 } 150 151 static double 152 microfacet_dummy_eval 153 (void* distrib, 154 const double N[3], 155 const double wi[3]) 156 { 157 (void)distrib, (void)N, (void)wi; 158 return 0.0; 159 } 160 161 static double 162 microfacet_dummy_pdf 163 (void* distrib, 164 const double N[3], 165 const double wi[3]) 166 { 167 (void)distrib, (void)N, (void)wi; 168 return 0.0; 169 } 170 171 static const struct ssf_microfacet_distribution_type microfacet_dummy = { 172 microfacet_dummy_init, 173 microfacet_dummy_release, 174 microfacet_dummy_sample, 175 microfacet_dummy_eval, 176 microfacet_dummy_pdf, 177 0, 1 178 }; 179 180 /******************************************************************************* 181 * Dummy Phase function type 182 ******************************************************************************/ 183 static res_T 184 phase_dummy_init(struct mem_allocator* allocator, void* phase) 185 { 186 (void)allocator, (void)phase; 187 return RES_OK; 188 } 189 190 static void 191 phase_dummy_release(void* phase) 192 { 193 (void)phase; 194 } 195 196 static void 197 phase_dummy_sample 198 (void* phase, 199 struct ssp_rng* rng, 200 const double w[3], 201 double dir[3], 202 double* pdf) 203 { 204 (void)phase, (void)rng, (void)w, (void)dir, (void)pdf; 205 } 206 207 static double 208 phase_dummy_eval 209 (void* phase, 210 const double wo[3], 211 const double wi[3]) 212 { 213 (void)phase, (void)wo, (void)wi; 214 return 0.0; 215 } 216 217 static double 218 phase_dummy_pdf 219 (void* phase, 220 const double wo[3], 221 const double wi[3]) 222 { 223 (void)phase, (void)wo, (void)wi; 224 return 0.0; 225 } 226 227 static const struct ssf_phase_type phase_dummy = { 228 phase_dummy_init, 229 phase_dummy_release, 230 phase_dummy_sample, 231 phase_dummy_eval, 232 phase_dummy_pdf, 233 0, 1 234 }; 235 236 /******************************************************************************* 237 * Miscellaneous functions 238 ******************************************************************************/ 239 static INLINE void 240 check_microfacet_distribution 241 (struct ssf_microfacet_distribution* distrib, 242 struct ssp_rng* rng) 243 { 244 double N[3]; 245 const size_t NSTEPS = 10000; 246 size_t i; 247 size_t n; 248 double sample[3]; 249 double E, V, SE; 250 double sum, sum2; 251 252 N[0] = ssp_rng_uniform_double(rng, -1, 1); 253 N[1] = ssp_rng_uniform_double(rng, -1, 1); 254 N[2] = ssp_rng_uniform_double(rng, -1, 1); 255 d3_normalize(N, N); 256 257 /* Check that D(wh) is normalized wrt \int_{2PI} D(wh) |wh.n| dwh */ 258 sum = sum2 = 0; 259 n = 0; 260 do { 261 FOR_EACH(i, 0, NSTEPS) { 262 double wh[3], pdf, D, weight; 263 ssp_ran_hemisphere_cos(rng, N, sample, &pdf); 264 d3_set(wh, sample); 265 D = ssf_microfacet_distribution_eval(distrib, N, wh); 266 weight = D * d3_dot(wh, N) / pdf; 267 sum += weight; 268 sum2 += weight*weight; 269 } 270 n += NSTEPS; 271 E = sum / (double)n; 272 V = MMAX(sum2 / (double)n - E*E, 0); 273 SE = sqrt(V/(double)n); 274 } while(SE > E * 0.05); 275 CHK(eq_eps(E, 1.0, 3*SE) == 1); 276 277 /* Check the sampling of a direction wh and the returned pdf */ 278 FOR_EACH(i, 0, NSTEPS) { 279 double wh[3], pdf, D, weight; 280 281 ssf_microfacet_distribution_sample(distrib, rng, N, wh, &pdf); 282 D = ssf_microfacet_distribution_eval(distrib, N, wh); 283 weight = D * d3_dot(wh, N) / pdf; 284 CHK(eq_eps(weight, 1.0, 1.e-6) == 1); 285 CHK(eq_eps(pdf, ssf_microfacet_distribution_pdf(distrib, N, wh), 1.e-6f)); 286 287 ssf_microfacet_distribution_sample(distrib, rng, N, wh, NULL); 288 } 289 } 290 291 static INLINE void 292 check_memory_allocator(struct mem_allocator* allocator) 293 { 294 if(MEM_ALLOCATED_SIZE(allocator)) { 295 char dump[512]; 296 MEM_DUMP(allocator, dump, sizeof(dump)/sizeof(char)); 297 fprintf(stderr, "%s\n", dump); 298 FATAL("Memory leaks\n"); 299 } 300 } 301 302 #endif /* TEST_SSF_UTILS_H */ 303