Blender V4.5
closures.cpp
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2009-2010 Sony Pictures Imageworks Inc., et al. All Rights Reserved.
2 * SPDX-FileCopyrightText: 2011-2022 Blender Foundation
3 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 *
6 * Adapted code from Open Shading Language. */
7
8#include <OSL/genclosure.h>
9#include <OSL/oslclosure.h>
10
11#include "kernel/types.h"
12
13#include "kernel/osl/globals.h"
14#include "kernel/osl/services.h"
15
16#include "util/math.h"
17#include "util/param.h"
18
19#include "kernel/globals.h"
20
21#include "kernel/geom/object.h"
23
24#include "kernel/osl/camera.h"
25#include "kernel/osl/osl.h"
26
27#define TO_VEC3(v) OSL::Vec3(v.x, v.y, v.z)
28#define TO_FLOAT3(v) make_float3(v[0], v[1], v[2])
29
31
32static_assert(sizeof(OSLClosure) == sizeof(OSL::ClosureColor) &&
33 sizeof(OSLClosureAdd) == sizeof(OSL::ClosureAdd) &&
34 sizeof(OSLClosureMul) == sizeof(OSL::ClosureMul) &&
35 sizeof(OSLClosureComponent) == sizeof(OSL::ClosureComponent));
36static_assert(sizeof(ShaderGlobals) >= sizeof(OSL::ShaderGlobals) &&
37 offsetof(ShaderGlobals, backfacing) == offsetof(OSL::ShaderGlobals, backfacing));
38
39/* Registration */
40
41#define OSL_CLOSURE_STRUCT_BEGIN(Upper, lower) \
42 static OSL::ClosureParam *osl_closure_##lower##_params() \
43 { \
44 static OSL::ClosureParam params[] = {
45#define OSL_CLOSURE_STRUCT_END(Upper, lower) \
46 CLOSURE_STRING_KEYPARAM(Upper##Closure, label, "label"), CLOSURE_FINISH_PARAM(Upper##Closure) \
47 } \
48 ; \
49 return params; \
50 }
51#define OSL_CLOSURE_STRUCT_MEMBER(Upper, TYPE, type, name, key) \
52 CLOSURE_##TYPE##_KEYPARAM(Upper##Closure, name, key),
53#define OSL_CLOSURE_STRUCT_ARRAY_MEMBER(Upper, TYPE, type, name, key, size) \
54 CLOSURE_##TYPE##_ARRAY_PARAM(Upper##Closure, name, size),
55
56#include "closures_template.h"
57
58static OSL::ClosureParam *osl_closure_layer_params()
59{
60 static OSL::ClosureParam params[] = {CLOSURE_CLOSURE_PARAM(LayerClosure, top),
61 CLOSURE_CLOSURE_PARAM(LayerClosure, base),
62 CLOSURE_FINISH_PARAM(LayerClosure)};
63 return params;
64}
65
66void OSLRenderServices::register_closures(OSL::ShadingSystem *ss)
67{
68#define OSL_CLOSURE_STRUCT_BEGIN(Upper, lower) \
69 ss->register_closure( \
70 #lower, OSL_CLOSURE_##Upper##_ID, osl_closure_##lower##_params(), nullptr, nullptr);
71
72#include "closures_template.h"
73 ss->register_closure(
74 "layer", OSL_CLOSURE_LAYER_ID, osl_closure_layer_params(), nullptr, nullptr);
75}
76
77/* Surface & Background */
78
79template<>
81 const void *state,
82 ShaderData *sd,
83 const uint32_t path_flag)
84{
85 /* setup shader globals from shader data */
86 shaderdata_to_shaderglobals(kg, sd, path_flag, &kg->osl.shader_globals);
87
88 /* clear trace data */
89 kg->osl.tracedata.init = false;
90
91 /* Used by render-services. */
92 kg->osl.shader_globals.kg = kg;
93 if (path_flag & PATH_RAY_SHADOW) {
94 kg->osl.shader_globals.path_state = nullptr;
95 kg->osl.shader_globals.shadow_path_state = (const IntegratorShadowStateCPU *)state;
96 }
97 else {
98 kg->osl.shader_globals.path_state = (const IntegratorStateCPU *)state;
99 kg->osl.shader_globals.shadow_path_state = nullptr;
100 }
101
102 /* execute shader for this point */
103 OSL::ShadingSystem *ss = (OSL::ShadingSystem *)kg->osl.ss;
104 OSL::ShaderGlobals *globals = reinterpret_cast<OSL::ShaderGlobals *>(&kg->osl.shader_globals);
105 OSL::ShadingContext *octx = kg->osl.context;
106 const int shader = sd->shader & SHADER_MASK;
107
108 if (sd->object == OBJECT_NONE) {
109 /* background */
110 if (kg->osl.globals->background_state) {
111 ss->execute(*octx,
112 *(kg->osl.globals->background_state),
113 kg->osl.thread_index,
114 0,
115 *globals,
116 nullptr,
117 nullptr);
118 }
119 }
120 else {
121 /* automatic bump shader */
122 if (kg->osl.globals->bump_state[shader]) {
123 /* save state */
124 const float3 P = sd->P;
125 const float dP = sd->dP;
126 const OSL::Vec3 dPdx = globals->dPdx;
127 const OSL::Vec3 dPdy = globals->dPdy;
128
129 /* set state as if undisplaced */
130 if (sd->flag & SD_HAS_DISPLACEMENT) {
131 float data[9];
132 const bool found = kg->osl.globals->services->get_attribute(
133 globals,
134 true,
136 TypeVector,
138 data);
139 (void)found;
140 assert(found);
141
142 differential3 tmp_dP;
143 sd->P = make_float3(data[0], data[1], data[2]);
144 tmp_dP.dx = make_float3(data[3], data[4], data[5]);
145 tmp_dP.dy = make_float3(data[6], data[7], data[8]);
146
147 object_position_transform(kg, sd, &sd->P);
148 object_dir_transform(kg, sd, &tmp_dP.dx);
149 object_dir_transform(kg, sd, &tmp_dP.dy);
150
151 sd->dP = differential_make_compact(tmp_dP);
152
153 globals->P = TO_VEC3(sd->P);
154 globals->dPdx = TO_VEC3(tmp_dP.dx);
155 globals->dPdy = TO_VEC3(tmp_dP.dy);
156 }
157
158 /* execute bump shader */
159 ss->execute(*octx,
160 *(kg->osl.globals->bump_state[shader]),
161 kg->osl.thread_index,
162 0,
163 *globals,
164 nullptr,
165 nullptr);
166
167 /* reset state */
168 sd->P = P;
169 sd->dP = dP;
170
171 /* Apply bump output to sd->N since it's used for shadow terminator logic, for example. */
172 sd->N = TO_FLOAT3(globals->N);
173
174 globals->P = TO_VEC3(P);
175 globals->dPdx = TO_VEC3(dPdx);
176 globals->dPdy = TO_VEC3(dPdy);
177 }
178
179 /* surface shader */
180 if (kg->osl.globals->surface_state[shader]) {
181 ss->execute(*octx,
182 *(kg->osl.globals->surface_state[shader]),
183 kg->osl.thread_index,
184 0,
185 *globals,
186 nullptr,
187 nullptr);
188 }
189 }
190
191 /* flatten closure tree */
192 if (kg->osl.shader_globals.Ci) {
193 flatten_closure_tree(kg, sd, path_flag, kg->osl.shader_globals.Ci);
194 }
195}
196
197/* Volume */
198
199template<>
201 const void *state,
202 ShaderData *sd,
203 const uint32_t path_flag)
204{
205 /* setup shader globals from shader data */
206 shaderdata_to_shaderglobals(kg, sd, path_flag, &kg->osl.shader_globals);
207
208 /* clear trace data */
209 kg->osl.tracedata.init = false;
210
211 /* Used by render-services. */
212 kg->osl.shader_globals.kg = kg;
213 if (path_flag & PATH_RAY_SHADOW) {
214 kg->osl.shader_globals.path_state = nullptr;
215 kg->osl.shader_globals.shadow_path_state = (const IntegratorShadowStateCPU *)state;
216 }
217 else {
218 kg->osl.shader_globals.path_state = (const IntegratorStateCPU *)state;
219 kg->osl.shader_globals.shadow_path_state = nullptr;
220 }
221
222 /* execute shader */
223 OSL::ShadingSystem *ss = (OSL::ShadingSystem *)kg->osl.ss;
224 OSL::ShaderGlobals *globals = reinterpret_cast<OSL::ShaderGlobals *>(&kg->osl.shader_globals);
225 OSL::ShadingContext *octx = kg->osl.context;
226 const int shader = sd->shader & SHADER_MASK;
227
228 if (kg->osl.globals->volume_state[shader]) {
229 ss->execute(*octx,
230 *(kg->osl.globals->volume_state[shader]),
231 kg->osl.thread_index,
232 0,
233 *globals,
234 nullptr,
235 nullptr);
236 }
237
238 /* flatten closure tree */
239 if (kg->osl.shader_globals.Ci) {
240 flatten_closure_tree(kg, sd, path_flag, kg->osl.shader_globals.Ci);
241 }
242}
243
244/* Displacement */
245
246template<>
248 const void *state,
249 ShaderData *sd,
250 const uint32_t path_flag)
251{
252 /* setup shader globals from shader data */
253 shaderdata_to_shaderglobals(kg, sd, path_flag, &kg->osl.shader_globals);
254
255 /* clear trace data */
256 kg->osl.tracedata.init = false;
257
258 /* Used by render-services. */
259 kg->osl.shader_globals.kg = kg;
260 kg->osl.shader_globals.path_state = (const IntegratorStateCPU *)state;
261 kg->osl.shader_globals.shadow_path_state = nullptr;
262
263 /* execute shader */
264 OSL::ShadingSystem *ss = (OSL::ShadingSystem *)kg->osl.ss;
265 OSL::ShaderGlobals *globals = reinterpret_cast<OSL::ShaderGlobals *>(&kg->osl.shader_globals);
266 OSL::ShadingContext *octx = kg->osl.context;
267 const int shader = sd->shader & SHADER_MASK;
268
269 if (kg->osl.globals->displacement_state[shader]) {
270 ss->execute(*octx,
271 *(kg->osl.globals->displacement_state[shader]),
272 kg->osl.thread_index,
273 0,
274 *globals,
275 nullptr,
276 nullptr);
277 }
278
279 /* get back position */
280 sd->P = TO_FLOAT3(globals->P);
281}
282
283/* Camera */
284
286 const packed_float3 sensor,
287 const packed_float3 dSdx,
288 const packed_float3 dSdy,
289 const float2 rand_lens,
291 packed_float3 &dPdx,
292 packed_float3 &dPdy,
294 packed_float3 &dDdx,
295 packed_float3 &dDdy)
296{
297 if (!kg->osl.globals->camera_state) {
298 return zero_spectrum();
299 }
300
301 /* Setup shader globals from the sensor position. */
302 cameradata_to_shaderglobals(sensor, dSdx, dSdy, rand_lens, &kg->osl.shader_globals);
303
304 /* Clear trace data. */
305 kg->osl.tracedata.init = false;
306
307 /* Provide kernel globals to the render-services. */
308 kg->osl.shader_globals.kg = kg;
309
310 /* Execute the shader. */
311 OSL::ShadingSystem *ss = (OSL::ShadingSystem *)kg->osl.ss;
312 OSL::ShaderGlobals *globals = reinterpret_cast<OSL::ShaderGlobals *>(&kg->osl.shader_globals);
313 OSL::ShadingContext *octx = kg->osl.context;
314
315 float output[21] = {0.0f};
316
317 ss->execute(
318 *octx, *kg->osl.globals->camera_state, kg->osl.thread_index, 0, *globals, nullptr, output);
319
320 P = make_float3(output[0], output[1], output[2]);
321 dPdx = make_float3(output[3], output[4], output[5]);
322 dPdy = make_float3(output[6], output[7], output[8]);
323 D = make_float3(output[9], output[10], output[11]);
324 dDdx = make_float3(output[12], output[13], output[14]);
325 dDdy = make_float3(output[15], output[16], output[17]);
326 return make_float3(output[18], output[19], output[20]);
327}
328
#define D
BMesh const char void * data
static ustring u_empty
Definition services.h:320
static ustring u_geom_undisplaced
Definition services.h:293
static void register_closures(OSL::ShadingSystem *ss)
Definition closures.cpp:66
packed_float3 osl_eval_camera(const ThreadKernelGlobalsCPU *kg, const packed_float3 sensor, const packed_float3 dSdx, const packed_float3 dSdy, const float2 rand_lens, packed_float3 &P, packed_float3 &dPdx, packed_float3 &dPdy, packed_float3 &D, packed_float3 &dDdx, packed_float3 &dDdy)
Definition closures.cpp:285
void osl_eval_nodes< SHADER_TYPE_DISPLACEMENT >(const ThreadKernelGlobalsCPU *kg, const void *state, ShaderData *sd, const uint32_t path_flag)
Definition closures.cpp:247
void osl_eval_nodes< SHADER_TYPE_VOLUME >(const ThreadKernelGlobalsCPU *kg, const void *state, ShaderData *sd, const uint32_t path_flag)
Definition closures.cpp:200
void osl_eval_nodes< SHADER_TYPE_SURFACE >(const ThreadKernelGlobalsCPU *kg, const void *state, ShaderData *sd, const uint32_t path_flag)
Definition closures.cpp:80
#define TO_FLOAT3(v)
Definition closures.cpp:28
static OSL::ClosureParam * osl_closure_layer_params()
Definition closures.cpp:58
#define TO_VEC3(v)
Definition closures.cpp:27
#define zero_spectrum
#define OBJECT_NONE
#define CCL_NAMESPACE_END
ccl_device_forceinline float3 make_float3(const float x, const float y, const float z)
#define offsetof(t, d)
ccl_device_forceinline float differential_make_compact(const float dD)
uint top
#define assert(assertion)
#define output
uiWidgetBaseParameters params[MAX_WIDGET_BASE_BATCH]
ccl_device_inline void object_dir_transform(KernelGlobals kg, const ccl_private ShaderData *sd, ccl_private float3 *D)
ccl_device_inline void object_position_transform(KernelGlobals kg, const ccl_private ShaderData *sd, ccl_private float3 *P)
CCL_NAMESPACE_BEGIN ccl_device_inline void cameradata_to_shaderglobals(const packed_float3 sensor, const packed_float3 dSdx, const packed_float3 dSdy, const float2 rand_lens, ccl_private ShaderGlobals *globals)
ccl_device void flatten_closure_tree(KernelGlobals kg, ccl_private ShaderData *sd, const uint32_t path_flag, const ccl_private OSLClosure *closure)
CCL_NAMESPACE_BEGIN ccl_device_inline void shaderdata_to_shaderglobals(KernelGlobals kg, ccl_private ShaderData *sd, const uint32_t path_flag, ccl_private ShaderGlobals *globals)
@ SD_HAS_DISPLACEMENT
@ PATH_RAY_SHADOW
@ SHADER_MASK
static ulong state[N]