# A complex approach - Iridescence in cycles

**URL:** <https://blenderartists.org/t/a-complex-approach-iridescence-in-cycles/613211>\
**Category:** Blender Tests\
**Created:** [June 14, 2014, 8:36pm UTC](https://blenderartists.org/t/a-complex-approach-iridescence-in-cycles/613211 "2014-06-14T20:36:39Z")\
**Posts on this page:** 20\
**Page:** 4

<div class="post-metadata">

**Author:** ![Microno](https://blenderartists.org/user_avatar/blenderartists.org/microno/32/22845_2.png) [@Microno](https://blenderartists.org/u/Microno)\
**Post date:** [September 14, 2014, 2:46pm UTC](https://blenderartists.org/t/a-complex-approach-iridescence-in-cycles/613211/61 "2014-09-14T14:46:01Z")

</div>

@Secrop alright, so I uploaded it to pasteall, [here’s the link](http://www.pasteall.org/blend/31577). I wanna ask how you came to that “implementation” of vector rotation, it seems somewhat similar to quaternion\*vector when the axis of rotation is perpendicular to the vector being rotated. Would I be correct in assuming that?

---

<div class="post-metadata">

**Author:** ![Secrop](https://blenderartists.org/user_avatar/blenderartists.org/secrop/32/20093_2.png) [@Secrop](https://blenderartists.org/u/Secrop)\
**Post date:** [September 14, 2014, 4:53pm UTC](https://blenderartists.org/t/a-complex-approach-iridescence-in-cycles/613211/62 "2014-09-14T16:53:39Z")

</div>

@Microno… It looks like the zero vector that results from the cross node, is not really a [0.0,0.0,0.0] vector :eek:  
(Null or NaN perhaps??)…

I never tried to use the cross product with a zero vector, so this was a surprise!!  
I’ve check the value of each component, with ‘GreaterThan’ and ‘LessThan’ and it turns out that there are no floats in any component.

That’s why the Add Vector couldn’t perform normally. (I’d love to know if there’s some info coming out in the debug, but i don’t know how to do it)

About my ‘implementation’, I don’t know if there’s any similarity to quaternions:confused:… I confess that I don’t understand quaternion logic at all. My first node was just replicating what I read in books…:o

In my new approach, I started by the principle that a point rotated around an axis will draw a circle. And for an angle x, the resulted vector would be the sum of a vector X, with length=cos(x) and a vector Y, with length=sin(x).  
I simplified it a bit, because in this case, the axis and the vector are allways perpendicular, which are the tangent and the normal. 🆒

So, for the Y vector, I find the axis perpendicular to the plane [Vector, Axis] with cross(Vector, Axis), multiply it by the sin(x).  
For the X vector, I just multiply the original Vector with cos(x).

A more correct approach for rotations, would be to find the minimum distance from the Axis to the point being rotated, and multiply this distance by the sine and cosine…(which is a little superfluous for this particular purpose)

---

<div class="post-metadata">

**Author:** ![Microno](https://blenderartists.org/user_avatar/blenderartists.org/microno/32/22845_2.png) [@Microno](https://blenderartists.org/u/Microno)\
**Post date:** [September 15, 2014, 7:59am UTC](https://blenderartists.org/t/a-complex-approach-iridescence-in-cycles/613211/63 "2014-09-15T07:59:29Z")

</div>

Oh I see what you’re doing. That process generalises to quaternions actually, it’s pretty useful. Quaternion logic, I found, was best explained on [this site](http://3dgep.com/understanding-quaternions/).

I suspected it produced a NaN or Null of some sort, but shouldn’t there be some code that defaults that to zero in calculations and throws an error? I believe that would be more efficient since it wouldn’t break already existent node structure. I think this should be submitted as a bug if it isn’t already there, I’ll start a thread and hopefully get someone who can get the debug data and submit a proper bug report.

One thing I’m curious about is why you’re using the cosine of the angle between as opposed to the sine in the DiffractionGrating node group?

---

<div class="post-metadata">

**Author:** ![Secrop](https://blenderartists.org/user_avatar/blenderartists.org/secrop/32/20093_2.png) [@Secrop](https://blenderartists.org/u/Secrop)\
**Post date:** [September 15, 2014, 9:38am UTC](https://blenderartists.org/t/a-complex-approach-iridescence-in-cycles/613211/64 "2014-09-15T09:38:51Z")

</div>

Thanks for the link. Looks very well explained! Must read it carefully 🙂

> [@Microno](#):
>
> One thing I’m curious about is why you’re using the cosine of the angle between as opposed to the sine in the DiffractionGrating node group?

I’m not seeing which cosine/sine are you refering to…do you mean in the AngleSolver or in the VectorRotation? can you specify it better?

---

<div class="post-metadata">

**Author:** ![Microno](https://blenderartists.org/user_avatar/blenderartists.org/microno/32/22845_2.png) [@Microno](https://blenderartists.org/u/Microno)\
**Post date:** [September 15, 2014, 10:02am UTC](https://blenderartists.org/t/a-complex-approach-iridescence-in-cycles/613211/65 "2014-09-15T10:02:22Z")

</div>

Oh, I didn’t realise I had an older version of your shader 😃 Ignore that question.

Again though, why not use the Cross Product as opposed to the Dot Product -\> arccos -\> sine as that would give the sine of the angle directly?

---

<div class="post-metadata">

**Author:** ![Secrop](https://blenderartists.org/user_avatar/blenderartists.org/secrop/32/20093_2.png) [@Secrop](https://blenderartists.org/u/Secrop)\
**Post date:** [September 15, 2014, 10:19am UTC](https://blenderartists.org/t/a-complex-approach-iridescence-in-cycles/613211/66 "2014-09-15T10:19:24Z")

</div>

You’re totally right!!! 🙂  
I was thinking that the cross product would only return the vector, and I thought in calculating the magnitude of the vector with another dot product… I read somewhere, that trignometric functions were just look up tables, and were not calculated, that’s why I end up using the arccos and sine (but i may have misread also :/)

I see now that the magnitude is outputted in the ‘value’ socket!!! This is great!!

---

<div class="post-metadata">

**Author:** ![Microno](https://blenderartists.org/user_avatar/blenderartists.org/microno/32/22845_2.png) [@Microno](https://blenderartists.org/u/Microno)\
**Post date:** [September 15, 2014, 10:28am UTC](https://blenderartists.org/t/a-complex-approach-iridescence-in-cycles/613211/67 "2014-09-15T10:28:27Z")

</div>

> [@Secrop](#):
>
> You’re totally right!!! 🙂  
> I was thinking that the cross product would only return the vector, and I thought in calculating the magnitude of the vector with another dot product… I read somewhere, that trignometric functions were just look up tables, and were not calculated, that’s why I end up using the arccos and sine (but i may have misread also :/)
> 
> I see now that the magnitude is outputted in the ‘value’ socket!!! This is great!!

Fantastic!

Mind you, have you come across instabilities with the rendering? I had several orders (from -4 to 1) all added together, but after the addition of 3 orders it began rendering black. I’m thinking it’s due to the heavy number of operations, but maybe it was the way I had constructed the addition of the shaders.

Also, would you mind if I took everything you’ve done and see if I can optimise and/or possibly see if I can speed it up?

---

<div class="post-metadata">

**Author:** ![Secrop](https://blenderartists.org/user_avatar/blenderartists.org/secrop/32/20093_2.png) [@Secrop](https://blenderartists.org/u/Secrop)\
**Post date:** [September 15, 2014, 11:21am UTC](https://blenderartists.org/t/a-complex-approach-iridescence-in-cycles/613211/68 "2014-09-15T11:21:38Z")

</div>

I’m aware of the instabilities… Cycles sometimes refuses to recompile the shader when in the viewport. I didn’t experience problems in final renders though.  
And I think there’s a limit in how many BSDF’s a material can have… I think is around 32, at least for CPU rendering.

To optimize it… well, I did rebuild the shader in OSL… It’s not heavy, but still takes some time. There are some things that still need to be done there, as the results are not quite the same as the original shader. And also room for some optimizations.

But the best optimization would be to create a new integrator in Cycles, to sample mainly where the strong lights are, and then figure out which wavelenght to use. (or wait for the OSL integrators)

---

<div class="post-metadata">

**Author:** ![Microno](https://blenderartists.org/user_avatar/blenderartists.org/microno/32/22845_2.png) [@Microno](https://blenderartists.org/u/Microno)\
**Post date:** [September 15, 2014, 1:38pm UTC](https://blenderartists.org/t/a-complex-approach-iridescence-in-cycles/613211/69 "2014-09-15T13:38:04Z")

</div>

Of course, I agree with the whole new integrator thing, it would be great if someone could program it.

I did some optimising here, I don’t actually know how fast it renders since I’m stuck using a mobile i5 cpu. I did get it to run faster by taking certain computations that are used generally and allowing all the node groups access, I don’t really know how effective that is though.

---

<div class="post-metadata">

**Author:** ![Secrop](https://blenderartists.org/user_avatar/blenderartists.org/secrop/32/20093_2.png) [@Secrop](https://blenderartists.org/u/Secrop)\
**Post date:** [September 16, 2014, 8:44am UTC](https://blenderartists.org/t/a-complex-approach-iridescence-in-cycles/613211/70 "2014-09-16T08:44:26Z")

</div>

Nice 🙂  
I would like to see the changes…

In the meanwhile I decided to complete the OSL code, with the all the optimizations I could think of. It’s now working as expected, sampling only necessary orders, and with a complete range of wavelenghts.

```auto
/*
 * Diffraction Grating Reflection
 *
 * by Miguel Porces
 * 2014
 *
 * random generator by Brecht
 *
 */

#include "stdosl.h"

void rng_seed(output int rng, int seed)
{
    int chash = seed;
    if (chash == 0) chash = 1;
    rng = chash * 891694213;
}

float rng_uniform(output int rng)
{
    float res = rng / float(2137483647) * 0.5 + 0.5;
    rng *= 891694213;
    return res;
}

float randomInterval(float minval, float maxval,point ipt)
{
    int rng;
    float f=0;
    float delta=maxval-minval;
    f = fmod(cellnoise(ipt*12345.0), 1.0);
    rng_seed(rng, int(f * 2137483647));

    return delta*rng_uniform(rng)+minval;
}

void rotateVector(output vector v, vector axis, float angle)
{
    float sf=0, cf=0;
    sincos(angle, sf, cf);
    v=(normalize(cross(axis,v))*sf)+(v*cf);
}

shader Diffraction
(
color Color=1.0,
float Distance=1200,
float Roughness=0.0,
float Rotation=0.0,
normal Normal = N,
normal Tangent = normal(0.0,0.0,0.0),
output closure color BRDF=reflection(N)
)

{
    float Rg=clamp(Roughness,0,1);
    
    /* setup Tangent direction */
    normal Tg=Tangent;
    if (Tangent==normal(0.0,0.0,0.0))
    {
        normal Zaxis=normal(0.0,0.0,1.0);
        Zaxis = transform("object", "world", Zaxis);
        Tg=normalize(cross(Zaxis,Normal));
    }
    rotateVector(Tg, Normal, Rotation*M_2PI);
    
    /* setup loop */
    color cl;
    BRDF=0;
    
    vector rht=cross(I,Normal);
    float dtr=dot(Tg,rht);
    float sTheta=length(rht) * dtr;
    
    float wave=randomInterval(380, 780,P);
    float wldst=wave/Distance;

    int ordmin=int(floor(Distance * (-1+sTheta)/wave))-1;
    int ordmax=int(ceil(Distance * (1-sTheta)/wave));
 
    float orddif;
    
    orddif=abs(ordmax-ordmin-1);

    /* sample wavelenght */
    for(int order=ordmin; order&lt;=ordmax;order++){
        if(order!=0){
            /* calculate angle */
            float wfac=order*wldst+sTheta;
            float angle= asin(wfac);

            /* rotate normal */
            normal NN=Normal;
            rotateVector(NN, Tg, angle);

            cl=wavelength_color(wave)*(Color)/orddif;

            if(Rg==0.0)
            {
                BRDF += (cl * reflection(NN));
            } else {
                BRDF += (cl * microfacet_beckmann(NN,Rg));
            }
        }
    }
}

```

---

<div class="post-metadata">

**Author:** ![norvman](https://blenderartists.org/user_avatar/blenderartists.org/norvman/32/13306_2.png) [@norvman](https://blenderartists.org/u/norvman)\
**Post date:** [September 26, 2014, 5:58pm UTC](https://blenderartists.org/t/a-complex-approach-iridescence-in-cycles/613211/71 "2014-09-26T17:58:27Z")

</div>

Nice thread… giving it a bump… until I can absorb all the above information…

---

<div class="post-metadata">

**Author:** ![Secrop](https://blenderartists.org/user_avatar/blenderartists.org/secrop/32/20093_2.png) [@Secrop](https://blenderartists.org/u/Secrop)\
**Post date:** [September 26, 2014, 7:30pm UTC](https://blenderartists.org/t/a-complex-approach-iridescence-in-cycles/613211/72 "2014-09-26T19:30:01Z")

</div>

🙂 Not dead…Though the diffraction grating works good, I still would like to do another physically based shader for something like [this](http://www.blenderartists.org/forum/showthread.php?254314-Cryptocephalus) kind of iridescence also. I’m just reading about it, but there’s not much to read, and most of it is hard to find. :spin:

In the meanwhile, feel free to post here any of your questions, doubts, experiments, opinions, sugestions… whatever! 😉

---

<div class="post-metadata">

**Author:** ![fluxcapacitance](https://blenderartists.org/user_avatar/blenderartists.org/fluxcapacitance/32/26939_2.png) [@fluxcapacitance](https://blenderartists.org/u/fluxcapacitance)\
**Post date:** [September 27, 2014, 6:33pm UTC](https://blenderartists.org/t/a-complex-approach-iridescence-in-cycles/613211/73 "2014-09-27T18:33:08Z")

</div>

Fascinating thread. I really enjoyed the science behind it.

---

<div class="post-metadata">

**Author:** ![Microno](https://blenderartists.org/user_avatar/blenderartists.org/microno/32/22845_2.png) [@Microno](https://blenderartists.org/u/Microno)\
**Post date:** [October 6, 2014, 4:24pm UTC](https://blenderartists.org/t/a-complex-approach-iridescence-in-cycles/613211/74 "2014-10-06T16:24:08Z")

</div>

Having gotten access to my desktop temporarily I’ve done the following tests. I created my own variant of the diffraction grating node group. So far, I would say yours is super-fast compared to anything I can conjure up by at least 1.5x which is pretty incredible. I got to hand it to you, it’s beautiful.

Now these are the renders in order that I’ve gotten which I thought would be useful to see side-by-side:

Anisotropic based (Slowest by a factor of 4):

 ![](https://blenderartists.org/uploads/default/original/4X/0/8/6/0863aa3fc21f9e3960560430d4476f10cc1fed51.jpg)  

Glossy based (Slower by a factor of 1.5):

 ![](https://blenderartists.org/uploads/default/original/4X/b/0/9/b09112f1c369a464413e573ae82548e8d285f623.jpg)  

Yours aka the fastest setup:

 ![](https://blenderartists.org/uploads/default/original/4X/c/8/f/c8f03b008db2653a291634757ee4b6c8f62d4d61.jpg)  

There has got to be someone who can hard-code your node group into cycles because that would be beyond incredible. 😃

---

<div class="post-metadata">

**Author:** ![Secrop](https://blenderartists.org/user_avatar/blenderartists.org/secrop/32/20093_2.png) [@Secrop](https://blenderartists.org/u/Secrop)\
**Post date:** [October 7, 2014, 8:55am UTC](https://blenderartists.org/t/a-complex-approach-iridescence-in-cycles/613211/75 "2014-10-07T08:55:56Z")

</div>

Your Glossy approach gives results more similar to the OSL shader. At least the color range is a bit bigger than the results from my setup.

As for the anisotropic shader, I confess that I’d tried it before, in previous tests, but didn’t like the results. Also because is a bit harder to control.

I’m now experimenting replicating the logic of the OSL into a new setup, this time avoiding having so many instances of the same nodegroups, and avoiding also the instabilities when updating/compiling.  
My main problem was allways the random values, and for all the tests I’ve done, it turns out that the brick texture is the only node to give random values uniformally distributed from 0 to 1. Even the cell noise, gives something concentrated around 0.5.

It’s kind of sad, to use such a texture just to get random values for each sample… But at least it will work with GPUs.

---

<div class="post-metadata">

**Author:** ![Microno](https://blenderartists.org/user_avatar/blenderartists.org/microno/32/22845_2.png) [@Microno](https://blenderartists.org/u/Microno)\
**Post date:** [December 31, 2014, 6:32pm UTC](https://blenderartists.org/t/a-complex-approach-iridescence-in-cycles/613211/76 "2014-12-31T18:32:45Z")

</div>

Well I did some render tests using a Brick Texture based setup of the diffraction shader and the end result was interesting to say the least. First and foremost, here are the results rendered with a GTX 580 @ 1000 samples:

“Glossy - Brick” Variant of the Shader - Rendered in 2:57.29:

 ![](https://blenderartists.org/uploads/default/original/4X/2/7/a/27a4438bbb70d60489f8664adcd5d42072f12378.jpg)  

“Secrop” variant of the Shader - Rendered in 7:50.65:

 ![](https://blenderartists.org/uploads/default/original/4X/7/1/e/71eaf141531a149c1ec3ae4abf5d10f8578a014f.jpg)  

Yours looks significantly better, but mine does show that it is possible with the brick texture as you suggested. Great catch, now the purpose is to improve the visual quality.

---

<div class="post-metadata">

**Author:** ![Secrop](https://blenderartists.org/user_avatar/blenderartists.org/secrop/32/20093_2.png) [@Secrop](https://blenderartists.org/u/Secrop)\
**Post date:** [January 4, 2015, 10:17am UTC](https://blenderartists.org/t/a-complex-approach-iridescence-in-cycles/613211/77 "2015-01-04T10:17:57Z")

</div>

Hi Microno,  
I’ve made a setup that should work ok with GPU, but sadly I don’t have any GPU capable card. ☹

Can you test this setup to see if it works ok?  
[DifractionGratingGPU.blend](https://blenderartists.org/uploads/default/original/4X/0/e/d/0ede49bd6608a1c8485b3a70a4d668862e81840c.blend) (445 KB)

edited:updated the blend so the shader is now a group for better usage 😉

---

<div class="post-metadata">

**Author:** ![Microno](https://blenderartists.org/user_avatar/blenderartists.org/microno/32/22845_2.png) [@Microno](https://blenderartists.org/u/Microno)\
**Post date:** [January 4, 2015, 3:57pm UTC](https://blenderartists.org/t/a-complex-approach-iridescence-in-cycles/613211/78 "2015-01-04T15:57:57Z")

</div>

> [@Secrop](#):
>
> Hi Microno,  
> I’ve made a setup that should work ok with GPU, but sadly I don’t have any GPU capable card. ☹
> 
> Can you test this setup to see if it works ok?  
> [ATTACH]353558[/ATTACH]
> 
> edited:updated the blend so the shader is now a group for better usage 😉

I’ve rendered with your node group and with mine for comparison purposes on the plane fabric mesh without the textures. These are the results:

Yours - 7 minutes 49 seconds @ 1000 samples:

 ![](https://blenderartists.org/uploads/default/original/4X/a/7/c/a7c291c961654d838c34e7ebd206011f18469d88.jpg)  

Mine - 8 minutes @ 1000 samples:

 ![](https://blenderartists.org/uploads/default/original/4X/5/2/5/525a484ca3658d7ba35300d7ed20eeba3d705af1.jpg)

---

<div class="post-metadata">

**Author:** ![CarlG](https://blenderartists.org/letter_avatar_proxy/v4/letter/c/aca169/32.png) [@CarlG](https://blenderartists.org/u/CarlG)\
**Post date:** [August 2, 2015, 12:21am UTC](https://blenderartists.org/t/a-complex-approach-iridescence-in-cycles/613211/79 "2015-08-02T00:21:33Z")

</div>

I didn’t detail read any of the blends/materials, but I got the impression that none of this is based on light position? I read hard coded and so on a couple of places. Is this useful in your ventures?

 ![](https://blenderartists.org/uploads/default/original/4X/b/4/5/b451b3662b656e507047be83f4a09bfd5afde63b.jpg)  
  
The red node is the key to the trick, where you just select the light. Obviously you would have to add the effect to work on all lights you want it to consider (may get ridiculous in complex lit scenes), rather than on a material basis as it should be (but impossible due lacking closure, if I got all that correctly :)).

I’m not good with maths, but I think the diffuse shading is about right, with some crazy ramp going on. If you mute the blue node, you cancel the absolute of the dot, and allows shading effects also on the backside (could be valid for soap bubbles and so on). You could even link to an empty in the general direction of a HDRI sunlight, but do not do the inverse square then 🙂 With light position obtained from scene data, one could also easily, for those with better math skills than me, do half angle based stuff like phong (reflections).

Don’t mind what’s going on in the right top section, that’s just me having fun 😃 But I think you see the idea.

I don’t know if this is useful at all. Thought I should just mention it.

---

<div class="post-metadata">

**Author:** ![Secrop](https://blenderartists.org/user_avatar/blenderartists.org/secrop/32/20093_2.png) [@Secrop](https://blenderartists.org/u/Secrop)\
**Post date:** [August 2, 2015, 2:54am UTC](https://blenderartists.org/t/a-complex-approach-iridescence-in-cycles/613211/80 "2015-08-02T02:54:17Z")

</div>

I’m not able to test it right now, but the idea should work. There are a few points I quite don’t understand, but being able now to retrieve other objects coordinates can be very usefull. 🙂

The main question is why is the spectrum color ramp connected to the tangent of the anisotropic node? Don’t know wich effect it will give, but it makes no sense to me giving colors to an input that requires a direction…

The second point is just a sugestion: in your ‘VECTOR DISTANCE’ frame, you can simply use a vector subtraction with the positions, dot product the result with itself, and square root the output of the dot product (because dot(V,V)=||V||²). No need to have so many nodes when just 3 are enough 😉

And yes, the big downfall of this approach is the need to add every lamp in the scene, and this doesn’t even take in acount if it’s a sun or an area light. Luckly, in the majority of the situations there’s only one or two lights that visibly contribute to these light phenomena.

I’ll try to look to the phong formula to see how could one implement it with nodes. No idea if it will work, but looks like a funny experiment 😃

[Previous page](https://blenderartists.org/t/a-complex-approach-iridescence-in-cycles/613211.md?page=3)

[Next page](https://blenderartists.org/t/a-complex-approach-iridescence-in-cycles/613211.md?page=5)
