网站公告 | [优惠活动] 12.4号周一开始结帖发放7天抢楼帖
查看: 1417|回复: 6
收起左侧

[再来一次] UnityShader实战 之 体积光的实现

[复制链接]

[再来一次] UnityShader实战 之 体积光的实现[复制链接]

再来一次 发表于 2017-1-6 13:49:43 [显示全部楼层] 回帖奖励 |倒序浏览 |阅读模式 回复:  6 浏览:  1417
本帖最后由 里斯 于 2017-1-7 11:33 编辑

      大家好,我是Zander. 今天我们用Shader来模拟体积光。先看一下效果:
这是在ShadowGun场景里的一个实现效果。
Shader代码如下:
[AppleScript] 纯文本查看 复制代码
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
最后的实现效果 :
   
好了,这一章就写到这,欢迎大家加入QQ群:280993838 。或者关注我的公众号:

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?立即注册

x

免费评分

参与人数 1泰斗币 +50 收起 理由
里斯 + 50 赞一个!

查看全部评分

+1
1416°C
6
  • aa710315280
  • 里斯
  • try111
  • 墨麟
  • 天长第9
过: 他们
最近访问 头像模式 列表模式
因分享而快乐,学习以自强!
aa710315280 发表于 2017-1-6 14:21:20 显示全部楼层
看了LZ的帖子,我只想说一句很好很强大!
因分享而快乐,学习以自强!
里斯 发表于 2017-1-7 11:34:10 显示全部楼层
膜拜神贴
因分享而快乐,学习以自强!
try111 发表于 2017-1-8 10:21:26 显示全部楼层
膜拜膜拜
因分享而快乐,学习以自强!
墨麟 发表于 2017-1-9 09:25:08 显示全部楼层
泰斗帖子强,满满正能量。
因分享而快乐,学习以自强!
天长第9 发表于 2017-1-9 13:45:50 显示全部楼层
膜拜神贴,后面请保持队形~
因分享而快乐,学习以自强!
nham123 发表于 2017-1-11 17:27:47 显示全部楼层
bfdbfdb fgdfg dfgfdgdf gdfgfdg retretr regergreg
因分享而快乐,学习以自强!

本版积分规则

VR/AR版块|Unity3d|Unreal4|新手报道|小黑屋|站点地图|沪ICP备14023207号-9|【泰斗社区】-专注互联网游戏和应用的开发者平台 ( 沪ICP备14023207号-9 )|网站地图

© 2001-2013 Comsenz Inc.  Powered by Discuz! X3.2

1
QQ