Thoughts on making Cycles into a spectral renderer

Basically encode with a pure 1.0/2.2 and try not to get confused by the out of gamut values.

I’m not sure what that means in practice. Is comparing the .exr output good enough or are there extra steps needed? The .exrs are already linear, is my understanding.

Currently, this is how I get my diffs. Is this correct? @troy_s


I think the current testing process is sound. It’s worth waiting for me to get a chance to ensure we’re using the right lookup tables for the CMFs we’ve got, since that could potentially explain a lot of the differences we’re seeing here.

1 Like

I have colorpicked all red values of your RGB and spectral triangles corners on the left .Look the magnitue difference vs a “spectral row”.Notice yellow and blue seems to fit.there is a red boost in cyan and green,and less in magenta and red.

Its just roughly colorpicked as sayed,but you can see clear the difference of the red values.

Found this massive library of diverse spectra
https://crustal.usgs.gov/speclab/
Tried the oak leaf spectrum they measured.

It’s just a single color so it lacks proper leaf texture of course, so I tested it on a noisy menger sponge hoping to get some nice range of direct and indirect light. Definitely looks appropriately leaf-y, although I’m not sure I’d describe it as specifically oak-leaf-y.

EDIT: Also, have a rusty Suzanne wherein both the iron and the rust should have the right spectrum! (The iron isn’t complex IOR data, of course. Instead it’s the reflectance spectrum of iron dust. I’m hoping that’s the same spectrum as if you have bulk iron)

4 Likes

Scroll down to reflectance,and checkmark the “R” for the average polarized Reflection.You can put in the lambda wavelength at the top of the page.

https://refractiveindex.info/?shelf=3d&book=metals&page=iron

With RGB at red 0.65 ,green 0.55, and blue 0.45 micrometer wavelength
you got a RGB F0 reflection “R” of 0.53123, 0.51236, 0.49583

Obviously iron is pretty darn close to colorless but the idea was kinda not to rely on just three colors lol.
This is the actual spectrum of iron dust. It looks pretty dark but I think that’s plausible for iron.

Sure,you can get the reflection values, from all wavelengths you want,inside the measured sample range ofc.

under the optical constant data ,you can download the n k values at the measured wavelengths.
Its quite easy to calc the reflection from these values.

https://refractiveindex.info/database/data/main/Fe/Johnson.yml

Here i made the calculation in Openoffice

1 Like

You kinda prompted me to look more into the Complex IOR math and if I understand right, I managed to partially succeed in implementing a Complex IOR shader in spectral Cycles just using nodes.
It isn’t actually complex yet in that I do not support a k value (though I think this should also be possible),
it only takes the r_s contributions (so the perpenticular beam),
and most importantly it can’t be straight-forwardly used as a mask like regular fresnel would be.

Instead it’s effectively a view-dependent color texture that does follow the math.

Result: (Note how the material becomes slightly lighter near the edge):

Node setup:

These nodes express the (squared) formula for r_s found here:


But currently, k is just set to 0.

To get this to work for arbitrary node setups, as far as I can tell, you’d somehow need a spectral mix shader node where the material weights can actually depend on the input spectrum.
But so long as you’re doing something that behaves like a metal, and so only takes a simple glossy material to model, this ought to work.

For clarity, without the glossy material, with the given spectrum, this results in a color that looks like this:
image

With a basic spectrum like this (note I take the inverse of this for now. Probably could also go for a +1 instead):
image

You instead get this:
image

Resulting in this:

Seems to work quite nicely!

Also,
@smilebags there is a bug right now when you render with GPU and CPU together, that sometimes the last few tiles get messed up (you can see this in the first image above)

4 Likes

This looks really cool, interested to see how this would need to be implemented as a node at some point. Thanks for the bug report, too. I won’t have time to check it for a while but good to know it’s there.

I think essentially you’d need to change (or copy for spectral use) four or five nodes:

  1. The Fresnel node needs two spectral inputs (n, k) (unless you find a way to directly give complex spectra) and at least one spectral output (I’d imagine it’s plausible to provide up to six of those. Could separately include both reflective and both transmissive beams by polarization as well as the unpolarized beams. This is probably overkill. Since we’re not accounting for polarization, it probably simply ought to be the averaged, unpolarized version?)
    1.1. Could also go for the Layer Weight node

  2. The Refraction, Glass, and Principled shaders need n, k as inputs

  3. The mix shader needs a spectrum as input instead of a factor

