Code Avarice
  • Home
  • Dev Blog
  • Games
    • ParaSHOTical ARKtiviBeatings
    • Season's Beatings
    • Arkshot
    • Paranautical Activity
  • Mailing List
  • Contact
  • Discord

Tutorial - Burning Edges Dissolve Shader in Unity

9/11/2015

 

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 _SliceGuide and _MainTex to better illustrate how the brightness of the pixel in _SliceGuide determines at which point a pixel is hidden.
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.

Our _BurnRamp looks like this: 
Picture

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.
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. :)


Here's how the final effect looks in Timefight Zone:

Timefight Zone Pre-Alpha Preview #4 - Complete Visual Overhaul

9/10/2015

 
We're finally back with another Timefight Zone preview video! We got tangled up in some non-Timefight related business for a while, so we didn't have anything to show, but a few weeks ago we dove back in and finally got rid of those placeholder visuals.
Expect another video pretty soon showing off some new and interesting mechanics.

    Archives

    February 2023
    January 2018
    November 2017
    October 2017
    May 2016
    March 2016
    September 2015
    March 2015
    January 2015
    November 2014

    Categories

    All

    RSS Feed