Cycles: Automatically detect HDRI resolution by default and use non-square sampling map
[blender.git] / intern / cycles / blender / addon / properties.py
1 #
2 # Copyright 2011-2013 Blender Foundation
3 #
4 # Licensed under the Apache License, Version 2.0 (the "License");
5 # you may not use this file except in compliance with the License.
6 # You may obtain a copy of the License at
7 #
8 # http://www.apache.org/licenses/LICENSE-2.0
9 #
10 # Unless required by applicable law or agreed to in writing, software
11 # distributed under the License is distributed on an "AS IS" BASIS,
12 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 # See the License for the specific language governing permissions and
14 # limitations under the License.
15 #
16
17 # <pep8 compliant>
18
19 import bpy
20 from bpy.props import (BoolProperty,
21                        EnumProperty,
22                        FloatProperty,
23                        IntProperty,
24                        PointerProperty,
25                        StringProperty)
26
27 # enums
28
29 import _cycles
30
31 enum_devices = (
32     ('CPU', "CPU", "Use CPU for rendering"),
33     ('GPU', "GPU Compute", "Use GPU compute device for rendering, configured in the system tab in the user preferences"),
34     )
35
36 if _cycles.with_network:
37     enum_devices += (('NETWORK', "Networked Device", "Use networked device for rendering"),)
38
39 enum_feature_set = (
40     ('SUPPORTED', "Supported", "Only use finished and supported features"),
41     ('EXPERIMENTAL', "Experimental", "Use experimental and incomplete features that might be broken or change in the future", 'ERROR', 1),
42     )
43
44 enum_displacement_methods = (
45     ('BUMP', "Bump Only", "Bump mapping to simulate the appearance of displacement"),
46     ('DISPLACEMENT', "Displacement Only", "Use true displacement of surface only, requires fine subdivision"),
47     ('BOTH', "Displacement and Bump", "Combination of true displacement and bump mapping for finer detail"),
48     )
49
50 enum_bvh_layouts = (
51     ('BVH2', "BVH2", "", 1),
52     ('BVH4', "BVH4", "", 2),
53     )
54
55 enum_bvh_types = (
56     ('DYNAMIC_BVH', "Dynamic BVH", "Objects can be individually updated, at the cost of slower render time"),
57     ('STATIC_BVH', "Static BVH", "Any object modification requires a complete BVH rebuild, but renders faster"),
58     )
59
60 enum_filter_types = (
61     ('BOX', "Box", "Box filter"),
62     ('GAUSSIAN', "Gaussian", "Gaussian filter"),
63     ('BLACKMAN_HARRIS', "Blackman-Harris", "Blackman-Harris filter"),
64     )
65
66 enum_aperture_types = (
67     ('RADIUS', "Radius", "Directly change the size of the aperture"),
68     ('FSTOP', "F-stop", "Change the size of the aperture by f-stop"),
69     )
70
71 enum_panorama_types = (
72     ('EQUIRECTANGULAR', "Equirectangular", "Render the scene with a spherical camera, also known as Lat Long panorama"),
73     ('FISHEYE_EQUIDISTANT', "Fisheye Equidistant", "Ideal for fulldomes, ignore the sensor dimensions"),
74     ('FISHEYE_EQUISOLID', "Fisheye Equisolid",
75                           "Similar to most fisheye modern lens, takes sensor dimensions into consideration"),
76     ('MIRRORBALL', "Mirror Ball", "Uses the mirror ball mapping"),
77     )
78
79 enum_curve_primitives = (
80     ('TRIANGLES', "Triangles", "Create triangle geometry around strands"),
81     ('LINE_SEGMENTS', "Line Segments", "Use line segment primitives"),
82     ('CURVE_SEGMENTS', "Curve Segments", "Use segmented cardinal curve primitives"),
83     )
84
85 enum_triangle_curves = (
86     ('CAMERA_TRIANGLES', "Planes", "Create individual triangles forming planes that face camera"),
87     ('TESSELLATED_TRIANGLES', "Tessellated", "Create mesh surrounding each strand"),
88     )
89
90 enum_curve_shape = (
91     ('RIBBONS', "Ribbons", "Ignore thickness of each strand"),
92     ('THICK', "Thick", "Use thickness of strand when rendering"),
93     )
94
95 enum_tile_order = (
96     ('CENTER', "Center", "Render from center to the edges"),
97     ('RIGHT_TO_LEFT', "Right to Left", "Render from right to left"),
98     ('LEFT_TO_RIGHT', "Left to Right", "Render from left to right"),
99     ('TOP_TO_BOTTOM', "Top to Bottom", "Render from top to bottom"),
100     ('BOTTOM_TO_TOP', "Bottom to Top", "Render from bottom to top"),
101     ('HILBERT_SPIRAL', "Hilbert Spiral", "Render in a Hilbert Spiral"),
102     )
103
104 enum_use_layer_samples = (
105     ('USE', "Use", "Per render layer number of samples override scene samples"),
106     ('BOUNDED', "Bounded", "Bound per render layer number of samples by global samples"),
107     ('IGNORE', "Ignore", "Ignore per render layer number of samples"),
108     )
109
110 enum_sampling_pattern = (
111     ('SOBOL', "Sobol", "Use Sobol random sampling pattern"),
112     ('CORRELATED_MUTI_JITTER', "Correlated Multi-Jitter", "Use Correlated Multi-Jitter random sampling pattern"),
113     )
114
115 enum_integrator = (
116     ('BRANCHED_PATH', "Branched Path Tracing", "Path tracing integrator that branches on the first bounce, giving more control over the number of light and material samples"),
117     ('PATH', "Path Tracing", "Pure path tracing integrator"),
118     )
119
120 enum_volume_sampling = (
121     ('DISTANCE', "Distance", "Use distance sampling, best for dense volumes with lights far away"),
122     ('EQUIANGULAR', "Equiangular", "Use equiangular sampling, best for volumes with low density with light inside or near the volume"),
123     ('MULTIPLE_IMPORTANCE', "Multiple Importance", "Combine distance and equi-angular sampling for volumes where neither method is ideal"),
124     )
125
126 enum_volume_interpolation = (
127     ('LINEAR', "Linear", "Good smoothness and speed"),
128     ('CUBIC', "Cubic", "Smoothed high quality interpolation, but slower")
129     )
130
131 enum_world_mis = (
132     ('NONE', "None", "Don't sample the background, faster but might cause noise for non-solid backgrounds"),
133     ('AUTOMATIC', "Auto", "Automatically try to determine the best setting"),
134     ('MANUAL', "Manual", "Manually set the resolution of the sampling map, higher values are slower and require more memory but reduce noise")
135     )
136
137 enum_device_type = (
138     ('CPU', "CPU", "CPU", 0),
139     ('CUDA', "CUDA", "CUDA", 1),
140     ('OPENCL', "OpenCL", "OpenCL", 2)
141     )
142
143 enum_texture_limit = (
144     ('OFF', "No Limit", "No texture size limit", 0),
145     ('128', "128", "Limit texture size to 128 pixels", 1),
146     ('256', "256", "Limit texture size to 256 pixels", 2),
147     ('512', "512", "Limit texture size to 512 pixels", 3),
148     ('1024', "1024", "Limit texture size to 1024 pixels", 4),
149     ('2048', "2048", "Limit texture size to 2048 pixels", 5),
150     ('4096', "4096", "Limit texture size to 4096 pixels", 6),
151     ('8192', "8192", "Limit texture size to 8192 pixels", 7),
152     )
153
154 class CyclesRenderSettings(bpy.types.PropertyGroup):
155     @classmethod
156     def register(cls):
157         bpy.types.Scene.cycles = PointerProperty(
158                 name="Cycles Render Settings",
159                 description="Cycles render settings",
160                 type=cls,
161                 )
162         cls.device = EnumProperty(
163                 name="Device",
164                 description="Device to use for rendering",
165                 items=enum_devices,
166                 default='CPU',
167                 )
168         cls.feature_set = EnumProperty(
169                 name="Feature Set",
170                 description="Feature set to use for rendering",
171                 items=enum_feature_set,
172                 default='SUPPORTED',
173                 )
174         cls.shading_system = BoolProperty(
175                 name="Open Shading Language",
176                 description="Use Open Shading Language (CPU rendering only)",
177                 )
178
179         cls.progressive = EnumProperty(
180                 name="Integrator",
181                 description="Method to sample lights and materials",
182                 items=enum_integrator,
183                 default='PATH',
184                 )
185
186         cls.use_square_samples = BoolProperty(
187                 name="Square Samples",
188                 description="Square sampling values for easier artist control",
189                 default=False,
190                 )
191
192         cls.samples = IntProperty(
193                 name="Samples",
194                 description="Number of samples to render for each pixel",
195                 min=1, max=2147483647,
196                 default=128,
197                 )
198         cls.preview_samples = IntProperty(
199                 name="Preview Samples",
200                 description="Number of samples to render in the viewport, unlimited if 0",
201                 min=0, max=2147483647,
202                 default=32,
203                 )
204         cls.preview_pause = BoolProperty(
205                 name="Pause Preview",
206                 description="Pause all viewport preview renders",
207                 default=False,
208                 )
209         cls.preview_active_layer = BoolProperty(
210                 name="Preview Active Layer",
211                 description="Preview active render layer in viewport",
212                 default=False,
213                 )
214
215         cls.aa_samples = IntProperty(
216                 name="AA Samples",
217                 description="Number of antialiasing samples to render for each pixel",
218                 min=1, max=2097151,
219                 default=128,
220                 )
221         cls.preview_aa_samples = IntProperty(
222                 name="AA Samples",
223                 description="Number of antialiasing samples to render in the viewport, unlimited if 0",
224                 min=0, max=2097151,
225                 default=32,
226                 )
227         cls.diffuse_samples = IntProperty(
228                 name="Diffuse Samples",
229                 description="Number of diffuse bounce samples to render for each AA sample",
230                 min=1, max=1024,
231                 default=1,
232                 )
233         cls.glossy_samples = IntProperty(
234                 name="Glossy Samples",
235                 description="Number of glossy bounce samples to render for each AA sample",
236                 min=1, max=1024,
237                 default=1,
238                 )
239         cls.transmission_samples = IntProperty(
240                 name="Transmission Samples",
241                 description="Number of transmission bounce samples to render for each AA sample",
242                 min=1, max=1024,
243                 default=1,
244                 )
245         cls.ao_samples = IntProperty(
246                 name="Ambient Occlusion Samples",
247                 description="Number of ambient occlusion samples to render for each AA sample",
248                 min=1, max=1024,
249                 default=1,
250                 )
251         cls.mesh_light_samples = IntProperty(
252                 name="Mesh Light Samples",
253                 description="Number of mesh emission light samples to render for each AA sample",
254                 min=1, max=1024,
255                 default=1,
256                 )
257
258         cls.subsurface_samples = IntProperty(
259                 name="Subsurface Samples",
260                 description="Number of subsurface scattering samples to render for each AA sample",
261                 min=1, max=1024,
262                 default=1,
263                 )
264
265         cls.volume_samples = IntProperty(
266                 name="Volume Samples",
267                 description="Number of volume scattering samples to render for each AA sample",
268                 min=1, max=1024,
269                 default=1,
270                 )
271
272         cls.sampling_pattern = EnumProperty(
273                 name="Sampling Pattern",
274                 description="Random sampling pattern used by the integrator",
275                 items=enum_sampling_pattern,
276                 default='SOBOL',
277                 )
278
279         cls.use_layer_samples = EnumProperty(
280                 name="Layer Samples",
281                 description="How to use per render layer sample settings",
282                 items=enum_use_layer_samples,
283                 default='USE',
284                 )
285
286         cls.sample_all_lights_direct = BoolProperty(
287                 name="Sample All Direct Lights",
288                 description="Sample all lights (for direct samples), rather than randomly picking one",
289                 default=True,
290                 )
291
292         cls.sample_all_lights_indirect = BoolProperty(
293                 name="Sample All Indirect Lights",
294                 description="Sample all lights (for indirect samples), rather than randomly picking one",
295                 default=True,
296                 )
297         cls.light_sampling_threshold = FloatProperty(
298                 name="Light Sampling Threshold",
299                 description="Probabilistically terminate light samples when the light contribution is below this threshold (more noise but faster rendering). "
300                             "Zero disables the test and never ignores lights",
301                 min=0.0, max=1.0,
302                 default=0.01,
303                 )
304
305         cls.caustics_reflective = BoolProperty(
306                 name="Reflective Caustics",
307                 description="Use reflective caustics, resulting in a brighter image (more noise but added realism)",
308                 default=True,
309                 )
310
311         cls.caustics_refractive = BoolProperty(
312                 name="Refractive Caustics",
313                 description="Use refractive caustics, resulting in a brighter image (more noise but added realism)",
314                 default=True,
315                 )
316
317         cls.blur_glossy = FloatProperty(
318                 name="Filter Glossy",
319                 description="Adaptively blur glossy shaders after blurry bounces, "
320                             "to reduce noise at the cost of accuracy",
321                 min=0.0, max=10.0,
322                 default=1.0,
323                 )
324
325         cls.max_bounces = IntProperty(
326                 name="Max Bounces",
327                 description="Total maximum number of bounces",
328                 min=0, max=1024,
329                 default=12,
330                 )
331
332         cls.diffuse_bounces = IntProperty(
333                 name="Diffuse Bounces",
334                 description="Maximum number of diffuse reflection bounces, bounded by total maximum",
335                 min=0, max=1024,
336                 default=4,
337                 )
338         cls.glossy_bounces = IntProperty(
339                 name="Glossy Bounces",
340                 description="Maximum number of glossy reflection bounces, bounded by total maximum",
341                 min=0, max=1024,
342                 default=4,
343                 )
344         cls.transmission_bounces = IntProperty(
345                 name="Transmission Bounces",
346                 description="Maximum number of transmission bounces, bounded by total maximum",
347                 min=0, max=1024,
348                 default=12,
349                 )
350         cls.volume_bounces = IntProperty(
351                 name="Volume Bounces",
352                 description="Maximum number of volumetric scattering events",
353                 min=0, max=1024,
354                 default=0,
355                 )
356
357         cls.transparent_max_bounces = IntProperty(
358                 name="Transparent Max Bounces",
359                 description="Maximum number of transparent bounces",
360                 min=0, max=1024,
361                 default=8,
362                 )
363
364         cls.volume_step_size = FloatProperty(
365                 name="Step Size",
366                 description="Distance between volume shader samples when rendering the volume "
367                             "(lower values give more accurate and detailed results, but also increased render time)",
368                 default=0.1,
369                 min=0.0000001, max=100000.0, soft_min=0.01, soft_max=1.0, precision=4
370                 )
371
372         cls.volume_max_steps = IntProperty(
373                 name="Max Steps",
374                 description="Maximum number of steps through the volume before giving up, "
375                             "to avoid extremely long render times with big objects or small step sizes",
376                 default=1024,
377                 min=2, max=65536
378                 )
379
380         cls.dicing_rate = FloatProperty(
381                 name="Dicing Rate",
382                 description="Size of a micropolygon in pixels",
383                 min=0.1, max=1000.0, soft_min=0.5,
384                 default=1.0,
385                 subtype="PIXEL"
386                 )
387         cls.preview_dicing_rate = FloatProperty(
388                 name="Preview Dicing Rate",
389                 description="Size of a micropolygon in pixels during preview render",
390                 min=0.1, max=1000.0, soft_min=0.5,
391                 default=8.0,
392                 subtype="PIXEL"
393                 )
394
395         cls.max_subdivisions = IntProperty(
396                 name="Max Subdivisions",
397                 description="Stop subdividing when this level is reached even if the dice rate would produce finer tessellation",
398                 min=0, max=16,
399                 default=12,
400                 )
401
402         cls.dicing_camera = PointerProperty(
403                 name="Dicing Camera",
404                 description="Camera to use as reference point when subdividing geometry, useful to avoid crawling "
405                             "artifacts in animations when the scene camera is moving",
406                 type=bpy.types.Object,
407                 poll=lambda self, obj: obj.type == 'CAMERA',
408                 )
409         cls.offscreen_dicing_scale = FloatProperty(
410                 name="Offscreen Dicing Scale",
411                 description="Multiplier for dicing rate of geometry outside of the camera view. The dicing rate "
412                             "of objects is gradually increased the further they are outside the camera view. "
413                             "Lower values provide higher quality reflections and shadows for off screen objects, "
414                             "while higher values use less memory",
415                 min=1.0, soft_max=25.0,
416                 default=4.0,
417                 )
418
419         cls.film_exposure = FloatProperty(
420                 name="Exposure",
421                 description="Image brightness scale",
422                 min=0.0, max=10.0,
423                 default=1.0,
424                 )
425         cls.film_transparent = BoolProperty(
426                 name="Transparent",
427                 description="World background is transparent, for compositing the render over another background",
428                 default=False,
429                 )
430         cls.film_transparent_glass = BoolProperty(
431                 name="Transparent Glass",
432                 description="Render transmissive surfaces as transparent, for compositing glass over another background",
433                 default=False,
434                 )
435         cls.film_transparent_roughness = FloatProperty(
436                 name="Transparent Roughness Threshold",
437                 description="For transparent transmission, keep surfaces with roughness above the threshold opaque",
438                 min=0.0, max=1.0,
439                 default=0.1,
440                 )
441
442         # Really annoyingly, we have to keep it around for a few releases,
443         # otherwise forward compatibility breaks in really bad manner: CRASH!
444         #
445         # TODO(sergey): Remove this during 2.8x series of Blender.
446         cls.filter_type = EnumProperty(
447                 name="Filter Type",
448                 description="Pixel filter type",
449                 items=enum_filter_types,
450                 default='BLACKMAN_HARRIS',
451                 )
452
453         cls.pixel_filter_type = EnumProperty(
454                 name="Filter Type",
455                 description="Pixel filter type",
456                 items=enum_filter_types,
457                 default='BLACKMAN_HARRIS',
458                 )
459
460         cls.filter_width = FloatProperty(
461                 name="Filter Width",
462                 description="Pixel filter width",
463                 min=0.01, max=10.0,
464                 default=1.5,
465                 )
466
467         cls.seed = IntProperty(
468                 name="Seed",
469                 description="Seed value for integrator to get different noise patterns",
470                 min=0, max=2147483647,
471                 default=0,
472                 )
473
474         cls.use_animated_seed = BoolProperty(
475                 name="Use Animated Seed",
476                 description="Use different seed values (and hence noise patterns) at different frames",
477                 default=False,
478                 )
479
480         cls.sample_clamp_direct = FloatProperty(
481                 name="Clamp Direct",
482                 description="If non-zero, the maximum value for a direct sample, "
483                             "higher values will be scaled down to avoid too "
484                             "much noise and slow convergence at the cost of accuracy",
485                 min=0.0, max=1e8,
486                 default=0.0,
487                 )
488
489         cls.sample_clamp_indirect = FloatProperty(
490                 name="Clamp Indirect",
491                 description="If non-zero, the maximum value for an indirect sample, "
492                             "higher values will be scaled down to avoid too "
493                             "much noise and slow convergence at the cost of accuracy",
494                 min=0.0, max=1e8,
495                 default=10.0,
496                 )
497
498         cls.debug_tile_size = IntProperty(
499                 name="Tile Size",
500                 description="",
501                 min=1, max=4096,
502                 default=1024,
503                 )
504
505         cls.preview_start_resolution = IntProperty(
506                 name="Start Resolution",
507                 description="Resolution to start rendering preview at, "
508                             "progressively increasing it to the full viewport size",
509                 min=8, max=16384,
510                 default=64,
511                 )
512
513         cls.debug_reset_timeout = FloatProperty(
514                 name="Reset timeout",
515                 description="",
516                 min=0.01, max=10.0,
517                 default=0.1,
518                 )
519         cls.debug_cancel_timeout = FloatProperty(
520                 name="Cancel timeout",
521                 description="",
522                 min=0.01, max=10.0,
523                 default=0.1,
524                 )
525         cls.debug_text_timeout = FloatProperty(
526                 name="Text timeout",
527                 description="",
528                 min=0.01, max=10.0,
529                 default=1.0,
530                 )
531
532         cls.debug_bvh_type = EnumProperty(
533                 name="Viewport BVH Type",
534                 description="Choose between faster updates, or faster render",
535                 items=enum_bvh_types,
536                 default='DYNAMIC_BVH',
537                 )
538         cls.debug_use_spatial_splits = BoolProperty(
539                 name="Use Spatial Splits",
540                 description="Use BVH spatial splits: longer builder time, faster render",
541                 default=False,
542                 )
543         cls.debug_use_hair_bvh = BoolProperty(
544                 name="Use Hair BVH",
545                 description="Use special type BVH optimized for hair (uses more ram but renders faster)",
546                 default=True,
547                 )
548         cls.debug_bvh_time_steps = IntProperty(
549                 name="BVH Time Steps",
550                 description="Split BVH primitives by this number of time steps to speed up render time in cost of memory",
551                 default=0,
552                 min=0, max=16,
553                 )
554         cls.tile_order = EnumProperty(
555                 name="Tile Order",
556                 description="Tile order for rendering",
557                 items=enum_tile_order,
558                 default='HILBERT_SPIRAL',
559                 options=set(),  # Not animatable!
560                 )
561         cls.use_progressive_refine = BoolProperty(
562                 name="Progressive Refine",
563                 description="Instead of rendering each tile until it is finished, "
564                             "refine the whole image progressively "
565                             "(this renders somewhat slower, "
566                             "but time can be saved by manually stopping the render when the noise is low enough)",
567                 default=False,
568                 )
569
570         cls.bake_type = EnumProperty(
571             name="Bake Type",
572             default='COMBINED',
573             description="Type of pass to bake",
574             items=(
575                 ('COMBINED', "Combined", ""),
576                 ('AO', "Ambient Occlusion", ""),
577                 ('SHADOW', "Shadow", ""),
578                 ('NORMAL', "Normal", ""),
579                 ('UV', "UV", ""),
580                 ('ROUGHNESS', "Roughness", ""),
581                 ('EMIT', "Emit", ""),
582                 ('ENVIRONMENT', "Environment", ""),
583                 ('DIFFUSE', "Diffuse", ""),
584                 ('GLOSSY', "Glossy", ""),
585                 ('TRANSMISSION', "Transmission", ""),
586                 ('SUBSURFACE', "Subsurface", ""),
587                 ),
588             )
589
590         cls.use_camera_cull = BoolProperty(
591                 name="Use Camera Cull",
592                 description="Allow objects to be culled based on the camera frustum",
593                 default=False,
594                 )
595
596         cls.camera_cull_margin = FloatProperty(
597                 name="Camera Cull Margin",
598                 description="Margin for the camera space culling",
599                 default=0.1,
600                 min=0.0, max=5.0
601                 )
602
603         cls.use_distance_cull = BoolProperty(
604                 name="Use Distance Cull",
605                 description="Allow objects to be culled based on the distance from camera",
606                 default=False,
607                 )
608
609         cls.distance_cull_margin = FloatProperty(
610                 name="Cull Distance",
611                 description="Cull objects which are further away from camera than this distance",
612                 default=50,
613                 min=0.0
614                 )
615
616         cls.motion_blur_position = EnumProperty(
617             name="Motion Blur Position",
618             default='CENTER',
619             description="Offset for the shutter's time interval, allows to change the motion blur trails",
620             items=(
621                 ('START', "Start on Frame", "The shutter opens at the current frame"),
622                 ('CENTER', "Center on Frame", "The shutter is open during the current frame"),
623                 ('END', "End on Frame", "The shutter closes at the current frame"),
624                 ),
625             )
626
627         cls.rolling_shutter_type = EnumProperty(
628             name="Shutter Type",
629             default='NONE',
630             description="Type of rolling shutter effect matching CMOS-based cameras",
631             items=(
632                 ('NONE', "None", "No rolling shutter effect used"),
633                 ('TOP', "Top-Bottom", "Sensor is being scanned from top to bottom")
634                 # TODO(seergey): Are there real cameras with different scanning direction?
635                 ),
636             )
637
638         cls.rolling_shutter_duration = FloatProperty(
639             name="Rolling Shutter Duration",
640             description="Scanline \"exposure\" time for the rolling shutter effect",
641             default=0.1,
642             min=0.0, max=1.0,
643             )
644
645         cls.texture_limit = EnumProperty(
646             name="Viewport Texture Limit",
647             default='OFF',
648             description="Limit texture size used by viewport rendering",
649             items=enum_texture_limit
650             )
651
652         cls.texture_limit_render = EnumProperty(
653             name="Render Texture Limit",
654             default='OFF',
655             description="Limit texture size used by final rendering",
656             items=enum_texture_limit
657             )
658
659         cls.ao_bounces = IntProperty(
660             name="AO Bounces",
661             default=0,
662             description="Approximate indirect light with background tinted ambient occlusion at the specified bounce, 0 disables this feature",
663             min=0, max=1024,
664             )
665
666         cls.ao_bounces_render = IntProperty(
667             name="AO Bounces Render",
668             default=0,
669             description="Approximate indirect light with background tinted ambient occlusion at the specified bounce, 0 disables this feature",
670             min=0, max=1024,
671             )
672
673         # Various fine-tuning debug flags
674
675         def devices_update_callback(self, context):
676             import _cycles
677             scene = context.scene.as_pointer()
678             return _cycles.debug_flags_update(scene)
679
680         cls.debug_use_cpu_avx2 = BoolProperty(name="AVX2", default=True)
681         cls.debug_use_cpu_avx = BoolProperty(name="AVX", default=True)
682         cls.debug_use_cpu_sse41 = BoolProperty(name="SSE41", default=True)
683         cls.debug_use_cpu_sse3 = BoolProperty(name="SSE3", default=True)
684         cls.debug_use_cpu_sse2 = BoolProperty(name="SSE2", default=True)
685         cls.debug_bvh_layout = EnumProperty(
686                 name="BVH Layout",
687                 items=enum_bvh_layouts,
688                 default='BVH4',
689                 )
690         cls.debug_use_cpu_split_kernel = BoolProperty(name="Split Kernel", default=False)
691
692         cls.debug_use_cuda_adaptive_compile = BoolProperty(name="Adaptive Compile", default=False)
693         cls.debug_use_cuda_split_kernel = BoolProperty(name="Split Kernel", default=False)
694
695         cls.debug_opencl_kernel_type = EnumProperty(
696             name="OpenCL Kernel Type",
697             default='DEFAULT',
698             items=(
699                 ('DEFAULT', "Default", ""),
700                 ('MEGA', "Mega", ""),
701                 ('SPLIT', "Split", ""),
702                 ),
703             update=devices_update_callback
704             )
705
706         cls.debug_opencl_device_type = EnumProperty(
707             name="OpenCL Device Type",
708             default='ALL',
709             items=(
710                 ('NONE', "None", ""),
711                 ('ALL', "All", ""),
712                 ('DEFAULT', "Default", ""),
713                 ('CPU', "CPU", ""),
714                 ('GPU', "GPU", ""),
715                 ('ACCELERATOR', "Accelerator", ""),
716                 ),
717             update=devices_update_callback
718             )
719
720         cls.debug_opencl_kernel_single_program = BoolProperty(
721             name="Single Program",
722             default=True,
723             update=devices_update_callback,
724             )
725
726         cls.debug_use_opencl_debug = BoolProperty(name="Debug OpenCL", default=False)
727
728         cls.debug_opencl_mem_limit = IntProperty(name="Memory limit", default=0,
729             description="Artificial limit on OpenCL memory usage in MB (0 to disable limit)")
730
731     @classmethod
732     def unregister(cls):
733         del bpy.types.Scene.cycles
734
735
736 class CyclesCameraSettings(bpy.types.PropertyGroup):
737     @classmethod
738     def register(cls):
739         import math
740
741         bpy.types.Camera.cycles = PointerProperty(
742                 name="Cycles Camera Settings",
743                 description="Cycles camera settings",
744                 type=cls,
745                 )
746
747         cls.aperture_type = EnumProperty(
748                 name="Aperture Type",
749                 description="Use f-stop number or aperture radius",
750                 items=enum_aperture_types,
751                 default='RADIUS',
752                 )
753         cls.aperture_fstop = FloatProperty(
754                 name="Aperture f-stop",
755                 description="F-stop ratio (lower numbers give more defocus, higher numbers give a sharper image)",
756                 min=0.0, soft_min=0.1, soft_max=64.0,
757                 default=5.6,
758                 step=10,
759                 precision=1,
760                 )
761         cls.aperture_size = FloatProperty(
762                 name="Aperture Size",
763                 description="Radius of the aperture for depth of field (higher values give more defocus)",
764                 min=0.0, soft_max=10.0,
765                 default=0.0,
766                 step=1,
767                 precision=4,
768                 subtype='DISTANCE',
769                 )
770         cls.aperture_blades = IntProperty(
771                 name="Aperture Blades",
772                 description="Number of blades in aperture for polygonal bokeh (at least 3)",
773                 min=0, max=100,
774                 default=0,
775                 )
776         cls.aperture_rotation = FloatProperty(
777                 name="Aperture Rotation",
778                 description="Rotation of blades in aperture",
779                 soft_min=-math.pi, soft_max=math.pi,
780                 subtype='ANGLE',
781                 default=0,
782                 )
783         cls.aperture_ratio = FloatProperty(
784                 name="Aperture Ratio",
785                 description="Distortion to simulate anamorphic lens bokeh",
786                 min=0.01, soft_min=1.0, soft_max=2.0,
787                 default=1.0,
788                 precision=4,
789                 )
790         cls.panorama_type = EnumProperty(
791                 name="Panorama Type",
792                 description="Distortion to use for the calculation",
793                 items=enum_panorama_types,
794                 default='FISHEYE_EQUISOLID',
795                 )
796         cls.fisheye_fov = FloatProperty(
797                 name="Field of View",
798                 description="Field of view for the fisheye lens",
799                 min=0.1745, soft_max=2.0 * math.pi, max=10.0 * math.pi,
800                 subtype='ANGLE',
801                 default=math.pi,
802                 )
803         cls.fisheye_lens = FloatProperty(
804                 name="Fisheye Lens",
805                 description="Lens focal length (mm)",
806                 min=0.01, soft_max=15.0, max=100.0,
807                 default=10.5,
808                 )
809         cls.latitude_min = FloatProperty(
810                 name="Min Latitude",
811                 description="Minimum latitude (vertical angle) for the equirectangular lens",
812                 min=-0.5 * math.pi, max=0.5 * math.pi,
813                 subtype='ANGLE',
814                 default=-0.5 * math.pi,
815                 )
816         cls.latitude_max = FloatProperty(
817                 name="Max Latitude",
818                 description="Maximum latitude (vertical angle) for the equirectangular lens",
819                 min=-0.5 * math.pi, max=0.5 * math.pi,
820                 subtype='ANGLE',
821                 default=0.5 * math.pi,
822                 )
823         cls.longitude_min = FloatProperty(
824                 name="Min Longitude",
825                 description="Minimum longitude (horizontal angle) for the equirectangular lens",
826                 min=-math.pi, max=math.pi,
827                 subtype='ANGLE',
828                 default=-math.pi,
829                 )
830         cls.longitude_max = FloatProperty(
831                 name="Max Longitude",
832                 description="Maximum longitude (horizontal angle) for the equirectangular lens",
833                 min=-math.pi, max=math.pi,
834                 subtype='ANGLE',
835                 default=math.pi,
836                 )
837
838     @classmethod
839     def unregister(cls):
840         del bpy.types.Camera.cycles
841
842
843 class CyclesMaterialSettings(bpy.types.PropertyGroup):
844     @classmethod
845     def register(cls):
846         bpy.types.Material.cycles = PointerProperty(
847                 name="Cycles Material Settings",
848                 description="Cycles material settings",
849                 type=cls,
850                 )
851         cls.sample_as_light = BoolProperty(
852                 name="Multiple Importance Sample",
853                 description="Use multiple importance sampling for this material, "
854                             "disabling may reduce overall noise for large "
855                             "objects that emit little light compared to other light sources",
856                 default=True,
857                 )
858         cls.use_transparent_shadow = BoolProperty(
859                 name="Transparent Shadows",
860                 description="Use transparent shadows for this material if it contains a Transparent BSDF, "
861                             "disabling will render faster but not give accurate shadows",
862                 default=True,
863                 )
864         cls.homogeneous_volume = BoolProperty(
865                 name="Homogeneous Volume",
866                 description="When using volume rendering, assume volume has the same density everywhere "
867                             "(not using any textures), for faster rendering",
868                 default=False,
869                 )
870         cls.volume_sampling = EnumProperty(
871                 name="Volume Sampling",
872                 description="Sampling method to use for volumes",
873                 items=enum_volume_sampling,
874                 default='MULTIPLE_IMPORTANCE',
875                 )
876
877         cls.volume_interpolation = EnumProperty(
878                 name="Volume Interpolation",
879                 description="Interpolation method to use for smoke/fire volumes",
880                 items=enum_volume_interpolation,
881                 default='LINEAR',
882                 )
883
884         cls.displacement_method = EnumProperty(
885                 name="Displacement Method",
886                 description="Method to use for the displacement",
887                 items=enum_displacement_methods,
888                 default='DISPLACEMENT',
889                 )
890
891     @classmethod
892     def unregister(cls):
893         del bpy.types.Material.cycles
894
895
896 class CyclesLampSettings(bpy.types.PropertyGroup):
897     @classmethod
898     def register(cls):
899         bpy.types.Lamp.cycles = PointerProperty(
900                 name="Cycles Lamp Settings",
901                 description="Cycles lamp settings",
902                 type=cls,
903                 )
904         cls.cast_shadow = BoolProperty(
905                 name="Cast Shadow",
906                 description="Lamp casts shadows",
907                 default=True,
908                 )
909         cls.samples = IntProperty(
910                 name="Samples",
911                 description="Number of light samples to render for each AA sample",
912                 min=1, max=10000,
913                 default=1,
914                 )
915         cls.max_bounces = IntProperty(
916                 name="Max Bounces",
917                 description="Maximum number of bounces the light will contribute to the render",
918                 min=0, max=1024,
919                 default=1024,
920                 )
921         cls.use_multiple_importance_sampling = BoolProperty(
922                 name="Multiple Importance Sample",
923                 description="Use multiple importance sampling for the lamp, "
924                             "reduces noise for area lamps and sharp glossy materials",
925                 default=True,
926                 )
927         cls.is_portal = BoolProperty(
928                 name="Is Portal",
929                 description="Use this area lamp to guide sampling of the background, "
930                             "note that this will make the lamp invisible",
931                 default=False,
932                 )
933
934     @classmethod
935     def unregister(cls):
936         del bpy.types.Lamp.cycles
937
938
939 class CyclesWorldSettings(bpy.types.PropertyGroup):
940     @classmethod
941     def register(cls):
942         bpy.types.World.cycles = PointerProperty(
943                 name="Cycles World Settings",
944                 description="Cycles world settings",
945                 type=cls,
946                 )
947         cls.sampling_method = EnumProperty(
948                 name="Sampling method",
949                 description="How to sample the background light",
950                 items=enum_world_mis,
951                 default='AUTOMATIC',
952                 )
953         cls.sample_map_resolution = IntProperty(
954                 name="Map Resolution",
955                 description="Importance map size is resolution x resolution/2; "
956                             "higher values potentially produce less noise, at the cost of memory and speed",
957                 min=4, max=8192,
958                 default=1024,
959                 )
960         cls.samples = IntProperty(
961                 name="Samples",
962                 description="Number of light samples to render for each AA sample",
963                 min=1, max=10000,
964                 default=1,
965                 )
966         cls.max_bounces = IntProperty(
967                 name="Max Bounces",
968                 description="Maximum number of bounces the background light will contribute to the render",
969                 min=0, max=1024,
970                 default=1024,
971                 )
972         cls.homogeneous_volume = BoolProperty(
973                 name="Homogeneous Volume",
974                 description="When using volume rendering, assume volume has the same density everywhere"
975                             "(not using any textures), for faster rendering",
976                 default=False,
977                 )
978         cls.volume_sampling = EnumProperty(
979                 name="Volume Sampling",
980                 description="Sampling method to use for volumes",
981                 items=enum_volume_sampling,
982                 default='EQUIANGULAR',
983                 )
984
985         cls.volume_interpolation = EnumProperty(
986                 name="Volume Interpolation",
987                 description="Interpolation method to use for volumes",
988                 items=enum_volume_interpolation,
989                 default='LINEAR',
990                 )
991
992     @classmethod
993     def unregister(cls):
994         del bpy.types.World.cycles
995
996
997 class CyclesVisibilitySettings(bpy.types.PropertyGroup):
998     @classmethod
999     def register(cls):
1000         bpy.types.Object.cycles_visibility = PointerProperty(
1001                 name="Cycles Visibility Settings",
1002                 description="Cycles visibility settings",
1003                 type=cls,
1004                 )
1005
1006         bpy.types.World.cycles_visibility = PointerProperty(
1007                 name="Cycles Visibility Settings",
1008                 description="Cycles visibility settings",
1009                 type=cls,
1010                 )
1011
1012         cls.camera = BoolProperty(
1013                 name="Camera",
1014                 description="Object visibility for camera rays",
1015                 default=True,
1016                 )
1017         cls.diffuse = BoolProperty(
1018                 name="Diffuse",
1019                 description="Object visibility for diffuse reflection rays",
1020                 default=True,
1021                 )
1022         cls.glossy = BoolProperty(
1023                 name="Glossy",
1024                 description="Object visibility for glossy reflection rays",
1025                 default=True,
1026                 )
1027         cls.transmission = BoolProperty(
1028                 name="Transmission",
1029                 description="Object visibility for transmission rays",
1030                 default=True,
1031                 )
1032         cls.shadow = BoolProperty(
1033                 name="Shadow",
1034                 description="Object visibility for shadow rays",
1035                 default=True,
1036                 )
1037         cls.scatter = BoolProperty(
1038                 name="Volume Scatter",
1039                 description="Object visibility for volume scatter rays",
1040                 default=True,
1041                 )
1042
1043     @classmethod
1044     def unregister(cls):
1045         del bpy.types.Object.cycles_visibility
1046         del bpy.types.World.cycles_visibility
1047
1048
1049 class CyclesMeshSettings(bpy.types.PropertyGroup):
1050     @classmethod
1051     def register(cls):
1052         bpy.types.Mesh.cycles = PointerProperty(
1053                 name="Cycles Mesh Settings",
1054                 description="Cycles mesh settings",
1055                 type=cls,
1056                 )
1057         bpy.types.Curve.cycles = PointerProperty(
1058                 name="Cycles Mesh Settings",
1059                 description="Cycles mesh settings",
1060                 type=cls,
1061                 )
1062         bpy.types.MetaBall.cycles = PointerProperty(
1063                 name="Cycles Mesh Settings",
1064                 description="Cycles mesh settings",
1065                 type=cls,
1066                 )
1067
1068     @classmethod
1069     def unregister(cls):
1070         del bpy.types.Mesh.cycles
1071         del bpy.types.Curve.cycles
1072         del bpy.types.MetaBall.cycles
1073
1074
1075 class CyclesObjectSettings(bpy.types.PropertyGroup):
1076     @classmethod
1077     def register(cls):
1078         bpy.types.Object.cycles = PointerProperty(
1079                 name="Cycles Object Settings",
1080                 description="Cycles object settings",
1081                 type=cls,
1082                 )
1083
1084         cls.use_motion_blur = BoolProperty(
1085                 name="Use Motion Blur",
1086                 description="Use motion blur for this object",
1087                 default=True,
1088                 )
1089
1090         cls.use_deform_motion = BoolProperty(
1091                 name="Use Deformation Motion",
1092                 description="Use deformation motion blur for this object",
1093                 default=True,
1094                 )
1095
1096         cls.motion_steps = IntProperty(
1097                 name="Motion Steps",
1098                 description="Control accuracy of motion blur, more steps gives more memory usage (actual number of steps is 2^(steps - 1))",
1099                 min=1, soft_max=8,
1100                 default=1,
1101                 )
1102
1103         cls.use_camera_cull = BoolProperty(
1104                 name="Use Camera Cull",
1105                 description="Allow this object and its duplicators to be culled by camera space culling",
1106                 default=False,
1107                 )
1108
1109         cls.use_distance_cull = BoolProperty(
1110                 name="Use Distance Cull",
1111                 description="Allow this object and its duplicators to be culled by distance from camera",
1112                 default=False,
1113                 )
1114
1115         cls.use_adaptive_subdivision = BoolProperty(
1116                 name="Use Adaptive Subdivision",
1117                 description="Use adaptive render time subdivision",
1118                 default=False,
1119                 )
1120
1121         cls.dicing_rate = FloatProperty(
1122                 name="Dicing Scale",
1123                 description="Multiplier for scene dicing rate (located in the Geometry Panel)",
1124                 min=0.1, max=1000.0, soft_min=0.5,
1125                 default=1.0,
1126                 )
1127
1128         cls.is_shadow_catcher = BoolProperty(
1129                 name="Shadow Catcher",
1130                 description="Only render shadows on this object, for compositing renders into real footage",
1131                 default=False,
1132                 )
1133
1134         cls.is_holdout = BoolProperty(
1135                 name="Holdout",
1136                 description="Render objects as a holdout or matte, creating a "
1137                             "hole in the image with zero alpha, to fill out in "
1138                             "compositing with real footange or another render",
1139                 default=False,
1140                 )
1141
1142
1143     @classmethod
1144     def unregister(cls):
1145         del bpy.types.Object.cycles
1146
1147
1148 class CyclesCurveRenderSettings(bpy.types.PropertyGroup):
1149     @classmethod
1150     def register(cls):
1151         bpy.types.Scene.cycles_curves = PointerProperty(
1152                 name="Cycles Hair Rendering Settings",
1153                 description="Cycles hair rendering settings",
1154                 type=cls,
1155                 )
1156         cls.primitive = EnumProperty(
1157                 name="Primitive",
1158                 description="Type of primitive used for hair rendering",
1159                 items=enum_curve_primitives,
1160                 default='LINE_SEGMENTS',
1161                 )
1162         cls.shape = EnumProperty(
1163                 name="Shape",
1164                 description="Form of hair",
1165                 items=enum_curve_shape,
1166                 default='THICK',
1167                 )
1168         cls.cull_backfacing = BoolProperty(
1169                 name="Cull back-faces",
1170                 description="Do not test the back-face of each strand",
1171                 default=True,
1172                 )
1173         cls.use_curves = BoolProperty(
1174                 name="Use Cycles Hair Rendering",
1175                 description="Activate Cycles hair rendering for particle system",
1176                 default=True,
1177                 )
1178         cls.resolution = IntProperty(
1179                 name="Resolution",
1180                 description="Resolution of generated mesh",
1181                 min=3, max=64,
1182                 default=3,
1183                 )
1184         cls.minimum_width = FloatProperty(
1185                 name="Minimal width",
1186                 description="Minimal pixel width for strands (0 - deactivated)",
1187                 min=0.0, max=100.0,
1188                 default=0.0,
1189                 )
1190         cls.maximum_width = FloatProperty(
1191                 name="Maximal width",
1192                 description="Maximum extension that strand radius can be increased by",
1193                 min=0.0, max=100.0,
1194                 default=0.1,
1195                 )
1196         cls.subdivisions = IntProperty(
1197                 name="Subdivisions",
1198                 description="Number of subdivisions used in Cardinal curve intersection (power of 2)",
1199                 min=0, max=24,
1200                 default=4,
1201                 )
1202
1203     @classmethod
1204     def unregister(cls):
1205         del bpy.types.Scene.cycles_curves
1206
1207 def update_render_passes(self, context):
1208     scene = context.scene
1209     rd = scene.render
1210     rl = rd.layers.active
1211     rl.update_render_passes()
1212
1213 class CyclesRenderLayerSettings(bpy.types.PropertyGroup):
1214     @classmethod
1215     def register(cls):
1216         bpy.types.SceneRenderLayer.cycles = PointerProperty(
1217                 name="Cycles SceneRenderLayer Settings",
1218                 description="Cycles SceneRenderLayer Settings",
1219                 type=cls,
1220                 )
1221         cls.pass_debug_bvh_traversed_nodes = BoolProperty(
1222                 name="Debug BVH Traversed Nodes",
1223                 description="Store Debug BVH Traversed Nodes pass",
1224                 default=False,
1225                 update=update_render_passes,
1226                 )
1227         cls.pass_debug_bvh_traversed_instances = BoolProperty(
1228                 name="Debug BVH Traversed Instances",
1229                 description="Store Debug BVH Traversed Instances pass",
1230                 default=False,
1231                 update=update_render_passes,
1232                 )
1233         cls.pass_debug_bvh_intersections = BoolProperty(
1234                 name="Debug BVH Intersections",
1235                 description="Store Debug BVH Intersections",
1236                 default=False,
1237                 update=update_render_passes,
1238                 )
1239         cls.pass_debug_ray_bounces = BoolProperty(
1240                 name="Debug Ray Bounces",
1241                 description="Store Debug Ray Bounces pass",
1242                 default=False,
1243                 update=update_render_passes,
1244                 )
1245         cls.pass_debug_render_time = BoolProperty(
1246                 name="Debug Render Time",
1247                 description="Render time in milliseconds per sample and pixel",
1248                 default=False,
1249                 update=update_render_passes,
1250                 )
1251         cls.use_pass_volume_direct = BoolProperty(
1252                 name="Volume Direct",
1253                 description="Deliver direct volumetric scattering pass",
1254                 default=False,
1255                 update=update_render_passes,
1256                 )
1257         cls.use_pass_volume_indirect = BoolProperty(
1258                 name="Volume Indirect",
1259                 description="Deliver indirect volumetric scattering pass",
1260                 default=False,
1261                 update=update_render_passes,
1262                 )
1263
1264         cls.use_denoising = BoolProperty(
1265                 name="Use Denoising",
1266                 description="Denoise the rendered image",
1267                 default=False,
1268                 update=update_render_passes,
1269                 )
1270         cls.denoising_diffuse_direct = BoolProperty(
1271                 name="Diffuse Direct",
1272                 description="Denoise the direct diffuse lighting",
1273                 default=True,
1274                 )
1275         cls.denoising_diffuse_indirect = BoolProperty(
1276                 name="Diffuse Indirect",
1277                 description="Denoise the indirect diffuse lighting",
1278                 default=True,
1279                 )
1280         cls.denoising_glossy_direct = BoolProperty(
1281                 name="Glossy Direct",
1282                 description="Denoise the direct glossy lighting",
1283                 default=True,
1284                 )
1285         cls.denoising_glossy_indirect = BoolProperty(
1286                 name="Glossy Indirect",
1287                 description="Denoise the indirect glossy lighting",
1288                 default=True,
1289                 )
1290         cls.denoising_transmission_direct = BoolProperty(
1291                 name="Transmission Direct",
1292                 description="Denoise the direct transmission lighting",
1293                 default=True,
1294                 )
1295         cls.denoising_transmission_indirect = BoolProperty(
1296                 name="Transmission Indirect",
1297                 description="Denoise the indirect transmission lighting",
1298                 default=True,
1299                 )
1300         cls.denoising_subsurface_direct = BoolProperty(
1301                 name="Subsurface Direct",
1302                 description="Denoise the direct subsurface lighting",
1303                 default=True,
1304                 )
1305         cls.denoising_subsurface_indirect = BoolProperty(
1306                 name="Subsurface Indirect",
1307                 description="Denoise the indirect subsurface lighting",
1308                 default=True,
1309                 )
1310         cls.denoising_strength = FloatProperty(
1311                 name="Denoising Strength",
1312                 description="Controls neighbor pixel weighting for the denoising filter (lower values preserve more detail, but aren't as smooth)",
1313                 min=0.0, max=1.0,
1314                 default=0.5,
1315                 )
1316         cls.denoising_feature_strength = FloatProperty(
1317                 name="Denoising Feature Strength",
1318                 description="Controls removal of noisy image feature passes (lower values preserve more detail, but aren't as smooth)",
1319                 min=0.0, max=1.0,
1320                 default=0.5,
1321                 )
1322         cls.denoising_radius = IntProperty(
1323                 name="Denoising Radius",
1324                 description="Size of the image area that's used to denoise a pixel (higher values are smoother, but might lose detail and are slower)",
1325                 min=1, max=25,
1326                 default=8,
1327         )
1328         cls.denoising_relative_pca = BoolProperty(
1329                 name="Relative filter",
1330                 description="When removing pixels that don't carry information, use a relative threshold instead of an absolute one (can help to reduce artifacts, but might cause detail loss around edges)",
1331                 default=False,
1332         )
1333         cls.denoising_store_passes = BoolProperty(
1334                 name="Store denoising passes",
1335                 description="Store the denoising feature passes and the noisy image",
1336                 default=False,
1337                 update=update_render_passes,
1338         )
1339
1340     @classmethod
1341     def unregister(cls):
1342         del bpy.types.SceneRenderLayer.cycles
1343
1344
1345 class CyclesCurveSettings(bpy.types.PropertyGroup):
1346     @classmethod
1347     def register(cls):
1348         bpy.types.ParticleSettings.cycles = PointerProperty(
1349                 name="Cycles Hair Settings",
1350                 description="Cycles hair settings",
1351                 type=cls,
1352                 )
1353         cls.radius_scale = FloatProperty(
1354                 name="Radius Scaling",
1355                 description="Multiplier of width properties",
1356                 min=0.0, max=1000.0,
1357                 default=0.01,
1358                 )
1359         cls.root_width = FloatProperty(
1360                 name="Root Size",
1361                 description="Strand's width at root",
1362                 min=0.0, max=1000.0,
1363                 default=1.0,
1364                 )
1365         cls.tip_width = FloatProperty(
1366                 name="Tip Multiplier",
1367                 description="Strand's width at tip",
1368                 min=0.0, max=1000.0,
1369                 default=0.0,
1370                 )
1371         cls.shape = FloatProperty(
1372                 name="Strand Shape",
1373                 description="Strand shape parameter",
1374                 min=-1.0, max=1.0,
1375                 default=0.0,
1376                 )
1377         cls.use_closetip = BoolProperty(
1378                 name="Close tip",
1379                 description="Set tip radius to zero",
1380                 default=True,
1381                 )
1382
1383     @classmethod
1384     def unregister(cls):
1385         del bpy.types.ParticleSettings.cycles
1386
1387
1388 class CyclesDeviceSettings(bpy.types.PropertyGroup):
1389     @classmethod
1390     def register(cls):
1391         cls.id = StringProperty(name="ID")
1392         cls.name = StringProperty(name="Name")
1393         cls.use = BoolProperty(name="Use", default=True)
1394         cls.type = EnumProperty(name="Type", items=enum_device_type, default='CUDA')
1395
1396
1397 class CyclesPreferences(bpy.types.AddonPreferences):
1398     bl_idname = __package__
1399
1400     def get_device_types(self, context):
1401         import _cycles
1402         has_cuda, has_opencl = _cycles.get_device_types()
1403         list = [('NONE', "None", "Don't use compute device", 0)]
1404         if has_cuda:
1405             list.append(('CUDA', "CUDA", "Use CUDA for GPU acceleration", 1))
1406         if has_opencl:
1407             list.append(('OPENCL', "OpenCL", "Use OpenCL for GPU acceleration", 2))
1408         return list
1409
1410     compute_device_type = EnumProperty(
1411             name="Compute Device Type",
1412             description="Device to use for computation (rendering with Cycles)",
1413             items=get_device_types,
1414             )
1415
1416     devices = bpy.props.CollectionProperty(type=CyclesDeviceSettings)
1417
1418     def find_existing_device_entry(self, device):
1419         for device_entry in self.devices:
1420             if device_entry.id == device[2] and device_entry.type == device[1]:
1421                 return device_entry
1422         return None
1423
1424
1425     def update_device_entries(self, device_list):
1426         for device in device_list:
1427             if not device[1] in {'CUDA', 'OPENCL', 'CPU'}:
1428                 continue
1429             # Try to find existing Device entry
1430             entry = self.find_existing_device_entry(device)
1431             if not entry:
1432                 # Create new entry if no existing one was found
1433                 entry = self.devices.add()
1434                 entry.id   = device[2]
1435                 entry.name = device[0]
1436                 entry.type = device[1]
1437                 entry.use  = entry.type != 'CPU'
1438             elif entry.name != device[0]:
1439                 # Update name in case it changed
1440                 entry.name = device[0]
1441
1442
1443     def get_devices(self):
1444         import _cycles
1445         # Layout of the device tuples: (Name, Type, Persistent ID)
1446         device_list = _cycles.available_devices()
1447         # Make sure device entries are up to date and not referenced before
1448         # we know we don't add new devices. This way we guarantee to not
1449         # hold pointers to a resized array.
1450         self.update_device_entries(device_list)
1451         # Sort entries into lists
1452         cuda_devices = []
1453         opencl_devices = []
1454         cpu_devices = []
1455         for device in device_list:
1456             entry = self.find_existing_device_entry(device)
1457             if entry.type == 'CUDA':
1458                 cuda_devices.append(entry)
1459             elif entry.type == 'OPENCL':
1460                 opencl_devices.append(entry)
1461             elif entry.type == 'CPU':
1462                 cpu_devices.append(entry)
1463         # Extend all GPU devices with CPU.
1464         cuda_devices.extend(cpu_devices)
1465         opencl_devices.extend(cpu_devices)
1466         return cuda_devices, opencl_devices
1467
1468
1469     def get_num_gpu_devices(self):
1470         import _cycles
1471         device_list = _cycles.available_devices()
1472         num = 0
1473         for device in device_list:
1474             if device[1] != self.compute_device_type:
1475                 continue
1476             for dev in self.devices:
1477                 if dev.use and dev.id == device[2]:
1478                     num += 1
1479         return num
1480
1481
1482     def has_active_device(self):
1483         return self.get_num_gpu_devices() > 0
1484
1485
1486     def draw_impl(self, layout, context):
1487         layout.label(text="Cycles Compute Device:")
1488         layout.row().prop(self, "compute_device_type", expand=True)
1489
1490         cuda_devices, opencl_devices = self.get_devices()
1491         row = layout.row()
1492
1493         if self.compute_device_type == 'CUDA' and cuda_devices:
1494             box = row.box()
1495             for device in cuda_devices:
1496                 box.prop(device, "use", text=device.name)
1497
1498         if self.compute_device_type == 'OPENCL' and opencl_devices:
1499             box = row.box()
1500             for device in opencl_devices:
1501                 box.prop(device, "use", text=device.name)
1502
1503
1504     def draw(self, context):
1505         self.draw_impl(self.layout, context)
1506
1507
1508 def register():
1509     bpy.utils.register_class(CyclesRenderSettings)
1510     bpy.utils.register_class(CyclesCameraSettings)
1511     bpy.utils.register_class(CyclesMaterialSettings)
1512     bpy.utils.register_class(CyclesLampSettings)
1513     bpy.utils.register_class(CyclesWorldSettings)
1514     bpy.utils.register_class(CyclesVisibilitySettings)
1515     bpy.utils.register_class(CyclesMeshSettings)
1516     bpy.utils.register_class(CyclesObjectSettings)
1517     bpy.utils.register_class(CyclesCurveRenderSettings)
1518     bpy.utils.register_class(CyclesCurveSettings)
1519     bpy.utils.register_class(CyclesDeviceSettings)
1520     bpy.utils.register_class(CyclesPreferences)
1521     bpy.utils.register_class(CyclesRenderLayerSettings)
1522
1523
1524 def unregister():
1525     bpy.utils.unregister_class(CyclesRenderSettings)
1526     bpy.utils.unregister_class(CyclesCameraSettings)
1527     bpy.utils.unregister_class(CyclesMaterialSettings)
1528     bpy.utils.unregister_class(CyclesLampSettings)
1529     bpy.utils.unregister_class(CyclesWorldSettings)
1530     bpy.utils.unregister_class(CyclesMeshSettings)
1531     bpy.utils.unregister_class(CyclesObjectSettings)
1532     bpy.utils.unregister_class(CyclesVisibilitySettings)
1533     bpy.utils.unregister_class(CyclesCurveRenderSettings)
1534     bpy.utils.unregister_class(CyclesCurveSettings)
1535     bpy.utils.unregister_class(CyclesDeviceSettings)
1536     bpy.utils.unregister_class(CyclesPreferences)
1537     bpy.utils.unregister_class(CyclesRenderLayerSettings)