I’d imagine the fresnel (and maybe layer weight) updates would actually be quite straight forward, and that alone would be enough to give us at least complex-IoR-based metals.
The shaders are probably gonna be trickier.
And I’m especially unsure about the mix shader. This might violate some aspect of the design philosophy or something.

The R0 (direct view a 0 degree angle) reflection calculation ,of the complex index of refraction, is very easy as you can see at my Openoffice post.However, with Fresnel the calculation gets more complicated,but even for this, you find approximations like the ones from Schlick.

btw funny that you found this need for a change.I have posted this idea at blender artists a few months ago.This would very usefull ,since you dont need to split every calc into trichromatic, or here for the spectral chromatics.This would make material creation,layering smaller and easyer,instandly.

This should no problem,as a dev sayed,its get weighted anyway.And the old mix inputs are mostly grey input facs,this would be backwards compatible too.

1 Like

If I did it right, that should amount to the following for Complex IoR:

The Complex IoR Angles node amounts to this:

Including a roughness input (which is missing from regular Fresnel as well)

With the given spectra, the result then looks like this:

Another bug @smilebags

Node Groups make spectral inputs and outputs into color inputs/outputs, in this case destroying the complex IoR effect.

3 Likes

Nice idea with the roughness influence.
If the equation is right then the result should be ok,its difficult to see if something is wrong the bigger the nodebuild gets.

How about checking with Gold nk values? its one of the most colorfull conductor beside maybe copper.

you could,put the reflection output into a plane at maybe a x axis into emission shader to check the values vs a wavlength map.

would be nice if we could plot out numbers directly,for comparison.

Was gonna do just that and here are the results:

Just the color gradient (it’s actually quite subtle on both copper and gold)

As actual shiny spheres (zero roughness, Filmic)

I’m not entirely convinced to be honest. Gold and Copper both appear to land in the right ball park. But they also seem perhaps too bright? I’m not entirely sure. It’s hard to say.

Also I previously accidentally a node input right after the n-spectrum where I failed to square it.
Effectively I put it through “the right math” but as a linear spectrum instead of squared, shifting the colors.
I now fixed this and went with a different example which is the third sphere here.

If anybody wants to fiddle with it (Spectral Branch only!) Dropbox - Complex IoR.blend - Simplify your life

EDIT: Ok I tried some more self-reflecting stuff which turned out to

I’m pretty sure those Complex IOR nodes are correct :slight_smile:

Edit: Here’s the arbitrary test metal in this setting:

I really love how the material ranges from orange to pink. It’s a very odd look. Could be really fun for some weird metallic coating type materials.

2 Likes

Don’t have time for a full reply but I was going to mention, I think a lot of the ‘essence’ of gold comes from the colour in its self reflections. Your menger sponge shows that well.

Yeah for sure! It’s also a rather bright metal. I can tell by the loooooong render times.
Like, that gold menger at 1024 samples took over two hours to render. The much darker weird metal I made only took like twenty minutes tops for the same settings.

Also I had to increase roughness. I tried to render this with roughness 0 at first. That was just a probably never-converging mess of pixels which took forever for every sample. (to be fair, I did set glossy reflections to 1024 bounces and I suspect in this structure there are inherently gonna be a ton of bounces with potentially little loss in brightness so many of the rays might actually get close to that. If I set it to something more reasonable it might render reasonably speedily)
But the higher roughness had the nice side-effect of Multiscatter GXC inherently boosting saturation on rough surfaces. Which, for gold, clearly matters a lot.

1 Like

About the gold color appearence.It depents strong how the shaderball/model is lit.I have the exact same nk IOR values for Gold,from refractive index site, in my carpaint shader,but as rgb cycles,not spectral render.
With filmic highcontrast,and very neutral lit in a modeled paint booth with white area lights.

here are the gold layer underneath/without clear coat (this is why the edges are dark)


And with clearcoat over gold.

the edge ought to go bright even without clearcoat. Like, I only used a single glossy shader for this.

Either way though, looks pretty nice.
If you share your scene there, I could try out the spectral gold to compare. (Or you just take my scene and append that gold material from it)