Blender V2.61 - r43446

svm_closure.h

Go to the documentation of this file.
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, &param1_offset, &param2_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, &param1_offset, &param2_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, &param1_offset, &param2_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, &param1_offset, &param2_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