Skip to content

Implement bubbles with ratios of indices of refraction and eliminate negative radius spheres #1420

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
hollasch opened this issue Mar 6, 2024 · 19 comments

Comments

@hollasch
Copy link
Collaborator

hollasch commented Mar 6, 2024

Currently, we implement bubbles (or transparent spheres with non-zero thickness) by specifying an inner sphere of negative radius. It's a hack that works, but creates several geometric issues that then need to be special-cased. Here are some issues dealing with this:

However, there's a much cleaner way to address this. Instead of having dielectric take an index of refraction for the single construction parameter, it should take the ratio of the inner index of refraction over the outer index of refraction. Since air is considered to have an index of refraction of 1.00, the resulting value is the same most materials, where the index of refraction is greater then 1.00. However, this means that bubbles (say of air inside glass) can be specified with a ratio of 1.00 over the index of refraction of the object material (that is, modeling a bubble of air, instead of a bubble of negative glass).

Tests show that the results are identical. To model a hollow glass sphere of non-zero thickness (implicitly filled with air), current code defines an inside sphere as having a negative radius, with an index of refraction of glass. If we change this to have an inside sphere of positive (but smaller) radius, with an index of refraction of 0.67 (= 1 / IOR_glass), then we get identical results. If we follow this approach, then we can eliminate the need to handle or special-case spheres of negative radii.

Before, with negative-radius bubble, IOR of glass:
x_720

After, with positive-radius bubble, IOR of 1/glass:
y_720

