diff options
Diffstat (limited to 'render_povray/shading.py')
-rw-r--r-- | render_povray/shading.py | 231 |
1 files changed, 231 insertions, 0 deletions
diff --git a/render_povray/shading.py b/render_povray/shading.py new file mode 100644 index 00000000..d882bfec --- /dev/null +++ b/render_povray/shading.py @@ -0,0 +1,231 @@ +# For BI > POV shaders emulation +import bpy + +def writeMaterial(DEF_MAT_NAME, scene, tabWrite, safety, comments, uniqueName, materialNames, material): + # Assumes only called once on each material + if material: + name_orig = material.name + name = materialNames[name_orig] = uniqueName(bpy.path.clean_name(name_orig), materialNames) + else: + name = name_orig = DEF_MAT_NAME + + + if material: + # If saturation(.s) is not zero, then color is not grey, and has a tint + colored_specular_found = (material.specular_color.s > 0.0) + + ################## + # Several versions of the finish: Level conditions are variations for specular/Mirror + # texture channel map with alternative finish of 0 specular and no mirror reflection. + # Level=1 Means No specular nor Mirror reflection + # Level=2 Means translation of spec and mir levels for when no map influences them + # Level=3 Means Maximum Spec and Mirror + + def povHasnoSpecularMaps(Level): + if Level == 1: + tabWrite("#declare %s = finish {" % safety(name, Level=1)) + if comments: + file.write(" //No specular nor Mirror reflection\n") + else: + tabWrite("\n") + elif Level == 2: + tabWrite("#declare %s = finish {" % safety(name, Level=2)) + if comments: + file.write(" //translation of spec and mir levels for when no map " \ + "influences them\n") + else: + tabWrite("\n") + elif Level == 3: + tabWrite("#declare %s = finish {" % safety(name, Level=3)) + if comments: + file.write(" //Maximum Spec and Mirror\n") + else: + tabWrite("\n") + + if material: + # POV-Ray 3.7 now uses two diffuse values respectively for front and back shading + # (the back diffuse is like blender translucency) + frontDiffuse = material.diffuse_intensity + backDiffuse = material.translucency + + if material.pov.conserve_energy: + + #Total should not go above one + if (frontDiffuse + backDiffuse) <= 1.0: + pass + elif frontDiffuse == backDiffuse: + # Try to respect the user's 'intention' by comparing the two values but + # bringing the total back to one. + frontDiffuse = backDiffuse = 0.5 + # Let the highest value stay the highest value. + elif frontDiffuse > backDiffuse: + # clamps the sum below 1 + backDiffuse = min(backDiffuse, (1.0 - frontDiffuse)) + else: + frontDiffuse = min(frontDiffuse, (1.0 - backDiffuse)) + + # map hardness between 0.0 and 1.0 + roughness = ((1.0 - ((material.specular_hardness - 1.0) / 510.0))) + ## scale from 0.0 to 0.1 + roughness *= 0.1 + # add a small value because 0.0 is invalid. + roughness += (1.0 / 511.0) + + ################################Diffuse Shader###################################### + # Not used for Full spec (Level=3) of the shader. + if material.diffuse_shader == 'OREN_NAYAR' and Level != 3: + # Blender roughness is what is generally called oren nayar Sigma, + # and brilliance in POV-Ray. + tabWrite("brilliance %.3g\n" % (0.9 + material.roughness)) + + if material.diffuse_shader == 'TOON' and Level != 3: + tabWrite("brilliance %.3g\n" % (0.01 + material.diffuse_toon_smooth * 0.25)) + # Lower diffuse and increase specular for toon effect seems to look better + # in POV-Ray. + frontDiffuse *= 0.5 + + if material.diffuse_shader == 'MINNAERT' and Level != 3: + #tabWrite("aoi %.3g\n" % material.darkness) + pass # let's keep things simple for now + if material.diffuse_shader == 'FRESNEL' and Level != 3: + #tabWrite("aoi %.3g\n" % material.diffuse_fresnel_factor) + pass # let's keep things simple for now + if material.diffuse_shader == 'LAMBERT' and Level != 3: + # trying to best match lambert attenuation by that constant brilliance value + tabWrite("brilliance 1.8\n") + + if Level == 2: + ###########################Specular Shader###################################### + # No difference between phong and cook torrence in blender HaHa! + if (material.specular_shader == 'COOKTORR' or + material.specular_shader == 'PHONG'): + tabWrite("phong %.3g\n" % (material.specular_intensity)) + tabWrite("phong_size %.3g\n" % (material.specular_hardness / 2 + 0.25)) + + # POV-Ray 'specular' keyword corresponds to a Blinn model, without the ior. + elif material.specular_shader == 'BLINN': + # Use blender Blinn's IOR just as some factor for spec intensity + tabWrite("specular %.3g\n" % (material.specular_intensity * + (material.specular_ior / 4.0))) + tabWrite("roughness %.3g\n" % roughness) + #Could use brilliance 2(or varying around 2 depending on ior or factor) too. + + elif material.specular_shader == 'TOON': + tabWrite("phong %.3g\n" % (material.specular_intensity * 2.0)) + # use extreme phong_size + tabWrite("phong_size %.3g\n" % (0.1 + material.specular_toon_smooth / 2.0)) + + elif material.specular_shader == 'WARDISO': + # find best suited default constant for brilliance Use both phong and + # specular for some values. + tabWrite("specular %.3g\n" % (material.specular_intensity / + (material.specular_slope + 0.0005))) + # find best suited default constant for brilliance Use both phong and + # specular for some values. + tabWrite("roughness %.4g\n" % (0.0005 + material.specular_slope / 10.0)) + # find best suited default constant for brilliance Use both phong and + # specular for some values. + tabWrite("brilliance %.4g\n" % (1.8 - material.specular_slope * 1.8)) + + #################################################################################### + elif Level == 1: + tabWrite("specular 0\n") + elif Level == 3: + tabWrite("specular 1\n") + tabWrite("diffuse %.3g %.3g\n" % (frontDiffuse, backDiffuse)) + + tabWrite("ambient %.3g\n" % material.ambient) + # POV-Ray blends the global value + #tabWrite("ambient rgb <%.3g, %.3g, %.3g>\n" % \ + # tuple([c*material.ambient for c in world.ambient_color])) + tabWrite("emission %.3g\n" % material.emit) # New in POV-Ray 3.7 + + #POV-Ray just ignores roughness if there's no specular keyword + #tabWrite("roughness %.3g\n" % roughness) + + if material.pov.conserve_energy: + # added for more realistic shading. Needs some checking to see if it + # really works. --Maurice. + tabWrite("conserve_energy\n") + + if colored_specular_found == True: + tabWrite("metallic\n") + + # 'phong 70.0 ' + if Level != 1: + if material.raytrace_mirror.use: + raytrace_mirror = material.raytrace_mirror + if raytrace_mirror.reflect_factor: + tabWrite("reflection {\n") + tabWrite("rgb <%.3g, %.3g, %.3g>\n" % material.mirror_color[:]) + if material.pov.mirror_metallic: + tabWrite("metallic %.3g\n" % (raytrace_mirror.reflect_factor)) + # Blurry reflections for UberPOV + if using_uberpov and raytrace_mirror.gloss_factor < 1.0: + #tabWrite("#ifdef(unofficial) #if(unofficial = \"patch\") #if(patch(\"upov-reflection-roughness\") > 0)\n") + tabWrite("roughness %.6f\n" % \ + (0.000001/raytrace_mirror.gloss_factor)) + #tabWrite("#end #end #end\n") # This and previous comment for backward compatibility, messier pov code + if material.pov.mirror_use_IOR: # WORKING ? + # Removed from the line below: gives a more physically correct + # material but needs proper IOR. --Maurice + tabWrite("fresnel 1 ") + tabWrite("falloff %.3g exponent %.3g} " % \ + (raytrace_mirror.fresnel, raytrace_mirror.fresnel_factor)) + + if material.subsurface_scattering.use: + subsurface_scattering = material.subsurface_scattering + tabWrite("subsurface { translucency <%.3g, %.3g, %.3g> }\n" % ( + (subsurface_scattering.radius[0]), + (subsurface_scattering.radius[1]), + (subsurface_scattering.radius[2]), + ) + ) + + if material.pov.irid_enable: + tabWrite("irid { %.4g thickness %.4g turbulence %.4g }" % \ + (material.pov.irid_amount, material.pov.irid_thickness, + material.pov.irid_turbulence)) + + else: + tabWrite("diffuse 0.8\n") + tabWrite("phong 70.0\n") + + #tabWrite("specular 0.2\n") + + # This is written into the object + ''' + if material and material.transparency_method=='RAYTRACE': + 'interior { ior %.3g} ' % material.raytrace_transparency.ior + ''' + + #tabWrite("crand 1.0\n") # Sand granyness + #tabWrite("metallic %.6f\n" % material.spec) + #tabWrite("phong %.6f\n" % material.spec) + #tabWrite("phong_size %.6f\n" % material.spec) + #tabWrite("brilliance %.6f " % (material.specular_hardness/256.0) # Like hardness + + tabWrite("}\n\n") + + # Level=2 Means translation of spec and mir levels for when no map influences them + povHasnoSpecularMaps(Level=2) + + if material: + special_texture_found = False + for t in material.texture_slots: + if t and t.use: + if (t.texture.type == 'IMAGE' and t.texture.image) or t.texture.type != 'IMAGE': + validPath=True + else: + validPath=False + if(t and t.use and validPath and + (t.use_map_specular or t.use_map_raymir or t.use_map_normal or t.use_map_alpha)): + special_texture_found = True + continue # Some texture found + + if special_texture_found or colored_specular_found: + # Level=1 Means No specular nor Mirror reflection + povHasnoSpecularMaps(Level=1) + + # Level=3 Means Maximum Spec and Mirror + povHasnoSpecularMaps(Level=3) |