Search Unity

  1. We are migrating the Unity Forums to Unity Discussions. On July 12, the Unity Forums will become read-only. On July 15, Unity Discussions will become read-only until July 18, when the new design and the migrated forum contents will go live. Read our full announcement for more information and let us know if you have any questions.

Unity UI big problem with lacking materialpropertyblock for ui image

Discussion in 'UGUI & TextMesh Pro' started by mahdiii, Nov 30, 2017.

  1. mahdiii

    mahdiii

    Joined:
    Oct 30, 2014
    Posts:
    856
    Hi all. I need to use materialpropertyblock for UI images. How can I handle it?
    I have a lot of UI square images that have different properties (Color property for example or another one). Thanks
     
    Last edited: Feb 7, 2020
    mdrunk likes this.
  2. karl_jones

    karl_jones

    Unity Technologies

    Joined:
    May 5, 2015
    Posts:
    8,570
    You can't use material property blocks with UI. What is it you want to change? Color is better changed through the UI components than a MPB. The color is placed into the mesh as vertex colors. If it's just lots of squares then changing the sprite color is perfectly fine. You could also write a custom component that puts the color into the vertexes yourself if it needs to be more complex.
     
  3. mahdiii

    mahdiii

    Joined:
    Oct 30, 2014
    Posts:
    856
    Thanks, I have written a custom shader. The property is not color. I know an image ui has a color property
    it is four float (vector4: x and y bottom left coordinate point and height width) , I need to mask a texture on these squares and overlay them
    I almost have 200 squares and can not have 200 pass call for that
     
    Last edited: May 27, 2022
  4. karl_jones

    karl_jones

    Unity Technologies

    Joined:
    May 5, 2015
    Posts:
    8,570
    What about putting the data into a different channel such as uv1 or uv2? The canvas allows for adding some extra channels. I have done something similar in the past using uv1 and a custom sprite to write in the channel.
     
    mahdiii likes this.
  5. mahdiii

    mahdiii

    Joined:
    Oct 30, 2014
    Posts:
    856
    perfect I understood it
    Can you refer to me a link about that?
    So I set a channel uv2 float4
    float4 uv2:TEXCOORD2. my data are between 0 and 1 but I think a texture RGBA can not have enough precision
    putting the data into a channel instead of sending to a shader with setvector
     
    Last edited: Nov 30, 2017
  6. karl_jones

    karl_jones

    Unity Technologies

    Joined:
    May 5, 2015
    Posts:
    8,570
    You can create a new BaseMeshEffect class and then put the data into the verts like this example:
    Then make sure you have enabled the channel in the canvas under the Additional Shader Channels
     
  7. mahdiii

    mahdiii

    Joined:
    Oct 30, 2014
    Posts:
    856
    some questions:
    1- ModifyMesh override function is executed only once?
    2- can we add different channels for different uis or not (in other words can we add texcoords to special uis not a canvas)
     
  8. karl_jones

    karl_jones

    Unity Technologies

    Joined:
    May 5, 2015
    Posts:
    8,570
    Its called whenever the canvas needs to generate a mesh. https://docs.unity3d.com/ScriptReference/UI.IMeshModifier.html

    What do you mean uis? You can modify selected elements, you dont have to attach your MeshModifier to every element.
     
    domportera and mahdiii like this.
  9. mahdiii

    mahdiii

    Joined:
    Oct 30, 2014
    Posts:
    856
    no, you said I must change Additional Shader Channels from the canvas so I can change it only for the canvas and if I want to have different channels for different images for example,I need to add all channels to consider all of them
     
  10. karl_jones

    karl_jones

    Unity Technologies

    Joined:
    May 5, 2015
    Posts:
    8,570
    Yes you need to make sure that the responsible canvas has the additional channels enabled. Then you can modify its child images.
     
  11. mahdiii

    mahdiii

    Joined:
    Oct 30, 2014
    Posts:
    856
    :) again thank you
    Code (CSharp):
    1. using System.Linq;
    2. using System.Collections;
    3. using System.Collections.Generic;
    4. using UnityEngine;
    5. using UnityEngine.UI;
    6.  
    7. [AddComponentMenu("UI/Effects/Position As UV1", 16)]
    8. public class PositionAsUV1 : BaseMeshEffect {
    9.  
    10.  
    11.     [SerializeField]
    12.     RectTransform m_maskImageRectTr;
    13.     [SerializeField]
    14.     RectTransform m_imageRectTr;
    15.     Vector4 vec;
    16.     [SerializeField]
    17.     int m_rowIdx;
    18.     [SerializeField]
    19.     int m_colIdx;
    20.     [SerializeField]
    21.     Vector2 m_margin;
    22.  
    23.     // Use this for initialization
    24.     protected override void Start() {
    25.         base.Start();
    26.         Vector2 vv = m_imageRectTr.sizeDelta.Divide(m_maskImageRectTr.sizeDelta);
    27.         vec.x = ((m_colIdx - 1) * (m_margin.x + m_imageRectTr.sizeDelta.x) + m_imageRectTr.sizeDelta.x) / m_maskImageRectTr.sizeDelta.x;
    28.         vec.y = ((m_rowIdx - 1) * (m_margin.y + m_imageRectTr.sizeDelta.y) + m_imageRectTr.sizeDelta.y) / m_maskImageRectTr.sizeDelta.y;
    29.         vec.z = vv.x;
    30.         vec.w = vv.y;
    31.     }
    32.     public void SetRowCol(int _row,int _col) {
    33.         m_rowIdx = _row;
    34.         m_colIdx = _col;
    35.     }
    36.     protected PositionAsUV1() { }
    37.  
    38.     public override void ModifyMesh(VertexHelper vh) {
    39.  
    40.         UIVertex vert = new UIVertex();
    41.         for (int i = 0; i < vh.currentVertCount; i++) {
    42.             vh.PopulateUIVertex(ref vert, i);
    43.             vert.uv1 = new Vector2(vec.x, vec.y);
    44.             vert.uv2 = new Vector2(vec.z, vec.w);          
    45.             vh.SetUIVertex(vert, i);
    46.         }
    47.     }
    48. }
    49.  


    Code (CSharp):
    1.     struct appdata
    2.             {
    3.                 float4 vertex : POSITION;
    4.                 float2 uv : TEXCOORD0;
    5.                 float2 uv1 : TEXCOORD1;
    6.                 float2 uv2 : TEXCOORD2;
    7.             };
    8.  
    9.             struct v2f
    10.             {
    11.                 float2 uv : TEXCOORD0;
    12.                 float2 uv1 : TEXCOORD1;
    13.                 float2 uv2 : TEXCOORD2;
    14.                
    15.                 float4 vertex : SV_POSITION;
    16.             };
    17.  
    18.             sampler2D _MainTex;
    19.             float4 _MainTex_ST;
    20.             sampler2D    _OverlayTex;
    21.             float4 _Rect;
    22.             fixed4 _Color;
    23.             float _Factor;
    24.             float _Factor2;
    25.             v2f vert (appdata v)
    26.             {
    27.                 v2f o;
    28.                 o.vertex = UnityObjectToClipPos(v.vertex);
    29.                 o.uv = TRANSFORM_TEX(v.uv, _MainTex);
    30.                 o.uv1=v.uv1;
    31.                 o.uv2=v.uv2;
    32.                 return o;
    33.             }
    34.            
    35.             fixed4 frag (v2f i) : SV_Target
    36.             {
    37.                 // sample the texture
    38.                 fixed4 col = tex2D(_MainTex, i.uv);
    39.                 float2 overlayUV=float2(i.uv1.x,i.uv1.y)+i.uv*float2(i.uv2.x,i.uv2.y);
    40.                 fixed4 col2 = tex2D(_OverlayTex,overlayUV);
    41.                 fixed4 finalCol=fixed4( col.r<=0.5 ? 2*col.r*col2.r: 1-2*(1-col.r)*(1-col2.r),
    42.                                         col.g<=0.5 ? 2*col.g*col2.g: 1-2*(1-col.g)*(1-col2.g),
    43.                                         col.b<=0.5 ? 2*col.b*col2.b: 1-2*(1-col.b)*(1-col2.b),1);
    44.                 finalCol=lerp(finalCol,col2*col,_Factor);
    45.                 finalCol=lerp(col,finalCol,_Factor2)*_Color;
    46.                 finalCol.a=col2.a;
    47.  
    48.                 return finalCol;
    49.             }
     

    Attached Files:

  12. karl_jones

    karl_jones

    Unity Technologies

    Joined:
    May 5, 2015
    Posts:
    8,570
    Looks great. Happy to help :D
     
  13. pbhogan

    pbhogan

    Joined:
    Aug 17, 2012
    Posts:
    386
    What is the justification for this obtuse restriction? Why doesn't CanvasRenderer have material property blocks?

    It arbitrarily limits UI elements and its super unintuitive. I'm trying to write a custom UI component with a fairly complex shader that needs quite a few bits of data passed in and that's in addition to vertex colors and UVs.

    I originally wanted to pass in several properties but I've been banging my head on this for hours only to come to find out there is no way to even pass in a single color property on a per instance basis. Encoding a uniform property value into additional UV channels is just silly and inefficient. And what if we wanted to pass in a second texture?

    I need many instances of this component with differing data values so I don't want draw calls to scale with instances.
     
  14. Aaron-Meyers

    Aaron-Meyers

    Joined:
    Dec 8, 2009
    Posts:
    305
    +1 for using MaterialPropertyBlocks with CanvasRenderer. MaterialPropertyBlock is an essential unity workflow. Why should it be any different for UI components with custom shaders/materials?
     
    MrDizzle26 and chrismarch like this.
  15. better_walk_away

    better_walk_away

    Joined:
    Jul 12, 2016
    Posts:
    291
    Unity really should consider adding MaterialPropertyBlock for CanvasRenderer. My game consists mostly UI Text and Image that are using CanvasRenderer. This will have huge impact on my workflow.
     
    MrDizzle26 likes this.
  16. fabiosagaz

    fabiosagaz

    Joined:
    Dec 13, 2013
    Posts:
    1
    Same problem here. This makes no sense at all. They could simply allow it to work. I have thousands of objects on a UI I need to set parameters dynamically, but there's no way to make it performantly assigning parameters manually
     
    MrDizzle26 and Julien_at_work like this.
  17. tweedie

    tweedie

    Joined:
    Apr 24, 2013
    Posts:
    311
    Just came across this limitation for the umpteenth time.

    There might be good reasons for this, but with no explanation why this is the case, it seems like such an arbitrary limitation. UI is such a great candidate for MBPs - 99% of the time, if I need a custom shader for a UI element, its going to be broadly the same with a few unique parameters. But nope. The "best" way I've worked around this is by trying to squeeze things into the rgb of the element's color tint (only good for floats), as that's at least per-element.
     
    Last edited: Apr 24, 2020
    squarelover, MrDizzle26 and mdrunk like this.
  18. Mehrdad995

    Mehrdad995

    Joined:
    Jul 17, 2013
    Posts:
    46
    Having "MaterialPropertyBlock" for "UI" would resolve pile of headaches for many of us.
    would be really nice to have it in a future update .
     
    MrDizzle26 likes this.
  19. felipefujioka

    felipefujioka

    Joined:
    Aug 28, 2019
    Posts:
    1
    What if I want to use a Dissolve Shader effect and change the Dissolution Level in a specific renderer? That would require the support for controlling the renderers canvas by canvas.
     
  20. Thomas-Mountainborn

    Thomas-Mountainborn

    Joined:
    Jun 11, 2015
    Posts:
    510
    Just gonna pitch in my support for MaterialPropertyBlocks for UI. Unity's UI has basically not changed since 4.6 in 2015, and yet UI is such a major part of any game or application. The kind of projects we build at the company I work at are pretty much only UI. Having to use new material instances for each UI element that you want to do more with than just the basics is a real performance bottleneck. Hacking around this by using additional shader channels is not a scalable or user friendly solution.
     
    Last edited: Sep 26, 2019
  21. j4n

    j4n

    Joined:
    Nov 30, 2017
    Posts:
    8
    Oof, just my luck. This is actually my first time writing a custom shader for something I need, and I just slammed against this roadblock that exists for no apparent reason.
     
    MrDizzle26, Fressbrett and mdrunk like this.
  22. RedVonix

    RedVonix

    Joined:
    Dec 13, 2011
    Posts:
    432
    Adding my vote that MaterialPropertyBlocks are flat-out needed for UI. There is still too much separation between the UI rendering and standard Rendering for UGUI to integrate smoothly into the rest of the Unity workflow. I've been hitting UGUI based roadblocks daily for months now due to UGUI not integrating well with Unity's rendering.
     
    MrDizzle26 and mdrunk like this.
  23. altair2020

    altair2020

    Joined:
    Mar 6, 2011
    Posts:
    49
    +1 MaterialPropertyBlocks
     
    MrDizzle26 and Fressbrett like this.
  24. ianwexl0rz

    ianwexl0rz

    Joined:
    Jul 20, 2017
    Posts:
    4
    +1 MaterialPropertyBlocks for UI

    I'm using MaterialPropertyBlocks to set data per renderer in custom shaders throughout my game. This limitation for UI interrupts my usual workflow and introduces seemingly unnecessary complexity. If there is a good reason for this, I would also appreciate an explanation.
     
    MrDizzle26 and Fressbrett like this.
  25. Ruzihm

    Ruzihm

    Joined:
    Aug 4, 2013
    Posts:
    4
    I'm also chiming in with a need for UI MaterialPropertyBlock
     
    MrDizzle26 likes this.
  26. Alexander_V

    Alexander_V

    Joined:
    Feb 26, 2020
    Posts:
    8
    GPU instancing is essential for UI. Please bring prop blocks to Canvasenderer. For example, I need to pass unity gradient into the shader and it 8 Colors + 16 floats(for positions).
    Also, I'm developing GPU scrolling tech for UI so setting prop block is needed.
     
    MrDizzle26 likes this.
  27. MrDizzle26

    MrDizzle26

    Joined:
    Feb 8, 2015
    Posts:
    37
    +1 for UI Canvas material property blocks!
     
  28. TJHeuvel-net

    TJHeuvel-net

    Joined:
    Jul 31, 2012
    Posts:
    838
    Its probably because all UI is baked to one mesh, so there are no multiple renderers to attach data to.
     
  29. Pawl

    Pawl

    Joined:
    Jun 23, 2013
    Posts:
    113
    +1 Just ran into this and was surprised to find out that UI does not support MPB, would love to see support for this to provide API and developer consistency.
     
  30. jamespaterson

    jamespaterson

    Joined:
    Jun 19, 2018
    Posts:
    407
    Would be good to get this supported. Or least a good reason why not :)
     
  31. TJHeuvel-net

    TJHeuvel-net

    Joined:
    Jul 31, 2012
    Posts:
    838
    The UI is one renderer, hence no per-renderer-data. You can modify the meshes generated though.
     
  32. jamespaterson

    jamespaterson

    Joined:
    Jun 19, 2018
    Posts:
    407
    Thanks for the response - this makes sense I guess. This is a limitation of the unity UI architecture rather than the GPU itself though I would have thought?
     
  33. TJHeuvel-net

    TJHeuvel-net

    Joined:
    Jul 31, 2012
    Posts:
    838
    jamespaterson likes this.
  34. jamespaterson

    jamespaterson

    Joined:
    Jun 19, 2018
    Posts:
    407
    Thanks for the suggestion :)
     
  35. Yandalf

    Yandalf

    Joined:
    Feb 11, 2014
    Posts:
    492
    Sorry for necroing, but then what's the purpose of the Canvas Renderer component that gets thrown everywhere? You'd think those would be an opportune target to hang PropertyBlocks to, without any knowledge of the inside of the system.
    That said the people here are right that as long as we have no official word about why this limitation exist, this might as well be arbitrary and considering it is almost reflexive for users to try this, Unity should implement it.
    The UI system as-is is really good, but adding a few features like these would make it so much less of a headache to work with and improve performance to boot, as it allows us to bake much more into a single draw call instead of having to split up all our elements!

    Sorry for a bit of a ramble, but this discovery has basically put me back on square one for something I'm working on.
     
  36. artplayer

    artplayer

    Joined:
    Apr 16, 2016
    Posts:
    18
    No solution yet?
    Has anyone managed to get around this problem?
     
  37. TJHeuvel-net

    TJHeuvel-net

    Joined:
    Jul 31, 2012
    Posts:
    838
    See my response, there is only one 'renderer' for UI. Everything is combined to a single mesh, and a single draw call.

    It might be possible to achieve the same if you add mesh modifiers and pass in custom data.
     
  38. chriscode

    chriscode

    Joined:
    Mar 2, 2015
    Posts:
    52
    Yeah this caught me out too. You just assume that if you can set a custom material with custom shader like you can for other things that you'll be able to use property blocks. May be some reasons under the hood, but not intuitive.
     
  39. Yandalf

    Yandalf

    Joined:
    Feb 11, 2014
    Posts:
    492
    Except it's not? UI elements create new draw calls all the time as soon as there's notable differences between two elements. There's a reason why voices critical of the current system suggest to use as few elements as possible and bake as much into simple bitmaps as you can (overdraw being the other major reason).
    Frame debugging UI quickly shows that if what you're describing is the intended effect, then the current system is doing a pretty meager job of it.
     
  40. TJHeuvel-net

    TJHeuvel-net

    Joined:
    Jul 31, 2012
    Posts:
    838
    You are right, i oversimplified. There is more than one draw call, for example for each panel, or material.

    However it does attempt to batch multiple elements together in renderers, and that is why you cannot have per renderer data.
     
  41. madGlory

    madGlory

    Joined:
    Jan 12, 2016
    Posts:
    44
    +1 this completely bonked me.
     
    MrDizzle26 and jashan like this.
  42. jashan

    jashan

    Joined:
    Mar 9, 2007
    Posts:
    3,307
    So how is it that you can use a different material for each UI element?

    The funny thing is: Unity seems to internally use MaterialPropertyBlock or something equivalent for using different textures for sprites / images. Have a look at UI-Default.shader - it's right in the very first line:

    Code (CSharp):
    1. [PerRendererData] _MainTex ("Sprite Texture", 2D) = "white" {}
    So, apparently, Unity uses "PerRendererData", which is also what is used for the general MaterialPropertyBlocks, to solve the issue of putting the sprites / textures into the rendering system without needing a different material for each sprite / image.

    Not being able to use the standard procedure for this is super-annoying. I'd need this to set an HDR color for an Image (I already have a shader that supports that but I'd rather not have to create a new material for each instance). Obviously, if vertex colors would support HDR, that would be preferable - but I doubt that they do because otherwise, the restriction to non-HDR colors in Graphic wouldn't make sense. So basically, what I'm trying to do is use the usual color for the base color, and then increase value via a HDR-tint. Any other ideas on how to achieve that, @karl_jones ?

    I guess I'll have to dig into the implementation of Graphic to figure this one out.

    EDIT: Hrmpf ... so, first I tried Graphic, then Image, then RawImage. RawImage calls a method SetTexture(...) on CanvasRenderer. Unfortunately, that's where my search ends - because that's a call into some native Unity code that I don't have access to. The method description says: "Sets the texture used by this renderer's material". So, most likely this does exactly what I'm assuming it does but there doesn't seem to be an API for me to do the same. Not cool. This is pretty dumb because it means I have to create a different material for each of my backgrounds instead of being able to use one with MaterialPropertyBlocks. Not happy.
     
    Last edited: Dec 21, 2020
    MrDizzle26 likes this.
  43. unity_q7DClpA5dzbzxA

    unity_q7DClpA5dzbzxA

    Joined:
    Dec 15, 2020
    Posts:
    2
    Another +1 for this. This is making things quite painful.
     
    MrDizzle26 likes this.
  44. Eric-van-Gastel

    Eric-van-Gastel

    Joined:
    Jan 2, 2016
    Posts:
    21
    After 4 years since the original post, another +1 from me. Specifically for a blur shader that shifts with the alpha of a fade layer behind popups and dialogs.
     
    B-Erolskiy and MrDizzle26 like this.
  45. alan25799

    alan25799

    Joined:
    Nov 12, 2020
    Posts:
    1
    +1
     
    MrDizzle26 likes this.
  46. treecki

    treecki

    Joined:
    Feb 6, 2017
    Posts:
    29
  47. NullQubit

    NullQubit

    Joined:
    Jun 1, 2015
    Posts:
    11
  48. unity_q7DClpA5dzbzxA

    unity_q7DClpA5dzbzxA

    Joined:
    Dec 15, 2020
    Posts:
    2
  49. TurgutHakki

    TurgutHakki

    Joined:
    Jun 15, 2017
    Posts:
    33
  50. yyysukiii

    yyysukiii

    Joined:
    Jun 13, 2020
    Posts:
    9