Cycles: add transparent shadow support, i.e. shadows through Transparent BSDF
[blender.git] / intern / cycles / blender / blender_sync.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 "background.h"
20 #include "film.h"
21 #include "../render/filter.h"
22 #include "graph.h"
23 #include "integrator.h"
24 #include "light.h"
25 #include "mesh.h"
26 #include "nodes.h"
27 #include "object.h"
28 #include "scene.h"
29 #include "shader.h"
30
31 #include "device.h"
32
33 #include "blender_sync.h"
34 #include "blender_util.h"
35
36 #include "util_debug.h"
37 #include "util_foreach.h"
38
39 CCL_NAMESPACE_BEGIN
40
41 /* Constructor */
42
43 BlenderSync::BlenderSync(BL::BlendData b_data_, BL::Scene b_scene_, Scene *scene_, bool preview_)
44 : b_data(b_data_), b_scene(b_scene_),
45   shader_map(&scene_->shaders),
46   object_map(&scene_->objects),
47   mesh_map(&scene_->meshes),
48   light_map(&scene_->lights),
49   world_map(NULL),
50   world_recalc(false)
51 {
52         scene = scene_;
53         preview = preview_;
54 }
55
56 BlenderSync::~BlenderSync()
57 {
58 }
59
60 /* Sync */
61
62 bool BlenderSync::sync_recalc()
63 {
64         /* sync recalc flags from blender to cycles. actual update is done separate,
65            so we can do it later on if doing it immediate is not suitable */
66
67         BL::BlendData::materials_iterator b_mat;
68
69         for(b_data.materials.begin(b_mat); b_mat != b_data.materials.end(); ++b_mat)
70                 if(b_mat->recalc())
71                         shader_map.set_recalc(*b_mat);
72
73         BL::BlendData::lamps_iterator b_lamp;
74
75         for(b_data.lamps.begin(b_lamp); b_lamp != b_data.lamps.end(); ++b_lamp)
76                 if(b_lamp->recalc())
77                         shader_map.set_recalc(*b_lamp);
78
79         BL::BlendData::objects_iterator b_ob;
80
81         for(b_data.objects.begin(b_ob); b_ob != b_data.objects.end(); ++b_ob) {
82                 if(b_ob->recalc()) {
83                         object_map.set_recalc(*b_ob);
84                         light_map.set_recalc(*b_ob);
85                 }
86
87                 if(object_is_mesh(*b_ob)) {
88                         if(b_ob->recalc_data() || b_ob->data().recalc()) {
89                                 BL::ID key = object_is_modified(*b_ob)? *b_ob: b_ob->data();
90                                 mesh_map.set_recalc(key);
91                         }
92                 }
93                 else if(object_is_light(*b_ob)) {
94                         if(b_ob->recalc_data() || b_ob->data().recalc())
95                                 light_map.set_recalc(*b_ob);
96                 }
97         }
98
99         BL::BlendData::meshes_iterator b_mesh;
100
101         for(b_data.meshes.begin(b_mesh); b_mesh != b_data.meshes.end(); ++b_mesh)
102                 if(b_mesh->recalc())
103                         mesh_map.set_recalc(*b_mesh);
104
105         BL::BlendData::worlds_iterator b_world;
106
107         for(b_data.worlds.begin(b_world); b_world != b_data.worlds.end(); ++b_world)
108                 if(world_map == b_world->ptr.data && b_world->recalc())
109                         world_recalc = true;
110
111         bool recalc =
112                 shader_map.has_recalc() ||
113                 object_map.has_recalc() ||
114                 light_map.has_recalc() ||
115                 mesh_map.has_recalc() ||
116                 BlendDataObjects_recalc_get(&b_data.ptr) ||
117                 world_recalc;
118
119         return recalc;
120 }
121
122 void BlenderSync::sync_data(BL::SpaceView3D b_v3d)
123 {
124         sync_integrator();
125         sync_film();
126         sync_render_layer(b_v3d);
127         sync_shaders();
128         sync_objects(b_v3d);
129 }
130
131 /* Integrator */
132
133 void BlenderSync::sync_integrator()
134 {
135         PointerRNA cscene = RNA_pointer_get(&b_scene.ptr, "cycles");
136
137         Integrator *integrator = scene->integrator;
138         Integrator previntegrator = *integrator;
139
140         integrator->min_bounce = get_int(cscene, "min_bounces");
141         integrator->max_bounce = get_int(cscene, "max_bounces");
142
143         integrator->max_diffuse_bounce = get_int(cscene, "diffuse_bounces");
144         integrator->max_glossy_bounce = get_int(cscene, "glossy_bounces");
145         integrator->max_transmission_bounce = get_int(cscene, "transmission_bounces");
146
147         integrator->transparent_max_bounce = get_int(cscene, "transparent_max_bounces");
148         integrator->transparent_min_bounce = get_int(cscene, "transparent_min_bounces");
149         integrator->transparent_shadows = get_boolean(cscene, "use_transparent_shadows");
150
151         integrator->no_caustics = get_boolean(cscene, "no_caustics");
152         integrator->blur_caustics = get_float(cscene, "blur_caustics");
153
154         if(integrator->modified(previntegrator))
155                 integrator->tag_update(scene);
156 }
157
158 /* Film */
159
160 void BlenderSync::sync_film()
161 {
162         PointerRNA cscene = RNA_pointer_get(&b_scene.ptr, "cycles");
163
164         Film *film = scene->film;
165         Film prevfilm = *film;
166
167         film->exposure = get_float(cscene, "film_exposure");
168
169         if(film->modified(prevfilm))
170                 film->tag_update(scene);
171
172         Filter *filter = scene->filter;
173         Filter prevfilter = *filter;
174
175         filter->filter_type = (FilterType)RNA_enum_get(&cscene, "filter_type");
176         filter->filter_width = (filter->filter_type == FILTER_BOX)? 1.0f: get_float(cscene, "filter_width");
177
178         if(filter->modified(prevfilter))
179                 filter->tag_update(scene);
180 }
181
182 /* Render Layer */
183
184 void BlenderSync::sync_render_layer(BL::SpaceView3D b_v3d)
185 {
186         if(b_v3d) {
187                 render_layer.scene_layer = get_layer(b_v3d.layers());
188                 render_layer.layer = render_layer.scene_layer;
189                 render_layer.material_override = PointerRNA_NULL;
190         }
191         else {
192                 BL::RenderSettings r = b_scene.render();
193                 BL::RenderSettings::layers_iterator b_rlay;
194                 bool first = true;
195
196                 for(r.layers.begin(b_rlay); b_rlay != r.layers.end(); ++b_rlay) {
197                         /* single layer for now */
198                         if(first) {
199                                 render_layer.scene_layer = get_layer(b_scene.layers());
200                                 render_layer.layer = get_layer(b_rlay->layers());
201                                 render_layer.material_override = b_rlay->material_override();
202
203                                 first = false;
204                         }
205                 }
206         }
207 }
208
209 /* Scene Parameters */
210
211 SceneParams BlenderSync::get_scene_params(BL::Scene b_scene)
212 {
213         SceneParams params;
214         PointerRNA cscene = RNA_pointer_get(&b_scene.ptr, "cycles");
215         int shadingsystem = RNA_enum_get(&cscene, "shading_system");
216
217         if(shadingsystem == 0)
218                 params.shadingsystem = SceneParams::SVM;
219         else if(shadingsystem == 1)
220                 params.shadingsystem = SceneParams::OSL;
221         
222         params.bvh_type = (SceneParams::BVHType)RNA_enum_get(&cscene, "debug_bvh_type");
223         params.use_bvh_spatial_split = RNA_boolean_get(&cscene, "debug_use_spatial_splits");
224
225         return params;
226 }
227
228 /* Session Parameters */
229
230 bool BlenderSync::get_session_pause(BL::Scene b_scene, bool background)
231 {
232         PointerRNA cscene = RNA_pointer_get(&b_scene.ptr, "cycles");
233         return (background)? false: get_boolean(cscene, "preview_pause");
234 }
235
236 static bool device_type_available(vector<DeviceType>& types, DeviceType dtype)
237 {
238         foreach(DeviceType dt, types)
239                 if(dt == dtype)
240                         return true;
241
242         return false;
243 }
244
245 SessionParams BlenderSync::get_session_params(BL::Scene b_scene, bool background)
246 {
247         SessionParams params;
248         PointerRNA cscene = RNA_pointer_get(&b_scene.ptr, "cycles");
249
250         /* device type */
251         params.device_type = DEVICE_CPU;
252
253         if(RNA_enum_get(&cscene, "device") != 0) {
254                 vector<DeviceType> types = Device::available_types();
255                 DeviceType dtype = (RNA_enum_get(&cscene, "gpu_type") == 0)? DEVICE_CUDA: DEVICE_OPENCL;
256
257                 if(device_type_available(types, dtype))
258                         params.device_type = dtype;
259                 else if(device_type_available(types, DEVICE_OPENCL))
260                         params.device_type = DEVICE_OPENCL;
261                 else if(device_type_available(types, DEVICE_CUDA))
262                         params.device_type = DEVICE_CUDA;
263         }
264                         
265         /* Background */
266         params.background = background;
267                         
268         /* samples */
269         if(background) {
270                 params.samples = get_int(cscene, "samples");
271         }
272         else {
273                 params.samples = get_int(cscene, "preview_samples");
274                 if(params.samples == 0)
275                         params.samples = INT_MAX;
276         }
277
278         /* other parameters */
279         params.threads = b_scene.render().threads();
280         params.tile_size = get_int(cscene, "debug_tile_size");
281         params.min_size = get_int(cscene, "debug_min_size");
282         params.cancel_timeout = get_float(cscene, "debug_cancel_timeout");
283         params.reset_timeout = get_float(cscene, "debug_reset_timeout");
284         params.text_timeout = get_float(cscene, "debug_text_timeout");
285
286         if(background) {
287                 params.progressive = true;
288                 params.min_size = INT_MAX;
289         }
290         else
291                 params.progressive = true;
292
293         return params;
294 }
295
296 CCL_NAMESPACE_END
297