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 shaders: combine texture map+directional light+spheremap ?

Discussion in 'Shaders' started by hippocoder, Jul 31, 2011.

  1. hippocoder

    hippocoder

    Digital Ape

    Joined:
    Apr 11, 2010
    Posts:
    29,723
    Edit: my working shader which is at the bottom of this thread, will cost you five galactic space credits to use. We will collect this money via telepathy.

    Here is what I have so far for a sphere map, but I would like to blend the nice glossy sphere map over the underlying texture if possible, yet also be affected by directional lighting. The target is iOS and PC desktop. Speed is a concern of course, am I on the right track?

    Any tips for adding directional light and texture welcome. When I examined the docs and tried it myself I just came up with a dark mess :(


    Code (csharp):
    1. Shader "Mobile/EnvTexDir"
    2. {
    3.      Properties
    4.      {
    5.  
    6.         _EnvMap ("EnvMap", 2D) = "black" { TexGen SphereMap }
    7.      }
    8.  
    9.      SubShader
    10.      {
    11.         Lighting on
    12.         Tags {"Queue" = "Transparent"}
    13.  
    14.         Pass
    15.         {
    16.             Name "BASE"
    17.             Blend One One       // additive
    18.             BindChannels
    19.             {
    20.                 Bind "Vertex", vertex
    21.                 Bind "normal", normal
    22.             }
    23.  
    24.             SetTexture [_EnvMap]
    25.             {
    26.                 combine texture//*texture
    27.             }
    28.         }
    29.     }
    30. }
     
    Last edited: Sep 23, 2011
  2. Martin-Kraus

    Martin-Kraus

    Joined:
    Feb 18, 2011
    Posts:
    617
    Hmmmm. Do you want to add the color of the sphere map to the color of the lit texture, or do you want to alpha blend the color of the sphere map over the color of the lit texture? In the latter case: which alpha (i.e. opacity) do you want to use for the alpha blending?
     
  3. hippocoder

    hippocoder

    Digital Ape

    Joined:
    Apr 11, 2010
    Posts:
    29,723
    I want the sphere map to be add blend like it is now (black is transparent) and not use the alpha component at all (no alpha channel) if possible :)
     
  4. Martin-Kraus

    Martin-Kraus

    Joined:
    Feb 18, 2011
    Posts:
    617
    What about this
    Code (csharp):
    1.  
    2. Shader "Mobile/EnvTexDir"
    3. {
    4.      Properties
    5.      {
    6.         _Color ("Main Color", COLOR) = (1,1,1,1)
    7.         _EnvMap ("EnvMap", 2D) = "black" { TexGen SphereMap }
    8.      }
    9.  
    10.      SubShader
    11.      {
    12.         Lighting on
    13.         Tags {"Queue" = "Transparent"}
    14.  
    15.         Pass
    16.         {
    17.             Name "BASE"
    18.             Blend One One       // additive
    19.             BindChannels
    20.             {
    21.                 Bind "Vertex", vertex
    22.                 Bind "normal", normal
    23.             }
    24.             Material {
    25.                 Diffuse [_Color]
    26.                 Ambient [_Color]
    27.             }
    28.             SetTexture [_EnvMap]
    29.             {
    30.                 combine primary + texture
    31.             }
    32.         }
    33.     }
    34. }
     
  5. hippocoder

    hippocoder

    Digital Ape

    Joined:
    Apr 11, 2010
    Posts:
    29,723
    Hi Martin, thank you, but it does not work, with the env map showing and no texture. combined with the env map ;(
     
    Last edited: Aug 1, 2011
  6. Martin-Kraus

    Martin-Kraus

    Joined:
    Feb 18, 2011
    Posts:
    617
    Well, there was no texture in your shader apart from the environment map. You would need to specify another shader property for another surface texture and then use another SetTexture instruction. Is that what you want?
     
  7. hippocoder

    hippocoder

    Digital Ape

    Joined:
    Apr 11, 2010
    Posts:
    29,723
    My latest attempt (everything is washed out bright)

    Code (csharp):
    1. Shader "Mobile/EnvTexDir"
    2.  
    3. {
    4.  
    5.      Properties
    6.  
    7.      {
    8.  
    9.         _MainTex ("Texture", 2D) = ""
    10.  
    11.         _EnvMap ("EnvMap", 2D) = "black" { TexGen SphereMap }
    12.  
    13.         _Color ("Main Color", COLOR) = (1,1,1,1)
    14.  
    15.  
    16.  
    17.      }
    18.  
    19.  
    20.  
    21.      SubShader
    22.  
    23.      {
    24.  
    25.         Lighting on
    26.  
    27.         Tags {"Queue" = "Geometry"}
    28.  
    29.  
    30.  
    31.         Pass
    32.  
    33.         {
    34.  
    35.             Name "BASE"
    36.  
    37.            
    38.  
    39.             //Blend One One     // additive not needed?
    40.  
    41.            
    42.  
    43.             BindChannels
    44.  
    45.             {
    46.  
    47.                 Bind "Vertex", vertex
    48.  
    49.                 Bind "normal", normal
    50.  
    51.             }
    52.  
    53.             Material {
    54.  
    55.                 Diffuse [_Color]
    56.  
    57.                 Ambient [_Color]
    58.  
    59.             }
    60.  
    61.            
    62.  
    63.             //need to draw the texture, but blend over a shiny env map.
    64.  
    65.             //env map should add blend
    66.  
    67.             SetTexture [_MainTex]
    68.  
    69.             {
    70.  
    71.                 combine texture + primary
    72.  
    73.             }
    74.  
    75.         }
    76.  
    77.     }
    78.  
    79. }
     
  8. hippocoder

    hippocoder

    Digital Ape

    Joined:
    Apr 11, 2010
    Posts:
    29,723
    I dont need Blend One One do I? the object is meant to be opaque. it is for an env map on solid objects that are textured with directional lighting on phone.
     
  9. Martin-Kraus

    Martin-Kraus

    Joined:
    Feb 18, 2011
    Posts:
    617
    No, you don't need "Blend One One" for opaque geometry. Try this
    Code (csharp):
    1.  
    2. Shader "Mobile/EnvTexDir"
    3.  
    4. {
    5.  
    6.      Properties
    7.  
    8.      {
    9.  
    10.         _MainTex ("Texture", 2D) = ""
    11.  
    12.         _EnvMap ("EnvMap", 2D) = "black" { TexGen SphereMap }
    13.  
    14.         _Color ("Main Color", COLOR) = (1,1,1,1)
    15.  
    16.  
    17.  
    18.      }
    19.  
    20.  
    21.  
    22.      SubShader
    23.  
    24.      {
    25.  
    26.         Tags {"Queue" = "Geometry"}
    27.  
    28.         Lighting On
    29.  
    30.  
    31.  
    32.         Pass
    33.  
    34.         {
    35.  
    36.             Name "BASE"
    37.  
    38.             Material {
    39.  
    40.                 Diffuse [_Color]
    41.  
    42.                 Ambient [_Color]
    43.  
    44.             }
    45.  
    46.            
    47.  
    48.             //need to draw the texture, but blend over a shiny env map.
    49.  
    50.             //env map should add blend
    51.  
    52.             SetTexture [_MainTex]
    53.  
    54.             {
    55.  
    56.                 combine texture * primary
    57.  
    58.             }
    59.  
    60.             SetTexture [_EnvMap]
    61.  
    62.             {
    63.  
    64.                 combine previous + texture
    65.  
    66.             }
    67.  
    68.         }
    69.  
    70.     }
    71.  
    72. }
    73.  
    It works for me on Unity 3.4 for Windows. I removed the attribute binding, because I don't know what that is good for. Also: do you have any particular reason not to use a cube map?
     
  10. hippocoder

    hippocoder

    Digital Ape

    Joined:
    Apr 11, 2010
    Posts:
    29,723
    Cube map is more draw calls and slower, I would think, on iOs. Thank you for your kind assistance :)
     
  11. Martin-Kraus

    Martin-Kraus

    Joined:
    Feb 18, 2011
    Posts:
    617
    I don't think the number of draw calls is any different (it shouldn't be). I have no idea about the performance on iOS, but internally cube maps require two additional divisions. On the other hand, you might be able to use a smaller texture image resolution with cube maps (because of the smaller variation of resolution) which would improve cache performance.
     
  12. henkdawson

    henkdawson

    Joined:
    Feb 26, 2007
    Posts:
    18
    Hi hippocoder, I'm trying to create a similar shader. Have you made any progress with yours? I can't seem to get yours to work.
     
  13. dadako

    dadako

    Joined:
    Jul 17, 2010
    Posts:
    66
    can't get this to work either, 3 different threads on it now ;) (including my own)

    bug?
     
  14. hippocoder

    hippocoder

    Digital Ape

    Joined:
    Apr 11, 2010
    Posts:
    29,723
    Yeah I made my own in the end, lemmie hop on the mac...
     
  15. hippocoder

    hippocoder

    Digital Ape

    Joined:
    Apr 11, 2010
    Posts:
    29,723
    Texture will use alpha channel and be over the spheremap. I didn't manage to add in decent lighting so maybe you could :) but it's good enough.

    Remember spheremap needs to be fairly dark overall. As it's brightness = how much you see through it.

    Code (csharp):
    1. Shader "Mobile/Tex Glass"
    2. {
    3.     Properties
    4.     {
    5.         _MainTex ("Texture", 2D) = "white" { }
    6.         _EnvTex ("Reflection", 2D) = "black" { TexGen SphereMap}
    7.     }
    8.    
    9.     Category
    10.     {
    11.         Tags { "Queue"="Transparent" "IgnoreProjector"="True" "RenderType"="Transparent" }
    12.         Lighting Off ZWrite Off
    13.         Blend SrcAlpha OneMinusSrcColor
    14.            
    15.         SubShader
    16.         {
    17.             Pass
    18.             {
    19.                 SetTexture [_EnvTex]
    20.                 {
    21.                     combine texture //double
    22.                 }
    23.                 SetTexture [_MainTex]
    24.                 {
    25.                     combine texture lerp(texture) previous     
    26.                 }
    27.      
    28.             }
    29.         }
    30.     }
    31. }
     
  16. AcidArrow

    AcidArrow

    Joined:
    May 20, 2010
    Posts:
    11,630
    You just made me get a mental image of a hippo happily hopping around in a room trying to get to his shiny mac... :p
     
  17. dadako

    dadako

    Joined:
    Jul 17, 2010
    Posts:
    66
    Code (csharp):
    1. Shader "Mobile/EnvTexDir"
    2. {
    3.     Properties
    4.     {
    5.     _MainTex ("Texture", 2D) = ""
    6.     _EnvMap ("EnvMap", 2D) = "black" { TexGen SphereMap }
    7.     _Color ("Main Color", COLOR) = (1,1,1,1)
    8.     _Blend ("Blend", Range (0, 1)) = 0.5
    9.     }
    10.        
    11.     SubShader
    12.     {
    13.        
    14.     Tags {"Queue" = "Geometry"}
    15.     Lighting On
    16.  
    17.     Pass
    18.     {
    19.         Name "BASE"
    20.         Material
    21.         {
    22.         Diffuse [_Color]
    23.         Ambient [_Color]
    24.        
    25.         }
    26.  
    27.         SetTexture [_MainTex]
    28.             {
    29.             combine texture * primary
    30.             }
    31.        
    32.         SetTexture [_EnvMap]
    33.             {
    34.             combine previous + texture
    35.             constantColor (1, 1, 1, [_Blend])
    36.             }
    37.        
    38.         }
    39.     }
    40. }
    The above code does actually shown the texture beneath but it's very dark.

    My suggestion would be to add a blend slider to the properties, but I'm not experienced with shaders enough to know how to implement it in the SubShader.

    Code (csharp):
    1. Properties
    2.     {
    3.        
    4.         _MainTex ("Texture", 2D) = ""
    5.         _EnvMap ("EnvMap", 2D) = "black" { TexGen SphereMap }
    6.         _Color ("Main Color", COLOR) = (1,1,1,1)
    7.         [COLOR="red"]_Blend ("Blend", Range (0, 1)) = 0.5[/COLOR]
    8.     }
    with constantColor (1, 1, 1, [_Blend]) ?
     
  18. hippocoder

    hippocoder

    Digital Ape

    Joined:
    Apr 11, 2010
    Posts:
    29,723
    We're surprisingly agile yet aquatic. Did you check my updated one? it works fine, you control the env map's see-through via the env map's brightness, and use a standard texture with alpha to overlay.

    The pro's of course is its very fast on mobile, it doesn't do anything outlandish and it does it in a single pass.

    If you wanted a solid reflection instead (opaque) it would be faster, but you just need to mess with blends.
     
    Last edited: Sep 23, 2011
  19. dadako

    dadako

    Joined:
    Jul 17, 2010
    Posts:
    66
    This code creates screenshot 1. (ghost)

    Code (csharp):
    1. Shader "Mobile/Env_Diffuse_NoLight"
    2. {
    3.     Properties
    4.     {
    5.         _MainTex ("Texture", 2D) = "white" { }
    6.         _EnvTex ("Reflection", 2D) = "black" { TexGen SphereMap}
    7.     }
    8.    
    9.     Category
    10.     {
    11.         Tags { "Queue"="Transparent" "IgnoreProjector"="True" "RenderType"="Transparent" }
    12.         Lighting Off ZWrite Off
    13.         Blend SrcAlpha OneMinusSrcColor
    14.            
    15.         SubShader
    16.         {
    17.             Pass
    18.             {
    19.                 SetTexture [_EnvTex]
    20.                 {
    21.                     combine texture //double
    22.                 }
    23.                 SetTexture [_MainTex]
    24.                 {
    25.                     combine texture lerp(texture) previous     
    26.                 }
    27.      
    28.             }
    29.         }
    30.     }
    31. }
    This code creates screenshot 2: (env only)

    Code (csharp):
    1. Shader "Mobile/EnvTexDir"
    2. {
    3.     Properties
    4.     {
    5.     _MainTex ("Texture", 2D) = ""
    6.     _EnvMap ("EnvMap", 2D) = "black" { TexGen SphereMap }
    7.     _Color ("Main Color", COLOR) = (1,1,1,1)
    8.     }
    9.        
    10.     SubShader
    11.     {
    12.        
    13.     Tags {"Queue" = "Geometry"}
    14.     Lighting On
    15.  
    16.     Pass
    17.     {
    18.         Name "BASE"
    19.         Material
    20.         {
    21.         Diffuse [_Color]
    22.         Ambient [_Color]
    23.        
    24.         }
    25.  
    26.         SetTexture [_MainTex]
    27.             {
    28.             combine texture * primary
    29.             }
    30.        
    31.         SetTexture [_EnvMap]
    32.             {
    33.             combine previous + texture
    34.             }
    35.        
    36.         }
    37.     }
    38. }
     

    Attached Files:

    Last edited: Sep 23, 2011
  20. dadako

    dadako

    Joined:
    Jul 17, 2010
    Posts:
    66
    Another experiment, closer but no cigar. (object become see through, although env is now letting texture through)

    Code (csharp):
    1. Shader "Mobile/env"
    2. {
    3.     Properties
    4.     {
    5.         _Color ("Main Color", Color) = (1,1,1,1)
    6.         _MainTex ("Base (RGB)", 2D) = "black" {}
    7.         _envTex ("Env", 2D) = "black" { TexGen SphereMap }
    8.     }
    9.  
    10.     SubShader
    11.     {
    12.         Lighting On
    13.  
    14.         Pass
    15.         {
    16.             Name "BASE"
    17.             ZWrite Off
    18.             Material {
    19.                 Diffuse [_Color]
    20.                 Ambient [_Color]
    21.             }
    22.             SetTexture [_MainTex]
    23.         }
    24.  
    25.         Pass
    26.         {
    27.             Name "ENV"
    28.             ZWrite On
    29.             Blend One One
    30.  
    31.             BindChannels {
    32.                 Bind "Vertex", vertex
    33.                 Bind "normal", normal
    34.                 Bind "texcoord", texcoord // main uses 1st uv
    35.             }
    36.                        
    37.             SetTexture [_envTex] {
    38.                 combine texture, previous
    39.             }
    40.         }
    41.  
    42.  
    43.     }
    44. }
     

    Attached Files:

  21. dadako

    dadako

    Joined:
    Jul 17, 2010
    Posts:
    66
    Ah, I tried this as you prescribed but the only drawback is it makes the model become semi-transparent.

    Would be good for faint patterns in glass I guess.
     

    Attached Files:

    Last edited: Sep 23, 2011
  22. hippocoder

    hippocoder

    Digital Ape

    Joined:
    Apr 11, 2010
    Posts:
    29,723
    no... the texture for env map is wrong, the env map needs to be really dull and dark, its for reflective glass, like what you see on a TV screen, and the alpha texture is for marks on the surface of the glass :)

    In that respect it works perfectly (with the right textutes) - its not meant for a solid reflective. To get a solid reflective you need to have the texture in the first texture unit and the env map in the last texture unit, with a lerp for how much it's shown, this shader I did isn't designed for that. Should be easy enough to poke about and make just by modding the shader. Need to kinda remove the blendmode thing to make it solid.
     
  23. dadako

    dadako

    Joined:
    Jul 17, 2010
    Posts:
    66
    nice!!

    Code (csharp):
    1.  
    2. Shader "Mobile/Tex&Env"
    3. {
    4.     Properties
    5.     {
    6.         _Color ("Main Color", Color) = (1,1,1,1)
    7.         _MainTex ("Texture", 2D) = "white" { }
    8.         _EnvTex ("Reflection", 2D) = "black" { TexGen SphereMap}
    9.     }
    10.    
    11.     Category
    12.     {
    13.         Lighting Off ZWrite On
    14.            
    15.         SubShader
    16.         {
    17.             Pass
    18.             {
    19.                
    20.                 SetTexture [_EnvTex]
    21.                 {
    22.                     combine texture //double
    23.                 }
    24.                 SetTexture [_MainTex]
    25.                 {
    26.                     combine texture lerp(texture) previous
    27.                        
    28.                 }
    29.             }
    30.         }
    31.     }
    32. }
    33.  
    As I say, there's several threads on this, all with dead ends.
    I guess what people are after is a nice "plastic" effect, or "polished wood". Shame Unity doesn't come with this kind of Env shader.

    Modified the above to light the texture beneath but with the right alpha levels on the texture, it does the job. Cheers.

    May try the original to make some cracked glass ;)

    I'm sure one day someone will come up with a solid reflective shader for iOS and we can stop pulling our hair out.
     

    Attached Files:

    Last edited: Sep 23, 2011
  24. antenna-tree

    antenna-tree

    Joined:
    Oct 30, 2005
    Posts:
    5,324
    There are several types of cubemap reflective shaders optimized for mobile in the AngryBots demo. The only catch is that most of them have no realtime lighting as they use lightmaps. However the enemies and main character have reflective cubemap shaders that accept realtime lighting.
     
  25. namoricoo

    namoricoo

    Joined:
    Apr 14, 2011
    Posts:
    534
    Is there an easy way to modify this and turn the circle into clouds. I'm trying to make a cloud shader for my upcoming mobile game. I'm trying to do this because UniSky is not compatible with Mobile platforms. Any insight would be appreciated. If you could also put a link to a Unity package that would also be nice.
     
  26. hippocoder

    hippocoder

    Digital Ape

    Joined:
    Apr 11, 2010
    Posts:
    29,723
    I don't think this is in any way whatsoever, useful for making clouds. Thanks for the tip on mobile cube maps antenna, I'll take a peek out of curiosity.
     
  27. Acumen

    Acumen

    Joined:
    Nov 20, 2010
    Posts:
    1,041
    Hey could you guys help me out on this.
    When I try to use dadako's second example and apply a spherical map to the EnvMap slot, it has the nice reflective look but I can't see the inititial applied texture on the model.
    The way you guys described it, it should be the intention of these shaders to display the textured model and then overlay the spherical map on top of that, is that correct ?