in shader, tutorial, Unity3D

3D Printer Shader Effect – Part 2

Share Button

This is the second part of the tutorial that will recreate the 3D printer effect seen in games such as Astroneer and Planetary Annihilation.


This is a two part tutorials:

A link to download the Unity package (code, shader and 3D models) is provided at the end of the tutorial.


The first part of this tutorial shown how to render part of an object with an unlit lighting model (picture below). There are few other things that are yet to be achieved to fully recreate the beautiful style seen in Astroneer.


Cutting the Geometry

The easiest effect to add to our shader is to stop drawing the upper part of the geometry. The keyword discard can be used to arbitrarily prevent a pixel from being drawn in a shader. We can use it to ensure that only a rim around the top part out model is drawn:

It is important to remember that this potentially leaves “holes” in out geometry. You should disable face culling, so that even the back of an object can be fully drawn.


Now, the most striking thing is that the object looks hollow. This is not just an impression: all 3D models are actually hollow. What we want to convey, however, is the illusion that the object is actually solid. This can be done easily by colouring the inside of an object with the same unlit shader. The object is still hollow, but it will be perceived as full.

To achieve this, we simply colour the triangles that are facing back to the camera. If you are unfamiliar with vector algebra, this might seen a rather complex condition to achieve. In reality, it can be done quite easily using the dot product. The dot product between two vectors indicates how “aligned” they are. Which is directly related with their angle. When the dot product between two vectors is negative, it means there is more than 90 degrees of separation between them. We can test for our original condition by taking the dot product between the view direction of the camera ( viewDir in a surface shader) and the normal of a triangle. If it is negative, it means that the triangle is not facing the camera. Hence, we are seeing his “back” side; we can then render it with a solid colour.

The result is shown in the following pictures. On the left, the “back geometry” is rendered in red. When we use the same colour for the top part of the object, it doesn’t look hollow anymore.



Wobbly Effect

pa2If you have played Planetary Annihilation, you know that the 3D printer shader it uses has a gentle wobbly effect. We can add this as well, by adding some noise to the world position of the pixels we are drawing. This can be achieved either with a noise texture, or by using some continuous, periodic function. In the piece of code below, I have use a sinusoid function with some arbitrary parameters.

These parameters have been tweaked manually until I obtained a pleasant wobbly effect.



The final part of this effect is the animation. This is achieved simply by changing the _ConstructY parameter of the material. The shader will take care of the rest. You can control the speed of the effect either via code, or using an animation curve. The former has the advantage that you can fully customise its speed.


As a final note, the model used in this picture looks hollow for few seconds because the bottom part of the boosters is not closed. Hence, it is actually hollow.


This concludes the 3D printer shader effect.

Patreon You can download the Unity project for this tutorial on Patreon.

A big thanks goes to the guys at System Era, and in particular to Jacob Liechty.

Support this blog! ♥

In the past two years I've been dedicating more and more of my time to the creation of quality tutorials, mainly about game development and machine learning. If you think these posts have either helped or inspired you, please consider supporting this blog.

PatreonBecome a Patron Oo4th_patreon_name
PaypalDonate on PayPal
Twitter_logoFollow on Twitter

Don't miss the next tutorial!

There's a new post every Wednesday: leave your email to be notified!

Write a Comment



    • Hey Julian!
      I suspect this is due to floating point errors with the dot product! Have you tried using a small margin of error? Something like:

      if (dot(s.Normal, viewDir) < 0 + margin) If you play with the value, you might get rid of the red fringe. Let me know if that works! 🙂

      • This shader won’t work as expeccted even if the geometry was closed on the bottom, let alone overlapping geometry as in Julians example.

        The problem is that the re-interpreted backface is still using the original depth, so the Z-test is going to yield incorrect results.

        Fixing this requires to write to the depth buffer explicitly for the reinterpreted backfaces.

        • That it can’t work with overlapping geometry was clear from the beginning, sure no problem.

          I believe Ext3h might be right in the end but the margin solution Alan suggested does indeed solve the issue as you can animate it to a slightly negative value towards the end of the animation and bam looks fine. You even might get an even more interesting effect moving it to a slightly positive value at the start of the construction effect.

  1. Hi, the effect is amazing, thanks for the tutorial but am I missing something or _ConstructY has to Range from the world position of the bottom of the object to the top of it in order to color it ? So do we have to manually enter those values in the shader in order to make it work ? Thanks again for the amazing work !

  2. I would recommend using the VFace semantic if possible as using the per pixel interpolated normal will get you false positives.

    Secondly you’d be better off manipulating the albedo and emissive in the surf function rather than using a custom lighting function as it’ll continue to work in deferred, and won’t make the glowing areas brighter when using more than one light.

    Also the shader source for the PA shaders are all easy to access and look at, they’re just in a folder called shaders as text files. You can see all my horrible code and how many more layers of stuff I did for the PA shader. 🙂

    • HEY Ben! 🙂
      Glad you made you’ve found this post! 🙂
      This is a nice introduction to the build effect, but is far from being perfect (or even optimised!).

      I didn’t know the shaders in PA were “available”. I guess I know how I’ll spend my evening. 🙂

      Thank you very much for your comment. And please, let me know if you’re coming to London anytime soon. I’d be super happy to have a chat! 🙂

  3. Thanks for the tut, but I don’t know why you’re using world position instead of local. Local is way more flexible. Would have also been nice to have the full working shader available since it takes a bit of work to try to piece together all these puzzle pieces of code.

  4. Really awesome tutorial!! One question though.. How can I get rid of some weird shadows show up? And the overall shadow of the object as well… Thank you in advance!!