Interference-based gradients

I was working on something for Krita, based on work I did on shaders for Blender (see here), when I realized I could create some gradients that have their origin in thin-film interference. So that’s what I did.

I create a bundle called Interference_Gradients.bundle with some gradients, including the soap bubble effect. To download, click the link and then download the file Interference_Gradients.bundle. See the image below for a visual representation.

gradients

As I’m not a painter, I’m not sure how useful these could be, but here’s an example that I could think of: adding some iridescence to water droplets.

Before image (original from Pixabay):

After image, with an extra paint layer set to Screen combined with a Filter Mask set to gradient map with the Soap Bubble as a source:


image

Another example is adding post-heating effects to metal objects:
Before (source from Pixabay):

After:


image

Download link is at the top! See below for a more technical explanation of the implementation. Also, though it pertains to Blender, my presentation at Bcon’22 gives some extra explanation of the physics, in case you’re interested.

Implementation details

The colors in the gradient are calculated by using the wave theory of light. The model takes a a base material, a thin layer on top of that and then a final medium. For example, a soap bubble has air as a base material (the inside of the bubble), a thin layer of soapy water, and then air as the final medium (the outside of the bubble). For a single wavelength (think color), incoming light can be partially or fully reflected depending on the thickness of the layer. For white light, this gives rise to a colorful reflection, as some colors are fully transmitted and others are fully reflected.

These gradients were calculated assuming a white light spectrum that is decribed by the CIE D50 standard illuminant, normally incident onto the base layer. For a certain layer thickness, the spectrum was sampled with 80 points (wavelengths). Then, from the resultant reflectance spectra, the CIE X, Y and Z chromaticities were calculated and converted to the ACEScg-elle-V4-g10 color space. This process yields a single color per layer thickness. This process was then repeated for 3000 layer thicknesses, giving 3000 color shades to make up a gradient.

Since gradients with 3000 stops are not very efficient, a subsequent post-processing step set out to eliminate as many stops as possible without sacrificing visual fidelity. In order to do so, the color at every other stop was compared to the color obtained by linear interpolation in the ACEScg color space. If the color difference (delta E) was less than 0.5 (and sometimes less than 0.1), the stop was removed in favor of linear interpolation. This process was repeated until no more stops could be removed without sacrificing visual fidelty.

14 Likes

Thank you for these gradients and the nicely presented examples and technical explanation :slight_smile:

1 Like

Thank you for your kind words and you’re welcome :slight_smile:

I’ve added a few more gradients :white_check_mark:

3 Likes

Thanks for sharing. :slight_smile:

Little issue when importing the bundle on macOS:

After changing the link to the color profile in the SVGs from:
C:/Program Files/Krita (x64)/share/color/icc/krita/ACEScg-elle-V4-g10.icc
to:
/Applications/Krita.app/Contents/share/color/icc/krita/ACEScg-elle-V4-g10.icc
they appear correctly:

It might be a problem on Windows portable version and linux as well.

1 Like

There is an identical issue with the Linux appimage.
This is complicated by the fact that the -/share/color/{etc} path is in the /tmp folder and has a different random name for each session.
It should be possible to workaround this by putting a copy of ACEScg-elle-V4-g10.icc in the standard user resources folder then pointing to it there.

For the Windows portable .zip version, there would be a similar consideration that would depend on where the user keeps their portable .zip versions.
Again, putting the .icc file in the standard user resources folder and pointing to it there should fix the problem.

NOTE: The above is guesswork and I haven’t tried any of it yet.

1 Like

@emilm , @AhabGreybeard, thank you both for reporting this issue! I was afraid something like that might happen. Initially I wanted to store the color values in the XYZ color space, as it’s built-in into Krita. However, it was made impossible by design (see my bug report here). So then I decided to go with a large color gamut that comes with Krita by default, ACEScg-elle-v4-g10.

