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 /* Closure Nodes */ 00022 00023 __device void svm_node_glossy_setup(ShaderData *sd, ShaderClosure *sc, int type, float eta, float roughness, bool refract) 00024 { 00025 if(type == CLOSURE_BSDF_REFRACTION_ID) { 00026 if(refract) 00027 bsdf_refraction_setup(sd, sc, eta); 00028 else 00029 bsdf_reflection_setup(sd, sc); 00030 } 00031 else if(type == CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID) { 00032 bsdf_microfacet_beckmann_setup(sd, sc, roughness, eta, refract); 00033 } 00034 else 00035 bsdf_microfacet_ggx_setup(sd, sc, roughness, eta, refract); 00036 } 00037 00038 __device_inline ShaderClosure *svm_node_closure_get(ShaderData *sd) 00039 { 00040 #ifdef __MULTI_CLOSURE__ 00041 ShaderClosure *sc = &sd->closure[sd->num_closure]; 00042 00043 if(sd->num_closure < MAX_CLOSURE) 00044 sd->num_closure++; 00045 00046 return sc; 00047 #else 00048 return &sd->closure; 00049 #endif 00050 } 00051 00052 __device_inline void svm_node_closure_set_mix_weight(ShaderClosure *sc, float mix_weight) 00053 { 00054 #ifdef __MULTI_CLOSURE__ 00055 sc->weight *= mix_weight; 00056 sc->sample_weight = fabsf(average(sc->weight)); 00057 #endif 00058 } 00059 00060 __device void svm_node_closure_bsdf(KernelGlobals *kg, ShaderData *sd, float *stack, uint4 node, float randb, int path_flag) 00061 { 00062 uint type, param1_offset, param2_offset; 00063 00064 #ifdef __MULTI_CLOSURE__ 00065 uint mix_weight_offset; 00066 decode_node_uchar4(node.y, &type, ¶m1_offset, ¶m2_offset, &mix_weight_offset); 00067 float mix_weight = (stack_valid(mix_weight_offset)? stack_load_float(stack, mix_weight_offset): 1.0f); 00068 00069 if(mix_weight == 0.0f) 00070 return; 00071 #else 00072 decode_node_uchar4(node.y, &type, ¶m1_offset, ¶m2_offset, NULL); 00073 float mix_weight = 1.0f; 00074 #endif 00075 00076 float param1 = (stack_valid(param1_offset))? stack_load_float(stack, param1_offset): __int_as_float(node.z); 00077 float param2 = (stack_valid(param2_offset))? stack_load_float(stack, param2_offset): __int_as_float(node.w); 00078 00079 switch(type) { 00080 case CLOSURE_BSDF_DIFFUSE_ID: { 00081 ShaderClosure *sc = svm_node_closure_get(sd); 00082 svm_node_closure_set_mix_weight(sc, mix_weight); 00083 00084 float roughness = param1; 00085 if(roughness == 0.0f) 00086 bsdf_diffuse_setup(sd, sc); 00087 else 00088 bsdf_oren_nayar_setup(sd, sc, roughness); 00089 break; 00090 } 00091 case CLOSURE_BSDF_TRANSLUCENT_ID: { 00092 ShaderClosure *sc = svm_node_closure_get(sd); 00093 svm_node_closure_set_mix_weight(sc, mix_weight); 00094 bsdf_translucent_setup(sd, sc); 00095 break; 00096 } 00097 case CLOSURE_BSDF_TRANSPARENT_ID: { 00098 ShaderClosure *sc = svm_node_closure_get(sd); 00099 svm_node_closure_set_mix_weight(sc, mix_weight); 00100 bsdf_transparent_setup(sd, sc); 00101 break; 00102 } 00103 case CLOSURE_BSDF_REFLECTION_ID: 00104 case CLOSURE_BSDF_MICROFACET_GGX_ID: 00105 case CLOSURE_BSDF_MICROFACET_BECKMANN_ID: { 00106 #ifdef __CAUSTICS_TRICKS__ 00107 if(kernel_data.integrator.no_caustics && (path_flag & PATH_RAY_DIFFUSE)) 00108 break; 00109 #endif 00110 ShaderClosure *sc = svm_node_closure_get(sd); 00111 svm_node_closure_set_mix_weight(sc, mix_weight); 00112 00113 float roughness = param1; 00114 00115 /* setup bsdf */ 00116 if(type == CLOSURE_BSDF_REFLECTION_ID) 00117 bsdf_reflection_setup(sd, sc); 00118 else if(type == CLOSURE_BSDF_MICROFACET_BECKMANN_ID) 00119 bsdf_microfacet_beckmann_setup(sd, sc, roughness, 1.0f, false); 00120 else 00121 bsdf_microfacet_ggx_setup(sd, sc, roughness, 1.0f, false); 00122 00123 break; 00124 } 00125 case CLOSURE_BSDF_REFRACTION_ID: 00126 case CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID: 00127 case CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID: { 00128 #ifdef __CAUSTICS_TRICKS__ 00129 if(kernel_data.integrator.no_caustics && (path_flag & PATH_RAY_DIFFUSE)) 00130 break; 00131 #endif 00132 /* index of refraction */ 00133 float eta = fmaxf(param2, 1.0f + 1e-5f); 00134 eta = (sd->flag & SD_BACKFACING)? 1.0f/eta: eta; 00135 00136 /* fresnel */ 00137 float cosNO = dot(sd->N, sd->I); 00138 float fresnel = fresnel_dielectric_cos(cosNO, eta); 00139 float roughness = param1; 00140 00141 #ifdef __MULTI_CLOSURE__ 00142 /* reflection */ 00143 ShaderClosure *sc = svm_node_closure_get(sd); 00144 00145 float3 weight = sc->weight; 00146 float sample_weight = sc->sample_weight; 00147 00148 svm_node_closure_set_mix_weight(sc, mix_weight*fresnel); 00149 svm_node_glossy_setup(sd, sc, type, eta, roughness, false); 00150 00151 /* refraction */ 00152 sc = svm_node_closure_get(sd); 00153 00154 sc->weight = weight; 00155 sc->sample_weight = sample_weight; 00156 00157 svm_node_closure_set_mix_weight(sc, mix_weight*(1.0f - fresnel)); 00158 svm_node_glossy_setup(sd, sc, type, eta, roughness, true); 00159 #else 00160 ShaderClosure *sc = svm_node_closure_get(sd); 00161 00162 bool refract = (randb > fresnel); 00163 00164 svm_node_closure_set_mix_weight(sc, mix_weight); 00165 svm_node_glossy_setup(sd, sc, type, eta, roughness, refract); 00166 #endif 00167 00168 break; 00169 } 00170 #ifdef __DPDU__ 00171 case CLOSURE_BSDF_WARD_ID: { 00172 #ifdef __CAUSTICS_TRICKS__ 00173 if(kernel_data.integrator.no_caustics && (path_flag & PATH_RAY_DIFFUSE)) 00174 break; 00175 #endif 00176 ShaderClosure *sc = svm_node_closure_get(sd); 00177 svm_node_closure_set_mix_weight(sc, mix_weight); 00178 00179 float roughness_u = param1; 00180 float roughness_v = param2; 00181 00182 bsdf_ward_setup(sd, sc, normalize(sd->dPdu), roughness_u, roughness_v); 00183 break; 00184 } 00185 #endif 00186 case CLOSURE_BSDF_ASHIKHMIN_VELVET_ID: { 00187 ShaderClosure *sc = svm_node_closure_get(sd); 00188 svm_node_closure_set_mix_weight(sc, mix_weight); 00189 00190 /* sigma */ 00191 float sigma = clamp(param1, 0.0f, 1.0f); 00192 bsdf_ashikhmin_velvet_setup(sd, sc, sigma); 00193 break; 00194 } 00195 default: 00196 break; 00197 } 00198 } 00199 00200 __device void svm_node_closure_volume(KernelGlobals *kg, ShaderData *sd, float *stack, uint4 node, int path_flag) 00201 { 00202 uint type, param1_offset, param2_offset; 00203 00204 #ifdef __MULTI_CLOSURE__ 00205 uint mix_weight_offset; 00206 decode_node_uchar4(node.y, &type, ¶m1_offset, ¶m2_offset, &mix_weight_offset); 00207 float mix_weight = (stack_valid(mix_weight_offset)? stack_load_float(stack, mix_weight_offset): 1.0f); 00208 00209 if(mix_weight == 0.0f) 00210 return; 00211 #else 00212 decode_node_uchar4(node.y, &type, ¶m1_offset, ¶m2_offset, NULL); 00213 float mix_weight = 1.0f; 00214 #endif 00215 00216 float param1 = (stack_valid(param1_offset))? stack_load_float(stack, param1_offset): __int_as_float(node.z); 00217 //float param2 = (stack_valid(param2_offset))? stack_load_float(stack, param2_offset): __int_as_float(node.w); 00218 00219 switch(type) { 00220 case CLOSURE_VOLUME_TRANSPARENT_ID: { 00221 ShaderClosure *sc = svm_node_closure_get(sd); 00222 svm_node_closure_set_mix_weight(sc, mix_weight); 00223 00224 float density = param1; 00225 volume_transparent_setup(sd, sc, density); 00226 break; 00227 } 00228 case CLOSURE_VOLUME_ISOTROPIC_ID: { 00229 ShaderClosure *sc = svm_node_closure_get(sd); 00230 svm_node_closure_set_mix_weight(sc, mix_weight); 00231 00232 float density = param1; 00233 volume_isotropic_setup(sd, sc, density); 00234 break; 00235 } 00236 default: 00237 break; 00238 } 00239 } 00240 00241 __device void svm_node_closure_emission(ShaderData *sd, float *stack, uint4 node) 00242 { 00243 #ifdef __MULTI_CLOSURE__ 00244 uint mix_weight_offset = node.y; 00245 00246 if(stack_valid(mix_weight_offset)) { 00247 float mix_weight = stack_load_float(stack, mix_weight_offset); 00248 00249 if(mix_weight == 0.0f) 00250 return; 00251 00252 ShaderClosure *sc = svm_node_closure_get(sd); 00253 sc->weight *= mix_weight; 00254 sc->type = CLOSURE_EMISSION_ID; 00255 } 00256 else { 00257 ShaderClosure *sc = svm_node_closure_get(sd); 00258 sc->type = CLOSURE_EMISSION_ID; 00259 } 00260 00261 #else 00262 ShaderClosure *sc = &sd->closure; 00263 sc->type = CLOSURE_EMISSION_ID; 00264 #endif 00265 00266 sd->flag |= SD_EMISSION; 00267 } 00268 00269 __device void svm_node_closure_background(ShaderData *sd, float *stack, uint4 node) 00270 { 00271 #ifdef __MULTI_CLOSURE__ 00272 uint mix_weight_offset = node.y; 00273 00274 if(stack_valid(mix_weight_offset)) { 00275 float mix_weight = stack_load_float(stack, mix_weight_offset); 00276 00277 if(mix_weight == 0.0f) 00278 return; 00279 00280 ShaderClosure *sc = svm_node_closure_get(sd); 00281 sc->weight *= mix_weight; 00282 sc->type = CLOSURE_BACKGROUND_ID; 00283 } 00284 else { 00285 ShaderClosure *sc = svm_node_closure_get(sd); 00286 sc->type = CLOSURE_BACKGROUND_ID; 00287 } 00288 00289 #else 00290 ShaderClosure *sc = &sd->closure; 00291 sc->type = CLOSURE_BACKGROUND_ID; 00292 #endif 00293 } 00294 00295 __device void svm_node_closure_holdout(ShaderData *sd, float *stack, uint4 node) 00296 { 00297 #ifdef __MULTI_CLOSURE__ 00298 uint mix_weight_offset = node.y; 00299 00300 if(stack_valid(mix_weight_offset)) { 00301 float mix_weight = stack_load_float(stack, mix_weight_offset); 00302 00303 if(mix_weight == 0.0f) 00304 return; 00305 00306 ShaderClosure *sc = svm_node_closure_get(sd); 00307 sc->weight = make_float3(mix_weight, mix_weight, mix_weight); 00308 sc->type = CLOSURE_HOLDOUT_ID; 00309 } 00310 else { 00311 ShaderClosure *sc = svm_node_closure_get(sd); 00312 sc->weight = make_float3(1.0f, 1.0f, 1.0f); 00313 sc->type = CLOSURE_HOLDOUT_ID; 00314 } 00315 #else 00316 ShaderClosure *sc = &sd->closure; 00317 sc->type = CLOSURE_HOLDOUT_ID; 00318 #endif 00319 00320 sd->flag |= SD_HOLDOUT; 00321 } 00322 00323 /* Closure Nodes */ 00324 00325 __device_inline void svm_node_closure_store_weight(ShaderData *sd, float3 weight) 00326 { 00327 #ifdef __MULTI_CLOSURE__ 00328 sd->closure[sd->num_closure].weight = weight; 00329 #else 00330 sd->closure.weight = weight; 00331 #endif 00332 } 00333 00334 __device void svm_node_closure_set_weight(ShaderData *sd, uint r, uint g, uint b) 00335 { 00336 float3 weight = make_float3(__int_as_float(r), __int_as_float(g), __int_as_float(b)); 00337 svm_node_closure_store_weight(sd, weight); 00338 } 00339 00340 __device void svm_node_emission_set_weight_total(KernelGlobals *kg, ShaderData *sd, uint r, uint g, uint b) 00341 { 00342 float3 weight = make_float3(__int_as_float(r), __int_as_float(g), __int_as_float(b)); 00343 00344 if(sd->object != ~0) 00345 weight /= object_surface_area(kg, sd->object); 00346 00347 svm_node_closure_store_weight(sd, weight); 00348 } 00349 00350 __device void svm_node_closure_weight(ShaderData *sd, float *stack, uint weight_offset) 00351 { 00352 float3 weight = stack_load_float3(stack, weight_offset); 00353 00354 svm_node_closure_store_weight(sd, weight); 00355 } 00356 00357 __device void svm_node_emission_weight(KernelGlobals *kg, ShaderData *sd, float *stack, uint4 node) 00358 { 00359 uint color_offset = node.y; 00360 uint strength_offset = node.z; 00361 uint total_power = node.w; 00362 00363 float strength = stack_load_float(stack, strength_offset); 00364 float3 weight = stack_load_float3(stack, color_offset)*strength; 00365 00366 if(total_power && sd->object != ~0) 00367 weight /= object_surface_area(kg, sd->object); 00368 00369 svm_node_closure_store_weight(sd, weight); 00370 } 00371 00372 __device void svm_node_mix_closure(ShaderData *sd, float *stack, 00373 uint4 node, int *offset, float *randb) 00374 { 00375 #ifdef __MULTI_CLOSURE__ 00376 /* fetch weight from blend input, previous mix closures, 00377 and write to stack to be used by closure nodes later */ 00378 uint weight_offset, in_weight_offset, weight1_offset, weight2_offset; 00379 decode_node_uchar4(node.y, &weight_offset, &in_weight_offset, &weight1_offset, &weight2_offset); 00380 00381 float weight = stack_load_float(stack, weight_offset); 00382 float in_weight = (stack_valid(in_weight_offset))? stack_load_float(stack, in_weight_offset): 1.0f; 00383 00384 if(stack_valid(weight1_offset)) 00385 stack_store_float(stack, weight1_offset, in_weight*(1.0f - weight)); 00386 if(stack_valid(weight2_offset)) 00387 stack_store_float(stack, weight2_offset, in_weight*weight); 00388 #else 00389 /* pick a closure and make the random number uniform over 0..1 again. 00390 closure 1 starts on the next node, for closure 2 the start is at an 00391 offset from the current node, so we jump */ 00392 uint weight_offset = node.y; 00393 uint node_jump = node.z; 00394 float weight = stack_load_float(stack, weight_offset); 00395 weight = clamp(weight, 0.0f, 1.0f); 00396 00397 if(*randb < weight) { 00398 *offset += node_jump; 00399 *randb = *randb/weight; 00400 } 00401 else 00402 *randb = (*randb - weight)/(1.0f - weight); 00403 #endif 00404 } 00405 00406 __device void svm_node_add_closure(ShaderData *sd, float *stack, uint unused, 00407 uint node_jump, int *offset, float *randb, float *closure_weight) 00408 { 00409 #ifdef __MULTI_CLOSURE__ 00410 /* nothing to do, handled in compiler */ 00411 #else 00412 /* pick one of the two closures with probability 0.5. sampling quality 00413 is not going to be great, for that we'd need to evaluate the weights 00414 of the two closures being added */ 00415 float weight = 0.5f; 00416 00417 if(*randb < weight) { 00418 *offset += node_jump; 00419 *randb = *randb/weight; 00420 } 00421 else 00422 *randb = (*randb - weight)/(1.0f - weight); 00423 00424 *closure_weight *= 2.0f; 00425 #endif 00426 } 00427 00428 CCL_NAMESPACE_END 00429