Tuesday 27 February 2018

Fancy Shaders - Part 1: Oil Interference

Final Cg Shader in Unity

I have decided to start a series of posts called "Fancy Shaders". From time to time I'll be posting some interesting tricks that you can do with shaders. Each post will have a bit of theory and explanation and, of course, source files. My main tool is Unity, as it will be easier for you to implement shaders there:)

The first post in "Fancy Shaders" is about interference. That's a pretty cool topic from wave physics which can be used in computer graphics as well! The effect is showed in the GIF above. Basically, it can also be used for puddles, some painting materials, etc. By the way, if you want to read more about diffraction & interference with Unity examples, I highly recommend you to check out the posts by Alan Zucconi. Also, another great source was this awesome book:

"Graphics Shaders: Theory and Practice, Second Edition"
by Mike Bailey and Steve Cunningham
  
Firstly, let's start with some light theory. I will just remind you some things from your high-school physics course:) Iridescence is a phenomenon that appears to change object's color when the view or illumination angles change (yeah, like in soap bubbles). We also know that light is a wave. More specifically, light is a disturbance in the electromagnetic field. A photon is a particle, the quantum of that field. It carries the energy which describes the color of light. As light is a wave, it has some wave's properties, such as wavelengths. We can also represent the energy as a wavelength, so different energies have different wavelengths and thus there're different colors (but the speed of light is constant). Take a look at this table:


Alright, now the question is how to convert this specter to a common RGB palette? There is no straightforward solution for that, but there are many functions which can approximate RGB values for wavelengths. I won't go into the details, as Alan Zucconi explains (here) that topic very well, so I will just use his method. I find it really decent and optimized for our purposes. Because you should understand that we must keep our shaders as simple as possible: i.e. putting a lot of branch-statements is not a good practice!

Ok, we converted the spectrum "somehow". Now to keep things a bit more clear we need to apply this approximation to our color in the shader. But we do not have anything for our function's input parameter - wavelength. Let's then move to interference. Again, to make it simple, I won't dive deep into physics. You can understand interference as a process of getting a new wave from two light waves that are reflecting from the surface (oil/water, let's say). To get a clear understanding take a look at this picture:


Also, for a good approximation, one incident ray is definitely not enough. We need to set a number of multipliers for our function and then loop through them. Another thing to mention is the refractive index which determines the deviation of the light angle. If you look at the picture, you will see that light changes its angle when hitting the oil surface. These refractive indexes are different for various surfaces. (air/oil is about 1.4) Down below is the formula that can be used for calculating the wavelength using the things above.



The final thing is d - the height of our refractive surface (in our case its oil). How can we calculate it? Well, we can use a noise function for that! "Graphics Shaders: Theory and Practice"  has an interesting approach: we multiply the height value (from the input, for instance) by an exponential height of the "hump" that we get from the noise texture. In fact, we assume that our oil surface has the shape of this "hump". That is why we can see all colors from wavelengths of different values.

Now we can calculate d:

And that's basically it! Now you know how we can achieve this cool interference effect with a couple of shader instructions. In addition, there is a lot of space for playing with variables and their values. Many things are editable so you can set everything for your special needs. You can use different noise textures for the pattern, too. And one more time I want to mention Alan Zucconi and his awesome blog. I recommend to go there and clarify all the things you did not understand or I did not mention here! Because the purpose of this post was to give a basic overview of this light phenomenon and its usage with shaders.

Once you have an understanding of the process, you can download my Cg shader here.

Links:
1. https://www.alanzucconi.com/2017/07/15/the-nature-of-light/
2. https://www.alanzucconi.com/2017/07/15/improving-the-rainbow/
3. https://www.alanzucconi.com/2017/07/15/improving-the-rainbow-2/
4. https://www.alanzucconi.com/2017/07/15/understanding-diffraction-grating/
5. https://www.alanzucconi.com/2017/07/15/the-mathematics-of-diffraction-grating/
6. https://bit.ly/2ougyTW

Monday 5 February 2018

Simple image processing with Xenko Engine

This will be a very short post, as I only want to introduce you Xenko Engine. It's a modern, open-source, 2D/3D cross-platform engine by Silicon Studio that has a plenty of cool features: scene editor, VR support, physics, animation, PBR and many more. Xenko is very similar to Unity because it also uses C#, so working with it wouldn't be painful. In addition, it has its own Xenko Shader Language that is based on HLSL. That's why I'd like to show you a couple of small shaders which I implemented while playing with the engine last night. They're just simple color tranformations: inversion, thermal vision and posterization. Nothing special, however, I find it kind of useful in order to understand how things work :)


Ok, so let's start with something difficult - color inversion... Of course, it's ridiculously simple! We just subtract our input color values and that's it :)


Inversion effect

Then we move to the thermal vision effect. You should understand that it's still a "fake" simulation of heat vision. However, it might be useful in some cases. Again - super simple: make gradient, calculate pixel's luminance and change it's color using linear interpolation. Here's the code:

Thermal Vision

Lastly, posterization effect. It is a process of a continuous gradation of tone to regions of fewer tones, with abrupt changes. Shader itself is quite simple, too, although, you may play with some settings: gamma value and number of colors.

Posterization Effect

If you want to add your own custom transform shaders, some .cs scripts should also be included. You can read more in Xenko's documentation. Don't worry, I will put everything into an archive down below. Oh, and by the way, some people may notice that I am inheriting Texturing on top of my shaders but I do not use any textures. That's true! I just wanted to show you that it is possible to create your own custom textures and implement more complicated and fancy effects, such as blur, for example.
Link to the archive: download