Squashed commit of the following:
authorPascal Schoen <pascal.schoen@adidas-group.com>
Tue, 18 Apr 2017 09:43:09 +0000 (11:43 +0200)
committerPascal Schoen <pascal.schoen@adidas-group.com>
Tue, 18 Apr 2017 09:43:09 +0000 (11:43 +0200)
commit 90778901c9ea1e16d5907981e91bceba25ff207d
Merge: 76eebd9 3bf0026
Author: Schoen <schoepas@deher1m1598.emea.adsint.biz>
Date:   Mon Apr 3 07:52:05 2017 +0200

    Merge branch 'master' into cycles_disney_brdf

commit 76eebd9379a5dad519ff01cf215fbe3db6de931e
Author: Schoen <schoepas@deher1m1598.emea.adsint.biz>
Date:   Thu Mar 30 15:34:20 2017 +0200

    Updated copyright for the new files.

commit 013f4a152a3898946ba5c616141c6e44d928ccfd
Author: Schoen <schoepas@deher1m1598.emea.adsint.biz>
Date:   Thu Mar 30 15:32:55 2017 +0200

    Switched from multiplication of base and subsurface color to blending
    between them using the subsurface parameter.

commit 482ec5d1f20ceabc9cbda4838d4ae37d1d673458
Author: Schoen <schoepas@deher1m1598.emea.adsint.biz>
Date:   Mon Mar 13 15:47:12 2017 +0100

    Fixed a bug that caused an additional white diffuse closure call when using
    path tracing.

commit 26e906d162a6a8d67f2ebc8880993fcbab69559e
Merge: 0593b8c 223aff9
Author: Pascal Schoen <pascal_schoen@gmx.net>
Date:   Mon Feb 6 11:32:31 2017 +0100

    Merge branch 'master' into cycles_disney_brdf

commit 0593b8c51bf7db0ed5ca92ed6f68d0d984dad0dd
Author: Pascal Schoen <pascal_schoen@gmx.net>
Date:   Mon Feb 6 11:30:36 2017 +0100

    Fixed the broken GLSL shader and implemented the Disney BRDF in the
    real-time view port.

commit 8c7e11423be640dc44b1807912058480710e51f4
Author: Pascal Schoen <pascal_schoen@gmx.net>
Date:   Fri Feb 3 14:24:05 2017 +0100

    Fix to comply strict compiler flags and some code cleanup

commit 17724e9d2dbffb1aaa61401224ecbf2349c1dac3
Merge: 379ba34 520afa2
Author: Pascal Schoen <pascal_schoen@gmx.net>
Date:   Tue Jan 24 09:59:58 2017 +0100

    Merge branch 'master' into cycles_disney_brdf

commit 379ba346b0acd1ea779365b940fcd01f5ba1165f
Author: Pascal Schoen <pascal_schoen@gmx.net>
Date:   Tue Jan 24 09:28:56 2017 +0100

    Renamed the Disney BSDF to Principled BSDF.

commit f80dcb4f34f1dc41841ced5965787fc26ace22a2
Author: Pascal Schoen <pascal_schoen@gmx.net>
Date:   Fri Dec 2 13:55:12 2016 +0100

    Removed reflection call when roughness is low because of artifacts.

commit 732db8a57f6d4e5d6f44bbad176c15fd55377f0a
Author: Pascal Schoen <pascal_schoen@gmx.net>
Date:   Wed Nov 16 09:22:25 2016 +0100

    Indication if to use fresnel is now handled via the type of the BSDF.

commit 0103659f5e705b314cde98b0e4a01c14c55acd5e
Author: Pascal Schoen <pascal_schoen@gmx.net>
Date:   Fri Nov 11 13:04:11 2016 +0100

    Fixed an error in the clearcoat where it appeared too bright for default
    light sources (like directional lights)

commit 0aa68f533529c9fd197a3ab0427f9e41a15456b9
Author: Pascal Schoen <pascal_schoen@gmx.net>
Date:   Mon Nov 7 12:04:38 2016 +0100

    Resolved inconsistencies in using tabs and spaces

commit f5897a9494e352de274b99e7bee971336c0dc386
Author: Pascal Schoen <pascal_schoen@gmx.net>
Date:   Mon Nov 7 08:13:41 2016 +0100

    Improved the clearcoat part by using GTR1 instead of GTR2

commit 3dfc240e61b3d4d0e7c476989792e4ada869ce91
Author: Pascal Schoen <pascal_schoen@gmx.net>
Date:   Mon Oct 31 11:31:36 2016 +0100

    Use reflection BSDF for glossy reflections when roughness is 0.0 to
    reduce computational expense and some code cleanup

    Code cleanup includes:
    - Code style cleanup and removed unused code
    - Consolidated code in the bsdf_microfacet_multi_impl.h to reduce
      some computational expense

commit a2dd0c5fafdabe1573299170fb3be98a3e46d17a
Author: Pascal Schoen <pascal_schoen@gmx.net>
Date:   Wed Oct 26 08:51:10 2016 +0200

    Fixed glossy reflections and refractions for low roughness values and
    cleaned up the code.

    For low roughness values, the reflections had some strange behavior.

commit 981737591231a1a5a1c85950950580b65d029505
Author: Pascal Schoen <pascal_schoen@gmx.net>
Date:   Tue Oct 25 12:37:40 2016 +0200

    Removed default values in setup functions and added extra functions for
    GGX with fresnel.

commit bbc5d9d4527346a74155cf17be21fb02ee3e0779
Author: Pascal Schoen <pascal_schoen@gmx.net>
Date:   Tue Oct 25 11:09:36 2016 +0200

    Switched from uniform to cosine hemisphere sampling for the diffuse and
    the sheen part.

commit d52d8f2813d64363713f11160a6c725d4cafbcfa
Author: Pascal Schoen <pascal_schoen@gmx.net>
Date:   Mon Oct 24 16:17:13 2016 +0200

    Removed the color parameters from the diffuse and sheen shader and use
    them as closure weights instead.

commit 8f3d92738532ad867a0a3543c00393626ab8f6ec
Author: Pascal Schoen <pascal_schoen@gmx.net>
Date:   Mon Oct 24 09:57:06 2016 +0200

    Fixed the issue with artifacts when using anisotropy without linking the
    tangent input to a tangent node.

commit d93f680db9acaaade0354b34857a3ccaf348557f
Author: Pascal Schoen <pascal_schoen@gmx.net>
Date:   Mon Oct 24 09:14:51 2016 +0200

    Added subsurface radius parameter to control the per color channel
    effection radius of the subsurface scattering.

commit c708c3e53b323773fc852bdc239bc51e157dcaef
Author: Pascal Schoen <pascal_schoen@gmx.net>
Date:   Mon Oct 24 08:14:10 2016 +0200

    Rearranged the inputs of the shader.

commit dfbfff9c389074d3e5c1f49dd38a95e9b317eb1f
Author: Pascal Schoen <pascal_schoen@gmx.net>
Date:   Fri Oct 21 09:27:05 2016 +0200

    Put spaces in the parameter names of the shader node

commit e5a748ced17c8f59e5e73309096adeea3ba95e04
Author: Pascal Schoen <pascal_schoen@gmx.net>
Date:   Fri Oct 21 08:51:20 2016 +0200

    Removed code that isn't in use anymore

commit 75992bebc128c8b44cab4f0d8855603787f57260
Author: Pascal Schoen <pascal_schoen@gmx.net>
Date:   Fri Oct 21 08:50:07 2016 +0200

    Code style cleanup

commit 4dfcf455f7769752044e051b399fb6a5dfcd0e22
Merge: 243a0e3 2cd6a89
Author: Pascal Schoen <pascal_schoen@gmx.net>
Date:   Thu Oct 20 10:41:50 2016 +0200

    Merge branch 'master' into cycles_disney_brdf

commit 243a0e3eb80ef82704d5ea2657384c3a4b9fb497
Author: Pascal Schoen <pascal_schoen@gmx.net>
Date:   Thu Oct 20 10:01:45 2016 +0200

    Switching between OSL and SVM is more consistant now when using Disney
    BSDF.

    There were some minor differences in the OSL implementation, e.g. the
    refraction roughness was missing.

commit 2a5ac509223c838285a00c4c12775567666e7154
Author: Pascal Schoen <pascal_schoen@gmx.net>
Date:   Tue Sep 27 09:17:57 2016 +0200

    Fixed a bug that caused transparency to be always white when using OSL and
    selecting GGX as distribution of the Disney BSDF

commit e1fa8623915407cea942a07fd0a106b04e113c09
Merge: d0530a8 7f76f6f
Author: Pascal Schoen <pascal_schoen@gmx.net>
Date:   Tue Sep 27 08:59:32 2016 +0200

    Merge branch 'master' into cycles_disney_brdf

commit d0530a8af0e076c0aca4c9a61b0a64cada45ac4d
Author: Pascal Schoen <pascal_schoen@gmx.net>
Date:   Tue Sep 27 08:53:18 2016 +0200

    Cleanup the Disney BSDF implementation and removing unneeded files.

commit 3f4fc826bd9c1f47c694c0f6b2947daf5b524b1a
Author: Pascal Schoen <pascal_schoen@gmx.net>
Date:   Tue Sep 27 08:36:07 2016 +0200

    Unified the OSL implementation of the Disney clearcoat as a simple
    microfacet shader like it was previously done in SVM

commit 4d3a0032ecea99031979f342bfd5f66ea5a8625a
Author: Pascal Schoen <pascal_schoen@gmx.net>
Date:   Mon Sep 26 12:35:36 2016 +0200

    Enhanced performance for Disney materials without subsurface scattering

commit 3cd5eb56cf5c9006837f111c8866e4c6e1c2a6fd
Author: Pascal Schoen <pascal_schoen@gmx.net>
Date:   Fri Sep 16 08:47:56 2016 +0200

    Fixed a bug in the Disney BSDF that caused specular reflections to be too
    bright and diffuse is now reacting to the roughness again

    - A normalization for the fresnel was missing which caused the specular
      reflections to become too bright for the single-scatter GGX
    - The roughness value for the diffuse BSSRDF part has always been
      overwritten and thus always 0
    - Also the performance for refractive materials with roughness=0.0 has
      been improved

commit 7cb37d711938e5626651db21f20da50edd96abaf
Author: Pascal Schoen <pascal_schoen@gmx.net>
Date:   Thu Sep 8 12:24:43 2016 +0200

    Added selection field to the Disney BSDF node for switching between
    "Multiscatter GGX" and "GGX"

    In the "GGX" mode there is an additional parameter for changing the
    refraction roughness for materials with smooth surfaces and rough interns
    (e.g. honey). With the "Multiscatter GGX" this effect can't be produced at
    the moment and so here will be no separation of the two roughness values.

commit cdd29d06bb86672ed0779eefb8eee95796b8f939
Merge: 02c315a b40d1c1
Author: Pascal Schoen <pascal_schoen@gmx.net>
Date:   Tue Sep 6 15:59:05 2016 +0200

    Merge branch 'master' into cycles_disney_brdf

commit 02c315aeb0f0d7bb429d4396912e03dbb8a77340
Author: Pascal Schoen <pascal_schoen@gmx.net>
Date:   Tue Sep 6 15:16:09 2016 +0200

    Implemented the OSL part of the Disney shader

commit 5f880293aeeacf269032824248b46d613691a36c
Merge: 630b80e b399a6d
Author: Pascal Schoen <pascal_schoen@gmx.net>
Date:   Fri Sep 2 10:53:36 2016 +0200

    Merge branch 'master' into cycles_disney_brdf

commit 630b80e08b6acf83834bc95264af4ccdbbc5f82c
Author: Pascal Schoen <pascal_schoen@gmx.net>
Date:   Fri Sep 2 10:52:13 2016 +0200

    Fresnel in the microfacet multiscatter implementation improved

commit 0d9f4d7acb2de65d1c98d425cea4bf364795c155
Author: Pascal Schoen <pascal_schoen@gmx.net>
Date:   Fri Aug 26 11:11:05 2016 +0200

    Fixed refraction roughness problem (refractions were always 100% rough)
    and set IOR of clearcoat to 1.5

commit 9eed34c7d980e1b998df457c4f76021162c80f78
Merge: ef29aae ae475e3
Author: Pascal Schoen <pascal_schoen@gmx.net>
Date:   Tue Aug 16 15:22:32 2016 +0200

    Merge branch 'master' into cycles_disney_brdf

commit ef29aaee1af8074e0228c480d962700e97ea5b36
Author: Pascal Schoen <pascal_schoen@gmx.net>
Date:   Tue Aug 16 15:17:12 2016 +0200

    Implemented the fresnel in the multi-scatter GGX for the Disney BSDF

    - The specular/metallic part uses the multi-scatter GGX
    - The fresnel of the metallic part is controlled by the specular value
    - The color of the reflection part when using transparency can be
      controlled by the specularTint value

commit 88567af085ac94119b98c95246b6d6f63161bc01
Merge: cc267e5 285e082
Author: Pascal Schoen <pascal_schoen@gmx.net>
Date:   Wed Aug 3 15:05:09 2016 +0200

    Merge branch 'master' into cycles_disney_brdf

commit cc267e52f20d036a66aeeff127ee1c856f7c651b
Author: Pascal Schoen <pascal_schoen@gmx.net>
Date:   Wed Aug 3 15:00:25 2016 +0200

    Implemented the Disney clearcoat as a variation of the microfacet bsdf,
    removed the transparency roughness again and added an input for
    anisotropic rotations

commit 81f6c06b1f53180bf32a5c11ac1fa64e2b6abf52
Merge: ece5a08 7065022
Author: Pascal Schoen <pascal_schoen@gmx.net>
Date:   Wed Aug 3 11:42:02 2016 +0200

    Merge branch 'master' into cycles_disney_brdf

commit ece5a08e0d6e51a83c223ea87346134216e5b34e
Author: Pascal Schoen <pascal_schoen@gmx.net>
Date:   Tue Jul 26 16:29:21 2016 +0200

    Base color now applied again to the refraction of transparent Disney
    materials

commit e3aff6849e06853c56da7bd610210dcab70e6070
Author: Pascal Schoen <pascal_schoen@gmx.net>
Date:   Tue Jul 26 16:05:19 2016 +0200

    Added subsurface color parameter to the Disney shader

commit b3ca6d8a2f4f866b323fc2df0a3beff577218c27
Author: Pascal Schoen <pascal_schoen@gmx.net>
Date:   Tue Jul 26 12:30:25 2016 +0200

    Improvement of the SSS in the Disney shader

     * Now the bump normal is correctly used for the SSS.
     * SSS in Disney uses the Disney diffuse shader

commit d68729300ee557e90a8e7e4be6eb8ef98db80fe2
Author: Pascal Schoen <pascal_schoen@gmx.net>
Date:   Tue Jul 26 12:23:13 2016 +0200

    Better calculation of the Disney diffuse part

    Now the values for NdotL und NdotV are clamped to 0.0f for a better look
    when using normal maps

commit cb6e500b12e7bce884d3db19ee138c975c215f2d
Author: Pascal Schoen <pascal_schoen@gmx.net>
Date:   Mon Jul 25 16:26:42 2016 +0200

    Now one can disable specular reflactions again by setting specular and
    metallic to 0 (cracked this in the previous commit)

commit bfb9cb11b548103369de2a46ce18b4ddf661362c
Author: Pascal Schoen <pascal_schoen@gmx.net>
Date:   Mon Jul 25 16:11:07 2016 +0200

    fixed the Disney SSS and cleaned the initialization of the Disney shaders

commit 642c0fdad12548c1a2ccbf595bae3a995d3022f7
Author: Pascal Schoen <pascal_schoen@gmx.net>
Date:   Mon Jul 25 16:09:55 2016 +0200

    fixed an error that was caused by the missing LABEL_REFLECT in the Disney
    diffuse shader

commit c10b484dcad3412c34455736e9656cd38716bcb0
Author: Jens Verwiebe <info@jensverwiebe.de>
Date:   Fri Jul 22 01:15:21 2016 +0200

    Rollback attempt to fix sss crashing, it prevented crash by disabling sss completely, thus useless

commit 462bba3f97fcc41834e0e20cc806a7958e5106f5
Author: Jens Verwiebe <info@jensverwiebe.de>
Date:   Thu Jul 21 23:11:59 2016 +0200

    Add an undef for sc_next for safety

commit 32d348577d69be251aa04110c5f6156cd2645f48
Author: Jens Verwiebe <info@jensverwiebe.de>
Date:   Thu Jul 21 00:15:48 2016 +0200

    Attempt to fix Disney SSS

commit dbad91ca6d46f5a4a6f2ba7ed4c811ffa723942f
Author: Pascal Schoen <pascal_schoen@gmx.net>
Date:   Wed Jul 20 11:13:00 2016 +0200

    Added a roughness parameter for refractions (for scattering of the rays
    within an object)

    With this, one can create a translucent material with a smooth surface and
    with a milky look.

    The final refraction roughness has to be calculated using the surface
    roughness and the refraction roughness because those two are correlated
    for refractions. If a ray hits a rough surface of a translucent material,
    it is scattered while entering the surface. Then it is scattered further
    within the object. The calculation I'm using is the following:

    RefrRoughnessFinal = 1.0 - (1.0 - Roughness) * (1.0 - RefrRoughness)

commit 50ea5e3e34394a727e3cceb6203adb48834a9ab7
Author: Pascal Schoen <pascal_schoen@gmx.net>
Date:   Tue Jun 7 10:24:50 2016 +0200

    Disney BSDF is now supporting CUDA

commit 10974cc826a4bfa8fb3ef59177abf0b0dc441065
Author: Pascal Schoen <pascal_schoen@gmx.net>
Date:   Tue May 31 11:18:07 2016 +0200

    Added parameters IOR and Transparency for refractions

    With this, the Disney BRDF/BSSRDF is extended by the BTDF part.

commit 218202c0905a4ec93ee19850360d1a39966d2c25
Author: Pascal Schoen <pascal_schoen@gmx.net>
Date:   Mon May 30 15:08:18 2016 +0200

    Added an additional normal for the clearcoat

    With this normal one can simulate a thin layer of clearcoat by applying a
    smoother normal map than the original to this input

commit dd139ead7e04aa87a894ccf3732cfce711258ff1
Author: Pascal Schoen <pascal_schoen@gmx.net>
Date:   Mon May 30 12:40:56 2016 +0200

    Switched to the improved subsurface scattering from Christensen and
    Burley

commit 11160fa4e1c32230119d4506e7e9fd3da2ab37f2
Author: Pascal Schoen <pascal_schoen@gmx.net>
Date:   Mon May 30 10:16:30 2016 +0200

    Added Disney Sheen shader as a preparation to get to a BSSRDF

commit cee4fe0cc94515ee60d4afa4d4e10c41003f1579
Merge: 4f955d0 6b5bab6
Author: Pascal Schoen <pascal_schoen@gmx.net>
Date:   Mon May 30 09:08:09 2016 +0200

    Merge branch 'cycles_disney_brdf' of git.blender.org:blender into cycles_disney_brdf

    Conflicts:
     intern/cycles/kernel/closure/bsdf_disney_clearcoat.h
     intern/cycles/kernel/closure/bsdf_disney_diffuse.h
     intern/cycles/kernel/closure/bsdf_disney_specular.h
     intern/cycles/kernel/closure/bsdf_util.h
     intern/cycles/kernel/osl/CMakeLists.txt
     intern/cycles/kernel/osl/bsdf_disney_clearcoat.cpp
     intern/cycles/kernel/osl/bsdf_disney_diffuse.cpp
     intern/cycles/kernel/osl/bsdf_disney_specular.cpp
     intern/cycles/kernel/osl/osl_closures.h
     intern/cycles/kernel/shaders/node_disney_bsdf.osl
     intern/cycles/render/nodes.cpp
     intern/cycles/render/nodes.h

commit 4f955d052358206209454decf2c3539e6a21b42f
Author: Pascal Schoen <pascal_schoen@gmx.net>
Date:   Tue May 24 16:38:23 2016 +0200

    SVM and OSL are both working for the simple version of the Disney BRDF

commit 1f5c41874b01ad297eb8a6bad9985296c6c0a6e1
Author: Pascal Schoen <pascal_schoen@gmx.net>
Date:   Tue May 24 09:58:50 2016 +0200

    Disney node can be used without SVM and started to cleanup the OSL implementation

    There is still some wrong behavior for SVM for the Schlick Fresnel part at the
    specular and clearcoat

commit d4b814e9304ebb44cc7c291cd83f7b7cdebcd152
Author: Pascal Schoen <pascal_schoen@gmx.net>
Date:   Wed May 18 10:22:29 2016 +0200

    Switched from a parameter struct for Disney parameters to ShaderClosure params

commit b86a1f5ba5019c7818153cb70b49f5f7a0bc52a0
Author: Pascal Schoen <pascal_schoen@gmx.net>
Date:   Wed May 18 10:19:57 2016 +0200

    Added additional variables for storing parameters in the ShaderClosure struct

commit 585b88623695fa07dfca9c9909d6d9184c3519c8
Author: Pascal Schoen <pascal_schoen@gmx.net>
Date:   Tue May 17 12:03:17 2016 +0200

    added output parameter to the DisneyBsdfNode

    That has been forgotten after removing the inheritance of BsdfNode

commit f91a28639884cbda7804715b910d64abba0718ef
Author: Pascal Schoen <pascal_schoen@gmx.net>
Date:   Tue May 17 10:40:48 2016 +0200

    removed BsdfNode class inheritance for DisneyBsdfNode

    That's due to a naming difference. The Disney BSDF uses the name 'Base Color'
    while the BsdfNode had a 'Color' input. That caused a text message to be
    printed while rendering.

commit 30da91c9c51d8cbc6a7564c7aaa61c9efe2ab654
Author: Pascal Schoen <pascal_schoen@gmx.net>
Date:   Wed May 4 16:08:10 2016 +0200

    disney implementation cleaned

commit 30d41da0f0352fad29375a395ffcb9cb7891eeb1
Author: Pascal Schoen <pascal_schoen@gmx.net>
Date:   Wed May 4 13:23:07 2016 +0200

    added the disney brdf as a shader node

commit 1f099fce249cb35e949cc629f7cca2167fca881a
Author: Pascal Schoen <pascal_schoen@gmx.net>
Date:   Tue May 3 16:54:49 2016 +0200

    added clearcoat implementation

commit 00a1378b98e435e9cdbfbac86eb974c19b2a8151
Author: Pascal Schoen <pascal_schoen@gmx.net>
Date:   Fri Apr 29 22:56:49 2016 +0200

    disney diffuse und specular implemented

commit 6baa7a7eb787638661cddad0c4e7f78bd3a8fa5c
Author: Pascal Schoen <pascal_schoen@gmx.net>
Date:   Mon Apr 18 15:21:32 2016 +0200

    disney diffuse is working correctly

commit d8fa169bf3caf71c40a124101b33dee6c510188e
Author: Pascal Schoen <pascal_schoen@gmx.net>
Date:   Mon Apr 18 08:41:53 2016 +0200

    added vessel for disney diffuse shader

