Skip to content
Snippets Groups Projects
shading.py 97.5 KiB
Newer Older
# ***** BEGIN GPL LICENSE BLOCK *****
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software Foundation,
# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
# #**** END GPL LICENSE BLOCK #****

# <pep8 compliant>

Maurice Raybaud's avatar
Maurice Raybaud committed
"""Translate complex shaders to exported POV textures."""

Maurice Raybaud's avatar
Maurice Raybaud committed
def writeMaterial(using_uberpov, DEF_MAT_NAME, scene, tabWrite, safety, comments, uniqueName, materialNames, material):
Maurice Raybaud's avatar
Maurice Raybaud committed
    """Translate Blender material POV texture{} block and write to exported file."""
    # 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.pov.specular_color.s > 0.0) and (material.pov.diffuse_shader != 'MINNAERT'))

    ##################
    # 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):
Maurice Raybaud's avatar
Maurice Raybaud committed
        """Translate Blender specular map influence to POV finish map trick and write to file."""
Maurice Raybaud's avatar
Maurice Raybaud committed
                tabWrite("//--No specular nor Mirror reflection--\n")
Maurice Raybaud's avatar
Maurice Raybaud committed
            tabWrite("#declare %s = finish {\n" % safety(name, Level=1))
Maurice Raybaud's avatar
Maurice Raybaud committed
                tabWrite("//--translation of spec and mir levels for when no map " \
                           "influences them--\n")
Maurice Raybaud's avatar
Maurice Raybaud committed
            tabWrite("#declare %s = finish {\n" % safety(name, Level=2))

Maurice Raybaud's avatar
Maurice Raybaud committed
                tabWrite("//--Maximum Spec and Mirror--\n")
Maurice Raybaud's avatar
Maurice Raybaud committed
            tabWrite("#declare %s = finish {\n" % safety(name, Level=3))
        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.pov.diffuse_intensity
            backDiffuse = material.pov.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.pov.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.pov.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.pov.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.pov.diffuse_shader == 'MINNAERT' and Level != 3:
                #tabWrite("aoi %.3g\n" % material.darkness)
                pass  # let's keep things simple for now
            if material.pov.diffuse_shader == 'FRESNEL' and Level != 3:
                #tabWrite("aoi %.3g\n" % material.diffuse_fresnel_factor)
                pass  # let's keep things simple for now
            if material.pov.diffuse_shader == 'LAMBERT' and Level != 3:
                # trying to best match lambert attenuation by that constant brilliance value
                tabWrite("brilliance 1\n")

            if Level == 2:
                ###########################Specular Shader######################################
                # No difference between phong and cook torrence in blender HaHa!
                if (material.pov.specular_shader == 'COOKTORR' or
                    material.pov.specular_shader == 'PHONG'):
                    tabWrite("phong %.3g\n" % (material.pov.specular_intensity))
                    tabWrite("phong_size %.3g\n" % (material.pov.specular_hardness /3.14))

                # POV-Ray 'specular' keyword corresponds to a Blinn model, without the ior.
                elif material.pov.specular_shader == 'BLINN':
                    # Use blender Blinn's IOR just as some factor for spec intensity
                    tabWrite("specular %.3g\n" % (material.pov.specular_intensity *
                                                  (material.pov.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.pov.specular_shader == 'TOON':
                    tabWrite("phong %.3g\n" % (material.pov.specular_intensity * 2.0))
                    tabWrite("phong_size %.3g\n" % (0.1 + material.pov.specular_toon_smooth / 2.0))
                elif material.pov.specular_shader == 'WARDISO':
                    # find best suited default constant for brilliance Use both phong and
                    # specular for some values.
                    tabWrite("specular %.3g\n" % (material.pov.specular_intensity /
                                                  (material.pov.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.pov.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.pov.specular_slope * 1.8))

            ####################################################################################
            elif Level == 1:
                if (material.pov.specular_shader == 'COOKTORR' or
                    material.pov.specular_shader == 'PHONG'):
                    tabWrite("phong 0\n")#%.3g\n" % (material.pov.specular_intensity/5))
                    tabWrite("phong_size %.3g\n" % (material.pov.specular_hardness /3.14))

                # POV-Ray 'specular' keyword corresponds to a Blinn model, without the ior.
                elif material.pov.specular_shader == 'BLINN':
                    # Use blender Blinn's IOR just as some factor for spec intensity
                    tabWrite("specular %.3g\n" % (material.pov.specular_intensity *
                                                  (material.pov.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.pov.specular_shader == 'TOON':
                    tabWrite("phong %.3g\n" % (material.pov.specular_intensity * 2.0))
                    # use extreme phong_size
                    tabWrite("phong_size %.3g\n" % (0.1 + material.pov.specular_toon_smooth / 2.0))
                elif material.pov.specular_shader == 'WARDISO':
                    # find best suited default constant for brilliance Use both phong and
                    # specular for some values.
                    tabWrite("specular %.3g\n" % (material.pov.specular_intensity /
                                                  (material.pov.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.pov.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.pov.specular_slope * 1.8))
                # Spec must be Max at Level 3 so that white of mixing texture always shows specularity
                # That's why it's multiplied by 255. maybe replace by texture's brightest pixel value?
                tabWrite("specular %.3g\n" % ((material.pov.specular_intensity*material.pov.specular_color.v)*(255* slot.specular_factor)))
                tabWrite("roughness %.3g\n" % (1/material.pov.specular_hardness))
            tabWrite("diffuse %.3g %.3g\n" % (frontDiffuse, backDiffuse))

            tabWrite("ambient %.3g\n" % material.pov.ambient)
            # POV-Ray blends the global value
            #tabWrite("ambient rgb <%.3g, %.3g, %.3g>\n" % \
            #         tuple([c*material.pov.ambient for c in world.ambient_color]))
            tabWrite("emission %.3g\n" % material.pov.emit)  # New in POV-Ray 3.7

            #POV-Ray just ignores roughness if there's no specular keyword
            #tabWrite("roughness %.3g\n" % roughness)

Loading
Loading full blame...