A question that showed up on Tasharen’s forum, where I happen to be a moderator, was this one:

(..) I have a panel that’s draggable and clipped, which displays a list of GameObjects, each one composed of usernames, avatars, and some other text. The avatars are not square, they have an hexagonal mask. To achieve this, they are Texture widgets with a special shader I found here. (..) when they get clipped by the panel, they keep showing even outside the boundaries. Only when completely out of sight, they get hidden(..).

Source: http://www.tasharen.com/forum/index.php?topic=5621

First: the reason it gets disabled when its entirely outside the clip area is the way NGUI culls widgets by simply not drawing them. It’s not that the gameObject is disabled, but the UIPanel does not feed this widget into the UIDrawCall’s geometry which is the thing that gets drawn on screen.

The shader he used for the masking was obtained at http://www.zedia.net/2013/masking-textures-using-shaders-ngui/ who based the shader on the old non-clipping version of NGUIs builtin Transparent Alpha shader (it has since changed to not use the combine keyword).

This doesn’t work with the different clipping options that NGUI uses (Alpha Clipping, Soft Clipping) since the UIPanels change the shader used and also feed in the coordinates where it needs to be clipped. It’s very worth noting that the way the UIPanel chooses shaders is entirely based on the name of the shader. This means that when you make a new shader, you should make a similar named shader but with ” (AlphaClip)” added to it, so it’s used when alpha cliping is enabled.

// If clipping should be used, we need to find a replacement shader if (useClipping && mClipping != Clipping.None) { Shader shader = null; const string alpha = " (AlphaClip)"; const string soft = " (SoftClip)"; // Figure out the normal shader's name string shaderName = mSharedMat.shader.name; shaderName = shaderName.Replace(alpha, ""); shaderName = shaderName.Replace(soft, ""); // Try to find the new shader if (mClipping == Clipping.HardClip || mClipping == Clipping.AlphaClip) shader = Shader.Find(shaderName + alpha); else if (mClipping == Clipping.SoftClip) shader = Shader.Find(shaderName + soft);

Source: UIDrawCall.cs in NGUI.

Note also that the former HardClipping is entirely deprecated and just changes to be AlphaClip under the surface.

Here’s a shader that works with Alpha Clipping based on the Transparent Colored (AlphaClip) builtin shader in NGUI:

Shader "Custom/MaskClipShader (AlphaClip)" { Properties { _MainTex ("Base (RGB), Alpha (A)", 2D) = "white" {} _AlphaTex ("MaskTexture", 2D) = "white" {} } SubShader { LOD 100 Tags{ "Queue" = "Transparent" "IgnoreProjector" = "True" "RenderType" = "Transparent" } Pass { Cull Off Lighting Off ZWrite Off Offset -1, -1 Fog { Mode Off } ColorMask RGB Blend SrcAlpha OneMinusSrcAlpha CGPROGRAM #pragma vertex vert #pragma fragment frag #include "UnityCG.cginc" sampler2D _MainTex; float4 _MainTex_ST; sampler2D _AlphaTex; struct appdata_t { float4 vertex : POSITION; half4 color : COLOR; float2 texcoord : TEXCOORD0; }; struct v2f { float4 vertex : POSITION; half4 color : COLOR; float2 texcoord : TEXCOORD0; float2 worldPos : TEXCOORD1; }; v2f vert (appdata_t v) { v2f o; o.vertex = mul(UNITY_MATRIX_MVP, v.vertex); o.color = v.color; o.texcoord = v.texcoord; o.worldPos = TRANSFORM_TEX(v.vertex.xy, _MainTex); return o; } half4 frag (v2f IN) : COLOR { // Sample the texture half4 col = tex2D(_MainTex, IN.texcoord) * IN.color; half4 a2 = tex2D(_AlphaTex, IN.texcoord); float2 factor = abs(IN.worldPos); float val = 1.0 - max(factor.x, factor.y); // Option 1: 'if' statement if (val < 0.0) col.a = 0.0; if (a2.a < col.a) col.a = a2.a; // Option 2: no 'if' statement -- may be faster on some devices //col.a *= ceil(clamp(val, 0.0, 1.0)); return col; } ENDCG } } }

You will have to use the non clipping shader that was provided on the other blog or make one based on the new version of the Transparent Colored shader in NGUI. This shader will get all sorts of weird if you use it in a non-clipping panel.

I use a custom Material which I put onto a UITexture. If you instantiate the material, you can feed it different mainTextures such as facebook images or something similar.

I hope this will be helpful to someone.

Nicki.