Search Unity

How to write a glow shader for lightsaber / aura effect?

Discussion in 'Shaders' started by Rowlan, Apr 1, 2017.

  1. Rowlan

    Rowlan

    Joined:
    Aug 4, 2016
    Posts:
    4,294
    How do you write a shader for a lightsaber / aura like effect? The result should be like this, created using MKGlow:

    cylinder.png

    It's a

    * simple cylinder
    * a mkglow emission shader is applied, outside of the cylinder is a glowing effect
    * applied on a per object basis
    * however you rotate it, the object itself is white, the outline is "glowing"
    * the effect starts outside of the object and fades out

    I've seen and tried various examples of a rim shader, I also tried atmosphere shaders, but none seemed to achieve that effect. I only need to have this single effect, so using the entire stack of (the awesome) MKGlow is a bit of a performance overkill.

    Thank you very much for the help!
     
  2. Teravisor

    Teravisor

    Joined:
    Dec 29, 2014
    Posts:
    654
  3. Rowlan

    Rowlan

    Joined:
    Aug 4, 2016
    Posts:
    4,294
  4. Teravisor

    Teravisor

    Joined:
    Dec 29, 2014
    Posts:
    654
    First, you got something wrong. Glowth usually consists of two parts: a solid cylinder and surrounding cylinder with falloff. You have not created a solid cylinder inside and set falloff too strong. But I agree that it's hard to configure properly and requires some tweaking of shader, proper normals, etc.

    Your best bet would be rendering cylinder onto texture, blurring it and then rendering it on scene again. Outline is done, for example like there: http://xroft666.blogspot.ru/2015/07/glow-highlighting-in-unity.html and then you apply it to solid cylinder. You would need to add Z-write checks so not to write outline over other objects though.

    Another approach would be some math in shader (would work only for simple shapes): you can pass 2 points near edges of cylinder from vertex shader (for example local position+(0,1,0) would be one point in local coordinates, then it's rotated to viewport coordinates as per usual unity_ObjectToWorld matrix) and then in fragment shader you would calculate distance from current fragment to line between them (excluding everything above those points) and setting alpha based on that value.

    Or you can store previous vertex coordinate (before modifying it in vertex shader) and in fragment shader you'd set alpha in inverse proportion to viewport distance between previous vertex coordinate and new one.

    If you don't want to program and tweak it working yourself, there are always assets: https://forum.unity3d.com/threads/highlighting-system-released.143043/
    If that highlight is applied to solid-color cylinder, that will produce needed effect.
     
    Last edited: Apr 1, 2017
    As_day and Rowlan like this.
  5. Rowlan

    Rowlan

    Joined:
    Aug 4, 2016
    Posts:
    4,294
  6. aubergine

    aubergine

    Joined:
    Sep 12, 2009
    Posts:
    2,880
  7. Rowlan

    Rowlan

    Joined:
    Aug 4, 2016
    Posts:
    4,294
  8. aubergine

    aubergine

    Joined:
    Sep 12, 2009
    Posts:
    2,880
    Actually it is, think of it like a paid tutorial.
     
    astracat111 and Oshigawa like this.
  9. bgolus

    bgolus

    Joined:
    Dec 7, 2012
    Posts:
    12,352
    Here's the short version of what you're looking for:
    MKGlow and similar effects are usually what are referred to as "bloom post process effects". These work by rendering the scene a second time with only emissive colors (like MK Glow) or copying the original scene output and adjusting the contrast to accentuate bright areas. Then you make a blurred version of that texture, which is either going to be expensive, or kind of crappy looking, but usually a mix of both. Then you add that blurred result in top of the scene.

    But that's the only guaranteed way to get nice, even sized glows on any object.

    So the alternatives you've been trying, like a front culled fresnel or volume fog shaders, only really work well on nicely rounded shapes ... specifically a perfect sphere. Anything else and you'll get situations where the effect fails. There's just not a good way to figure out how "far away" you are from the original "edge" with out a blur or sampling the screen multiple times (which is what a blur is).

    Now there are other alternatives, some very cheap, but all come with a "gotcha" of some kind.

    Option 1: Use a "3d sprite", usually a single direction & camera oriented plane for the body of something, and maybe one or two cross planes and/or camera facing circular glows to "fill in" when looking at the object edge on. Works surprisingly well, and I guarantee you 90% of the glowing streaks you've seen in major games that look like they have some kind of volume were done like this.

    Option 2: Use "volumetric lines." This is basically just an more elegant implementation of option 1. See: https://www.assetstore.unity3d.com/en/#!/content/29160

    Option 3: Shells. Sometimes you can get something vaguely soft, but not very consistent with fresnel style glows, but if you layer 3 or more of these on top of each other at different sizes (and maybe different opacities) you can get something that looks acceptable, or even almost as good as a real bloom, especially for smaller glows. This can be expensive with higher poly geometry, but you can sometimes get away with just a cheap additive solid color shader for this. Some people like doing this with multiple passes, but it's better to do it with a single glow mesh that includes all of the shells if possible, and remember to keep all the edges soft so you can push the corners out via the vertex normal! Using a mesh with rounded edges helps the look too.

    Option 4: Fake it with a ton of particles. It's kind of the naive version of option 1, but still fairly effective. Can easily become more expensive than bloom if you go overboard, and hard to control to get a consistent result.

    Last option I can think of would be something like the Doom 3 glow / hand drawn outline effect, but this isn't something you can easily do with just a shader, especially since Unity doesn't supply adjacency information to geometry shaders. The short explination is on the CPU (or GPU using a compute shader) calculate the edges of the mesh and generate "fin" geometry. Search for "shells and fins" and you'll get a ton of examples of this using geometry shaders & adjacency data, which Unity can't do, but which you could recreate on the CPU.
     
  10. jRocket

    jRocket

    Joined:
    Jul 12, 2012
    Posts:
    700
    That's a pretty good explanation of the effects. For my project, I went with the post-process glow route, using command buffers to make an RT of everything I'm going to blur and then using unity's downsampled fastblur shader to do the blurring and then cutting out the original RT. The effect is pretty nice, but one downside I noticed- overlapping glow/outlines will not look correct because it doesn't take depth into account. I suppose one could do the post process effect for each glowing object, but that would quickly get way more expensive with multiple glowing objects. Is there an easier way?
     
  11. Rowlan

    Rowlan

    Joined:
    Aug 4, 2016
    Posts:
    4,294
    I tried that as well. Also with the link that @Teravisor posted. Unfortunately it handles only 1 single color. You can't have multiple objects with different colors. It does handle depth though, so you might want to take a look at it.

    I spent 3 days now, including studying several tutorials. My conclusion: A lot of people want it. Especially for VR this comes in very handy. Unreal has it out of the box. And it's sad that Unity doesn't have this available except if you buy some overloaded asset on the asset store. I wouldn't mind buying it, but I'd like to make my application open source, so that's out of the question.
     
    Last edited: Apr 8, 2017
  12. Teravisor

    Teravisor

    Joined:
    Dec 29, 2014
    Posts:
    654
    I can't see how that can be true when there's _Color variable in shader you can change. Render first object with one color, change it, render next one... It would be horrible for performance if there will be a lot of them though.
     
  13. Rowlan

    Rowlan

    Joined:
    Aug 4, 2016
    Posts:
    4,294
    It seems to render all objects at once with 1 single material. At least from what I've found out. Anyway, the solution seems to be to put the glow objects on a dedicated layer, render all objects of that layer into a temporary camera, apply blur effect and blit that image back to the original camera. The only other solution I've found is to use a the command buffer. It's expensive either way. I also tried the new postprocessing stack with bloom. That one doesn't give the desired effect.
     
  14. Mauri

    Mauri

    Joined:
    Dec 9, 2010
    Posts:
    2,665
    No offense, but you always advertise your Assets in threads like these. The thread creator already own 'MK Glow', which does the same like your product and is even free...

    @Rowlan
    Could this help?
     
  15. aubergine

    aubergine

    Joined:
    Sep 12, 2009
    Posts:
    2,880
    So, whats wrong with advertising if it is a related product to the question? And what is wrong with advertising a different product that does alittle bit more than what is in your hand?
    From your point of view, and i am just making a guess here from what you said, its wrong because it is a paid product?
    Isnt it nice just to have an alternative?

    Just as a side note; i dont see the question or the thread itself mentioning that the answer should be only a free solution, so i am allowed to advertise, and you are allowed not to be allergic to advertisements and just ignore if you must.
     
    minus4games likes this.
  16. Rowlan

    Rowlan

    Joined:
    Aug 4, 2016
    Posts:
    4,294
    Thank you @Mauri. I've already dug through the code of that example. It has problems with overlapping. And it uses also a temporary camera for the effect, like MKGlow. The other example in that uses a command buffer. Same problem with overlapping. You can see the glow through objects in front of it.

    @aubergine I want to give what I create away for free as open source. When you say I buy your product and I should see it as a paid tutorial I'm still not allowed to give it away for free. So although appreciated, I can't do that.
     
    Last edited: Apr 10, 2017