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

Soap bubble shader

Discussion in 'Shaders' started by litebox, Apr 22, 2013.

  1. litebox

    litebox

    Joined:
    Aug 29, 2011
    Posts:
    158
    Hi all.
    I try to achieve soap bubble material for Unity 3.5 (not pro);
    I found nice shader Shield (http://wiki.unity3d.com/index.php/Shield), but it doesn't support cube map and highlights from lights (directional light). I also found shader Glass Reflective (http://wiki.unity3d.com/index.php/Glass_Shader).
    So I try to merge both shaders into one.

    Code (csharp):
    1.  
    2. Shader "Bubble"
    3. {
    4.     Properties
    5.     {
    6.         _Color("_Color", Color) = (0.0,1.0,0.0,1.0)
    7.         _Inside("_Inside", Range(0.0,2.0) ) = 0.0
    8.         _Rim("_Rim", Range(0.0,2.0) ) = 1.2
    9.         _Texture("_Texture", 2D) = "white" {}
    10.         _Speed("_Speed", Range(0.5,5.0) ) = 0.5
    11.         _Tile("_Tile", Range(1.0,10.0) ) = 5.0
    12.         _Strength("_Strength", Range(0.0,5.0) ) = 1.5
    13.        
    14.         _Cube ("Reflection Cubemap", Cube) = "black" { TexGen CubeReflect }
    15.     }
    16.    
    17.     SubShader
    18.     {
    19.         Tags
    20.         {
    21.             "Queue"="Transparent"
    22.             "IgnoreProjector"="True"
    23.             "RenderType"="Transparent"
    24.    
    25.         }
    26.    
    27.         Cull Back
    28.         ZWrite On
    29.         ZTest LEqual
    30.        
    31.        
    32.         CGPROGRAM
    33.         #pragma surface surf BlinnPhongEditor alpha vertex:vert
    34.         //#pragma target 3.0
    35.        
    36.        
    37.         fixed4 _Color;
    38.         sampler2D _CameraDepthTexture;
    39.         fixed _Inside;
    40.         fixed _Rim;
    41.         sampler2D _Texture;
    42.         fixed _Speed;
    43.         fixed _Tile;
    44.         fixed _Strength;
    45.        
    46.         samplerCUBE _Cube;
    47.        
    48.         fixed4 _ReflectColor;
    49.         half _Shininess;
    50.        
    51.         struct EditorSurfaceOutput
    52.         {
    53.             half3 Albedo;
    54.             half3 Normal;
    55.             half3 Emission;
    56.             half3 Gloss;
    57.             half Specular;
    58.             half Alpha;
    59.            
    60.             half Custom;
    61.         };
    62.                    
    63.         inline half4 LightingBlinnPhongEditor_PrePass (EditorSurfaceOutput s, half4 light)
    64.         {
    65.             half3 spec = light.a * s.Gloss;
    66.            
    67.             half4 c;
    68.            
    69.             c.rgb = (s.Albedo * light.rgb + light.rgb * spec);
    70.            
    71.             c.a = s.Alpha + Luminance(spec);
    72.            
    73.             return c;
    74.         }
    75.        
    76.         inline half4 LightingBlinnPhongEditor (EditorSurfaceOutput s, half3 lightDir, half3 viewDir, half atten)
    77.         {
    78.             viewDir = normalize(viewDir);
    79.             half3 h = normalize (lightDir + viewDir);
    80.            
    81.             half diff = max (0, dot (s.Normal, lightDir));
    82.            
    83.             float nh = max (0, dot (s.Normal, h));
    84.             float3 spec = pow (nh, s.Specular*128.0) * s.Gloss;
    85.            
    86.             half4 res;
    87.             res.rgb = _LightColor0.rgb * (diff * atten * 2.0);
    88.             res.w = spec * Luminance (_LightColor0.rgb);
    89.        
    90.             return LightingBlinnPhongEditor_PrePass( s, res );
    91.         }
    92.        
    93.         struct Input
    94.         {
    95.             float4 screenPos;
    96.             float3 viewDir;
    97.             float2 uv_Texture;
    98.            
    99.             float3 worldRefl;
    100.         };
    101.        
    102.         void vert (inout appdata_full v, out Input o)
    103.         {
    104.             o.worldRefl = float3(0.3,0.3,0.3);
    105.         }
    106.        
    107.         void surf (Input IN, inout EditorSurfaceOutput o)
    108.         {
    109.             o.Albedo = fixed3(0.0,0.0,0.0);
    110.             o.Normal = fixed3(0.0,0.0,1.0);
    111.             o.Emission = 0.0;
    112.             o.Gloss = 0.0;
    113.             o.Specular = 0.0;
    114.             o.Alpha = 1.0;
    115.             float4 ScreenDepthDiff0= LinearEyeDepth (tex2Dproj(_CameraDepthTexture, UNITY_PROJ_COORD(IN.screenPos)).r) - IN.screenPos.z;
    116.             float4 Saturate0=fixed4(0.3,0.3,0.3,1.0);//
    117.             float4 Fresnel0_1_NoInput = fixed4(0,0,1,1);
    118.             float4 Fresnel0=float4( 1.0 - dot( normalize( float4(IN.viewDir, 1.0).xyz), normalize( Fresnel0_1_NoInput.xyz ) ) );
    119.             float4 Step0=step(Fresnel0,float4( 1.0 ));
    120.             float4 Clamp0=clamp(Step0,_Inside.xxxx,float4( 1.0 ));
    121.             float4 Pow0=pow(Fresnel0,_Rim.xxxx);
    122.             float4 Multiply5=_Time * _Speed.xxxx;
    123.             float4 UV_Pan0=float4((IN.uv_Texture.xyxy).x,(IN.uv_Texture.xyxy).y + Multiply5.x,(IN.uv_Texture.xyxy).z,(IN.uv_Texture.xyxy).w);
    124.             float4 Multiply1=UV_Pan0 * _Tile.xxxx;
    125.             float4 Tex2D0=tex2D(_Texture,Multiply1.xy);
    126.             float4 Multiply2=Tex2D0 * _Strength.xxxx;
    127.             float4 Multiply0=Pow0 * Multiply2;
    128.             float4 Multiply3=Clamp0 * Multiply0;
    129.             float4 Multiply4=Saturate0 * Multiply3;
    130.             //o.Emission = Multiply3.xyz * _Color.rgb; - original shader
    131.             //o.Alpha =  Multiply3.w * _Color.a;
    132.            
    133.             // I added this cube map calculations
    134.             fixed4 reflcol = texCUBE (_Cube, IN.worldRefl);
    135.             o.Emission = reflcol.rgb;// * _ReflectColor.rgb;
    136.             o.Alpha = reflcol.a;
    137.            
    138.        
    139.         }
    140.         ENDCG
    141.     }
    142.    
    143.     Fallback "Diffuse"
    144. }
    When I add only line
    Code (csharp):
    1.  
    2. fixed4 reflcol = texCUBE (_Cube, IN.worldRefl);
    all is ok - no errors, but when I try to use refcol result for o.Alpha I get error "Shader error in 'Bubble': Too many texture interpolators would be used for ForwardBase pass at line 31" and if I try to use refcol result for o.Emission I get several errors:
    Shader error in 'Bubble': GLSL vertex shader: ERROR: 0:488: 'TtoW0' : no such field in structure at line 31
    Shader error in 'Bubble': Program 'frag_surf', expression left of ."TtoW0" is not a struct or array at line 211
    Keywords: DIRECTIONAL, LIGHTMAP_OFF, DIRLIGHTMAP_OFF

    Any suggestions how to make it work?

    Thanks.
     
    FABRICIO-RONISON likes this.
  2. litebox

    litebox

    Joined:
    Aug 29, 2011
    Posts:
    158
    the problem was I used Normal
     
  3. Torigas

    Torigas

    Joined:
    Jan 1, 2014
    Posts:
    63
    Sorry for necroing the thread.

    I'm trying to get that Shader to work on DirectX 11.
    So far so good - the shield part works.

    However it seems the texCUBE macro doesn't work anymore.
    Any way I could fix that?

    EDIT: Fixed code. I guess part of the issue was the old BlinnPhongEditor stuff. It works now and looks quite decent with a little texture.

    Also added a unitypackage with a textured bubble y'all can use.

    Code (csharp):
    1. Shader "Bubble"
    2. {
    3.     //http://forum.unity3d.com/threads/179374-Soap-bubble-shader
    4.     Properties
    5.     {
    6.         _Color("_Color", Color) = (0.0,1.0,0.0,1.0)
    7.         _Inside("_Inside", Range(0.0,2.0) ) = 0.0
    8.         _Rim("_Rim", Range(0.0,2.0) ) = 1.2
    9.         _Texture("_Texture", 2D) = "white" {
    10.             }
    11.         _Speed("_Speed", Range(0.5,5.0) ) = 0.5
    12.         _Tile("_Tile", Range(1.0,10.0) ) = 5.0
    13.         _Strength("_Strength", Range(0.0,5.0) ) = 1.5
    14.         //_Cube ("Reflection Cubemap", Cube) = "black" {TexGen CubeReflect }
    15.         _Cube ("Cubemap", Cube) = "" {}
    16.     }
    17.     SubShader
    18.     {
    19.         Tags
    20.         {
    21.             "Queue"="Transparent"
    22.             "IgnoreProjector"="True"
    23.             "RenderType"="Transparent"  
    24.         }
    25.         Cull Back
    26.         ZWrite On
    27.         ZTest LEqual
    28.  
    29.         CGPROGRAM
    30.         //#pragma surface surf BlinnPhongEditor alpha vertex:vert
    31.         #pragma surface surf BlinnPhong alpha
    32.         #pragma target 3.0
    33.  
    34.         fixed4 _Color;
    35.         sampler2D _CameraDepthTexture;
    36.         fixed _Inside;
    37.         fixed _Rim;
    38.         sampler2D _Texture;
    39.         fixed _Speed;
    40.         fixed _Tile;
    41.         fixed _Strength;
    42.         samplerCUBE _Cube;
    43.         fixed4 _ReflectColor;
    44.         half _Shininess;
    45.  
    46.         //struct SurfaceOutput
    47.         //{
    48.         //    half3 Albedo;
    49.         //    half3 Normal;
    50.         //    half3 Emission;
    51.         //    half3 Gloss;
    52.         //    half Specular;
    53.         //    half Alpha;
    54.         //    half Custom;
    55.         //};
    56.         inline half4 LightingBlinnPhongEditor_PrePass (SurfaceOutput s, half4 light)
    57.         {
    58.             half3 spec = light.a * s.Gloss;
    59.             half4 c = half4(0,0,0,0);
    60.             c.rgb = (s.Albedo * light.rgb + light.rgb * spec);
    61.             c.a = s.Alpha + Luminance(spec);
    62.             return c;
    63.         }
    64.         inline half4 LightingBlinnPhongEditor (SurfaceOutput s, half3 lightDir, half3 viewDir, half atten)
    65.         {
    66.             viewDir = normalize(viewDir);
    67.             half3 h = normalize (lightDir + viewDir);
    68.             half diff = max (0, dot (s.Normal, lightDir));
    69.             float nh = max (0, dot (s.Normal, h));
    70.             float3 spec = pow (nh, s.Specular*128.0) * s.Gloss;
    71.             half4 res;
    72.             res.rgb = _LightColor0.rgb * (diff * atten * 2.0);
    73.             res.w = spec * Luminance (_LightColor0.rgb);
    74.             return LightingBlinnPhongEditor_PrePass( s, res );
    75.         }
    76.  
    77.         struct Input
    78.         {
    79.             float4 screenPos;
    80.             float3 viewDir;
    81.             float2 uv_Texture;
    82.             float3 worldRefl;
    83.             INTERNAL_DATA
    84.         };
    85.         void vert (inout appdata_full v, out Input o)
    86.         {
    87.             o.screenPos = v.vertex;
    88.             o.viewDir = v.normal;
    89.             o.uv_Texture = v.texcoord;
    90.             o.worldRefl = float3(0.3,0.3,0.3);
    91.         }
    92.         void surf (Input IN, inout SurfaceOutput o)
    93.         {
    94.             o.Albedo = fixed3(0.0,0.0,0.0);
    95.             o.Normal = fixed3(0.0,0.0,1.0);
    96.             o.Emission = 0.0;
    97.             o.Gloss = 0.0;
    98.             o.Specular = 0.0;
    99.             o.Alpha = 1.0;
    100.             float4 ScreenDepthDiff0= LinearEyeDepth (tex2Dproj(_CameraDepthTexture, UNITY_PROJ_COORD(IN.screenPos)).r) - IN.screenPos.z;
    101.             //float4 ScreenDepthDiff0= float4(1.0,1.0,1.0,1.0);
    102.             float4 Saturate0=fixed4(0.3,0.3,0.3,1.0);
    103.             float4 Fresnel0_1_NoInput = fixed4(0,0,1.0,1.0);
    104.             //float f=1.0 - dot( normalize( float4(IN.viewDir, 1.0).xyz), normalize( Fresnel0_1_NoInput.xyz ) );
    105.             float f = 1.0 - dot( normalize( IN.viewDir ), normalize( Fresnel0_1_NoInput.xyz ) );
    106.             float4 Fresnel0=float4( f,f,f,f );
    107.             float4 Step0=step(Fresnel0,float4( 1.0,1.0,1.0,1.0 ));
    108.             float4 Clamp0=clamp(Step0,_Inside.xxxx,float4( 1.0,1.0,1.0,1.0 ));
    109.             float4 Pow0=pow(Fresnel0,_Rim.xxxx);
    110.             float4 Multiply5=_Time * _Speed.xxxx;
    111.             float4 UV_Pan0=float4((IN.uv_Texture.xyxy).x,(IN.uv_Texture.xyxy).y + Multiply5.x,(IN.uv_Texture.xyxy).z,(IN.uv_Texture.xyxy).w);
    112.             float4 Multiply1=UV_Pan0 * _Tile.xxxx;
    113.             float4 Tex2D0=tex2D(_Texture,Multiply1.xy);
    114.             float4 Multiply2=Tex2D0 * _Strength.xxxx;
    115.             float4 Multiply0=Pow0 * Multiply2;
    116.             float4 Multiply3=Clamp0 * Multiply0;
    117.             float4 Multiply4=Saturate0 * Multiply3;
    118.  
    119.             //o.Emission = Multiply3.xyz * _Color.rgb;
    120.             //o.Emission = texCUBE(_Cube, IN.worldRefl).xyz;
    121.             o.Alpha =  Multiply3.w * _Color.a;
    122.             o.Emission = Multiply3.xyz * _Color.rgb * texCUBE(_Cube, IN.worldRefl).xyz;
    123.             //o.Alpha = texCUBE(_Cube, IN.worldRefl).w;
    124.             #ifdef SHADER_API_D3D11
    125.             ////these lines work:
    126.            
    127.             //#else
    128.             ////these lines kill:
    129.            
    130.             #endif
    131.        
    132.             o.Albedo = 1;
    133.            
    134.         }
    135.         ENDCG
    136.  
    137.     }
    138.     //Fallback "Diffuse"
    139. }
    140.  
    141.  
     

    Attached Files:

    Last edited: Feb 25, 2014
  4. listener

    listener

    Joined:
    Apr 2, 2012
    Posts:
    187
    Will this work on mobile platform?
     
  5. Mikea15

    Mikea15

    Joined:
    Sep 20, 2012
    Posts:
    93
    This is actually pretty nice.. :) Thanks
     
  6. Pthorndycraft

    Pthorndycraft

    Joined:
    Feb 27, 2014
    Posts:
    2
    Really nice shader, thank you for sharing!
     
  7. orisil

    orisil

    Joined:
    Oct 11, 2017
    Posts:
    4
    How do I use it?
    Where do I create a new Shader and attach this code??
     
  8. LarryTheBrave

    LarryTheBrave

    Joined:
    Nov 20, 2016
    Posts:
    24
    A dear friend of mine suggested that I create a SOAP bubble generator in my Augmented Reality experiments. I think it would be a cool APP to have a virtual bubble generator. If you can get this to be usable in ARCore then it can be done.
     
  9. jgwinner

    jgwinner

    Joined:
    Dec 21, 2016
    Posts:
    19
    I'm checking this with the regular renderer (not the LWRP), and I'm getting a division by 0.

    Shader warning in 'Bubble': floating point division by zero at line 100 (on d3d11)

    Compiling Fragment program with UNITY_PASS_FORWARDBASE DIRECTIONAL
    Platform defines: UNITY_ENABLE_REFLECTION_BUFFERS UNITY_USE_DITHER_MASK_FOR_ALPHABLENDED_SHADOWS UNITY_PBS_USE_BRDF1 UNITY_SPECCUBE_BOX_PROJECTION UNITY_SPECCUBE_BLENDING UNITY_ENABLE_DETAIL_NORMALMAP SHADER_API_DESKTOP UNITY_LIGHT_PROBE_PROXY_VOLUME UNITY_LIGHTMAP_FULL_HDR


    Looks like it's this line:
    Code (CSharp):
    1.  float4 ScreenDepthDiff0= LinearEyeDepth (tex2Dproj(_CameraDepthTexture, UNITY_PROJ_COORD(IN.screenPos)).r) - IN.screenPos.z;
    Is this a problem with VR rendering?

    == John ==