Pupil Dilation in Material Editor

This is something that’s been driving me nuts. I found a method that produces a somewhat pleasing result, but it’s totally inaccurate. It just involves multiplying a spherical gradient by a texture coordinate, and feeding that into the UVs of an eye texture. You can see what it looks like at minimum and maximum possible dilation, but the third image shows what it does to a grid texture. It seems to be wrapping the UVs around in a circle, and that’s just totally wrong. If anyone has a solution to fix this, I’d really appreciate it!

Also, I’d like to feed this into a parallax displacement (bump offset) node to make the iris appear inset. Any suggestions on that would be great. Thank you!




I don’t know what your application is for this but for me- this would be way easier to do with geo.

Map a sphere and scale the iris- morph between the two geo’s as an animation.


This gets rid of the distortion issue you are having but you still need to work on it.

Yes! Thank you so much, this helped a lot! I managed to get a nice working eye shader with it! I just fed the results into a bump offset UVs, used a separate gradient as a heightmap, and what do you know? It works! I will mess with it some more to see if I can fix a few issues here and there, and post the results. It looks amazing!

The results of scaling the iris from the material editor are beneficial for a few reasons: 1, the result is always going to be perfectly clean and smooth because it is not bound to the underlying geometry, doesn’t change it, and keeps the original iris texture completely intact. 2, it is easily editable and transferable to other meshes because, well, it’s just a material! You can replace the iris texture, keep the same material, and basically do anything you want with it. All it takes to change the pupil size is a single parameter (and with some tweaking it can also support crazy iris shapes as well). And 3, you can use techniques like bump offset (parallax) to curve the texture of the iris inward, with the reflections taking the shape of the bulge of the cornea, and keep everything on one mesh with one master material that just does everything perfectly.

Cool! It will be great if you share the material setup of the end result with all of us. :slight_smile:

Here is a .gif of the dilation, the finished eye, and the material breakdown:




I’m using a 512 free Iris texture and a 512 normal map to make the reflections/highlights appear to bulge out (might be easier to just bulge it out with the model and get rid of the normal map all together :expressionless: Might change that later). Everything else is procedurally generated, so it works fine. The only drawback is you can’t dilate the Pupil too large or too narrow because it will start distorting the image, and clamping doesn’t seem to help. Parallax also has the tendency to screw it up. It looks brilliant with subsurface scattering too, and not at all like glossy plastic!

This still looks like there is a lot of distortion going on. I’d rather use a radial gradient texture instead of generating the gradients. This makes the material less complex and saves instructions, you can also use the same texture for a parallax effect or SSS.
With the source texture having a pretty small pupil and the material primarily performing a pupil widening you should get rid of major distortions.

That’s my material setup with a radial gradient stored in the diffuse textures alpha channel:

Which distortion are you seeing? Is it the parallax? I have a lot of parallaxing going on, so there will always be some distortion with that. Also, If I do make a texture, I would not use the alpha channel. Alpha channels are uncompressed, and all you need is a soft gradient for the dilation and displacement map, and a sharp circle to define the SSS mask.

Also, if I do use a texture, I wouldn’t use the alpha channel: they’re never compressed, and cost just as much as a standard 3-channel texture of the same size. Since the parallax and dilation need a soft gradient and the SSS mask a sharp circle, I’d put both those masks in two channels of a brand new texture, and maybe put the iris texture in a third and just multiply it by a color. How’s that for optimization?

I’ll make a few versions of this shader and see which one is more optimized without ruining the quality.

You can also generate a sharp circular mask from the soft version, this is still less instructions than the material based method.
Personally I find it easier to create the soft mask in an image editor to exactly match the diffuse texture. A 512²px DXT1 map is only 170KB btw.

Each frame of your gif is showing heavy texture distortions, this is basically just stretched lines towards the center: http://abload.de/img/pupildilation_02rwu5e.jpg

Looking Good (pun intended). I’ve always desired better eyeballs with my Characters. Eyeballs that move around vs the stiff stare version. Pupil dilation is even a greater detail of realism. I’m considering an approach using animated iris flipbook textures to deal with oddly shaped pupils (ie: insect, creature, alien). Its all theory at this point, your procedural works well for human eyeballs.

The numbers are a bit more difficult to fiddle with in the texture masked version of this shader, but it would be 10% cheaper to use at only 66 instructions (release stats). I’ll see if I can get a texture masked version up here tomorrow. I’m not sure if the proceduraly generated method is more expensive per-pixel or per-object, but I’m guessing it’s per pixel, in which case the shader is not very heavy at all and pretty much gives you a perfect eye.

I also tried using the texture version of this shader to work on cat eyes, but the distortion is too great, and I’m having trouble mimicking the proper shape dilation. If I can find a way to clamp distortion at extreme values, then I can dilate the pupil as large as I want without the distortion warping/wrapping the texture around. I tried just clamping the values, but it just doesn’t work that way.

EDIT: Apparently, I was animating the normal map with the iris! Whoops! I implemented a static switch parameter to switch between the procedural and texture methods, and it seems to only save 3 instructions. If this is the case, then there’s no point in wasting more time on a texture-based shader because surely the memory and quality cost (and time lost trying to make it work) for only saving 3 instructions is not worth it.

Is it not better (more easy), to use a shape key aka morph key for the pupil?

I suppose you could do it that way, but it really doesn’t take much material instructions to do this at all, and the result is much cleaner.

Wow, this thread is a year old! Happy birthday!