Search Unity

Per renderer stencil using MaterialPropertyBlock

Discussion in 'Shaders' started by Thomas-Mountainborn, May 12, 2016.

  1. Thomas-Mountainborn

    Thomas-Mountainborn

    Joined:
    Jun 11, 2015
    Posts:
    501
    Hey there! I'm trying to set individual stencil read / write values on materials using [PerRendererData] and MaterialPropertyBlocks. Sadly, without success so far - I've gone over my code over and over and I don't see anything wrong with it. Has anyone else had any experience with changing the stencil Ref value using material property blocks? Is it perhaps not supported for some reason?
     
  2. jvo3dc

    jvo3dc

    Joined:
    Oct 11, 2013
    Posts:
    1,520
    I haven't tried that before, but besides Ref, you also have ReadMask and WriteMask. Are you sure everything is set correctly? For most stencil uses I keep Ref at 255, but set the bits through the masks. Only for actual counting would it be different, but I usually use the stencil for a one bit mask.
     
  3. Thomas-Mountainborn

    Thomas-Mountainborn

    Joined:
    Jun 11, 2015
    Posts:
    501
    I have to use Ref since I also increment the value from a second object using IncrSat - the object that reads the stencil value is to be rendered only when it is inside the bounds of 2 different stencil writers. It all works just fine when I manually set the values on the materials, but the values refuse to be changed by MaterialPropertyBlocks.
     
  4. jvo3dc

    jvo3dc

    Joined:
    Oct 11, 2013
    Posts:
    1,520
    And if you set a keyword on the material from a script without MaterialPropertyBlocks? I don't know how many variations you need, but if there are not that many, some #ifdef's might also do.
     
  5. Thomas-Mountainborn

    Thomas-Mountainborn

    Joined:
    Jun 11, 2015
    Posts:
    501
    Oh, are keywords on a per renderer basis as well? If so, that would be a good solution. I'll give it a whirl when I'm back at the office.
     
  6. jvo3dc

    jvo3dc

    Joined:
    Oct 11, 2013
    Posts:
    1,520
    Well, no, per material, but it might be a good test to isolate the issue. You could also generate all the required materials in the editor.
     
  7. andrew_moran

    andrew_moran

    Joined:
    Jan 2, 2013
    Posts:
    2
    Did you manage to find a reasonable solution? I have came across the same issue when trying to change [PerRendererData]Ref value per object using MaterialPropertyBlocks. Again, it works somewhat when I duplicate materials in the editor and change Ref values directly, however, I want to do it via scripting.
     
  8. chrismarch

    chrismarch

    Joined:
    Jul 24, 2013
    Posts:
    471
    I've been struggling with this as well in 2018.3.12f1. Here's something odd: my MaterialPropertyBlock sets the value of _Stencil to 4, which is displayed in the Material inspector during play mode. However, if I change the inspector to debug mode, the value is 43! It appears that the value just remains at whatever was previously in memory...

    I dug up an old explanation from Aras: https://gist.github.com/aras-p/b2a0952161cb0c2b2cc0
    If you just use renderer.materials/GetMaterials and SetFloat, you can work around this limitation. You can also supposedly use shader globals... (but I would prefer to use a property blocks)
     
    Last edited: May 10, 2019
  9. bgolus

    bgolus

    Joined:
    Dec 7, 2012
    Posts:
    12,342
    A MaterialPropertyBlock cannot change the render state, ie: Blend, ZWrite, Stencils, etc., only the shader uniforms are changed (i.e.: the values inside the CGPROGRAM block). If you want to change a Stencil Ref you must use a new material.

    The material inspector you see when selecting a game object with a renderer component in the editor knows about property blocks and and will show the value that the shader will receive. The debug inspector is showing the actual material asset, which has not actually been modified so the value is unchanged.