seems there has no this kind of shader, so i'm glad to share mine. what is volume fog? see these pictures below: out of the volume fog: inside the volume fog: it's a ideally solution to make part of your game world with fog. like this one: so, here is the shader: note that this shader only support sphere object, and you should pass the sphere's center to FogParam.xyz, and pass the sphere's radius to FogParam.w. And the example are included in Xffect Editor's Free Editon too. Code (csharp): 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" inline 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" } Code (csharp): using UnityEngine; using System.Collections; public class XftVolumeFogObject : MonoBehaviour { protected MeshRenderer FogObject; protected float Radius = 10f; public Material VolumFogMaterial; public Color FogColor = Color.white; void Awake() { FogObject = gameObject.GetComponent<MeshRenderer>(); if (FogObject == null) { Debug.LogError("Volume Fog Object must have a MeshRenderer Component!"); } } void OnEnable() { //Note: In forward lightning path, the depth texture is not automatically generated. if (Camera.main.depthTextureMode == DepthTextureMode.None) Camera.main.depthTextureMode = DepthTextureMode.Depth; } void Start() { FogObject.material = VolumFogMaterial; FogObject.material.SetColor("_FogColor", FogColor); Radius = (transform.localScale.x + transform.localScale.y + transform.localScale.z) / 6; FogObject.material.SetVector("FogParam", new Vector4(transform.position.x, transform.position.y, transform.position.z, Radius)); } void Update () { } }
You know, you can do it much simpler like this(I read the original hlsl paper in a german site but i dont remember the adress now): Its not very optimised as im posting here the very first draft and exact copy of the original paper, (Because i have the optimised one in a commercial pack) What you need to know is: P = Center of your sphere r = radius of your sphere This is just a simple no light fragment shader which only has the necessary fog math and a simple texture on the object. So, just copy the fog part into your surface shaders or anything else to make it fancier.
@aubergine: I just took a look at your shader, but i think it's not the same with mine. you know, the main problem for volume objects is sampling the fogs from distance, in your shader, the distance is calculated from vertex, it's very simple indeed, but the results is not good. anyway, thanks for your advice, it does need some optimization, i just translated it from my old HLSL shader.
I didnt really check yours carefully but it sure looks elegant. On my version; you can remove the worldposition calculation from the fog and do it in object space (P=0,0,0 and a radius of 1) and also remove the color factor as well. Add it to a spherical object and do some alpha blending and there you have your very fine spherical volume fog object for a very cheap price. As i said, its just the basic fog function there, its your job to make it look better.
I know this is an old thread, but I found it only recently when looking for a spherical fog solution. For reference, I created a modified version with somewhat different functionality. You can see it and download it in this thread if you want: http://forum.unity3d.com/threads/spherical-fog-shader-shared-project.269771/