9
$\begingroup$

This question is based on the shader in this answer. When I render the scene using plain glass for the material ball, it takes about 500 samples to converge. Here is the node setup and the result at 512 samples:

enter image description here

enter image description here

When I use the dispersion glass material, however, it produces a large amount of noise. Here is the node setup and the result at 2048 samples (4 times as many samples, which should be more than enough to make up for using 3 glass nodes).

enter image description here

enter image description here

Using mix shaders with 3x brighter glass produces the same result. The image does eventually converge after around a hundred thousand samples, but that's obviously not practical for real-world renders. Here is an overnight render at 65536 samples:

enter image description here

I can get a similar, but slightly different, result in far fewer samples by rendering 3 separate images and combining the color channels in an image editor:

enter image description here

But that leaves me with two questions: first, why does using the add shader produce so much more noise than expected? Second, why does it give a different result than a normal glass shader? Specifically, where does the black band at the bottom of the material ball come from?

Here is the .blend file, for reference:

All of this is observed in the material ball scene as of Blender 2.76. There are no lamps in the scene, and enabling/disabling multiple importance sampling of the world background doesn't have any significant effect on the noise. I haven't tested it in other scenes or other versions of Blender/Cycles.

Update: Based on the discussion of Rich Sedman's answer, I experimented with a hybrid shader which uses diffractive glass for the first ray bounce and standard glass for subsequent bounces:

enter image description here

It seems this may be the best we can do within blender, without either using the compositor, or getting a way to generate a per-ray random value within Cycles. Here's the result at 4096 samples, rendered using Blender 3.5.1:

enter image description here

And here is the result if I randomize the IOR of the standard glass as well:

enter image description here

$\endgroup$
2
  • 1
    $\begingroup$ Could the downvoter please explain why they downvoted and suggest how the question could be improved? $\endgroup$
    – Stuntddude
    Jan 3, 2016 at 9:03
  • $\begingroup$ What would be the purpose of adding those shaders? If you need three different colors for the shame shader use color mix nodes. When glass shaders are added they break the energy conservation principle, so the object reflects more light than it receives. Read: blender.stackexchange.com/questions/102462/… $\endgroup$
    – susu
    Feb 6, 2021 at 4:24

3 Answers 3

2
$\begingroup$

The difference is all due to light path.

Consider your 'composite' method - you're essentially just rendering each wavelength of light separately and then combinine the results. This is really simple and for each bounce the wavelength of light considered in the bounce does not change.

In your 'add shader' method, however, Blender will split the ray at each bounce and that resultant ray may or may not be the same "wavelength" on each bounce (Blender is forced to pick one of the IORs for the ray - this is effectively the "wavelength"). If the wavelength for the entire path is the same then your light gets through. However, if the choice of IORs differs over that path then your shader is effectively filtering out the light (eg, a'Red' bounce filters out everything but red light. If that's followed by a 'Green' bounce then that will filter out all the Red and Blue and you've got no light contributed from that ray).

Essentially, on each bounce your shader is discarding two-thirds of the rays. This means you need to really ramp up the samples to give any rays the chance of getting through and contributing to the final image.

For example, consider just 5 bounces. For your composit method, every ray would be considered over its whole path. For the multiple glass shaders method, the chance of a ray not being filtered out becomes 0.333 * 0.333 * 0.333 * 0.333 * 0.333 = 0.004 - ie, you're effectively getting only 0.4% of the rays to contribute to the image.

The solution...? Use the 'composit' method so that you consider each 'band' of colour separately.


EDIT: I've been playing around with this a little bit. Here's my initial take on a dispersion glass material using a single Glass Shader :

material

And here's the result :

result

Rendered using the 'out of the box' Blender 3.5.0 Cycles default settings.

The ranger of IOR is controlled via the second Map Range node (in this case 1.40 to 1.50) and the corresponding light for that IOR range is defined in the Color Ramp. This setup is a bit of a fudge in that you need the Vector Scale 3.0 to adjust the brightness and to manually adjust the colour of the glass by manually varying the amount of RGB in the Color Ramp node.

I've got some ideas for other solutions (such as rendering as separate images and recombining in the compositor) which I'll update as I can.

$\endgroup$
5
  • $\begingroup$ Actually, looks like the above solution (or ones very much like it) have been posted in answers for other questions on this site. Just search for ‘dispersion’ to find some. $\endgroup$ Apr 24 at 22:56
  • $\begingroup$ Thank you so much! I had long since given up on solving this mystery, but you're totally right. I never considered that it will choose a new random path at every bounce. That still doesn't explain why the results of the two methods looked different, but I re-rendered the scene with the add shader in Blender 2.90 and it now looks basically the same as the composite method, so I'm willing to chalk that up as a problem with cycles that got patched at some point. $\endgroup$
    – Stuntddude
    Apr 29 at 20:08
  • $\begingroup$ I'll also note that the color ramp shader seems to have a similar amount of noise as the add shader, I think because the camera data view vector output changes at each bounce, instead of staying the same for the entire ray which is what you'd want. I couldn't find any way to get a unique value per ray/sample, so I'm not sure it's even possible to do dispersion in cycles without an additional compositing step. $\endgroup$
    – Stuntddude
    Apr 29 at 21:07
  • $\begingroup$ I’ve been trying to come up with a way of getting a unique value per sample but, you’re right, there doesn’t seem to be any way to achieve that, which is a shame. It would probably be quite simple to achieve if ‘SampleNumber’ or similar could be exposed to the Attribute Node. I’ll maybe put forward a suggestion to the developers. I do have a plan for a method where each frame could be rendered for a separate wavelength and then combine in the compositor. That should be able to produce quite a good result - although quite cumbersome to set up. $\endgroup$ Apr 29 at 22:32
  • $\begingroup$ Another idea was to set the color of the bounce on the first bounce and then randomly affect just the IOR on each subsequent bounce. Not as physically accurate but produces reasonable results with less noise (as rays aren’t “lost”. $\endgroup$ Apr 29 at 22:36
1
$\begingroup$

It looks like by splitting out into three glass shaders you're getting three times the caustics, and they're tricolor making them difficult to resolve.

Unfortunately cycles is not great with glass, there are other types of renderers that use algorithms like Metropolis Light Transport to find the most likely refraction angles and bias rays in those directions.

LuxCoreRender might be a place to start.

$\endgroup$
1
  • $\begingroup$ I expect this shader to produce 3x as much noise (or even 4x, because the nested add nodes might be splitting samples 50/50, and then 50/50 again if they go down the blue/green branch). Instead, the observed behavior is that it produces more than 100x as much noise. The dark band also remains unexplained. $\endgroup$
    – Stuntddude
    Feb 10, 2021 at 3:54
0
$\begingroup$

This method can be used for every 3d program: you render 1 sample 200 times at same spot and combine using average mode.

$\endgroup$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .