Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  2. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

iOS Cloud Shader (Rim Alpha?)

Discussion in 'Shaders' started by Vancent, Oct 3, 2011.

  1. Vancent

    Vancent

    Joined:
    Oct 3, 2011
    Posts:
    6
    Hello, I'm trying to create a shader for the iOS to make meshes look like fluffy clouds. I'm pretty new to writing shaders for unity and have run into some trouble.

    My original idea was to combine a fresnel like alpha (rim alpha) with a cloud texture alpha to have the model fade out towards it's edges in fluffy lumps. I could not find a way to create a fresnel "rim light" effect however. At least not without getting into the more advanced surface shader stuff, which I'm under the impression won't work on iOS.

    Instead, to try and fake the rim alpha effect, I tried making a texture with a radial gradient and sphere mapping it to the model. This almost worked quite well, except it creates some ugly artifacts around the edges of the models:



    I would really appreciate some help with either some way of cleaning up those rendering artifacts or achieving the rim alpha effect I wanted. Here's the code for my current shader for the above picture:

    Code (csharp):
    1. Shader "Mobile/Custom/Cloud Shader" {
    2.     Properties {
    3.         _Color("Main Color", Color)= (1,1,1)
    4.         _MainTex ("Diffuse Color", 2D) = "white" {}
    5.         _AlphaTex ("Edge Alpha", 2D) = "white" {TexGen Spheremap}
    6.         _AlphaBlend ("Alpha", 2D) = "white" {TexGen SphereMap}
    7.     }
    8.     SubShader {
    9.         Blend SrcAlpha OneMinusSrcAlpha
    10.         Lighting On
    11.         Material {
    12.             Diffuse [_Color]
    13.             Ambient [_Color]
    14.         }
    15.         Tags {Queue = Transparent}
    16.         //Cull Off
    17.         Pass {
    18.             SetTexture[_MainTex] {Combine primary * texture Quad}
    19.             SetTexture[_AlphaTex] {Combine previous, texture alpha}
    20.             SetTexture[_AlphaBlend] {Combine previous, previous alpha * texture alpha Double}
    21.             SetTexture[_AlphaBlend] {Combine previous, previous alpha + texture alpha Double}
    22.         }
    23.     }
    24. }
    25.  
    26.  
     
  2. Jessy

    Jessy

    Joined:
    Jun 7, 2007
    Posts:
    7,325
    That impression is incorrect. Any iOS device that could handle your four texture stages can use GLSL. Work with the dot product of the view direction, and normal.
     
  3. Vancent

    Vancent

    Joined:
    Oct 3, 2011
    Posts:
    6
    I haven't tested the current shader on an actual iPhone yet, only in graphics emulation. I plan to reduce it down to two texture stages if I do end up using it.

    Good to know that the surface shader stuff can work with iOS, now I just have to learn how to write it...

    Also, thanks for those video tutorials you made. They're how I learned how to write shaders to begin with.
     
  4. Vancent

    Vancent

    Joined:
    Oct 3, 2011
    Posts:
    6
    Okay, wrote up a surface shader, mostly just copying from the Reference Manual.

    Code (csharp):
    1. Shader "Mobile/Custom/Cloud Shader CG" {
    2.     Properties {
    3.         _Color("Main Color", Color)= (1,1,1)
    4.         _MainTex ("Diffuse Color", 2D) = "white" {}
    5.         _RimTex ("Edge Alpha", 2D) = "white" {}
    6.         _RimPower ("Alpha Amount", Range(0,10)) = 3.5
    7.     }
    8.     SubShader {
    9.         Tags { "RenderType" = "Opaque" }
    10.         CGPROGRAM
    11.         #pragma surface surf Lambert alpha
    12.         struct Input {
    13.             float2 uv_MainTex;
    14.             float2 uv_RimTex;
    15.             float3 viewDir;
    16.         };
    17.         float4 _Color;
    18.         sampler2D _MainTex;
    19.         sampler2D _RimTex;
    20.         float _RimPower;
    21.         void surf (Input IN, inout SurfaceOutput o) {
    22.             o.Albedo = tex2D (_MainTex, IN.uv_MainTex).rgb * _Color.rgb;
    23.             half rim = saturate(dot (normalize(IN.viewDir), o.Normal));
    24.             half rim2 = 1.0 - rim;
    25.             o.Alpha = -tex2D (_RimTex, IN.uv_RimTex).rgb + (rim * _RimPower) - rim2;
    26.         }
    27.         ENDCG
    28.     }
    29.     Fallback "Diffuse"
    30. }

    It's looking great but for one problem. It's too transparent:


    I'm pretty sure that this is caused by my using alpha instead of alphatest, but I can't seem to get alphatest to work. I'm not sure how to use it. An explanation of how to use alphatest in surface shaders would be nice, or any other ideas on how I can get the visible area properly opaque?
     
  5. Vancent

    Vancent

    Joined:
    Oct 3, 2011
    Posts:
    6
    Okay, I've kind of figured out how to get alphatest to work. But it looks terrible with rough ugly pixelated edges, and the hard edges don't have that fluffy cloud feel. is there really no middle ground method available?
     
  6. hippocoder

    hippocoder

    Digital Ape

    Joined:
    Apr 11, 2010
    Posts:
    29,723
    I've got an idea. How about a toon outline that extrudes verts and fades the extrusion to zero alpha?
     
  7. Deleted User

    Deleted User

    Guest

    Why not use the albedo of the cloud as the primary alpha, and modulate it by the rim contribution, a little like this:
    Code (csharp):
    1.  
    2. Shader "Mobile/Custom/CloudShader" {
    3.     Properties {
    4.         _Color("Main Color", Color)= (1,1,1)
    5.         _MainTex ("Diffuse Color", 2D) = "white" {}
    6.         _RimColor("Rim Colour", Color)= (0,0,1)
    7.         _RimPower ("Alpha Amount", Range(0.5,8)) = 3.5
    8.         _AlphaMultiplier( "Alpha Multiplier" , Range( 0,8 )) = 2.0
    9.     }
    10.     SubShader {
    11.         Tags { "Queue"="Transparent" "RenderType"="Opaque" }
    12.         CGPROGRAM
    13.         #pragma surface surf Lambert alpha
    14.        
    15.         struct Input {
    16.             float2 uv_MainTex;
    17.             float3 viewDir;
    18.         };
    19.        
    20.         float4 _Color;
    21.         float4 _RimColour;
    22.         sampler2D _MainTex;
    23.         float _RimPower;
    24.         float _AlphaMultiplier;
    25.        
    26.         void surf (Input IN, inout SurfaceOutput o) {
    27.             o.Albedo = tex2D (_MainTex, IN.uv_MainTex).rgb * _Color.rgb;
    28.             half VN = saturate(dot (normalize(IN.viewDir), o.Normal));
    29.             half rim = pow (1.0f - VN, _RimPower);
    30.             o.Alpha = o.Albedo.r - (rim * _AlphaMultiplier);
    31.             o.Albedo += rim * _RimColour;
    32.         }
    33.         ENDCG
    34.     }
    35.  
    36.     FallBack "Diffuse"
    37. }
    38.  
    Note that I've also moved it into the "Transparent" queue, so it gets drawn after everything else. This is a quickly knocked together example:

    Also, don't use AlphaTest on iOS, it's known to have a drastic effect on performance.
     
  8. Vancent

    Vancent

    Joined:
    Oct 3, 2011
    Posts:
    6
    Ah ha! Transparent queue! Now I feel dumb for not realizing that...

    Thank you very much, gaustwick, all my problems are solved.
     
  9. Frankov

    Frankov

    Joined:
    Apr 30, 2013
    Posts:
    10
    I'm trying to achieve exactly the opposite for a simple ghost shader.

    Right now, if I change the main color alpha, the rim also fades, I'd like it to be linked to the rim color alpha.

    Here's the code :
    Code (csharp):
    1.  
    2. Shader "RimAlpha" {
    3.     Properties {
    4.         _Color ("Main Color", Color) = (1,1,1,1)
    5.         _MainAlpha ("Main Alpha", Range(0.0,1.0)) = 1.0
    6.         _RimColor ("Rim Color", Color) = (0.26,0.19,0.16,0.0)
    7.         _RimPower ("Rim Power", Range(0.5,8.0)) = 3.0
    8.     }
    9.    
    10.     SubShader {
    11.        
    12.             Tags { "Queue"="Transparent" "RenderType"="Transparent" }
    13.            
    14.             CGPROGRAM
    15.            
    16.             #pragma surface surf Lambert alpha
    17.            
    18.             struct Input {
    19.                 float3 _Color;
    20.                 float3 viewDir;
    21.             };
    22.            
    23.             float4 _Color;
    24.             float4 _RimColor;
    25.             float _RimPower;
    26.             float _MainAlpha;
    27.            
    28.             void surf (Input IN, inout SurfaceOutput o) {
    29.                
    30.                 o.Albedo = _Color;
    31.                
    32.                 half rim = 1.0 - saturate(dot (normalize(IN.viewDir), o.Normal));
    33.                 o.Emission = _RimColor.rgb * pow (rim, _RimPower);
    34.                
    35.                 o.Alpha = _MainAlpha;
    36.             }
    37.            
    38.             ENDCG
    39.            
    40.     }
    41.    
    42.     FallBack "Diffuse"
    43. }
    44.  
    Can't figure out how to add the Rim in a separate pass (new to shaders). Any explanation is welcome !
     
  10. thestrandedmoose

    thestrandedmoose

    Joined:
    Jul 21, 2015
    Posts:
    70
    Hey all, I really love the look of this shader, but I need it to work from all angles. Is there a way to achieve this?
     
  11. brownboot67

    brownboot67

    Joined:
    Jan 5, 2013
    Posts:
    375
    What doesn't work from "all angles"?
     
  12. thestrandedmoose

    thestrandedmoose

    Joined:
    Jul 21, 2015
    Posts:
    70
    Sorry I guess it's not 100% clear what I'm getting at..

    Angle 1:
    https://i.imgur.com/1j0UebI.png

    Angle 2:
    https://imgur.com/QU995uC

    In other words, is there a solution which will always keep the edges faded, regardless of where the camera is? Because if I spin around this one, it develops a hard edge at any other angle than head on
     
  13. marcrem

    marcrem

    Joined:
    Oct 13, 2016
    Posts:
    340
    Did you find a way?
     
    thestrandedmoose likes this.
  14. thestrandedmoose

    thestrandedmoose

    Joined:
    Jul 21, 2015
    Posts:
    70
    Prodigga likes this.
  15. Prodigga

    Prodigga

    Joined:
    Apr 13, 2011
    Posts:
    1,123
    Looks awesome!