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 #include "kernel_compat_cpu.h" 00020 #include "kernel_types.h" 00021 #include "kernel_globals.h" 00022 #include "kernel_object.h" 00023 00024 #include "osl_services.h" 00025 #include "osl_shader.h" 00026 00027 #include "util_foreach.h" 00028 00029 #include <OSL/oslexec.h> 00030 #include <oslexec_pvt.h> 00031 00032 CCL_NAMESPACE_BEGIN 00033 00034 tls_ptr(OSLGlobals::ThreadData, OSLGlobals::thread_data); 00035 00036 /* Threads */ 00037 00038 void OSLShader::thread_init(KernelGlobals *kg) 00039 { 00040 OSL::pvt::ShadingSystemImpl *ssi = (OSL::pvt::ShadingSystemImpl*)kg->osl.ss; 00041 00042 OSLGlobals::ThreadData *tdata = new OSLGlobals::ThreadData(); 00043 00044 memset(&tdata->globals, 0, sizeof(OSL::ShaderGlobals)); 00045 tdata->thread_info = ssi->create_thread_info(); 00046 00047 tls_set(kg->osl.thread_data, tdata); 00048 00049 ((OSLRenderServices*)ssi->renderer())->thread_init(kg); 00050 } 00051 00052 void OSLShader::thread_free(KernelGlobals *kg) 00053 { 00054 OSL::pvt::ShadingSystemImpl *ssi = (OSL::pvt::ShadingSystemImpl*)kg->osl.ss; 00055 00056 OSLGlobals::ThreadData *tdata = tls_get(OSLGlobals::ThreadData, kg->osl.thread_data); 00057 00058 ssi->destroy_thread_info(tdata->thread_info); 00059 00060 delete tdata; 00061 } 00062 00063 /* Globals */ 00064 00065 #define TO_VEC3(v) (*(OSL::Vec3*)&(v)) 00066 #define TO_COLOR3(v) (*(OSL::Color3*)&(v)) 00067 #define TO_FLOAT3(v) make_float3(v[0], v[1], v[2]) 00068 00069 static void shaderdata_to_shaderglobals(KernelGlobals *kg, ShaderData *sd, 00070 int path_flag, OSL::ShaderGlobals *globals) 00071 { 00072 /* copy from shader data to shader globals */ 00073 globals->P = TO_VEC3(sd->P); 00074 globals->dPdx = TO_VEC3(sd->dP.dx); 00075 globals->dPdy = TO_VEC3(sd->dP.dy); 00076 globals->I = TO_VEC3(sd->I); 00077 globals->dIdx = TO_VEC3(sd->dI.dx); 00078 globals->dIdy = TO_VEC3(sd->dI.dy); 00079 globals->N = TO_VEC3(sd->N); 00080 globals->Ng = TO_VEC3(sd->Ng); 00081 globals->u = sd->u; 00082 globals->dudx = sd->du.dx; 00083 globals->dudy = sd->du.dy; 00084 globals->v = sd->v; 00085 globals->dvdx = sd->dv.dx; 00086 globals->dvdy = sd->dv.dy; 00087 globals->dPdu = TO_VEC3(sd->dPdu); 00088 globals->dPdv = TO_VEC3(sd->dPdv); 00089 globals->surfacearea = (sd->object == ~0)? 1.0f: object_surface_area(kg, sd->object); 00090 00091 /* booleans */ 00092 globals->raytype = path_flag; /* todo: add our own ray types */ 00093 globals->backfacing = (sd->flag & SD_BACKFACING); 00094 00095 /* don't know yet if we need this */ 00096 globals->flipHandedness = false; 00097 00098 /* shader data to be used in services callbacks */ 00099 globals->renderstate = sd; 00100 00101 /* hacky, we leave it to services to fetch actual object matrix */ 00102 globals->shader2common = sd; 00103 globals->object2common = sd; 00104 00105 /* must be set to NULL before execute */ 00106 globals->Ci = NULL; 00107 } 00108 00109 /* Surface */ 00110 00111 static void flatten_surface_closure_tree(ShaderData *sd, bool no_glossy, 00112 const OSL::ClosureColor *closure, float3 weight = make_float3(1.0f, 1.0f, 1.0f)) 00113 { 00114 /* OSL gives use a closure tree, we flatten it into arrays per 00115 * closure type, for evaluation, sampling, etc later on. */ 00116 00117 if(closure->type == OSL::ClosureColor::COMPONENT) { 00118 OSL::ClosureComponent *comp = (OSL::ClosureComponent*)closure; 00119 OSL::ClosurePrimitive *prim = (OSL::ClosurePrimitive*)comp->data(); 00120 00121 if(prim) { 00122 ShaderClosure sc; 00123 sc.prim = prim; 00124 sc.weight = weight; 00125 00126 switch(prim->category()) { 00127 case ClosurePrimitive::BSDF: { 00128 if(sd->num_closure == MAX_CLOSURE) 00129 return; 00130 00131 OSL::BSDFClosure *bsdf = (OSL::BSDFClosure*)prim; 00132 ustring scattering = bsdf->scattering(); 00133 00134 /* no caustics option */ 00135 if(no_glossy && scattering == OSL::Labels::GLOSSY) 00136 return; 00137 00138 /* sample weight */ 00139 float albedo = bsdf->albedo(TO_VEC3(sd->I)); 00140 float sample_weight = fabsf(average(weight))*albedo; 00141 float sample_sum = sd->osl_closure.bsdf_sample_sum + sample_weight; 00142 00143 sc.sample_weight = sample_weight; 00144 sc.type = CLOSURE_BSDF_ID; 00145 sd->osl_closure.bsdf_sample_sum = sample_sum; 00146 00147 /* scattering flags */ 00148 if(scattering == OSL::Labels::DIFFUSE) 00149 sd->flag |= SD_BSDF|SD_BSDF_HAS_EVAL; 00150 else if(scattering == OSL::Labels::GLOSSY) 00151 sd->flag |= SD_BSDF|SD_BSDF_HAS_EVAL|SD_BSDF_GLOSSY; 00152 else 00153 sd->flag |= SD_BSDF; 00154 00155 /* add */ 00156 sd->closure[sd->num_closure++] = sc; 00157 break; 00158 } 00159 case ClosurePrimitive::Emissive: { 00160 if(sd->num_closure == MAX_CLOSURE) 00161 return; 00162 00163 /* sample weight */ 00164 float sample_weight = fabsf(average(weight)); 00165 float sample_sum = sd->osl_closure.emissive_sample_sum + sample_weight; 00166 00167 sc.sample_weight = sample_weight; 00168 sc.type = CLOSURE_EMISSION_ID; 00169 sd->osl_closure.emissive_sample_sum = sample_sum; 00170 00171 /* flag */ 00172 sd->flag |= SD_EMISSION; 00173 00174 sd->closure[sd->num_closure++] = sc; 00175 break; 00176 } 00177 case ClosurePrimitive::Holdout: 00178 if(sd->num_closure == MAX_CLOSURE) 00179 return; 00180 00181 sc.sample_weight = 0.0f; 00182 sc.type = CLOSURE_HOLDOUT_ID; 00183 sd->flag |= SD_HOLDOUT; 00184 sd->closure[sd->num_closure++] = sc; 00185 break; 00186 case ClosurePrimitive::BSSRDF: 00187 case ClosurePrimitive::Debug: 00188 break; /* not implemented */ 00189 case ClosurePrimitive::Background: 00190 case ClosurePrimitive::Volume: 00191 break; /* not relevant */ 00192 } 00193 } 00194 } 00195 else if(closure->type == OSL::ClosureColor::MUL) { 00196 OSL::ClosureMul *mul = (OSL::ClosureMul*)closure; 00197 flatten_surface_closure_tree(sd, no_glossy, mul->closure, TO_FLOAT3(mul->weight) * weight); 00198 } 00199 else if(closure->type == OSL::ClosureColor::ADD) { 00200 OSL::ClosureAdd *add = (OSL::ClosureAdd*)closure; 00201 flatten_surface_closure_tree(sd, no_glossy, add->closureA, weight); 00202 flatten_surface_closure_tree(sd, no_glossy, add->closureB, weight); 00203 } 00204 } 00205 00206 void OSLShader::eval_surface(KernelGlobals *kg, ShaderData *sd, float randb, int path_flag) 00207 { 00208 /* gather pointers */ 00209 OSL::pvt::ShadingSystemImpl *ssi = (OSL::pvt::ShadingSystemImpl*)kg->osl.ss; 00210 OSLGlobals::ThreadData *tdata = tls_get(OSLGlobals::ThreadData, kg->osl.thread_data); 00211 OSL::ShaderGlobals *globals = &tdata->globals; 00212 OSL::pvt::ShadingContext *ctx = ssi->get_context(tdata->thread_info); 00213 00214 /* setup shader globals from shader data */ 00215 sd->osl_ctx = ctx; 00216 shaderdata_to_shaderglobals(kg, sd, path_flag, globals); 00217 00218 /* execute shader for this point */ 00219 int shader = sd->shader & SHADER_MASK; 00220 00221 if(kg->osl.surface_state[shader]) 00222 ctx->execute(OSL::pvt::ShadUseSurface, *(kg->osl.surface_state[shader]), *globals); 00223 00224 /* flatten closure tree */ 00225 sd->num_closure = 0; 00226 sd->randb_closure = randb; 00227 00228 if(globals->Ci) { 00229 bool no_glossy = (path_flag & PATH_RAY_DIFFUSE) && kernel_data.integrator.no_caustics; 00230 flatten_surface_closure_tree(sd, no_glossy, globals->Ci); 00231 } 00232 } 00233 00234 /* Background */ 00235 00236 static float3 flatten_background_closure_tree(const OSL::ClosureColor *closure) 00237 { 00238 /* OSL gives use a closure tree, if we are shading for background there 00239 * is only one supported closure type at the moment, which has no evaluation 00240 * functions, so we just sum the weights */ 00241 00242 if(closure->type == OSL::ClosureColor::COMPONENT) { 00243 OSL::ClosureComponent *comp = (OSL::ClosureComponent*)closure; 00244 OSL::ClosurePrimitive *prim = (OSL::ClosurePrimitive*)comp->data(); 00245 00246 if(prim && prim->category() == OSL::ClosurePrimitive::Background) 00247 return make_float3(1.0f, 1.0f, 1.0f); 00248 } 00249 else if(closure->type == OSL::ClosureColor::MUL) { 00250 OSL::ClosureMul *mul = (OSL::ClosureMul*)closure; 00251 00252 return TO_FLOAT3(mul->weight) * flatten_background_closure_tree(mul->closure); 00253 } 00254 else if(closure->type == OSL::ClosureColor::ADD) { 00255 OSL::ClosureAdd *add = (OSL::ClosureAdd*)closure; 00256 00257 return flatten_background_closure_tree(add->closureA) + 00258 flatten_background_closure_tree(add->closureB); 00259 } 00260 00261 return make_float3(0.0f, 0.0f, 0.0f); 00262 } 00263 00264 float3 OSLShader::eval_background(KernelGlobals *kg, ShaderData *sd, int path_flag) 00265 { 00266 /* gather pointers */ 00267 OSL::pvt::ShadingSystemImpl *ssi = (OSL::pvt::ShadingSystemImpl*)kg->osl.ss; 00268 OSLGlobals::ThreadData *tdata = tls_get(OSLGlobals::ThreadData, kg->osl.thread_data); 00269 OSL::ShaderGlobals *globals = &tdata->globals; 00270 OSL::pvt::ShadingContext *ctx = ssi->get_context(tdata->thread_info); 00271 00272 /* setup shader globals from shader data */ 00273 sd->osl_ctx = ctx; 00274 shaderdata_to_shaderglobals(kg, sd, path_flag, globals); 00275 00276 /* execute shader for this point */ 00277 if(kg->osl.background_state) 00278 ctx->execute(OSL::pvt::ShadUseSurface, *kg->osl.background_state, *globals); 00279 00280 /* return background color immediately */ 00281 if(globals->Ci) 00282 return flatten_background_closure_tree(globals->Ci); 00283 00284 return make_float3(0.0f, 0.0f, 0.0f); 00285 } 00286 00287 /* Volume */ 00288 00289 static void flatten_volume_closure_tree(ShaderData *sd, 00290 const OSL::ClosureColor *closure, float3 weight = make_float3(1.0f, 1.0f, 1.0f)) 00291 { 00292 /* OSL gives use a closure tree, we flatten it into arrays per 00293 * closure type, for evaluation, sampling, etc later on. */ 00294 00295 if(closure->type == OSL::ClosureColor::COMPONENT) { 00296 OSL::ClosureComponent *comp = (OSL::ClosureComponent*)closure; 00297 OSL::ClosurePrimitive *prim = (OSL::ClosurePrimitive*)comp->data(); 00298 00299 if(prim) { 00300 ShaderClosure sc; 00301 sc.prim = prim; 00302 sc.weight = weight; 00303 00304 switch(prim->category()) { 00305 case ClosurePrimitive::Volume: { 00306 if(sd->num_closure == MAX_CLOSURE) 00307 return; 00308 00309 /* sample weight */ 00310 float sample_weight = fabsf(average(weight)); 00311 float sample_sum = sd->osl_closure.volume_sample_sum + sample_weight; 00312 00313 sc.sample_weight = sample_weight; 00314 sc.type = CLOSURE_VOLUME_ID; 00315 sd->osl_closure.volume_sample_sum = sample_sum; 00316 00317 /* add */ 00318 sd->closure[sd->num_closure++] = sc; 00319 break; 00320 } 00321 case ClosurePrimitive::Holdout: 00322 case ClosurePrimitive::Debug: 00323 break; /* not implemented */ 00324 case ClosurePrimitive::Background: 00325 case ClosurePrimitive::BSDF: 00326 case ClosurePrimitive::Emissive: 00327 case ClosurePrimitive::BSSRDF: 00328 break; /* not relevant */ 00329 } 00330 } 00331 } 00332 else if(closure->type == OSL::ClosureColor::MUL) { 00333 OSL::ClosureMul *mul = (OSL::ClosureMul*)closure; 00334 flatten_volume_closure_tree(sd, mul->closure, TO_FLOAT3(mul->weight) * weight); 00335 } 00336 else if(closure->type == OSL::ClosureColor::ADD) { 00337 OSL::ClosureAdd *add = (OSL::ClosureAdd*)closure; 00338 flatten_volume_closure_tree(sd, add->closureA, weight); 00339 flatten_volume_closure_tree(sd, add->closureB, weight); 00340 } 00341 } 00342 00343 void OSLShader::eval_volume(KernelGlobals *kg, ShaderData *sd, float randb, int path_flag) 00344 { 00345 /* gather pointers */ 00346 OSL::pvt::ShadingSystemImpl *ssi = (OSL::pvt::ShadingSystemImpl*)kg->osl.ss; 00347 OSLGlobals::ThreadData *tdata = tls_get(OSLGlobals::ThreadData, kg->osl.thread_data); 00348 OSL::ShaderGlobals *globals = &tdata->globals; 00349 OSL::pvt::ShadingContext *ctx = ssi->get_context(tdata->thread_info); 00350 00351 /* setup shader globals from shader data */ 00352 sd->osl_ctx = ctx; 00353 shaderdata_to_shaderglobals(kg, sd, path_flag, globals); 00354 00355 /* execute shader */ 00356 int shader = sd->shader & SHADER_MASK; 00357 00358 if(kg->osl.volume_state[shader]) 00359 ctx->execute(OSL::pvt::ShadUseSurface, *(kg->osl.volume_state[shader]), *globals); 00360 00361 /* retrieve resulting closures */ 00362 sd->osl_closure.volume_sample_sum = 0.0f; 00363 sd->osl_closure.num_volume = 0; 00364 sd->osl_closure.randb = randb; 00365 00366 if(globals->Ci) 00367 flatten_volume_closure_tree(sd, globals->Ci); 00368 } 00369 00370 /* Displacement */ 00371 00372 void OSLShader::eval_displacement(KernelGlobals *kg, ShaderData *sd) 00373 { 00374 /* gather pointers */ 00375 OSL::pvt::ShadingSystemImpl *ssi = (OSL::pvt::ShadingSystemImpl*)kg->osl.ss; 00376 OSLGlobals::ThreadData *tdata = tls_get(OSLGlobals::ThreadData, kg->osl.thread_data); 00377 OSL::ShaderGlobals *globals = &tdata->globals; 00378 OSL::pvt::ShadingContext *ctx = ssi->get_context(tdata->thread_info); 00379 00380 /* setup shader globals from shader data */ 00381 sd->osl_ctx = ctx; 00382 shaderdata_to_shaderglobals(kg, sd, 0, globals); 00383 00384 /* execute shader */ 00385 int shader = sd->shader & SHADER_MASK; 00386 00387 if(kg->osl.displacement_state[shader]) 00388 ctx->execute(OSL::pvt::ShadUseSurface, *(kg->osl.displacement_state[shader]), *globals); 00389 00390 /* get back position */ 00391 sd->P = TO_FLOAT3(globals->P); 00392 } 00393 00394 void OSLShader::release(KernelGlobals *kg, const ShaderData *sd) 00395 { 00396 OSL::pvt::ShadingSystemImpl *ssi = (OSL::pvt::ShadingSystemImpl*)kg->osl.ss; 00397 OSLGlobals::ThreadData *tdata = tls_get(OSLGlobals::ThreadData, kg->osl.thread_data); 00398 00399 ssi->release_context((OSL::pvt::ShadingContext*)sd->osl_ctx, tdata->thread_info); 00400 } 00401 00402 /* BSDF Closure */ 00403 00404 int OSLShader::bsdf_sample(const ShaderData *sd, const ShaderClosure *sc, float randu, float randv, float3& eval, float3& omega_in, differential3& domega_in, float& pdf) 00405 { 00406 OSL::BSDFClosure *sample_bsdf = (OSL::BSDFClosure*)sc->prim; 00407 int label = LABEL_NONE; 00408 00409 pdf = 0.0f; 00410 00411 /* sample BSDF closure */ 00412 ustring ulabel; 00413 00414 ulabel = sample_bsdf->sample(TO_VEC3(sd->Ng), 00415 TO_VEC3(sd->I), TO_VEC3(sd->dI.dx), TO_VEC3(sd->dI.dy), 00416 randu, randv, 00417 TO_VEC3(omega_in), TO_VEC3(domega_in.dx), TO_VEC3(domega_in.dy), 00418 pdf, TO_COLOR3(eval)); 00419 00420 /* convert OSL label */ 00421 if(ulabel == OSL::Labels::REFLECT) 00422 label = LABEL_REFLECT; 00423 else if(ulabel == OSL::Labels::TRANSMIT) 00424 label = LABEL_TRANSMIT; 00425 else 00426 return LABEL_NONE; /* sampling failed */ 00427 00428 /* convert scattering to our bitflag label */ 00429 ustring uscattering = sample_bsdf->scattering(); 00430 00431 if(uscattering == OSL::Labels::DIFFUSE) 00432 label |= LABEL_DIFFUSE; 00433 else if(uscattering == OSL::Labels::GLOSSY) 00434 label |= LABEL_GLOSSY; 00435 else if(uscattering == OSL::Labels::SINGULAR) 00436 label |= LABEL_SINGULAR; 00437 else 00438 label |= LABEL_TRANSPARENT; 00439 00440 return label; 00441 } 00442 00443 float3 OSLShader::bsdf_eval(const ShaderData *sd, const ShaderClosure *sc, const float3& omega_in, float& pdf) 00444 { 00445 OSL::BSDFClosure *bsdf = (OSL::BSDFClosure*)sc->prim; 00446 OSL::Color3 bsdf_eval; 00447 00448 if(dot(sd->Ng, omega_in) >= 0.0f) 00449 bsdf_eval = bsdf->eval_reflect(TO_VEC3(sd->I), TO_VEC3(omega_in), pdf); 00450 else 00451 bsdf_eval = bsdf->eval_transmit(TO_VEC3(sd->I), TO_VEC3(omega_in), pdf); 00452 00453 return TO_FLOAT3(bsdf_eval); 00454 } 00455 00456 /* Emissive Closure */ 00457 00458 float3 OSLShader::emissive_eval(const ShaderData *sd, const ShaderClosure *sc) 00459 { 00460 OSL::EmissiveClosure *emissive = (OSL::EmissiveClosure*)sc->prim; 00461 OSL::Color3 emissive_eval = emissive->eval(TO_VEC3(sd->Ng), TO_VEC3(sd->I)); 00462 eval += TO_FLOAT3(emissive_eval); 00463 00464 return eval; 00465 } 00466 00467 /* Volume Closure */ 00468 00469 float3 OSLShader::volume_eval_phase(const ShaderData *sd, const ShaderClosure *sc, const float3 omega_in, const float3 omega_out) 00470 { 00471 OSL::VolumeClosure *volume = (OSL::VolumeClosure*)sc->prim; 00472 OSL::Color3 volume_eval = volume->eval_phase(TO_VEC3(omega_in), TO_VEC3(omega_out)); 00473 return TO_FLOAT3(volume_eval)*sc->weight; 00474 } 00475 00476 CCL_NAMESPACE_END 00477