555edf598f1988f49af1fa46f2138a88ab8eeb63
[blender.git] / intern / cycles / kernel / osl / osl_shader.cpp
1 /*
2  * Copyright 2011, Blender Foundation.
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License
6  * as published by the Free Software Foundation; either version 2
7  * of the License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software Foundation,
16  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17  */
18
19 #include "kernel_compat_cpu.h"
20 #include "kernel_types.h"
21 #include "kernel_globals.h"
22 #include "kernel_object.h"
23
24 #include "osl_bssrdf.h"
25 #include "osl_closures.h"
26 #include "osl_globals.h"
27 #include "osl_services.h"
28 #include "osl_shader.h"
29
30 #include "util_foreach.h"
31
32 #include "attribute.h"
33
34 #include <OSL/oslexec.h>
35
36 CCL_NAMESPACE_BEGIN
37
38 /* Threads */
39
40 void OSLShader::thread_init(KernelGlobals *kg, KernelGlobals *kernel_globals, OSLGlobals *osl_globals)
41 {
42         /* no osl used? */
43         if(!osl_globals->use) {
44                 kg->osl = NULL;
45                 return;
46         }
47
48         /* per thread kernel data init*/
49         kg->osl = osl_globals;
50         kg->osl->services->thread_init(kernel_globals);
51
52         OSL::ShadingSystem *ss = kg->osl->ss;
53         OSLThreadData *tdata = new OSLThreadData();
54
55         memset(&tdata->globals, 0, sizeof(OSL::ShaderGlobals));
56         tdata->globals.tracedata = &tdata->tracedata;
57         tdata->globals.flipHandedness = false;
58         tdata->thread_info = ss->create_thread_info();
59
60         for(int i = 0; i < SHADER_CONTEXT_NUM; i++)
61                 tdata->context[i] = ss->get_context(tdata->thread_info);
62
63         kg->osl_ss = (OSLShadingSystem*)ss;
64         kg->osl_tdata = tdata;
65 }
66
67 void OSLShader::thread_free(KernelGlobals *kg)
68 {
69         if(!kg->osl)
70                 return;
71
72         OSL::ShadingSystem *ss = (OSL::ShadingSystem*)kg->osl_ss;
73         OSLThreadData *tdata = kg->osl_tdata;
74
75         for(int i = 0; i < SHADER_CONTEXT_NUM; i++)
76                 ss->release_context(tdata->context[i]);
77
78         ss->destroy_thread_info(tdata->thread_info);
79
80         delete tdata;
81
82         kg->osl = NULL;
83         kg->osl_ss = NULL;
84         kg->osl_tdata = NULL;
85 }
86
87 /* Globals */
88
89 static void shaderdata_to_shaderglobals(KernelGlobals *kg, ShaderData *sd,
90                                         int path_flag, OSLThreadData *tdata)
91 {
92         OSL::ShaderGlobals *globals = &tdata->globals;
93
94         /* copy from shader data to shader globals */
95         globals->P = TO_VEC3(sd->P);
96         globals->dPdx = TO_VEC3(sd->dP.dx);
97         globals->dPdy = TO_VEC3(sd->dP.dy);
98         globals->I = TO_VEC3(sd->I);
99         globals->dIdx = TO_VEC3(sd->dI.dx);
100         globals->dIdy = TO_VEC3(sd->dI.dy);
101         globals->N = TO_VEC3(sd->N);
102         globals->Ng = TO_VEC3(sd->Ng);
103         globals->u = sd->u;
104         globals->dudx = sd->du.dx;
105         globals->dudy = sd->du.dy;
106         globals->v = sd->v;
107         globals->dvdx = sd->dv.dx;
108         globals->dvdy = sd->dv.dy;
109         globals->dPdu = TO_VEC3(sd->dPdu);
110         globals->dPdv = TO_VEC3(sd->dPdv);
111         globals->surfacearea = (sd->object == ~0) ? 1.0f : object_surface_area(kg, sd->object);
112         globals->time = sd->time;
113
114         /* booleans */
115         globals->raytype = path_flag;
116         globals->backfacing = (sd->flag & SD_BACKFACING);
117
118         /* shader data to be used in services callbacks */
119         globals->renderstate = sd; 
120
121         /* hacky, we leave it to services to fetch actual object matrix */
122         globals->shader2common = sd;
123         globals->object2common = sd;
124
125         /* must be set to NULL before execute */
126         globals->Ci = NULL;
127
128         /* clear trace data */
129         tdata->tracedata.init = false;
130 }
131
132 /* Surface */
133
134 static void flatten_surface_closure_tree(ShaderData *sd, bool no_glossy,
135                                          const OSL::ClosureColor *closure, float3 weight = make_float3(1.0f, 1.0f, 1.0f))
136 {
137         /* OSL gives us a closure tree, we flatten it into arrays per
138          * closure type, for evaluation, sampling, etc later on. */
139
140         if (closure->type == OSL::ClosureColor::COMPONENT) {
141                 OSL::ClosureComponent *comp = (OSL::ClosureComponent *)closure;
142                 OSL::ClosurePrimitive *prim = (OSL::ClosurePrimitive *)comp->data();
143
144                 if (prim) {
145                         ShaderClosure sc;
146                         sc.weight = weight;
147
148                         switch (prim->category()) {
149                                 case OSL::ClosurePrimitive::BSDF: {
150                                         CBSDFClosure *bsdf = (CBSDFClosure *)prim;
151                                         int scattering = bsdf->scattering();
152
153                                         /* no caustics option */
154                                         if (no_glossy && scattering == LABEL_GLOSSY)
155                                                 return;
156
157                                         /* sample weight */
158                                         float sample_weight = fabsf(average(weight));
159
160                                         sc.sample_weight = sample_weight;
161
162                                         sc.type = bsdf->sc.type;
163                                         sc.N = bsdf->sc.N;
164                                         sc.T = bsdf->sc.T;
165                                         sc.data0 = bsdf->sc.data0;
166                                         sc.data1 = bsdf->sc.data1;
167                                         sc.prim = bsdf->sc.prim;
168
169                                         /* add */
170                                         if(sc.sample_weight > 1e-5f && sd->num_closure < MAX_CLOSURE) {
171                                                 sd->closure[sd->num_closure++] = sc;
172                                                 sd->flag |= bsdf->shaderdata_flag();
173                                         }
174                                         break;
175                                 }
176                                 case OSL::ClosurePrimitive::Emissive: {
177                                         /* sample weight */
178                                         float sample_weight = fabsf(average(weight));
179
180                                         sc.sample_weight = sample_weight;
181                                         sc.type = CLOSURE_EMISSION_ID;
182                                         sc.prim = NULL;
183
184                                         /* flag */
185                                         if(sd->num_closure < MAX_CLOSURE) {
186                                                 sd->closure[sd->num_closure++] = sc;
187                                                 sd->flag |= SD_EMISSION;
188                                         }
189                                         break;
190                                 }
191                                 case AmbientOcclusion: {
192                                         /* sample weight */
193                                         float sample_weight = fabsf(average(weight));
194
195                                         sc.sample_weight = sample_weight;
196                                         sc.type = CLOSURE_AMBIENT_OCCLUSION_ID;
197                                         sc.prim = NULL;
198
199                                         if(sd->num_closure < MAX_CLOSURE) {
200                                                 sd->closure[sd->num_closure++] = sc;
201                                                 sd->flag |= SD_AO;
202                                         }
203                                         break;
204                                 }
205                                 case OSL::ClosurePrimitive::Holdout: {
206                                         sc.sample_weight = 0.0f;
207                                         sc.type = CLOSURE_HOLDOUT_ID;
208                                         sc.prim = NULL;
209
210                                         if(sd->num_closure < MAX_CLOSURE) {
211                                                 sd->closure[sd->num_closure++] = sc;
212                                                 sd->flag |= SD_HOLDOUT;
213                                         }
214                                         break;
215                                 }
216                                 case OSL::ClosurePrimitive::BSSRDF: {
217                                         CBSSRDFClosure *bssrdf = (CBSSRDFClosure *)prim;
218                                         float sample_weight = fabsf(average(weight));
219
220                                         if(sample_weight > 1e-5f && sd->num_closure+2 < MAX_CLOSURE) {
221                                                 sc.sample_weight = sample_weight;
222
223                                                 sc.type = bssrdf->sc.type;
224                                                 sc.N = bssrdf->sc.N;
225                                                 sc.data1 = bssrdf->sc.data1;
226                                                 sc.prim = NULL;
227
228                                                 /* create one closure for each color channel */
229                                                 if(fabsf(weight.x) > 0.0f) {
230                                                         sc.weight = make_float3(weight.x, 0.0f, 0.0f);
231                                                         sc.data0 = bssrdf->radius.x;
232                                                         sd->closure[sd->num_closure++] = sc;
233                                                         sd->flag |= bssrdf->shaderdata_flag();
234                                                 }
235
236                                                 if(fabsf(weight.y) > 0.0f) {
237                                                         sc.weight = make_float3(0.0f, weight.y, 0.0f);
238                                                         sc.data0 = bssrdf->radius.y;
239                                                         sd->closure[sd->num_closure++] = sc;
240                                                         sd->flag |= bssrdf->shaderdata_flag();
241                                                 }
242
243                                                 if(fabsf(weight.z) > 0.0f) {
244                                                         sc.weight = make_float3(0.0f, 0.0f, weight.z);
245                                                         sc.data0 = bssrdf->radius.z;
246                                                         sd->closure[sd->num_closure++] = sc;
247                                                         sd->flag |= bssrdf->shaderdata_flag();
248                                                 }
249                                         }
250                                         break;
251                                 }
252                                 case OSL::ClosurePrimitive::Debug:
253                                         break; /* not implemented */
254                                 case OSL::ClosurePrimitive::Background:
255                                 case OSL::ClosurePrimitive::Volume:
256                                         break; /* not relevant */
257                         }
258                 }
259         }
260         else if (closure->type == OSL::ClosureColor::MUL) {
261                 OSL::ClosureMul *mul = (OSL::ClosureMul *)closure;
262                 flatten_surface_closure_tree(sd, no_glossy, mul->closure, TO_FLOAT3(mul->weight) * weight);
263         }
264         else if (closure->type == OSL::ClosureColor::ADD) {
265                 OSL::ClosureAdd *add = (OSL::ClosureAdd *)closure;
266                 flatten_surface_closure_tree(sd, no_glossy, add->closureA, weight);
267                 flatten_surface_closure_tree(sd, no_glossy, add->closureB, weight);
268         }
269 }
270
271 void OSLShader::eval_surface(KernelGlobals *kg, ShaderData *sd, float randb, int path_flag, ShaderContext ctx)
272 {
273         /* setup shader globals from shader data */
274         OSLThreadData *tdata = kg->osl_tdata;
275         shaderdata_to_shaderglobals(kg, sd, path_flag, tdata);
276
277         /* execute shader for this point */
278         OSL::ShadingSystem *ss = (OSL::ShadingSystem*)kg->osl_ss;
279         OSL::ShaderGlobals *globals = &tdata->globals;
280         OSL::ShadingContext *octx = tdata->context[(int)ctx];
281         int shader = sd->shader & SHADER_MASK;
282
283         if (kg->osl->surface_state[shader])
284                 ss->execute(*octx, *(kg->osl->surface_state[shader]), *globals);
285
286         /* flatten closure tree */
287         sd->num_closure = 0;
288         sd->randb_closure = randb;
289
290         if (globals->Ci) {
291                 bool no_glossy = (path_flag & PATH_RAY_DIFFUSE) && kernel_data.integrator.no_caustics;
292                 flatten_surface_closure_tree(sd, no_glossy, globals->Ci);
293         }
294 }
295
296 /* Background */
297
298 static float3 flatten_background_closure_tree(const OSL::ClosureColor *closure)
299 {
300         /* OSL gives us a closure tree, if we are shading for background there
301          * is only one supported closure type at the moment, which has no evaluation
302          * functions, so we just sum the weights */
303
304         if (closure->type == OSL::ClosureColor::COMPONENT) {
305                 OSL::ClosureComponent *comp = (OSL::ClosureComponent *)closure;
306                 OSL::ClosurePrimitive *prim = (OSL::ClosurePrimitive *)comp->data();
307
308                 if (prim && prim->category() == OSL::ClosurePrimitive::Background)
309                         return make_float3(1.0f, 1.0f, 1.0f);
310         }
311         else if (closure->type == OSL::ClosureColor::MUL) {
312                 OSL::ClosureMul *mul = (OSL::ClosureMul *)closure;
313
314                 return TO_FLOAT3(mul->weight) * flatten_background_closure_tree(mul->closure);
315         }
316         else if (closure->type == OSL::ClosureColor::ADD) {
317                 OSL::ClosureAdd *add = (OSL::ClosureAdd *)closure;
318
319                 return flatten_background_closure_tree(add->closureA) +
320                        flatten_background_closure_tree(add->closureB);
321         }
322
323         return make_float3(0.0f, 0.0f, 0.0f);
324 }
325
326 float3 OSLShader::eval_background(KernelGlobals *kg, ShaderData *sd, int path_flag, ShaderContext ctx)
327 {
328         /* setup shader globals from shader data */
329         OSLThreadData *tdata = kg->osl_tdata;
330         shaderdata_to_shaderglobals(kg, sd, path_flag, tdata);
331
332         /* execute shader for this point */
333         OSL::ShadingSystem *ss = (OSL::ShadingSystem*)kg->osl_ss;
334         OSL::ShaderGlobals *globals = &tdata->globals;
335         OSL::ShadingContext *octx = tdata->context[(int)ctx];
336
337         if (kg->osl->background_state)
338                 ss->execute(*octx, *(kg->osl->background_state), *globals);
339
340         /* return background color immediately */
341         if (globals->Ci)
342                 return flatten_background_closure_tree(globals->Ci);
343
344         return make_float3(0.0f, 0.0f, 0.0f);
345 }
346
347 /* Volume */
348
349 static void flatten_volume_closure_tree(ShaderData *sd,
350                                         const OSL::ClosureColor *closure, float3 weight = make_float3(1.0f, 1.0f, 1.0f))
351 {
352         /* OSL gives us a closure tree, we flatten it into arrays per
353          * closure type, for evaluation, sampling, etc later on. */
354
355         if (closure->type == OSL::ClosureColor::COMPONENT) {
356                 OSL::ClosureComponent *comp = (OSL::ClosureComponent *)closure;
357                 OSL::ClosurePrimitive *prim = (OSL::ClosurePrimitive *)comp->data();
358
359                 if (prim) {
360                         ShaderClosure sc;
361                         sc.weight = weight;
362
363                         switch (prim->category()) {
364                                 case OSL::ClosurePrimitive::Volume: {
365                                         /* sample weight */
366                                         float sample_weight = fabsf(average(weight));
367
368                                         sc.sample_weight = sample_weight;
369                                         sc.type = CLOSURE_VOLUME_ID;
370                                         sc.prim = NULL;
371
372                                         /* add */
373                                         if(sc.sample_weight > 1e-5f && sd->num_closure < MAX_CLOSURE)
374                                                 sd->closure[sd->num_closure++] = sc;
375                                         break;
376                                 }
377                                 case OSL::ClosurePrimitive::Holdout:
378                                 case OSL::ClosurePrimitive::Debug:
379                                         break; /* not implemented */
380                                 case OSL::ClosurePrimitive::Background:
381                                 case OSL::ClosurePrimitive::BSDF:
382                                 case OSL::ClosurePrimitive::Emissive:
383                                 case OSL::ClosurePrimitive::BSSRDF:
384                                         break; /* not relevant */
385                         }
386                 }
387         }
388         else if (closure->type == OSL::ClosureColor::MUL) {
389                 OSL::ClosureMul *mul = (OSL::ClosureMul *)closure;
390                 flatten_volume_closure_tree(sd, mul->closure, TO_FLOAT3(mul->weight) * weight);
391         }
392         else if (closure->type == OSL::ClosureColor::ADD) {
393                 OSL::ClosureAdd *add = (OSL::ClosureAdd *)closure;
394                 flatten_volume_closure_tree(sd, add->closureA, weight);
395                 flatten_volume_closure_tree(sd, add->closureB, weight);
396         }
397 }
398
399 void OSLShader::eval_volume(KernelGlobals *kg, ShaderData *sd, float randb, int path_flag, ShaderContext ctx)
400 {
401         /* setup shader globals from shader data */
402         OSLThreadData *tdata = kg->osl_tdata;
403         shaderdata_to_shaderglobals(kg, sd, path_flag, tdata);
404
405         /* execute shader */
406         OSL::ShadingSystem *ss = (OSL::ShadingSystem*)kg->osl_ss;
407         OSL::ShaderGlobals *globals = &tdata->globals;
408         OSL::ShadingContext *octx = tdata->context[(int)ctx];
409         int shader = sd->shader & SHADER_MASK;
410
411         if (kg->osl->volume_state[shader])
412                 ss->execute(*octx, *(kg->osl->volume_state[shader]), *globals);
413
414         if (globals->Ci)
415                 flatten_volume_closure_tree(sd, globals->Ci);
416 }
417
418 /* Displacement */
419
420 void OSLShader::eval_displacement(KernelGlobals *kg, ShaderData *sd, ShaderContext ctx)
421 {
422         /* setup shader globals from shader data */
423         OSLThreadData *tdata = kg->osl_tdata;
424         shaderdata_to_shaderglobals(kg, sd, 0, tdata);
425
426         /* execute shader */
427         OSL::ShadingSystem *ss = (OSL::ShadingSystem*)kg->osl_ss;
428         OSL::ShaderGlobals *globals = &tdata->globals;
429         OSL::ShadingContext *octx = tdata->context[(int)ctx];
430         int shader = sd->shader & SHADER_MASK;
431
432         if (kg->osl->displacement_state[shader])
433                 ss->execute(*octx, *(kg->osl->displacement_state[shader]), *globals);
434
435         /* get back position */
436         sd->P = TO_FLOAT3(globals->P);
437 }
438
439 /* BSDF Closure */
440
441 int OSLShader::bsdf_sample(const ShaderData *sd, const ShaderClosure *sc, float randu, float randv, float3& eval, float3& omega_in, differential3& domega_in, float& pdf)
442 {
443         CBSDFClosure *sample_bsdf = (CBSDFClosure *)sc->prim;
444
445         pdf = 0.0f;
446
447         return sample_bsdf->sample(sd->Ng,
448                                    sd->I, sd->dI.dx, sd->dI.dy,
449                                    randu, randv,
450                                    omega_in, domega_in.dx, domega_in.dy,
451                                    pdf, eval);
452 }
453
454 float3 OSLShader::bsdf_eval(const ShaderData *sd, const ShaderClosure *sc, const float3& omega_in, float& pdf)
455 {
456         CBSDFClosure *bsdf = (CBSDFClosure *)sc->prim;
457         float3 bsdf_eval;
458
459         if (dot(sd->Ng, omega_in) >= 0.0f)
460                 bsdf_eval = bsdf->eval_reflect(sd->I, omega_in, pdf);
461         else
462                 bsdf_eval = bsdf->eval_transmit(sd->I, omega_in, pdf);
463         
464         return bsdf_eval;
465 }
466
467 void OSLShader::bsdf_blur(ShaderClosure *sc, float roughness)
468 {
469         CBSDFClosure *bsdf = (CBSDFClosure *)sc->prim;
470         bsdf->blur(roughness);
471 }
472
473 /* Emissive Closure */
474
475 float3 OSLShader::emissive_eval(const ShaderData *sd, const ShaderClosure *sc)
476 {
477         OSL::EmissiveClosure *emissive = (OSL::EmissiveClosure *)sc->prim;
478         OSL::Color3 emissive_eval = emissive->eval(TO_VEC3(sd->Ng), TO_VEC3(sd->I));
479
480         return TO_FLOAT3(emissive_eval);
481 }
482
483 /* Volume Closure */
484
485 float3 OSLShader::volume_eval_phase(const ShaderClosure *sc, const float3 omega_in, const float3 omega_out)
486 {
487         OSL::VolumeClosure *volume = (OSL::VolumeClosure *)sc->prim;
488         OSL::Color3 volume_eval = volume->eval_phase(TO_VEC3(omega_in), TO_VEC3(omega_out));
489         return TO_FLOAT3(volume_eval) * sc->weight;
490 }
491
492 /* Attributes */
493
494 int OSLShader::find_attribute(KernelGlobals *kg, const ShaderData *sd, uint id, AttributeElement *elem)
495 {
496         /* for OSL, a hash map is used to lookup the attribute by name. */
497         int object = sd->object*ATTR_PRIM_TYPES;
498 #ifdef __HAIR__
499         if(sd->segment != ~0) object += ATTR_PRIM_CURVE;
500 #endif
501
502         OSLGlobals::AttributeMap &attr_map = kg->osl->attribute_map[object];
503         ustring stdname(std::string("geom:") + std::string(Attribute::standard_name((AttributeStandard)id)));
504         OSLGlobals::AttributeMap::const_iterator it = attr_map.find(stdname);
505
506         if (it != attr_map.end()) {
507                 const OSLGlobals::Attribute &osl_attr = it->second;
508                 *elem = osl_attr.elem;
509                 /* return result */
510                 return (osl_attr.elem == ATTR_ELEMENT_NONE) ? (int)ATTR_STD_NOT_FOUND : osl_attr.offset;
511         }
512         else
513                 return (int)ATTR_STD_NOT_FOUND;
514 }
515
516 CCL_NAMESPACE_END
517