bf615f673cfea03fac02ff27085a6fceffe0bf5f
[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_services.h"
25 #include "osl_shader.h"
26
27 #include "util_foreach.h"
28
29 #include <OSL/oslexec.h>
30
31 CCL_NAMESPACE_BEGIN
32
33 tls_ptr(OSLGlobals::ThreadData, OSLGlobals::thread_data);
34
35 /* Threads */
36
37 void OSLShader::thread_init(KernelGlobals *kg)
38 {
39         OSL::ShadingSystem *ss = kg->osl.ss;
40
41         OSLGlobals::ThreadData *tdata = new OSLGlobals::ThreadData();
42
43         memset(&tdata->globals, 0, sizeof(OSL::ShaderGlobals));
44         tdata->thread_info = ss->create_thread_info();
45
46         tls_set(kg->osl.thread_data, tdata);
47
48         //((OSLRenderServices *)ssi->renderer())->thread_init(kg);
49         /* XXX not sure here - dingto */
50         thread_init(kg);
51 }
52
53 void OSLShader::thread_free(KernelGlobals *kg)
54 {
55         OSL::ShadingSystem *ss = kg->osl.ss;
56
57         OSLGlobals::ThreadData *tdata = tls_get(OSLGlobals::ThreadData, kg->osl.thread_data);
58
59         ss->destroy_thread_info(tdata->thread_info);
60
61         delete tdata;
62 }
63
64 /* Globals */
65
66 #define TO_VEC3(v) (*(OSL::Vec3 *)&(v))
67 #define TO_COLOR3(v) (*(OSL::Color3 *)&(v))
68 #define TO_FLOAT3(v) make_float3(v[0], v[1], v[2])
69
70 static void shaderdata_to_shaderglobals(KernelGlobals *kg, ShaderData *sd,
71                                         int path_flag, OSL::ShaderGlobals *globals)
72 {
73         /* copy from shader data to shader globals */
74         globals->P = TO_VEC3(sd->P);
75         globals->dPdx = TO_VEC3(sd->dP.dx);
76         globals->dPdy = TO_VEC3(sd->dP.dy);
77         globals->I = TO_VEC3(sd->I);
78         globals->dIdx = TO_VEC3(sd->dI.dx);
79         globals->dIdy = TO_VEC3(sd->dI.dy);
80         globals->N = TO_VEC3(sd->N);
81         globals->Ng = TO_VEC3(sd->Ng);
82         globals->u = sd->u;
83         globals->dudx = sd->du.dx;
84         globals->dudy = sd->du.dy;
85         globals->v = sd->v;
86         globals->dvdx = sd->dv.dx;
87         globals->dvdy = sd->dv.dy;
88         globals->dPdu = TO_VEC3(sd->dPdu);
89         globals->dPdv = TO_VEC3(sd->dPdv);
90         globals->surfacearea = (sd->object == ~0) ? 1.0f : object_surface_area(kg, sd->object);
91
92         /* booleans */
93         globals->raytype = path_flag; /* todo: add our own ray types */
94         globals->backfacing = (sd->flag & SD_BACKFACING);
95
96         /* don't know yet if we need this */
97         globals->flipHandedness = false;
98         
99         /* shader data to be used in services callbacks */
100         globals->renderstate = sd; 
101
102         /* hacky, we leave it to services to fetch actual object matrix */
103         globals->shader2common = sd;
104         globals->object2common = sd;
105
106         /* must be set to NULL before execute */
107         globals->Ci = NULL;
108 }
109
110 /* Surface */
111
112 static void flatten_surface_closure_tree(ShaderData *sd, bool no_glossy,
113                                          const OSL::ClosureColor *closure, float3 weight = make_float3(1.0f, 1.0f, 1.0f))
114 {
115         /* OSL gives us a closure tree, we flatten it into arrays per
116          * closure type, for evaluation, sampling, etc later on. */
117
118         if (closure->type == OSL::ClosureColor::COMPONENT) {
119                 OSL::ClosureComponent *comp = (OSL::ClosureComponent *)closure;
120                 OSL::ClosurePrimitive *prim = (OSL::ClosurePrimitive *)comp->data();
121
122                 if (prim) {
123                         ShaderClosure sc;
124                         sc.prim = prim;
125                         sc.weight = weight;
126
127                         switch (prim->category()) {
128                                 case OSL::ClosurePrimitive::BSDF: {
129                                         if (sd->num_closure == MAX_CLOSURE)
130                                                 return;
131
132                                         OSL::BSDFClosure *bsdf = (OSL::BSDFClosure *)prim;
133                                         ustring scattering = bsdf->scattering();
134
135                                         /* no caustics option */
136                                         if (no_glossy && scattering == OSL::Labels::GLOSSY)
137                                                 return;
138
139                                         /* sample weight */
140                                         float albedo = bsdf->albedo(TO_VEC3(sd->I));
141                                         float sample_weight = fabsf(average(weight)) * albedo;
142
143                                         sc.sample_weight = sample_weight;
144                                         sc.type = CLOSURE_BSDF_ID;
145
146                                         /* scattering flags */
147                                         if (scattering == OSL::Labels::DIFFUSE)
148                                                 sd->flag |= SD_BSDF | SD_BSDF_HAS_EVAL;
149                                         else if (scattering == OSL::Labels::GLOSSY)
150                                                 sd->flag |= SD_BSDF | SD_BSDF_HAS_EVAL | SD_BSDF_GLOSSY;
151                                         else
152                                                 sd->flag |= SD_BSDF;
153
154                                         /* add */
155                                         sd->closure[sd->num_closure++] = sc;
156                                         break;
157                                 }
158                                 case OSL::ClosurePrimitive::Emissive: {
159                                         if (sd->num_closure == MAX_CLOSURE)
160                                                 return;
161
162                                         /* sample weight */
163                                         float sample_weight = fabsf(average(weight));
164
165                                         sc.sample_weight = sample_weight;
166                                         sc.type = CLOSURE_EMISSION_ID;
167
168                                         /* flag */
169                                         sd->flag |= SD_EMISSION;
170
171                                         sd->closure[sd->num_closure++] = sc;
172                                         break;
173                                 }
174                                 case OSL::ClosurePrimitive::Holdout:
175                                         if (sd->num_closure == MAX_CLOSURE)
176                                                 return;
177
178                                         sc.sample_weight = 0.0f;
179                                         sc.type = CLOSURE_HOLDOUT_ID;
180                                         sd->flag |= SD_HOLDOUT;
181                                         sd->closure[sd->num_closure++] = sc;
182                                         break;
183                                 case OSL::ClosurePrimitive::BSSRDF:
184                                 case OSL::ClosurePrimitive::Debug:
185                                         break; /* not implemented */
186                                 case OSL::ClosurePrimitive::Background:
187                                 case OSL::ClosurePrimitive::Volume:
188                                         break; /* not relevant */
189                         }
190                 }
191         }
192         else if (closure->type == OSL::ClosureColor::MUL) {
193                 OSL::ClosureMul *mul = (OSL::ClosureMul *)closure;
194                 flatten_surface_closure_tree(sd, no_glossy, mul->closure, TO_FLOAT3(mul->weight) * weight);
195         }
196         else if (closure->type == OSL::ClosureColor::ADD) {
197                 OSL::ClosureAdd *add = (OSL::ClosureAdd *)closure;
198                 flatten_surface_closure_tree(sd, no_glossy, add->closureA, weight);
199                 flatten_surface_closure_tree(sd, no_glossy, add->closureB, weight);
200         }
201 }
202
203 void OSLShader::eval_surface(KernelGlobals *kg, ShaderData *sd, float randb, int path_flag)
204 {
205         /* gather pointers */
206         OSL::ShadingSystem *ss = kg->osl.ss;
207         OSLGlobals::ThreadData *tdata = tls_get(OSLGlobals::ThreadData, kg->osl.thread_data);
208         OSL::ShaderGlobals *globals = &tdata->globals;
209         OSL::ShadingContext *ctx = ss->get_context(tdata->thread_info);
210
211         /* setup shader globals from shader data */
212         sd->osl_ctx = ctx;
213         shaderdata_to_shaderglobals(kg, sd, path_flag, globals);
214
215         /* execute shader for this point */
216         int shader = sd->shader & SHADER_MASK;
217
218         if (kg->osl.surface_state[shader])
219                 ss->execute(*ctx, *(kg->osl.surface_state[shader]), *globals);
220
221         /* flatten closure tree */
222         sd->num_closure = 0;
223         sd->randb_closure = randb;
224
225         if (globals->Ci) {
226                 bool no_glossy = (path_flag & PATH_RAY_DIFFUSE) && kernel_data.integrator.no_caustics;
227                 flatten_surface_closure_tree(sd, no_glossy, globals->Ci);
228         }
229 }
230
231 /* Background */
232
233 static float3 flatten_background_closure_tree(const OSL::ClosureColor *closure)
234 {
235         /* OSL gives us a closure tree, if we are shading for background there
236          * is only one supported closure type at the moment, which has no evaluation
237          * functions, so we just sum the weights */
238
239         if (closure->type == OSL::ClosureColor::COMPONENT) {
240                 OSL::ClosureComponent *comp = (OSL::ClosureComponent *)closure;
241                 OSL::ClosurePrimitive *prim = (OSL::ClosurePrimitive *)comp->data();
242
243                 if (prim && prim->category() == OSL::ClosurePrimitive::Background)
244                         return make_float3(1.0f, 1.0f, 1.0f);
245         }
246         else if (closure->type == OSL::ClosureColor::MUL) {
247                 OSL::ClosureMul *mul = (OSL::ClosureMul *)closure;
248
249                 return TO_FLOAT3(mul->weight) * flatten_background_closure_tree(mul->closure);
250         }
251         else if (closure->type == OSL::ClosureColor::ADD) {
252                 OSL::ClosureAdd *add = (OSL::ClosureAdd *)closure;
253
254                 return flatten_background_closure_tree(add->closureA) +
255                        flatten_background_closure_tree(add->closureB);
256         }
257
258         return make_float3(0.0f, 0.0f, 0.0f);
259 }
260
261 float3 OSLShader::eval_background(KernelGlobals *kg, ShaderData *sd, int path_flag)
262 {
263         /* gather pointers */
264         OSL::ShadingSystem *ss = kg->osl.ss;
265         OSLGlobals::ThreadData *tdata = tls_get(OSLGlobals::ThreadData, kg->osl.thread_data);
266         OSL::ShaderGlobals *globals = &tdata->globals;
267         OSL::ShadingContext *ctx = ss->get_context(tdata->thread_info);
268
269         /* setup shader globals from shader data */
270         sd->osl_ctx = ctx;
271         shaderdata_to_shaderglobals(kg, sd, path_flag, globals);
272
273         /* execute shader for this point */
274         if (kg->osl.background_state)
275                 ss->execute(*ctx, *(kg->osl.background_state), *globals);
276
277         /* return background color immediately */
278         if (globals->Ci)
279                 return flatten_background_closure_tree(globals->Ci);
280
281         return make_float3(0.0f, 0.0f, 0.0f);
282 }
283
284 /* Volume */
285
286 static void flatten_volume_closure_tree(ShaderData *sd,
287                                         const OSL::ClosureColor *closure, float3 weight = make_float3(1.0f, 1.0f, 1.0f))
288 {
289         /* OSL gives us a closure tree, we flatten it into arrays per
290          * closure type, for evaluation, sampling, etc later on. */
291
292         if (closure->type == OSL::ClosureColor::COMPONENT) {
293                 OSL::ClosureComponent *comp = (OSL::ClosureComponent *)closure;
294                 OSL::ClosurePrimitive *prim = (OSL::ClosurePrimitive *)comp->data();
295
296                 if (prim) {
297                         ShaderClosure sc;
298                         sc.prim = prim;
299                         sc.weight = weight;
300
301                         switch (prim->category()) {
302                                 case OSL::ClosurePrimitive::Volume: {
303                                         if (sd->num_closure == MAX_CLOSURE)
304                                                 return;
305
306                                         /* sample weight */
307                                         float sample_weight = fabsf(average(weight));
308
309                                         sc.sample_weight = sample_weight;
310                                         sc.type = CLOSURE_VOLUME_ID;
311
312                                         /* add */
313                                         sd->closure[sd->num_closure++] = sc;
314                                         break;
315                                 }
316                                 case OSL::ClosurePrimitive::Holdout:
317                                 case OSL::ClosurePrimitive::Debug:
318                                         break; /* not implemented */
319                                 case OSL::ClosurePrimitive::Background:
320                                 case OSL::ClosurePrimitive::BSDF:
321                                 case OSL::ClosurePrimitive::Emissive:
322                                 case OSL::ClosurePrimitive::BSSRDF:
323                                         break; /* not relevant */
324                         }
325                 }
326         }
327         else if (closure->type == OSL::ClosureColor::MUL) {
328                 OSL::ClosureMul *mul = (OSL::ClosureMul *)closure;
329                 flatten_volume_closure_tree(sd, mul->closure, TO_FLOAT3(mul->weight) * weight);
330         }
331         else if (closure->type == OSL::ClosureColor::ADD) {
332                 OSL::ClosureAdd *add = (OSL::ClosureAdd *)closure;
333                 flatten_volume_closure_tree(sd, add->closureA, weight);
334                 flatten_volume_closure_tree(sd, add->closureB, weight);
335         }
336 }
337
338 void OSLShader::eval_volume(KernelGlobals *kg, ShaderData *sd, float randb, int path_flag)
339 {
340         /* gather pointers */
341         OSL::ShadingSystem *ss = kg->osl.ss;
342         OSLGlobals::ThreadData *tdata = tls_get(OSLGlobals::ThreadData, kg->osl.thread_data);
343         OSL::ShaderGlobals *globals = &tdata->globals;
344         OSL::ShadingContext *ctx = ss->get_context(tdata->thread_info);
345
346         /* setup shader globals from shader data */
347         sd->osl_ctx = ctx;
348         shaderdata_to_shaderglobals(kg, sd, path_flag, globals);
349
350         /* execute shader */
351         int shader = sd->shader & SHADER_MASK;
352
353         if (kg->osl.volume_state[shader])
354                 ss->execute(*ctx, *(kg->osl.volume_state[shader]), *globals);
355
356         if (globals->Ci)
357                 flatten_volume_closure_tree(sd, globals->Ci);
358 }
359
360 /* Displacement */
361
362 void OSLShader::eval_displacement(KernelGlobals *kg, ShaderData *sd)
363 {
364         /* gather pointers */
365         OSL::ShadingSystem *ss = kg->osl.ss;
366         OSLGlobals::ThreadData *tdata = tls_get(OSLGlobals::ThreadData, kg->osl.thread_data);
367         OSL::ShaderGlobals *globals = &tdata->globals;
368         OSL::ShadingContext *ctx = ss->get_context(tdata->thread_info);
369
370         /* setup shader globals from shader data */
371         sd->osl_ctx = ctx;
372         shaderdata_to_shaderglobals(kg, sd, 0, globals);
373
374         /* execute shader */
375         int shader = sd->shader & SHADER_MASK;
376
377         if (kg->osl.displacement_state[shader])
378                 ss->execute(*ctx, *(kg->osl.displacement_state[shader]), *globals);
379
380         /* get back position */
381         sd->P = TO_FLOAT3(globals->P);
382 }
383
384 void OSLShader::release(KernelGlobals *kg, const ShaderData *sd)
385 {
386         OSL::ShadingSystem *ss = kg->osl.ss;
387         OSLGlobals::ThreadData *tdata = tls_get(OSLGlobals::ThreadData, kg->osl.thread_data);
388         OSL::ShadingContext *ctx = ss->get_context(tdata->thread_info);
389
390         ss->release_context(ctx);
391 }
392
393 /* BSDF Closure */
394
395 int OSLShader::bsdf_sample(const ShaderData *sd, const ShaderClosure *sc, float randu, float randv, float3& eval, float3& omega_in, differential3& domega_in, float& pdf)
396 {
397         OSL::BSDFClosure *sample_bsdf = (OSL::BSDFClosure *)sc->prim;
398         int label = LABEL_NONE;
399
400         pdf = 0.0f;
401
402         /* sample BSDF closure */
403         ustring ulabel;
404
405         ulabel = sample_bsdf->sample(TO_VEC3(sd->Ng),
406                                      TO_VEC3(sd->I), TO_VEC3(sd->dI.dx), TO_VEC3(sd->dI.dy),
407                                      randu, randv,
408                                      TO_VEC3(omega_in), TO_VEC3(domega_in.dx), TO_VEC3(domega_in.dy),
409                                      pdf, TO_COLOR3(eval));
410
411         /* convert OSL label */
412         if (ulabel == OSL::Labels::REFLECT)
413                 label = LABEL_REFLECT;
414         else if (ulabel == OSL::Labels::TRANSMIT)
415                 label = LABEL_TRANSMIT;
416         else
417                 return LABEL_NONE;  /* sampling failed */
418
419         /* convert scattering to our bitflag label */
420         ustring uscattering = sample_bsdf->scattering();
421
422         if (uscattering == OSL::Labels::DIFFUSE)
423                 label |= LABEL_DIFFUSE;
424         else if (uscattering == OSL::Labels::GLOSSY)
425                 label |= LABEL_GLOSSY;
426         else if (uscattering == OSL::Labels::SINGULAR)
427                 label |= LABEL_SINGULAR;
428         else
429                 label |= LABEL_TRANSPARENT;
430
431         return label;
432 }
433
434 float3 OSLShader::bsdf_eval(const ShaderData *sd, const ShaderClosure *sc, const float3& omega_in, float& pdf)
435 {
436         OSL::BSDFClosure *bsdf = (OSL::BSDFClosure *)sc->prim;
437         OSL::Color3 bsdf_eval;
438
439         if (dot(sd->Ng, omega_in) >= 0.0f)
440                 bsdf_eval = bsdf->eval_reflect(TO_VEC3(sd->I), TO_VEC3(omega_in), pdf);
441         else
442                 bsdf_eval = bsdf->eval_transmit(TO_VEC3(sd->I), TO_VEC3(omega_in), pdf);
443         
444         return TO_FLOAT3(bsdf_eval);
445 }
446
447 /* Emissive Closure */
448
449 float3 OSLShader::emissive_eval(const ShaderData *sd, const ShaderClosure *sc)
450 {
451         OSL::EmissiveClosure *emissive = (OSL::EmissiveClosure *)sc->prim;
452         OSL::Color3 emissive_eval = emissive->eval(TO_VEC3(sd->Ng), TO_VEC3(sd->I));
453
454         return TO_FLOAT3(emissive_eval);
455 }
456
457 /* Volume Closure */
458
459 float3 OSLShader::volume_eval_phase(const ShaderData *sd, const ShaderClosure *sc, const float3 omega_in, const float3 omega_out)
460 {
461         OSL::VolumeClosure *volume = (OSL::VolumeClosure *)sc->prim;
462         OSL::Color3 volume_eval = volume->eval_phase(TO_VEC3(omega_in), TO_VEC3(omega_out));
463         return TO_FLOAT3(volume_eval) * sc->weight;
464 }
465
466 CCL_NAMESPACE_END
467