UnityShader实战 之 体积光的实现

大家好,我是Zander. 今天我们用Shader来模拟体积光。先看一下效果:

这是在ShadowGun场景里的一个实现效果。

Shader代码如下:

Shader "Custom/Blinking GodRays" {

Properties {

_MainTex ("Base texture", 2D) = "white" {}                                        //用于模拟光照的透明纹理

_FadeOutDistNear ("Near fadeout dist", float) = 10                               //小于这个距离时 会出现淡出效果

_FadeOutDistFar ("Far fadeout dist", float) = 10000                               //大于这个距离时 会出现淡出效果

_Multiplier("Color multiplier", float) = 1                                        //光照颜色的乘数  可以用来调节最后的模拟光照

_Bias("Bias",float) = 0                                                          //模拟闪烁时  波形的偏移  可以理解为波形图像Y方向的移动量

_TimeOnDuration("ON duration",float) = 0.5                                        //模拟闪烁时  闪烁时亮着的时间

_TimeOffDuration("OFF duration",float) = 0.5                                      //模拟闪烁时  闪烁时暗着的时间

_BlinkingTimeOffsScale("Blinking time offset scale (seconds)",float) = 5          //模拟闪烁时  指定闪烁在波形中开始位置

_SizeGrowStartDist("Size grow start dist",float) = 5                              //大于这个距离时,会开始对顶点进行扩展,即从0开始增长。

_SizeGrowEndDist("Size grow end dist",float) = 50                                //达到这个距离时,扩张达到最大程度,即扩展程度为1。

_MaxGrowSize("Max grow size",float) = 2.5                                        //扩张的最大大小

_NoiseAmount("Noise amount (when zero, pulse wave is used)", Range(0,0.5)) = 0    //模拟闪烁时,噪声的程度,用于混合均匀的脉冲波和噪声波

_Color("Color", Color) = (1,1,1,1)                                                //用于改变光照颜色。

}

SubShader{

Tags{ "Queue" = "Transparent"  "IgnoreProjector" = "True"  "RenderType" = "Transparent" }

Blend One One    // 贴图和背景叠加  无Alpha透明通道处理

Cull Off Lighting Off ZWrite Off Fog { Color (0,0,0,0) }

CGINCLUDE

#include "UnityCG.cginc"

sampler2D _MainTex;

float  _FadeOutDistNear;

float  _FadeOutDistFar;

float  _Multiplier;

float  _Bias;

float  _TimeOnDuration;

float  _TimeOffDuration;

float  _BlinkingTimeOffsScale;

float  _SizeGrowStartDist;

float  _SizeGrowEndDist;

float  _MaxGrowSize;

float  _NoiseAmount;

float4  _Color;

struct v2f{

float4 pos : SV_POSITION;  //裁剪空间中的顶点坐标

float2 uv  : TEXCOORD0;    //顶点的纹理坐标

fixed4 color : TEXCOORD1;    //顶点颜色

};

v2f vert(appdata_full  v)

{

v2f  o;

float time =  _Time.y + _BlinkingTimeOffsScale * v.color.b;

float3     viewPos     =  mul(UNITY_MATRIX_MV,v.vertex);                          //mul(x, y) 返回x、y矩阵相乘的积。

float dist =  length(viewPos);                                        //length(v)  返回v向量的长度  dist  距离视角的远近

float nfadeout     =  saturate(dist / _FadeOutDistNear);                      //saturate(x) 把x截取在[0, 1]之间    如果小于了_FadeOutDistNear,那么就会开始模拟淡出的效果

float ffadeout     =  1 - saturate(max(dist - _FadeOutDistFar,0) * 0.2);      //0.2是模拟了淡入的速率

float fracTime     =  fmod(time,_TimeOnDuration + _TimeOffDuration);          //fmod(x, y)  返回x/y的浮点余数。

float wave =  smoothstep(0,_TimeOnDuration * 0.25,fracTime)  * (1 - smoothstep(_TimeOnDuration * 0.75,_TimeOnDuration,fracTime));  //smoothstep(min, max, x) 如果x的范围是[min, max],则返回一个介于0和1之间的Hermite插值。

float noiseTime     =  time *  (6.2831853f / _TimeOnDuration);

float noise =  sin(noiseTime) * (0.5f * cos(noiseTime * 0.6366f + 56.7272f) + 0.5f);

float noiseWave     =  _NoiseAmount * noise + (1 - _NoiseAmount);

float distScale     =  min(max(dist - _SizeGrowStartDist,0) / _SizeGrowEndDist,1);

wave = _NoiseAmount < 0.01f ? wave : noiseWave;    //这里主要是为了模拟闪烁的效果

distScale = distScale * distScale * _MaxGrowSize * v.color.a;  //扩大顶点区域  这主要是为了模拟射灯的效果 ,我们在远离光源的过程中会感觉好像光照范围范围变大了

wave += _Bias;

ffadeout *= ffadeout;

nfadeout *= nfadeout;

nfadeout *= nfadeout;

nfadeout *= ffadeout;

float4 mdlPos = v.vertex;

mdlPos.xyz += distScale * v.normal;

o.uv = v.texcoord.xy;

o.pos = mul(UNITY_MATRIX_MVP, mdlPos);

o.color = nfadeout * _Color * _Multiplier * wave;

return o;

}

ENDCG

Pass {

CGPROGRAM

#pragma vertex vert

#pragma fragment frag

#pragma fragmentoption ARB_precision_hint_fastest

fixed4 frag (v2f i) : COLOR

{

return tex2D (_MainTex, i.uv.xy) * i.color;

}

ENDCG

}

}

}

具体的实现逻辑我在上面添加了注释 ,如有不对的地方,还望不吝指导。

所需要的图片:

所需要的模型资源地址:

链接:http://pan.baidu.com/s/1kVJjjTX 密码:payr

最后的实现效果 :

UnityShader实战 之 体积光的实现_第1张图片

好了,这一章就写到这,欢迎大家加入QQ群:280993838 。或者关注我的公众号:

UnityShader实战 之 体积光的实现_第2张图片

你可能感兴趣的:(UnityShader实战 之 体积光的实现)