/* * 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. */ /* PYLA 1.3 : PhYsically Correct LAyer Mixer * * by François GASTALDO * * contact me at : pressf9@free.fr * * blog (3D, shaders, photos and more) : http://vadrouillegraphique.blogspot.fr/ * * Small Documentation : This shader is a Physically correct Shader Mixer for layered Materials. It simulates materials made of multiple coating, or layers, like car paint, polished nails ... This is a very simple shader, but very powerful ! You could better manage your mixed Materials, in more realistic way, and with better results. documentation : INPUT : Base = the base shader, the layer will come on top of it. Layer = the layer Material. You can use any shader, except tranparent or glass shader. Pyla is a mixer, and not a real layer simulation, so tranparent shader should give unwanted results ! Opacity = between 0.0 and 1.0, 0.0 = no visible layer, 1.0 = full effect. Depth = the depth of the layer. The thikker the layer is, the less you could see the base. value between 0.0 to 10.0, good value : 2.0. Fresnel = Fresnel visibility for the layer. a full fresnel ( 1.0 ) is perfect for clear coat simulation. 0.0 = the depth only control the visibilty, and not the fresnel effect. IoR = The Index of Refraction for the fresnel effect. The greater it is, the more visible is the layer. MaskLayer = Put here a mask image to have the layer visible just on the white part of the mask. Secondary_Layer = Secondary Optimization: 0.0 = NO Optimization 1.0 = secondary is Base, use this if your Base shader is faster than Layer Shader 2.0 = secondary is Layer, use this if your Layer shader is faster than Base Shader 3.0 = secondary is black (null closure). This is the fatest render, but could be unwanted in case of readable reflection of the object. OUTPUT : Layered (Closure) = Mixed Base and Layer Inputs. Layer Mix (float) = amount of mixing between the base and Layer. You can use it to put in a classical Shader Mixer, or a color mixier, as you wish! TODO : * Transparent Layer capability. This shader was edited with Sublime text Editor : http://www.sublimetext.com/ with OSL package : https://github.com/roesti77/Sublime-Open-Shading-Language * This shader is made for educationnal purpose only. Use it in production at your own risk. * * Closures are for Blender/Cycles. They could need adaptation for your renderer. * * If you use this shader, please credit it and me. Thank you. * * Enjoy ! * * François Gastaldo */ #include "stdosl.h" #include "node_fresnel.h" #include "oslutil.h" float fresnel_dielectric(vector Incoming, normal Normal, float eta) { /* compute fresnel reflectance without explicitly computing * the refracted direction */ float c = fabs(dot(Incoming, Normal)); float g = eta * eta - 1 + c * c; float result; if (g > 0) { g = sqrt(g); float A = (g - c) / (g + c); float B = (c * (g + c) - 1) / (c * (g - c) + 1); result = 0.5 * A * A * (1 + B * B); } else result = 1.0; /* TIR (no refracted component) */ return result; } shader PyLa ( closure color Base = diffuse(N), closure color Layer = 0.0 , float Opacity = 0.5, float depth = 2.0, float Fresnel = 0.5, float IoR = 1.5, float MaskLayer = 1.0 , float Secondary_Layer = 1.0, output closure color Layered = diffuse(N), output float layermix = 0.5 ) { // version 1.2, with optimization float Optim_Secondary = Secondary_Layer ; int RTdirect = raytype ("camera") ; int Optimise = ( RTdirect ) | ( Optim_Secondary == 0.0 ) ; if ( Optimise ) { // Incidence with depth power float InvDepth = 1.0/max( depth , 0.01) ; float incidence = pow ( (1.0 - dot(I, N)) , InvDepth ) ; float fresnelincidence = pow ( fresnel_dielectric( I , N , IoR ) , InvDepth ) ; //float Kr ; float Kt; vector Rr; vector Tt; //fresnel ( -I, N, IoR, Kr, Kt, Rr, Tt); //float fresnelincidence = pow ( Kr , InvDepth ) ; // Mix factor float MixLayer = clamp ( MaskLayer * Opacity * ( (Fresnel * fresnelincidence) + (1.0 - Fresnel) * incidence ) , 0.0 , 1.0 ) ; // float Optim_Threshold = 0.01 ; // if ( MixLayer <= Optim_Threshold ) // { // Layered = Base ; // // } else { Layered = ( MixLayer * Layer) + ( 1.0 - MixLayer ) * Base ; // } layermix = MixLayer ; } else { if ( Secondary_Layer == 1.0 ) { Layered = Base ; } else { if ( Secondary_Layer == 3.0 ) { Layered = 0.0 ; } else { Layered = Layer ; } } } }