Blender V2.61 - r43446

kernel_shader.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 /*
00020  * ShaderData, used in four steps:
00021  *
00022  * Setup from incoming ray, sampled position and background.
00023  * Execute for surface, volume or displacement.
00024  * Evaluate one or more closures.
00025  * Release.
00026  *
00027  */
00028 
00029 
00030 #ifdef __OSL__
00031 
00032 #include "osl_shader.h"
00033 
00034 #else
00035 
00036 #include "svm/bsdf.h"
00037 #include "svm/emissive.h"
00038 #include "svm/volume.h"
00039 #include "svm/svm_bsdf.h"
00040 #include "svm/svm.h"
00041 
00042 #endif
00043 
00044 CCL_NAMESPACE_BEGIN
00045 
00046 /* ShaderData setup from incoming ray */
00047 
00048 __device_inline void shader_setup_from_ray(KernelGlobals *kg, ShaderData *sd,
00049     const Intersection *isect, const Ray *ray)
00050 {
00051     /* fetch triangle data */
00052     int prim = kernel_tex_fetch(__prim_index, isect->prim);
00053     float4 Ns = kernel_tex_fetch(__tri_normal, prim);
00054     float3 Ng = make_float3(Ns.x, Ns.y, Ns.z);
00055     int shader = __float_as_int(Ns.w);
00056 
00057     /* vectors */
00058     sd->P = bvh_triangle_refine(kg, isect, ray);
00059     sd->Ng = Ng;
00060     sd->N = Ng;
00061     sd->I = -ray->D;
00062     sd->shader = shader;
00063 
00064     /* triangle */
00065 #ifdef __INSTANCING__
00066     sd->object = isect->object;
00067 #endif
00068     sd->prim = prim;
00069 #ifdef __UV__
00070     sd->u = isect->u;
00071     sd->v = isect->v;
00072 #endif
00073 
00074     /* smooth normal */
00075     if(sd->shader & SHADER_SMOOTH_NORMAL)
00076         sd->N = triangle_smooth_normal(kg, sd->prim, sd->u, sd->v);
00077 
00078     sd->flag = kernel_tex_fetch(__shader_flag, sd->shader & SHADER_MASK);
00079 
00080 #ifdef __DPDU__
00081     /* dPdu/dPdv */
00082     triangle_dPdudv(kg, &sd->dPdu, &sd->dPdv, sd->prim);
00083 #endif
00084 
00085 #ifdef __INSTANCING__
00086     if(sd->object != ~0) {
00087         /* instance transform */
00088         object_normal_transform(kg, sd->object, &sd->N);
00089         object_normal_transform(kg, sd->object, &sd->Ng);
00090 #ifdef __DPDU__
00091         object_dir_transform(kg, sd->object, &sd->dPdu);
00092         object_dir_transform(kg, sd->object, &sd->dPdv);
00093 #endif
00094     }
00095     else {
00096         /* non-instanced object index */
00097         sd->object = kernel_tex_fetch(__prim_object, isect->prim);
00098     }
00099 #endif
00100 
00101     /* backfacing test */
00102     bool backfacing = (dot(sd->Ng, sd->I) < 0.0f);
00103 
00104     if(backfacing) {
00105         sd->flag |= SD_BACKFACING;
00106         sd->Ng = -sd->Ng;
00107         sd->N = -sd->N;
00108 #ifdef __DPDU__
00109         sd->dPdu = -sd->dPdu;
00110         sd->dPdv = -sd->dPdv;
00111 #endif
00112     }
00113 
00114 #ifdef __RAY_DIFFERENTIALS__
00115     /* differentials */
00116     differential_transfer(&sd->dP, ray->dP, ray->D, ray->dD, sd->Ng, isect->t);
00117     differential_incoming(&sd->dI, ray->dD);
00118     differential_dudv(&sd->du, &sd->dv, sd->dPdu, sd->dPdv, sd->dP, sd->Ng);
00119 #endif
00120 }
00121 
00122 /* ShaderData setup from position sampled on mesh */
00123 
00124 __device void shader_setup_from_sample(KernelGlobals *kg, ShaderData *sd,
00125     const float3 P, const float3 Ng, const float3 I,
00126     int shader, int object, int prim,  float u, float v)
00127 {
00128     /* vectors */
00129     sd->P = P;
00130     sd->N = Ng;
00131     sd->Ng = Ng;
00132     sd->I = I;
00133     sd->shader = shader;
00134 
00135     /* primitive */
00136 #ifdef __INSTANCING__
00137     sd->object = object;
00138 #endif
00139     sd->prim = prim;
00140 #ifdef __UV__
00141     sd->u = u;
00142     sd->v = v;
00143 #endif
00144 
00145     /* detect instancing, for non-instanced the object index is -object-1 */
00146 #ifdef __INSTANCING__
00147     bool instanced = false;
00148 
00149     if(sd->prim != ~0) {
00150         if(sd->object >= 0)
00151             instanced = true;
00152         else
00153 #endif
00154             sd->object = -sd->object-1;
00155 #ifdef __INSTANCING__
00156     }
00157 #endif
00158 
00159     /* smooth normal */
00160     if(sd->shader & SHADER_SMOOTH_NORMAL) {
00161         sd->N = triangle_smooth_normal(kg, sd->prim, sd->u, sd->v);
00162 
00163 #ifdef __INSTANCING__
00164         if(instanced)
00165             object_normal_transform(kg, sd->object, &sd->N);
00166 #endif
00167     }
00168 
00169     sd->flag = kernel_tex_fetch(__shader_flag, sd->shader & SHADER_MASK);
00170 
00171 #ifdef __DPDU__
00172     /* dPdu/dPdv */
00173     if(sd->prim == ~0) {
00174         sd->dPdu = make_float3(0.0f, 0.0f, 0.0f);
00175         sd->dPdv = make_float3(0.0f, 0.0f, 0.0f);
00176     }
00177     else {
00178         triangle_dPdudv(kg, &sd->dPdu, &sd->dPdv, sd->prim);
00179 
00180 #ifdef __INSTANCING__
00181         if(instanced) {
00182             object_dir_transform(kg, sd->object, &sd->dPdu);
00183             object_dir_transform(kg, sd->object, &sd->dPdv);
00184         }
00185 #endif
00186     }
00187 #endif
00188 
00189     /* backfacing test */
00190     if(sd->prim != ~0) {
00191         bool backfacing = (dot(sd->Ng, sd->I) < 0.0f);
00192 
00193         if(backfacing) {
00194             sd->flag |= SD_BACKFACING;
00195             sd->Ng = -sd->Ng;
00196             sd->N = -sd->N;
00197 #ifdef __DPDU__
00198             sd->dPdu = -sd->dPdu;
00199             sd->dPdv = -sd->dPdv;
00200 #endif
00201         }
00202     }
00203 
00204 #ifdef __RAY_DIFFERENTIALS__
00205     /* no ray differentials here yet */
00206     sd->dP.dx = make_float3(0.0f, 0.0f, 0.0f);
00207     sd->dP.dy = make_float3(0.0f, 0.0f, 0.0f);
00208     sd->dI.dx = make_float3(0.0f, 0.0f, 0.0f);
00209     sd->dI.dy = make_float3(0.0f, 0.0f, 0.0f);
00210     sd->du.dx = 0.0f;
00211     sd->du.dy = 0.0f;
00212     sd->dv.dx = 0.0f;
00213     sd->dv.dy = 0.0f;
00214 #endif
00215 }
00216 
00217 /* ShaderData setup for displacement */
00218 
00219 __device void shader_setup_from_displace(KernelGlobals *kg, ShaderData *sd,
00220     int object, int prim, float u, float v)
00221 {
00222     float3 P, Ng, I = make_float3(0.0f, 0.0f, 0.0f);
00223     int shader;
00224 
00225     P = triangle_point_MT(kg, prim, u, v);
00226     Ng = triangle_normal_MT(kg, prim, &shader);
00227 
00228     /* force smooth shading for displacement */
00229     shader |= SHADER_SMOOTH_NORMAL;
00230 
00231     /* watch out: no instance transform currently */
00232 
00233     shader_setup_from_sample(kg, sd, P, Ng, I, shader, object, prim, u, v);
00234 }
00235 
00236 /* ShaderData setup from ray into background */
00237 
00238 __device_inline void shader_setup_from_background(KernelGlobals *kg, ShaderData *sd, const Ray *ray)
00239 {
00240     /* vectors */
00241     sd->P = ray->D;
00242     sd->N = -sd->P;
00243     sd->Ng = -sd->P;
00244     sd->I = -sd->P;
00245     sd->shader = kernel_data.background.shader;
00246     sd->flag = kernel_tex_fetch(__shader_flag, sd->shader & SHADER_MASK);
00247 
00248 #ifdef __INSTANCING__
00249     sd->object = ~0;
00250 #endif
00251     sd->prim = ~0;
00252 #ifdef __UV__
00253     sd->u = 0.0f;
00254     sd->v = 0.0f;
00255 #endif
00256 
00257 #ifdef __DPDU__
00258     /* dPdu/dPdv */
00259     sd->dPdu = make_float3(0.0f, 0.0f, 0.0f);
00260     sd->dPdv = make_float3(0.0f, 0.0f, 0.0f);
00261 #endif
00262 
00263 #ifdef __RAY_DIFFERENTIALS__
00264     /* differentials */
00265     sd->dP = ray->dD;
00266     differential_incoming(&sd->dI, sd->dP);
00267     sd->du.dx = 0.0f;
00268     sd->du.dy = 0.0f;
00269     sd->dv.dx = 0.0f;
00270     sd->dv.dy = 0.0f;
00271 #endif
00272 }
00273 
00274 /* BSDF */
00275 
00276 #ifdef __MULTI_CLOSURE__
00277 
00278 __device_inline float3 _shader_bsdf_multi_eval(const ShaderData *sd, const float3 omega_in, float *pdf,
00279     int skip_bsdf, float3 sum_eval, float sum_pdf, float sum_sample_weight)
00280 {
00281     for(int i = 0; i< sd->num_closure; i++) {
00282         if(i == skip_bsdf)
00283             continue;
00284 
00285         const ShaderClosure *sc = &sd->closure[i];
00286 
00287         if(CLOSURE_IS_BSDF(sc->type)) {
00288             float bsdf_pdf = 0.0f;
00289 #ifdef __OSL__
00290             float3 eval = OSLShader::bsdf_eval(sd, sc, omega_in, bsdf_pdf);
00291 #else
00292             float3 eval = svm_bsdf_eval(sd, sc, omega_in, &bsdf_pdf);
00293 #endif
00294 
00295             if(bsdf_pdf != 0.0f) {
00296                 sum_eval += eval*sc->weight;
00297                 sum_pdf += bsdf_pdf*sc->sample_weight;
00298             }
00299 
00300             sum_sample_weight += sc->sample_weight;
00301         }
00302     }
00303 
00304     *pdf = sum_pdf/sum_sample_weight;
00305     return sum_eval;
00306 }
00307 
00308 #endif
00309 
00310 __device float3 shader_bsdf_eval(KernelGlobals *kg, const ShaderData *sd,
00311     const float3 omega_in, float *pdf)
00312 {
00313 #ifdef __MULTI_CLOSURE__
00314     return _shader_bsdf_multi_eval(sd, omega_in, pdf, -1, make_float3(0.0f, 0.0f, 0.0f), 0.0f, 0.0f);
00315 #else
00316     const ShaderClosure *sc = &sd->closure;
00317     *pdf = 0.0f;
00318     return svm_bsdf_eval(sd, sc, omega_in, pdf)*sc->weight;
00319 #endif
00320 }
00321 
00322 __device int shader_bsdf_sample(KernelGlobals *kg, const ShaderData *sd,
00323     float randu, float randv, float3 *eval,
00324     float3 *omega_in, differential3 *domega_in, float *pdf)
00325 {
00326 #ifdef __MULTI_CLOSURE__
00327     int sampled = 0;
00328 
00329     if(sd->num_closure > 1) {
00330         /* pick a BSDF closure based on sample weights */
00331         float sum = 0.0f;
00332 
00333         for(sampled = 0; sampled < sd->num_closure; sampled++) {
00334             const ShaderClosure *sc = &sd->closure[sampled];
00335             
00336             if(CLOSURE_IS_BSDF(sc->type))
00337                 sum += sc->sample_weight;
00338         }
00339 
00340         float r = sd->randb_closure*sum;
00341         sum = 0.0f;
00342 
00343         for(sampled = 0; sampled < sd->num_closure; sampled++) {
00344             const ShaderClosure *sc = &sd->closure[sampled];
00345             
00346             if(CLOSURE_IS_BSDF(sc->type)) {
00347                 sum += sd->closure[sampled].sample_weight;
00348 
00349                 if(r <= sum)
00350                     break;
00351             }
00352         }
00353 
00354         if(sampled == sd->num_closure) {
00355             *pdf = 0.0f;
00356             return LABEL_NONE;
00357         }
00358     }
00359 
00360     const ShaderClosure *sc = &sd->closure[sampled];
00361     int label;
00362 
00363     *pdf = 0.0f;
00364 #ifdef __OSL__
00365     label = OSLShader::bsdf_sample(sd, sc, randu, randv, *eval, *omega_in, *domega_in, *pdf);
00366 #else
00367     label = svm_bsdf_sample(sd, sc, randu, randv, eval, omega_in, domega_in, pdf);
00368 #endif
00369 
00370     *eval *= sc->weight;
00371 
00372     if(sd->num_closure > 1 && *pdf != 0.0f) {
00373         float sweight = sc->sample_weight;
00374         *eval = _shader_bsdf_multi_eval(sd, *omega_in, pdf, sampled, *eval, *pdf*sweight, sweight);
00375     }
00376 
00377     return label;
00378 #else
00379     /* sample the single closure that we picked */
00380     *pdf = 0.0f;
00381     int label = svm_bsdf_sample(sd, &sd->closure, randu, randv, eval, omega_in, domega_in, pdf);
00382     *eval *= sd->closure.weight;
00383     return label;
00384 #endif
00385 }
00386 
00387 __device void shader_bsdf_blur(KernelGlobals *kg, ShaderData *sd, float roughness)
00388 {
00389 #ifndef __OSL__
00390 #ifdef __MULTI_CLOSURE__
00391     for(int i = 0; i< sd->num_closure; i++) {
00392         ShaderClosure *sc = &sd->closure[i];
00393 
00394         if(CLOSURE_IS_BSDF(sc->type))
00395             svm_bsdf_blur(sc, roughness);
00396     }
00397 #else
00398     svm_bsdf_blur(&sd->closure, roughness);
00399 #endif
00400 #endif
00401 }
00402 
00403 __device float3 shader_bsdf_transparency(KernelGlobals *kg, ShaderData *sd)
00404 {
00405 #ifdef __MULTI_CLOSURE__
00406     float3 eval = make_float3(0.0f, 0.0f, 0.0f);
00407 
00408     for(int i = 0; i< sd->num_closure; i++) {
00409         ShaderClosure *sc = &sd->closure[i];
00410 
00411         if(sc->type == CLOSURE_BSDF_TRANSPARENT_ID) // todo: make this work for osl
00412             eval += sc->weight;
00413     }
00414 
00415     return eval;
00416 #else
00417     if(sd->closure.type == CLOSURE_BSDF_TRANSPARENT_ID)
00418         return sd->closure.weight;
00419     else
00420         return make_float3(0.0f, 0.0f, 0.0f);
00421 #endif
00422 }
00423 
00424 
00425 /* Emission */
00426 
00427 __device float3 shader_emissive_eval(KernelGlobals *kg, ShaderData *sd)
00428 {
00429     float3 eval;
00430 #ifdef __MULTI_CLOSURE__
00431     eval = make_float3(0.0f, 0.0f, 0.0f);
00432 
00433     for(int i = 0; i < sd->num_closure; i++) {
00434         ShaderClosure *sc = &sd->closure[i];
00435 
00436         if(CLOSURE_IS_EMISSION(sc->type)) {
00437 #ifdef __OSL__
00438             eval += OSLShader::emissive_eval(sd)*sc->weight;
00439 #else
00440             eval += svm_emissive_eval(sd, sc)*sc->weight;
00441 #endif
00442         }
00443     }
00444 #else
00445     eval = svm_emissive_eval(sd, &sd->closure)*sd->closure.weight;
00446 #endif
00447 
00448     return eval;
00449 }
00450 
00451 /* Holdout */
00452 
00453 __device float3 shader_holdout_eval(KernelGlobals *kg, ShaderData *sd)
00454 {
00455 #ifdef __MULTI_CLOSURE__
00456     float3 weight = make_float3(0.0f, 0.0f, 0.0f);
00457 
00458     for(int i = 0; i < sd->num_closure; i++) {
00459         ShaderClosure *sc = &sd->closure[i];
00460 
00461         if(CLOSURE_IS_HOLDOUT(sc->type))
00462             weight += sc->weight;
00463     }
00464 
00465     return weight;
00466 #else
00467     if(sd->closure.type == CLOSURE_HOLDOUT_ID)
00468         return make_float3(1.0f, 1.0f, 1.0f);
00469 
00470     return make_float3(0.0f, 0.0f, 0.0f);
00471 #endif
00472 }
00473 
00474 /* Surface Evaluation */
00475 
00476 __device void shader_eval_surface(KernelGlobals *kg, ShaderData *sd,
00477     float randb, int path_flag)
00478 {
00479 #ifdef __OSL__
00480     OSLShader::eval_surface(kg, sd, randb, path_flag);
00481 #else
00482 
00483 #ifdef __SVM__
00484     svm_eval_nodes(kg, sd, SHADER_TYPE_SURFACE, randb, path_flag);
00485 #else
00486     bsdf_diffuse_setup(sd, &sd->closure);
00487     sd->closure.weight = make_float3(0.8f, 0.8f, 0.8f);
00488 #endif
00489 
00490 #endif
00491 }
00492 
00493 /* Background Evaluation */
00494 
00495 __device float3 shader_eval_background(KernelGlobals *kg, ShaderData *sd, int path_flag)
00496 {
00497 #ifdef __OSL__
00498     return OSLShader::eval_background(kg, sd, path_flag);
00499 #else
00500 
00501 #ifdef __SVM__
00502     svm_eval_nodes(kg, sd, SHADER_TYPE_SURFACE, 0.0f, path_flag);
00503 
00504 #ifdef __MULTI_CLOSURE__
00505     float3 eval = make_float3(0.0f, 0.0f, 0.0f);
00506 
00507     for(int i = 0; i< sd->num_closure; i++) {
00508         const ShaderClosure *sc = &sd->closure[i];
00509 
00510         if(CLOSURE_IS_BACKGROUND(sc->type))
00511             eval += sc->weight;
00512     }
00513 
00514     return eval;
00515 #else
00516     if(sd->closure.type == CLOSURE_BACKGROUND_ID)
00517         return sd->closure.weight;
00518     else
00519         return make_float3(0.0f, 0.0f, 0.0f);
00520 #endif
00521 
00522 #else
00523     return make_float3(0.8f, 0.8f, 0.8f);
00524 #endif
00525 
00526 #endif
00527 }
00528 
00529 /* Volume */
00530 
00531 __device float3 shader_volume_eval_phase(KernelGlobals *kg, ShaderData *sd,
00532     float3 omega_in, float3 omega_out)
00533 {
00534 #ifdef __MULTI_CLOSURE__
00535     float3 eval = make_float3(0.0f, 0.0f, 0.0f);
00536 
00537     for(int i = 0; i< sd->num_closure; i++) {
00538         const ShaderClosure *sc = &sd->closure[i];
00539 
00540         if(CLOSURE_IS_VOLUME(sc->type)) {
00541 #ifdef __OSL__
00542             eval += OSLShader::volume_eval_phase(sd, omega_in, omega_out);
00543 #else
00544             eval += volume_eval_phase(sd, sc, omega_in, omega_out);
00545 #endif
00546         }
00547     }
00548 
00549     return eval;
00550 #else
00551     return volume_eval_phase(sd, &sd->closure, omega_in, omega_out);
00552 #endif
00553 }
00554 
00555 /* Volume Evaluation */
00556 
00557 __device void shader_eval_volume(KernelGlobals *kg, ShaderData *sd,
00558     float randb, int path_flag)
00559 {
00560 #ifdef __SVM__
00561 #ifdef __OSL__
00562     OSLShader::eval_volume(kg, sd, randb, path_flag);
00563 #else
00564     svm_eval_nodes(kg, sd, SHADER_TYPE_VOLUME, randb, path_flag);
00565 #endif
00566 #endif
00567 }
00568 
00569 /* Displacement Evaluation */
00570 
00571 __device void shader_eval_displacement(KernelGlobals *kg, ShaderData *sd)
00572 {
00573     /* this will modify sd->P */
00574 #ifdef __SVM__
00575 #ifdef __OSL__
00576     OSLShader::eval_displacement(kg, sd);
00577 #else
00578     svm_eval_nodes(kg, sd, SHADER_TYPE_DISPLACEMENT, 0.0f, 0);
00579 #endif
00580 #endif
00581 }
00582 
00583 /* Transparent Shadows */
00584 
00585 #ifdef __TRANSPARENT_SHADOWS__
00586 __device bool shader_transparent_shadow(KernelGlobals *kg, Intersection *isect)
00587 {
00588     int prim = kernel_tex_fetch(__prim_index, isect->prim);
00589     float4 Ns = kernel_tex_fetch(__tri_normal, prim);
00590     int shader = __float_as_int(Ns.w);
00591     int flag = kernel_tex_fetch(__shader_flag, shader & SHADER_MASK);
00592 
00593     return (flag & SD_HAS_SURFACE_TRANSPARENT) != 0;
00594 }
00595 #endif
00596 
00597 /* Free ShaderData */
00598 
00599 __device void shader_release(KernelGlobals *kg, ShaderData *sd)
00600 {
00601 #ifdef __OSL__
00602     OSLShader::release(kg, sd);
00603 #endif
00604 }
00605 
00606 CCL_NAMESPACE_END
00607