반응형

Introduction

We wanted to have the enemies in Timefight Zone sort of “burn” into existence when they spawn, and burn away when they die. We began to look into how to do this, and quickly came across something called a dissolve shader.

We're going to assume you have a basic knowledge of Unity shaders for this tutorial, if you don’t, there are lots of excellent tutorials that can familiarize you with the basics just one Google search away.


Basic Dissolve Shader

So thanks to the Unity wiki page I linked above, we have a dissolve shader to work with. It looks like this:

  Shader "Dissolving" {
    Properties {
      _MainTex ("Texture (RGB)", 2D) = "white" {}
      _SliceGuide ("Slice Guide (RGB)", 2D) = "white" {}
      _SliceAmount ("Slice Amount", Range(0.0, 1.0)) = 0.5
    }
    SubShader {
      Tags { "RenderType" = "Opaque" }
      Cull Off
      CGPROGRAM
      //if you're not planning on using shadows, remove "addshadow" for better performance
      #pragma surface surf Lambert addshadow
      struct Input {
          float2 uv_MainTex;
          float2 uv_SliceGuide;
          float _SliceAmount;
      };
      sampler2D _MainTex;
      sampler2D _SliceGuide;
      float _SliceAmount;
      void surf (Input IN, inout SurfaceOutput o) {
          clip(tex2D (_SliceGuide, IN.uv_SliceGuide).rgb - _SliceAmount);
          o.Albedo = tex2D (_MainTex, IN.uv_MainTex).rgb;
      }
      ENDCG
    } 
    Fallback "Diffuse"
  }

This shader takes a value (_SliceAmount) and a texture (_SliceGuide), and uses a function called clip() to hide any pixels on _SliceGuide who's brightness is less than _SliceAmount.

Below is a gif showing the basic dissolve shader in action. I mapped the same texture to _SliceGuideand _MainTex to better illustrate how the brightness of the pixel in _SliceGuide determines at which point a pixel is hidden.

 

 

https://thumbs.gfycat.com/RegalWanIrishsetter-mobile.mp4

불러오는 중입니다...

 

Note how the darkest pixels are the first to dissolve when dissolving, and the last to re-appear when un-dissolving.

Adding Burnt Edges

Now for the interesting part, adding the burn effect around the areas that are about to dissolve. If you just want the code, here it is:

    Shader "Dissolving" {
    Properties {
      _MainTex ("Texture (RGB)", 2D) = "white" {}
      _SliceGuide ("Slice Guide (RGB)", 2D) = "white" {}
      _SliceAmount ("Slice Amount", Range(0.0, 1.0)) = 0.5


 _BurnSize ("Burn Size", Range(0.0, 1.0)) = 0.15
 _BurnRamp ("Burn Ramp (RGB)", 2D) = "white" {}
    }
    SubShader {
      Tags { "RenderType" = "Opaque" }
      Cull Off
      CGPROGRAM
      //if you're not planning on using shadows, remove "addshadow" for better performance
      #pragma surface surf Lambert addshadow
      struct Input {
          float2 uv_MainTex;
          float2 uv_SliceGuide;
          float _SliceAmount;
      };


      sampler2D _MainTex;
      sampler2D _SliceGuide;
      float _SliceAmount;
 sampler2D _BurnRamp;
 float _BurnSize;


      void surf (Input IN, inout SurfaceOutput o) {
          clip(tex2D (_SliceGuide, IN.uv_SliceGuide).rgb - _SliceAmount);
          o.Albedo = tex2D (_MainTex, IN.uv_MainTex).rgb;
 
 half test = tex2D (_SliceGuide, IN.uv_MainTex).rgb - _SliceAmount;
 if(test < _BurnSize && _SliceAmount > 0 && _SliceAmount < 1){
    o.Emission = tex2D(_BurnRamp, float2(test *(1/_BurnSize), 0));
 o.Albedo *= o.Emission;
 }
      }
      ENDCG
    } 
    Fallback "Diffuse"
  }


We have added a new value (_BurnSize), and a new texture (_BurnRamp). To recap, we are hiding parts of the model using clip(), which hides the pixel if the value passed into it is less than 0. We subtract_SliceAmount from the RGB value (brightness) of _SliceGuide, so if _SliceAmount is greater than the brightness of the given pixel of _SliceGuide, the pixel is hidden.

To add the burn effect, we again subtract _SliceAmount from the RGB value (brightness) of _SliceGuide, and this time if the resulting value is less than _BurnSize, we choose a pixel on _BurnRamp to color the pixel. This means that we can change _BurnSize to modify how far out from the dissolved area gets a burn effect. The higher _BurnSize is, the farther the burn effect extends.


The pixel on _BurnRamp is chosen based on how far past _BurnSize test is. At 0 you get the far left pixel, and as the value approaches _BurnSize you move farther to the right side of the image. So you're generally going to want to have the bright ember colors on the left, and the dimmer charred colors on the right on your _BurnRamp.

Below is a gif of _BurnSize being modified in real time to illustrate it's effect.

 

https://thumbs.gfycat.com/WarlikeKaleidoscopicAplomadofalcon-mobile.mp4

 

 

 

 

Note how increasing _BurnSize does not effect the areas that are dissolved, it merely changes how large the burned area extends.

That's about it. It's a relatively simple effect to achieve, but surprisingly hard to find concrete information on. Hopefully this post will help a few people add a cool effect to their game.

Notes

  • The way we are coloring the burnt edges is by setting the emission (o.Emission) to the color of the pixel we chose off _BurnRamp, as well as multiplying the base color (o.Albedo). This will cause the burnt areas to glow in the dark. If you want to achieve an effect with this shader where the edges shouldn't glow, you'll have to change o.Emission, to o.Albedo, and remove the next line down where we multiply o.Albedo by o.Emission.
  • Our _BurnRamp is designed for a cartoony art style. If your game has a more realistic art style, you may want a smoother gradient.
  • Feel free to use this shader and _BurnRamp in your game. We made this tutorial because we couldn't find any specific information on this type of shader outside paid Unity assets. Hopefully this has been informative, but even if it made absolutely no sense, we'd like for more people to be able to achieve this effect in their games, so just steal our version. :)

 

https://thumbs.gfycat.com/AnimatedUnderstatedJunebug-mobile.mp4

불러오는 중입니다...

https://thumbs.gfycat.com/WellinformedMadAlaskajingle-mobile.mp4

 

 

ref : http://www.codeavarice.com/dev-blog/tutorial-burning-edges-dissolve-shader-in-unity

반응형

+ Recent posts