Tasharen Entertainment Forum

Support => NGUI 3 Support => Topic started by: Scryed on March 10, 2015, 06:30:38 AM

Title: Masking UITexture inside ScrollView doesn't work!!
Post by: Scryed on March 10, 2015, 06:30:38 AM
Hi guys,

So I recently upgraded to NGUI 3.8.0 from some previous version and noticed that the shader I used to mask players facebook avatars inside a list of your friends no longer works. I was using Nicki's solution found at:

http://nickithansen.dk/masking-and-clipping-textures-using-shaders-in-ngui/

However he has since confirmed this no longer works in the latest version of NGUI due to a change in the way scroll views work. It also doesn't appear as though anything is bundled with NGUI that I can pick up and use.

Any idea what's going wrong here? Curious to know if anybody has encountered this and has any solutions to allow masking inside scroll views.

Cheers guys :)
Scryed
Title: Re: Masking UITexture inside ScrollView doesn't work!!
Post by: ArenMook on March 10, 2015, 08:35:20 PM
I recommend having a look at the clipping shaders that come with NGUI, such as "Unlit - Transparent Colored 1". '1' means 1 panel will clip the widget. Note how _ClipRange0 and _ClipArgs0 are used.
Title: Re: Masking UITexture inside ScrollView doesn't work!!
Post by: Scryed on March 11, 2015, 05:23:20 AM
Thanks for the reply Aren!

So good news is that putting the UITexture below a panel of the same size with TextureMask clipping works immediately and the UITexture is properly masked. Fantastic!!

However this is a secondary (hopefully simple) problem now. The Panel / UITexture is no longer clipped by the Scroll View it's nested underneath. Unsure as to whether or not there's a simple checkbox fix on the scroll view / panel components to make them play nice, or if it's an issue with having one panel nested within another and I'll need to drastically change my object hierarchy to get around the problem.

I've attached a screenshot of the issue with the current settings of the panel with the texture mask that I created. It's all pretty out of the box settings-wise but you might spot something amiss.

Thanks again :)
Scryed
Title: Re: Masking UITexture inside ScrollView doesn't work!!
Post by: DCalabrese on March 11, 2015, 01:43:30 PM
I'm afraid this is still not working for me. I have copy / pasted the contents of the Unlit - Transparent Colored 1 shader into a new shader. Quite literally the only difference between that shader and my shader is the name at the top.

The original:  Shader "Hidden/Unlit/Transparent Colored 1"
Mine:  Shader "Unlit/NGUI Unlit Colored Clip Mask"

When I apply the original shader, it clips fine. When I apply my shader, the clipping fails (see attached image). Since I can't even get a duplicate of the original shader to work here, I'm not sure where to go next. Any continued assistance would be very helpful!
Title: Re: Masking UITexture inside ScrollView doesn't work!!
Post by: ArenMook on March 12, 2015, 08:10:37 PM
It'll take longer to explain than to just write the shader. Here you go.
Title: Re: Masking UITexture inside ScrollView doesn't work!!
Post by: Scryed on March 13, 2015, 05:13:25 AM
That shader worked immediately, you rock Aren!!

Eyeballing the code it seems like the only difference is that you're passing the texture mask to the frag and using it's alpha values. I'm ashamed to say I didn't even try that!!

Thanks for the assist, saved the next release of the game :)
Title: Re: Masking UITexture inside ScrollView doesn't work!!
Post by: DCalabrese on March 13, 2015, 12:15:15 PM
Thanks ArenMook - that indeed gets the job done! Though when you have a few moments, I would really like to understand why duplicating the original shader did not work. I'm a big baffled on that one and feel like I should really understand why it didn't work.

Title: Re: Masking UITexture inside ScrollView doesn't work!!
Post by: ArenMook on March 13, 2015, 10:03:52 PM
After duplicating the shader you need to go inside and change its name. Afterwards you need to modify it to use a texture mask, as the original shader does not. I suggest have the two shaders side by side and compare the difference.
Title: Re: Masking UITexture inside ScrollView doesn't work!!
Post by: DCalabrese on March 14, 2015, 12:31:54 PM
That's actually what I did - though in my initial test, I wasn't trying to mask. What I initially wanted to do was just duplicate the shader and get the identical result to the original shader. So I duplicated the shader and changed it's name - but the resulting shader did not function the same as the identical original shader.
Title: Re: Masking UITexture inside ScrollView doesn't work!!
Post by: Mistra on July 14, 2015, 08:41:11 AM
It'll take longer to explain than to just write the shader. Here you go.

@ArenMook thanks for code. It did worked perfectly. Im using the shader with a material and setting offsets
maskedMaterial.SetTextureOffset("_AlphaTex", new Vector2(x, y));

the offset is working fine outside scroll. but it is not working inside it. I would really appreciate your help.
Title: Re: Masking UITexture inside ScrollView doesn't work!!
Post by: ArenMook on July 15, 2015, 12:11:45 AM
That's because NGUI doesn't use your material. It makes a copy for its own draw calls.

