📜 ⬆️ ⬇️

Blast Wave in Unity3D (displacement shader)

Hello everyone, I am writing a small 2D game and in parallel I would like to talk about the implementation of some things in Unity3D.
Programming graphics in itself is a very interesting activity with an unlimited number of variations of the result. In this article I will describe the implementation of the distortion of space from the blast wave.


Usually, any distortions in the x, y planes are made using a normal map, which stores the amount of distortion in the color component. Through this, water surface, blast waves, hot air, etc. are realized.

In the game that I write a lot of shots, in this regard, the number of distortions is also large:


')
One of the options: a mathematical model of distortion. We directly in the shader consider the formulas distortion at a particular point. The disadvantage of this approach is excessive load. After all, all these miscalculations will be made for each pixel, so in programming graphics, textures are often used, within which the mathematical values ​​of something are calculated. In the case of the blast wave, I took this texture:


Create a new shader in Unity:

Shader "Hidden/DisplacementEffect" { Properties { _MainTex ("Base (RGB)", 2D) = "white" {} _DisplacementTex ("Displacement rt", 2D) = "white" {} _DisplacementPower ("Displacement power", Float) = 0.025 } SubShader { Pass { CGPROGRAM #pragma vertex vert_img #pragma fragment frag #include "UnityCG.cginc" uniform sampler2D _MainTex; uniform sampler2D _DisplacementTex; uniform float _DisplacementPower; float4 frag(v2f_img i) : COLOR { fixed4 displacementVector = tex2D(_DisplacementTex, i.uv); fixed2 uv_distorted = i.uv + _DisplacementPower * displacementVector.xy; return tex2D(_MainTex, uv_distorted); } ENDCG } } } 


There are two parameters to the input: _DisplacementTex and _DisplacementPower . The first is our distortion texture, and the second is the strength of the distortion.

We get the distortion force in the current pixel:
 float4 displacementVector = tex2D(_DisplacementTex, i.uvgrab); 


Shift the uv-coordinates of the current pixel with the specified force and direction obtained above.
 float2 uv_distorted = i.uvgrab + _DisplacementPower * displacementVector.xy; return tex2D(_MainTex, uv_distorted); 


In other words, each pixel in the displacement texture stores in vector color by which we must move the pixel of the picture.

The next problem: how to extend the code to an infinite number of explosions. To the rescue comes a render to the texture. Create a new camera that sees only a specific layer (layer), which I called displacements.

At the moment of the explosion, you create on the scene at the point of the explosion a sprite displacement of the texture, which is placed on the displacements layer. This layer sees only its separate camera, which renders to a different texture.


On the screenshot above, the Camera Preview shows what the camera “sees” the displacements layer, and below it is the game result, where the displacements layer does not fall, but the result of the shader processing is already visible.

In the shader, which we have already written above, the following texture will get into the _DisplacementTex parameter (for multiple shots):


In fact, the black color of the texture is zero, in this place the colors of the resulting texture do not shift. In the same place where the color distortion texture is traced. As a result, any number of explosions and distortions are drawn in exactly two passes:

If you are interested in this topic, I will continue to describe the effects that you see in the photo:

- Old TV, RGB Shift and other postprocess effects
- Gravitational distortion (physical part and visual)
- Unique background pattern using Wang Tiles
- 2D shadows from physical objects

Source: https://habr.com/ru/post/282604/


All Articles