C # Use shader to realize the effect of night Countdown _c# tutorial

Source: Internet
Author: User
Tags mul

The recent hot global PC game Battlerite (War ritual) in the countdown will produce a similar effect of the night, will be the center of the battlefield, a length of the radius is dark outside, and this radius will gradually shrink, and the dark part of the circle is attached to the terrain, This article attempts to use the method of screen post processing to achieve this effect.

(Temporarily missing Battlerite screenshot, later will fill up)

First look at the effect chart:

Note: This article refers to the Tasharen Fog of the war plug-in

Create a C # script, named NightFall.cs, and create some common variables (nightcolor,center and RADIUS) for the Nightfall class, plus a nightfall.shader.

First, we want to make sure that the effect is implemented before the scene is rendered to the screen, so the nightfall script is mounted on the main Camera (add attributes [Requirecomponent (typeof (Camera))]), And to implement the Onrenderimage method.

Second, in the Onrenderimage method, we eventually need to call the Graphics.blit method, and the third parameter of this method is the material type, so we need to create a temporary material in the code that uses the Nightfall.shader.

Again, we need to convert the screen coordinates into world coordinates in the shader to compute the coordinates with the world center, so we need the MVP inverse matrix (refer to the shader (16) coordinate space and the transformation matrix).

Finally, in order to attach the terrain, we need to compute the depth in the shader, that is, the relative distance between the coordinate point and the camera, so we need the camera position.

Code for C #:

Using Unityengine;

[Requirecomponent (typeof (Camera))] public class Nightfall:monobehaviour {public Shader Shader; 
Public color Nightcolor = new Color (0.05f, 0.05f, 0.05f, 0.5f); 
Public Vector3 Center = Vector3.zero; 
public float radius = 10; 
Camera Mcam; 
matrix4x4 MINVERSEMVP; 
Material Mmat; 
The camera we ' re working with needs depth. 
void Onenable () {Mcam = getcomponent<camera> (); 
Mcam.depthtexturemode = depthtexturemode.depth; 
if (shader = = null) shader = Shader.find ("Image effects/nightfall"); 
}///Destroy the material when disabled. 
void Ondisable () {if (Mmat) destroyimmediate (Mmat);} 
Automatically disable the effect if the shaders don ' t support it. void Start () {if (! systeminfo.supportsimageeffects | | !shader | | 
!shader.issupported) {enabled = false; 
}//called by camera to apply image effect void Onrenderimage (rendertexture source, rendertexture destination) { 
Print (Nightcolor); 
print (destination); Calculate the inverse modelview-prOjection matrix to convert screens coordinates to the world coordinates MINVERSEMVP = (Mcam.projectionmatrix * Mcam.worldtocam 
Eramatrix). Inverse; 
if (Mmat = = null) {Mmat = new Material (shader); 
Mmat.hideflags = Hideflags.hideanddontsave; 
} Vector4 CamPos = mCam.transform.position; 
This is accounts for anti-aliasing on Windows flipping the depth UV coordinates. Despite the official documentation, the following approach simply ' doesn ' t work://Http://docs.unity3d.com/Documentati on/components/sl-platformdifferences.html if (qualitysettings.antialiasing > 0) {runtimeplatform PL = Application.p 
Latform; 
if (pl = = Runtimeplatform.windowseditor | | 
PL = Runtimeplatform.windowsplayer | | 
PL = = Runtimeplatform.windowswebplayer) {CAMPOS.W = 1f; 
} mmat.setvector ("_campos", CamPos); 
Mmat.setmatrix ("_INVERSEMVP", MINVERSEMVP); 
Mmat.setcolor ("_nightcolor", Nightcolor); 
Mmat.setvector ("_center", Center); 
Mmat.setfloat ("_radius", Radius); Graphics.blit (Source, DestinatiOn, Mmat); } 
}

Shader Code:

