diff --git a/render_povray/__init__.py b/render_povray/__init__.py index 3eb7522e5eaf04b07703eabd1af27f1ac077205c..1606535c2672c48f6d78fcfb47cb75ebc45c1491 100644 --- a/render_povray/__init__.py +++ b/render_povray/__init__.py @@ -71,6 +71,10 @@ def register(): default=False) # Real pov options + Scene.pov_max_trace_level = IntProperty( + name="Max Trace Level", description="Number of reflections/refractions allowed on ray path", + min=1, max=256, default=5) + Scene.pov_radio_adc_bailout = FloatProperty( name="ADC Bailout", description="The adc_bailout for radiosity rays. Use adc_bailout = 0.01 / brightest_ambient_object for good results", min=0.0, max=1000.0, soft_min=0.0, soft_max=1.0, default=0.01) @@ -84,8 +88,8 @@ def register(): min=0.0, max=1000.0, soft_min=0.0, soft_max=10.0, default=1.0) Scene.pov_radio_count = IntProperty( - name="Ray Count", description="Number of rays that are sent out whenever a new radiosity value has to be calculated", - min=1, max=1600, default=35) + name="Ray Count", description="Number of rays for each new radiosity value to be calculated (halton sequence over 1600)", + min=1, max=10000, soft_max=1600, default=35) Scene.pov_radio_error_bound = FloatProperty( name="Error Bound", description="One of the two main speed/quality tuning values, lower values are more accurate", @@ -96,7 +100,7 @@ def register(): min=0.0, max=1.0, soft_min=0, soft_max=1, default=0.0) Scene.pov_radio_low_error_factor = FloatProperty( - name="Low Error Factor", description="If you calculate just enough samples, but no more, you will get an image which has slightly blotchy lighting", + name="Low Error Factor", description="Just enough samples is slightly blotchy. Low error changes error tolerance for less critical last refining pass", min=0.0, max=1.0, soft_min=0.0, soft_max=1.0, default=0.5) # max_sample - not available yet @@ -120,6 +124,14 @@ def register(): name="Recursion Limit", description="how many recursion levels are used to calculate the diffuse inter-reflection", min=1, max=20, default=3) + Scene.pov_radio_pretrace_start = FloatProperty( + name="Pretrace Start", description="Fraction of the screen width which sets the size of the blocks in the mosaic preview first pass", + min=0.01, max=1.00, soft_min=0.02, soft_max=1.0, default=0.08) + + Scene.pov_radio_pretrace_end = FloatProperty( + name="Pretrace End", description="Fraction of the screen width which sets the size of the blocks in the mosaic preview last pass", + min=0.01, max=1.00, soft_min=0.02, soft_max=1.0, default=0.04) + ########################################MR###################################### Mat = bpy.types.Material @@ -208,6 +220,13 @@ def register(): name="Custom texture gamma", description="value for which the file was issued e.g. a Raw photo is gamma 1.0", min=0.45, max=5.00, soft_min=1.00, soft_max=2.50, default=1.00) + + #Importance sampling + Obj = bpy.types.Object + Obj.pov_importance_value = FloatProperty( + name="Radiosity Importance", + description="Priority value relative to other objects for sampling radiosity rays. Increase to get more radiosity rays at comparatively small yet bright objects", + min=0.01, max=1.00, default=1.00) ######################################EndMR##################################### @@ -216,6 +235,7 @@ def unregister(): Scene = bpy.types.Scene Mat = bpy.types.Material # MR Tex = bpy.types.Texture # MR + Obj = bpy.types.Object # MR del Scene.pov_radio_enable del Scene.pov_radio_display_advanced del Scene.pov_radio_adc_bailout @@ -230,10 +250,13 @@ def unregister(): del Scene.pov_radio_nearest_count del Scene.pov_radio_normal del Scene.pov_radio_recursion_limit + del Scene.pov_radio_pretrace_start # MR + del Scene.pov_radio_pretrace_end # MR del Scene.pov_media_enable # MR del Scene.pov_media_samples # MR del Scene.pov_media_color # MR del Scene.pov_baking_enable # MR + del Scene.pov_max_trace_level # MR del Mat.pov_irid_enable # MR del Mat.pov_mirror_use_IOR # MR del Mat.pov_mirror_metallic # MR @@ -250,6 +273,7 @@ def unregister(): del Mat.pov_refraction_type # MR del Tex.pov_tex_gamma_enable # MR del Tex.pov_tex_gamma_value # MR + del Obj.pov_importance_value # MR if __name__ == "__main__": register() diff --git a/render_povray/render.py b/render_povray/render.py index bcd95f6d5563cf5fa19643c1b6ab99a8c31e01fb..ae3921c8a727ccf7bbd94055f67b7fff018c4e69 100644 --- a/render_povray/render.py +++ b/render_povray/render.py @@ -545,6 +545,7 @@ def write_pov(filename, scene=None, info_callback=None): for ob in metas: meta = ob.data + importance=ob.pov_importance_value file.write('blob {\n') file.write('\t\tthreshold %.4g\n' % meta.threshold) @@ -597,6 +598,10 @@ def write_pov(filename, scene=None, info_callback=None): writeObjectMaterial(material) writeMatrix(global_matrix * ob.matrix_world) + #Importance for radiosity sampling added here: + file.write('\tradiosity { importance %3g }\n' % importance) + + file.write('}\n') #End of Metaball block file.write('}\n') @@ -620,6 +625,7 @@ def write_pov(filename, scene=None, info_callback=None): continue me = ob.data + importance=ob.pov_importance_value me_materials = me.materials me = ob.create_mesh(scene, True, 'RENDER') @@ -1073,7 +1079,11 @@ def write_pov(filename, scene=None, info_callback=None): print(me) writeMatrix(matrix) - file.write('}\n') + + #Importance for radiosity sampling added here: + file.write('\tradiosity { importance %3g }\n' % importance) + + file.write('}\n') # End of mesh block file.write('%s\n' % name) # Use named declaration to allow reference e.g. for baking. MR bpy.data.meshes.remove(me) @@ -1100,9 +1110,10 @@ def write_pov(filename, scene=None, info_callback=None): file.write('background {rgbt<%.3g, %.3g, %.3g, 1>}\n' % (tuple(world.horizon_color))) - + worldTexCount=0 #For Background image textures for t in world.texture_slots: #risk to write several sky_spheres but maybe ok. + worldTexCount+=1 if t and t.texture.type == 'IMAGE': #and t.use: #No enable checkbox for world textures yet (report it?) image_filename = path_image(t.texture.image.filepath) if t.texture.image.filepath != image_filename: t.texture.image.filepath = image_filename @@ -1113,7 +1124,11 @@ def write_pov(filename, scene=None, info_callback=None): #commented below was an idea to make the Background image oriented as camera taken here: http://news.povray.org/povray.newusers/thread/%3Cweb.4a5cddf4e9c9822ba2f93e20@news.povray.org%3E/ #mappingBlend = (" translate <%.4g,%.4g,%.4g> rotate z*degrees(atan((camLocation - camLookAt).x/(camLocation - camLookAt).y)) rotate x*degrees(atan((camLocation - camLookAt).y/(camLocation - camLookAt).z)) rotate y*degrees(atan((camLocation - camLookAt).z/(camLocation - camLookAt).x)) scale <%.4g,%.4g,%.4g>b" % (t_blend.offset.x / 10 ,t_blend.offset.y / 10 ,t_blend.offset.z / 10, t_blend.scale.x ,t_blend.scale.y ,t_blend.scale.z))#replace 4/3 by the ratio of each image found by some custom or existing function #using camera rotation valuesdirectly from blender seems much easier - mappingBlend = (" translate <%.4g-0.5,%.4g-0.5,%.4g-0.5> rotate<%.4g,%.4g,%.4g> scale <%.4g,%.4g,%.4g>" % (t_blend.offset.x / 10 ,t_blend.offset.y / 10 ,t_blend.offset.z / 10, degrees(camera.rotation_euler[0]), degrees(camera.rotation_euler[1]), degrees(camera.rotation_euler[2]), t_blend.scale.x*0.85 , t_blend.scale.y*0.85 , t_blend.scale.z*0.85 )) + if t_blend.texture_coords!='ANGMAP': + mappingBlend = (" translate <%.4g-0.5,%.4g-0.5,%.4g-0.5> rotate<0,0,0> scale <%.4g,%.4g,%.4g>" % (t_blend.offset.x / 10 ,t_blend.offset.y / 10 ,t_blend.offset.z / 10, t_blend.scale.x*0.85 , t_blend.scale.y*0.85 , t_blend.scale.z*0.85 )) + #The initial position and rotation of the pov camera is probably creating the rotation offset should look into it someday but at least background won't rotate with the camera now. + else: + mappingBlend = ("") #Putting the map on a plane would not introduce the skysphere distortion and allow for better image scale matching but also some waay to chose depth and size of the plane relative to camera. file.write('sky_sphere {\n') file.write('\tpigment {\n') @@ -1124,11 +1139,11 @@ def write_pov(filename, scene=None, info_callback=None): #For only Background gradient - if not t: + if worldTexCount==0: if world.use_sky_blend: file.write('sky_sphere {\n') file.write('\tpigment {\n') - file.write('\t\tgradient z\n')#maybe Should follow the advice of POV doc about replacing gradient for skysphere..5.5 + file.write('\t\tgradient y\n')#maybe Should follow the advice of POV doc about replacing gradient for skysphere..5.5 file.write('\t\tcolor_map {\n') if render.alpha_mode == 'STRAIGHT': file.write('\t\t\t[0.0 rgbt<%.3g, %.3g, %.3g, 1>]\n' % (tuple(world.horizon_color))) @@ -1174,7 +1189,7 @@ def write_pov(filename, scene=None, info_callback=None): file.write('global_settings {\n') file.write('\tassumed_gamma 1.0\n') - file.write('\tmax_trace_level 7\n') + file.write('\tmax_trace_level %d\n' % scene.pov_max_trace_level) if scene.pov_radio_enable: file.write('\tradiosity {\n') @@ -1189,6 +1204,8 @@ def write_pov(filename, scene=None, info_callback=None): file.write("\t\tminimum_reuse %.4g\n" % scene.pov_radio_minimum_reuse) file.write("\t\tnearest_count %d\n" % scene.pov_radio_nearest_count) file.write("\t\tnormal %d\n" % scene.pov_radio_normal) + file.write("\t\tpretrace_start %.3g\n" % scene.pov_radio_pretrace_start) + file.write("\t\tpretrace_end %.3g\n" % scene.pov_radio_pretrace_end) file.write("\t\trecursion_limit %d\n" % scene.pov_radio_recursion_limit) file.write('\t}\n') once=1 @@ -1203,7 +1220,7 @@ def write_pov(filename, scene=None, info_callback=None): if material.pov_photons_refraction or material.pov_photons_reflection: file.write("\tphotons {\n") file.write("\t\tspacing 0.003\n") - file.write("\t\tmax_trace_level 4\n") + file.write("\t\tmax_trace_level 5\n") file.write("\t\tadc_bailout 0.1\n") file.write("\t\tgather 30, 150\n") @@ -1266,7 +1283,7 @@ def write_pov_ini(filename_ini, filename_pov, filename_image): if render.use_antialiasing: aa_mapping = {'5': 2, '8': 3, '11': 4, '16': 5} # method 2 (recursive) with higher max subdiv forced because no mipmapping in povray needs higher sampling. - file.write('Antialias=1\n') + file.write('Antialias=on\n') file.write('Sampling_Method=2\n') file.write('Antialias_Depth=%d\n' % aa_mapping[render.antialiasing_samples]) file.write('Antialias_Threshold=0.1\n')#rather high settings but necessary. diff --git a/render_povray/ui.py b/render_povray/ui.py index 95dc5e37816ee789dc278b2cfe1d13ba0f3a83eb..9046b44e45258197f2349c616ff0bac13561c2be 100644 --- a/render_povray/ui.py +++ b/render_povray/ui.py @@ -117,6 +117,18 @@ class TextureButtonsPanel(): tex = context.texture rd = context.scene.render return tex and (rd.use_game_engine == False) and (rd.engine in cls.COMPAT_ENGINES) + +class ObjectButtonsPanel(): + bl_space_type = 'PROPERTIES' + bl_region_type = 'WINDOW' + bl_context = "object" + # COMPAT_ENGINES must be defined in each subclass, external engines can add themselves here + + @classmethod + def poll(cls, context): + obj = context.object + rd = context.scene.render + return obj and (rd.use_game_engine == False) and (rd.engine in cls.COMPAT_ENGINES) ########################################MR###################################### class MATERIAL_PT_povray_mirrorIOR(MaterialButtonsPanel, bpy.types.Panel): bl_label = "IOR Mirror" @@ -249,6 +261,21 @@ class MATERIAL_PT_povray_caustics(MaterialButtonsPanel, bpy.types.Panel): ## col.prop(mat, "pov_photons_reflection") ####TODO : MAKE THIS A real RADIO BUTTON (using EnumProperty?) ######################################EndMR##################################### +class RENDER_PT_povray_max_trace_level(RenderButtonsPanel, bpy.types.Panel): + bl_label = "Global Settings" + COMPAT_ENGINES = {'POVRAY_RENDER'} + + def draw(self, context): + layout = self.layout + + scene = context.scene + rd = scene.render + + layout.active = scene.pov_max_trace_level + split = layout.split() + + col = split.column() + col.prop(scene, "pov_max_trace_level", text="Ray Depth") class RENDER_PT_povray_radiosity(RenderButtonsPanel, bpy.types.Panel): bl_label = "Radiosity" @@ -284,11 +311,13 @@ class RENDER_PT_povray_radiosity(RenderButtonsPanel, bpy.types.Panel): col.prop(scene, "pov_radio_adc_bailout", slider=True) col.prop(scene, "pov_radio_gray_threshold", slider=True) col.prop(scene, "pov_radio_low_error_factor", slider=True) + col.prop(scene, "pov_radio_pretrace_start", slider=True) col = split.column() col.prop(scene, "pov_radio_brightness") col.prop(scene, "pov_radio_minimum_reuse", text="Min Reuse") col.prop(scene, "pov_radio_nearest_count") + col.prop(scene, "pov_radio_pretrace_end", slider=True) split = layout.split() @@ -359,4 +388,19 @@ class TEXTURE_PT_povray_tex_gamma(TextureButtonsPanel, bpy.types.Panel): col = split.column() col.prop(tex, "pov_tex_gamma_value", text="Gamma Value") + +class OBJECT_PT_povray_obj_importance(ObjectButtonsPanel, bpy.types.Panel): + bl_label = "POV-Ray" + COMPAT_ENGINES = {'POVRAY_RENDER'} + + def draw(self, context): + layout = self.layout + + obj = context.object + + layout.active = obj.pov_importance_value + split = layout.split() + + col = split.column() + col.prop(obj, "pov_importance_value", text="Importance")