Search Unity

Forcing a material to update after changing a parameter?

Discussion in 'Shaders' started by doomtoo, Mar 14, 2018.

  1. doomtoo

    doomtoo

    Joined:
    Feb 16, 2015
    Posts:
    41
    When using material.SetFloatArray- how do you force the shader to run at that point?

    I'm making a drawing app, I send the point to the shader to draw, but if I send multiple points to draw- it will usually only use the last point, and the others will get ovewritten before the shader gets run.

    So for instance if I have points [0,0], [10,10], [20,20], and set them all to the material. When it actually renders, it will only render the last point on android [20,20], because it will just set each point, overwrite, and set the next point before the shader code is ever run.

    The only way I found to have it run the shader code is to only set the point once each Update- but then it's very slow.

    Any way to basically:
    material.SetFloatArray(...)
    material.RunShader(...)
    material.SetFloatArray(...)
    ?
     
  2. bgolus

    bgolus

    Joined:
    Dec 7, 2012
    Posts:
    12,336
    Two options:
    1. Change your shader to be able to draw multiple points, or potentially lines, per update rather than a single point.
    2. Render the mesh the material is on manually with multiple DrawMesh function calls, or multiple copies of the mesh, or using Blit().
    3. Do both of the above.
     
  3. doomtoo

    doomtoo

    Joined:
    Feb 16, 2015
    Posts:
    41
    Thank you for the reply!!!

    1) I was doing that before- but Android again behaves strange compared to desktop. Android complains that the points can't be longer than 240 points- but even sending over 50 points at a time, it will batch them up and somehow occasionally have too many points (so it will randomly not draw saying I'm sending over more points than the maximum amount- so same problem of not actually running the shader code until potentially multiple frames have passed)

    2) Thanks! I'l try it with the drawMesh calls!
    I use Blit after setting the parameters- and works great on Desktop- draws every point, but on Android, it seems to not do it /ignore the Blit call (right now everything works perfect on Desktop, but not Android :/)


    Thank you again for the reply!
     
  4. doomtoo

    doomtoo

    Joined:
    Feb 16, 2015
    Posts:
    41
    No Luck :/

    On PC doing multiple drawmesh calls still works the same (properly), but on Android it also doesn't change (only draws last point sent to shader before next frame).

    DrawMeshNow changes- but makes both not work/ only able to draw one point total (so seems to only take the first click) o_O

    I can add back in sending vertex arrays, but without being able to reliably know when the shader actually has run/ used those points, it's going to be too unreliable to move forward :(
     
  5. bgolus

    bgolus

    Joined:
    Dec 7, 2012
    Posts:
    12,336
    Use a materialpropertyblock with DrawMesh rather than setting values on the material directly.
     
  6. doomtoo

    doomtoo

    Joined:
    Feb 16, 2015
    Posts:
    41
    Thanks- I tried it, but same affect- works on PC, doesn't update it to the GPU on Android:

    After making a change / setting an attribute for the material/ shader:
    material.SetFloatArray("_BrushUVPosition", vec4);

    To try to make the change run/ process:

    public void Apply()
    {
    Graphics.Blit(rendertex, rendertex, material);

    MaterialPropertyBlock block = new MaterialPropertyBlock();

    block.SetColor("_Color", Color.red);
    Graphics.DrawMesh(((MeshFilter)plane.GetComponent("MeshFilter")).mesh, new Vector3(0, 0, 0), Quaternion.identity, material, 0, null, 0, block);
    }


    Just blit works on PC, but not Android :/ (will just use whatever the last point set whenever the shader does get around to running)