Complex fresnel using VRayOSLtex

Here’s an osl texture based on the paper “Artist friendly metallic fresnel” by Ole Gulbrandsen
http://jcgt.org/published/0003/04/03/

Usage is: diffuse black, fresnel off, add VRayOSLTex to the reflection map.

Example scene from vray-materials.de

OSL texture




AFMFresnel.zip (403 KB)

Looks cool. Looking forward to trying it out.

And thanks!

Wow thats amazing, thank you.

Wow…that’s great…is it possible to port this to maya to try it out?

you know I thought it would work in maya just the same, I’ll have a look on monday.

OMG somebody’s using OSL - that’s supercool :slight_smile:

Thanks for sharing!

Best regards,
Vlado

Seems nice,
How do we use it ?
I’ve got a black render and nothing appearing in the shader itself

Stan

Same here. And I could have sworn I had OSL working with the thin-film shader that Vlado posted in another thread. That’s not working now either.

looks like you are using it as an OSL material, it’s used with the OSL texture in reflection and regular VRay material.

@jasonhuang so the .oso file will load into maya but I had to change the Color Output from result to Col_Out (max did this for me by default)
rest is the same, diffuse black and fresnel off as the shader does that work now.

Thanks Jay. Will give that a try!

cheers!

Thanks for the OSL Texture. But I’m not really sure how to use it. On the refractiveindex.info site I can find the n and k values for a whole range of materials, but in the texture I can only put in colors, not the values for n and k. Is there a way to convert these numbers to rgb colors?

Hey OK! Looks like you just put in the values for R,G and B wavelengths respectively, so if you find the data on red for a material you enter that as the R part of the N and K colours, same for G and B. If your scale is 0-255 then just multiply your N,K values by 255.

So you look up N,K values for the R,G,B wavelengths and multiply them by 255. Optionally you could rewrite it to accept textures and put a VRayColor map in so you can use the direct values.

Rensy-Baby, thanks for the answer. But somehow it doesn’t work as expected. Let’s take a copper material for example:

When I type in the average wavelength for the blue component (472nm), the n value is already 1.2335. Obviously I can not multiply that value with 255, because I can’t put values greater that 255 into the color slots of the OSL. Same is for the k value.

Ah.. Duh, good point.

Here’s a quick hack, see if that works:


	//--Artist Friendly Metallic Fresnel--
	// BY Ole Gulbrandsen - Framestore
	//olegul@hotmail.com
	//http://jcgt.org/published/0003/04/03/
	//OSL version by JayCMiller
	//jcmiller.web@gmail.com
	//AFfresnel V 0.1 - tested in VRay 3.05.07
	// added texture slots - rh

	float n_min( float r ){
		return (1-r )/(1+ r );
	}
	float n_max( float r ){
		return (1+ sqrt ( r ))/(1- sqrt ( r ));
	}
	float get_n ( float r , float g){
		return n_min( r )*g + (1-g)*n_max( r );
	}
	float get_k2 ( float r , float n){
	float nr = (n+1)*(n+1)*r-(n-1)*(n-1);
		return nr/(1-r );
	}
	float get_r ( float n, float k){
		return ((n-1)*(n-1)+k*k )/(( n+1)*(n+1)+k*k);
	}
	float get_g ( float n, float k){
	float r = get_r (n,k);
		return (n_max( r)-n )/( n_max( r)-n_min( r ));
	}
	float AFMF ( float r , float g, float theta ){
	//clamp parameters
	float _r = clamp(r ,0 ,0.99);
	//compute n and k
	float n = get_n (_r ,g);
	float k2 = get_k2 (_r ,n);

	float c = cos ( theta );
	float rs_num = n*n + k2 - 2*n*c + c*c;
	float rs_den = n*n + k2 + 2*n*c + c*c;
	float rs = rs_num/ rs_den ;

	float rp_num = (n*n + k2)*c*c - 2*n*c + 1;
	float rp_den = (n*n + k2)*c*c + 2*n*c + 1;
	float rp = rp_num/ rp_den ;

	return 0.5*( rs+rp );
	}

shader AFMFresnelTex (

	string N__ReflectivityTex = "",
	string K__EdgetintTex = "",
	float Color_Gamma = 2.2,

    output color Col_Out = color(0.5)
)

{
	color N__Reflectivity = texture(N__ReflectivityTex, u, v);
	color K__Edgetint = texture(K__EdgetintTex, u, v);
	float thetaB = acos(dot(-I,N));
	float RCH = AFMF(N__Reflectivity[0],K__Edgetint[0],thetaB);
	float GCH = AFMF(N__Reflectivity[1],K__Edgetint[1],thetaB);
	float BCH = AFMF(N__Reflectivity[2],K__Edgetint[2],thetaB);

	Col_Out = pow(color(RCH,GCH,BCH), Color_Gamma);

}

Isn’t inputting rgb wavelength n and k values exactly what this shader tries to avoid?

I understand how to get the reflectivity value from the charts, but how exactly is the edgetint color determined (in layman terms)? Shouldn’t it always be white?

If the colour swatches used float values instead of 0-255, can you not use the R values from the reflection calculator?

Ah, completely missed the first link, sorry. Yes, they remapped it.

So, Reflectivity and Edgetint aren’t N and K values, they are calculated from it. Which allows for easy picking and storing of the values. The falloff to white is handled by the shader. Haven’t found a calculator for the colour values online, but the conversion is done with equation 14 and 15 from the paper.

I have no idea what this is all about, then :wink:
I thought that this osl texture should make the creation of realistic metals easier. So far I have always recreated the reflectance curves for each color component with the output curves from a falloff map. The results are great, but the process is tedious… I was expecting to just put the n and k values into the osl texture and there you go. Wishfull thinking :smile:

Well, you are welcome to contact the authors of the paper and explain this to them :slight_smile: I was a bit puzzled myself what is the purpose of their work…

In any case, it is not too difficult to modify the shader to take n and k values directly instead of random colors - will see if I can do that if I get a bit of time.

Best regards,
Vlado