Here’s the strange thing: I tested the Windows Portable version of Krita on a sandboxed version of Windows (essentially a clean install). It had no issues finding the correct color profile despite the fact that the linked color profile pointed to C:/Program Files/Krita (x64)/share/color/icc/krita/ACEScg-elle-V4-g10.icc, and the actual Krita instance ran from C:\Users\WDAGUtilityAccount\Desktop\SandboxFiles\krita-x64-5.2.3

It also had no issues finding the correct color profile when I completely removed the xlink:href="C:/Program Files/Krita (x64)/share/color/icc/krita/ACEScg-elle-V4-g10.icc" text from the file, as it seems that the local identifier should uniquely point to a single ICC profile on the computer, based on an MD5 hash. Since it comes with Krita, it theoretically should always be found.

It only failed to import the gradients correctly when in a subsequent trial I removed the ACEScg-elle-V4-g10.icc file from the share/color/icc folder.

In between these tests, I reset the sandbox, as it seems that Krita is a bit finicky when re-importing gradients that already have been imported before. Sometimes the gradient doesn’t appear, and on my main installation it simply crashes (that might be related to this bug)

According to the standard, the local profile should be tried first, and on failure, the profile in the xlink:href field. The fact that it fails to do the right thing on MacOS (and Linux?) might actually indicate a bug in the profile finding logic? Or, the profile on MacOS has a different MD5 hash than on Windows?

Normally, when the profile isn’t available, the sRGB colors that are also in the gradient definition. As a happy accident, my code to write the sRGB colors contained a bug which makes the gradients appear as very different from what they are supposed to be. In that sense, my bug was the canary in a coal mine. I’ll fix the gradients such that they will successfully fall back to sRGB mode.

To be honest, I don’t really know how to tackle this issue for MacOS users, as it seems to be out of my control. @emilm would you mind trying a test ‘gradient’ file that indicates whether the color profile is found based on the local field only? The file linked to below is a ‘gradient’ that is pure green if the color profile is found based on local, and red if it falls back to sRGB colors (I’m now exaggerating the canary property :laughing:).

Color profile test gradient

If there’s anyone out there using Linux I’d like to know the results as well!

2 Likes

I fixed the sRGB values, so the gradients should also be usable now when the color profile isn’t found, be it at perhaps a lower visual fidelity. It doesn’t matter if one only uses sRGB colors anyway :slight_smile:

2 Likes

The ‘color profile test gradient’ gave this result with the Linux appimage:

The original .bundle file now seems to have been fixed:

Thank you for the rapid repair :slight_smile:

2 Likes

Thanks for testing! I see that what you predicted for an AppImage indeed happened. I think I’ll report this as a bug, because the behavior is now depending on the OS. Also, it doesn’t seem make sense to extract color profiles to then not parse them :thinking:

1 Like

I get the same result as Ahab.

I tried changing the local tag to the md5 I got for the icc profile in the Krita mac app bundle: f8f26509a7b93f3122380a4d0484dbdb but with no difference.

Adding the href it shows up as green.

2 Likes

Please post a link to any resulting bug report in a reply to this topic.

1 Like

Here it is!
https://bugs.kde.org/show_bug.cgi?id=493493

2 Likes

re. the bug report:

Steps in Linux

4. Adding the field xlink:href=“/Applications/Krita.app/Contents/share/color/icc/krita/ACEScg-elle-V4-g10.icc” to the color-profile tag and re-importing the gradient likely makes it show up in green

That filepath seems to be a copy of the Steps in MacOS section.

For Linux Mint, I have:

i.e. /tmp/.mount_krita-{random}/usr/share/color/icc/ACEScg-elle-V4-g10.icc

Edit:Spelling error corrected for the Linux Mint filepath.

2 Likes

Thanks for that, I’ve added an erratum :white_check_mark:
Indeed I forgot to update the path after copying the MacOS steps

1 Like

You’ve copied my typed spelling mistake.
It’s not colour, it’s color :slight_smile:

I’ve corrected that in my previous reply.

1 Like

Right! :laughing:
Well first let them respond, I think it’s a detail that is worth correcting but once it gets some attention (as I can’t edit the text but only add new)

1 Like