Building an Iridescence Shader in UE4

James Emory shared a detailed breakdown of his Iridescence Shader made in UE4.

James Emory shared a detailed breakdown of his Iridescence Shader made in UE4.

Introduction

I’m James Emory, and I’ve been an independent/freelance developer for 5 years now. I first started off as a texture artist working in Photoshop, and then moved to Substance Designer which is still one of my favorite programs to this day. A few years ago, I switched over to technical art because I dislike modeling and felt that learning shaders was the next logical step from texturing. I currently work as a technical artist on the upcoming PC horror game Lunacy: Saint Rhodes.

Iridescence Shader in UE4

1 of 2

Goal

I started building this iridescence shader for a client working on an ARK mod, and they needed to replicate that traditional beetle shell sort of look. There’s a very scientifically accurate iridescence shader over on the Polycount forums, which was my first approach, but it had its fair share of problems as it’s written in Unreal‘s custom HLSL node (which wouldn’t easily work as ARK’s engine version is quite old) and it is far from being artist friendly. At this point, I knew I’d need a custom approach that would work on such an old engine version without HLSL which led to a shader that can produce similar results to the Polycount version while being constructed in a totally different manner.

Working Strategy

To start off, I’ll give a brief overview of what we’ll be building and then explain how it all works. To start, there will 5 material functions: 3 main functions and 2 helper functions. The 3 methods for generating the color patterns are hue shifting, Rodrigues rotation, and zucconi6 spectrum. The first half of the 3 main functions is exactly the same, with the latter half being specific to the generated color method.

So, my original approach was to handle the iridescence through a UV based hue shift, as I wanted to try creating the colors without prebaked textures. Later I’d expand it to include UV agnostic methods as well. Using the hue shift to produce a rainbow gradient was a trick I picked up years ago, and using it here seemed like a good application. Initially, this method was only UV bound before I adapted it to work without that limitation. That being said, 2 out of the 3 methods contain switches for working in either UV/3D coordinates, with Rodrigues only working in 3D space.

This was my initial prototype graph before expanding it to the system that it is now.

And this is the result applied to a test mesh.

This was a good start, and while not enough, it served as an inspiration to keep going as I felt I was on the right track. So I started adding in features, such as the UV-less methods and light source support.

Foundations

To start, we have to generate a fresnel-like effect by getting the dot product of the pixel normal (or a specified normal that’s transformed to world space) and camera vector. From there, we generate a half vector, which is traditionally used for specular highlights, but in this case, we use it to make sure that the iridescence isn’t being applied everywhere all at once but instead based on the direction of a specified light source.

That is the first half of each of the 3 main functions. What I’d like to do now is cover the 2 helper functions, and then go back to finishing the 3 main functions.

Helper Functions

The first helper function is the Rodrigues Rotation Formula. I came across this on the UDK Polycount forum, so credit to the user who posted it. This formula rotates a Euclidean vector given a rotation axis and an angle of rotation. More info here.

Implementing this into its own main function looks like this:

Next up is the zucconi6 gradient function, and this will produce the best color results by a significant margin, so this one is what I like the most out of all 3 methods. This function is named after Alan Zucconi, the man who created the code for this gradient. I’d highly suggest reading his series on thin film, improving the rainbow and anything else he puts out because he’s amazing.

Now, the code he provides in that article is specifically for Unity and Shadertoy, and I’m using UE4. While you could port the Shadertoy code over to UE using the custom HLSL node, this proved to be quite annoying due to it having helper functions. What I ended up doing was just porting the Shadertoy code over into UE’s node graph and got a very similar result that I’m pleased with.

I won’t be providing a screenshot of this because the color values for some of the nodes are very specific and there’s no way to include all that information in one graph screenshot, so what I’ve done is created a pastebin link for the function. All you have to do is Ctrl + A, Ctrl + C the text at the bottom of that page and then Ctrl + V into your graph and it’ll appear straight away.

This is the gradient that the code produces.

And this is how to implement the function into its own main function:

Finally, we have the hueshift method. This is the first method I tried out, and the UV version is what I applied to the cars in my original post/video.

So that’s it for all the functions, and this is how you’d implement one of the functions into a material. For the half vector (light source support) you’d apply the light source’s rotation to the parameter collection inside a blueprint. Keep in mind, this only works for one light.

As far as the cars go, I used the UV bound function types additively (using add instead of multiply on the base color) and got some very good results out of the functions. This, in my opinion, is where the functions shine.

The final result of the z6 iridescence applied to a material

Summing Up

To sum up, this is all just simple camera/normal vectors + light support being fed into a gradient, so at the end of the day, you could create whatever gradient you want with UE’s curve tools and feed the first half of those main functions into the curve and have whatever colors you want. That being said, being able to generate different colors on the fly with these functions is a very big convenience, at least for me.

James Emory, Technical Artist

Interview conducted by Kirill Tokarev

Join discussion

Comments 4

  • rosewerther

    Question: How did you link a static bool to a Material Instance?

    1

    rosewerther

    ·3 years ago·
  • Anonymous user

    Thanks for the shader breakdown.
    Some questions:

    What is the vector mask output of these 3 functions? How is it calculated?

    What are the inputs for the Append and the Switch node in the MF_IridZ6 coming from outside of the screenshot?

    0

    Anonymous user

    ·3 years ago·
  • Anonymous user

    This is super helpful. Thanks for sharing!

    0

    Anonymous user

    ·4 years ago·
  • Alexey Kropachev

    Hi James,
    Thanks for great work.

    0

    Alexey Kropachev

    ·4 years ago·

You might also like

We need your consent

We use cookies on this website to make your browsing experience better. By using the site you agree to our use of cookies.Learn more