Merge branch 'master' into blender2.8
[blender.git] / release / scripts / startup / bl_ui / properties_render.py
1 # ##### BEGIN GPL LICENSE BLOCK #####
2
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 # ##### END GPL LICENSE BLOCK #####
19
20 # <pep8 compliant>
21 import bpy
22 from bpy.types import Menu, Panel, UIList
23 from bl_operators.presets import PresetMenu
24 from .space_view3d import (
25     VIEW3D_PT_shading_lighting,
26     VIEW3D_PT_shading_color,
27     VIEW3D_PT_shading_options,
28 )
29
30
31 class RENDER_PT_presets(PresetMenu):
32     bl_label = "Render Presets"
33     preset_subdir = "render"
34     preset_operator = "script.execute_preset"
35     preset_add_operator = "render.preset_add"
36
37
38 class RENDER_PT_ffmpeg_presets(PresetMenu):
39     bl_label = "FFMPEG Presets"
40     preset_subdir = "ffmpeg"
41     preset_operator = "script.python_file_run"
42
43
44 class RENDER_MT_framerate_presets(Menu):
45     bl_label = "Frame Rate Presets"
46     preset_subdir = "framerate"
47     preset_operator = "script.execute_preset"
48     draw = Menu.draw_preset
49
50
51 class RenderButtonsPanel:
52     bl_space_type = 'PROPERTIES'
53     bl_region_type = 'WINDOW'
54     bl_context = "render"
55     # COMPAT_ENGINES must be defined in each subclass, external engines can add themselves here
56
57     @classmethod
58     def poll(cls, context):
59         return (context.engine in cls.COMPAT_ENGINES)
60
61
62 class RENDER_PT_context(Panel):
63     bl_space_type = 'PROPERTIES'
64     bl_region_type = 'WINDOW'
65     bl_context = "render"
66     bl_options = {'HIDE_HEADER'}
67     bl_label = ""
68
69     @classmethod
70     def poll(cls, context):
71         return context.scene
72
73     def draw(self, context):
74         layout = self.layout
75         layout.use_property_split = True
76         layout.use_property_decorate = False
77
78         scene = context.scene
79         rd = scene.render
80
81         if rd.has_multiple_engines:
82             layout.prop(rd, "engine", text="Render Engine")
83
84
85 class RENDER_PT_dimensions(RenderButtonsPanel, Panel):
86     bl_label = "Dimensions"
87     COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_OPENGL'}
88
89     _frame_rate_args_prev = None
90     _preset_class = None
91
92     def draw_header_preset(self, context):
93         RENDER_PT_presets.draw_panel_header(self.layout)
94
95     @staticmethod
96     def _draw_framerate_label(*args):
97         # avoids re-creating text string each draw
98         if RENDER_PT_dimensions._frame_rate_args_prev == args:
99             return RENDER_PT_dimensions._frame_rate_ret
100
101         fps, fps_base, preset_label = args
102
103         if fps_base == 1.0:
104             fps_rate = round(fps)
105         else:
106             fps_rate = round(fps / fps_base, 2)
107
108         # TODO: Change the following to iterate over existing presets
109         custom_framerate = (fps_rate not in {23.98, 24, 25, 29.97, 30, 50, 59.94, 60})
110
111         if custom_framerate is True:
112             fps_label_text = f"Custom ({fps_rate!r} fps)"
113             show_framerate = True
114         else:
115             fps_label_text = f"{fps_rate!r} fps"
116             show_framerate = (preset_label == "Custom")
117
118         RENDER_PT_dimensions._frame_rate_args_prev = args
119         RENDER_PT_dimensions._frame_rate_ret = args = (fps_label_text, show_framerate)
120         return args
121
122     @staticmethod
123     def draw_framerate(layout, sub, rd):
124         if RENDER_PT_dimensions._preset_class is None:
125             RENDER_PT_dimensions._preset_class = bpy.types.RENDER_MT_framerate_presets
126
127         args = rd.fps, rd.fps_base, RENDER_PT_dimensions._preset_class.bl_label
128         fps_label_text, show_framerate = RENDER_PT_dimensions._draw_framerate_label(*args)
129
130         sub.menu("RENDER_MT_framerate_presets", text=fps_label_text)
131
132         if show_framerate:
133             col = layout.column(align=True)
134             col.prop(rd, "fps")
135             col.prop(rd, "fps_base", text="Base")
136
137     def draw(self, context):
138         layout = self.layout
139         layout.use_property_split = True
140         layout.use_property_decorate = False  # No animation.
141
142         scene = context.scene
143         rd = scene.render
144
145         col = layout.column(align=True)
146         col.prop(rd, "resolution_x", text="Resolution X")
147         col.prop(rd, "resolution_y", text="Y")
148         col.prop(rd, "resolution_percentage", text="%")
149
150         col = layout.column(align=True)
151         col.prop(rd, "pixel_aspect_x", text="Aspect X")
152         col.prop(rd, "pixel_aspect_y", text="Y")
153
154         col = layout.column(align=True)
155         col.prop(rd, "use_border", text="Border")
156         sub = col.column(align=True)
157         sub.active = rd.use_border
158         sub.prop(rd, "use_crop_to_border", text="Crop")
159
160         col = layout.column(align=True)
161         col.prop(scene, "frame_start", text="Frame Start")
162         col.prop(scene, "frame_end", text="End")
163         col.prop(scene, "frame_step", text="Step")
164
165         col = layout.split()
166         col.alignment = 'RIGHT'
167         col.label(text="Frame Rate")
168         self.draw_framerate(layout, col, rd)
169
170
171 class RENDER_PT_frame_remapping(RenderButtonsPanel, Panel):
172     bl_label = "Time Remapping"
173     bl_parent_id = "RENDER_PT_dimensions"
174     bl_options = {'DEFAULT_CLOSED'}
175     COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_OPENGL'}
176
177     def draw(self, context):
178         layout = self.layout
179         layout.use_property_split = True
180         layout.use_property_decorate = False  # No animation.
181
182         rd = context.scene.render
183
184         col = layout.column(align=True)
185         col.prop(rd, "frame_map_old", text="Old")
186         col.prop(rd, "frame_map_new", text="New")
187
188
189 class RENDER_PT_post_processing(RenderButtonsPanel, Panel):
190     bl_label = "Post Processing"
191     bl_options = {'DEFAULT_CLOSED'}
192     COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_OPENGL'}
193
194     def draw(self, context):
195         layout = self.layout
196         layout.use_property_split = True
197
198         rd = context.scene.render
199
200         col = layout.column(align=True)
201         col.prop(rd, "use_compositing")
202         col.prop(rd, "use_sequencer")
203
204         col.prop(rd, "dither_intensity", text="Dither", slider=True)
205
206
207 class RENDER_PT_stamp(RenderButtonsPanel, Panel):
208     bl_label = "Metadata"
209     bl_options = {'DEFAULT_CLOSED'}
210     COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_OPENGL'}
211
212     def draw(self, context):
213         layout = self.layout
214         layout.use_property_split = True
215         layout.use_property_decorate = False  # No animation.
216
217         rd = context.scene.render
218
219         flow = layout.grid_flow(row_major=True, columns=0, even_columns=True, even_rows=False, align=False)
220
221         col = flow.column()
222         col.prop(rd, "use_stamp_date", text="Date")
223         col = flow.column()
224         col.prop(rd, "use_stamp_time", text="Time")
225
226         col = flow.column()
227         col.prop(rd, "use_stamp_render_time", text="Render Time")
228         col = flow.column()
229         col.prop(rd, "use_stamp_frame", text="Frame")
230         col = flow.column()
231         col.prop(rd, "use_stamp_frame_range", text="Frame Range")
232         col = flow.column()
233         col.prop(rd, "use_stamp_memory", text="Memory")
234
235         col = flow.column()
236         col.prop(rd, "use_stamp_camera", text="Camera")
237         col = flow.column()
238         col.prop(rd, "use_stamp_lens", text="Lens")
239
240         col = flow.column()
241         col.prop(rd, "use_stamp_scene", text="Scene")
242         col = flow.column()
243         col.prop(rd, "use_stamp_marker", text="Marker")
244
245         col = flow.column()
246         col.prop(rd, "use_stamp_filename", text="Filename")
247
248         col = flow.column()
249         col.prop(rd, "use_stamp_sequencer_strip", text="Strip Name")
250
251         if rd.use_sequencer:
252             col = flow.column()
253             col.prop(rd, "use_stamp_strip_meta", text="Use Strip Metadata")
254
255         row = layout.split(factor=0.3)
256         row.prop(rd, "use_stamp_note", text="Note")
257         sub = row.row()
258         sub.active = rd.use_stamp_note
259         sub.prop(rd, "stamp_note_text", text="")
260
261
262 class RENDER_PT_stamp_burn(RenderButtonsPanel, Panel):
263     bl_label = "Burn Into Image"
264     bl_parent_id = "RENDER_PT_stamp"
265     bl_options = {'DEFAULT_CLOSED'}
266     COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_OPENGL'}
267
268     def draw_header(self, context):
269         rd = context.scene.render
270
271         self.layout.prop(rd, "use_stamp", text="")
272
273     def draw(self, context):
274         layout = self.layout
275
276         rd = context.scene.render
277
278         layout.use_property_split = True
279
280         col = layout.column()
281         col.active = rd.use_stamp
282         col.prop(rd, "stamp_font_size", text="Font Size")
283         col.prop(rd, "use_stamp_labels", text="Draw Labels")
284         col.column().prop(rd, "stamp_foreground", slider=True)
285         col.column().prop(rd, "stamp_background", slider=True)
286
287
288 class RENDER_PT_output(RenderButtonsPanel, Panel):
289     bl_label = "Output"
290     COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_OPENGL'}
291
292     def draw(self, context):
293         layout = self.layout
294         layout.use_property_split = False
295         layout.use_property_decorate = False  # No animation.
296
297         rd = context.scene.render
298         image_settings = rd.image_settings
299
300         layout.prop(rd, "filepath", text="")
301
302         layout.use_property_split = True
303
304         flow = layout.grid_flow(row_major=True, columns=0, even_columns=True, even_rows=False, align=False)
305
306         col = flow.column()
307         col.active = not rd.is_movie_format
308         col.prop(rd, "use_overwrite")
309         col = flow.column()
310         col.active = not rd.is_movie_format
311         col.prop(rd, "use_placeholder")
312         col = flow.column()
313         col.prop(rd, "use_file_extension")
314         col = flow.column()
315         col.prop(rd, "use_render_cache")
316
317         layout.template_image_settings(image_settings, color_management=False)
318
319
320 class RENDER_PT_output_views(RenderButtonsPanel, Panel):
321     bl_label = "Views"
322     bl_parent_id = "RENDER_PT_output"
323     COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_OPENGL'}
324
325     @classmethod
326     def poll(self, context):
327         rd = context.scene.render
328         return rd.use_multiview
329
330     def draw(self, context):
331         layout = self.layout
332         layout.use_property_split = False
333         layout.use_property_decorate = False  # No animation.
334
335         rd = context.scene.render
336         layout.template_image_views(rd.image_settings)
337
338
339 class RENDER_PT_encoding(RenderButtonsPanel, Panel):
340     bl_label = "Encoding"
341     bl_parent_id = "RENDER_PT_output"
342     bl_options = {'DEFAULT_CLOSED'}
343     COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_OPENGL'}
344
345     def draw_header_preset(self, context):
346         RENDER_PT_ffmpeg_presets.draw_panel_header(self.layout)
347
348     @classmethod
349     def poll(cls, context):
350         rd = context.scene.render
351         return rd.image_settings.file_format in {'FFMPEG', 'XVID', 'H264', 'THEORA'}
352
353     def draw(self, context):
354         layout = self.layout
355         layout.use_property_split = True
356         layout.use_property_decorate = False
357
358         rd = context.scene.render
359         ffmpeg = rd.ffmpeg
360
361         layout.prop(rd.ffmpeg, "format")
362         layout.prop(ffmpeg, "use_autosplit")
363
364
365 class RENDER_PT_encoding_video(RenderButtonsPanel, Panel):
366     bl_label = "Video"
367     bl_parent_id = "RENDER_PT_encoding"
368     COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_OPENGL'}
369
370     @classmethod
371     def poll(cls, context):
372         rd = context.scene.render
373         return rd.image_settings.file_format in {'FFMPEG', 'XVID', 'H264', 'THEORA'}
374
375     def draw(self, context):
376         layout = self.layout
377         layout.use_property_split = True
378         layout.use_property_decorate = False
379
380         rd = context.scene.render
381         ffmpeg = rd.ffmpeg
382
383         self.draw_vcodec(context)
384
385     def draw_vcodec(self, context):
386         """Video codec options."""
387         layout = self.layout
388         ffmpeg = context.scene.render.ffmpeg
389
390         needs_codec = ffmpeg.format in {'AVI', 'QUICKTIME', 'MKV', 'OGG', 'MPEG4'}
391         if needs_codec:
392             layout.prop(ffmpeg, "codec")
393
394         if needs_codec and ffmpeg.codec == 'NONE':
395             return
396
397         if ffmpeg.codec in {'DNXHD'}:
398             layout.prop(ffmpeg, "use_lossless_output")
399
400         # Output quality
401         use_crf = needs_codec and ffmpeg.codec in {'H264', 'MPEG4', 'WEBM'}
402         if use_crf:
403             layout.prop(ffmpeg, "constant_rate_factor")
404
405         # Encoding speed
406         layout.prop(ffmpeg, "ffmpeg_preset")
407         # I-frames
408         layout.prop(ffmpeg, "gopsize")
409         # B-Frames
410         split = layout.split(factor=0.5)
411         split.prop(ffmpeg, "use_max_b_frames", text="Max B-frames")
412         pbox = split.column()
413         pbox.prop(ffmpeg, "max_b_frames", text="")
414         pbox.enabled = ffmpeg.use_max_b_frames
415
416         if not use_crf or ffmpeg.constant_rate_factor == 'NONE':
417             col = layout.column()
418
419             sub = col.column(align=True)
420             sub.prop(ffmpeg, "video_bitrate")
421             sub.prop(ffmpeg, "minrate", text="Minimum")
422             sub.prop(ffmpeg, "maxrate", text="Maximum")
423
424             col.prop(ffmpeg, "buffersize", text="Buffer")
425
426             col.separator()
427
428             col.prop(ffmpeg, "muxrate", text="Mux Rate")
429             col.prop(ffmpeg, "packetsize", text="Mux Packet Size")
430
431
432 class RENDER_PT_encoding_audio(RenderButtonsPanel, Panel):
433     bl_label = "Audio"
434     bl_parent_id = "RENDER_PT_encoding"
435     COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_OPENGL'}
436
437     @classmethod
438     def poll(cls, context):
439         rd = context.scene.render
440         return rd.image_settings.file_format in {'FFMPEG', 'XVID', 'H264', 'THEORA'}
441
442     def draw(self, context):
443         layout = self.layout
444         layout.use_property_split = True
445         layout.use_property_decorate = False
446
447         rd = context.scene.render
448         ffmpeg = rd.ffmpeg
449
450         if ffmpeg.format != 'MP3':
451             layout.prop(ffmpeg, "audio_codec", text="Audio Codec")
452
453         if ffmpeg.audio_codec != 'NONE':
454             layout.prop(ffmpeg, "audio_bitrate")
455             layout.prop(ffmpeg, "audio_volume", slider=True)
456
457
458 class RENDER_UL_renderviews(UIList):
459     def draw_item(self, context, layout, data, item, icon, active_data, active_propname, index):
460         view = item
461         if self.layout_type in {'DEFAULT', 'COMPACT'}:
462             if view.name in {"left", "right"}:
463                 layout.label(text=view.name, icon_value=icon + (not view.use))
464             else:
465                 layout.prop(view, "name", text="", index=index, icon_value=icon, emboss=False)
466             layout.prop(view, "use", text="", index=index)
467
468         elif self.layout_type == 'GRID':
469             layout.alignment = 'CENTER'
470             layout.label(text="", icon_value=icon + (not view.use))
471
472
473 class RENDER_PT_stereoscopy(RenderButtonsPanel, Panel):
474     bl_label = "Stereoscopy"
475     COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_OPENGL'}
476     bl_options = {'DEFAULT_CLOSED'}
477
478     def draw_header(self, context):
479         rd = context.scene.render
480         self.layout.prop(rd, "use_multiview", text="")
481
482     def draw(self, context):
483         layout = self.layout
484
485         scene = context.scene
486         rd = scene.render
487         rv = rd.views.active
488
489         layout.active = rd.use_multiview
490         basic_stereo = rd.views_format == 'STEREO_3D'
491
492         row = layout.row()
493         row.prop(rd, "views_format", expand=True)
494
495         if basic_stereo:
496             row = layout.row()
497             row.template_list("RENDER_UL_renderviews", "name", rd, "stereo_views", rd.views, "active_index", rows=2)
498
499             row = layout.row()
500             row.label(text="File Suffix:")
501             row.prop(rv, "file_suffix", text="")
502
503         else:
504             row = layout.row()
505             row.template_list("RENDER_UL_renderviews", "name", rd, "views", rd.views, "active_index", rows=2)
506
507             col = row.column(align=True)
508             col.operator("scene.render_view_add", icon='ZOOMIN', text="")
509             col.operator("scene.render_view_remove", icon='ZOOMOUT', text="")
510
511             row = layout.row()
512             row.label(text="Camera Suffix:")
513             row.prop(rv, "camera_suffix", text="")
514
515
516 class RENDER_PT_eevee_ambient_occlusion(RenderButtonsPanel, Panel):
517     bl_label = "Ambient Occlusion"
518     bl_options = {'DEFAULT_CLOSED'}
519     COMPAT_ENGINES = {'BLENDER_EEVEE'}
520
521     @classmethod
522     def poll(cls, context):
523         return (context.engine in cls.COMPAT_ENGINES)
524
525     def draw_header(self, context):
526         scene = context.scene
527         props = scene.eevee
528         self.layout.prop(props, "use_gtao", text="")
529
530     def draw(self, context):
531         layout = self.layout
532         layout.use_property_split = True
533         scene = context.scene
534         props = scene.eevee
535
536         layout.active = props.use_gtao
537         col = layout.column()
538         col.prop(props, "use_gtao_bent_normals")
539         col.prop(props, "use_gtao_bounce")
540         col.prop(props, "gtao_distance")
541         col.prop(props, "gtao_factor")
542         col.prop(props, "gtao_quality")
543
544
545 class RENDER_PT_eevee_motion_blur(RenderButtonsPanel, Panel):
546     bl_label = "Motion Blur"
547     bl_options = {'DEFAULT_CLOSED'}
548     COMPAT_ENGINES = {'BLENDER_EEVEE'}
549
550     @classmethod
551     def poll(cls, context):
552         return (context.engine in cls.COMPAT_ENGINES)
553
554     def draw_header(self, context):
555         scene = context.scene
556         props = scene.eevee
557         self.layout.prop(props, "use_motion_blur", text="")
558
559     def draw(self, context):
560         layout = self.layout
561         layout.use_property_split = True
562         scene = context.scene
563         props = scene.eevee
564
565         layout.active = props.use_motion_blur
566         col = layout.column()
567         col.prop(props, "motion_blur_samples")
568         col.prop(props, "motion_blur_shutter")
569
570
571 class RENDER_PT_eevee_depth_of_field(RenderButtonsPanel, Panel):
572     bl_label = "Depth of Field"
573     bl_options = {'DEFAULT_CLOSED'}
574     COMPAT_ENGINES = {'BLENDER_EEVEE'}
575
576     @classmethod
577     def poll(cls, context):
578         return (context.engine in cls.COMPAT_ENGINES)
579
580     def draw_header(self, context):
581         scene = context.scene
582         props = scene.eevee
583         self.layout.prop(props, "use_dof", text="")
584
585     def draw(self, context):
586         layout = self.layout
587         layout.use_property_split = True
588         scene = context.scene
589         props = scene.eevee
590
591         layout.active = props.use_dof
592         col = layout.column()
593         col.prop(props, "bokeh_max_size")
594         col.prop(props, "bokeh_threshold")
595
596
597 class RENDER_PT_eevee_bloom(RenderButtonsPanel, Panel):
598     bl_label = "Bloom"
599     bl_options = {'DEFAULT_CLOSED'}
600     COMPAT_ENGINES = {'BLENDER_EEVEE'}
601
602     @classmethod
603     def poll(cls, context):
604         return (context.engine in cls.COMPAT_ENGINES)
605
606     def draw_header(self, context):
607         scene = context.scene
608         props = scene.eevee
609         self.layout.prop(props, "use_bloom", text="")
610
611     def draw(self, context):
612         layout = self.layout
613         layout.use_property_split = True
614
615         scene = context.scene
616         props = scene.eevee
617
618         layout.active = props.use_bloom
619         col = layout.column()
620         col.prop(props, "bloom_threshold")
621         col.prop(props, "bloom_knee")
622         col.prop(props, "bloom_radius")
623         col.prop(props, "bloom_color")
624         col.prop(props, "bloom_intensity")
625         col.prop(props, "bloom_clamp")
626
627
628 class RENDER_PT_eevee_volumetric(RenderButtonsPanel, Panel):
629     bl_label = "Volumetric"
630     bl_options = {'DEFAULT_CLOSED'}
631     COMPAT_ENGINES = {'BLENDER_EEVEE'}
632
633     @classmethod
634     def poll(cls, context):
635         return (context.engine in cls.COMPAT_ENGINES)
636
637     def draw_header(self, context):
638         scene = context.scene
639         props = scene.eevee
640         self.layout.prop(props, "use_volumetric", text="")
641
642     def draw(self, context):
643         layout = self.layout
644         layout.use_property_split = True
645
646         scene = context.scene
647         props = scene.eevee
648
649         layout.active = props.use_volumetric
650         col = layout.column()
651         sub = col.column(align=True)
652         sub.prop(props, "volumetric_start")
653         sub.prop(props, "volumetric_end")
654         col.prop(props, "volumetric_tile_size")
655         col.separator()
656         col.prop(props, "volumetric_samples")
657         sub.prop(props, "volumetric_sample_distribution")
658         col.separator()
659         col.prop(props, "use_volumetric_lights")
660
661         sub = col.column()
662         sub.active = props.use_volumetric_lights
663         sub.prop(props, "volumetric_light_clamp", text="Light Clamping")
664         col.separator()
665         col.prop(props, "use_volumetric_shadows")
666         sub = col.column()
667         sub.active = props.use_volumetric_shadows
668         sub.prop(props, "volumetric_shadow_samples", text="Shadow Samples")
669
670
671 class RENDER_PT_eevee_subsurface_scattering(RenderButtonsPanel, Panel):
672     bl_label = "Subsurface Scattering"
673     bl_options = {'DEFAULT_CLOSED'}
674     COMPAT_ENGINES = {'BLENDER_EEVEE'}
675
676     @classmethod
677     def poll(cls, context):
678         return (context.engine in cls.COMPAT_ENGINES)
679
680     def draw_header(self, context):
681         scene = context.scene
682         props = scene.eevee
683         self.layout.prop(props, "use_sss", text="")
684
685     def draw(self, context):
686         layout = self.layout
687         layout.use_property_split = True
688
689         scene = context.scene
690         props = scene.eevee
691
692         layout.active = props.use_sss
693
694         col = layout.column()
695         col.prop(props, "sss_samples")
696         col.prop(props, "sss_jitter_threshold")
697         col.prop(props, "use_sss_separate_albedo")
698
699
700 class RENDER_PT_eevee_screen_space_reflections(RenderButtonsPanel, Panel):
701     bl_label = "Screen Space Reflections"
702     bl_options = {'DEFAULT_CLOSED'}
703     COMPAT_ENGINES = {'BLENDER_EEVEE'}
704
705     @classmethod
706     def poll(cls, context):
707         return (context.engine in cls.COMPAT_ENGINES)
708
709     def draw_header(self, context):
710         scene = context.scene
711         props = scene.eevee
712         self.layout.prop(props, "use_ssr", text="")
713
714     def draw(self, context):
715         layout = self.layout
716         layout.use_property_split = True
717
718         scene = context.scene
719         props = scene.eevee
720
721         col = layout.column()
722         col.active = props.use_ssr
723         col.prop(props, "use_ssr_refraction", text="Refraction")
724         col.prop(props, "use_ssr_halfres")
725         col.prop(props, "ssr_quality")
726         col.prop(props, "ssr_max_roughness")
727         col.prop(props, "ssr_thickness")
728         col.prop(props, "ssr_border_fade")
729         col.prop(props, "ssr_firefly_fac")
730
731
732 class RENDER_PT_eevee_shadows(RenderButtonsPanel, Panel):
733     bl_label = "Shadows"
734     bl_options = {'DEFAULT_CLOSED'}
735     COMPAT_ENGINES = {'BLENDER_EEVEE'}
736
737     @classmethod
738     def poll(cls, context):
739         return (context.engine in cls.COMPAT_ENGINES)
740
741     def draw(self, context):
742         layout = self.layout
743         layout.use_property_split = True
744
745         scene = context.scene
746         props = scene.eevee
747
748         col = layout.column()
749         col.prop(props, "shadow_method")
750         col.prop(props, "shadow_cube_size", text="Cube Size")
751         col.prop(props, "shadow_cascade_size", text="Cascade Size")
752         col.prop(props, "use_shadow_high_bitdepth")
753
754
755 class RENDER_PT_eevee_sampling(RenderButtonsPanel, Panel):
756     bl_label = "Sampling"
757     bl_options = {'DEFAULT_CLOSED'}
758     COMPAT_ENGINES = {'BLENDER_EEVEE'}
759
760     @classmethod
761     def poll(cls, context):
762         return (context.engine in cls.COMPAT_ENGINES)
763
764     def draw(self, context):
765         layout = self.layout
766         layout.use_property_split = True
767         layout.use_property_decorate = False  # No animation.
768
769         scene = context.scene
770         props = scene.eevee
771
772         col = layout.column()
773         col.prop(props, "taa_samples")
774         col.prop(props, "taa_render_samples")
775         col.prop(props, "use_taa_reprojection")
776
777
778 class RENDER_PT_eevee_indirect_lighting(RenderButtonsPanel, Panel):
779     bl_label = "Indirect Lighting"
780     bl_options = {'DEFAULT_CLOSED'}
781     COMPAT_ENGINES = {'BLENDER_EEVEE'}
782
783     @classmethod
784     def poll(cls, context):
785         return (context.engine in cls.COMPAT_ENGINES)
786
787     def draw(self, context):
788         layout = self.layout
789         layout.use_property_split = True
790         layout.use_property_decorate = False  # No animation.
791
792         scene = context.scene
793         props = scene.eevee
794
795         col = layout.column()
796         col.operator("scene.light_cache_bake", text="Bake Indirect Lighting", icon='RENDER_STILL')
797         col.operator("scene.light_cache_bake", text="Bake Cubemap Only", icon='LIGHTPROBE_CUBEMAP').subset = 'CUBEMAPS'
798         col.operator("scene.light_cache_free", text="Free Lighting Cache")
799
800         cache_info = scene.eevee.gi_cache_info
801         if cache_info:
802             col.label(text=cache_info)
803
804         col.prop(props, "gi_auto_bake")
805
806         col.prop(props, "gi_diffuse_bounces")
807         col.prop(props, "gi_cubemap_resolution")
808         col.prop(props, "gi_visibility_resolution", text="Diffuse Occlusion")
809
810         layout.use_property_split = False
811         row = layout.split(factor=0.5)
812         row.alignment = 'RIGHT'
813         row.label(text="Cubemap Display")
814
815         sub = row.row(align=True)
816         sub.prop(props, "gi_cubemap_display_size", text="Size")
817         if props.gi_show_cubemaps:
818             sub.prop(props, "gi_show_cubemaps", text="", toggle=True, icon='HIDE_OFF')
819         else:
820             sub.prop(props, "gi_show_cubemaps", text="", toggle=True, icon='HIDE_ON')
821
822         row = layout.split(factor=0.5)
823         row.alignment = 'RIGHT'
824         row.label(text="Irradiance Display")
825
826         sub = row.row(align=True)
827         sub.prop(props, "gi_irradiance_display_size", text="Size")
828         if props.gi_show_irradiance:
829             sub.prop(props, "gi_show_irradiance", text="", toggle=True, icon='HIDE_OFF')
830         else:
831             sub.prop(props, "gi_show_irradiance", text="", toggle=True, icon='HIDE_ON')
832
833
834 class RENDER_PT_eevee_film(RenderButtonsPanel, Panel):
835     bl_label = "Film"
836     bl_options = {'DEFAULT_CLOSED'}
837     COMPAT_ENGINES = {'BLENDER_EEVEE'}
838
839     @classmethod
840     def poll(cls, context):
841         return (context.engine in cls.COMPAT_ENGINES)
842
843     def draw(self, context):
844         layout = self.layout
845         layout.use_property_split = True
846
847         scene = context.scene
848         rd = scene.render
849
850         col = layout.column()
851         col.prop(rd, "filter_size")
852         col.prop(rd, "alpha_mode", text="Alpha")
853
854
855 class RENDER_PT_eevee_hair(RenderButtonsPanel, Panel):
856     bl_label = "Hair"
857     bl_options = {'DEFAULT_CLOSED'}
858     COMPAT_ENGINES = {'BLENDER_EEVEE'}
859
860     @classmethod
861     def poll(cls, context):
862         return (context.engine in cls.COMPAT_ENGINES)
863
864     def draw(self, context):
865         layout = self.layout
866         scene = context.scene
867         rd = scene.render
868
869         row = layout.row()
870         row.prop(rd, "hair_type", expand=True)
871
872         layout.use_property_split = True
873         layout.prop(rd, "hair_subdiv")
874
875
876 class RENDER_PT_opengl_film(RenderButtonsPanel, Panel):
877     bl_label = "Film"
878     bl_options = {'DEFAULT_CLOSED'}
879     COMPAT_ENGINES = {'BLENDER_OPENGL'}
880
881     def draw(self, context):
882         layout = self.layout
883         layout.use_property_split = True
884         layout.use_property_decorate = False  # No animation.
885
886         rd = context.scene.render
887
888         layout.prop(rd, "use_antialiasing")
889
890         layout.prop(rd, "antialiasing_samples")
891         layout.prop(rd, "alpha_mode")
892
893
894 class RENDER_PT_opengl_lighting(RenderButtonsPanel, Panel):
895     bl_label = "Lighting"
896     COMPAT_ENGINES = {'BLENDER_OPENGL'}
897
898     @classmethod
899     def poll(cls, context):
900         return (context.engine in cls.COMPAT_ENGINES)
901
902     def draw(self, context):
903         VIEW3D_PT_shading_lighting.draw(self, context)
904
905
906 class RENDER_PT_opengl_color(RenderButtonsPanel, Panel):
907     bl_label = "Color"
908     COMPAT_ENGINES = {'BLENDER_OPENGL'}
909
910     @classmethod
911     def poll(cls, context):
912         return (context.engine in cls.COMPAT_ENGINES)
913
914     def draw(self, context):
915         VIEW3D_PT_shading_color._draw_color_type(self, context)
916
917
918 class RENDER_PT_opengl_options(RenderButtonsPanel, Panel):
919     bl_label = "Options"
920     COMPAT_ENGINES = {'BLENDER_OPENGL'}
921
922     @classmethod
923     def poll(cls, context):
924         return (context.engine in cls.COMPAT_ENGINES)
925
926     def draw(self, context):
927         VIEW3D_PT_shading_options.draw(self, context)
928
929
930 classes = (
931     RENDER_PT_presets,
932     RENDER_PT_ffmpeg_presets,
933     RENDER_MT_framerate_presets,
934     RENDER_PT_context,
935     RENDER_PT_dimensions,
936     RENDER_PT_frame_remapping,
937     RENDER_PT_post_processing,
938     RENDER_PT_output,
939     RENDER_PT_output_views,
940     RENDER_PT_encoding,
941     RENDER_PT_encoding_video,
942     RENDER_PT_encoding_audio,
943     RENDER_PT_stamp,
944     RENDER_PT_stamp_burn,
945     RENDER_UL_renderviews,
946     RENDER_PT_stereoscopy,
947     RENDER_PT_eevee_hair,
948     RENDER_PT_eevee_sampling,
949     RENDER_PT_eevee_film,
950     RENDER_PT_eevee_shadows,
951     RENDER_PT_eevee_indirect_lighting,
952     RENDER_PT_eevee_subsurface_scattering,
953     RENDER_PT_eevee_screen_space_reflections,
954     RENDER_PT_eevee_ambient_occlusion,
955     RENDER_PT_eevee_volumetric,
956     RENDER_PT_eevee_motion_blur,
957     RENDER_PT_eevee_depth_of_field,
958     RENDER_PT_eevee_bloom,
959     RENDER_PT_opengl_film,
960     RENDER_PT_opengl_lighting,
961     RENDER_PT_opengl_color,
962     RENDER_PT_opengl_options,
963 )
964
965 if __name__ == "__main__":  # only for live edit.
966     from bpy.utils import register_class
967     for cls in classes:
968         register_class(cls)