Author Topic: clipping a panel with a non-square rect  (Read 15922 times)

briangibson

  • Newbie
  • *
  • Thank You
  • -Given: 2
  • -Receive: 0
  • Posts: 26
    • View Profile
clipping a panel with a non-square rect
« on: April 28, 2014, 10:39:40 AM »
Hey there- I would like to clip a scrollview panel contents via rounded clipping corners or another sort of clipping mask around the edges. How would you recommend going about this?

I was thinking maybe my grid contents could use a particular material that clips with a 2nd texture input or something... but I'm not entirely sure about the rendering pipeline involved in a scrollview contents + the ngui-generated meshes.

Would be a killer feature to add- being able to use a Sliced uisprite as a clipping mask for a UIPanel.

I saw this: but it isn't quite what I'm looking for. I need to sort of sample the texcoords in world space to use as a mask, more or less.
http://nickithansen.dk/masking-and-clipping-textures-using-shaders-in-ngui/
« Last Edit: April 28, 2014, 11:51:26 AM by briangibson »

ArenMook

  • Administrator
  • Hero Member
  • *****
  • Thank You
  • -Given: 337
  • -Receive: 1171
  • Posts: 22,128
  • Toronto, Canada
    • View Profile
Re: clipping a panel with a non-square rect
« Reply #1 on: April 29, 2014, 02:39:21 PM »
NGUI's clipping is done via a shader -- if the texture position lies outside the rectangle, it's faded out. Involving texture sampling is doable, but not using sliced sprites. Sliced sprites are drawn using 9-slicing -- by drawing 9 triangles, each scaled differently than its UVs. TLDR version: this would not be a simple feature. Masking is easy. Sliced masking? Not so much. It wouldn't be worth the effort as it would complicate everything dramatically.

briangibson

  • Newbie
  • *
  • Thank You
  • -Given: 2
  • -Receive: 0
  • Posts: 26
    • View Profile
Re: clipping a panel with a non-square rect
« Reply #2 on: April 29, 2014, 02:54:12 PM »
I understand that 9 sliced masking would be a complicated feature. Let's say for simplicity's sake, I just want to clip a panel via a 'mask' sprite placed somewhere in the scene. In theory, I could make a solid image with an alpha background...and use the solid color as a mask for the scrollview contents (or for other content)

Is that out of the realm of possibility? "Involving texture sampling is doable" gives me hope... I poked at the shader that does the clipping, but I'm not sure how I'd go about this with NGUI. Perhaps writing to the stencil buffer? *ponder*

ArenMook

  • Administrator
  • Hero Member
  • *****
  • Thank You
  • -Given: 337
  • -Receive: 1171
  • Posts: 22,128
  • Toronto, Canada
    • View Profile
Re: clipping a panel with a non-square rect
« Reply #3 on: April 30, 2014, 05:09:43 PM »
You can currently already do this using a stencil buffer. Write a shader that will write to a stencil buffer, then create a shader that will only write where stencil is set.

cayou

  • Jr. Member
  • **
  • Thank You
  • -Given: 3
  • -Receive: 3
  • Posts: 90
    • View Profile
Re: clipping a panel with a non-square rect
« Reply #4 on: September 16, 2014, 03:23:34 PM »
Hi guys, I'm bumping this thread.
I think there is a way in the next Unity UI system to make clipping using texture as mask.
Is there any way to have this as well on NGUI?

Thanks !

ArenMook

  • Administrator
  • Hero Member
  • *****
  • Thank You
  • -Given: 337
  • -Receive: 1171
  • Posts: 22,128
  • Toronto, Canada
    • View Profile
Re: clipping a panel with a non-square rect
« Reply #5 on: September 17, 2014, 12:00:43 PM »
Yes, as I mentioned above you just need to write two shaders. One shader to write to stencil, another to draw only where the stencil was written. The first shader will go on the mask, the second shader will go on the atlas material.

cayou

  • Jr. Member
  • **
  • Thank You
  • -Given: 3
  • -Receive: 3
  • Posts: 90
    • View Profile
Re: clipping a panel with a non-square rect
« Reply #6 on: September 17, 2014, 12:16:35 PM »
One of our developer made it without using stencil buffer or even writing shaders.
He modified UIPanel and few other scripts, and it works well.
Would you be interested on adding this feature into the actual version of NGUI? It would be cool to share it with all users.

ArenMook

  • Administrator
  • Hero Member
  • *****
  • Thank You
  • -Given: 337
  • -Receive: 1171
  • Posts: 22,128
  • Toronto, Canada
    • View Profile
Re: clipping a panel with a non-square rect
« Reply #7 on: September 17, 2014, 01:23:07 PM »
Without writing shaders? I see no way this can be done without writing at least one shader. You are welcome to share the solution here if you like. Just don't post all of NGUI's source code. A few files is fine.

cayou

  • Jr. Member
  • **
  • Thank You
  • -Given: 3
  • -Receive: 3
  • Posts: 90
    • View Profile
Re: clipping a panel with a non-square rect
« Reply #8 on: September 17, 2014, 02:26:56 PM »
My bad, he made a new variation of shaders you created for NGUI (AlphaClip, SoftClip, etc...). I'll post only those new scripts, but we are using a quite old version on NGUI, so the code might no be up-to-date (3.5.3).

cayou

  • Jr. Member
  • **
  • Thank You
  • -Given: 3
  • -Receive: 3
  • Posts: 90
    • View Profile
Re: clipping a panel with a non-square rect
« Reply #9 on: September 17, 2014, 02:40:56 PM »
I attached an archive with UIPanelInspector, UIPanel and UIDrawCall scripts.
It also includes all new variation shaders (TextureClip).

The lines added/modified on scripts:

UIPanel ->