commit 6b5bab6cecde153122625cf8dc10e4209ed1eb0f
Author: Pascal Schoen <pascal_schoen@gmx.net>
Date:   Wed May 18 10:22:29 2016 +0200

    Switched from a parameter struct for Disney parameters to ShaderClosure params

commit f6499c2676e074a36033627ffc7540107777630d
Author: Pascal Schoen <pascal_schoen@gmx.net>
Date:   Wed May 18 10:19:57 2016 +0200

    Added additional variables for storing parameters in the ShaderClosure struct

commit 7100640b65c2ff5447a18c01fc4e93594b4f486a
Author: Pascal Schoen <pascal_schoen@gmx.net>
Date:   Tue May 17 12:03:17 2016 +0200

    added output parameter to the DisneyBsdfNode

    That has been forgotten after removing the inheritance of BsdfNode

commit 419ee5441100a906b4b3fd8373cb768a71bfdfe6
Author: Pascal Schoen <pascal_schoen@gmx.net>
Date:   Tue May 17 10:40:48 2016 +0200

    removed BsdfNode class inheritance for DisneyBsdfNode

    That's due to a naming difference. The Disney BSDF uses the name 'Base Color'
    while the BsdfNode had a 'Color' input. That caused a text message to be
    printed while rendering.

commit 6006f91e8730f78df5874f808690d3908db103ab
Author: Pascal Schoen <pascal_schoen@gmx.net>
Date:   Wed May 4 16:08:10 2016 +0200

    disney implementation cleaned

commit 0ed08959141fc7c5f8c6e37c6552ecb9fcc5749c
Author: Pascal Schoen <pascal_schoen@gmx.net>
Date:   Wed May 4 13:23:07 2016 +0200

    added the disney brdf as a shader node

commit 0630b742d71c658915575a4a71a325094a0fc313
Author: Pascal Schoen <pascal_schoen@gmx.net>
Date:   Tue May 3 16:54:49 2016 +0200

    added clearcoat implementation

commit 9f3d39744b85619750c79c901f678b8c07fe0ee2
Author: Pascal Schoen <pascal_schoen@gmx.net>
Date:   Fri Apr 29 22:56:49 2016 +0200

    disney diffuse und specular implemented

commit 9b262063767d6b05a617891c967d887d21bfb177
Author: Pascal Schoen <pascal_schoen@gmx.net>
Date:   Mon Apr 18 15:21:32 2016 +0200

    disney diffuse is working correctly

commit 4711a3927dfcadaa1c36de0ba78fc304fac1dc8a
Author: Pascal Schoen <pascal_schoen@gmx.net>
Date:   Mon Apr 18 08:41:53 2016 +0200

    added vessel for disney diffuse shader

Differential Revision: https://developer.blender.org/D2313

32 files changed:
intern/cycles/blender/blender_shader.cpp
intern/cycles/kernel/CMakeLists.txt
intern/cycles/kernel/closure/bsdf.h
intern/cycles/kernel/closure/bsdf_microfacet.h
intern/cycles/kernel/closure/bsdf_microfacet_multi.h
intern/cycles/kernel/closure/bsdf_microfacet_multi_impl.h
intern/cycles/kernel/closure/bsdf_principled_diffuse.h [new file with mode: 0644]
intern/cycles/kernel/closure/bsdf_principled_sheen.h [new file with mode: 0644]
intern/cycles/kernel/closure/bsdf_util.h
intern/cycles/kernel/closure/bssrdf.h
intern/cycles/kernel/kernel_subsurface.h
intern/cycles/kernel/osl/osl_bssrdf.cpp
intern/cycles/kernel/osl/osl_closures.cpp
intern/cycles/kernel/osl/osl_closures.h
intern/cycles/kernel/shaders/CMakeLists.txt
intern/cycles/kernel/shaders/node_principled_bsdf.osl [new file with mode: 0644]
intern/cycles/kernel/shaders/stdosl.h
intern/cycles/kernel/svm/svm_closure.h
intern/cycles/kernel/svm/svm_types.h
intern/cycles/render/graph.cpp
intern/cycles/render/nodes.cpp
intern/cycles/render/nodes.h
release/scripts/startup/nodeitems_builtins.py
source/blender/blenkernel/BKE_node.h
source/blender/blenkernel/intern/node.c
source/blender/editors/space_node/drawnode.c
source/blender/gpu/shaders/gpu_shader_material.glsl
source/blender/makesrna/intern/rna_nodetree.c
source/blender/nodes/CMakeLists.txt
source/blender/nodes/NOD_shader.h
source/blender/nodes/NOD_static_types.h
source/blender/nodes/shader/nodes/node_shader_bsdf_principled.c [new file with mode: 0644]

index 3f04f11aab4c2e2cde8f06abb5ad37ccac461235..bdbab1006c06c5e19643ccbfbfbb243fbd149c8c 100644 (file)
@@ -521,6 +521,19 @@ static ShaderNode *add_node(Scene *scene,
                }
                node = hair;
        }
+       else if(b_node.is_a(&RNA_ShaderNodeBsdfPrincipled)) {
+               BL::ShaderNodeBsdfPrincipled b_principled_node(b_node);
+               PrincipledBsdfNode *principled = new PrincipledBsdfNode();
+               switch (b_principled_node.distribution()) {
+                       case BL::ShaderNodeBsdfPrincipled::distribution_GGX:
+                               principled->distribution = CLOSURE_BSDF_MICROFACET_GGX_GLASS_ID;
+                               break;
+                       case BL::ShaderNodeBsdfPrincipled::distribution_MULTI_GGX:
+                               principled->distribution = CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_ID;
+                               break;
+               }
+               node = principled;
+       }
        else if(b_node.is_a(&RNA_ShaderNodeBsdfTranslucent)) {
                node = new TranslucentBsdfNode();
        }
