Hi. I have a mesh terrain that I want to blend with the skybox (at a distance) so it looks like one seamless object. The idea is to apply fog with color that matches the skybox. To do that I thought the _GrabTexture would be ideal but I'm having trouble making it work as fog. If I use a color defined in the properties I get colored fog: Code (csharp): Fog { Color [_FogColor] Mode Linear Range [_Near], [_Far] } Using a GrabPass and then applying the _GrabTexture as fog only gives me the fog color defined in render settings. Is it not possible to assign a texture to the fog property? Code (csharp): Fog { Color [_GrabTexture] Mode Linear Range [_Near], [_Far] } My camera will never move close to the edge of my terrain (only orbit a static location) so I could of course just add an alpha channel that makes the edges transparent. But ideally I'd like the effect to be distance based from the camera. Something inside me also says that transparancy is more performance demanding than fog, is that true or am I way off here? Third possible sollution would be to create a cubemap with the same textures as the skybox and use that for fog color, but if the problem is that textures can't be used for fog this won't work either. If none of these options work I guess a fragment program is needed? thanks - Patrik
The fog that is built into the hardware is only a single color. If you want to manually apply fog texture, turn off the hardware fog and manually lerp towards your texture in the pixel shader based on whatever fog factor you want to use.
Hmm... So I guess 'fog factor' should be a value based on viewing distance to the pixel right? How do I get that value in the fragment program? /Patrik
It should be distance to the camera I guess. Usually for exponential fog the formula on "how much fog to blend in" is e raised to the power of (-density * distance). The distance is usually computed per vertex (o.pos.z, see PositionFog in UnityCG.cginc on how it's computed) and passed to pixel shader in vertex-to-fragment structure.
Having some problems with this... I've only managed to lerp between a texture and a color (both defined in the Property block) based on distance but I can't get it to work with _GrabTexture. My problem is that I don't know how to access the color value from the _GrabTexture in my fragment program. I've tried something like this without success: 1. added a GrabPass{} as the first thing in my subshader. 2. registered it in the CGPROGRAM: sampler2D _GrabTexture : register(s1); (this is all a mystery to me) 3. then tried getting the color from it in the fragment program: half4 grabcol = tex2D( _GrabTexture, i.uv ); (Should I use different uv's maybe...) ...but it doesn't work, grabcol is all black... What am I doing wrong? Here's the shader so far (Only lerping between _MainTex and _FogColor): Code (csharp): Shader "SC/Textured fog" { Properties { _Color ("Color", Color) = (.5,.5,.5,.5) _MainTex ("Main Texture (RGB) ", 2D) = "" {} _FogColor ("Color", Color) = (1,0,0,1) // fog color _Near ("Near", Float) = 10 _Far ("Far", Float) = 20 } SubShader { Pass { CGPROGRAM // profiles arbfp1 // vertex vert // fragment frag // fragmentoption ARB_fog_exp2 #include "UnityCG.cginc" float4 _Color; float4 _FogColor; float _Near; float _Far; sampler2D _MainTex : register(s0); struct v2f { //V2F_POS_FOG; float4 pos : POSITION; float2 uv : TEXCOORD1; float dist : TEXCOORD2; }; v2f vert (appdata_base v){ v2f o; o.pos = mul( glstate.matrix.mvp, v.vertex); o.dist = o.pos.z; o.uv = TRANSFORM_UV(0); return o; } half4 frag (v2f i) : COLOR { half4 texcol = tex2D( _MainTex, i.uv ); float multi = (i.dist-_Near)/(_Far-_Near); multi = clamp(multi,0,1); return lerp(texcol*_Color,_FogColor,multi); } ENDCG SetTexture [_MainTex] {} } } }
I guess you're missing a SetTexture[_GrabTexture] at the end. And yes, different UVs should be used, I think it's easiest to start from modifying the refractive glass shader (it generates all the required UVs).
Yes! It's working! Thanks for the help Aras. Not sure how usefull this is to anyone else, but here it is. I guess the best explanation is that it can make objects appear transparent at a distance... This one is a mystery to me: o.uvgrab = mul(glstate.matrix.texture[0], v.vertex);. Something similar is going on with this: TRANSFORM_UV(0). What does it do exactly? Transform uv's somehow? Do I really need to learn about matrices..? :? Code (csharp): Shader "SC/Textured fog grab" { Properties { _Color ("Color", Color) = (.5,.5,.5,.5) _MainTex ("Main Texture (RGB) ", 2D) = "" {} _Near ("Near", Float) = 10 _Far ("Far", Float) = 20 } SubShader { GrabPass{} Pass { CGPROGRAM // profiles arbfp1 // vertex vert // fragment frag // fragmentoption ARB_fog_exp2 #include "UnityCG.cginc" float4 _Color; float _Near; float _Far; sampler2D _MainTex : register(s1); samplerRECT _GrabTexture : register(s0); struct v2f { float4 pos : POSITION; float4 uvgrab : TEXCOORD0; float2 uv : TEXCOORD1; float dist : TEXCOORD2; }; v2f vert (appdata_base v){ v2f o; o.pos = mul( glstate.matrix.mvp, v.vertex); o.dist = o.pos.z; o.uv = TRANSFORM_UV(1); o.uvgrab = mul(glstate.matrix.texture[0], v.vertex); return o; } half4 frag (v2f i) : COLOR { half4 texcol = tex2D( _MainTex, i.uv ); half4 grabcol = texRECTproj( _GrabTexture, i.uvgrab ); float multi = (i.dist-_Near)/(_Far-_Near); multi = clamp(multi,0,1); return lerp(texcol,grabcol,multi); } ENDCG SetTexture [_GrabTexture] {} SetTexture [_MainTex] {} } } }