Thoughts on making Cycles into a spectral renderer

Usally for a wave its used 2Pi for one wave cycle.
http://www.math.ubc.ca/~cass/courses/m309-03a/a1/clayton/part2.html

Oh that’s what you mean by lambda. I thought you meant the wavelength.
I think that’s what the δ in my post above does. Or more specifically the cos(δ).
So yeah, then we are (sorta) talking about the same issue: I need trig functions to make this work.

the only trig functions i know from the thinfilm shader, are the fresnel equations and its refraction into the film layer.

here thinfilm in a nutshell

The extra cosine occurs to decide whether a given point is interfereing positively or negatively or something in between. If you’re only looking for only the very brightest or very darkest point (as it’s often being phrased), you get a fixed number. But if you want to smoothly describe the full pattern, you’ll get, for each wavelength, a sort of periodic pattern, the expression of which involves a cosine.
That video considers only the location of the first interference maximum. (And in fact it uses the small angle approximation, dropping those angles entirely)

You mean calc of a wavemodel, where waves can be canceld out or doubled with amplitude?

Yes, that’s the interference part in “thin film interference” after all.

In the thinfilm shader i have rebuild,is a simple greather than node to compare if the IOR of the Thinfilm is bigger as the outer IOR layer,then it gets a phaseshift.of PI. iirc…same for the substrate layer.

I’m guessing that phase shift is the Δ in the above. I don’t see how that makes it possible to get the δ or cos(δ) above though.

yes,the PI gets added to the 2PI then,then you have a sine instead of a cosine.

right, still a trig function that I can’t currently do on Spectra

Here is the thin film shader i have rebuilded,it is well explaned how it works.
https://www.gamedev.net/tutorials/_/technical/graphics-programming-and-theory/thin-film-interference-for-computer-graphics-r2962/
https://docs.chaosgroup.com/display/OSLShaders/Thin+Film+Shader

1 Like

In the code on that page, you get these two lines:

float ts = pow(beta_s) / (pow(alpha_s, 2) - 2 * alpha_s * cos(phi) + 1);
float tp = pow(beta_p) / (pow(alpha_p, 2) - 2 * alpha_p * cos(phi) + 1);

I get all the way to that point. But that phi is spectrally dependent. Constructing it involves n, lambda, and delta, all of which depend on the spectrum. So phi must itself depend on the spectrum. So I need the cos of a spectrum.

Here is a placeholder implementation (I haven’t yet added in the whole Fresnel business or the cutoff for total reflection, but the issue already arises before I need to plug in those values)

As an aside, taking greater than currently also is rather cumbersome. Not impossible, and in fact there are multiple methods, but it takes five nodes where one ought to suffice. So getting such boolean operations would be quite nice as well.

Another thing that would come in extremely handy:
A remap node that works on spectral data. It’d allow me to quite short-circuit how I’m gonna route in those R = 1 nodes (which represent the special case of total reflection) - right now, fitting those in is gonna involve some, like, three or four node spaghetti where, once again, a single node ought to suffice.

1 Like

I’d like to understand this more. What’s the expected behaviour for a node like this?

Sorry I meant a Map Range node.
Just make each of the inputs of that spectral. It should behave per wavelength exactly as the regular Map Range node behaves for a single value. (Honestly I’d also like to see this for vector inputs)

It’s, among other things, a really simple way to generate an If-Then-Else.

  • Plug in as Value your boolean operation (such as my Greater Than hack above),
  • keep From Min and From Max the same (in this case just black and Illuminant E-white respectively, as standins for 0 and 1),
  • and plug in your Then clause into To Max (the behavior if your condition is true)
  • and your Else clause into To Min (the behavior if your condition is false)

I kinda wish (but that’s unrelated to this branch) that there were operator overloaded takes for all nodes where that makes sense. Like, for instance, a singular map range node that works for a simple value, a color, a vector, and spectral data.

Thus far that was easy in that if you have a vector variant, it’ll work for values and colors too.
But due to spectral upsampling, the spectral input behaves differently from the color input so these things would have to be distinguished.

To summarize my current node wishlist:

  • Trig functions for spectral math
  • boolean ops for spectral math
  • Map Range for spectral math (and vector math too)
  • fix node groups involving spectral inputs/outputs (they will currently turn into color input/output, destroying the spectral behavior)
2 Likes

I think fixing node groups is a high priority but the others (while certainly worthwhile features) could wait for a post-merge patch. It might sound like I’m delaying the features by saying that but instead I think it’s important to limit initial scope so that things get done (merged) more quickly.

As someone who has probably used the spectral build far more in-depth than myself, would you agree with that prioritisation?

Imo it depends on when that merge would be happening. If it’s on the horizon then yes.
If it’s still unclear then I think the other extra features wouldn’t really make things that much more complex? - I’m guessing the Map Range one is a bit trickier perhaps. But the various trig and booleans options are like… You already have a lot of other math stuff including logarithms and exponents. I don’t know the code but I’d at least think it’d be relatively trivial to add those. Wouldn’t really delay developing other features much? And I don’t foresee it to be very bugtastic either.
I think if I get at least a Cos (or a Sin but right now a Cos would be more directly useful) I could do everything I currently would like to do.

That said, generally speaking, yes, bug fixes are definitely highest priority so the grouping issue is the most important one. It’d also mean I can make node groups for most currently missing stuff so it’d be more complex than it’d need to be, but at least I don’t need to copy five nodes for a simple boolean operation. I’d just package it up in a group instead.

1 Like

I agree, if it’s just a few percent more work I’m keen to throw it in with the initial release. My concern is with all the ‘little features’ which end up causing bugs and are difficult to explain (with my level of knowledge of the codebase).

The other factor is that each addition is also more lines of code to review. New code warrants much more attention than cookie-cutter changes to large amounts of existing code, so trying to keep that to a minimum is one of my priorities here, especially for the initial patch.

I’m excited to continue developing more features for this because it becomes more and more powerful the more tools we can give to the artist. As always, available time is my weakness here :grinning_face_with_smiling_eyes:

3 Likes

Speaking of bugs and complex features: The spectral version of the sky texture appears to currently be broken.
It might not be worth fixing though. Instead I’d personally opt to have it removed until after the rest of it all gets included. It already had the wrong brightness all along anyways

Yes, I am aware of this one. It’s a lower priority, possibly low enough that the spectral version could be removed (or disabled, depending on Blender’s development practices) for the initial version, and introduced again later.

2 Likes

Those are trivial to add, expect them in the next build :slightly_smiling_face:. Spectral I/O in node groups will be a bit trickier, I’ll figure out something. Right now spectral socket type implementation on the Blender side is kinda hackish, that’s why issues like this pop up sometimes.

My bad, forgot to uncomment some code. I’ll remake this node at some point, hopefully, that will fix brightness issues.

@smilebags As for the code changes complexity, the spectral nodes’ code is not intertwined with the kernel and can be easily separated or removed. I expect that part would have to be rewritten anyway to be properly integrated with Blender. Maybe universal nodes for different data types (like @kram1032 mentioned) would be possible, seeing how quickly node functionality is improved with the everything nodes project.

3 Likes