If you want to set some material property, you need to subscribe to widget.onRender
Title: Re: Masking UITexture inside ScrollView doesn't work!!
Post by: Mistra on July 28, 2015, 09:49:21 AM
That's because NGUI doesn't use your material. It makes a copy for its own draw calls.

If you want to set some material property, you need to subscribe to widget.onRender


I tried applying widget.onRender. and it didn't work.

           Material maskedMaterial = new Material(maskShader);
      // assign the textures
      maskedMaterial.SetTexture("_AlphaTex", maskTexture.mainTexture);
      maskedMaterial.SetTexture("_MainTex", mainTexture.mainTexture);     
      maskedMaterial.SetTextureOffset("_AlphaTex", new Vector2(x, y));
      // assign the material
      mainTexture.material = maskedMaterial;

AND

   void OnRender (Material mat) {
      mat.SetTextureOffset("_AlphaTex", new Vector2(.10f, .10f));
Debug.Log("offsetX: " + mat.GetTextureOffset("_AlphaTex").x + "  offsety: " + mat.GetTextureOffset("_AlphaTex").y);
   }

// on render debug shows correct values

Above is my code for assigning material, the material has the shader. But it still dont apply offsets.
Title: Re: Masking UITexture inside ScrollView doesn't work!!
Post by: Mistra on July 28, 2015, 11:35:27 AM
Here is another thought
1) Get pixels from UITexture.
2) Make a new UITexture with those pixels
3) Display it

But i dont know how to achieve this.
Can anyone help ?
Title: Re: Masking UITexture inside ScrollView doesn't work!!
Post by: ArenMook on July 28, 2015, 06:50:43 PM
Assuming your widget.onRender is set on the correct widget, your callback function will be triggered with the correct material passed in. This is the material used to draw the widget. If you see correct values, then the shader should get the correct values as well. However the texture offset is suspect... which shader are you using? Not all shaders use the texture matrices. For example Unlit - Transparent Colored does not. You need to use a shader that does.
Title: Re: Masking UITexture inside ScrollView doesn't work!!
Post by: Mistra on July 29, 2015, 02:11:32 AM
I have modified the same shader which you have provided above.
// modified code
v2f vert (appdata_t v)
         {
            o.vertex = mul(UNITY_MATRIX_MVP, v.vertex);
            o.texcoord = v.texcoord, _MainTex;
            o.texcoord1 = TRANSFORM_TEX(v.texcoord1, _AlphaTex);
            o.color = v.color;
            return o;
         }
 // end

Same shader and piece of code works absolutely fine when outside scroll so i can assume shader and widget.OnRender is working fine.

I want to crop face and when it is inside a scrollview
1) masking is done as expected so no issues with it
2) offset of the mask is not updated
Title: Re: Masking UITexture inside ScrollView doesn't work!!
Post by: Mistra on July 29, 2015, 07:04:10 AM
I solved the issue by following cropping function. newtex is your desired cropped face.
Use a transparent overly if you want rounded corners or anything relating.

public void CreateCroppedTex (UITexture tex,Vector2 pixelOffset) {
               
// rect values to crop
               int x;
               int y;
               int width;
               int height;

      Texture2D _texture = tex.mainTexture as Texture2D;
      Sprite newSprite = Sprite.Create(_texture,
                                         new Rect(x, y,width, height),
                                       new Vector2(0.5f, 0.5f));

      Color[] c =   newSprite.texture.GetPixels((int)newSprite.textureRect.x,
                                              (int)newSprite.textureRect.y,
                                                       (int)faceWidth,
                                                       (int)faceHeight );

      Texture2D newtex = new Texture2D( (int)faceWidth, (int)faceHeight, TextureFormat.ARGB32,false);
      newtex.filterMode = FilterMode.Bilinear;
      newtex.SetPixels(c);
      newtex.Apply();

      tex.mainTexture = newtex;

   }
Title: Re: Masking UITexture inside ScrollView doesn't work!!
Post by: cedtat on August 22, 2015, 07:37:23 AM
Hello,

I am actually trying to do exactly the same as Scryed, I have a scroll view, with a table composed of a list of textures. Each UITexture is nested inside a panel with a circle mask and now I am experiencing the same problem as scryed. The profile picture is not clipped by the scrollview on the edge. It only disappears when completly outside of the scrollview. I have 3 UIPanel (UIRoot, ScrollView and texture mask)

I have tried changing the shader on my texture with "Unlit - Transpasrent Masked" 1,2 and 3 and "Unlit - Transparent Colored" versions but without any success.
Obviously I have missed something, is there someone here to help me ?

Thanks,
Cedric
Title: Re: Masking UITexture inside ScrollView doesn't work!!
Post by: cedtat on August 22, 2015, 02:08:20 PM
ok, thanks to this subject, I found a solution :http://www.tasharen.com/forum/index.php?topic=13450.0

I understood it was not possible to mix rect-based clipping with texture mask-based clipping.
So I stopped using a panel above my texture to mask it inside a scrollview. I am now using a material with a shader modified from "unlit/Transparent Colored 1".
I made multiple errors in the process of creating the shader, not placing it in appropriate ressource folder and not naming it correclty so that NGUI find it.

Cheers,
Cedric