ssf_microfacet_distribution.c (4652B)
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 #include "ssf.h" 17 #include "ssf_microfacet_distribution_c.h" 18 19 #include <rsys/double3.h> 20 #include <rsys/mem_allocator.h> 21 #include <rsys/ref_count.h> 22 23 #include <string.h> 24 25 /******************************************************************************* 26 * Helper functions 27 ******************************************************************************/ 28 static INLINE int 29 check_microfacet_distribution_type 30 (const struct ssf_microfacet_distribution_type* type) 31 { 32 return type 33 && type->sample 34 && type->eval 35 && type->pdf 36 && IS_POW2(type->alignof_distribution); 37 } 38 39 static void 40 microfacet_distribution_release(ref_T* ref) 41 { 42 struct ssf_microfacet_distribution* distrib = 43 CONTAINER_OF(ref, struct ssf_microfacet_distribution, ref); 44 ASSERT(ref); 45 if(distrib->data) { 46 if(distrib->type.release) distrib->type.release(distrib->data); 47 MEM_RM(distrib->allocator, distrib->data); 48 } 49 MEM_RM(distrib->allocator, distrib); 50 } 51 52 /******************************************************************************* 53 * Exported functions 54 ******************************************************************************/ 55 res_T 56 ssf_microfacet_distribution_create 57 (struct mem_allocator* allocator, 58 const struct ssf_microfacet_distribution_type* type, 59 struct ssf_microfacet_distribution** out_distrib) 60 { 61 struct mem_allocator* mem_allocator = NULL; 62 struct ssf_microfacet_distribution* distrib = NULL; 63 res_T res = RES_OK; 64 65 if(!out_distrib || !check_microfacet_distribution_type(type)) { 66 res = RES_BAD_ARG; 67 goto error; 68 } 69 mem_allocator = allocator ? allocator : &mem_default_allocator; 70 distrib = MEM_CALLOC 71 (mem_allocator, 1, sizeof(struct ssf_microfacet_distribution)); 72 if(!distrib) { 73 res = RES_MEM_ERR; 74 goto error; 75 } 76 ref_init(&distrib->ref); 77 distrib->allocator = mem_allocator; 78 distrib->type = *type; 79 80 if(distrib->type.sizeof_distribution) { 81 distrib->data = MEM_ALLOC_ALIGNED 82 (distrib->allocator, 83 distrib->type.sizeof_distribution, 84 distrib->type.alignof_distribution); 85 if(!distrib->data) { 86 res = RES_MEM_ERR; 87 goto error; 88 } 89 memset(distrib->data, 0, distrib->type.sizeof_distribution); 90 if(distrib->type.init) { 91 res = distrib->type.init(mem_allocator, distrib->data); 92 if(res != RES_OK) goto error; 93 } 94 } 95 96 exit: 97 if(out_distrib) *out_distrib = distrib; 98 return res; 99 error: 100 if(distrib) { 101 SSF(microfacet_distribution_ref_put(distrib)); 102 distrib = NULL; 103 } 104 goto exit; 105 } 106 107 res_T 108 ssf_microfacet_distribution_ref_get(struct ssf_microfacet_distribution* distrib) 109 { 110 if(!distrib) return RES_BAD_ARG; 111 ref_get(&distrib->ref); 112 return RES_OK; 113 } 114 115 res_T 116 ssf_microfacet_distribution_ref_put(struct ssf_microfacet_distribution* distrib) 117 { 118 if(!distrib) return RES_BAD_ARG; 119 ref_put(&distrib->ref, microfacet_distribution_release); 120 return RES_OK; 121 } 122 123 void 124 ssf_microfacet_distribution_sample 125 (struct ssf_microfacet_distribution* distrib, 126 struct ssp_rng* rng, 127 const double N[3], 128 double wh[3], 129 double* out_pdf) 130 { 131 ASSERT(distrib && rng && N && wh); 132 ASSERT(d3_is_normalized(N)); 133 distrib->type.sample(distrib->data, rng, N, wh, out_pdf); 134 } 135 136 double 137 ssf_microfacet_distribution_eval 138 (struct ssf_microfacet_distribution* distrib, 139 const double N[3], 140 const double wh[3]) 141 { 142 ASSERT(distrib && N && wh); 143 ASSERT(d3_is_normalized(N) && d3_is_normalized(wh)); 144 return distrib->type.eval(distrib->data, N, wh); 145 } 146 147 double 148 ssf_microfacet_distribution_pdf 149 (struct ssf_microfacet_distribution* distrib, 150 const double N[3], 151 const double wh[3]) 152 { 153 ASSERT(distrib && wh ); 154 ASSERT(d3_is_normalized(N) && d3_is_normalized(wh)); 155 return distrib->type.pdf(distrib->data, N, wh); 156 } 157 158 res_T 159 ssf_microfacet_distribution_get_data 160 (struct ssf_microfacet_distribution* distrib, void** data) 161 { 162 if(!distrib || !data) return RES_BAD_ARG; 163 *data = distrib->data; 164 return RES_OK; 165 } 166