So recently I had the need to convert some Arnold materials to Vray. The aiStandard uses the Schlick’s approximation under the “reflectance at normal” attribute, similar to the Mental ray’s brdf control, the difference is that in Arnold you only have control over the 0 degree reflection, not 90 degrees slider or brdf curve control like in the Mia material. But, VrayMtl doesn’t have any other control for reflection falloff other than based on IOR, so having the background on the Fresnel formula implementation with remapValue node and sampler info, the Schlick’s approximation should be easy enough to implement and attach to a VrayMtl. In this post I am going to share with you the Schlick approximation formula in python and how to get around some issues.
The first step is to find the Schlick’s approximation formula and convert it to python. So the formula looks like this:
Right, so if you follow along the previous posts about Fresnel you have seen already that this will be really easy to implement, we already have the maths in python for the incident angles in radians, and all the other parts are just simple numbers, like the reflectance at normal incident that we want to input.
Translating the formula to Python
def SchlickAprox(reflt0): reflt0 = reflt0 theta_deg = 0 RefltResult =  while theta_deg <= 90: theta = math.radians(theta_deg) refVal = reflt0 + (float(1-reflt0)) * (1-math.cos(theta))**5 RefltResult.append( round(refVal,6) ) theta_deg += 1 return RefltResult
So, we use the same approach of the complex IOR formula, this function will output the values into an array, from 0 to 90 degrees. The argument reflt0 is where we will input later the desired reflectance at normal.
VRay with Schlick Fresnel
The main reason I dived into the Schlick thing is that I wanted to convert some Arnold materials into VRayMtl’s. So, just like in the previous posts about Fresnel we need a function to draw the curve for us into the remapValue node and use a samplerInfo node to input the facing ratio.And again we use the Ramer-Douglas-Peucker algorithm to reduce the curve points. So here is the draw function for the Schlick’s curves:
def drawSchlick(normalReflt,VrayMtlNode): ref0Val = normalReflt # create remapValue node remapNode = cmds.shadingNode('remapValue',asUtility=1) schlickSInfo = cmds.shadingNode('samplerInfo',asUtility=1) cmds.connectAttr(schlickSInfo+'.facingRatio', remapNode+'.inputValue',f=1) # Material connection cmds.connectAttr(remapNode+'.outValue', VrayMtlNode+'.reflectionColorAmount') # Calculate Fresnel Curve SchlickList = SchlickAprox(ref0Val) # Compensate for non-linear facingRatio linearValues = [ float(i)/90 for i in range(91) ] rawValues = [ math.sin(linearValues[i]*90*math.pi/180) for i in range(91) ] rawValues.reverse() # Reduce curve points myline = zip(rawValues, SchlickList) precisionVals = [0.00005,0.0001,0.0002,0.0003] simplified =  for i in precisionVals: if len(simplified) == 0 or len(simplified) > 50: simplified = ramerdouglas(myline, dist = i) # Remove default values cmds.removeMultiInstance(remapNode+'.value', b=1) cmds.removeMultiInstance(remapNode+'.value', b=1) # Draw curve on remapValue Editor for i in simplified: currentSize = cmds.getAttr(remapNode +'.value',size=1) # First and last values with Linear interpolation if simplified.index(i) == 0 or simplified.index(i) == len(simplified)-1: cmds.setAttr( remapNode+'.value['+str( currentSize+1 )+']', i,i,1, type="double3") # Others with Spline interpolation else: cmds.setAttr( remapNode+'.value['+str( currentSize+1 )+']', i,i,3, type="double3")
So, after this I started working on a Material Converter between Arnold and Vray, and this is the part where I am dealing with Arnold’s Schlick Fresnel:
#Schlick fresnel else: print 'Schlick Fresnel' normalReflt = cmds.getAttr(Material+'.Ksn') drawSchlick(normalReflt,VrayMtlNode) # reflections not traced under certain threshold (no reflection issue) cmds.setAttr(VrayMtlNode + '.cutoffThreshold', 0.009) cmds.setAttr(VrayMtlNode+'.useFresnel',0) cmds.select(ObjsWithMat) cmds.hyperShade( assign=VrayMtlNode ) cmds.select(clear=1)
So, in this part of the Material Converter script I call the drawSchlick function with the input being the Arnold equivalent material.
VRay reflection threshold
When I was doing some tests on some dummy objects I run into this “strange” issue:
Both the dummy object and the Fresnel “measure” scene were giving me dark spots, I had no idea where that issue was coming from but after playing around with the VRayMtl I found that reducing the cuttoff threshold under the options to 0.009 (default is 0.01) would solve the issue. That’s why in the last code block I change that attribute on line 9.
So, there you have Schlick’s approximation in python that you can now use for any render engine that supports maya’s remapValue node, even on other 3D applications. Ok, I think I will give Fresnel some rest, hopefully we both learned something from this. Post you comments and let me know if you have a more simple approach to this, or maybe some hidden VRay feature to enable Schlick Fresnel? Thanks for reading.