Line 130: 
  1.  
  2. [HideInInspector][SerializeField] Texture2D mClipTexture = null;
  3.  

Line 433:
  1.    
  2. public Texture2D clipTexture
  3.     {
  4.         get
  5.         {
  6.             return mClipTexture;
  7.         }
  8.         set
  9.         {
  10.             if (mClipTexture != value)
  11.             {
  12.                 mClipTexture = value;
  13. #if UNITY_EDITOR
  14.                 if (!Application.isPlaying) UpdateDrawCalls();
  15. #endif
  16.             }
  17.         }
  18.     }
  19.  

Line 1222:
  1.            
  2. dc.clipTexture = mClipTexture;
  3.  

UIDrawcall ->

Line 43:
  1.         TextureClip = 5,
  2.  

Line 72:
  1.     Texture2D       mClipTexture;
  2.  

Line 261:
  1.     public Texture2D clipTexture { get { return mClipTexture; } set { mClipTexture = value; } }
  2.  

Line 271:
  1.         const string textureClip = " (TextureClip)";
  2.  

Line 279:
  1.         shaderName = shaderName.Replace(textureClip, "");
  2.  

Line 292:
  1.         else if (mClipping == Clipping.TextureClip)
  2.         {
  3.             shader = Shader.Find(shaderName + textureClip);
  4.         }
  5.  

Line 569:
  1.             mDynamicMat.SetTexture("_ClipTex", mClipTexture);
  2.  

And finally on UIPanelInspector ->

Line 511:
  1.             if (mPanel.clipping == UIDrawCall.Clipping.TextureClip)
  2.             {
  3.                 GUILayout.BeginHorizontal();
  4.                 GUILayout.Space(80f);
  5.                 Texture2D tex = (Texture2D)EditorGUILayout.ObjectField("Clip Texture", mPanel.clipTexture, typeof(Texture2D), false, GUILayout.Width(200));
  6.                 GUILayout.EndHorizontal();
  7.  
  8.                 if (mPanel.clipTexture != tex)
  9.                 {
  10.                     NGUIEditorTools.RegisterUndo("Clipping Change", mPanel);
  11.                     mPanel.clipTexture = tex;
  12.                     EditorUtility.SetDirty(mPanel);
  13.                 }
  14.             }
  15.  

cayou

  • Jr. Member
  • **
  • Thank You
  • -Given: 3
  • -Receive: 3
  • Posts: 90
    • View Profile
Re: clipping a panel with a non-square rect
« Reply #10 on: September 17, 2014, 04:01:15 PM »
One thing:
Maybe it's not logic right now that the sprites or textures will be faded out when the alpha of the texture mask is 0.
So in my version I changed in all shaders the line where the alpha of the texture is multiplied by the alpha of the mask to 1 - alpha to inverse it.

cayou

  • Jr. Member
  • **
  • Thank You
  • -Given: 3
  • -Receive: 3
  • Posts: 90
    • View Profile
Re: clipping a panel with a non-square rect
« Reply #11 on: September 17, 2014, 04:09:28 PM »
Here's an example of the result: it's pretty damn AMAZING.


badawe

  • Jr. Member
  • **
  • Thank You
  • -Given: 8
  • -Receive: 7
  • Posts: 70
    • View Profile
Re: clipping a panel with a non-square rect
« Reply #12 on: September 17, 2014, 07:50:05 PM »
This is TO DAMN AWESOME!

This mask feature of the new Unity almost made me switch a entire project to it!
But I'll give a try in this test, and try to update this to the new NGUI! :D

Thanks for sharing this!

afrokick

  • Newbie
  • *
  • Thank You
  • -Given: 4
  • -Receive: 0
  • Posts: 6
    • View Profile
Re: clipping a panel with a non-square rect
« Reply #13 on: September 18, 2014, 05:44:51 AM »
Thank you very much! But it doesn't work in 3.7.0.

Fixes:


UIPanel:
clipCount
  1. if (p.mClipping == UIDrawCall.Clipping.SoftClip || p.mClipping == UIDrawCall.Clipping.TextureClip) ++count;
  2.  

hasClipping
  1. public bool hasClipping { get { return mClipping == UIDrawCall.Clipping.SoftClip || mClipping == UIDrawCall.Clipping.TextureClip; } }
  2.  

UIDrawCall:
void CreateMaterial ()
  1. // Legacy functionality
  2. if (shader == null && mClipCount == 1){
  3.     mLegacyShader = true;
  4.     shader = Shader.Find(shaderName + soft);
  5. }
  6.  
  7. //added
  8. if(panel.clipping == Clipping.TextureClip){
  9.     mLegacyShader = true;
  10.     shader = Shader.Find(shaderName + textureClip);
  11. }
  12. //end
  13. ...
  14.  
  15. mDynamicMat.SetVector("_ClipSharpness", sharpness);
  16. mDynamicMat.SetTexture("_ClipTex", mClipTexture);//<---- added
  17.  
« Last Edit: September 18, 2014, 06:11:41 AM by afrokick »

cayou

  • Jr. Member
  • **
  • Thank You
  • -Given: 3
  • -Receive: 3
  • Posts: 90
    • View Profile
Re: clipping a panel with a non-square rect
« Reply #14 on: September 18, 2014, 08:21:49 AM »
I think the best way to do it is to wait for ArenMook to integrate it in the latest version of NGUI.
Or you will have to figure out where to integrate changes on those 3 files in the new version (maybe script like UIPanel is completely different) and add new shaders into your project (from the archive I attached in my previous post).
I don't think that's not going to work on the last version, we didn't change a lot of things into the project, we just add pretty much the support for a new clipping mode, and the shader is very similar to the original one. Basically it's just multiplying the alpha of the sprite/texture/label with the alpha of the mask texture.