原文地址:Unity 体积雾
Shader|http://game.ceeger.com/forum/read.php?tid=3132
 
全局雾很简单,在unity里只需要一个选项即可,可是它不能控制局部地区的雾化效果。所以有”Volume
Fog”这种shader,网上搜了很久,只有一个比较满意:www.youtube.com/watch?v=HPo2gfy675o,可是要卖50刀(站长看看有没有意愿团一个?~~)
算了,自己动手,再次硬着头皮上了,为此我还狠心买了《GPU
Gems》全套,既然目前我都在研究游戏里的特效实现,不光是粒子系统,shader也是重要的组成部分,所以我决定以后也会在Xffect里多包含一些实用的shader,比如这次分享的Volume
Fog。还有很早前就包含的“Heat
Distortion”(热浪?)shader,这个是非常实用的,因为很多特效都有局部画面扭曲效果。
下面放2张截图,目前的体积雾只支持球体。
在fog外面看到的效果:
 
http://game.ceeger.com/forum/attachment/thumb/Mon_1208/2_2159_f575b82e0d12d53.jpg?52着色器]Unity 体积雾 Shader"  TITLE="[Shader 着色器]Unity 体积雾 Shader" />
在fog里面看到的效果:
http://game.ceeger.com/forum/attachment/thumb/Mon_1208/2_2159_f89c7ad414ee9c6.jpg?61着色器]Unity 体积雾 Shader"  TITLE="[Shader 着色器]Unity 体积雾 Shader" />
我的游戏项目里用到的效果:
http://game.ceeger.com/forum/attachment/thumb/Mon_1208/2_2159_023f45b97dc5aac.jpg?173着色器]Unity 体积雾 Shader"  TITLE="[Shader 着色器]Unity 体积雾 Shader" />
http://game.ceeger.com/forum/attachment/thumb/Mon_1208/2_2159_7a43ec5e02b1939.jpg?147着色器]Unity 体积雾 Shader"  TITLE="[Shader 着色器]Unity 体积雾 Shader" />
=================================================================
好了,放上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版本里加入完整的例子,包括免费版。
- 
//http://forum.unity3d.com/threads/142245-Xffect-Editor-Pro-powerful-tool-to-create-amazing-effects!
- 
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;
- 
    if
( fD < 0.0f )
- 
        return
0;
- 
  
- 
  float recpTwoA = 0.5 / fA;
- 
  
- 
  float dist;
- 
  if (fD == 0.0f)
- 
  {
- 
    dist
= backDepth;
- 
  }
- 
  else
- 
  {
- 
    float
DSqrt = sqrt(fD);
- 
    dist
= (-fB - DSqrt) * recpTwoA;
- 
  }
- 
  dist = min(dist,
maxDistance);
- 
  backDepth = min(backDepth,
maxDistance);
- 
  
- 
  float sample = dist;
- 
  float fog = 0;
- 
  float step_distance = (
backDepth - dist ) / 10;
- 
  for ( int seg = 0; seg
< 10; seg++ )
- 
  {
- 
    float3
position = cameraPosition + viewDirection * sample;
- 
    fog
+= 1 - saturate( length( sphereCenter - position ) / sphereRadius
);
- 
    sample
+= step_distance;
- 
  }
- 
  fog /= 10;
- 
  fog  =
saturate( fog * density );
- 
  return fog;
- 
}
- 
fixed4 _FogColor;
- 
sampler2D _CameraDepthTexture;
- 
uniform float4 FogParam;
- 
struct v2f {
- 
    float4
pos : SV_POSITION;
- 
    float3
view : TEXCOORD0;
- 
    float4
projPos : TEXCOORD1;
- 
};
- 
v2f vert (appdata_base v)
- 
{
- 
    v2f
o;
- 
    float4
wPos = mul (_Object2World, v.vertex);
- 
    o.pos
= mul (UNITY_MATRIX_MVP, v.vertex);
- 
    o.view
= wPos.xyz - _WorldSpaceCameraPos;
- 
    o.projPos
= ComputeScreenPos (o.pos);
- 
    //
move projected z to near plane if point is behind near plane
- 
    float
inFrontOf = ( o.pos.z / o.pos.w ) > 0;
- 
    o.pos.z
*= inFrontOf;
- 
    return
o;
- 
}
- 
half4 frag (v2f i) : COLOR
- 
{
- 
    half4
color = half4(1,1,1,1);
- 
    float
depth = LinearEyeDepth
(UNITY_SAMPLE_DEPTH(tex2Dproj(_CameraDepthTexture,
UNITY_PROJ_COORD(i.projPos))));
- 
    float
backDist = length(i.view);
- 
    float3
viewDir = normalize(i.view);
- 
    float
fog = CalcVolumeFogIntensity(FogParam.xyz, FogParam.w,
_WorldSpaceCameraPos, viewDir, backDist, depth,_FogColor.a);
- 
    
- 
    color.rgb
= _FogColor.rgb;
- 
    color.a
= fog;
- 
    return
color;
- 
}
- 
ENDCG
- 
        }
- 
    }
- 
}
- 
Fallback "VertexLit"
- 
}
 							
		 
						
		加载中,请稍候......