Page MenuHome

Conductive BSDF Node

Authored by Thomas Dinges (dingto) on Dec 28 2013, 4:18 PM.



This adds a Conductive BSDF Node that implements the Fresnel Equation for Conductors. Inputs are Eta and K (now as vector inputs), the real and imaginary part of the complex IOR of the conductor. These values can be calculated from online availible measurements of various materials.

Diff Detail

Event Timeline

Maybe it would be more useful to implement this as a Color-output node instead of a BSDF, so it could be used for other BSDFs (Anisotropic etc.), just as it is currently done with the Fresnel node.

Thomas Dinges (dingto) requested changes to this revision.Dec 29 2013, 11:36 PM

yes, that is probably a good idea to do. See also Brechts latest comment on this.
Maybe wait a bit though until you completely change it.

Added some code review comments already for the conductor function.


Code style: we usually do:

make_float3(1.0f, 1.0f, 1.0f);

Same code style comment as above.

Wrong: 2.0f
Right: 2.0

OSL handles these as floats anyway, the "f" would cause compiler errors.

I think it should be indeed implemented as a Color node.
Similar to the Fresnel node we have, we would have a "Fresnel Conductor" node.
This can then be used with all closures.

@Brecht Van Lommel (brecht) Does that sound reasonable? :)

If Brecht agrees, you can go ahead and implement this Lukas.

Yes, I think having them as a separate node is best for now.

Lukas Stockner (lukasstockner97) updated this revision to Unknown Object (????).Jan 25 2014, 8:29 PM

The Node is now a Color-Output node. OSL was not tested, since my build somehow doesn't contain it. GPU is also untested.

Brecht Van Lommel (brecht) requested changes to this revision.Feb 4 2014, 6:31 PM

Looks mostly fine, I'll probably commit this for 2.71 as we're not really adding new features at this point in the release cycle.


This doesn't work, there is no float3 type in OSL. It needs to be:

color fresnel_conductive(float cosi, color eta, color k)
    color cosi2 = color(cosi*cosi);
    color one = color(1, 1, 1);
    color tmp_f = eta * eta + k * k;
    color tmp = tmp_f * cosi2;
    color Rparl2 = (tmp - (2.0 * eta * cosi) + one)/
                   (tmp + (2.0 * eta * cosi) + one);
    color Rperp2 = (tmp_f - (2.0 * eta * cosi) + cosi2)/
                   (tmp_f + (2.0 * eta * cosi) + cosi2);
    return (Rparl2 + Rperp2) * 0.5;

(also it the code uses 8 spaces instead of tabs here which does not follow the style convention)


There is a missing ) bracket at the end of this line.


This stack_valid check for eta and k is not necessary, the way the code is now in nodes.cpp it will always have a valid stack offset.


In other nodes we call this IOR, so I think that for consistency Eta should be replaced by that?

Hey Lukas and Brecht,
what is the status of this?

I can fix the remaining issues and merge it, just need to know what needs to be done. Rename ETA to IOR?

Well, we could rename it, although I see two problems with the Name IOR:

  • IOR is usually referring to transmission
  • Both Eta and K are IOR components since the IOR of conductors is a complex number, so only calling the Real part IOR seems strange

My suggestion would be N and K, since "NK-Data" is used at least in LuxRender and Indigo (I don't know about other renderers).

Yes, I'd rename it to IOR. Besides that just needs the OSL shader to be fixed as mentioned in my review above, after that it should be ok to commit.

Missed the above message, but N and K is fine with me.

Thomas Dinges (dingto) updated this revision to Unknown Object (????).Jun 19 2014, 3:21 PM
  • Changed naming to N and K
  • Several fixes

1 Issue remains, although OSL works fine and the N/K values are being passed fine, console prints a warning:

WARNING: attempting to set nonexistent parameter: N WARNING: attempting to set nonexistent parameter: K

We cannot use N in the OSL shader (OSL Global), I pass it as parameter_color() in nodes.cpp.

@Lukas Stockner (lukasstockner97):
We need some values for the wiki or so I guess, I checked online but I usually only find .nk files with more than 3 values, how can these be converted?

Afaik, usually you would need just three Values for RGB. The question is which Wavelength this should be?

In my Metal KN Shader i used those Values here:
R=680nm G=550nm B=400nm

on you can get the NK Values for different Materials and Wavelengths.

You can have a look at my Blend file:
where i have those Values for some common Metals used.

As i said, the exact Wavelength that should be used is something i’m not entirely sure about. but the Concept works that way.

Hope this helps you somewhat Thomas.

AFAIK the spectra for N and K should be multiplied with the CIE XYZ curves. Integrating over these products then gives the XYZ values which then get converted back to RGB by a 3x3 conversion matrix.
I have written an Octave script that does just this, I'll convert the PBRT tables and post them here once I'm home (Monday).

Thank you @Sebastian Röthlisberger (bashi), now I figured it out. :)

It would be nice to have some Example values (Gold, Aluminium, Silver etc) for the Commit Log and Wiki.

Actually just taking the data at specific wavelengths isn't correct since the RGB primitives aren't monochromatic. also gives CSV tables, these seem really useful and can be processed easily, but just taking three wavelengths is quite an approximation. In fact, even the full approach I mentioned isn't entirely correct since that would require full.spectral rendering, but it's the best you can get with Cycles.
Since also has the data, I think I'll be able to post some data later today (like copper, silver, gold, aluminium, chrome).

OK, I just wrote a quick script that parses the database and converts the values by reinterpolating to the CIE table spacings, multiplying the XYZ curves and the N/K-Curves, integrating over them, scaling them appropriately and converting them to RGB space. The CIE XYZ data is from (2006 LMS-transformed, 2-deg, 1nm spacing), the XYZ to RGB matrix is from util_color.h .

I'll also attach the Octave/Matlab-script, it basically expects a cie.csv containing the CIE curves and a data.yml containing the NK-data, in the format "µm-value N-value K-value". Just take a "full database record" from and remove the text header. For using PBRT data, you have to remove the 1000-factor from the script since PBRT uses a nm-scala and copy the N and K files together.

I forgot to mention that usually the Rakic values are the most accurate since the tables are more detailed (the script uses spline interpolation anyways, but you can never be sure). Just look what uses as default. Also, the output is always "R <newline> G <newline> B".
The new gold values are a bit different from the "old" PBRT ones used as default in the node, but there shouldn't be that much of a difference.

Lukas Stockner (lukasstockner97) edited edge metadata.

So, are there any problems remaining with this? I could write a Wiki page with the values once it's commited.

This revision now requires changes to proceed.Jul 20 2014, 4:22 PM

The functionality is ok, but the OSL error from is still remaining. I did not find a solution for this yet.

I commited this as a OSL template now only.


  • This way people can test it first.
  • After further thinking I have my doubts if this node would have been so good in the SVM system, mainly because of the variable naming, which is pretty cryptic still.