Search Unity

_GrabTexture as fog

Discussion in 'Shaders' started by metervara, Sep 20, 2007.

  1. metervara

    metervara

    Joined:
    Jun 15, 2006
    Posts:
    203
    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):
    1. Fog {
    2.    Color [_FogColor]
    3.    Mode Linear Range [_Near], [_Far]
    4. }
    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):
    1. Fog {
    2.    Color [_GrabTexture]
    3.    Mode Linear Range [_Near], [_Far]
    4. }
    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
     
  2. Aras

    Aras

    Unity Technologies

    Joined:
    Nov 7, 2005
    Posts:
    4,770
    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.
     
  3. metervara

    metervara

    Joined:
    Jun 15, 2006
    Posts:
    203
    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
     
  4. Aras

    Aras

    Unity Technologies

    Joined:
    Nov 7, 2005
    Posts:
    4,770
    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.
     
  5. metervara

    metervara

    Joined:
    Jun 15, 2006
    Posts:
    203
    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):
    1. Shader "SC/Textured fog" {
    2.     Properties {
    3.         _Color ("Color", Color)  = (.5,.5,.5,.5)
    4.         _MainTex ("Main Texture (RGB) ", 2D) = "" {}
    5.         _FogColor ("Color", Color)  = (1,0,0,1) // fog color
    6.         _Near ("Near", Float) = 10
    7.         _Far ("Far", Float) = 20
    8.     }
    9.     SubShader {
    10.         Pass {
    11.    
    12.         CGPROGRAM
    13.         // profiles arbfp1
    14.         // vertex vert
    15.         // fragment frag
    16.         // fragmentoption ARB_fog_exp2
    17.         #include "UnityCG.cginc"
    18.        
    19.         float4 _Color;
    20.         float4 _FogColor;
    21.         float _Near;
    22.         float _Far;
    23.         sampler2D _MainTex : register(s0);
    24.        
    25.         struct v2f {
    26.             //V2F_POS_FOG;
    27.             float4 pos : POSITION;
    28.             float2  uv : TEXCOORD1;
    29.             float dist : TEXCOORD2;
    30.         };
    31.  
    32.         v2f vert (appdata_base v){
    33.             v2f o;
    34.            
    35.             o.pos = mul( glstate.matrix.mvp, v.vertex);
    36.             o.dist = o.pos.z;
    37.            
    38.             o.uv = TRANSFORM_UV(0);
    39.             return o;
    40.         }
    41.  
    42.         half4 frag (v2f i) : COLOR {
    43.             half4 texcol = tex2D( _MainTex, i.uv );
    44.            
    45.             float multi = (i.dist-_Near)/(_Far-_Near);
    46.             multi = clamp(multi,0,1);
    47.            
    48.             return lerp(texcol*_Color,_FogColor,multi);
    49.         }
    50.         ENDCG
    51.        
    52.         SetTexture [_MainTex] {}
    53.         }
    54.     }
    55. }
     
  6. Aras

    Aras

    Unity Technologies

    Joined:
    Nov 7, 2005
    Posts:
    4,770
    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).
     
  7. metervara

    metervara

    Joined:
    Jun 15, 2006
    Posts:
    203
    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):
    1. Shader "SC/Textured fog grab" {
    2.     Properties {
    3.         _Color ("Color", Color)  = (.5,.5,.5,.5)
    4.         _MainTex ("Main Texture (RGB) ", 2D) = "" {}
    5.         _Near ("Near", Float) = 10
    6.         _Far ("Far", Float) = 20
    7.     }
    8.     SubShader {
    9.        
    10.         GrabPass{}
    11.        
    12.         Pass {
    13.            
    14.         CGPROGRAM
    15.         // profiles arbfp1
    16.         // vertex vert
    17.         // fragment frag
    18.         // fragmentoption ARB_fog_exp2
    19.         #include "UnityCG.cginc"
    20.        
    21.         float4 _Color;
    22.         float _Near;
    23.         float _Far;
    24.        
    25.         sampler2D _MainTex : register(s1);
    26.         samplerRECT _GrabTexture : register(s0);
    27.        
    28.         struct v2f {
    29.             float4 pos : POSITION;
    30.             float4 uvgrab : TEXCOORD0;
    31.             float2 uv : TEXCOORD1;
    32.             float dist : TEXCOORD2;
    33.         };
    34.        
    35.         v2f vert (appdata_base v){
    36.             v2f o;
    37.            
    38.             o.pos = mul( glstate.matrix.mvp, v.vertex);
    39.             o.dist = o.pos.z;
    40.            
    41.             o.uv = TRANSFORM_UV(1);
    42.             o.uvgrab = mul(glstate.matrix.texture[0], v.vertex);
    43.             return o;
    44.         }
    45.  
    46.         half4 frag (v2f i) : COLOR {
    47.             half4 texcol = tex2D( _MainTex, i.uv );
    48.             half4 grabcol = texRECTproj( _GrabTexture, i.uvgrab );
    49.            
    50.             float multi = (i.dist-_Near)/(_Far-_Near);
    51.             multi = clamp(multi,0,1);
    52.            
    53.             return lerp(texcol,grabcol,multi);
    54.         }
    55.         ENDCG
    56.        
    57.             SetTexture [_GrabTexture] {}
    58.             SetTexture [_MainTex] {}
    59.         }
    60.     }
    61. }