(Note that Vassillen Chizhov (@vchizhov) has already made this suggestion parenthetically here: #270 (comment).)

If this work is done, I suggest we either take the absolute value of sphere radii in the constructor, or throw an exception for negative radii or something. Following that, remove the negative-radius hack from the text.

@hollasch
Copy link
Collaborator Author

hollasch commented Mar 7, 2024

I should also point out that this change would allow you to specify bubbles of arbitrary material, such as a bubble of air inside a bubble of water inside a bubble of diamond inside a bubble of quartz inside a sphere of glass in the air.

It still has the limitation that this cannot model a sphere of glass half in and half out of water — instead, the sphere must be fully engulfed by a single medium. To be free of this limitation, we'd have to include the index of refraction for the context of each ray.

@hollasch hollasch added this to the v4.0.0-alpha.2 milestone Mar 11, 2024
hollasch added a commit that referenced this issue Mar 11, 2024
We were using negative radii on spheres to invert the sense of front vs
back faces of spheres, and using this to get an inverted index of
refraction (IOR) for bubbles. This method was used to model a hollow
glass sphere.

Over the past couple of years we've encountered a number of bugs induced
by negative radii spheres (see the list in the description for issue
1420).

Instead, this change interprets the dielectric parameter not as an IOR
relative to surrounding air, but instead as the ratio of the IOR of the
object material over the IOR of the surrounding medium. Interpreting the
parameter this way lets you model a sphere of air enclosed in glass --
just what we need to model a hollow glass sphere purely with the proper
IORs, and without resorting to inverted geometry with negative radii
spheres.

We also end up using this method to properly demonstrate total
internal/external reflection in another section.

Resolves #1420
@TheThief
Copy link

TheThief commented Mar 11, 2024

I think the fix to the call to reflectance in #1426 breaks the idea of representing the inner bubble using 1/ir - the Schlick formula specifically needs to know the two IRs, not the ratio, so representing the inner bubble of air as 1/ir isn't helpful in general as we need 1 and the ir for the Schlick formula. It's possible to detect an ir<1.0 and invert it to recover the ir of the outer medium for the Schlick formula - but that only works in specifically the case of air inside another medium, not e.g. water (ir 1.333) inside the glass (ir 1.5) sphere, so it's not a general solution.

@hollasch
Copy link
Collaborator Author

Not sure I understand. Given $R_1$ and $R_2$, and their ratio $x = \frac{R_1}{R_2}$, then the inverse of $1/x$ yields the inverse of the ratio: $\frac{1}{\frac{R_1}{R_2}} = \frac{R_2}{R_1}$. This works for any two indices of refraction, not just air.

@hollasch
Copy link
Collaborator Author

Put another way, if you know the index of refraction of a material relative to air, and the IOR of a second material relative to air, then you can find the effective IOR of the first material embedded in the second material. No?

@TheThief
Copy link

The Schlick formula doesn't take the ratio, it takes the two IRs. One is hard-coded to 1 in the reflectance() function

@hollasch
Copy link
Collaborator Author

Here's another way to put it. The refractive index is the ratio of the speed of light in a vacuum over the speed of light in the medium. Thus:

$$ n_1 = \frac{c}{V_1} $$

$$ n_2 = \frac{c}{V_2} $$

Thus, the effective refractive index of light traveling from material 1 into material 2, $n_x$, is given by

$$ n_{12} = \frac{V_1}{V_2} = \frac{\frac{c}{n_1}}{\frac{c}{n_2}} = \frac{n_2}{n_1} $$

So you can interpret the vacuum-to-glass refraction as the ratio $\frac{1.50}{1.00}$.

@hollasch
Copy link
Collaborator Author

The Schlick formula doesn't take the ratio, it takes the two IRs. One is hard-coded to 1 in the reflectance() function

Yes, that should be fine. You can use the ratios 1.25 and 1.50, or you can use the ratios 1.00 and 1.20 — they both yield the same result.

@hollasch
Copy link
Collaborator Author

It's not hard-coded to 1 because it only works when traveling from a vacuum; it works from medium to medium, and the inverse of the relative refraction index is the same as the inverse of the ratio of the two refraction indices relative to a vacuum.

Or are you saying that Schlick's formula works only in a vacuum? I haven't seen that stated anywhere. Most sources indicate that it deals with the relative indices of refraction.

@TheThief
Copy link

TheThief commented Mar 11, 2024

I've just run it through mathematically, and you're right! The Schlick formula is stated as taking two irs, but it works identically taking 1.0 and the ratio of the two irs. That's interesting.

For the example of water (ir 4/3) and glass (ir 3/2) and a relative ir of 4/3 / 3/2 = 8/9:

Schlick: R0 = ((ir1 - ir2) / (ir1 + ir2)) ^ 2
(4/3 - 3/2) / (4/3 + 3/2) = -1/6 / 17/6 = -1/17
R0 = 1/(17^2)

Using ratio (8/9) in the current reflectance function:
R0 = ((1 - ir_ratio) / (1 + ir_ratio)) ^ 2
(1 - 8/9) / (1 + 8/9) = 1/9 / 17/9 = 1/17
R0 = 1/(17^2)

@hollasch
Copy link
Collaborator Author

Phew! Thanks for double checking. I think another way to look at it is that the refraction from medium 1 into medium 2 is the same as the refraction from a vacuum into some imagined medium with refraction $\frac{n_2}{n_1}$. At least that's what the $n_{12}$ derivation above seems to suggest.

Or the relative change in the speed of light from one medium to the next is the same as the relative change in the speed of light from a vacuum into an imagined medium with a refractive index of the ratio of the two mediums.

Anyway, lots of ways to look at it, but I'm relieved it all works.

@TheThief
Copy link

I guess this means the change in #1418 / #1426 isn't technically needed after all - the reflectance function returns the same result regardless of whether it's fed ir or 1/ir (give or take error caused by the inversion). I'd assumed this wasn't true "in general", but it seems to be.

@TheThief
Copy link

I'd already extended my implementation to instead track the current "ir stack" in the ray, and push/pop from it on transitions between objects, so the cheat of using 1/ir or ir1/ir2 isn't required

@hollasch
Copy link
Collaborator Author

Oh man, you're right. I think I'll drop this particular PR then.

By the way, I think the following an algebraic proof of the reflectance equivalence:

$$ \frac{(1 - \frac{a}{b})^2}{(1 + \frac{a}{b})^2} = \frac{(b-a)^2}{(b+a)^2} $$

$$ \frac{(1 - \frac{a}{b})(b+a)}{(1 + \frac{a}{b})(b-a)} = \frac{(b-a)(1+\frac{a}{b})}{(b+a)(1-\frac{a}{b})} $$

$$ \frac{b + a - a - \frac{a^2}{b}}{b - a + a - \frac{a^2}{b}} = \frac{b + a - a - \frac{a^2}{b}}{b - a + a - \frac{a^2}{b}} $$

$$ \frac{b - \frac{a^2}{b}}{b - \frac{a^2}{b}} = \frac{b - \frac{a^2}{b}}{b - \frac{a^2}{b}} $$

$$ 1 == 1 $$

@hollasch
Copy link
Collaborator Author

Closing this issue. Added @TheThief to acknowledgments in separate PR (#1429).

@hollasch
Copy link
Collaborator Author

Ugh. Wrong issue. 😄

@hollasch hollasch reopened this Mar 11, 2024
@hollasch
Copy link
Collaborator Author

Realized lying in bed last night that there's an easier proof.

$$ \frac{(1 - \frac{a}{b})^2}{(1 + \frac{a}{b})^2} = \frac{b^2(1 - \frac{a}{b})^2}{b^2(1 + \frac{a}{b})^2} = \frac{(b - a)^2}{(b - a)^2} $$

@TheThief
Copy link

TheThief commented Mar 12, 2024

The really fun thing is that:

$$\left(\frac{a - b}{a + b}\right)^2 = \left(\frac{1 - \frac{b}{a}}{1 + \frac{b}{a}}\right)^2 = \left(\frac{\frac{a}{b} - 1}{\frac{a}{b} + 1}\right)^2$$

$$= \left(\frac{b - a}{b + a}\right)^2 = \left(\frac{1 - \frac{a}{b}}{1 + \frac{a}{b}}\right)^2 = \left(\frac{\frac{b}{a} - 1}{\frac{b}{a} + 1}\right)^2$$

and it's not the least bit intuitive that that should be so.

@TheThief
Copy link

And if a is 1 (as it is when moving between air-being-approximated-as-1.0 and another medium) you additionally get:

$$\left(\frac{1 - b}{1 + b}\right)^2 = \left(\frac{\frac{1}{b} - 1}{\frac{1}{b} + 1}\right)^2 = \left(\frac{1 - \frac{1}{b}}{1 + \frac{1}{b}}\right)^2$$

which similarly seems nonsensical, but it's just dividing the top and bottom by b

hollasch added a commit that referenced this issue Mar 12, 2024
We were using negative radii on spheres to invert the sense of front vs
back faces of spheres, and using this to get an inverted index of
refraction (IOR) for bubbles. This method was used to model a hollow
glass sphere.

Over the past couple of years we've encountered a number of bugs induced
by negative radii spheres (see the list in the description for issue
1420).

Instead, this change interprets the dielectric parameter not as an IOR
relative to surrounding air, but instead as the ratio of the IOR of the
object material over the IOR of the surrounding medium. Interpreting the
parameter this way lets you model a sphere of air enclosed in glass --
just what we need to model a hollow glass sphere purely with the proper
IORs, and without resorting to inverted geometry with negative radii
spheres.

We also end up using this method to properly demonstrate total
internal/external reflection in another section.

Resolves #1420
hollasch added a commit that referenced this issue Mar 14, 2024
We were using negative radii on spheres to invert the sense of front vs
back faces of spheres, and using this to get an inverted index of
refraction (IOR) for bubbles. This method was used to model a hollow
glass sphere.

Over the past couple of years we've encountered a number of bugs induced
by negative radii spheres (see the list in the description for issue
1420).

Instead, this change interprets the dielectric parameter not as an IOR
relative to surrounding air, but instead as the ratio of the IOR of the
object material over the IOR of the surrounding medium. Interpreting the
parameter this way lets you model a sphere of air enclosed in glass --
just what we need to model a hollow glass sphere purely with the proper
IORs, and without resorting to inverted geometry with negative radii
spheres.

We also end up using this method to properly demonstrate total
internal/external reflection in another section.

Resolves #1420
@hollasch
Copy link
Collaborator Author

Done.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants