1 # SPDX-FileCopyrightText: 2021-2022 Blender Foundation
3 # SPDX-License-Identifier: GPL-2.0-or-later
5 """Declare shading properties exported to POV textures."""
7 from bpy
.utils
import register_class
, unregister_class
8 from bpy
.types
import PropertyGroup
9 from bpy
.props
import (
20 def check_material(mat
):
21 """Check that material node tree is not empty if use node button is on"""
23 return not mat
.node_tree
if mat
.use_nodes
else True
27 def pov_context_tex_datablock(context
):
28 """Texture context type recreated as deprecated in blender 2.8"""
30 idblock
= context
.brush
31 if idblock
and context
.scene
.texture_context
== "OTHER":
34 # idblock = bpy.context.active_object.active_material
35 idblock
= context
.view_layer
.objects
.active
.active_material
36 if idblock
and context
.scene
.texture_context
== "MATERIAL":
39 idblock
= context
.scene
.world
40 if idblock
and context
.scene
.texture_context
== "WORLD":
43 idblock
= context
.light
44 if idblock
and context
.scene
.texture_context
== "LIGHT":
47 if context
.particle_system
and context
.scene
.texture_context
== "PARTICLES":
48 idblock
= context
.particle_system
.settings
50 idblock
= context
.line_style
51 if idblock
and context
.scene
.texture_context
== "LINESTYLE":
57 def active_texture_name_from_uilist(self
, context
):
58 """Name created texture slots the same as created texture"""
59 idblock
= pov_context_tex_datablock(context
)
60 # mat = context.view_layer.objects.active.active_material
61 if idblock
is not None:
62 index
= idblock
.pov
.active_texture_index
63 name
= idblock
.pov_texture_slots
[index
].name
64 newname
= idblock
.pov_texture_slots
[index
].texture
65 tex
= bpy
.data
.textures
[name
]
67 idblock
.pov_texture_slots
[index
].name
= newname
70 def active_texture_name_from_search(self
, context
):
71 """Texture rolldown to change the data linked by an existing texture"""
72 idblock
= pov_context_tex_datablock(context
)
73 # mat = context.view_layer.objects.active.active_material
74 if idblock
is not None:
75 index
= idblock
.pov
.active_texture_index
76 slot
= idblock
.pov_texture_slots
[index
]
77 name
= slot
.texture_search
80 # tex = bpy.data.textures[name]
83 # Switch paint brush to this texture so settings remain contextual
84 # bpy.context.tool_settings.image_paint.brush.texture = tex
85 # bpy.context.tool_settings.image_paint.brush.mask_texture = tex
86 except BaseException
as e
:
88 print("An exception occurred: {}".format(e
))
91 def brush_texture_update(self
, context
):
93 """Brush texture rolldown must show active slot texture props"""
94 idblock
= pov_context_tex_datablock(context
)
95 if idblock
is not None:
96 # mat = context.view_layer.objects.active.active_material
97 idblock
= pov_context_tex_datablock(context
)
98 slot
= idblock
.pov_texture_slots
[idblock
.pov
.active_texture_index
]
99 if tex
:= slot
.texture
:
100 # Switch paint brush to active texture so slot and settings remain contextual
101 # bpy.ops.pov.textureslotupdate()
102 bpy
.context
.tool_settings
.image_paint
.brush
.texture
= bpy
.data
.textures
[tex
]
103 bpy
.context
.tool_settings
.image_paint
.brush
.mask_texture
= bpy
.data
.textures
[tex
]
106 class RenderPovSettingsMaterial(PropertyGroup
):
107 """Declare material level properties controllable in UI and translated to POV."""
109 # --------------------------- Begin Old Blender Internal Props --------------------------- #
110 # former Space properties from removed Blender Internal
111 use_limited_texture_context
: BoolProperty(
113 description
="Use the limited version of texture user (for ‘old shading’ mode)",
116 texture_context
: EnumProperty(
117 name
="Texture context",
118 description
="Type of texture data to display and edit",
120 ("MATERIAL", "", "Show material textures", "MATERIAL", 0), # "Show material textures"
121 ("WORLD", "", "Show world textures", "WORLD", 1), # "Show world textures"
122 ("LAMP", "", "Show lamp textures", "LIGHT", 2), # "Show lamp textures"
126 "Show particles textures",
129 ), # "Show particles textures"
133 "Show linestyle textures",
136 ), # "Show linestyle textures"
140 "Show other data textures",
143 ), # "Show other data textures"
148 active_texture_index
: IntProperty(
149 name
="Index for texture_slots", default
=0, update
=brush_texture_update
152 transparency_method
: EnumProperty(
153 name
="Specular Shader Model",
154 description
="Method to use for rendering transparency",
156 ("MASK", "Mask", "Mask the background"),
157 ("Z_TRANSPARENCY", "Z Transparency", "Use alpha buffer for transparent faces"),
158 ("RAYTRACE", "Raytrace", "Use raytracing for transparent refraction rendering"),
163 use_transparency
: BoolProperty(
164 name
="Transparency", description
="Render material as transparent", default
=False
167 alpha
: FloatProperty(
169 description
="Alpha transparency of the material",
178 specular_alpha
: FloatProperty(
179 name
="Specular alpha",
180 description
="Alpha transparency for specular areas",
189 ambient
: FloatProperty(
191 description
="Amount of global ambient color the material receives",
199 # TODO: replace by newer agnostic Material.diffuse_color and remove from pov panel
200 diffuse_color
: FloatVectorProperty(
201 name
="Diffuse color",
202 description
="Diffuse color of the material",
205 min=0, # max=inf, soft_max=1,
206 default
=(0.6, 0.6, 0.6),
207 options
={"ANIMATABLE"},
211 darkness
: FloatProperty(
213 description
="Minnaert darkness",
222 diffuse_fresnel
: FloatProperty(
223 name
="Diffuse fresnel",
224 description
="Power of Fresnel",
233 diffuse_fresnel_factor
: FloatProperty(
234 name
="Diffuse fresnel factor",
235 description
="Blending factor of Fresnel",
244 diffuse_intensity
: FloatProperty(
245 name
="Diffuse intensity",
246 description
="Amount of diffuse reflection multiplying color",
255 diffuse_ramp_blend
: EnumProperty(
256 name
="Diffuse ramp blend",
257 description
="Blending method of the ramp and the diffuse color",
261 ("MULTIPLY", "Multiply", ""),
262 ("SUBTRACT", "Subtract", ""),
263 ("SCREEN", "Screen", ""),
264 ("DIVIDE", "Divide", ""),
265 ("DIFFERENCE", "Difference", ""),
266 ("DARKEN", "Darken", ""),
267 ("LIGHTEN", "Lighten", ""),
268 ("OVERLAY", "Overlay", ""),
269 ("DODGE", "Dodge", ""),
270 ("BURN", "Burn", ""),
272 ("SATURATION", "Saturation", ""),
273 ("VALUE", "Value", ""),
274 ("COLOR", "Color", ""),
275 ("SOFT_LIGHT", "Soft light", ""),
276 ("LINEAR_LIGHT", "Linear light", ""),
281 diffuse_ramp_factor
: FloatProperty(
283 description
="Blending factor (also uses alpha in Colorband)",
292 diffuse_ramp_input
: EnumProperty(
294 description
="How the ramp maps on the surface",
296 ("SHADER", "Shader", ""),
297 ("ENERGY", "Energy", ""),
298 ("NORMAL", "Normal", ""),
299 ("RESULT", "Result", ""),
304 diffuse_shader
: EnumProperty(
305 name
="Diffuse Shader Model",
306 description
="How the ramp maps on the surface",
308 ("LAMBERT", "Lambert", "Use a Lambertian shader"),
309 ("OREN_NAYAR", "Oren-Nayar", "Use an Oren-Nayar shader"),
310 ("MINNAERT", "Minnaert", "Use a Minnaert shader"),
311 ("FRESNEL", "Fresnel", "Use a Fresnel shader"),
316 diffuse_toon_size
: FloatProperty(
318 description
="Size of diffuse toon area",
327 diffuse_toon_smooth
: FloatProperty(
329 description
="Smoothness of diffuse toon area",
340 description
="Amount of light to emit",
342 soft_min
=0.0, # max=inf, soft_max=inf,
347 mirror_color
: FloatVectorProperty(
349 description
="Mirror color of the material",
352 min=0, # max=inf, soft_max=1,
353 default
=(0.6, 0.6, 0.6),
354 options
={"ANIMATABLE"},
358 roughness
: FloatProperty(
360 description
="Oren-Nayar Roughness",
369 halo
: BoolProperty(name
="Halo", description
=" Halo settings for the material", default
=False)
370 # (was readonly in Blender2.79, never None)
372 line_color
: FloatVectorProperty(
374 description
="Line color used for Freestyle line rendering",
377 min=0, # max=inf, soft_max=1,
378 default
=(0.0, 0.0, 0.0),
379 options
={"ANIMATABLE"},
384 ## Color ramp used to affect diffuse shading
385 ## Type: ColorRamp, (readonly)
387 # cr_node = bpy.data.materials['Material'].node_tree.nodes['ColorRamp']
388 # layout.template_color_ramp(cr_node, "color_ramp", expand=True)
392 # class bpy.types.ColorRamp(bpy_struct)
394 line_priority
: IntProperty(
395 name
="Recursion Limit",
396 description
="The line color of a higher priority is used at material boundaries",
402 specular_color
: FloatVectorProperty(
403 name
="Specular color",
404 description
="Specular color of the material ",
409 default
=(1.0, 1.0, 1.0),
410 options
={"ANIMATABLE"},
413 specular_hardness
: IntProperty(
415 description
="How hard (sharp) the specular reflection is",
420 # TODO: replace by newer agnostic Material.specular_intensity and remove from pov panel
421 specular_intensity
: FloatProperty(
423 description
="How intense (bright) the specular reflection is",
432 specular_ior
: FloatProperty(
434 description
="Specular index of refraction",
445 description
="Index of refraction",
454 specular_shader
: EnumProperty(
455 name
="Specular Shader Model",
456 description
="How the ramp maps on the surface",
458 ("COOKTORR", "CookTorr", "Use a Cook-Torrance shader"),
459 ("PHONG", "Phong", "Use a Phong shader"),
460 ("BLINN", "Blinn", "Use a Blinn shader"),
461 ("TOON", "Toon", "Use a Toon shader"),
462 ("WARDISO", "WardIso", "Use a Ward anisotropic shader"),
467 specular_slope
: FloatProperty(
469 description
="The standard deviation of surface slope",
478 specular_toon_size
: FloatProperty(
480 description
="Size of specular toon area",
489 specular_toon_smooth
: FloatProperty(
491 description
="Smoothness of specular toon area",
500 translucency
: FloatProperty(
502 description
="Amount of diffuse shading on the back side",
511 transparency_method
: EnumProperty(
512 name
="Specular Shader Model",
513 description
="Method to use for rendering transparency",
515 ("MASK", "Mask", "Mask the background"),
516 ("Z_TRANSPARENCY", "Z Transparency", "Use an ior of 1 for transparent faces"),
517 ("RAYTRACE", "Raytrace", "Use raytracing for transparent refraction rendering"),
524 description
="Material type defining how the object is rendered",
526 ("SURFACE", "Surface", "Render object as a surface"),
527 # TO UPDATE > USE wire MACRO AND CHANGE DESCRIPTION
528 ("WIRE", "Wire", "Render the edges of faces as wires (not supported in raytracing)"),
529 ("VOLUME", "Volume", "Render object as a volume"),
530 # TO UPDATE > USE halo MACRO AND CHANGE DESCRIPTION
531 ("HALO", "Halo", "Render object as halo particles"),
536 use_cast_shadows
: BoolProperty(
537 name
="Cast", description
="Allow this material to cast shadows", default
=True
540 use_cast_shadows_only
: BoolProperty(
542 description
="Make objects with this material "
543 "appear invisible (not rendered), only "
548 use_cubic
: BoolProperty(
549 name
="Cubic Interpolation",
550 description
="Use cubic interpolation for diffuse " "values, for smoother transitions",
554 use_diffuse_ramp
: BoolProperty(
555 name
="Ramp", description
="Toggle diffuse ramp operations", default
=False
558 use_light_group_exclusive
: BoolProperty(
560 description
="Material uses the light group exclusively"
561 "- these lamps are excluded from other "
566 use_light_group_local
: BoolProperty(
568 description
="When linked in, material uses local light" " group with the same name",
572 use_mist
: BoolProperty(
574 description
="Use mist with this material " "(in world settings)",
578 use_nodes
: BoolProperty(
580 # Add Icon in UI or here? icon='NODES'
581 description
="Use shader nodes to render the material",
585 use_object_color
: BoolProperty(
587 description
="Modulate the result with a per-object color",
591 use_only_shadow
: BoolProperty(
593 description
="Render shadows as the material’s alpha "
594 "value, making the material transparent "
595 "except for shadowed areas",
599 use_shadeless
: BoolProperty(
601 description
="Make this material insensitive to " "light or shadow",
605 use_shadows
: BoolProperty(
606 name
="Receive", description
="Allow this material to receive shadows", default
=True
609 use_sky
: BoolProperty(
611 description
="Render this material with zero alpha, "
612 "with sky background in place (scanline only)",
616 use_specular_ramp
: BoolProperty(
617 name
="Ramp", description
="Toggle specular ramp operations", default
=False
620 use_tangent_shading
: BoolProperty(
621 name
="Tangent Shading",
622 description
="Use the material’s tangent vector instead"
623 "of the normal for shading - for "
624 "anisotropic shading effects",
628 use_transparent_shadows
: BoolProperty(
629 name
="Receive Transparent",
630 description
="Allow this object to receive transparent " "shadows cast through other object",
632 ) # linked to fake caustics
634 use_vertex_color_light
: BoolProperty(
635 name
="Vertex Color Light",
636 description
="Add vertex colors as additional lighting",
640 # TODO create interface:
641 use_vertex_color_paint
: BoolProperty(
642 name
="Vertex Color Paint",
643 description
="Replace object base color with vertex "
644 "colors (multiply with ‘texture face’ "
645 "face assigned textures)",
649 specular_ramp_blend
: EnumProperty(
650 name
="Specular ramp blend",
651 description
="Blending method of the ramp and the specular color",
655 ("MULTIPLY", "Multiply", ""),
656 ("SUBTRACT", "Subtract", ""),
657 ("SCREEN", "Screen", ""),
658 ("DIVIDE", "Divide", ""),
659 ("DIFFERENCE", "Difference", ""),
660 ("DARKEN", "Darken", ""),
661 ("LIGHTEN", "Lighten", ""),
662 ("OVERLAY", "Overlay", ""),
663 ("DODGE", "Dodge", ""),
664 ("BURN", "Burn", ""),
666 ("SATURATION", "Saturation", ""),
667 ("VALUE", "Value", ""),
668 ("COLOR", "Color", ""),
669 ("SOFT_LIGHT", "Soft light", ""),
670 ("LINEAR_LIGHT", "Linear light", ""),
675 specular_ramp_factor
: FloatProperty(
677 description
="Blending factor (also uses alpha in Colorband)",
686 specular_ramp_input
: EnumProperty(
688 description
="How the ramp maps on the surface",
690 ("SHADER", "Shader", ""),
691 ("ENERGY", "Energy", ""),
692 ("NORMAL", "Normal", ""),
693 ("RESULT", "Result", ""),
698 irid_enable
: BoolProperty(
699 name
="Iridescence coating",
700 description
="Newton's thin film interference (like an oil slick on a puddle of "
701 "water or the rainbow hues of a soap bubble.)",
705 mirror_use_IOR
: BoolProperty(
706 name
="Correct Reflection",
707 description
="Use same IOR as raytrace transparency to calculate mirror reflections. "
708 "More physically correct",
712 conserve_energy
: BoolProperty(
713 name
="Conserve Energy",
714 description
="Light transmitted is more correctly reduced by mirror reflections, "
715 "also the sum of diffuse and translucency gets reduced below one ",
719 irid_amount
: FloatProperty(
721 description
="Contribution of the iridescence effect to the overall surface color. "
722 "As a rule of thumb keep to around 0.25 (25% contribution) or less, "
723 "but experiment. If the surface is coming out too white, try lowering "
724 "the diffuse and possibly the ambient values of the surface",
732 irid_thickness
: FloatProperty(
734 description
="A very thin film will have a high frequency of color changes while a "
735 "thick film will have large areas of color",
743 irid_turbulence
: FloatProperty(
745 description
="This parameter varies the thickness",
753 interior_fade_color
: FloatVectorProperty(
754 name
="Interior Fade Color",
755 description
="Color of filtered attenuation for transparent " "materials",
761 options
={"ANIMATABLE"},
765 caustics_enable
: BoolProperty(
767 description
="use only fake refractive caustics (default) or photon based "
768 "reflective/refractive caustics",
772 fake_caustics
: BoolProperty(
773 name
="Fake Caustics",
774 description
="use only (Fast) fake refractive caustics based on transparent shadows",
778 fake_caustics_power
: FloatProperty(
779 name
="Fake caustics power",
780 description
="Values typically range from 0.0 to 1.0 or higher. Zero is no caustics. "
781 "Low, non-zero values give broad hot-spots while higher values give "
782 "tighter, smaller simulated focal points",
790 refraction_caustics
: BoolProperty(
791 name
="Refractive Caustics",
792 description
="hotspots of light focused when going through the material",
796 photons_dispersion
: FloatProperty(
797 name
="Chromatic Dispersion",
798 description
="Light passing through will be separated according to wavelength. "
799 "This ratio of refractive indices for violet to red controls how much "
800 "the colors are spread out 1 = no dispersion, good values are 1.01 to 1.1",
809 photons_dispersion_samples
: IntProperty(
810 name
="Dispersion Samples",
811 description
="Number of color-steps for dispersion",
817 photons_reflection
: BoolProperty(
818 name
="Reflective Photon Caustics",
819 description
="Use this to make your Sauron's ring ;-P",
823 refraction_type
: EnumProperty(
825 ("1", "Z Transparency Fake Caustics", "use fake caustics"),
826 ("2", "Raytrace Photons Caustics", "use photons for refractive caustics"),
828 name
="Refraction Type:",
829 description
="use fake caustics (fast) or true photons for refractive Caustics",
833 # ------------------------------ CustomPOV Code ------------------------------ #
834 replacement_text
: StringProperty(
835 name
="Declared name:",
836 description
="Type the variable name as declared either directly inlined "
837 "in your custom POV code from the text editor datablock (checked as a "
838 "source to render in it's side property panel), or this declaration can be "
839 "from an external .inc it points at. Here, name = texture {} expected",
845 def use_material_nodes_callback(self
, context
):
846 """Identify if node has been added and if it is used yet or default"""
848 if hasattr(context
.space_data
, "tree_type"):
849 context
.space_data
.tree_type
= "ObjectNodeTree"
850 mat
= context
.object.active_material
851 if mat
.pov
.material_use_nodes
:
854 # tree.name = mat.name # XXX READONLY
857 if len(tree
.nodes
) == 2:
860 for node
in tree
.nodes
:
861 if node
.type in {"OUTPUT", "MATERIAL"}:
862 tree
.nodes
.remove(node
)
864 for node
in tree
.nodes
:
865 if node
.bl_idname
== "PovrayOutputNode":
867 elif node
.bl_idname
== "PovrayTextureNode":
869 if o
== 1 and m
== 1:
871 elif len(tree
.nodes
) == 0:
876 output
= tree
.nodes
.new("PovrayOutputNode")
877 output
.location
= 200, 200
878 tmap
= tree
.nodes
.new("PovrayTextureNode")
879 tmap
.location
= 0, 200
880 links
.new(tmap
.outputs
[0], output
.inputs
[0])
882 tree
.nodes
.active
= tmap
884 mat
.use_nodes
= False
886 def use_texture_nodes_callback(self
, context
):
887 """Identify texture nodes by filtering out output and composite ones"""
889 tex
= context
.object.active_material
.active_texture
890 if tex
.pov
.texture_use_nodes
:
892 if len(tex
.node_tree
.nodes
) == 2:
893 for node
in tex
.node_tree
.nodes
:
894 if node
.type in {"OUTPUT", "CHECKER"}:
895 tex
.node_tree
.nodes
.remove(node
)
897 tex
.use_nodes
= False
899 def node_active_callback(self
, context
):
900 """Synchronize active node with material before getting it"""
902 items
= [] # XXX comment out > remove?
903 mat
= context
.material
904 mat
.node_tree
.nodes
# XXX comment out > remove?
905 for node
in mat
.node_tree
.nodes
:
907 for node
in mat
.node_tree
.nodes
:
908 if node
.name
== mat
.pov
.material_active_node
:
910 mat
.node_tree
.nodes
.active
= node
914 def node_enum_callback(self
, context
):
915 mat
= context
.material
916 nodes
= mat
.node_tree
.nodes
917 return [("%s" % node
.name
, "%s" % node
.name
, "") for node
in nodes
]
919 def pigment_normal_callback(self
, context
):
920 render
= context
.scene
.pov
.render
# XXX comment out > remove?
922 [("pigment", "Pigment", ""), ("normal", "Normal", "")]
923 # XXX Find any other such traces of hgpovray experiment > remove or deploy ?
924 if render
!= "hgpovray"
926 ("pigment", "Pigment", ""),
927 ("normal", "Normal", ""),
928 ("modulation", "Modulation", ""),
932 def glow_callback(self
, context
):
933 scene
= context
.scene
935 ob
.pov
.mesh_write_as_old
= ob
.pov
.mesh_write_as
936 if scene
.pov
.render
== "uberpov" and ob
.pov
.glow
:
937 ob
.pov
.mesh_write_as
= "NONE"
939 ob
.pov
.mesh_write_as
= ob
.pov
.mesh_write_as_old
941 material_use_nodes
: BoolProperty(
942 name
="Use nodes", description
="", update
=use_material_nodes_callback
, default
=False
945 material_active_node
: EnumProperty(
946 name
="Active node", description
="", items
=node_enum_callback
, update
=node_active_callback
949 preview_settings
: BoolProperty(name
="Preview Settings", description
="", default
=False)
951 object_preview_transform
: BoolProperty(name
="Transform object", description
="", default
=False)
953 object_preview_scale
: FloatProperty(name
="XYZ", min=0.5, max=2.0, default
=1.0)
955 object_preview_rotate
: FloatVectorProperty(
956 name
="Rotate", description
="", min=-180.0, max=180.0, default
=(0.0, 0.0, 0.0), subtype
="XYZ"
959 object_preview_bgcontrast
: FloatProperty(name
="Contrast", min=0.0, max=1.0, default
=0.5)
963 # ------------------------------ End Old Blender Internal Props ------------------------------ #
967 RenderPovSettingsMaterial
,
975 bpy
.types
.Material
.pov
= PointerProperty(type=RenderPovSettingsMaterial
)
979 del bpy
.types
.Material
.pov
981 for cls
in reversed(classes
):
982 unregister_class(cls
)