Search Unity

Masking off certian portions

Discussion in 'Immediate Mode GUI (IMGUI)' started by Ablaze, Aug 8, 2009.

  1. Ablaze

    Ablaze

    Joined:
    Jul 27, 2009
    Posts:
    11
    I'm trying to make a round minimap which, so far as I can tell, will require getting a subset of my large map to display on the screen and then masking off the edges of that square map to make it round. Is there a way to apply an overlay to a texture that will modify that texture's alpha channel on a per pixel basis?

    Also, if there's a simpler way I'm very open to hearing about that as well.
     
  2. Ablaze

    Ablaze

    Joined:
    Jul 27, 2009
    Posts:
    11
    I've been looking around for two days now and I can't find a single reference to this sort of functionality anywhere, and I can't imagine why.
     
  3. Dreamora

    Dreamora

    Joined:
    Apr 5, 2008
    Posts:
    26,601
    There is no way to do that unless you write your own system.
    The images are used as they are without any option to modify them before beeing shown on screen.
     
  4. Ablaze

    Ablaze

    Joined:
    Jul 27, 2009
    Posts:
    11
    Well, I did find this thread but I'm not sure if it is possible to apply a shader to a GUIObject. Anyone know?
     
  5. Dreamora

    Dreamora

    Joined:
    Apr 5, 2008
    Posts:
    26,601
    Easiest is to try so.

    For GUI.xxx you definitely can't as they are no game objects or even objects at all
     
  6. Ablaze

    Ablaze

    Joined:
    Jul 27, 2009
    Posts:
    11
    After much reading and a good deal of experimentation I have managed to make a shader that can be applied to a texture on a plane. That plane can then be put in front of an orthographic camera.. ect. ect.

    So my question is this: Can anyone tell me how to improve my shader so that I can use a gradient of transparency? Currently, because of AlphaTest, I can only define a visible section and a not visible section, with no partial visibility in between.

    Also, am I correct in assuming that this shader would be compatible with all graphic cards?

    Code (csharp):
    1. Shader "Library/Cull Mask"
    2. {
    3.     Properties
    4.     {
    5.         _MainTex ("Base (RGB)", 2D) = "white" {}
    6.         _Mask ("Culling Mask", 2D) = "white" {}
    7.         _Cutoff ("Alpha cutoff", Range (0,1)) = 0.9
    8.  
    9.  
    10.     }
    11.     SubShader
    12.     {
    13.  
    14.       Blend One Zero
    15.       Pass
    16.       {
    17.         AlphaTest LEqual [_Cutoff]
    18.         SetTexture [_Mask] {combine texture}
    19.         SetTexture [_MainTex] {combine texture, previous}
    20.       }
    21.     }
    22. }
     
  7. tomvds

    tomvds

    Joined:
    Oct 10, 2008
    Posts:
    1,028
    Try this:

    Code (csharp):
    1. Shader "MaskedTexture"
    2. {
    3.     Properties
    4.     {
    5.         _MainTex ("Base (RGB)", 2D) = "white" {}
    6.         _Mask ("Culling Mask", 2D) = "white" {}
    7.         _Cutoff ("Alpha cutoff", Range (0,1)) = 0.1
    8.     }
    9.     SubShader
    10.     {
    11.         Tags {"Queue"="Transparent"}
    12.         ZWrite Off
    13.         Blend SrcAlpha OneMinusSrcAlpha
    14.         AlphaTest GEqual [_Cutoff]
    15.         Pass
    16.         {
    17.             SetTexture [_Mask] {combine texture}
    18.             SetTexture [_MainTex] {combine texture, previous}
    19.         }
    20.     }
    21. }
    Note that I flipped your cut-off, as you were using LEqual, which works opposite to conventional blending. This means you'll probably have to invert your test mask to work with this shader.
     
  8. Ablaze

    Ablaze

    Joined:
    Jul 27, 2009
    Posts:
    11
    Thanks tom. Most helpful. :) I turned off lighting as well and posted this to the wiki.
     
  9. MultimediaPlusGreg

    MultimediaPlusGreg

    Joined:
    Jul 15, 2009
    Posts:
    23
    I don't think this actually creates a helpful map. Sure, you can use it to mask off edges of a texture, but the mask is locked to that texture. Generally in games, the circle crops only a portion of the map that you're currently in and the map moves as you move. With this technique, there's no way to move the map independent of it's mask. Am I missing something?
     
  10. andeeeee

    andeeeee

    Joined:
    Jul 19, 2005
    Posts:
    8,768
    It depends how the map is created. If it is generated from an overhead view using a render texture, then this would be exactly what you want.
     
  11. MultimediaPlusGreg

    MultimediaPlusGreg

    Joined:
    Jul 15, 2009
    Posts:
    23
    Unfortunately, I'm not. I'm using a Grand Theft Auto/Assassin's Creed style graphical map with icons. What I have been working with (unsuccessfully) was to combine the CullAll shader with this shader. My idea is to make a texture that's essentially an "invisible hole." I have the culling functionality, working to knock out everything behind, outside of my hole, with the texture cropped within the circle. This is my existing shader code:

    Code (csharp):
    1. Shader "MaskedTexture"
    2. {
    3.     Properties
    4.     {
    5.         _MainTex ("Base (RGB) Trans (A)", 2D) = "white" {}
    6.         _Mask ("Culling Mask", 2D) = "white" {}
    7.         _Cutoff ("Alpha cutoff", Range (0,1)) = 0.1
    8.     }
    9.     SubShader
    10.     {
    11.         Tags {"Queue"="Background"}
    12.         Lighting Off
    13.         ZTest Always
    14.         ZWrite Off
    15.         AlphaTest GEqual [_Cutoff]
    16.         Blend SrcAlpha OneMinusSrcAlpha
    17.         Pass
    18.         {
    19.             SetTexture [_Mask] {combine texture}
    20.             SetTexture [_MainTex] {combine texture, previous}
    21.         }
    22.     }
    23. }
    Now, the last element I need is for the _MainTex to take advantage of an alpha channel. So the resulting shader would be one that has a mask to cull everything that shouldn't be seen, while using a main texture with an alpha channel that would allow you to see through the hole to whatever is immediately beneath it. Does that make sense?

    I know very little about shaders and it took me the better part of a day just to get to this point. If anyone can create what I'm theorizing here, I think we'd have the ultimate solution to masked minimaps.[/quote]
     
    rakkarage likes this.
  12. MultimediaPlusGreg

    MultimediaPlusGreg

    Joined:
    Jul 15, 2009
    Posts:
    23
    Shader Noob Makes Good!

    I seem to have solved my issue. After a lot of experimentation and a little bit of blind luck, I've created a masking shader for minimaps and any other masking needs. This is not a GUI solution, but requires a separate camera and 2 texture planes, one for the mask, one for the map. This also does not require RenderTexture (which is only available to Pro users).

    Use this shader on your mask plane with a bitmap imported with format "Alpha 8" and "Build Alpha From Grayscale" selected.

    Code (csharp):
    1. Shader "TextureMask"
    2. {
    3.    Properties
    4.    {
    5.       _Mask ("Culling Mask", 2D) = "white" {}
    6.    }
    7.    SubShader
    8.    {
    9.         Tags {"Queue" = "Background"}
    10.         Blend SrcAlpha OneMinusSrcAlpha
    11.         Lighting Off
    12.         ZWrite On
    13.         ZTest Always
    14.         Alphatest LEqual 0
    15.         Pass
    16.         {
    17.             SetTexture [_Mask] {combine texture}
    18.         }
    19.    }
    20. }
    As I mentioned, I really don't know a whole lot about what was done here, so if it looks like there's any extraneous data here or something that can be improved, please let me know.
     
  13. spav1789

    spav1789

    Joined:
    Sep 13, 2010
    Posts:
    11
    Hey guys I've found this thread very helpful, unfortunately I think I'm doing something wrong. I have the same issue as MultimediaPlusGreg in that I want to have a circular minimap that is part of a larger map. So the way I've tried to do it was by using MPG's shader with this mask and then setting its coordinates to be the same as the camera except the Y position which is 1 in front of it:

    Mask:


    How it looks on the map


    The problem is that while it does mask off the corners, it still displays the masked off area. I'm using the normalized view port rect on the camera to display the minimap.



    Is this not correct or is there a way to not display the masked area in the view port rect?
     
  14. andeeeee

    andeeeee

    Joined:
    Jul 19, 2005
    Posts:
    8,768
    Try setting the minimap camera's clear flags to Depth Only in the inspector.
     
  15. spav1789

    spav1789

    Joined:
    Sep 13, 2010
    Posts:
    11
    It worked! Thanks for the help :)
     
  16. ddesmond

    ddesmond

    Joined:
    Feb 9, 2010
    Posts:
    163
    Hello,

    I am trying this and for some reason, even when I set my mini map camera clear flags to depth only, it doesn't make a difference. I have copied the shader used here and have a similar image I created in Photoshop elements. The transparency works, the only difference is that I am using the following code in a script to render the second camera:

    camera.pixelRect = Rect(fl_screen_width - fl_map_width, fl_screen_height - fl_map_height, fl_map_width, fl_map_height);

    . Any tips.

    thanks,
    Donald
     
    Last edited: Nov 25, 2010
  17. andeeeee

    andeeeee

    Joined:
    Jul 19, 2005
    Posts:
    8,768
    When you say it doesn't work, does the plane block out the minimap view altogether or do you just not see the mask image at all?
     
  18. ddesmond

    ddesmond

    Joined:
    Feb 9, 2010
    Posts:
    163
    Hi Andee,

    Thanks for responding, what I see the white part of the image, the black part is invisible. So I see see the rectangle region and I see the white circle and the black part is all invisible.

    Here are the camera settings (2 cameras):

    mini map camera
    depth = 2
    clear flags = solid color

    game camera
    depth = 1
    clear flags = depth only
     
    Last edited: Nov 25, 2010
  19. andeeeee

    andeeeee

    Joined:
    Jul 19, 2005
    Posts:
    8,768
    The minimap camera is the one that should have its clear flags set to depth only. The meaning of the setting is that the camera's background doesn't get cleared during the overlay, only its depth buffer.
     
  20. deepak

    deepak

    Joined:
    Aug 10, 2010
    Posts:
    44
    Hi I want to make an scrollable content and have to mask the content with a masker, so that the viewable area can be limited to a certain bounds. Can anyone suggest me how to do this. The basic idea is to have a panel with number of items and the viewable area size is limited to half of the screen size.

    Thanks in advance
     
  21. deepak

    deepak

    Joined:
    Aug 10, 2010
    Posts:
    44
    Hi I want to make an scrollable content and have to mask the content with a masker, so that the viewable area can be limited to a certain bounds. Can anyone suggest me how to do this. The basic idea is to have a panel with number of items and the viewable area size is limited to half of the screen size.

    Thanks in advance
     
  22. Airship

    Airship

    Joined:
    Sep 10, 2011
    Posts:
    260
    The shader posted by MultimediaMaxGreg works great!

    Is there anyway to make the alpha have a soft faded edge instead of a sharp alpha cutoff? This shader seems to do that even if the alpha texture has soft edges.


    Code (csharp):
    1. Shader "TextureMask"
    2. {
    3.    Properties
    4.    {
    5.       _Mask ("Culling Mask", 2D) = "white" {}
    6.    }
    7.    SubShader
    8.    {
    9.         Tags {"Queue" = "Background"}
    10.         Blend SrcAlpha OneMinusSrcAlpha
    11.         Lighting Off
    12.         ZWrite On
    13.         ZTest Always
    14.         Alphatest LEqual 0
    15.         Pass
    16.         {
    17.             SetTexture [_Mask] {combine texture}
    18.         }
    19.    }
    20. }