Unity shader-death Dissolution effect

Source: Internet
Author: User
Introduction
In the game, there are many ways to show the character's death effect when the character dies. The simplest and most brutal, play the death animation directly deleted or the direct y-axis gradually lowered, sank to the ground; a good death effect is the effect of today's study-death dissolution. The personal impression is more profound is the "biochemistry crisis 6" inside of Chris, inside of the dead corpse hanging off will have a similar death dissolution effect. However, "biochemistry crisis 6" This 3 a masterpiece effect is certainly not only a shader can make out, also cooperated with the particle to make the dissipation and the fire effect.
Bright General study shader children's shoes, will study this stuff .... After all, this effect is often used in grey. Today, I'm also going to look at the effect of death dissolution.
Basic Dissolution Effect
Dissolution, which is to let the model fade away. So, the simplest, the fragment shader operation of this pixel directly discard, this pixel disappears. And then, what we're going to do is let this dissolve part of the object disappear, another part exists, so, this time we need a mask to control, we sampled this mask, we can get this pixel point current mask value, Then use this mask value and we set a threshold value to compare, less than the threshold of the partial discard, greater than the part of the normal calculation. Finally, we will gradually increase this threshold from 0 to 1, we can realize that part of the model of the pixel disappears first, until the entire model disappears completely the effect. The simple principle is explained, first comes a basic dissolution effect:
Dissolution effect//by:puppet_master//2017.5.18 Shader "Apcshader/dissolveeffect" {properties{_diffuse ("diffuse", Color) = (1, 1,1,1) _maintex ("Base 2D", 2D) = "White" {} _dissolvemap ("Dissolvemap", 2D) = "White" {} _dissolvethreshold ("Dissolvet
	Hreshold ", Range (0,1)) = 0} cginclude #include" lighting.cginc "uniform fixed4 _diffuse;
	Uniform sampler2d _maintex;
	Uniform FLOAT4 _maintex_st;
	Uniform sampler2d _dissolvemap;
	
	Uniform float _dissolvethreshold;
		struct V2F {float4 pos:sv_position;
		FLOAT3 worldnormal:texcoord0;
	FLOAT2 Uv:texcoord1;
	
	};
		v2f Vert (Appdata_base v) {v2f o;
		O.pos = Mul (UNITY_MATRIX_MVP, V.vertex);
		O.UV = Transform_tex (V.texcoord, _maintex);
		O.worldnormal = Mul (V.normal, (float3x3) unity_worldtoobject);
	return o;
		} fixed4 Frag (v2f i): sv_target {//Sample dissolve Map fixed4 dissolvevalue = tex2d (_dissolvemap, I.UV);
		Portions below the threshold are directly discard if (DISSOLVEVALUE.R < _dissolvethreshold) {discard; }//diffuse + Ambient lightAccording to the calculation fixed3 Worldnormal = normalize (i.worldnormal);
		Fixed3 Worldlightdir = normalize (_WORLDSPACELIGHTPOS0.XYZ);
		Fixed3 lambert = saturate (dot (worldnormal, worldlightdir));
		FIXED3 albedo = Lambert * _diffuse.xyz * _lightcolor0.xyz + unity_lightmodel_ambient.xyz;
		Fixed3 color = tex2d (_maintex, I.UV). RGB * ALBEDO;
	return fixed4 (color, 1); } ENDCG Subshader {tags{"rendertype" = "Opaque"} Pass {cgprogram #pragma vertex vert #pragma fragm
 ent frag ENDCG}} FallBack "Diffuse"}
Recently found a more handsome model, first exploded a photo (opened Bloom and Depth of Field): Then, let us dissolve it, here we directly use a noise diagram, the simplest snowflake point of the kind can, gradually adjust the dissolve Threshold, you can:

increase the dissolution effect of the transition
The dissolution effect on the top feels like being shot into a sieve ... The wood has a clear transition, the feeling effect is not very good. The following is an increase in the dissolution of the transition effect, let the dissolved part of the edge into the color we set, in order to increase the richness, we can add two transition colors. Set two thresholds respectively. First, when the threshold is less than the color a threshold, return color A, the threshold value is less than the color B, return color B, otherwise return the original color. The shader code is as follows:
Dissolution effect//by:puppet_master//2017.5.18 Shader "Apcshader/dissolveeffect" {properties{_diffuse ("diffuse", Color) = (1,
		1,1,1) _dissolvecolora ("Dissolve color A", color) = (0,0,0,0) _dissolvecolorb ("Dissolve color B", color) = (1,1,1,1) _maintex ("Base 2D", 2D) = "White" {} _dissolvemap ("Dissolvemap", 2D) = "White" {} _dissolvethreshold ("Dissolvethreshold
	
	", Range (0,1)) = 0 _colorfactora (" Colorfactora ", Range (0,1)) = 0.7 _colorfactorb (" Colorfactorb ", Range (0,1)) = 0.8}
	Cginclude #include "lighting.cginc" uniform fixed4 _diffuse;
	Uniform fixed4 _dissolvecolora;
	Uniform fixed4 _dissolvecolorb;
	Uniform sampler2d _maintex;
	Uniform FLOAT4 _maintex_st;
	Uniform sampler2d _dissolvemap;
	Uniform float _dissolvethreshold;
	Uniform float _colorfactora;
	
	Uniform float _colorfactorb;
		struct V2F {float4 pos:sv_position;
		FLOAT3 worldnormal:texcoord0;
	FLOAT2 Uv:texcoord1;
	
	};
		v2f Vert (Appdata_base v) {v2f o;
		O.pos = Mul (UNITY_MATRIX_MVP, V.vertex); O. UV = Transform_tex (V.texcoord, _maintex);
		O.worldnormal = Mul (V.normal, (float3x3) unity_worldtoobject);
	return o;
		} fixed4 Frag (v2f i): sv_target {//Sample dissolve Map fixed4 dissolvevalue = tex2d (_dissolvemap, I.UV);
		Portions below the threshold are directly discard if (DISSOLVEVALUE.R < _dissolvethreshold) {discard;
		}//diffuse + ambient illumination calculation fixed3 Worldnormal = normalize (i.worldnormal);
		Fixed3 Worldlightdir = normalize (_WORLDSPACELIGHTPOS0.XYZ);
		Fixed3 lambert = saturate (dot (worldnormal, worldlightdir));
		FIXED3 albedo = Lambert * _diffuse.xyz * _lightcolor0.xyz + unity_lightmodel_ambient.xyz;
		Fixed3 color = tex2d (_maintex, I.UV). RGB * ALBEDO;
		Here for the sake of convenience, directly with color and the final edge lerp float lerpvalue = _DISSOLVETHRESHOLD/DISSOLVEVALUE.R;
			if (Lerpvalue > _colorfactora) {if (Lerpvalue > _colorfactorb) return _dissolvecolorb;
		return _dissolvecolora;
	} return Fixed4 (color, 1);
} ENDCG Subshader {tags{"rendertype" = "Opaque"} Pass {Cgprogram			#pragma vertex vert #pragma fragment Frag ENDCG}} FallBack "Diffuse"}
 
Above the model, we configure a lightning-type dissolution effect, with two color values given to white and blue respectively. Then the noise map to a more gentle transition, as shown below: To a dynamic diagram, the first gradually increase the dissolution threshold, is the dissolution effect, and then reduce the threshold, is the effect of the shiny debut:
Although the above shader is relatively easy to understand, we have directly used two if to judge. But feel shader inside branches or as little as possible, after all, if there is Dynamic branch (some of the compile period can be automatically optimized, such as we write a fixed number of cycles, this should be directly in the compilation period), the runtime of the shader has a dynamic branch, it will first execute a branch, Then go to the B branch, the efficiency is down, you can refer to the discussion of the great God. So ... We're still going to write a value to judge (except discard):
Dissolution effect//by:puppet_master//2017.5.19 Shader "Apcshader/dissolveeffect" {properties{_diffuse ("diffuse", Color) = (1, 1,1,1) _dissolvecolor ("Dissolve color", color) = (0,0,0,0) _dissolveedgecolor ("Dissolve Edge Color", color) = (1,1,1,1 ) _maintex ("Base 2D", 2D) = "White" {} _dissolvemap ("Dissolvemap", 2D) = "White" {} _dissolvethreshold ("Dissolvethresh 
	
	Old ", range (0,1)) = 0 _colorfactor (" Colorfactor ", Range (0,1)) = 0.7 _dissolveedge (" Dissolveedge ", Range (0,1)) = 0.8}
	Cginclude #include "lighting.cginc" uniform fixed4 _diffuse;
	Uniform fixed4 _dissolvecolor;
	Uniform fixed4 _dissolveedgecolor;
	Uniform sampler2d _maintex;
	Uniform FLOAT4 _maintex_st;
	Uniform sampler2d _dissolvemap;
	Uniform float _dissolvethreshold;
	Uniform float _colorfactor;
	
	Uniform float _dissolveedge;
		struct V2F {float4 pos:sv_position;
		FLOAT3 worldnormal:texcoord0;
	FLOAT2 Uv:texcoord1;
	
	};
		v2f Vert (Appdata_base v) {v2f o;
	O.pos = Mul (UNITY_MATRIX_MVP, V.vertex);	O.UV = Transform_tex (V.texcoord, _maintex);
		O.worldnormal = Mul (V.normal, (float3x3) unity_worldtoobject);
	return o;
		} fixed4 Frag (v2f i): sv_target {//Sample dissolve Map fixed4 dissolvevalue = tex2d (_dissolvemap, I.UV);
		Portions below the threshold are directly discard if (DISSOLVEVALUE.R < _dissolvethreshold) {discard;
		}//diffuse + ambient illumination calculation fixed3 Worldnormal = normalize (i.worldnormal);
		Fixed3 Worldlightdir = normalize (_WORLDSPACELIGHTPOS0.XYZ);
		Fixed3 lambert = saturate (dot (worldnormal, worldlightdir));
		FIXED3 albedo = Lambert * _diffuse.xyz * _lightcolor0.xyz + unity_lightmodel_ambient.xyz;

		Fixed3 color = tex2d (_maintex, I.UV). RGB * ALBEDO;
		Optimized version, try not to judge the version in the shader with the branch, but the code is difficult to understand ah .... float percentage = _DISSOLVETHRESHOLD/DISSOLVEVALUE.R;
		If current percentage-color weight-edge color float Lerpedge = sign (percentage-_colorfactor-_dissolveedge); It seems that the value returned by sign has to be saturate, otherwise it is a very strange value fixed3 Edgecolor = Lerp (_dissolveedgecolor.rgb, _dissolvecolor.rgb, saturate (
		Lerpedge)); Final output ColorThe Lerp value of float lerpout = sign (percentage-_colorfactor); The difference between the final color in the original color and the color calculated in the previous step (in fact, after saturate (.
		) Lerpout should only be 0 or 1) fixed3 colorout = lerp (color, Edgecolor, saturate (lerpout));
	Return Fixed4 (Colorout, 1); } ENDCG Subshader {tags{"rendertype" = "Opaque"} Pass {cgprogram #pragma vertex vert #pragma fragm
 ent frag ENDCG}} FallBack "Diffuse"}
The effect is basically the same as above, so this time we will change the color of the burning dissolution effect, the color adjustment to yellow and red:

One more launch diagram:

not just the dissolution, but the Ashes.
Our model was dissolved and it was already miserable enough. If we make it worse, let it go. "Biochemistry crisis 6" in the dissipation effect feeling should be produced by particle effects, in fact, we directly with shader should also be able to make similar effects, but certainly not specifically to do a special effect of good, can only simulate a similar effect. First of all, if we want to get the fragments of the model to fly out, then we have to offset the pixel position before rasterization, so this operation is done in vertex shader. We let the vertex coordinates of the model do some deviation according to certain rules, we can achieve the effect of flying out. For example, we try to let the model in accordance with the normal direction of extension, and then the minimum range, you can achieve the size of the expansion of the model, but this expansion is not much, if too large, there will be "triangle explosion" situation, you can refer to the last picture of this article. We're just going to let it expand a little bit. For example, the following sentence, when greater than a certain threshold, only to start the expansion effect:
V.VERTEX.XYZ + = V.normal * Saturate (_dissolvethreshold-_flythreshold) * _flyfactor;
This time we change a snowflake point type noise graph, the effect is as follows:

A little discussion about the effect of dissipation along a certain direction
Feel the effect of flying along the normal direction of the feeling is not good control, especially easy to see the situation of triangle wearing help. We can also let the model in the dissolution of more than a certain threshold to fly upward, presumably such an effect, or the handsome model, but we changed an angle:

The following paragraph is purely nonsense, interested can look at my inner monologue:
To make the model move upward, there are several situations. The first is the model space upward, the simplest, directly in the Appdata_base incoming vertex y-axis coordinates can be modified, but in this case the model will only follow the so-called model y-axis offset, if the luck, the y-axis just above the head, then the effect is normal, But if the y-axis is not the top of the head, what we call upward is not necessarily where it is, the second is in the screen space upward, such as the angle of our experiment above, we can directly calculate the MVP after the coordinates obtained by the y direction of the offset, relatively simple, but this situation will have some problems, For example, if we look at the camera for a different angle, the offset direction of the model is still moving upward on the screen, this effect is not correct, the third is in the world coordinates upward, the world space only one, and all models share this world space, we in this space offset operation, All models, regardless of their coordinate system, and regardless of the camera observation angle, will be offset in the Y direction of world space, which is most in line with our real world, the so-called world is there, if the angle of observation is different, then the results will be different (NN, Write a shader unexpectedly also rise to philosophical level =. =). Let's take a look at the operation of model offsets in world space. This is not directly in the model space or screen space to operate conveniently, because this operation is interspersed in the MVP transformation in the middle, we need to first ... (Wait, I seem to think of something), let the model from the world space to move in one direction, is not to change transform Y axis direction (I am not writing shader write silly =. =) ... If I do this in the shader, the model has N vertices, then this is an O (N) complexity operation, and if I let the model shift in the Y direction directly at the scripting level, This time complexity is O (1) (like the transformation matrix and so on each frame is calculated for each object and then passed to the shader in the operation, that is, shader in the uniform type of variable). So, the best way to realize this is to just hang up the script and translate the model up and down in the y direction just by the time it's greater than a certain value.
In short, although shader strong, can make a lot of very interesting effect, but, not all the effects are suitable for shader. After all, if we calculate in the script, for a model, it only needs to be calculated once. But if put in vertex shader in need of the model vertex number of operations, put to fragment shader the words need to be rasterized after the visible pixel number of operations, performance or not the same.
dissolution effect by-product
Writing a shader often writes some by-products, though the effect is not the same as what is currently wanted (and, more bluntly, the failed version of the experiment ...). , but the effect is sometimes quite fun, and intends to shader by the byproduct also recorded, in case later use, 2333.
The first one is to calculate a superimposed color value directly behind the dissolve effect, superimposed on the original model based on the noise sample:
float Lerpvalue = (DISSOLVEVALUE.R-_dissolvethreshold) * _dissolveedge;
FIXED3 final = color + _dissolvecolor * lerpvalue;
Brain repair use of the scene: From left to right is the virus infection, flash blind (in fact, just over-violence, because plus bloom compared to the effect of it), Santu rebirth to end (fire fans exposed ....) )

Second bomb, explosion effect ... This is the dissolution of the debris fly out, the weight of the value is too high, the direct triangle burst open .... Feel good, in fact, the main thing is to follow the normal direction of the model offset:
V.VERTEX.XYZ + = V.normal * _dissolvethreshold * 0.5;





Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.