Shader "Image effects/nightfall" {Properties {_nightcolor ("Night color", color) = (0.05, 0.05, 0.05, 0.05) _cente  R ("Center", Vector) = (0,0,0,0) _radius ("Radius", float) = ten} Subshader {pass {ZTest Always cull off Zwrite Off Fog {Mode off} Blend srcalpha oneminussrcalpha cgprogram #pragma vertex vert_img #pragma fragment frag vertex: 
Vert #pragma fragmentoption arb_precision_hint_fastest #include "unitycg.cginc" sampler2d _cameradepthtexture; 
Uniform float4x4 _INVERSEMVP; 
Uniform FLOAT4 _campos; 
Uniform Half4 _nightcolor; 
Uniform Half4 _center; 
Uniform half _radius; 
struct Input {float4 position:position; 
FLOAT2 uv:texcoord0; 
}; 
void Vert (InOut appdata_full V, out Input o) {o.position = Mul (UNITY_MATRIX_MVP, V.vertex); 
O.UV = V.texcoord.xy; 
} FLOAT3 Camtoworld (in Float2 UV) {float4 pos = float4 (uv.x, uv.y, depth, 1.0); 
POS.XYZ = pos.xyz * 2.0-1.0; 
pos = Mul (_INVERSEMVP, POS); 
return POS.XYZ/POS.W; } fiXed4 Frag (Input i): COLOR {#if Shader_api_d3d9 | | 
Shader_api_d3d11 float2 Depthuv = I.UV; 
Depthuv.y = Lerp (Depthuv.y, 1.0-depthuv.y, _CAMPOS.W); 
float depth = unity_sample_depth (tex2d (_cameradepthtexture, Depthuv)); 
FLOAT3 pos = Camtoworld (depthuv, depth); 
#else Float depth = unity_sample_depth (tex2d (_cameradepthtexture, I.UV)); 
FLOAT3 pos = Camtoworld (i.uv, depth); #endif//Limit to sea level if (Pos.y < 0.0) {/This is a simplified version of the Ray-plane intersection formu 
La:t =-(N.O + D)/(N.D) Float3 dir = normalize (pos-_campos.xyz); 
pos = _campos.xyz-dir * (_CAMPOS.Y/DIR.Y); 
} Half4 Col; 
float dis = Length (Pos.xz-_CENTER.XZ); 
if (Dis < _radius) {col = fixed4 (0,0,0,0); 
else {col = _nightcolor; 
return col; } ENDCG} fallback off}

A few points to note:

1, because platform difference, in order to compatible with Direct3D, so in C # and shader through the CamPos (_campos) of the W component to adjust the UV coordinates.

2, although there is no statement _maintex, but _maintex is in fact the screen image will be imaged, so here's i.uv refers to the screen image texture coordinates.

3, _cameradepthtexture is the depth of the camera texture, through the Unity_sample_depth method to obtain depth.

4, Camtoworld inside, first based on the UV coordinates and depth depth created a float4 coordinate value POS, and then to the POS multiply 2 minus 1 is the coordinate range from [0,1] to [ -1,1], corresponding to the world coordinates. Then using the passed-in MVP inverse matrix _INVERSEMVP multiplied by this coordinate value, we get the world coordinates of the screen point. Finally, the XYZ component of the POS is divided by the W component, where the W component represents the scaling value resulting from the proximity.

5, after the calculation of world coordinates, for y less than 0 of the coordinates to do a deal, the effect is limited to the sea level (ocean levels), using the Ray plane intersection equation (ray-plane intersection formula) simplified version to deal with.

6. Finally, the color value is returned according to the distance.

If you want to achieve the effect of the night countdown, just get the nightfall component on the camera in the control script (C #) and modify the RADIUS variable according to the time.

The above mentioned is small set to introduce C # use shader to realize the countdown effect of night falls, hope to help everyone, if you have any questions please give me a message, small series will promptly reply to everyone. Here also thank you very much for the cloud Habitat Community website support!

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.