体积雾shader

全局雾很简单,在unity里只需要一个选项即可,可是它不能控制局部地区的雾化效果。所以有”Volume Fog”这种shader,网上搜了很久,只有一个比较满意: www.youtube.com/watch?v=HPo2gfy675o ,可是要卖50刀(站长看看有没有意愿团一个?~~)

算了,自己动手,再次硬着头皮上了,为此我还狠心买了《GPU Gems》全套,既然目前我都在研究游戏里的特效实现,不光是粒子系统,shader也是重要的组成部分,所以我决定以后也会在Xffect里多包含一些实用的shader,比如这次分享的Volume Fog。还有很早前就包含的“Heat Distortion”(热浪?)shader,这个是非常实用的,因为很多特效都有局部画面扭曲效果。

下面放2张截图,目前的体积雾只支持球体。

在fog外面看到的效果:

在fog里面看到的效果:

我的游戏项目里用到的效果:



=================================================================

好了,放上shader代码,需要注意的是,该shader需要开启DepthTextureMode,如果是deffered lightning则不需要手动开启,Forward lightning需要手动开启:“Camera.main.depthTextureMode = DepthTextureMode.Depth;”

另外,需要外部传送FogParam参数,FogParam.xyz代表Sphere center, FogParam.z 代表sphere radius,所以该shader不能独立使用,需要配合简单的脚本,脚本我就不放上了,不过我会在Xffect 1.2.3版本里加入完整的例子,包括免费版。


复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
Shader "Xffect/volume_fog" {
Properties {
    _FogColor ("Fog Color", Color) = (1,1,1,1)
}
 
Category {
    Tags { "Queue"="Transparent+99" "IgnoreProjector"="True" "RenderType"="Transparent" }
    Blend SrcAlpha OneMinusSrcAlpha
    Cull Off Lighting Off ZWrite Off
    ZTest Always
 
SubShader {
    Pass {
 
CGPROGRAM
#pragma target 3.0
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
 
float CalcVolumeFogIntensity(float3 sphereCenter, float sphereRadius, float3 cameraPosition, float3 viewDirection, float backDepth, float maxDistance, float density)
{
    float3 local = cameraPosition - sphereCenter;
    float  fA      = dot(viewDirection, viewDirection);
    float  fB      = 2 * dot(viewDirection, local);
    float  fC      = dot(local, local) - sphereRadius * sphereRadius;
    float  fD      = fB * fB - 4 * fA * fC;
&nbsp;&nbsp;&nbsp;&nbsp;if ( fD < 0.0f )
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return 0;
&nbsp;&nbsp;
&nbsp;&nbsp;float recpTwoA = 0.5 / fA;
&nbsp;&nbsp;
&nbsp;&nbsp;float dist;
 
&nbsp;&nbsp;if (fD == 0.0f)
&nbsp;&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;dist = backDepth;
&nbsp;&nbsp;}
&nbsp;&nbsp;else
&nbsp;&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;float DSqrt = sqrt(fD);
&nbsp;&nbsp;&nbsp;&nbsp;dist = (-fB - DSqrt) * recpTwoA;
&nbsp;&nbsp;}
 
&nbsp;&nbsp;dist = min(dist, maxDistance);
&nbsp;&nbsp;backDepth = min(backDepth, maxDistance);
&nbsp;&nbsp;
&nbsp;&nbsp;float sample = dist;
&nbsp;&nbsp;float fog = 0;
&nbsp;&nbsp;float step_distance = ( backDepth - dist ) / 10;
&nbsp;&nbsp;for ( int seg = 0; seg < 10; seg++ )
&nbsp;&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;float3 position = cameraPosition + viewDirection * sample;
&nbsp;&nbsp;&nbsp;&nbsp;fog += 1 - saturate( length( sphereCenter - position ) / sphereRadius );
&nbsp;&nbsp;&nbsp;&nbsp;sample += step_distance;
&nbsp;&nbsp;}
&nbsp;&nbsp;fog /= 10;
&nbsp;&nbsp;fog&nbsp;&nbsp;= saturate( fog * density );
&nbsp;&nbsp;return fog;
}
 
fixed4 _FogColor;
sampler2D _CameraDepthTexture;
uniform float4 FogParam;
 
struct v2f {
&nbsp;&nbsp;&nbsp;&nbsp;float4 pos : SV_POSITION;
&nbsp;&nbsp;&nbsp;&nbsp;float3 view : TEXCOORD0;
&nbsp;&nbsp;&nbsp;&nbsp;float4 projPos : TEXCOORD1;
};
 
 
v2f vert (appdata_base v)
{
&nbsp;&nbsp;&nbsp;&nbsp;v2f o;
&nbsp;&nbsp;&nbsp;&nbsp;float4 wPos = mul (_Object2World, v.vertex);
&nbsp;&nbsp;&nbsp;&nbsp;o.pos = mul (UNITY_MATRIX_MVP, v.vertex);
&nbsp;&nbsp;&nbsp;&nbsp;o.view = wPos.xyz - _WorldSpaceCameraPos;
&nbsp;&nbsp;&nbsp;&nbsp;o.projPos = ComputeScreenPos (o.pos);
 
&nbsp;&nbsp;&nbsp;&nbsp;// move projected z to near plane if point is behind near plane
&nbsp;&nbsp;&nbsp;&nbsp;float inFrontOf = ( o.pos.z / o.pos.w ) > 0;
&nbsp;&nbsp;&nbsp;&nbsp;o.pos.z *= inFrontOf;
&nbsp;&nbsp;&nbsp;&nbsp;return o;
}
 
half4 frag (v2f i) : COLOR
{
&nbsp;&nbsp;&nbsp;&nbsp;half4 color = half4(1,1,1,1);
&nbsp;&nbsp;&nbsp;&nbsp;float depth = LinearEyeDepth (UNITY_SAMPLE_DEPTH(tex2Dproj(_CameraDepthTexture, UNITY_PROJ_COORD(i.projPos))));
&nbsp;&nbsp;&nbsp;&nbsp;float backDist = length(i.view);
&nbsp;&nbsp;&nbsp;&nbsp;float3 viewDir = normalize(i.view);
&nbsp;&nbsp;&nbsp;&nbsp;float fog = CalcVolumeFogIntensity(FogParam.xyz, FogParam.w, _WorldSpaceCameraPos, viewDir, backDist, depth,_FogColor.a);
&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;color.rgb = _FogColor.rgb;
&nbsp;&nbsp;&nbsp;&nbsp;color.a = fog;
&nbsp;&nbsp;&nbsp;&nbsp;return color;
}
ENDCG
 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}
&nbsp;&nbsp;&nbsp;&nbsp;}
}
Fallback "VertexLit"
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值