index dbc2ba2503a5756a2226178a9c5e08fa846cf7a5..c3772dfa2d8ac301c7050c61efc2d5d5a54c8d7a 100644 (file)
@@ -120,6 +120,8 @@ set(SRC_CLOSURE_HEADERS
        closure/bssrdf.h
        closure/emissive.h
        closure/volume.h
+       closure/bsdf_principled_diffuse.h
+       closure/bsdf_principled_sheen.h
 )
 
 set(SRC_SVM_HEADERS
index 9139b99353a360ea81a034a644b4f2d377c690de..0302fa9b43e35a283d24da588a57d61967d4b3e6 100644 (file)
@@ -27,6 +27,8 @@
 #include "kernel/closure/bsdf_ashikhmin_shirley.h"
 #include "kernel/closure/bsdf_toon.h"
 #include "kernel/closure/bsdf_hair.h"
+#include "kernel/closure/bsdf_principled_diffuse.h"
+#include "kernel/closure/bsdf_principled_sheen.h"
 #ifdef __SUBSURFACE__
 #  include "kernel/closure/bssrdf.h"
 #endif
@@ -86,16 +88,21 @@ ccl_device_forceinline int bsdf_sample(KernelGlobals *kg,
                                eval, omega_in, &domega_in->dx, &domega_in->dy, pdf);
                        break;
                case CLOSURE_BSDF_MICROFACET_GGX_ID:
+               case CLOSURE_BSDF_MICROFACET_GGX_FRESNEL_ID:
+               case CLOSURE_BSDF_MICROFACET_GGX_CLEARCOAT_ID:
                case CLOSURE_BSDF_MICROFACET_GGX_ANISO_ID:
+               case CLOSURE_BSDF_MICROFACET_GGX_ANISO_FRESNEL_ID:
                case CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID:
                        label = bsdf_microfacet_ggx_sample(kg, sc, sd->Ng, sd->I, sd->dI.dx, sd->dI.dy, randu, randv,
                                eval, omega_in, &domega_in->dx, &domega_in->dy, pdf);
                        break;
                case CLOSURE_BSDF_MICROFACET_MULTI_GGX_ID:
+               case CLOSURE_BSDF_MICROFACET_MULTI_GGX_FRESNEL_ID:
                        label = bsdf_microfacet_multi_ggx_sample(kg, sc, sd->Ng, sd->I, sd->dI.dx, sd->dI.dy, randu, randv,
                                eval, omega_in,  &domega_in->dx, &domega_in->dy, pdf, &sd->lcg_state);
                        break;
                case CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_ID:
+               case CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_FRESNEL_ID:
                        label = bsdf_microfacet_multi_ggx_glass_sample(kg, sc, sd->Ng, sd->I, sd->dI.dx, sd->dI.dy, randu, randv,
                                eval, omega_in,  &domega_in->dx, &domega_in->dy, pdf, &sd->lcg_state);
                        break;
@@ -130,6 +137,15 @@ ccl_device_forceinline int bsdf_sample(KernelGlobals *kg,
                        label = bsdf_hair_transmission_sample(sc, sd->Ng, sd->I, sd->dI.dx, sd->dI.dy, randu, randv,
                                eval, omega_in, &domega_in->dx, &domega_in->dy, pdf);
                        break;
+               case CLOSURE_BSDF_PRINCIPLED_DIFFUSE_ID:
+               case CLOSURE_BSDF_BSSRDF_PRINCIPLED_ID:
+                       label = bsdf_principled_diffuse_sample(sc, sd->Ng, sd->I, sd->dI.dx, sd->dI.dy, randu, randv,
+                               eval, omega_in, &domega_in->dx, &domega_in->dy, pdf);
+                       break;
+               case CLOSURE_BSDF_PRINCIPLED_SHEEN_ID:
+                       label = bsdf_principled_sheen_sample(sc, sd->Ng, sd->I, sd->dI.dx, sd->dI.dy, randu, randv,
+                               eval, omega_in, &domega_in->dx, &domega_in->dy, pdf);
+                       break;
 #endif
 #ifdef __VOLUME__
                case CLOSURE_VOLUME_HENYEY_GREENSTEIN_ID:
@@ -188,14 +204,19 @@ float3 bsdf_eval(KernelGlobals *kg,
                                eval = bsdf_transparent_eval_reflect(sc, sd->I, omega_in, pdf);
                                break;
                        case CLOSURE_BSDF_MICROFACET_GGX_ID:
+                       case CLOSURE_BSDF_MICROFACET_GGX_FRESNEL_ID:
+                       case CLOSURE_BSDF_MICROFACET_GGX_CLEARCOAT_ID:
                        case CLOSURE_BSDF_MICROFACET_GGX_ANISO_ID:
+                       case CLOSURE_BSDF_MICROFACET_GGX_ANISO_FRESNEL_ID:
                        case CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID:
                                eval = bsdf_microfacet_ggx_eval_reflect(sc, sd->I, omega_in, pdf);
                                break;
                        case CLOSURE_BSDF_MICROFACET_MULTI_GGX_ID:
+                       case CLOSURE_BSDF_MICROFACET_MULTI_GGX_FRESNEL_ID:
                                eval = bsdf_microfacet_multi_ggx_eval_reflect(sc, sd->I, omega_in, pdf, &sd->lcg_state);
                                break;
                        case CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_ID:
+                       case CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_FRESNEL_ID:
                                eval = bsdf_microfacet_multi_ggx_glass_eval_reflect(sc, sd->I, omega_in, pdf, &sd->lcg_state);
                                break;
                        case CLOSURE_BSDF_MICROFACET_BECKMANN_ID:
@@ -222,6 +243,13 @@ float3 bsdf_eval(KernelGlobals *kg,
                        case CLOSURE_BSDF_HAIR_TRANSMISSION_ID:
                                eval = bsdf_hair_transmission_eval_reflect(sc, sd->I, omega_in, pdf);
                                break;
+                       case CLOSURE_BSDF_PRINCIPLED_DIFFUSE_ID:
+                       case CLOSURE_BSDF_BSSRDF_PRINCIPLED_ID:
+                               eval = bsdf_principled_diffuse_eval_reflect(sc, sd->I, omega_in, pdf);
+                               break;
+                       case CLOSURE_BSDF_PRINCIPLED_SHEEN_ID:
+                               eval = bsdf_principled_sheen_eval_reflect(sc, sd->I, omega_in, pdf);
+                               break;
 #endif
 #ifdef __VOLUME__
                        case CLOSURE_VOLUME_HENYEY_GREENSTEIN_ID:
@@ -256,14 +284,19 @@ float3 bsdf_eval(KernelGlobals *kg,
                                eval = bsdf_transparent_eval_transmit(sc, sd->I, omega_in, pdf);
                                break;
                        case CLOSURE_BSDF_MICROFACET_GGX_ID:
+                       case CLOSURE_BSDF_MICROFACET_GGX_FRESNEL_ID:
+                       case CLOSURE_BSDF_MICROFACET_GGX_CLEARCOAT_ID:
                        case CLOSURE_BSDF_MICROFACET_GGX_ANISO_ID:
+                       case CLOSURE_BSDF_MICROFACET_GGX_ANISO_FRESNEL_ID:
                        case CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID:
                                eval = bsdf_microfacet_ggx_eval_transmit(sc, sd->I, omega_in, pdf);
                                break;
                        case CLOSURE_BSDF_MICROFACET_MULTI_GGX_ID:
+                       case CLOSURE_BSDF_MICROFACET_MULTI_GGX_FRESNEL_ID:
                                eval = bsdf_microfacet_multi_ggx_eval_transmit(sc, sd->I, omega_in, pdf, &sd->lcg_state);
                                break;
                        case CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_ID:
+                       case CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_FRESNEL_ID:
                                eval = bsdf_microfacet_multi_ggx_glass_eval_transmit(sc, sd->I, omega_in, pdf, &sd->lcg_state);
                                break;
                        case CLOSURE_BSDF_MICROFACET_BECKMANN_ID:
@@ -290,6 +323,13 @@ float3 bsdf_eval(KernelGlobals *kg,
                        case CLOSURE_BSDF_HAIR_TRANSMISSION_ID:
                                eval = bsdf_hair_transmission_eval_transmit(sc, sd->I, omega_in, pdf);
                                break;
+                       case CLOSURE_BSDF_PRINCIPLED_DIFFUSE_ID:
+                       case CLOSURE_BSDF_BSSRDF_PRINCIPLED_ID:
+                               eval = bsdf_principled_diffuse_eval_transmit(sc, sd->I, omega_in, pdf);
+                               break;
+                       case CLOSURE_BSDF_PRINCIPLED_SHEEN_ID:
+                               eval = bsdf_principled_sheen_eval_transmit(sc, sd->I, omega_in, pdf);
+                               break;
 #endif
 #ifdef __VOLUME__
                        case CLOSURE_VOLUME_HENYEY_GREENSTEIN_ID:
@@ -311,11 +351,16 @@ ccl_device void bsdf_blur(KernelGlobals *kg, ShaderClosure *sc, float roughness)
 #ifdef __SVM__
        switch(sc->type) {
                case CLOSURE_BSDF_MICROFACET_MULTI_GGX_ID:
+               case CLOSURE_BSDF_MICROFACET_MULTI_GGX_FRESNEL_ID:
                case CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_ID:
+               case CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_FRESNEL_ID:
                        bsdf_microfacet_multi_ggx_blur(sc, roughness);
                        break;
                case CLOSURE_BSDF_MICROFACET_GGX_ID:
+               case CLOSURE_BSDF_MICROFACET_GGX_FRESNEL_ID:
+               case CLOSURE_BSDF_MICROFACET_GGX_CLEARCOAT_ID:
                case CLOSURE_BSDF_MICROFACET_GGX_ANISO_ID:
+               case CLOSURE_BSDF_MICROFACET_GGX_ANISO_FRESNEL_ID:
                case CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID:
                        bsdf_microfacet_ggx_blur(sc, roughness);
                        break;
@@ -349,10 +394,15 @@ ccl_device bool bsdf_merge(ShaderClosure *a, ShaderClosure *b)
                case CLOSURE_BSDF_REFLECTION_ID:
                case CLOSURE_BSDF_REFRACTION_ID:
                case CLOSURE_BSDF_MICROFACET_GGX_ID:
+               case CLOSURE_BSDF_MICROFACET_GGX_FRESNEL_ID:
+               case CLOSURE_BSDF_MICROFACET_GGX_CLEARCOAT_ID:
                case CLOSURE_BSDF_MICROFACET_GGX_ANISO_ID:
+               case CLOSURE_BSDF_MICROFACET_GGX_ANISO_FRESNEL_ID:
                case CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID:
                case CLOSURE_BSDF_MICROFACET_MULTI_GGX_ID:
+               case CLOSURE_BSDF_MICROFACET_MULTI_GGX_FRESNEL_ID:
                case CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_ID:
+               case CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_FRESNEL_ID:
                case CLOSURE_BSDF_MICROFACET_BECKMANN_ID:
                case CLOSURE_BSDF_MICROFACET_BECKMANN_ANISO_ID:
                case CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID:
index 1c7b3eb9dddf45104a1e5f1059a167d82e9ba3eb..58f6140970d52e8ba52413479c5723eaf1418c01 100644 (file)
@@ -36,7 +36,8 @@
 CCL_NAMESPACE_BEGIN
 
 typedef ccl_addr_space struct MicrofacetExtra {
-       float3 color;
+       float3 color, cspec0;
+       float clearcoat;
 } MicrofacetExtra;
 
 typedef ccl_addr_space struct MicrofacetBsdf {
@@ -233,6 +234,36 @@ ccl_device_forceinline float3 microfacet_sample_stretched(
        return normalize(make_float3(-slope_x, -slope_y, 1.0f));
 } 
 
+/* Calculate the reflection color
+ *
+ * If fresnel is used, the color is an interpolation of the F0 color and white
+ * with respect to the fresnel
+ *
+ * Else it is simply white
+ */
+ccl_device_forceinline float3 reflection_color(const MicrofacetBsdf *bsdf, float3 L, float3 H) {
+       float3 F = make_float3(1.0f, 1.0f, 1.0f);
+       bool use_fresnel = (bsdf->type == CLOSURE_BSDF_MICROFACET_GGX_FRESNEL_ID
+                          || bsdf->type == CLOSURE_BSDF_MICROFACET_GGX_CLEARCOAT_ID
+                          || bsdf->type == CLOSURE_BSDF_MICROFACET_GGX_ANISO_FRESNEL_ID);
+
+       if(use_fresnel) {
+               float F0 = fresnel_dielectric_cos(1.0f, bsdf->ior);
+
+               F = interpolate_fresnel_color(L, H, bsdf->ior, F0, bsdf->extra->cspec0);
+       }
+
+       return F;
+}
+
+ccl_device_forceinline float D_GTR1(float NdotH, float alpha)
+{
+       if (alpha >= 1.0f) return M_1_PI_F;
+       float alpha2 = alpha*alpha;
+       float t = 1.0f + (alpha2 - 1.0f) * NdotH*NdotH;
+       return (alpha2 - 1.0f) / (M_PI_F * logf(alpha2) * t);
+}
+
 /* GGX microfacet with Smith shadow-masking from:
  *
  * Microfacet Models for Refraction through Rough Surfaces
@@ -248,14 +279,44 @@ ccl_device_forceinline float3 microfacet_sample_stretched(
 
 ccl_device int bsdf_microfacet_ggx_setup(MicrofacetBsdf *bsdf)
 {
+       bsdf->extra = NULL;
+
        bsdf->alpha_x = saturate(bsdf->alpha_x);
        bsdf->alpha_y = bsdf->alpha_x;
-       
+
        bsdf->type = CLOSURE_BSDF_MICROFACET_GGX_ID;
 
        return SD_BSDF|SD_BSDF_HAS_EVAL;
 }
 
+ccl_device int bsdf_microfacet_ggx_fresnel_setup(MicrofacetBsdf *bsdf)
+{
+       bsdf->extra->cspec0.x = saturate(bsdf->extra->cspec0.x);
+       bsdf->extra->cspec0.y = saturate(bsdf->extra->cspec0.y);
+       bsdf->extra->cspec0.z = saturate(bsdf->extra->cspec0.z);
+
+       bsdf->alpha_x = saturate(bsdf->alpha_x);
+       bsdf->alpha_y = bsdf->alpha_x;
+
+       bsdf->type = CLOSURE_BSDF_MICROFACET_GGX_FRESNEL_ID;
+
+       return SD_BSDF|SD_BSDF_HAS_EVAL;
+}
+
+ccl_device int bsdf_microfacet_ggx_clearcoat_setup(MicrofacetBsdf *bsdf)
+{
+       bsdf->extra->cspec0.x = saturate(bsdf->extra->cspec0.x);
+       bsdf->extra->cspec0.y = saturate(bsdf->extra->cspec0.y);
+       bsdf->extra->cspec0.z = saturate(bsdf->extra->cspec0.z);
+
+       bsdf->alpha_x = saturate(bsdf->alpha_x);
+       bsdf->alpha_y = bsdf->alpha_x;
+
+       bsdf->type = CLOSURE_BSDF_MICROFACET_GGX_CLEARCOAT_ID;
+
+       return SD_BSDF|SD_BSDF_HAS_EVAL;
+}
+
 ccl_device bool bsdf_microfacet_merge(const ShaderClosure *a, const ShaderClosure *b)
 {
        const MicrofacetBsdf *bsdf_a = (const MicrofacetBsdf*)a;
@@ -273,16 +334,34 @@ ccl_device bool bsdf_microfacet_merge(const ShaderClosure *a, const ShaderClosur
 
 ccl_device int bsdf_microfacet_ggx_aniso_setup(MicrofacetBsdf *bsdf)
 {
+       bsdf->extra = NULL;
+
        bsdf->alpha_x = saturate(bsdf->alpha_x);
        bsdf->alpha_y = saturate(bsdf->alpha_y);
-       
+
        bsdf->type = CLOSURE_BSDF_MICROFACET_GGX_ANISO_ID;
 
        return SD_BSDF|SD_BSDF_HAS_EVAL;
 }
 
+ccl_device int bsdf_microfacet_ggx_aniso_fresnel_setup(MicrofacetBsdf *bsdf)
+{
+       bsdf->extra->cspec0.x = saturate(bsdf->extra->cspec0.x);
+       bsdf->extra->cspec0.y = saturate(bsdf->extra->cspec0.y);
+       bsdf->extra->cspec0.z = saturate(bsdf->extra->cspec0.z);
+
+       bsdf->alpha_x = saturate(bsdf->alpha_x);
+       bsdf->alpha_y = saturate(bsdf->alpha_y);
+
+       bsdf->type = CLOSURE_BSDF_MICROFACET_GGX_ANISO_FRESNEL_ID;
+
+       return SD_BSDF|SD_BSDF_HAS_EVAL;
+}
+
 ccl_device int bsdf_microfacet_ggx_refraction_setup(MicrofacetBsdf *bsdf)
 {
+       bsdf->extra = NULL;
+
        bsdf->alpha_x = saturate(bsdf->alpha_x);
        bsdf->alpha_y = bsdf->alpha_x;
 
@@ -319,6 +398,8 @@ ccl_device float3 bsdf_microfacet_ggx_eval_reflect(const ShaderClosure *sc, cons
                float alpha2 = alpha_x * alpha_y;
                float D, G1o, G1i;
 
+               bool is_principled_clearcoat = (bsdf->type == CLOSURE_BSDF_MICROFACET_GGX_CLEARCOAT_ID);
+
                if(alpha_x == alpha_y) {
                        /* isotropic
                         * eq. 20: (F*G*D)/(4*in*on)
@@ -327,7 +408,18 @@ ccl_device float3 bsdf_microfacet_ggx_eval_reflect(const ShaderClosure *sc, cons
                        float cosThetaM2 = cosThetaM * cosThetaM;
                        float cosThetaM4 = cosThetaM2 * cosThetaM2;
                        float tanThetaM2 = (1 - cosThetaM2) / cosThetaM2;
-                       D = alpha2 / (M_PI_F * cosThetaM4 * (alpha2 + tanThetaM2) * (alpha2 + tanThetaM2));
+
+                       if(is_principled_clearcoat) {
+                               /* use GTR1 for clearcoat */
+                               D = D_GTR1(cosThetaM, bsdf->alpha_x);
+
+                               /* the alpha value for clearcoat is a fixed 0.25 => alpha2 = 0.25 * 0.25 */
+                               alpha2 = 0.0625f;
+                       }
+                       else {
+                               /* use GTR2 otherwise */
+                               D = alpha2 / (M_PI_F * cosThetaM4 * (alpha2 + tanThetaM2) * (alpha2 + tanThetaM2));
+                       }
 
                        /* eq. 34: now calculate G1(i,m) and G1(o,m) */
                        G1o = 2 / (1 + safe_sqrtf(1 + alpha2 * (1 - cosNO * cosNO) / (cosNO * cosNO)));
@@ -374,7 +466,13 @@ ccl_device float3 bsdf_microfacet_ggx_eval_reflect(const ShaderClosure *sc, cons
 
                /* eq. 20 */
                float common = D * 0.25f / cosNO;
-               float out = G * common;
+
+               float3 F = reflection_color(bsdf, omega_in, m);
+               if(is_principled_clearcoat) {
+                       F *= 0.25f * bsdf->extra->clearcoat;
+               }
+
+               float3 out = F * G * common;
 
                /* eq. 2 in distribution of visible normals sampling
                 * pm = Dw = G1o * dot(m, I) * D / dot(N, I); */
@@ -384,7 +482,7 @@ ccl_device float3 bsdf_microfacet_ggx_eval_reflect(const ShaderClosure *sc, cons
                 * pdf = pm * 0.25 / dot(m, I); */
                *pdf = G1o * common;
 
-               return make_float3(out, out, out);
+               return out;
        }
 
        return make_float3(0.0f, 0.0f, 0.0f);
@@ -489,6 +587,17 @@ ccl_device int bsdf_microfacet_ggx_sample(KernelGlobals *kg, const ShaderClosure
                                                /* some high number for MIS */
                                                *pdf = 1e6f;
                                                *eval = make_float3(1e6f, 1e6f, 1e6f);
+
+                                               bool use_fresnel = (bsdf->type == CLOSURE_BSDF_MICROFACET_GGX_FRESNEL_ID
+                                                                  || bsdf->type == CLOSURE_BSDF_MICROFACET_GGX_CLEARCOAT_ID
+                                                                  || bsdf->type == CLOSURE_BSDF_MICROFACET_GGX_ANISO_FRESNEL_ID);
+
+                                               /* if fresnel is used, calculate the color with reflection_color(...) */
+                                               if(use_fresnel) {
+                                                       *pdf = 1.0f;
+                                                       *eval = reflection_color(bsdf, *omega_in, m);
+                                               }
+
                                                label = LABEL_REFLECT | LABEL_SINGULAR;
                                        }
                                        else {
@@ -497,16 +606,32 @@ ccl_device int bsdf_microfacet_ggx_sample(KernelGlobals *kg, const ShaderClosure
                                                float alpha2 = alpha_x * alpha_y;
                                                float D, G1i;
 
+                                               bool is_principled_clearcoat = (bsdf->type == CLOSURE_BSDF_MICROFACET_GGX_CLEARCOAT_ID);
+
                                                if(alpha_x == alpha_y) {
                                                        /* isotropic */
                                                        float cosThetaM2 = cosThetaM * cosThetaM;
                                                        float cosThetaM4 = cosThetaM2 * cosThetaM2;
                                                        float tanThetaM2 = 1/(cosThetaM2) - 1;
-                                                       D = alpha2 / (M_PI_F * cosThetaM4 * (alpha2 + tanThetaM2) * (alpha2 + tanThetaM2));
 
                                                        /* eval BRDF*cosNI */
                                                        float cosNI = dot(N, *omega_in);
 
+                                                       if(is_principled_clearcoat) {
+                                                               /* use GTR1 for clearcoat */
+                                                               D = D_GTR1(cosThetaM, bsdf->alpha_x);
+
+                                                               /* the alpha value for clearcoat is a fixed 0.25 => alpha2 = 0.25 * 0.25 */
+                                                               alpha2 = 0.0625f;
+
+                                                               /* recalculate G1o */
+                                                               G1o = 2 / (1 + safe_sqrtf(1 + alpha2 * (1 - cosNO * cosNO) / (cosNO * cosNO)));
+                                                       }
+                                                       else {
+                                                               /* use GTR2 otherwise */
+                                                               D = alpha2 / (M_PI_F * cosThetaM4 * (alpha2 + tanThetaM2) * (alpha2 + tanThetaM2));
+                                                       }
+
                                                        /* eq. 34: now calculate G1(i,m) */
                                                        G1i = 2 / (1 + safe_sqrtf(1 + alpha2 * (1 - cosNI * cosNI) / (cosNI * cosNI))); 
                                                }
@@ -538,10 +663,14 @@ ccl_device int bsdf_microfacet_ggx_sample(KernelGlobals *kg, const ShaderClosure
 
                                                /* see eval function for derivation */
                                                float common = (G1o * D) * 0.25f / cosNO;
-                                               float out = G1i * common;
                                                *pdf = common;
 
-                                               *eval = make_float3(out, out, out);
+                                               float3 F = reflection_color(bsdf, *omega_in, m);
+                                               if(is_principled_clearcoat) {
+                                                       F *= 0.25f * bsdf->extra->clearcoat;
+                                               }
+
+                                               *eval = G1i * common * F;
                                        }
 
 #ifdef __RAY_DIFFERENTIALS__
index 7d87727004f55c2bf9ffeeb2999b43aea98d90ed..57f1e733ee7911548542f81aac0957305ac4a878 100644 (file)
@@ -345,8 +345,9 @@ ccl_device int bsdf_microfacet_multi_ggx_common_setup(MicrofacetBsdf *bsdf)
        bsdf->extra->color.x = saturate(bsdf->extra->color.x);
        bsdf->extra->color.y = saturate(bsdf->extra->color.y);
        bsdf->extra->color.z = saturate(bsdf->extra->color.z);
-
-       bsdf->type = CLOSURE_BSDF_MICROFACET_MULTI_GGX_ID;
+       bsdf->extra->cspec0.x = saturate(bsdf->extra->cspec0.x);
+       bsdf->extra->cspec0.y = saturate(bsdf->extra->cspec0.y);
+       bsdf->extra->cspec0.z = saturate(bsdf->extra->cspec0.z);
 
        return SD_BSDF|SD_BSDF_HAS_EVAL|SD_BSDF_NEEDS_LCG;
 }
@@ -356,6 +357,18 @@ ccl_device int bsdf_microfacet_multi_ggx_aniso_setup(MicrofacetBsdf *bsdf)
        if(is_zero(bsdf->T))
                bsdf->T = make_float3(1.0f, 0.0f, 0.0f);
 
+       bsdf->type = CLOSURE_BSDF_MICROFACET_MULTI_GGX_ID;
+
+       return bsdf_microfacet_multi_ggx_common_setup(bsdf);
+}
+
+ccl_device int bsdf_microfacet_multi_ggx_aniso_fresnel_setup(MicrofacetBsdf *bsdf)
+{
+       if(is_zero(bsdf->T))
+               bsdf->T = make_float3(1.0f, 0.0f, 0.0f);
+
+       bsdf->type = CLOSURE_BSDF_MICROFACET_MULTI_GGX_FRESNEL_ID;
+
        return bsdf_microfacet_multi_ggx_common_setup(bsdf);
 }
 
@@ -363,6 +376,26 @@ ccl_device int bsdf_microfacet_multi_ggx_setup(MicrofacetBsdf *bsdf)
 {
        bsdf->alpha_y = bsdf->alpha_x;
 
+       bsdf->type = CLOSURE_BSDF_MICROFACET_MULTI_GGX_ID;
+
+       return bsdf_microfacet_multi_ggx_common_setup(bsdf);
+}
+
+ccl_device int bsdf_microfacet_multi_ggx_fresnel_setup(MicrofacetBsdf *bsdf)
+{
+       bsdf->alpha_y = bsdf->alpha_x;
+
+       bsdf->type = CLOSURE_BSDF_MICROFACET_MULTI_GGX_FRESNEL_ID;
+
+       return bsdf_microfacet_multi_ggx_common_setup(bsdf);
+}
+
+ccl_device int bsdf_microfacet_multi_ggx_refraction_setup(MicrofacetBsdf *bsdf)
+{
+       bsdf->alpha_y = bsdf->alpha_x;
+
+       bsdf->type = CLOSURE_BSDF_MICROFACET_MULTI_GGX_ID;
+
        return bsdf_microfacet_multi_ggx_common_setup(bsdf);
 }
 
@@ -378,6 +411,8 @@ ccl_device float3 bsdf_microfacet_multi_ggx_eval_reflect(const ShaderClosure *sc
                return make_float3(0.0f, 0.0f, 0.0f);
        }
 
+       bool use_fresnel = (bsdf->type == CLOSURE_BSDF_MICROFACET_MULTI_GGX_FRESNEL_ID);
+
        bool is_aniso = (bsdf->alpha_x != bsdf->alpha_y);
        float3 X, Y, Z;
        Z = bsdf->N;
@@ -393,7 +428,7 @@ ccl_device float3 bsdf_microfacet_multi_ggx_eval_reflect(const ShaderClosure *sc
                *pdf = mf_ggx_aniso_pdf(localI, localO, make_float2(bsdf->alpha_x, bsdf->alpha_y));
        else
                *pdf = mf_ggx_pdf(localI, localO, bsdf->alpha_x);
-       return mf_eval_glossy(localI, localO, true, bsdf->extra->color, bsdf->alpha_x, bsdf->alpha_y, lcg_state, NULL, NULL);
+       return mf_eval_glossy(localI, localO, true, bsdf->extra->color, bsdf->alpha_x, bsdf->alpha_y, lcg_state, NULL, NULL, bsdf->ior, use_fresnel, bsdf->extra->cspec0);
 }
 
 ccl_device int bsdf_microfacet_multi_ggx_sample(KernelGlobals *kg, const ShaderClosure *sc, float3 Ng, float3 I, float3 dIdx, float3 dIdy, float randu, float randv, float3 *eval, float3 *omega_in, float3 *domega_in_dx, float3 *domega_in_dy, float *pdf, ccl_addr_space uint *lcg_state)
@@ -410,6 +445,8 @@ ccl_device int bsdf_microfacet_multi_ggx_sample(KernelGlobals *kg, const ShaderC
                return LABEL_REFLECT|LABEL_SINGULAR;
        }
 
+       bool use_fresnel = (bsdf->type == CLOSURE_BSDF_MICROFACET_MULTI_GGX_FRESNEL_ID);
+
        bool is_aniso = (bsdf->alpha_x != bsdf->alpha_y);
        if(is_aniso)
                make_orthonormals_tangent(Z, bsdf->T, &X, &Y);
@@ -419,7 +456,7 @@ ccl_device int bsdf_microfacet_multi_ggx_sample(KernelGlobals *kg, const ShaderC
        float3 localI = make_float3(dot(I, X), dot(I, Y), dot(I, Z));
        float3 localO;
 
-       *eval = mf_sample_glossy(localI, &localO, bsdf->extra->color, bsdf->alpha_x, bsdf->alpha_y, lcg_state, NULL, NULL);
+       *eval = mf_sample_glossy(localI, &localO, bsdf->extra->color, bsdf->alpha_x, bsdf->alpha_y, lcg_state, NULL, NULL, bsdf->ior, use_fresnel, bsdf->extra->cspec0);
        if(is_aniso)
                *pdf = mf_ggx_aniso_pdf(localI, localO, make_float2(bsdf->alpha_x, bsdf->alpha_y));
        else
@@ -450,6 +487,23 @@ ccl_device int bsdf_microfacet_multi_ggx_glass_setup(MicrofacetBsdf *bsdf)
        return SD_BSDF|SD_BSDF_HAS_EVAL|SD_BSDF_NEEDS_LCG;
 }
 
+ccl_device int bsdf_microfacet_multi_ggx_glass_fresnel_setup(MicrofacetBsdf *bsdf)
+{
+       bsdf->alpha_x = clamp(bsdf->alpha_x, 1e-4f, 1.0f);
+       bsdf->alpha_y = bsdf->alpha_x;
+       bsdf->ior = max(0.0f, bsdf->ior);
+       bsdf->extra->color.x = saturate(bsdf->extra->color.x);
+       bsdf->extra->color.y = saturate(bsdf->extra->color.y);
+       bsdf->extra->color.z = saturate(bsdf->extra->color.z);
+       bsdf->extra->cspec0.x = saturate(bsdf->extra->cspec0.x);
+       bsdf->extra->cspec0.y = saturate(bsdf->extra->cspec0.y);
+       bsdf->extra->cspec0.z = saturate(bsdf->extra->cspec0.z);
+
+       bsdf->type = CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_FRESNEL_ID;
+
+       return SD_BSDF|SD_BSDF_HAS_EVAL|SD_BSDF_NEEDS_LCG;
+}
+
 ccl_device float3 bsdf_microfacet_multi_ggx_glass_eval_transmit(const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf, ccl_addr_space uint *lcg_state) {
        const MicrofacetBsdf *bsdf = (const MicrofacetBsdf*)sc;
 
@@ -465,7 +519,7 @@ ccl_device float3 bsdf_microfacet_multi_ggx_glass_eval_transmit(const ShaderClos
        float3 localO = make_float3(dot(omega_in, X), dot(omega_in, Y), dot(omega_in, Z));
 
        *pdf = mf_glass_pdf(localI, localO, bsdf->alpha_x, bsdf->ior);
-       return mf_eval_glass(localI, localO, false, bsdf->extra->color, bsdf->alpha_x, bsdf->alpha_y, lcg_state, bsdf->ior);
+       return mf_eval_glass(localI, localO, false, bsdf->extra->color, bsdf->alpha_x, bsdf->alpha_y, lcg_state, bsdf->ior, false, bsdf->extra->color);
 }
 
 ccl_device float3 bsdf_microfacet_multi_ggx_glass_eval_reflect(const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf, ccl_addr_space uint *lcg_state) {
@@ -475,6 +529,8 @@ ccl_device float3 bsdf_microfacet_multi_ggx_glass_eval_reflect(const ShaderClosu
                return make_float3(0.0f, 0.0f, 0.0f);
        }
 
+       bool use_fresnel = (bsdf->type == CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_FRESNEL_ID);
+
        float3 X, Y, Z;
        Z = bsdf->N;
        make_orthonormals(Z, &X, &Y);
@@ -483,7 +539,7 @@ ccl_device float3 bsdf_microfacet_multi_ggx_glass_eval_reflect(const ShaderClosu
        float3 localO = make_float3(dot(omega_in, X), dot(omega_in, Y), dot(omega_in, Z));
 
        *pdf = mf_glass_pdf(localI, localO, bsdf->alpha_x, bsdf->ior);
-       return mf_eval_glass(localI, localO, true, bsdf->extra->color, bsdf->alpha_x, bsdf->alpha_y, lcg_state, bsdf->ior);
+       return mf_eval_glass(localI, localO, true, bsdf->extra->color, bsdf->alpha_x, bsdf->alpha_y, lcg_state, bsdf->ior, use_fresnel, bsdf->extra->cspec0);
 }
 
 ccl_device int bsdf_microfacet_multi_ggx_glass_sample(KernelGlobals *kg, const ShaderClosure *sc, float3 Ng, float3 I, float3 dIdx, float3 dIdy, float randu, float randv, float3 *eval, float3 *omega_in, float3 *domega_in_dx, float3 *domega_in_dy, float *pdf, ccl_addr_space uint *lcg_state)
@@ -525,12 +581,14 @@ ccl_device int bsdf_microfacet_multi_ggx_glass_sample(KernelGlobals *kg, const S
                }
        }
 
+       bool use_fresnel = (bsdf->type == CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_FRESNEL_ID);
+
        make_orthonormals(Z, &X, &Y);
 
        float3 localI = make_float3(dot(I, X), dot(I, Y), dot(I, Z));
        float3 localO;
 
-       *eval = mf_sample_glass(localI, &localO, bsdf->extra->color, bsdf->alpha_x, bsdf->alpha_y, lcg_state, bsdf->ior);
+       *eval = mf_sample_glass(localI, &localO, bsdf->extra->color, bsdf->alpha_x, bsdf->alpha_y, lcg_state, bsdf->ior, use_fresnel, bsdf->extra->cspec0);
        *pdf = mf_glass_pdf(localI, localO, bsdf->alpha_x, bsdf->ior);
        *eval *= *pdf;
 
index 8054fa8e84932e8ba6f8491c8e7b5da1b7cbff1b..16d900088cbf504aceee4b0303e7b5e24a8c298d 100644 (file)
@@ -35,8 +35,13 @@ ccl_device_forceinline float3 MF_FUNCTION_FULL_NAME(mf_eval)(
          ccl_addr_space uint *lcg_state
 #ifdef MF_MULTI_GLASS
         , const float eta
+        , bool use_fresnel
+        , const float3 cspec0
 #elif defined(MF_MULTI_GLOSSY)
-        , float3 *n, float3 *k
+         , float3 *n, float3 *k
+         , const float eta
+         , bool use_fresnel
+         , const float3 cspec0
 #endif
 )
 {
@@ -71,12 +76,20 @@ ccl_device_forceinline float3 MF_FUNCTION_FULL_NAME(mf_eval)(
 
        /* Analytically compute single scattering for lower noise. */
        float3 eval;
+       float3 throughput = make_float3(1.0f, 1.0f, 1.0f);
 #ifdef MF_MULTI_GLASS
        eval = mf_eval_phase_glass(-wi, lambda_r, wo, wo_outside, alpha, eta);
        if(wo_outside)
                eval *= -lambda_r / (shadowing_lambda - lambda_r);
        else
                eval *= -lambda_r * beta(-lambda_r, shadowing_lambda+1.0f);
+
+       float F0 = fresnel_dielectric_cos(1.0f, eta);
+       if(use_fresnel) {
+               throughput = interpolate_fresnel_color(wi, normalize(wi + wo), eta, F0, cspec0);
+
+               eval *= throughput;
+       }
 #elif defined(MF_MULTI_DIFFUSE)
        /* Diffuse has no special closed form for the single scattering bounce */
        eval = make_float3(0.0f, 0.0f, 0.0f);
@@ -94,6 +107,13 @@ ccl_device_forceinline float3 MF_FUNCTION_FULL_NAME(mf_eval)(
        else {
                eval = make_float3(val, val, val);
        }
+
+       float F0 = fresnel_dielectric_cos(1.0f, eta);
+       if(use_fresnel) {
+               throughput = interpolate_fresnel_color(wi, wh, eta, F0, cspec0);
+
+               eval = throughput * val;
+       }
 #endif
 
        float3 wr = -wi;
@@ -101,7 +121,6 @@ ccl_device_forceinline float3 MF_FUNCTION_FULL_NAME(mf_eval)(
        float C1_r = 1.0f;
        float G1_r = 0.0f;
        bool outside = true;
-       float3 throughput = make_float3(1.0f, 1.0f, 1.0f);
 
        for(int order = 0; order < 10; order++) {
                /* Sample microfacet height and normal */
@@ -116,6 +135,18 @@ ccl_device_forceinline float3 MF_FUNCTION_FULL_NAME(mf_eval)(
                        const float G2_G1 = -lambda_r / (shadowing_lambda - lambda_r);
                        eval += throughput * G2_G1 * mf_eval_phase_diffuse(wo, wm);
                }
+#endif
+#ifdef MF_MULTI_GLASS
+               if(order == 0 && use_fresnel) {
+                       /* Evaluate amount of scattering towards wo on this microfacet. */
+                       float3 phase;
+                       if(outside)
+                               phase = mf_eval_phase_glass(wr, lambda_r, wo, wo_outside, alpha, eta);
+                       else
+                               phase = mf_eval_phase_glass(wr, lambda_r, -wo, !wo_outside, alpha, 1.0f / eta);
+
+                       eval = throughput * phase * mf_G1(wo_outside ? wo : -wo, mf_C1((outside == wo_outside) ? hr : -hr), shadowing_lambda);
+               }
 #endif
                if(order > 0) {
                        /* Evaluate amount of scattering towards wo on this microfacet. */
@@ -136,23 +167,39 @@ ccl_device_forceinline float3 MF_FUNCTION_FULL_NAME(mf_eval)(
                        /* Bounce from the microfacet. */
 #ifdef MF_MULTI_GLASS
                        bool next_outside;
+                       float3 wi_prev = -wr;
                        wr = mf_sample_phase_glass(-wr, outside? eta: 1.0f/eta, wm, lcg_step_float_addrspace(lcg_state), &next_outside);
                        if(!next_outside) {
                                outside = !outside;
                                wr = -wr;
                                hr = -hr;
                        }
+
+                       if(use_fresnel && !next_outside) {
+                               throughput *= color;
+                       }
+                       else if(use_fresnel && order > 0) {
+                               throughput *= interpolate_fresnel_color(wi_prev, wm, eta, F0, cspec0);
+                       }
 #elif defined(MF_MULTI_DIFFUSE)
                        wr = mf_sample_phase_diffuse(wm,
                                                     lcg_step_float_addrspace(lcg_state),
                                                     lcg_step_float_addrspace(lcg_state));
 #else /* MF_MULTI_GLOSSY */
+                       if(use_fresnel && order > 0) {
+                               throughput *= interpolate_fresnel_color(-wr, wm, eta, F0, cspec0);
+                       }
                        wr = mf_sample_phase_glossy(-wr, n, k, &throughput, wm);
 #endif
 
                        lambda_r = mf_lambda(wr, alpha);
 
+#if defined(MF_MULTI_GLOSSY) || defined(MF_MULTI_GLASS)
+                       if(!use_fresnel)
+                               throughput *= color;
+#else
                        throughput *= color;
+#endif
 
                        C1_r = mf_C1(hr);
                        G1_r = mf_G1(wr, C1_r, lambda_r);
@@ -171,8 +218,13 @@ ccl_device_forceinline float3 MF_FUNCTION_FULL_NAME(mf_eval)(
 ccl_device_forceinline float3 MF_FUNCTION_FULL_NAME(mf_sample)(float3 wi, float3 *wo, const float3 color, const float alpha_x, const float alpha_y, ccl_addr_space uint *lcg_state
 #ifdef MF_MULTI_GLASS
        , const float eta
+       , bool use_fresnel
+       , const float3 cspec0
 #elif defined(MF_MULTI_GLOSSY)
        , float3 *n, float3 *k
+       , const float eta
+       , bool use_fresnel
+       , const float3 cspec0
 #endif
 )
 {
@@ -185,6 +237,17 @@ ccl_device_forceinline float3 MF_FUNCTION_FULL_NAME(mf_sample)(float3 wi, float3
        float C1_r = 1.0f;
        float G1_r = 0.0f;
        bool outside = true;
+#ifdef MF_MULTI_GLASS
+       float F0 = fresnel_dielectric_cos(1.0f, eta);
+       if(use_fresnel) {
+               throughput = interpolate_fresnel_color(wi, normalize(wi + wr), eta, F0, cspec0);
+       }
+#elif defined(MF_MULTI_GLOSSY)
+       float F0 = fresnel_dielectric_cos(1.0f, eta);
+       if(use_fresnel) {
+               throughput = interpolate_fresnel_color(wi, normalize(wi + wr), eta, F0, cspec0);
+       }
+#endif
 
        int order;
        for(order = 0; order < 10; order++) {
@@ -199,23 +262,51 @@ ccl_device_forceinline float3 MF_FUNCTION_FULL_NAME(mf_sample)(float3 wi, float3
                                                                   lcg_step_float_addrspace(lcg_state)));
 
                /* First-bounce color is already accounted for in mix weight. */
+#if defined(MF_MULTI_GLASS) || defined(MF_MULTI_GLOSSY)
+               if(!use_fresnel && order > 0)
+                       throughput *= color;
+#else
                if(order > 0)
                        throughput *= color;
+#endif
 
                /* Bounce from the microfacet. */
 #ifdef MF_MULTI_GLASS
                bool next_outside;
+               float3 wi_prev = -wr;
                wr = mf_sample_phase_glass(-wr, outside? eta: 1.0f/eta, wm, lcg_step_float_addrspace(lcg_state), &next_outside);
                if(!next_outside) {
                        hr = -hr;
                        wr = -wr;
                        outside = !outside;
                }
+
+               if(use_fresnel) {
+                       if(!next_outside) {
+                               throughput *= color;
+                       }
+                       else {
+                               float3 t_color = interpolate_fresnel_color(wi_prev, wm, eta, F0, cspec0);
+
+                               if(order == 0)
+                                       throughput = t_color;
+                               else
+                                       throughput *= t_color;
+                       }
+               }
 #elif defined(MF_MULTI_DIFFUSE)
                wr = mf_sample_phase_diffuse(wm,
                                             lcg_step_float_addrspace(lcg_state),
                                             lcg_step_float_addrspace(lcg_state));
 #else /* MF_MULTI_GLOSSY */
+               if(use_fresnel) {
+                       float3 t_color = interpolate_fresnel_color(-wr, wm, eta, F0, cspec0);
+
+                       if(order == 0)
+                               throughput = t_color;
+                       else
+                               throughput *= t_color;
+               }
                wr = mf_sample_phase_glossy(-wr, n, k, &throughput, wm);
 #endif
 
diff --git a/intern/cycles/kernel/closure/bsdf_principled_diffuse.h b/intern/cycles/kernel/closure/bsdf_principled_diffuse.h
new file mode 100644 (file)
index 0000000..8a11669
--- /dev/null
@@ -0,0 +1,120 @@
+/*
+ * Copyright 2011-2017 Blender Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __BSDF_PRINCIPLED_DIFFUSE_H__
+#define __BSDF_PRINCIPLED_DIFFUSE_H__
+
+/* DISNEY PRINCIPLED DIFFUSE BRDF
+ *
+ * Shading model by Brent Burley (Disney): "Physically Based Shading at Disney" (2012)
+ */
+
+CCL_NAMESPACE_BEGIN
+
+typedef ccl_addr_space struct PrincipledDiffuseBsdf {
+       SHADER_CLOSURE_BASE;
+
+       float roughness;
+       float3 N;
+} PrincipledDiffuseBsdf;
+
+ccl_device float3 calculate_principled_diffuse_brdf(const PrincipledDiffuseBsdf *bsdf,
+       float3 N, float3 V, float3 L, float3 H, float *pdf)
+{
+       float NdotL = max(dot(N, L), 0.0f);
+       float NdotV = max(dot(N, V), 0.0f);
+
+       if(NdotL < 0 || NdotV < 0) {
+               *pdf = 0.0f;
+               return make_float3(0.0f, 0.0f, 0.0f);
+       }
+
+       float LdotH = dot(L, H);
+
+       float FL = schlick_fresnel(NdotL), FV = schlick_fresnel(NdotV);
+       const float Fd90 = 0.5f + 2.0f * LdotH*LdotH * bsdf->roughness;
+       float Fd = (1.0f * (1.0f - FL) + Fd90 * FL) * (1.0f * (1.0f - FV) + Fd90 * FV);
+
+       float value = M_1_PI_F * NdotL * Fd;
+
+       return make_float3(value, value, value);
+}
+
+ccl_device int bsdf_principled_diffuse_setup(PrincipledDiffuseBsdf *bsdf)
+{
+       bsdf->type = CLOSURE_BSDF_PRINCIPLED_DIFFUSE_ID;
+       return SD_BSDF|SD_BSDF_HAS_EVAL;
+}
+
+ccl_device float3 bsdf_principled_diffuse_eval_reflect(const ShaderClosure *sc, const float3 I,
+       const float3 omega_in, float *pdf)
+{
+       const PrincipledDiffuseBsdf *bsdf = (const PrincipledDiffuseBsdf *)sc;
+
+       float3 N = bsdf->N;
+       float3 V = I; // outgoing
+       float3 L = omega_in; // incoming
+       float3 H = normalize(L + V);
+
+       if(dot(N, omega_in) > 0.0f) {
+               *pdf = fmaxf(dot(N, omega_in), 0.0f) * M_1_PI_F;
+               return calculate_principled_diffuse_brdf(bsdf, N, V, L, H, pdf);
+       }
+       else {
+               *pdf = 0.0f;
+               return make_float3(0.0f, 0.0f, 0.0f);
+       }
+}
+
+ccl_device float3 bsdf_principled_diffuse_eval_transmit(const ShaderClosure *sc, const float3 I,
+       const float3 omega_in, float *pdf)
+{
+       return make_float3(0.0f, 0.0f, 0.0f);
+}
+
+ccl_device int bsdf_principled_diffuse_sample(const ShaderClosure *sc,
+       float3 Ng, float3 I, float3 dIdx, float3 dIdy, float randu, float randv,
+       float3 *eval, float3 *omega_in, float3 *domega_in_dx,
+       float3 *domega_in_dy, float *pdf)
+{
+       const PrincipledDiffuseBsdf *bsdf = (const PrincipledDiffuseBsdf *)sc;
+
+       float3 N = bsdf->N;
+
+       sample_cos_hemisphere(N, randu, randv, omega_in, pdf);
+
+       if(dot(Ng, *omega_in) > 0) {
+               float3 H = normalize(I + *omega_in);
+
+               *eval = calculate_principled_diffuse_brdf(bsdf, N, I, *omega_in, H, pdf);
+
+#ifdef __RAY_DIFFERENTIALS__
+               // TODO: find a better approximation for the diffuse bounce
+               *domega_in_dx = -((2 * dot(N, dIdx)) * N - dIdx);
+               *domega_in_dy = -((2 * dot(N, dIdy)) * N - dIdy);
+#endif
+       }
+       else {
+               *pdf = 0.0f;
+       }
+       return LABEL_REFLECT|LABEL_DIFFUSE;
+}
+
+CCL_NAMESPACE_END
+
+#endif /* __BSDF_PRINCIPLED_DIFFUSE_H__ */
+
+
diff --git a/intern/cycles/kernel/closure/bsdf_principled_sheen.h b/intern/cycles/kernel/closure/bsdf_principled_sheen.h
new file mode 100644 (file)
index 0000000..58df4f7
--- /dev/null
@@ -0,0 +1,114 @@
+/*
+ * Copyright 2011-2017 Blender Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __BSDF_PRINCIPLED_SHEEN_H__
+#define __BSDF_PRINCIPLED_SHEEN_H__
+
+/* DISNEY PRINCIPLED SHEEN BRDF
+ *
+ * Shading model by Brent Burley (Disney): "Physically Based Shading at Disney" (2012)
+ */
+
+CCL_NAMESPACE_BEGIN
+
+typedef ccl_addr_space struct PrincipledSheenBsdf {
+       SHADER_CLOSURE_BASE;
+       float3 N;
+} PrincipledSheenBsdf;
+
+ccl_device float3 calculate_principled_sheen_brdf(const PrincipledSheenBsdf *bsdf,
+       float3 N, float3 V, float3 L, float3 H, float *pdf)
+{
+       float NdotL = dot(N, L);
+       float NdotV = dot(N, V);
+
+       if(NdotL < 0 || NdotV < 0) {
+               *pdf = 0.0f;
+               return make_float3(0.0f, 0.0f, 0.0f);
+       }
+
+       float LdotH = dot(L, H);
+
+       float value = schlick_fresnel(LdotH) * NdotL;
+
+       return make_float3(value, value, value);
+}
+
+ccl_device int bsdf_principled_sheen_setup(PrincipledSheenBsdf *bsdf)
+{
+       bsdf->type = CLOSURE_BSDF_PRINCIPLED_SHEEN_ID;
+       return SD_BSDF|SD_BSDF_HAS_EVAL;
+}
+
+ccl_device float3 bsdf_principled_sheen_eval_reflect(const ShaderClosure *sc, const float3 I,
+       const float3 omega_in, float *pdf)
+{
+       const PrincipledSheenBsdf *bsdf = (const PrincipledSheenBsdf *)sc;
+
+       float3 N = bsdf->N;
+       float3 V = I; // outgoing
+       float3 L = omega_in; // incoming
+       float3 H = normalize(L + V);
+
+       if(dot(N, omega_in) > 0.0f) {
+               *pdf = fmaxf(dot(N, omega_in), 0.0f) * M_1_PI_F;
+               return calculate_principled_sheen_brdf(bsdf, N, V, L, H, pdf);
+       }
+       else {
+               *pdf = 0.0f;
+               return make_float3(0.0f, 0.0f, 0.0f);
+       }
+}
+
+ccl_device float3 bsdf_principled_sheen_eval_transmit(const ShaderClosure *sc, const float3 I,
+       const float3 omega_in, float *pdf)
+{
+       return make_float3(0.0f, 0.0f, 0.0f);
+}
+
+ccl_device int bsdf_principled_sheen_sample(const ShaderClosure *sc,
+       float3 Ng, float3 I, float3 dIdx, float3 dIdy, float randu, float randv,
+       float3 *eval, float3 *omega_in, float3 *domega_in_dx,
+       float3 *domega_in_dy, float *pdf)
+{
+       const PrincipledSheenBsdf *bsdf = (const PrincipledSheenBsdf *)sc;
+
+       float3 N = bsdf->N;
+
+       sample_cos_hemisphere(N, randu, randv, omega_in, pdf);
+
+       if(dot(Ng, *omega_in) > 0) {
+               float3 H = normalize(I + *omega_in);
+
+               *eval = calculate_principled_sheen_brdf(bsdf, N, I, *omega_in, H, pdf);
+
+#ifdef __RAY_DIFFERENTIALS__
+               // TODO: find a better approximation for the diffuse bounce
+               *domega_in_dx = -((2 * dot(N, dIdx)) * N - dIdx);
+               *domega_in_dy = -((2 * dot(N, dIdy)) * N - dIdy);
+#endif
+       }
+       else {
+               *pdf = 0.0f;
+       }
+       return LABEL_REFLECT|LABEL_DIFFUSE;
+}
+
+CCL_NAMESPACE_END
+
+#endif /* __BSDF_PRINCIPLED_SHEEN_H__ */
+
+
index b0c5280b6cbb0efd64336b890ab8f6f56aa99007..3dc15d5791cbedef640e2a072c0da8b8f8355277 100644 (file)
@@ -124,6 +124,13 @@ ccl_device float3 fresnel_conductor(float cosi, const float3 eta, const float3 k
        return(Rparl2 + Rperp2) * 0.5f;
 }
 
+ccl_device float schlick_fresnel(float u)
+{
+       float m = clamp(1.0f - u, 0.0f, 1.0f);
+       float m2 = m * m;
+       return m2 * m2 * m; // pow(m, 5)
+}
+
 ccl_device float smooth_step(float edge0, float edge1, float x)
 {
        float result;
@@ -136,6 +143,19 @@ ccl_device float smooth_step(float edge0, float edge1, float x)
        return result;
 }
 
+/* Calculate the fresnel color which is a blend between white and the F0 color (cspec0) */
+ccl_device_forceinline float3 interpolate_fresnel_color(float3 L, float3 H, float ior, float F0, float3 cspec0) {
+       /* Calculate the fresnel interpolation factor
+        * The value from fresnel_dielectric_cos(...) has to be normalized because
+        * the cspec0 keeps the F0 color
+       */
+       float F0_norm = 1.0f / (1.0f - F0);
+       float FH = (fresnel_dielectric_cos(dot(L, H), ior) - F0) * F0_norm;
+
+       /* Blend between white and a specular color with respect to the fresnel */
+       return cspec0 * (1.0f - FH) + make_float3(1.0f, 1.0f, 1.0f) * FH;
+}
+
 CCL_NAMESPACE_END
 
 #endif /* __BSDF_UTIL_H__ */
index af0bbd861a9f4679da143c775ff2705ddd9f1207..8363cef53c8bcc875e195288f4339cead04a6160 100644 (file)
@@ -27,6 +27,7 @@ typedef ccl_addr_space struct Bssrdf {
        float d;
        float texture_blur;
        float albedo;
+       float roughness;
        float3 N;
 } Bssrdf;
 
@@ -360,10 +361,29 @@ ccl_device int bssrdf_setup(Bssrdf *bssrdf, ClosureType type)
 {
        if(bssrdf->radius < BSSRDF_MIN_RADIUS) {
                /* revert to diffuse BSDF if radius too small */
-               DiffuseBsdf *bsdf = (DiffuseBsdf*)bssrdf;
-               bsdf->N = bssrdf->N;
-               int flag = bsdf_diffuse_setup(bsdf);
-               bsdf->type = CLOSURE_BSDF_BSSRDF_ID;
+               int flag;
+               if(type == CLOSURE_BSSRDF_PRINCIPLED_ID) {
+                       float roughness = bssrdf->roughness;
+                       float3 N = bssrdf->N;
+                       float3 weight = bssrdf->weight;
+                       float sample_weight = bssrdf->sample_weight;
+
+                       PrincipledDiffuseBsdf *bsdf = (PrincipledDiffuseBsdf*)bssrdf;
+
+                       bsdf->N = N;
+                       bsdf->roughness = roughness;
+                       bsdf->weight = weight;
+                       bsdf->sample_weight = sample_weight;
+                       flag = bsdf_principled_diffuse_setup(bsdf);
+                       bsdf->type = CLOSURE_BSDF_BSSRDF_PRINCIPLED_ID;
+               }
+               else {
+                       DiffuseBsdf *bsdf = (DiffuseBsdf*)bssrdf;
+                       bsdf->N = bssrdf->N;
+                       flag = bsdf_diffuse_setup(bsdf);
+                       bsdf->type = CLOSURE_BSDF_BSSRDF_ID;
+               }
+               
                return flag;
        }
        else {
@@ -371,7 +391,7 @@ ccl_device int bssrdf_setup(Bssrdf *bssrdf, ClosureType type)
                bssrdf->sharpness = saturate(bssrdf->sharpness);
                bssrdf->type = type;
 
-               if(type == CLOSURE_BSSRDF_BURLEY_ID) {
+               if(type == CLOSURE_BSSRDF_BURLEY_ID || type == CLOSURE_BSSRDF_PRINCIPLED_ID) {
                        bssrdf_burley_setup(bssrdf);
                }
 
@@ -385,7 +405,7 @@ ccl_device void bssrdf_sample(const ShaderClosure *sc, float xi, float *r, float
                bssrdf_cubic_sample(sc, xi, r, h);
        else if(sc->type == CLOSURE_BSSRDF_GAUSSIAN_ID)
                bssrdf_gaussian_sample(sc, xi, r, h);
-       else /*if(sc->type == CLOSURE_BSSRDF_BURLEY_ID)*/
+       else /*if(sc->type == CLOSURE_BSSRDF_BURLEY_ID || sc->type == CLOSURE_BSSRDF_PRINCIPLED_ID)*/
                bssrdf_burley_sample(sc, xi, r, h);
 }
 
@@ -395,7 +415,7 @@ ccl_device_forceinline float bssrdf_pdf(const ShaderClosure *sc, float r)
                return bssrdf_cubic_pdf(sc, r);
        else if(sc->type == CLOSURE_BSSRDF_GAUSSIAN_ID)
                return bssrdf_gaussian_pdf(sc, r);
-       else /*if(sc->type == CLOSURE_BSSRDF_BURLEY_ID)*/
+       else /*if(sc->type == CLOSURE_BSSRDF_BURLEY_ID || sc->type == CLOSURE_BSSRDF_PRINCIPLED_ID)*/
                return bssrdf_burley_pdf(sc, r);
 }
 
index f75e9337bdbc4514443003d182585ae38dacdc2b..6c8b7cca4ce4e37547376af7a1b851ef5d618df8 100644 (file)
@@ -140,7 +140,7 @@ ccl_device_inline float3 subsurface_scatter_eval(ShaderData *sd,
 }
 
 /* replace closures with a single diffuse bsdf closure after scatter step */
-ccl_device void subsurface_scatter_setup_diffuse_bsdf(ShaderData *sd, float3 weight, bool hit, float3 N)
+ccl_device void subsurface_scatter_setup_diffuse_bsdf(ShaderData *sd, ShaderClosure *sc, float3 weight, bool hit, float3 N)
 {
        sd->flag &= ~SD_CLOSURE_FLAGS;
        sd->randb_closure = 0.0f;
@@ -148,15 +148,31 @@ ccl_device void subsurface_scatter_setup_diffuse_bsdf(ShaderData *sd, float3 wei
        sd->num_closure_extra = 0;
 
        if(hit) {
-               DiffuseBsdf *bsdf = (DiffuseBsdf*)bsdf_alloc(sd, sizeof(DiffuseBsdf), weight);
+               Bssrdf *bssrdf = (Bssrdf *)sc;
+               if(bssrdf->type == CLOSURE_BSSRDF_PRINCIPLED_ID) {
+                       PrincipledDiffuseBsdf *bsdf = (PrincipledDiffuseBsdf*)bsdf_alloc(sd, sizeof(PrincipledDiffuseBsdf), weight);
+
+                       if(bsdf) {
+                               bsdf->N = N;
+                               bsdf->roughness = bssrdf->roughness;
+                               sd->flag |= bsdf_principled_diffuse_setup(bsdf);
+
+                               /* replace CLOSURE_BSDF_PRINCIPLED_DIFFUSE_ID with this special ID so render passes
+                               * can recognize it as not being a regular Disney principled diffuse closure */
+                               bsdf->type = CLOSURE_BSDF_BSSRDF_PRINCIPLED_ID;
+                       }
+               }
+               else if(CLOSURE_IS_BSSRDF(bssrdf->type)) {
+                       DiffuseBsdf *bsdf = (DiffuseBsdf*)bsdf_alloc(sd, sizeof(DiffuseBsdf), weight);
 
-               if(bsdf) {
-                       bsdf->N = N;
-                       sd->flag |= bsdf_diffuse_setup(bsdf);
+                       if(bsdf) {
+                               bsdf->N = N;
+                               sd->flag |= bsdf_diffuse_setup(bsdf);
 
-                       /* replace CLOSURE_BSDF_DIFFUSE_ID with this special ID so render passes
-                        * can recognize it as not being a regular diffuse closure */
-                       bsdf->type = CLOSURE_BSDF_BSSRDF_ID;
+                               /* replace CLOSURE_BSDF_DIFFUSE_ID with this special ID so render passes
+                               * can recognize it as not being a regular diffuse closure */
+                               bsdf->type = CLOSURE_BSDF_BSSRDF_ID;
+                       }
                }
        }
 }
@@ -388,7 +404,7 @@ ccl_device_noinline void subsurface_scatter_multi_setup(
        subsurface_color_bump_blur(kg, sd, state, state_flag, &weight, &N);
 
        /* Setup diffuse BSDF. */
-       subsurface_scatter_setup_diffuse_bsdf(sd, weight, true, N);
+       subsurface_scatter_setup_diffuse_bsdf(sd, sc, weight, true, N);
 }
 
 #ifndef __SPLIT_KERNEL__
@@ -479,7 +495,7 @@ ccl_device void subsurface_scatter_step(KernelGlobals *kg, ShaderData *sd, PathS
        subsurface_color_bump_blur(kg, sd, state, state_flag, &eval, &N);
 
        /* setup diffuse bsdf */
-       subsurface_scatter_setup_diffuse_bsdf(sd, eval, (ss_isect.num_hits > 0), N);
+       subsurface_scatter_setup_diffuse_bsdf(sd, sc, eval, (ss_isect.num_hits > 0), N);
 }
 #endif /* ! __SPLIT_KERNEL__ */
 
index 95beea01d2564a88a2c8887714fd4da06fc5bc16..188c3960a5f3c77b19f77d68b52397fc9702c23f 100644 (file)
@@ -39,7 +39,9 @@
 #include "kernel/kernel_montecarlo.h"
 
 #include "kernel/closure/alloc.h"
+#include "kernel/closure/bsdf_util.h"
 #include "kernel/closure/bsdf_diffuse.h"
+#include "kernel/closure/bsdf_principled_diffuse.h"
 #include "kernel/closure/bssrdf.h"
 
 CCL_NAMESPACE_BEGIN
@@ -78,6 +80,7 @@ public:
                                bssrdf->albedo = albedo.x;
                                bssrdf->sharpness = sharpness;
                                bssrdf->N = params.N;
+                               bssrdf->roughness = params.roughness;
                                sd->flag |= bssrdf_setup(bssrdf, (ClosureType)type);
                        }
 
@@ -89,6 +92,7 @@ public:
                                bssrdf->albedo = albedo.y;
                                bssrdf->sharpness = sharpness;
                                bssrdf->N = params.N;
+                               bssrdf->roughness = params.roughness;
                                sd->flag |= bssrdf_setup(bssrdf, (ClosureType)type);
                        }
 
@@ -100,6 +104,7 @@ public:
                                bssrdf->albedo = albedo.z;
                                bssrdf->sharpness = sharpness;
                                bssrdf->N = params.N;
+                               bssrdf->roughness = params.roughness;
                                sd->flag |= bssrdf_setup(bssrdf, (ClosureType)type);
                        }
                }
@@ -180,5 +185,31 @@ ClosureParam *closure_bssrdf_burley_params()
 
 CCLOSURE_PREPARE(closure_bssrdf_burley_prepare, BurleyBSSRDFClosure)
 
+/* Disney principled */
+
+class PrincipledBSSRDFClosure : public CBSSRDFClosure {
+public:
+       void setup(ShaderData *sd, int path_flag, float3 weight)
+       {
+               alloc(sd, path_flag, weight * albedo, CLOSURE_BSSRDF_PRINCIPLED_ID);
+       }
+};
+
+ClosureParam *closure_bssrdf_principled_params()
+{
+       static ClosureParam params[] = {
+               CLOSURE_FLOAT3_PARAM(PrincipledBSSRDFClosure, params.N),
+               CLOSURE_FLOAT3_PARAM(PrincipledBSSRDFClosure, radius),
+               CLOSURE_FLOAT_PARAM(PrincipledBSSRDFClosure, params.texture_blur),
+               CLOSURE_FLOAT3_PARAM(PrincipledBSSRDFClosure, albedo),
+               CLOSURE_FLOAT_PARAM(PrincipledBSSRDFClosure, params.roughness),
+               CLOSURE_STRING_KEYPARAM(PrincipledBSSRDFClosure, label, "label"),
+               CLOSURE_FINISH_PARAM(PrincipledBSSRDFClosure)
+       };
+       return params;
+}
+
+CCLOSURE_PREPARE(closure_bssrdf_principled_prepare, PrincipledBSSRDFClosure)
+
 CCL_NAMESPACE_END
 
index f44714c2150f372c9f3233bbc2f715861c8abe73..5b66793a05da22f79ce2263f468c972cedd4340c 100644 (file)
@@ -60,6 +60,8 @@
 #include "kernel/closure/bsdf_ashikhmin_shirley.h"
 #include "kernel/closure/bsdf_toon.h"
 #include "kernel/closure/bsdf_hair.h"
+#include "kernel/closure/bsdf_principled_diffuse.h"
+#include "kernel/closure/bsdf_principled_sheen.h"
 #include "kernel/closure/volume.h"
 
 CCL_NAMESPACE_BEGIN
@@ -176,6 +178,63 @@ VOLUME_CLOSURE_CLASS_END(VolumeHenyeyGreenstein, henyey_greenstein)
 VOLUME_CLOSURE_CLASS_BEGIN(VolumeAbsorption, absorption, ShaderClosure, LABEL_SINGULAR)
 VOLUME_CLOSURE_CLASS_END(VolumeAbsorption, absorption)
 
+BSDF_CLOSURE_CLASS_BEGIN(PrincipledDiffuse, principled_diffuse, PrincipledDiffuseBsdf, LABEL_DIFFUSE)
+       CLOSURE_FLOAT3_PARAM(PrincipledDiffuseClosure, params.N),
+       CLOSURE_FLOAT_PARAM(PrincipledDiffuseClosure, params.roughness),
+BSDF_CLOSURE_CLASS_END(PrincipledDiffuse, principled_diffuse)
+
+BSDF_CLOSURE_CLASS_BEGIN(PrincipledSheen, principled_sheen, PrincipledSheenBsdf, LABEL_DIFFUSE)
+       CLOSURE_FLOAT3_PARAM(PrincipledSheenClosure, params.N),
+BSDF_CLOSURE_CLASS_END(PrincipledSheen, principled_sheen)
+
+/* DISNEY PRINCIPLED CLEARCOAT */
+class PrincipledClearcoatClosure : public CBSDFClosure {
+public:
+       MicrofacetBsdf params;
+       float clearcoat, clearcoat_gloss;
+
+       MicrofacetBsdf *alloc(ShaderData *sd, int path_flag, float3 weight)
+       {
+               MicrofacetBsdf *bsdf = (MicrofacetBsdf*)bsdf_alloc_osl(sd, sizeof(MicrofacetBsdf), weight, &params);
+               MicrofacetExtra *extra = (MicrofacetExtra*)closure_alloc_extra(sd, sizeof(MicrofacetExtra));
+               if(bsdf && extra) {
+                       bsdf->extra = extra;
+
+                       bsdf->ior = 1.5f;
+
+                       bsdf->alpha_x = 0.1f * (1.0f - clearcoat_gloss) + 0.001f * clearcoat_gloss;
+                       bsdf->alpha_y = 0.1f * (1.0f - clearcoat_gloss) + 0.001f * clearcoat_gloss;
+
+                       bsdf->extra->cspec0 = make_float3(0.04f, 0.04f, 0.04f);
+                       bsdf->extra->clearcoat = clearcoat;
+
+                       return bsdf;
+               }
+
+               return NULL;
+       }
+
+       void setup(ShaderData *sd, int path_flag, float3 weight)
+       {
+               MicrofacetBsdf *bsdf = alloc(sd, path_flag, weight);
+               sd->flag |= (bsdf) ? bsdf_microfacet_ggx_clearcoat_setup(bsdf) : 0;
+       }
+};
+
+ClosureParam *closure_bsdf_principled_clearcoat_params()
+{
+       static ClosureParam params[] = {
+               CLOSURE_FLOAT3_PARAM(PrincipledClearcoatClosure, params.N),
+               CLOSURE_FLOAT_PARAM(PrincipledClearcoatClosure, clearcoat),
+               CLOSURE_FLOAT_PARAM(PrincipledClearcoatClosure, clearcoat_gloss),
+               CLOSURE_STRING_KEYPARAM(PrincipledClearcoatClosure, label, "label"),
+               CLOSURE_FINISH_PARAM(PrincipledClearcoatClosure)
+       };
+       return params;
+}
+CCLOSURE_PREPARE(closure_bsdf_principled_clearcoat_prepare, PrincipledClearcoatClosure)
+
+
 /* Registration */
 
 static void register_closure(OSL::ShadingSystem *ss, const char *name, int id, OSL::ClosureParam *params, OSL::PrepareClosureFunc prepare)
@@ -215,6 +274,16 @@ void OSLShader::register_closures(OSLShadingSystem *ss_)
                closure_bsdf_microfacet_multi_ggx_glass_params(), closure_bsdf_microfacet_multi_ggx_glass_prepare);
        register_closure(ss, "microfacet_multi_ggx_aniso", id++,
                closure_bsdf_microfacet_multi_ggx_aniso_params(), closure_bsdf_microfacet_multi_ggx_aniso_prepare);
+       register_closure(ss, "microfacet_ggx_fresnel", id++,
+               closure_bsdf_microfacet_ggx_fresnel_params(), closure_bsdf_microfacet_ggx_fresnel_prepare);
+       register_closure(ss, "microfacet_ggx_aniso_fresnel", id++,
+               closure_bsdf_microfacet_ggx_aniso_fresnel_params(), closure_bsdf_microfacet_ggx_aniso_fresnel_prepare);
+       register_closure(ss, "microfacet_multi_ggx_fresnel", id++,
+               closure_bsdf_microfacet_multi_ggx_fresnel_params(), closure_bsdf_microfacet_multi_ggx_fresnel_prepare);
+       register_closure(ss, "microfacet_multi_ggx_glass_fresnel", id++,
+               closure_bsdf_microfacet_multi_ggx_glass_fresnel_params(), closure_bsdf_microfacet_multi_ggx_glass_fresnel_prepare);
+       register_closure(ss, "microfacet_multi_ggx_aniso_fresnel", id++,
+               closure_bsdf_microfacet_multi_ggx_aniso_fresnel_params(), closure_bsdf_microfacet_multi_ggx_aniso_fresnel_prepare);
        register_closure(ss, "microfacet_beckmann", id++,
                bsdf_microfacet_beckmann_params(), bsdf_microfacet_beckmann_prepare);
        register_closure(ss, "microfacet_beckmann_aniso", id++,
@@ -229,6 +298,12 @@ void OSLShader::register_closures(OSLShadingSystem *ss_)
                bsdf_diffuse_toon_params(), bsdf_diffuse_toon_prepare);
        register_closure(ss, "glossy_toon", id++,
                bsdf_glossy_toon_params(), bsdf_glossy_toon_prepare);
+       register_closure(ss, "principled_diffuse", id++,
+               bsdf_principled_diffuse_params(), bsdf_principled_diffuse_prepare);
+       register_closure(ss, "principled_sheen", id++,
+               bsdf_principled_sheen_params(), bsdf_principled_sheen_prepare);
+       register_closure(ss, "principled_clearcoat", id++,
+               closure_bsdf_principled_clearcoat_params(), closure_bsdf_principled_clearcoat_prepare);
 
        register_closure(ss, "emission", id++,
                closure_emission_params(), closure_emission_prepare);
@@ -248,6 +323,8 @@ void OSLShader::register_closures(OSLShadingSystem *ss_)
                closure_bssrdf_gaussian_params(), closure_bssrdf_gaussian_prepare);
        register_closure(ss, "bssrdf_burley", id++,
                closure_bssrdf_burley_params(), closure_bssrdf_burley_prepare);
+       register_closure(ss, "bssrdf_principled", id++,
+               closure_bssrdf_principled_params(), closure_bssrdf_principled_prepare);
 
        register_closure(ss, "hair_reflection", id++,
                bsdf_hair_reflection_params(), bsdf_hair_reflection_prepare);
@@ -278,6 +355,86 @@ bool CBSDFClosure::skip(const ShaderData *sd, int path_flag, int scattering)
        return false;
 }
 
+
+/* GGX closures with Fresnel */
+
+class MicrofacetFresnelClosure : public CBSDFClosure {
+public:
+       MicrofacetBsdf params;
+       float3 color;
+       float3 cspec0;
+
+       MicrofacetBsdf *alloc(ShaderData *sd, int path_flag, float3 weight)
+       {
+               /* Technically, the MultiGGX Glass closure may also transmit. However,
+               * since this is set statically and only used for caustic flags, this
+               * is probably as good as it gets. */
+               if(!skip(sd, path_flag, LABEL_GLOSSY | LABEL_REFLECT)) {
+                       MicrofacetBsdf *bsdf = (MicrofacetBsdf*)bsdf_alloc_osl(sd, sizeof(MicrofacetBsdf), weight, &params);
+                       MicrofacetExtra *extra = (MicrofacetExtra*)closure_alloc_extra(sd, sizeof(MicrofacetExtra));
+                       if(bsdf && extra) {
+                               bsdf->extra = extra;
+                               bsdf->extra->color = color;
+                               bsdf->extra->cspec0 = cspec0;
+                               return bsdf;
+                       }
+               }
+
+               return NULL;
+       }
+};
+
+class MicrofacetGGXFresnelClosure : public MicrofacetFresnelClosure {
+public:
+       void setup(ShaderData *sd, int path_flag, float3 weight)
+       {
+               MicrofacetBsdf *bsdf = alloc(sd, path_flag, weight);
+               sd->flag |= (bsdf) ? bsdf_microfacet_ggx_fresnel_setup(bsdf) : 0;
+       }
+};
+
+ClosureParam *closure_bsdf_microfacet_ggx_fresnel_params()
+{
+       static ClosureParam params[] = {
+               CLOSURE_FLOAT3_PARAM(MicrofacetGGXFresnelClosure, params.N),
+               CLOSURE_FLOAT_PARAM(MicrofacetGGXFresnelClosure, params.alpha_x),
+               CLOSURE_FLOAT_PARAM(MicrofacetGGXFresnelClosure, params.ior),
+               CLOSURE_FLOAT3_PARAM(MicrofacetGGXFresnelClosure, color),
+               CLOSURE_FLOAT3_PARAM(MicrofacetGGXFresnelClosure, cspec0),
+               CLOSURE_STRING_KEYPARAM(MicrofacetGGXFresnelClosure, label, "label"),
+               CLOSURE_FINISH_PARAM(MicrofacetGGXFresnelClosure)
+       };
+       return params;
+}
+CCLOSURE_PREPARE(closure_bsdf_microfacet_ggx_fresnel_prepare, MicrofacetGGXFresnelClosure);
+
+class MicrofacetGGXAnisoFresnelClosure : public MicrofacetFresnelClosure {
+public:
+       void setup(ShaderData *sd, int path_flag, float3 weight)
+       {
+               MicrofacetBsdf *bsdf = alloc(sd, path_flag, weight);
+               sd->flag |= (bsdf) ? bsdf_microfacet_ggx_aniso_fresnel_setup(bsdf) : 0;
+       }
+};
+
+ClosureParam *closure_bsdf_microfacet_ggx_aniso_fresnel_params()
+{
+       static ClosureParam params[] = {
+               CLOSURE_FLOAT3_PARAM(MicrofacetGGXFresnelClosure, params.N),
+               CLOSURE_FLOAT3_PARAM(MicrofacetGGXFresnelClosure, params.T),
+               CLOSURE_FLOAT_PARAM(MicrofacetGGXFresnelClosure, params.alpha_x),
+               CLOSURE_FLOAT_PARAM(MicrofacetGGXFresnelClosure, params.alpha_y),
+               CLOSURE_FLOAT_PARAM(MicrofacetGGXFresnelClosure, params.ior),
+               CLOSURE_FLOAT3_PARAM(MicrofacetGGXFresnelClosure, color),
+               CLOSURE_FLOAT3_PARAM(MicrofacetGGXFresnelClosure, cspec0),
+               CLOSURE_STRING_KEYPARAM(MicrofacetGGXFresnelClosure, label, "label"),
+               CLOSURE_FINISH_PARAM(MicrofacetGGXFresnelClosure)
+       };
+       return params;
+}
+CCLOSURE_PREPARE(closure_bsdf_microfacet_ggx_aniso_fresnel_prepare, MicrofacetGGXAnisoFresnelClosure);
+
+
 /* Multiscattering GGX closures */
 
 class MicrofacetMultiClosure : public CBSDFClosure {
@@ -287,7 +444,7 @@ public:
 
        MicrofacetBsdf *alloc(ShaderData *sd, int path_flag, float3 weight)
        {
-               /* Technically, the MultiGGX Glass closure may also transmit. However,
+               /* Technically, the MultiGGX closure may also transmit. However,
                 * since this is set statically and only used for caustic flags, this
                 * is probably as good as it gets. */
            if(!skip(sd, path_flag, LABEL_GLOSSY|LABEL_REFLECT)) {
@@ -375,5 +532,110 @@ ClosureParam *closure_bsdf_microfacet_multi_ggx_glass_params()
 }
 CCLOSURE_PREPARE(closure_bsdf_microfacet_multi_ggx_glass_prepare, MicrofacetMultiGGXGlassClosure);
 
+
+/* Multiscattering GGX closures with Fresnel */
+
+class MicrofacetMultiFresnelClosure : public CBSDFClosure {
+public:
+       MicrofacetBsdf params;
+       float3 color;
+       float3 cspec0;
+
+       MicrofacetBsdf *alloc(ShaderData *sd, int path_flag, float3 weight)
+       {
+               /* Technically, the MultiGGX closure may also transmit. However,
+               * since this is set statically and only used for caustic flags, this
+               * is probably as good as it gets. */
+               if(!skip(sd, path_flag, LABEL_GLOSSY | LABEL_REFLECT)) {
+                       MicrofacetBsdf *bsdf = (MicrofacetBsdf*)bsdf_alloc_osl(sd, sizeof(MicrofacetBsdf), weight, &params);
+                       MicrofacetExtra *extra = (MicrofacetExtra*)closure_alloc_extra(sd, sizeof(MicrofacetExtra));
+                       if(bsdf && extra) {
+                               bsdf->extra = extra;
+                               bsdf->extra->color = color;
+                               bsdf->extra->cspec0 = cspec0;
+                               return bsdf;
+                       }
+               }
+
+               return NULL;
+       }
+};
+
+class MicrofacetMultiGGXFresnelClosure : public MicrofacetMultiFresnelClosure {
+public:
+       void setup(ShaderData *sd, int path_flag, float3 weight)
+       {
+               MicrofacetBsdf *bsdf = alloc(sd, path_flag, weight);
+               sd->flag |= (bsdf) ? bsdf_microfacet_multi_ggx_fresnel_setup(bsdf) : 0;
+       }
+};
+
+ClosureParam *closure_bsdf_microfacet_multi_ggx_fresnel_params()
+{
+       static ClosureParam params[] = {
+               CLOSURE_FLOAT3_PARAM(MicrofacetMultiGGXFresnelClosure, params.N),
+               CLOSURE_FLOAT_PARAM(MicrofacetMultiGGXFresnelClosure, params.alpha_x),
+               CLOSURE_FLOAT_PARAM(MicrofacetMultiGGXFresnelClosure, params.ior),
+               CLOSURE_FLOAT3_PARAM(MicrofacetMultiGGXFresnelClosure, color),
+               CLOSURE_FLOAT3_PARAM(MicrofacetMultiGGXFresnelClosure, cspec0),
+               CLOSURE_STRING_KEYPARAM(MicrofacetMultiGGXFresnelClosure, label, "label"),
+               CLOSURE_FINISH_PARAM(MicrofacetMultiGGXFresnelClosure)
+       };
+       return params;
+}
+CCLOSURE_PREPARE(closure_bsdf_microfacet_multi_ggx_fresnel_prepare, MicrofacetMultiGGXFresnelClosure);
+
+class MicrofacetMultiGGXAnisoFresnelClosure : public MicrofacetMultiFresnelClosure {
+public:
+       void setup(ShaderData *sd, int path_flag, float3 weight)
+       {
+               MicrofacetBsdf *bsdf = alloc(sd, path_flag, weight);
+               sd->flag |= (bsdf) ? bsdf_microfacet_multi_ggx_aniso_fresnel_setup(bsdf) : 0;
+       }
+};
+
+ClosureParam *closure_bsdf_microfacet_multi_ggx_aniso_fresnel_params()
+{
+       static ClosureParam params[] = {
+               CLOSURE_FLOAT3_PARAM(MicrofacetMultiGGXFresnelClosure, params.N),
+               CLOSURE_FLOAT3_PARAM(MicrofacetMultiGGXFresnelClosure, params.T),
+               CLOSURE_FLOAT_PARAM(MicrofacetMultiGGXFresnelClosure, params.alpha_x),
+               CLOSURE_FLOAT_PARAM(MicrofacetMultiGGXFresnelClosure, params.alpha_y),
+               CLOSURE_FLOAT_PARAM(MicrofacetMultiGGXFresnelClosure, params.ior),
+               CLOSURE_FLOAT3_PARAM(MicrofacetMultiGGXFresnelClosure, color),
+               CLOSURE_FLOAT3_PARAM(MicrofacetMultiGGXFresnelClosure, cspec0),
+               CLOSURE_STRING_KEYPARAM(MicrofacetMultiGGXFresnelClosure, label, "label"),
+               CLOSURE_FINISH_PARAM(MicrofacetMultiGGXFresnelClosure)
+       };
+       return params;
+}
+CCLOSURE_PREPARE(closure_bsdf_microfacet_multi_ggx_aniso_fresnel_prepare, MicrofacetMultiGGXAnisoFresnelClosure);
+
+class MicrofacetMultiGGXGlassFresnelClosure : public MicrofacetMultiFresnelClosure {
+public:
+       MicrofacetMultiGGXGlassFresnelClosure() : MicrofacetMultiFresnelClosure() {}
+
+       void setup(ShaderData *sd, int path_flag, float3 weight)
+       {
+               MicrofacetBsdf *bsdf = alloc(sd, path_flag, weight);
+               sd->flag |= (bsdf) ? bsdf_microfacet_multi_ggx_glass_fresnel_setup(bsdf) : 0;
+       }
+};
+
+ClosureParam *closure_bsdf_microfacet_multi_ggx_glass_fresnel_params()
+{
+       static ClosureParam params[] = {
+               CLOSURE_FLOAT3_PARAM(MicrofacetMultiGGXFresnelClosure, params.N),
+               CLOSURE_FLOAT_PARAM(MicrofacetMultiGGXFresnelClosure, params.alpha_x),
+               CLOSURE_FLOAT_PARAM(MicrofacetMultiGGXFresnelClosure, params.ior),
+               CLOSURE_FLOAT3_PARAM(MicrofacetMultiGGXFresnelClosure, color),
+               CLOSURE_FLOAT3_PARAM(MicrofacetMultiGGXFresnelClosure, cspec0),
+               CLOSURE_STRING_KEYPARAM(MicrofacetMultiGGXFresnelClosure, label, "label"),
+               CLOSURE_FINISH_PARAM(MicrofacetMultiGGXFresnelClosure)
+       };
+       return params;
+}
+CCLOSURE_PREPARE(closure_bsdf_microfacet_multi_ggx_glass_fresnel_prepare, MicrofacetMultiGGXGlassFresnelClosure);
+
 CCL_NAMESPACE_END
 
index 929cf00a7e6bd7690c92fb5464e80c4edbe1917c..ff5fd9cc9053e6f0965863c8a3ba8f6d36419646 100644 (file)
@@ -51,10 +51,17 @@ OSL::ClosureParam *closure_bsdf_phong_ramp_params();
 OSL::ClosureParam *closure_bssrdf_cubic_params();
 OSL::ClosureParam *closure_bssrdf_gaussian_params();
 OSL::ClosureParam *closure_bssrdf_burley_params();
+OSL::ClosureParam *closure_bssrdf_principled_params();
 OSL::ClosureParam *closure_henyey_greenstein_volume_params();
 OSL::ClosureParam *closure_bsdf_microfacet_multi_ggx_params();
 OSL::ClosureParam *closure_bsdf_microfacet_multi_ggx_glass_params();
 OSL::ClosureParam *closure_bsdf_microfacet_multi_ggx_aniso_params();
+OSL::ClosureParam *closure_bsdf_microfacet_ggx_fresnel_params();
+OSL::ClosureParam *closure_bsdf_microfacet_ggx_aniso_fresnel_params();
+OSL::ClosureParam *closure_bsdf_microfacet_multi_ggx_fresnel_params();
+OSL::ClosureParam *closure_bsdf_microfacet_multi_ggx_glass_fresnel_params();
+OSL::ClosureParam *closure_bsdf_microfacet_multi_ggx_aniso_fresnel_params();
+OSL::ClosureParam *closure_bsdf_principled_clearcoat_params();
 
 void closure_emission_prepare(OSL::RendererServices *, int id, void *data);
 void closure_background_prepare(OSL::RendererServices *, int id, void *data);
@@ -65,10 +72,17 @@ void closure_bsdf_phong_ramp_prepare(OSL::RendererServices *, int id, void *data
 void closure_bssrdf_cubic_prepare(OSL::RendererServices *, int id, void *data);
 void closure_bssrdf_gaussian_prepare(OSL::RendererServices *, int id, void *data);
 void closure_bssrdf_burley_prepare(OSL::RendererServices *, int id, void *data);
+void closure_bssrdf_principled_prepare(OSL::RendererServices *, int id, void *data);
 void closure_henyey_greenstein_volume_prepare(OSL::RendererServices *, int id, void *data);
 void closure_bsdf_microfacet_multi_ggx_prepare(OSL::RendererServices *, int id, void *data);
 void closure_bsdf_microfacet_multi_ggx_glass_prepare(OSL::RendererServices *, int id, void *data);
 void closure_bsdf_microfacet_multi_ggx_aniso_prepare(OSL::RendererServices *, int id, void *data);
+void closure_bsdf_microfacet_ggx_fresnel_prepare(OSL::RendererServices *, int id, void *data);
+void closure_bsdf_microfacet_ggx_aniso_fresnel_prepare(OSL::RendererServices *, int id, void *data);
+void closure_bsdf_microfacet_multi_ggx_fresnel_prepare(OSL::RendererServices *, int id, void *data);
+void closure_bsdf_microfacet_multi_ggx_glass_fresnel_prepare(OSL::RendererServices *, int id, void *data);
+void closure_bsdf_microfacet_multi_ggx_aniso_fresnel_prepare(OSL::RendererServices *, int id, void *data);
+void closure_bsdf_principled_clearcoat_prepare(OSL::RendererServices *, int id, void *data);
 
 #define CCLOSURE_PREPARE(name, classname)          \
 void name(RendererServices *, int id, void *data) \
index b43f8402d42f57c7157acc8da476f87d8ca0566b..ef1f405e34e4468968450182338af4a6d9669c1d 100644 (file)
@@ -81,6 +81,7 @@ set(SRC_OSL
        node_wireframe.osl
        node_hair_bsdf.osl
        node_uv_map.osl
+       node_principled_bsdf.osl
        node_rgb_to_bw.osl
 )
 
diff --git a/intern/cycles/kernel/shaders/node_principled_bsdf.osl b/intern/cycles/kernel/shaders/node_principled_bsdf.osl
new file mode 100644 (file)
index 0000000..39c6c7e
--- /dev/null
@@ -0,0 +1,120 @@
+/*
+ * Copyright 2011-2017 Blender Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "stdosl.h"
+#include "node_fresnel.h"
+
+shader node_principled_bsdf(
+       string distribution = "Multiscatter GGX",
+       color BaseColor = color(0.8, 0.8, 0.8),
+       float Subsurface = 0.0,
+       vector SubsurfaceRadius = vector(1.0, 1.0, 1.0),
+       color SubsurfaceColor = color(0.7, 0.1, 0.1),
+       float Metallic = 0.0,
+       float Specular = 0.5,
+       float SpecularTint = 0.0,
+       float Roughness = 0.5,
+       float Anisotropic = 0.0,
+       float AnisotropicRotation = 0.0,
+       float Sheen = 0.0,
+       float SheenTint = 0.5,
+       float Clearcoat = 0.0,
+       float ClearcoatGloss = 1.0,
+       float IOR = 1.45,
+       float Transparency = 0.0,
+       float RefractionRoughness = 0.0,
+       normal Normal = N,
+       normal ClearcoatNormal = N,
+       normal Tangent = normalize(dPdu),
+       output closure color BSDF = 0)
+{
+       float f = max(IOR, 1e-5);
+       float diffuse_weight = (1.0 - clamp(Metallic, 0.0, 1.0)) * (1.0 - clamp(Transparency, 0.0, 1.0));
+       float transp = clamp(Transparency, 0.0, 1.0) * (1.0 - clamp(Metallic, 0.0, 1.0));
+       float specular_weight = (1.0 - transp);
+
+       vector T = Tangent;
+
+       float m_cdlum = luminance(BaseColor);
+       color m_ctint = m_cdlum > 0.0 ? BaseColor / m_cdlum : color(0.0, 0.0, 0.0); // normalize lum. to isolate hue+sat
+
+       /* rotate tangent */
+       if (AnisotropicRotation != 0.0)
+               T = rotate(T, AnisotropicRotation * M_2PI, point(0.0, 0.0, 0.0), Normal);
+
+       if (diffuse_weight > 1e-5) {
+               if (Subsurface > 1e-5) {
+                       color Albedo = SubsurfaceColor * Subsurface + BaseColor * (1.0 - Subsurface);
+                       BSDF = bssrdf_principled(Normal, Subsurface * SubsurfaceRadius, 0.0, Albedo, Roughness);
+               } else {
+                       BSDF = BaseColor * principled_diffuse(Normal, Roughness);
+               }
+
+               if (Sheen > 1e-5) {
+                       color sheen_color = color(1.0, 1.0, 1.0) * (1.0 - SheenTint) + m_ctint * SheenTint;
+
+                       BSDF = BSDF + sheen_color * Sheen * principled_sheen(Normal);
+               }
+
+               BSDF = BSDF * diffuse_weight;
+       }
+
+       if (specular_weight > 1e-5) {
+               float aspect = sqrt(1.0 - Anisotropic * 0.9);
+               float r2 = Roughness * Roughness;
+
+               float alpha_x = max(0.001, r2 / aspect);
+               float alpha_y = max(0.001, r2 * aspect);
+
+               color tmp_col = color(1.0, 1.0, 1.0) * (1.0 - SpecularTint) + m_ctint * SpecularTint;
+
+               color Cspec0 = (Specular * 0.08 * tmp_col) * (1.0 - Metallic) + BaseColor * Metallic;
+
+               if (distribution == "GGX" || Roughness <= 0.075) {
+                       BSDF = BSDF  + specular_weight * microfacet_ggx_aniso_fresnel(Normal, T, alpha_x, alpha_y, (2.0 / (1.0 - sqrt(0.08 * Specular))) - 1.0, BaseColor, Cspec0);
+               } else {
+                       BSDF = BSDF + specular_weight * microfacet_multi_ggx_aniso_fresnel(Normal, T, alpha_x, alpha_y, (2.0 / (1.0 - sqrt(0.08 * Specular))) - 1.0, BaseColor, Cspec0);
+               }
+       }
+
+       if (transp > 1e-5) {
+               color Cspec0 = BaseColor * SpecularTint + color(1.0, 1.0, 1.0) * (1.0 - SpecularTint);
+               float eta = backfacing() ? 1.0 / f : f;
+
+               if (distribution == "GGX" || Roughness <= 5e-2) {
+                       float cosNO = dot(Normal, I);
+                       float Fr = fresnel_dielectric_cos(cosNO, eta);
+
+               float refl_roughness = Roughness;
+               if (Roughness <= 1e-2)
+                       refl_roughness = 0.0;
+
+                       float refraction_roughness = refl_roughness;
+                       if (distribution == "GGX")
+                               refraction_roughness = 1.0 - (1.0 - refl_roughness) * (1.0 - RefractionRoughness);
+
+                       BSDF = BSDF + transp * (Fr * microfacet_ggx_fresnel(Normal, refl_roughness * refl_roughness, eta, BaseColor, Cspec0) +
+                              (1.0 - Fr) * BaseColor * microfacet_ggx_refraction(Normal, refraction_roughness * refraction_roughness, eta));
+               } else {
+                       BSDF = BSDF + transp * microfacet_multi_ggx_glass_fresnel(Normal, Roughness * Roughness, eta, BaseColor, Cspec0);
+               }
+       }
+
+       if (Clearcoat > 1e-5) {
+               BSDF = BSDF + principled_clearcoat(ClearcoatNormal, Clearcoat, ClearcoatGloss);
+       }
+}
+
index a8dda8a12c9041e992c42374270ae61d0c57381b..289d1091b0a1160dca80101c2fc38637b5699a8c 100644 (file)
@@ -530,6 +530,11 @@ closure color microfacet_ggx_refraction(normal N, float ag, float eta) BUILTIN;
 closure color microfacet_multi_ggx(normal N, float ag, color C) BUILTIN;
 closure color microfacet_multi_ggx_aniso(normal N, vector T, float ax, float ay, color C) BUILTIN;
 closure color microfacet_multi_ggx_glass(normal N, float ag, float eta, color C) BUILTIN;
+closure color microfacet_ggx_fresnel(normal N, float ag, float eta, color C, color Cspec0) BUILTIN;
+closure color microfacet_ggx_aniso_fresnel(normal N, vector T, float ax, float ay, float eta, color C, color Cspec0) BUILTIN;
+closure color microfacet_multi_ggx_fresnel(normal N, float ag, float eta, color C, color Cspec0) BUILTIN;
+closure color microfacet_multi_ggx_aniso_fresnel(normal N, vector T, float ax, float ay, float eta, color C, color Cspec0) BUILTIN;
+closure color microfacet_multi_ggx_glass_fresnel(normal N, float ag, float eta, color C, color Cspec0) BUILTIN;
 closure color microfacet_beckmann(normal N, float ab) BUILTIN;
 closure color microfacet_beckmann_aniso(normal N, vector T, float ax, float ay) BUILTIN;
 closure color microfacet_beckmann_refraction(normal N, float ab, float eta) BUILTIN;
@@ -539,11 +544,15 @@ closure color emission() BUILTIN;
 closure color background() BUILTIN;
 closure color holdout() BUILTIN;
 closure color ambient_occlusion() BUILTIN;
+closure color principled_diffuse(normal N, float roughness) BUILTIN;
+closure color principled_sheen(normal N) BUILTIN;
+closure color principled_clearcoat(normal N, float clearcoat, float clearcoat_gloss) BUILTIN;
 
 // BSSRDF
 closure color bssrdf_cubic(normal N, vector radius, float texture_blur, float sharpness) BUILTIN;
 closure color bssrdf_gaussian(normal N, vector radius, float texture_blur) BUILTIN;
 closure color bssrdf_burley(normal N, vector radius, float texture_blur, color albedo) BUILTIN;
+closure color bssrdf_principled(normal N, vector radius, float texture_blur, color subsurface_color, float roughness) BUILTIN;
 
 // Hair
 closure color hair_reflection(normal N, float roughnessu, float roughnessv, vector T, float offset) BUILTIN;
index 1885e1af85195aaedfcf108c4df0d84e6219b021..9a3689a94f404951d1ca22d00b36119a6d8a054e 100644 (file)
@@ -76,6 +76,338 @@ ccl_device void svm_node_closure_bsdf(KernelGlobals *kg, ShaderData *sd, float *
        float param2 = (stack_valid(param2_offset))? stack_load_float(stack, param2_offset): __uint_as_float(node.w);
 
        switch(type) {
+               case CLOSURE_BSDF_PRINCIPLED_ID: {
+                       uint specular_offset, roughness_offset, specular_tint_offset, anisotropic_offset, sheen_offset,
+                               sheen_tint_offset, clearcoat_offset, clearcoat_gloss_offset, eta_offset, transparency_offset,
+                               anisotropic_rotation_offset, refraction_roughness_offset;
+                       uint4 data_node2 = read_node(kg, offset);
+
+                       float3 T = stack_load_float3(stack, data_node.y);
+                       decode_node_uchar4(data_node.z, &specular_offset, &roughness_offset, &specular_tint_offset, &anisotropic_offset);
+                       decode_node_uchar4(data_node.w, &sheen_offset, &sheen_tint_offset, &clearcoat_offset, &clearcoat_gloss_offset);
+                       decode_node_uchar4(data_node2.x, &eta_offset, &transparency_offset, &anisotropic_rotation_offset, &refraction_roughness_offset);
+
+                       // get Disney principled parameters
+                       float metallic = param1;
+                       float subsurface = param2;
+                       float specular = stack_load_float(stack, specular_offset);
+                       float roughness = stack_load_float(stack, roughness_offset);
+                       float specular_tint = stack_load_float(stack, specular_tint_offset);
+                       float anisotropic = stack_load_float(stack, anisotropic_offset);
+                       float sheen = stack_load_float(stack, sheen_offset);
+                       float sheen_tint = stack_load_float(stack, sheen_tint_offset);
+                       float clearcoat = stack_load_float(stack, clearcoat_offset);
+                       float clearcoat_gloss = stack_load_float(stack, clearcoat_gloss_offset);
+                       float transparency = stack_load_float(stack, transparency_offset);
+                       float anisotropic_rotation = stack_load_float(stack, anisotropic_rotation_offset);
+                       float refraction_roughness = stack_load_float(stack, refraction_roughness_offset);
+                       float eta = fmaxf(stack_load_float(stack, eta_offset), 1e-5f);
+
+                       ClosureType distribution = stack_valid(data_node2.y) ? (ClosureType) data_node2.y : CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_ID;
+
+                       /* rotate tangent */
+                       if(anisotropic_rotation != 0.0f)
+                               T = rotate_around_axis(T, N, anisotropic_rotation * M_2PI_F);
+
+                       /* calculate ior */
+                       float ior = (sd->flag & SD_BACKFACING) ? 1.0f / eta : eta;
+
+                       // calculate fresnel for refraction
+                       float cosNO = dot(N, sd->I);
+                       float fresnel = fresnel_dielectric_cos(cosNO, ior);
+
+                       // calculate weights of the diffuse and specular part
+                       float diffuse_weight = (1.0f - saturate(metallic)) * (1.0f - saturate(transparency));
+                       
+                       float transp = saturate(transparency) * (1.0f - saturate(metallic));
+                       float specular_weight = (1.0f - transp);
+
+                       // get the base color
+                       uint4 data_base_color = read_node(kg, offset);
+                       float3 base_color = stack_valid(data_base_color.x) ? stack_load_float3(stack, data_base_color.x) :
+                               make_float3(__uint_as_float(data_base_color.y), __uint_as_float(data_base_color.z), __uint_as_float(data_base_color.w));
+
+                       // get the additional clearcoat normal and subsurface scattering radius
+                       uint4 data_cn_ssr = read_node(kg, offset);
+                       float3 clearcoat_normal = stack_valid(data_cn_ssr.x) ? stack_load_float3(stack, data_cn_ssr.x) : sd->N;
+                       float3 subsurface_radius = stack_valid(data_cn_ssr.y) ? stack_load_float3(stack, data_cn_ssr.y) : make_float3(1.0f, 1.0f, 1.0f);
+
+                       // get the subsurface color
+                       uint4 data_subsurface_color = read_node(kg, offset);
+                       float3 subsurface_color = stack_valid(data_subsurface_color.x) ? stack_load_float3(stack, data_subsurface_color.x) :
+                               make_float3(__uint_as_float(data_subsurface_color.y), __uint_as_float(data_subsurface_color.z), __uint_as_float(data_subsurface_color.w));
+
+                       float3 weight = sd->svm_closure_weight * mix_weight;
+
+#ifdef __SUBSURFACE__
+                       float3 albedo = subsurface_color * subsurface + base_color * (1.0f - subsurface);
+                       float3 subsurf_weight = weight * albedo * diffuse_weight;
+                       float subsurf_sample_weight = fabsf(average(subsurf_weight));
+
+                       /* disable in case of diffuse ancestor, can't see it well then and
+                        * adds considerably noise due to probabilities of continuing path
+                        * getting lower and lower */
+                       if(path_flag & PATH_RAY_DIFFUSE_ANCESTOR) {
+                               subsurface = 0.0f;
+                       }
+
+                       /* diffuse */
+                       if(fabsf(average(base_color)) > CLOSURE_WEIGHT_CUTOFF) {
+                               if(subsurface < CLOSURE_WEIGHT_CUTOFF && diffuse_weight > CLOSURE_WEIGHT_CUTOFF) {
+                                       float3 diff_weight = weight * base_color * diffuse_weight;
+
+                                       PrincipledDiffuseBsdf *bsdf = (PrincipledDiffuseBsdf*)bsdf_alloc(sd, sizeof(PrincipledDiffuseBsdf), diff_weight);
+
+                                       if(bsdf) {
+                                               bsdf->N = N;
+                                               bsdf->roughness = roughness;
+
+                                               /* setup bsdf */
+                                               sd->flag |= bsdf_principled_diffuse_setup(bsdf);
+                                       }
+                               }
+                               else if(subsurface > CLOSURE_WEIGHT_CUTOFF && subsurf_sample_weight > CLOSURE_WEIGHT_CUTOFF) {
+                                       /* radius * scale */
+                                       float3 radius = subsurface_radius * subsurface;
+                                       /* sharpness */
+                                       float sharpness = 0.0f;
+                                       /* texture color blur */
+                                       float texture_blur = 0.0f;
+
+                                       /* create one closure per color channel */
+                                       Bssrdf *bssrdf = bssrdf_alloc(sd, make_float3(subsurf_weight.x, 0.0f, 0.0f));
+                                       if(bssrdf) {
+                                               bssrdf->sample_weight = subsurf_sample_weight;
+                                               bssrdf->radius = radius.x;
+                                               bssrdf->texture_blur = texture_blur;
+                                               bssrdf->albedo = albedo.x;
+                                               bssrdf->sharpness = sharpness;
+                                               bssrdf->N = N;
+                                               bssrdf->roughness = roughness;
+
+                                               /* setup bsdf */
+                                               sd->flag |= bssrdf_setup(bssrdf, (ClosureType)CLOSURE_BSSRDF_PRINCIPLED_ID);
+                                       }
+
+                                       bssrdf = bssrdf_alloc(sd, make_float3(0.0f, subsurf_weight.y, 0.0f));
+                                       if(bssrdf) {
+                                               bssrdf->sample_weight = subsurf_sample_weight;
+                                               bssrdf->radius = radius.y;
+                                               bssrdf->texture_blur = texture_blur;
+                                               bssrdf->albedo = albedo.y;
+                                               bssrdf->sharpness = sharpness;
+                                               bssrdf->N = N;
+                                               bssrdf->roughness = roughness;
+
+                                               /* setup bsdf */
+                                               sd->flag |= bssrdf_setup(bssrdf, (ClosureType)CLOSURE_BSSRDF_PRINCIPLED_ID);
+                                       }
+
+                                       bssrdf = bssrdf_alloc(sd, make_float3(0.0f, 0.0f, subsurf_weight.z));
+                                       if(bssrdf) {
+                                               bssrdf->sample_weight = subsurf_sample_weight;
+                                               bssrdf->radius = radius.z;
+                                               bssrdf->texture_blur = texture_blur;
+                                               bssrdf->albedo = albedo.z;
+                                               bssrdf->sharpness = sharpness;
+                                               bssrdf->N = N;
+                                               bssrdf->roughness = roughness;
+
+                                               /* setup bsdf */
+                                               sd->flag |= bssrdf_setup(bssrdf, (ClosureType)CLOSURE_BSSRDF_PRINCIPLED_ID);
+                                       }
+                               }
+                       }
+#else
+                       /* diffuse */
+                       if(diffuse_weight > CLOSURE_WEIGHT_CUTOFF) {
+                               float3 diff_weight = weight * base_color * diffuse_weight;
+
+                               PrincipledDiffuseBsdf *bsdf = (PrincipledDiffuseBsdf*)bsdf_alloc(sd, sizeof(PrincipledDiffuseBsdf), diff_weight);
+
+                               if(bsdf) {
+                                       bsdf->N = N;
+                                       bsdf->roughness = roughness;
+
+                                       /* setup bsdf */
+                                       sd->flag |= bsdf_principled_diffuse_setup(bsdf);
+                               }
+                       }
+#endif
+
+                       /* sheen */
+                       if(diffuse_weight > CLOSURE_WEIGHT_CUTOFF && sheen > CLOSURE_WEIGHT_CUTOFF) {
+                               float m_cdlum = linear_rgb_to_gray(base_color);
+                               float3 m_ctint = m_cdlum > 0.0f ? base_color / m_cdlum : make_float3(1.0f, 1.0f, 1.0f); // normalize lum. to isolate hue+sat
+
+                               /* color of the sheen component */
+                               float3 sheen_color = make_float3(1.0f, 1.0f, 1.0f) * (1.0f - sheen_tint) + m_ctint * sheen_tint;
+
+                               float3 sheen_weight = weight * sheen * sheen_color * diffuse_weight;
+
+                               PrincipledSheenBsdf *bsdf = (PrincipledSheenBsdf*)bsdf_alloc(sd, sizeof(PrincipledSheenBsdf), sheen_weight);
+
+                               if(bsdf) {
+                                       bsdf->N = N;
+
+                                       /* setup bsdf */
+                                       sd->flag |= bsdf_principled_sheen_setup(bsdf);
+                               }
+                       }
+
+                       /* specular reflection */
+#ifdef __CAUSTICS_TRICKS__
+                       if(kernel_data.integrator.caustics_reflective || (path_flag & PATH_RAY_DIFFUSE) == 0) {
+#endif
+                               if(specular_weight > CLOSURE_WEIGHT_CUTOFF && (specular > CLOSURE_WEIGHT_CUTOFF || metallic > CLOSURE_WEIGHT_CUTOFF)) {
+                                       float3 spec_weight = weight * specular_weight;
+
+                                       MicrofacetBsdf *bsdf = (MicrofacetBsdf*)bsdf_alloc(sd, sizeof(MicrofacetBsdf), spec_weight);
+                                       MicrofacetExtra *extra = (MicrofacetExtra*)closure_alloc_extra(sd, sizeof(MicrofacetExtra));
+
+                                       if(bsdf && extra) {
+                                               bsdf->N = N;
+                                               bsdf->ior = (2.0f / (1.0f - safe_sqrtf(0.08f * specular))) - 1.0f;
+                                               bsdf->T = T;
+                                               bsdf->extra = extra;
+
+                                               float aspect = safe_sqrtf(1.0f - anisotropic * 0.9f);
+                                               float r2 = roughness * roughness;
+
+                                               bsdf->alpha_x = fmaxf(0.001f, r2 / aspect);
+                                               bsdf->alpha_y = fmaxf(0.001f, r2 * aspect);
+
+                                               float m_cdlum = 0.3f * base_color.x + 0.6f * base_color.y + 0.1f * base_color.z; // luminance approx.
+                                               float3 m_ctint = m_cdlum > 0.0f ? base_color / m_cdlum : make_float3(0.0f, 0.0f, 0.0f); // normalize lum. to isolate hue+sat
+                                               float3 tmp_col = make_float3(1.0f, 1.0f, 1.0f) * (1.0f - specular_tint) + m_ctint * specular_tint;
+
+                                               bsdf->extra->cspec0 = (specular * 0.08f * tmp_col) * (1.0f - metallic) + base_color * metallic;
+                                               bsdf->extra->color = base_color;
+
+                                               /* setup bsdf */
+                                               if(distribution == CLOSURE_BSDF_MICROFACET_GGX_GLASS_ID || roughness <= 0.075f) /* use single-scatter GGX */
+                                                       sd->flag |= bsdf_microfacet_ggx_aniso_fresnel_setup(bsdf);
+                                               else /* use multi-scatter GGX */
+                                                       sd->flag |= bsdf_microfacet_multi_ggx_aniso_fresnel_setup(bsdf);
+                                       }
+                               }
+#ifdef __CAUSTICS_TRICKS__
+                       }
+#endif
+
+                       /* BSDF */
+#ifdef __CAUSTICS_TRICKS__
+                       if(kernel_data.integrator.caustics_reflective || kernel_data.integrator.caustics_refractive || (path_flag & PATH_RAY_DIFFUSE) == 0) {
+#endif
+                               if(transp > CLOSURE_WEIGHT_CUTOFF) {
+                                       float3 glass_weight = weight * transp;
+                                       float3 cspec0 = base_color * specular_tint + make_float3(1.0f, 1.0f, 1.0f) * (1.0f - specular_tint);
+
+                                       if(roughness <= 5e-2f || distribution == CLOSURE_BSDF_MICROFACET_GGX_GLASS_ID) { /* use single-scatter GGX */
+                                               float refl_roughness = roughness;
+
+                                               /* reflection */
+#ifdef __CAUSTICS_TRICKS__
+                                               if(kernel_data.integrator.caustics_reflective || (path_flag & PATH_RAY_DIFFUSE) == 0)
+#endif
+                                               {
+                                                       MicrofacetBsdf *bsdf = (MicrofacetBsdf*)bsdf_alloc(sd, sizeof(MicrofacetBsdf), glass_weight*fresnel);
+                                                       MicrofacetExtra *extra = (MicrofacetExtra*)closure_alloc_extra(sd, sizeof(MicrofacetExtra));
+
+                                                       if(bsdf && extra) {
+                                                               bsdf->N = N;
+                                                               bsdf->extra = extra;
+
+                                                               bsdf->alpha_x = refl_roughness * refl_roughness;
+                                                               bsdf->alpha_y = refl_roughness * refl_roughness;
+                                                               bsdf->ior = ior;
+
+                                                               bsdf->extra->color = base_color;
+                                                               bsdf->extra->cspec0 = cspec0;
+
+                                                               /* setup bsdf */
+                                                               sd->flag |= bsdf_microfacet_ggx_fresnel_setup(bsdf);
+                                                       }
+                                               }
+
+                                               /* refraction */
+#ifdef __CAUSTICS_TRICKS__
+                                               if(kernel_data.integrator.caustics_refractive || (path_flag & PATH_RAY_DIFFUSE) == 0)
+#endif
+                                               {
+                                                       MicrofacetBsdf *bsdf = (MicrofacetBsdf*)bsdf_alloc(sd, sizeof(MicrofacetBsdf), base_color*glass_weight*(1.0f - fresnel));
+
+                                                       if(bsdf) {
+                                                               bsdf->N = N;
+
+                                                               if(distribution == CLOSURE_BSDF_MICROFACET_GGX_GLASS_ID)
+                                                                       refraction_roughness = 1.0f - (1.0f - refl_roughness) * (1.0f - refraction_roughness);
+                                                               else
+                                                                       refraction_roughness = refl_roughness;
+
+                                                               bsdf->alpha_x = refraction_roughness * refraction_roughness;
+                                                               bsdf->alpha_y = refraction_roughness * refraction_roughness;
+                                                               bsdf->ior = ior;
+
+                                                               /* setup bsdf */
+                                                               sd->flag |= bsdf_microfacet_ggx_refraction_setup(bsdf);
+                                                       }
+                                               }
+                                       }
+                                       else { /* use multi-scatter GGX */
+                                               MicrofacetBsdf *bsdf = (MicrofacetBsdf*)bsdf_alloc(sd, sizeof(MicrofacetBsdf), glass_weight);
+                                               MicrofacetExtra *extra = (MicrofacetExtra*)closure_alloc_extra(sd, sizeof(MicrofacetExtra));
+
+                                               if(bsdf && extra) {
+                                                       bsdf->N = N;
+                                                       bsdf->extra = extra;
+                                                       bsdf->T = make_float3(0.0f, 0.0f, 0.0f);
+
+                                                       bsdf->alpha_x = roughness * roughness;
+                                                       bsdf->alpha_y = roughness * roughness;
+                                                       bsdf->ior = ior;
+
+                                                       bsdf->extra->color = base_color;
+                                                       bsdf->extra->cspec0 = cspec0;
+
+                                                       /* setup bsdf */
+                                                       sd->flag |= bsdf_microfacet_multi_ggx_glass_fresnel_setup(bsdf);
+                                               }
+                                       }
+                               }
+#ifdef __CAUSTICS_TRICKS__
+                       }
+#endif
+
+                       /* clearcoat */
+#ifdef __CAUSTICS_TRICKS__
+                       if(kernel_data.integrator.caustics_reflective || (path_flag & PATH_RAY_DIFFUSE) == 0) {
+#endif
+                               if(clearcoat > CLOSURE_WEIGHT_CUTOFF) {
+                                       MicrofacetBsdf *bsdf = (MicrofacetBsdf*)bsdf_alloc(sd, sizeof(MicrofacetBsdf), weight);
+                                       MicrofacetExtra *extra = (MicrofacetExtra*)closure_alloc_extra(sd, sizeof(MicrofacetExtra));
+
+                                       if(bsdf && extra) {
+                                               bsdf->N = clearcoat_normal;
+                                               bsdf->ior = 1.5f;
+                                               bsdf->extra = extra;
+
+                                               bsdf->alpha_x = 0.1f * (1.0f - clearcoat_gloss) + 0.001f * clearcoat_gloss;
+                                               bsdf->alpha_y = 0.1f * (1.0f - clearcoat_gloss) + 0.001f * clearcoat_gloss;
+
+                                               bsdf->extra->cspec0 = make_float3(0.04f, 0.04f, 0.04f);
+                                               bsdf->extra->clearcoat = clearcoat;
+
+                                               /* setup bsdf */
+                                               sd->flag |= bsdf_microfacet_ggx_clearcoat_setup(bsdf);
+                                       }
+                               }
+#ifdef __CAUSTICS_TRICKS__
+                       }
+#endif
+
+                       break;
+               }
                case CLOSURE_BSDF_DIFFUSE_ID: {
                        float3 weight = sd->svm_closure_weight * mix_weight;
                        OrenNayarBsdf *bsdf = (OrenNayarBsdf*)bsdf_alloc(sd, sizeof(OrenNayarBsdf), weight);
index 47209ddfbab6dcd58b26031a639d7abd95a3f099..4a8cdb6095268d936d727b24053d6a18c1d7bb89 100644 (file)
@@ -397,17 +397,24 @@ typedef enum ClosureType {
        CLOSURE_BSDF_DIFFUSE_ID,
        CLOSURE_BSDF_OREN_NAYAR_ID,
        CLOSURE_BSDF_DIFFUSE_RAMP_ID,
+       CLOSURE_BSDF_PRINCIPLED_DIFFUSE_ID,
+       CLOSURE_BSDF_PRINCIPLED_SHEEN_ID,
        CLOSURE_BSDF_DIFFUSE_TOON_ID,
 
        /* Glossy */
        CLOSURE_BSDF_GLOSSY_ID,
        CLOSURE_BSDF_REFLECTION_ID,
        CLOSURE_BSDF_MICROFACET_GGX_ID,
+       CLOSURE_BSDF_MICROFACET_GGX_FRESNEL_ID,
+       CLOSURE_BSDF_MICROFACET_GGX_CLEARCOAT_ID,
        CLOSURE_BSDF_MICROFACET_BECKMANN_ID,
        CLOSURE_BSDF_MICROFACET_MULTI_GGX_ID,
+       CLOSURE_BSDF_MICROFACET_MULTI_GGX_FRESNEL_ID,
        CLOSURE_BSDF_ASHIKHMIN_SHIRLEY_ID,
        CLOSURE_BSDF_MICROFACET_GGX_ANISO_ID,
+       CLOSURE_BSDF_MICROFACET_GGX_ANISO_FRESNEL_ID,
        CLOSURE_BSDF_MICROFACET_MULTI_GGX_ANISO_ID,
+       CLOSURE_BSDF_MICROFACET_MULTI_GGX_ANISO_FRESNEL_ID,
        CLOSURE_BSDF_MICROFACET_BECKMANN_ANISO_ID,
        CLOSURE_BSDF_ASHIKHMIN_SHIRLEY_ANISO_ID,
        CLOSURE_BSDF_ASHIKHMIN_VELVET_ID,
@@ -424,16 +431,19 @@ typedef enum ClosureType {
        CLOSURE_BSDF_MICROFACET_BECKMANN_GLASS_ID,
        CLOSURE_BSDF_MICROFACET_GGX_GLASS_ID,
        CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_ID,
+       CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_FRESNEL_ID,
        CLOSURE_BSDF_SHARP_GLASS_ID,
        CLOSURE_BSDF_HAIR_TRANSMISSION_ID,
 
        /* Special cases */
        CLOSURE_BSDF_BSSRDF_ID,
+       CLOSURE_BSDF_BSSRDF_PRINCIPLED_ID,
        CLOSURE_BSDF_TRANSPARENT_ID,
 
        /* BSSRDF */
        CLOSURE_BSSRDF_CUBIC_ID,
        CLOSURE_BSSRDF_GAUSSIAN_ID,
+       CLOSURE_BSSRDF_PRINCIPLED_ID,
        CLOSURE_BSSRDF_BURLEY_ID,
 
        /* Other */
@@ -447,6 +457,8 @@ typedef enum ClosureType {
        CLOSURE_VOLUME_ABSORPTION_ID,
        CLOSURE_VOLUME_HENYEY_GREENSTEIN_ID,
 
+       CLOSURE_BSDF_PRINCIPLED_ID,
+
        NBUILTIN_CLOSURES
 } ClosureType;
 
@@ -455,7 +467,7 @@ typedef enum ClosureType {
 #define CLOSURE_IS_BSDF_DIFFUSE(type) (type >= CLOSURE_BSDF_DIFFUSE_ID && type <= CLOSURE_BSDF_DIFFUSE_TOON_ID)
 #define CLOSURE_IS_BSDF_GLOSSY(type) (type >= CLOSURE_BSDF_GLOSSY_ID && type <= CLOSURE_BSDF_HAIR_REFLECTION_ID)
 #define CLOSURE_IS_BSDF_TRANSMISSION(type) (type >= CLOSURE_BSDF_TRANSMISSION_ID && type <= CLOSURE_BSDF_HAIR_TRANSMISSION_ID)
-#define CLOSURE_IS_BSDF_BSSRDF(type) (type == CLOSURE_BSDF_BSSRDF_ID)
+#define CLOSURE_IS_BSDF_BSSRDF(type) (type == CLOSURE_BSDF_BSSRDF_ID || type == CLOSURE_BSDF_BSSRDF_PRINCIPLED_ID)
 #define CLOSURE_IS_BSDF_ANISOTROPIC(type) (type >= CLOSURE_BSDF_MICROFACET_GGX_ANISO_ID && type <= CLOSURE_BSDF_ASHIKHMIN_SHIRLEY_ANISO_ID)
 #define CLOSURE_IS_BSDF_MULTISCATTER(type) (type == CLOSURE_BSDF_MICROFACET_MULTI_GGX_ID ||\
                                             type == CLOSURE_BSDF_MICROFACET_MULTI_GGX_ANISO_ID || \
@@ -469,6 +481,7 @@ typedef enum ClosureType {
 #define CLOSURE_IS_AMBIENT_OCCLUSION(type) (type == CLOSURE_AMBIENT_OCCLUSION_ID)
 #define CLOSURE_IS_PHASE(type) (type == CLOSURE_VOLUME_HENYEY_GREENSTEIN_ID)
 #define CLOSURE_IS_GLASS(type) (type >= CLOSURE_BSDF_MICROFACET_BECKMANN_GLASS_ID && type <= CLOSURE_BSDF_SHARP_GLASS_ID)
+#define CLOSURE_IS_PRINCIPLED(type) (type == CLOSURE_BSDF_PRINCIPLED_ID)
 
 #define CLOSURE_WEIGHT_CUTOFF 1e-5f
 
index 4dac078e15108f85482975688447fbc1aa9e4b6b..2d810ff664fc395c3bb6f25487b5a87f7d657aae 100644 (file)
@@ -1037,6 +1037,9 @@ int ShaderGraph::get_num_closures()
                else if(CLOSURE_IS_BSDF_MULTISCATTER(closure_type)) {
                        num_closures += 2;
                }
+               else if(CLOSURE_IS_PRINCIPLED(closure_type)) {
+                       num_closures += 8;
+               }
                else {
                        ++num_closures;
                }
index 1070e05a03b20b8b8f8f07f61168c77e87b2ac37..3f56690d0c1be9ffe71c6a3c18e718699f49e3c6 100644 (file)
@@ -2286,6 +2286,150 @@ void DiffuseBsdfNode::compile(OSLCompiler& compiler)
        compiler.add(this, "node_diffuse_bsdf");
 }
 
+/* Disney principled BSDF Closure */
+NODE_DEFINE(PrincipledBsdfNode)
+{
+       NodeType* type = NodeType::add("principled_bsdf", create, NodeType::SHADER);
+
+       static NodeEnum distribution_enum;
+       distribution_enum.insert("GGX", CLOSURE_BSDF_MICROFACET_GGX_GLASS_ID);
+       distribution_enum.insert("Multiscatter GGX", CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_ID);
+       SOCKET_ENUM(distribution, "Distribution", distribution_enum, CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_ID);
+       SOCKET_IN_COLOR(base_color, "Base Color", make_float3(0.8f, 0.8f, 0.8f));
+       SOCKET_IN_COLOR(subsurface_color, "Subsurface Color", make_float3(0.8f, 0.8f, 0.8f));
+       SOCKET_IN_FLOAT(metallic, "Metallic", 0.0f);
+       SOCKET_IN_FLOAT(subsurface, "Subsurface", 0.0f);
+       SOCKET_IN_VECTOR(subsurface_radius, "Subsurface Radius", make_float3(0.1f, 0.1f, 0.1f));
+       SOCKET_IN_FLOAT(specular, "Specular", 0.0f);
+       SOCKET_IN_FLOAT(roughness, "Roughness", 0.0f);
+       SOCKET_IN_FLOAT(specular_tint, "Specular Tint", 0.0f);
+       SOCKET_IN_FLOAT(anisotropic, "Anisotropic", 0.0f);
+       SOCKET_IN_FLOAT(sheen, "Sheen", 0.0f);
+       SOCKET_IN_FLOAT(sheen_tint, "Sheen Tint", 0.0f);
+       SOCKET_IN_FLOAT(clearcoat, "Clearcoat", 0.0f);
+       SOCKET_IN_FLOAT(clearcoat_gloss, "Clearcoat Gloss", 0.0f);
+       SOCKET_IN_FLOAT(ior, "IOR", 0.0f);
+       SOCKET_IN_FLOAT(transparency, "Transparency", 0.0f);
+       SOCKET_IN_FLOAT(refraction_roughness, "Refraction Roughness", 0.0f);
+       SOCKET_IN_FLOAT(anisotropic_rotation, "Anisotropic Rotation", 0.0f);
+       SOCKET_IN_NORMAL(normal, "Normal", make_float3(0.0f, 0.0f, 0.0f), SocketType::LINK_NORMAL);
+       SOCKET_IN_NORMAL(clearcoat_normal, "Clearcoat Normal", make_float3(0.0f, 0.0f, 0.0f), SocketType::LINK_NORMAL);
+       SOCKET_IN_NORMAL(tangent, "Tangent", make_float3(0.0f, 0.0f, 0.0f), SocketType::LINK_TANGENT);
+       SOCKET_IN_FLOAT(surface_mix_weight, "SurfaceMixWeight", 0.0f, SocketType::SVM_INTERNAL);
+
+       SOCKET_OUT_CLOSURE(BSDF, "BSDF");
+
+       return type;
+}
+
+PrincipledBsdfNode::PrincipledBsdfNode()
+       : ShaderNode(node_type)
+{
+       special_type = SHADER_SPECIAL_TYPE_CLOSURE;
+       closure = CLOSURE_BSDF_PRINCIPLED_ID;
+       distribution = CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_ID;
+       distribution_orig = NBUILTIN_CLOSURES;
+}
+
+void PrincipledBsdfNode::attributes(Shader *shader, AttributeRequestSet *attributes)
+{
+       if(shader->has_surface) {
+               ShaderInput *tangent_in = input("Tangent");
+
+               if(!tangent_in->link)
+                       attributes->add(ATTR_STD_GENERATED);
+       }
+
+       ShaderNode::attributes(shader, attributes);
+}
+
+void PrincipledBsdfNode::compile(SVMCompiler& compiler, ShaderInput *p_metallic, ShaderInput *p_subsurface, ShaderInput *p_subsurface_radius,
+       ShaderInput *p_specular, ShaderInput *p_roughness, ShaderInput *p_specular_tint, ShaderInput *p_anisotropic,
+       ShaderInput *p_sheen, ShaderInput *p_sheen_tint, ShaderInput *p_clearcoat, ShaderInput *p_clearcoat_gloss,
+       ShaderInput *p_ior, ShaderInput *p_transparency, ShaderInput *p_anisotropic_rotation, ShaderInput *p_refraction_roughness)
+{
+       ShaderInput *base_color_in = input("Base Color");
+       ShaderInput *subsurface_color_in = input("Subsurface Color");
+       ShaderInput *normal_in = input("Normal");
+       ShaderInput *clearcoat_normal_in = input("Clearcoat Normal");
+       ShaderInput *tangent_in = input("Tangent");
+
+       float3 weight = make_float3(1.0f, 1.0f, 1.0f);
+
+       compiler.add_node(NODE_CLOSURE_SET_WEIGHT, weight);
+
+       int normal_offset = compiler.stack_assign_if_linked(normal_in);
+       int clearcoat_normal_offset = compiler.stack_assign_if_linked(clearcoat_normal_in);
+       int tangent_offset = compiler.stack_assign_if_linked(tangent_in);
+       int specular_offset = compiler.stack_assign(p_specular);
+       int roughness_offset = compiler.stack_assign(p_roughness);
+       int specular_tint_offset = compiler.stack_assign(p_specular_tint);
+       int anisotropic_offset = compiler.stack_assign(p_anisotropic);
+       int sheen_offset = compiler.stack_assign(p_sheen);
+       int sheen_tint_offset = compiler.stack_assign(p_sheen_tint);
+       int clearcoat_offset = compiler.stack_assign(p_clearcoat);
+       int clearcoat_gloss_offset = compiler.stack_assign(p_clearcoat_gloss);
+       int ior_offset = compiler.stack_assign(p_ior);
+       int transparency_offset = compiler.stack_assign(p_transparency);
+       int refraction_roughness_offset = compiler.stack_assign(p_refraction_roughness);
+       int anisotropic_rotation_offset = compiler.stack_assign(p_anisotropic_rotation);
+       int subsurface_radius_offset = compiler.stack_assign(p_subsurface_radius);
+
+       compiler.add_node(NODE_CLOSURE_BSDF,
+               compiler.encode_uchar4(closure,
+               compiler.stack_assign(p_metallic),
+               compiler.stack_assign(p_subsurface),
+               compiler.closure_mix_weight_offset()),
+               __float_as_int((p_metallic) ? get_float(p_metallic->socket_type) : 0.0f),
+               __float_as_int((p_subsurface) ? get_float(p_subsurface->socket_type) : 0.0f));
+
+       compiler.add_node(normal_offset, tangent_offset,
+               compiler.encode_uchar4(specular_offset, roughness_offset, specular_tint_offset, anisotropic_offset),
+               compiler.encode_uchar4(sheen_offset, sheen_tint_offset, clearcoat_offset, clearcoat_gloss_offset));
+
+       compiler.add_node(compiler.encode_uchar4(ior_offset, transparency_offset, anisotropic_rotation_offset, refraction_roughness_offset),
+               distribution, SVM_STACK_INVALID, SVM_STACK_INVALID);
+
+       float3 bc_default = get_float3(base_color_in->socket_type);
+
+       compiler.add_node(((base_color_in->link) ? compiler.stack_assign(base_color_in) : SVM_STACK_INVALID),
+               __float_as_int(bc_default.x), __float_as_int(bc_default.y), __float_as_int(bc_default.z));
+
+       compiler.add_node(clearcoat_normal_offset, subsurface_radius_offset, SVM_STACK_INVALID, SVM_STACK_INVALID);
+
+       float3 ss_default = get_float3(subsurface_color_in->socket_type);
+
+       compiler.add_node(((subsurface_color_in->link) ? compiler.stack_assign(subsurface_color_in) : SVM_STACK_INVALID),
+               __float_as_int(ss_default.x), __float_as_int(ss_default.y), __float_as_int(ss_default.z));
+}
+
+bool PrincipledBsdfNode::has_integrator_dependency()
+{
+       ShaderInput *roughness_input = input("Roughness");
+       return !roughness_input->link && roughness <= 1e-4f;
+}
+
+void PrincipledBsdfNode::compile(SVMCompiler& compiler)
+{
+       compile(compiler, input("Metallic"), input("Subsurface"), input("Subsurface Radius"), input("Specular"),
+               input("Roughness"), input("Specular Tint"), input("Anisotropic"), input("Sheen"), input("Sheen Tint"),
+               input("Clearcoat"), input("Clearcoat Gloss"), input("IOR"), input("Transparency"),
+               input("Anisotropic Rotation"), input("Refraction Roughness"));
+}
+
+void PrincipledBsdfNode::compile(OSLCompiler& compiler)
+{
+       compiler.parameter(this, "distribution");
+       compiler.add(this, "node_principled_bsdf");
+}
+
+bool PrincipledBsdfNode::has_bssrdf_bump()
+{
+       /* detect if anything is plugged into the normal input besides the default */
+       ShaderInput *normal_in = input("Normal");
+       return (normal_in->link && normal_in->link->parent->special_type != SHADER_SPECIAL_TYPE_GEOMETRY);
+}
+
 /* Translucent BSDF Closure */
 
 NODE_DEFINE(TranslucentBsdfNode)
index cf68bd804588d6d9c64d2a31585063f0aaa84bb3..bc488161e3b8b38ecebb660fe272c81ae19615e0 100644 (file)
@@ -361,6 +361,39 @@ public:
        float roughness;
 };
 
+/* Disney principled BRDF */
+class PrincipledBsdfNode : public ShaderNode {
+public:
+       SHADER_NODE_CLASS(PrincipledBsdfNode)
+
+       bool has_spatial_varying() { return true; }
+       bool has_surface_bssrdf() { return true; }
+       bool has_bssrdf_bump();
+       void compile(SVMCompiler& compiler, ShaderInput *metallic, ShaderInput *subsurface, ShaderInput *subsurface_radius,
+               ShaderInput *specular, ShaderInput *roughness, ShaderInput *specular_tint, ShaderInput *anisotropic,
+               ShaderInput *sheen, ShaderInput *sheen_tint, ShaderInput *clearcoat, ShaderInput *clearcoat_gloss,
+               ShaderInput *ior, ShaderInput *transparency, ShaderInput *anisotropic_rotation, ShaderInput *refraction_roughness);
+
+       float3 base_color;
+       float3 subsurface_color, subsurface_radius;
+       float metallic, subsurface, specular, roughness, specular_tint, anisotropic,
+               sheen, sheen_tint, clearcoat, clearcoat_gloss, ior, transparency,
+               anisotropic_rotation, refraction_roughness;
+       float3 normal, clearcoat_normal, tangent;
+       float surface_mix_weight;
+       ClosureType closure, distribution, distribution_orig;
+
+       virtual bool equals(const ShaderNode * /*other*/)
+       {
+               /* TODO(sergey): With some care BSDF nodes can be de-duplicated. */
+               return false;
+       }
+
+       ClosureType get_closure_type() { return closure; }
+       bool has_integrator_dependency();
+       void attributes(Shader *shader, AttributeRequestSet *attributes);
+};
+
 class TranslucentBsdfNode : public BsdfNode {
 public:
        SHADER_NODE_CLASS(TranslucentBsdfNode)
index 517a0738b445ab1524f4080cdf32f2d89a2df52d..bee6ae80590fe7340027b8d6ff711ee3f103a4d9 100644 (file)
@@ -226,6 +226,7 @@ shader_node_categories = [
         NodeItem("ShaderNodeMixShader"),
         NodeItem("ShaderNodeAddShader"),
         NodeItem("ShaderNodeBsdfDiffuse", poll=object_shader_nodes_poll),
+        NodeItem("ShaderNodeBsdfPrincipled", poll=object_shader_nodes_poll),
         NodeItem("ShaderNodeBsdfGlossy", poll=object_shader_nodes_poll),
         NodeItem("ShaderNodeBsdfTransparent", poll=object_shader_nodes_poll),
         NodeItem("ShaderNodeBsdfRefraction", poll=object_shader_nodes_poll),
index 193f1154c548fd2282e40311766765a9325ec2ca..7544e8f5b3e7cef6852ec6baae58a996e007f007 100644 (file)
@@ -785,6 +785,7 @@ struct ShadeResult;
 #define SH_NODE_OUTPUT_LINESTYLE               190
 #define SH_NODE_UVALONGSTROKE                  191
 #define SH_NODE_TEX_POINTDENSITY               192
+#define SH_NODE_BSDF_PRINCIPLED         193
 
 /* custom defines options for Material node */
 #define SH_NODE_MAT_DIFF   1
index f3223e31b17ca28ba1b155a8835760a7155071ac..63da1b5f9e75704cf900c06a1ce75b98f448a459 100644 (file)
@@ -3568,6 +3568,7 @@ static void registerShaderNodes(void)
        register_node_type_sh_background();
        register_node_type_sh_bsdf_anisotropic();
        register_node_type_sh_bsdf_diffuse();
+       register_node_type_sh_bsdf_principled();
        register_node_type_sh_bsdf_glossy();
        register_node_type_sh_bsdf_glass();
        register_node_type_sh_bsdf_translucent();
index e4f5802a395fe061d2b0747e1e2531e77691ba85..8dba0e3952407242dec3a23b34816eeace1aeab7 100644 (file)
@@ -1234,6 +1234,7 @@ static void node_shader_set_butfunc(bNodeType *ntype)
                case SH_NODE_BSDF_GLOSSY:
                case SH_NODE_BSDF_GLASS:
                case SH_NODE_BSDF_REFRACTION:
+               case SH_NODE_BSDF_PRINCIPLED:
                        ntype->draw_buttons = node_shader_buts_glossy;
                        break;
                case SH_NODE_BSDF_ANISOTROPIC:
index c354b274f00beda3c163f658cdcc77cfa39a2cd2..b88fba12f55cd0bc1a2b643775ad96c4c2dabc66 100644 (file)
@@ -2378,11 +2378,19 @@ void shade_alpha_obcolor(vec4 col, vec4 obcol, out vec4 outcol)
 
 /*********** NEW SHADER UTILITIES **************/
 
-float fresnel_dielectric(vec3 Incoming, vec3 Normal, float eta)
+float fresnel_dielectric_0(float eta)
+{
+       /* compute fresnel reflactance at normal incidence => cosi = 1.0 */
+       float A = (eta - 1.0) / (eta + 1.0);
+
+       return A * A;
+}
+
+float fresnel_dielectric_cos(float cosi, float eta)
 {
        /* compute fresnel reflectance without explicitly computing
         * the refracted direction */
-       float c = abs(dot(Incoming, Normal));
+       float c = abs(cosi);
        float g = eta * eta - 1.0 + c * c;
        float result;
 
@@ -2399,6 +2407,13 @@ float fresnel_dielectric(vec3 Incoming, vec3 Normal, float eta)
        return result;
 }
 
+float fresnel_dielectric(vec3 Incoming, vec3 Normal, float eta)
+{
+       /* compute fresnel reflectance without explicitly computing
+        * the refracted direction */
+       return fresnel_dielectric_cos(dot(Incoming, Normal), eta);
+}
+
 float hypot(float x, float y)
 {
        return sqrt(x * x + y * y);
@@ -2492,6 +2507,57 @@ float floorfrac(float x, out int i)
        return x - i;
 }
 
+
+/* Principled BSDF operations */
+
+float sqr(float a)
+{
+       return a*a;
+}
+
+float schlick_fresnel(float u)
+{
+       float m = clamp(1.0 - u, 0.0, 1.0);
+       float m2 = m * m;
+       return m2 * m2 * m; // pow(m,5)
+}
+
+float GTR1(float NdotH, float a)
+{
+       if (a >= 1.0) return M_1_PI;
+       float a2 = a*a;
+       float t = 1.0 + (a2 - 1.0) * NdotH*NdotH;
+       return (a2 - 1.0) / (M_PI * log(a2) * t);
+}
+
+float GTR2(float NdotH, float a)
+{
+       float a2 = a*a;
+       float t = 1.0 + (a2 - 1.0) * NdotH*NdotH;
+       return a2 / (M_PI * t*t);
+}
+
+float GTR2_aniso(float NdotH, float HdotX, float HdotY, float ax, float ay)
+{
+       return 1.0 / (M_PI * ax*ay * sqr(sqr(HdotX / ax) + sqr(HdotY / ay) + NdotH*NdotH));
+}
+
+float smithG_GGX(float NdotV, float alphaG)
+{
+       float a = alphaG*alphaG;
+       float b = NdotV*NdotV;
+       return 1.0 / (NdotV + sqrt(a + b - a * b));
+}
+
+vec3 rotate_vector(vec3 p, vec3 n, float theta) {
+       return (
+                  p * cos(theta) + cross(n, p) *
+                  sin(theta) + n * dot(p, n) *
+                  (1.0 - cos(theta))
+              );
+}
+
+
 /*********** NEW SHADER NODES ***************/
 
 #define NUM_LIGHTS 3
@@ -2553,6 +2619,126 @@ void node_bsdf_toon(vec4 color, float size, float tsmooth, vec3 N, out vec4 resu
        node_bsdf_diffuse(color, 0.0, N, result);
 }
 
+void node_bsdf_principled(vec4 base_color, float subsurface, vec3 subsurface_radius, vec4 subsurface_color, float metallic, float specular,
+       float specular_tint, float roughness, float anisotropic, float anisotropic_rotation, float sheen, float sheen_tint, float clearcoat,
+       float clearcoat_gloss, float ior, float transparency, float refraction_roughness, vec3 N, vec3 CN, vec3 T, vec3 I, out vec4 result)
+{
+       /* ambient light */
+       // TODO: set ambient light to an appropriate value
+       vec3 L = vec3(mix(0.1, 0.03, metallic)) * base_color.rgb;
+
+       float eta = (2.0 / (1.0 - sqrt(0.08 * specular))) - 1.0;
+
+       /* set the viewing vector */
+       vec3 V = -normalize(I);
+
+       /* get the tangent */
+       vec3 Tangent = T;
+       if (T == vec3(0.0)) {
+               // if no tangent is set, use a default tangent
+               Tangent = vec3(1.0, 0.0, 0.0);
+               if (N.x != 0.0 || N.y != 0.0) {
+                       vec3 N_xz = normalize(vec3(N.x, 0.0, N.z));
+
+                       vec3 axis = normalize(cross(vec3(0.0, 0.0, 1.0), N_xz));
+                       float angle = acos(dot(vec3(0.0, 0.0, 1.0), N_xz));
+
+                       Tangent = normalize(rotate_vector(vec3(1.0, 0.0, 0.0), axis, angle));
+               }
+       }
+
+       /* rotate tangent */
+       if (anisotropic_rotation != 0.0) {
+               Tangent = rotate_vector(Tangent, N, anisotropic_rotation * 2.0 * M_PI);
+       }
+
+       /* calculate the tangent and bitangent */
+       vec3 Y = normalize(cross(N, Tangent));
+       vec3 X = cross(Y, N);
+
+       /* fresnel normalization parameters */
+       float F0 = fresnel_dielectric_0(eta);
+       float F0_norm = 1.0 / (1.0 - F0);
+
+       /* directional lights */
+       for (int i = 0; i < NUM_LIGHTS; i++) {
+               vec3 light_position_world = gl_LightSource[i].position.xyz;
+               vec3 light_position = normalize(gl_NormalMatrix * light_position_world);
+
+               vec3 H = normalize(light_position + V);
+
+               vec3 light_specular = gl_LightSource[i].specular.rgb;
+
+               float NdotL = dot(N, light_position);
+               float NdotV = dot(N, V);
+               float LdotH = dot(light_position, H);
+
+               vec3 diffuse_and_specular_bsdf = vec3(0.0);
+               if (NdotL >= 0.0 && NdotV >= 0.0) {
+                       float NdotH = dot(N, H);
+
+                       float Cdlum = 0.3 * base_color.r + 0.6 * base_color.g + 0.1 * base_color.b; // luminance approx.
+
+                       vec3 Ctint = Cdlum > 0 ? base_color.rgb / Cdlum : vec3(1.0); // normalize lum. to isolate hue+sat
+                       vec3 Cspec0 = mix(specular * 0.08 * mix(vec3(1.0), Ctint, specular_tint), base_color.rgb, metallic);
+                       vec3 Csheen = mix(vec3(1.0), Ctint, sheen_tint);
+
+                       // Diffuse fresnel - go from 1 at normal incidence to .5 at grazing
+                       // and mix in diffuse retro-reflection based on roughness
+
+                       float FL = schlick_fresnel(NdotL), FV = schlick_fresnel(NdotV);
+                       float Fd90 = 0.5 + 2.0 * LdotH*LdotH * roughness;
+                       float Fd = mix(1.0, Fd90, FL) * mix(1.0, Fd90, FV);
+
+                       // Based on Hanrahan-Krueger brdf approximation of isotropic bssrdf
+                       // 1.25 scale is used to (roughly) preserve albedo
+                       // Fss90 used to "flatten" retroreflection based on roughness
+                       float Fss90 = LdotH*LdotH * roughness;
+                       float Fss = mix(1.0, Fss90, FL) * mix(1.0, Fss90, FV);
+                       float ss = 1.25 * (Fss * (1.0 / (NdotL + NdotV) - 0.5) + 0.5);
+
+                       // specular
+                       float aspect = sqrt(1.0 - anisotropic * 0.9);
+                       float a = sqr(roughness);
+                       float ax = max(0.001, a / aspect);
+                       float ay = max(0.001, a * aspect);
+                       float Ds = GTR2_aniso(NdotH, dot(H, X), dot(H, Y), ax, ay); //GTR2(NdotH, a);
+                       float FH = (fresnel_dielectric_cos(LdotH, eta) - F0) * F0_norm;
+                       vec3 Fs = mix(Cspec0, vec3(1.0), FH);
+                       float roughg = sqr(roughness * 0.5 + 0.5);
+                       float Gs = smithG_GGX(NdotL, roughg) * smithG_GGX(NdotV, roughg);
+
+                       // sheen
+                       vec3 Fsheen = schlick_fresnel(LdotH) * sheen * Csheen;
+
+                       diffuse_and_specular_bsdf = (M_1_PI * mix(Fd, ss, subsurface) * base_color.rgb + Fsheen)
+                                                   * (1.0 - metallic) + Gs * Fs * Ds;
+               }
+               diffuse_and_specular_bsdf *= max(NdotL, 0.0);
+
+               float CNdotL = dot(CN, light_position);
+               float CNdotV = dot(CN, V);
+
+               vec3 clearcoat_bsdf = vec3(0.0);
+               if (CNdotL >= 0.0 && CNdotV >= 0.0 && clearcoat > 0.0) {
+                       float CNdotH = dot(CN, H);
+                       //float FH = schlick_fresnel(LdotH);
+
+                       // clearcoat (ior = 1.5 -> F0 = 0.04)
+                       float Dr = GTR1(CNdotH, mix(0.1, 0.001, clearcoat_gloss));
+                       float Fr = fresnel_dielectric_cos(LdotH, 1.5); //mix(0.04, 1.0, FH);
+                       float Gr = smithG_GGX(CNdotL, 0.25) * smithG_GGX(CNdotV, 0.25);
+
+                       clearcoat_bsdf = clearcoat * Gr * Fr * Dr * vec3(0.25);
+               }
+               clearcoat_bsdf *= max(CNdotL, 0.0);
+
+               L += light_specular * (diffuse_and_specular_bsdf + clearcoat_bsdf);
+       }
+
+       result = vec4(L, 1.0);
+}
+
 void node_bsdf_translucent(vec4 color, vec3 N, out vec4 result)
 {
        node_bsdf_diffuse(color, 0.0, N, result);
index 8d42d746e1c6d1d4b1d2f5b87a59bad8da4a3418..c3477644979ef85c6665b4e845fed9cf583f592e 100644 (file)
@@ -2995,6 +2995,15 @@ static void rna_ShaderNodeScript_update(Main *bmain, Scene *scene, PointerRNA *p
        ED_node_tag_update_nodetree(bmain, ntree, node);
 }
 
+static void rna_ShaderNodePrincipled_update(Main *bmain, Scene *scene, PointerRNA *ptr)
+{
+       bNodeTree *ntree = (bNodeTree *)ptr->id.data;
+       bNode *node = (bNode *)ptr->data;
+
+       nodeUpdate(ntree, node);
+       rna_Node_update(bmain, scene, ptr);
+}
+
 static void rna_ShaderNodeSubsurface_update(Main *bmain, Scene *scene, PointerRNA *ptr)
 {
        bNodeTree *ntree = (bNodeTree *)ptr->id.data;
@@ -3254,6 +3263,12 @@ static EnumPropertyItem node_script_mode_items[] = {
        {0, NULL, 0, NULL, NULL}
 };
 
+static EnumPropertyItem node_principled_distribution_items[] = {
+       { SHD_GLOSSY_GGX, "GGX", 0, "GGX", "" },
+       { SHD_GLOSSY_MULTI_GGX, "MULTI_GGX", 0, "Multiscatter GGX", "" },
+       { 0, NULL, 0, NULL, NULL }
+};
+
 /* -- Common nodes ---------------------------------------------------------- */
 
 static void def_group_input(StructRNA *srna)
@@ -4188,6 +4203,17 @@ static void def_glass(StructRNA *srna)
        RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update");
 }
 
+static void def_principled(StructRNA *srna)
+{
+       PropertyRNA *prop;
+
+       prop = RNA_def_property(srna, "distribution", PROP_ENUM, PROP_NONE);
+       RNA_def_property_enum_sdna(prop, NULL, "custom1");
+       RNA_def_property_enum_items(prop, node_principled_distribution_items);
+       RNA_def_property_ui_text(prop, "Distribution", "");
+       RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_ShaderNodePrincipled_update");
+}
+
 static void def_refraction(StructRNA *srna)
 {
        PropertyRNA *prop;
index d20881df150cbdffc8243831843731c0b02fb4d7..3596a2aa12dd53ecdd94ce988646d0f503d35567 100644 (file)
@@ -163,6 +163,7 @@ set(SRC
        shader/nodes/node_shader_background.c
        shader/nodes/node_shader_bsdf_anisotropic.c
        shader/nodes/node_shader_bsdf_diffuse.c
+       shader/nodes/node_shader_bsdf_principled.c
        shader/nodes/node_shader_bsdf_glass.c
        shader/nodes/node_shader_bsdf_glossy.c
        shader/nodes/node_shader_bsdf_toon.c
index 4c0047f1d583abfe2623c7db55ee31070004a8ee..804c1897a27411ece66048701963849530aa0b16 100644 (file)
@@ -106,6 +106,7 @@ void register_node_type_sh_bsdf_transparent(void);
 void register_node_type_sh_bsdf_velvet(void);
 void register_node_type_sh_bsdf_toon(void);
 void register_node_type_sh_bsdf_anisotropic(void);
+void register_node_type_sh_bsdf_principled(void);
 void register_node_type_sh_emission(void);
 void register_node_type_sh_holdout(void);
 void register_node_type_sh_volume_absorption(void);
index a9c0df7d7e8dcea366f0366d58fc08e193abe02f..e754d06339707e91d8f367399b7322bd0e838318 100644 (file)
@@ -80,6 +80,7 @@ DefNode( ShaderNode,     SH_NODE_BACKGROUND,         0,                      "BA
 DefNode( ShaderNode,     SH_NODE_HOLDOUT,            0,                      "HOLDOUT",            Holdout,          "Holdout",           ""       )
 DefNode( ShaderNode,     SH_NODE_BSDF_ANISOTROPIC,   def_anisotropic,        "BSDF_ANISOTROPIC",   BsdfAnisotropic,  "Anisotropic BSDF",  ""       )
 DefNode( ShaderNode,     SH_NODE_BSDF_DIFFUSE,       0,                      "BSDF_DIFFUSE",       BsdfDiffuse,      "Diffuse BSDF",      ""       )
+DefNode( ShaderNode,     SH_NODE_BSDF_PRINCIPLED,    def_principled,         "BSDF_PRINCIPLED",    BsdfPrincipled,   "Principled BSDF",   ""       )
 DefNode( ShaderNode,     SH_NODE_BSDF_GLOSSY,        def_glossy,             "BSDF_GLOSSY",        BsdfGlossy,       "Glossy BSDF",       ""       )
 DefNode( ShaderNode,     SH_NODE_BSDF_GLASS,         def_glass,              "BSDF_GLASS",         BsdfGlass,        "Glass BSDF",        ""       )
 DefNode( ShaderNode,     SH_NODE_BSDF_REFRACTION,    def_refraction,         "BSDF_REFRACTION",    BsdfRefraction,   "Refraction BSDF",   ""       )
diff --git a/source/blender/nodes/shader/nodes/node_shader_bsdf_principled.c b/source/blender/nodes/shader/nodes/node_shader_bsdf_principled.c
new file mode 100644 (file)
index 0000000..8b0bfa3
--- /dev/null
@@ -0,0 +1,114 @@
+/*
+ * ***** 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.
+ *
+ * The Original Code is Copyright (C) 2005 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#include "../node_shader_util.h"
+
+/* **************** OUTPUT ******************** */
+
+static bNodeSocketTemplate sh_node_bsdf_principled_in[] = {
+       {       SOCK_RGBA, 1, N_("Base Color"),                         0.8f, 0.8f, 0.8f, 1.0f, 0.0f, 1.0f},
+       {       SOCK_FLOAT, 1, N_("Subsurface"),                        0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_FACTOR},
+       {       SOCK_VECTOR, 1, N_("Subsurface Radius"),        1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 100.0f},
+       {       SOCK_RGBA, 1, N_("Subsurface Color"),           0.7f, 0.1f, 0.1f, 1.0f, 0.0f, 1.0f},
+       {       SOCK_FLOAT, 1, N_("Metallic"),                          0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_FACTOR},
+       {       SOCK_FLOAT, 1, N_("Specular"),                          0.5f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_FACTOR},
+       {       SOCK_FLOAT, 1, N_("Specular Tint"),                     0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_FACTOR},
+       {       SOCK_FLOAT, 1, N_("Roughness"),                         0.5f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_FACTOR},
+       {       SOCK_FLOAT, 1, N_("Anisotropic"),                       0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_FACTOR},
+       {       SOCK_FLOAT, 1, N_("Anisotropic Rotation"),      0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_FACTOR},
+       {       SOCK_FLOAT, 1, N_("Sheen"),                                     0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_FACTOR},
+       {       SOCK_FLOAT, 1, N_("Sheen Tint"),                        0.5f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_FACTOR},
+       {       SOCK_FLOAT, 1, N_("Clearcoat"),                         0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_FACTOR},
+       {       SOCK_FLOAT, 1, N_("Clearcoat Gloss"),           1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_FACTOR},
+       {       SOCK_FLOAT, 1, N_("IOR"),                                       1.45f, 0.0f, 0.0f, 0.0f, 0.0f, 1000.0f},
+       {       SOCK_FLOAT, 1, N_("Transparency"),                      0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_FACTOR},
+       {       SOCK_FLOAT, 1, N_("Refraction Roughness"),      0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_FACTOR},
+       {       SOCK_VECTOR, 1, N_("Normal"),                           0.0f, 0.0f, 0.0f, 1.0f, -1.0f, 1.0f, PROP_NONE, SOCK_HIDE_VALUE},
+       {       SOCK_VECTOR, 1, N_("Clearcoat Normal"),         0.0f, 0.0f, 0.0f, 1.0f, -1.0f, 1.0f, PROP_NONE, SOCK_HIDE_VALUE},
+       {       SOCK_VECTOR, 1, N_("Tangent"),                          0.0f, 0.0f, 0.0f, 1.0f, -1.0f, 1.0f, PROP_NONE, SOCK_HIDE_VALUE},
+       {       -1, 0, ""       }
+};
+
+static bNodeSocketTemplate sh_node_bsdf_principled_out[] = {
+       {       SOCK_SHADER, 0, N_("BSDF")},
+       {       -1, 0, ""       }
+};
+
+static void node_shader_init_principled(bNodeTree *UNUSED(ntree), bNode *node)
+{
+       node->custom1 = SHD_GLOSSY_MULTI_GGX;
+}
+
+static int node_shader_gpu_bsdf_principled(GPUMaterial *mat, bNode *UNUSED(node), bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out)
+{
+       // normal
+       if (!in[17].link)
+               in[17].link = GPU_builtin(GPU_VIEW_NORMAL);
+       else
+               GPU_link(mat, "direction_transform_m4v3", in[17].link, GPU_builtin(GPU_VIEW_MATRIX), &in[17].link);
+
+       // clearcoat normal
+       if (!in[18].link)
+               in[18].link = GPU_builtin(GPU_VIEW_NORMAL);
+       else
+               GPU_link(mat, "direction_transform_m4v3", in[18].link, GPU_builtin(GPU_VIEW_MATRIX), &in[18].link);
+
+       return GPU_stack_link(mat, "node_bsdf_principled", in, out, GPU_builtin(GPU_VIEW_POSITION));
+}
+
+static void node_shader_update_principled(bNodeTree *UNUSED(ntree), bNode *node)
+{
+       bNodeSocket *sock;
+       int distribution = node->custom1;
+
+       for (sock = node->inputs.first; sock; sock = sock->next) {
+               if (STREQ(sock->name, "Refraction Roughness")) {
+                       if (distribution == SHD_GLOSSY_GGX)
+                               sock->flag &= ~SOCK_UNAVAIL;
+                       else
+                               sock->flag |= SOCK_UNAVAIL;
+
+               }
+       }
+}
+
+/* node type definition */
+void register_node_type_sh_bsdf_principled(void)
+{
+       static bNodeType ntype;
+
+       sh_node_type_base(&ntype, SH_NODE_BSDF_PRINCIPLED, "Principled BSDF", NODE_CLASS_SHADER, 0);
+       node_type_compatibility(&ntype, NODE_NEW_SHADING);
+       node_type_socket_templates(&ntype, sh_node_bsdf_principled_in, sh_node_bsdf_principled_out);
+       node_type_size_preset(&ntype, NODE_SIZE_MIDDLE);
+       node_type_init(&ntype, node_shader_init_principled);
+       node_type_storage(&ntype, "", NULL, NULL);
+       node_type_gpu(&ntype, node_shader_gpu_bsdf_principled);
+       node_type_update(&ntype, node_shader_update_principled, NULL);
+
+       nodeRegisterType(&ntype);
+}