Search Unity

Can I have instanced properties on shader?

Discussion in 'Shaders' started by bitinn, Dec 1, 2016.

  1. bitinn

    bitinn

    Joined:
    Aug 20, 2016
    Posts:
    961
    I read through GPU instancing, but don't think SetPropertyBlock is what I am looking for.

    My scenario being:

    - I have a vertex and fragment shader with some properties, say _Color.

    - I have a few different game objects, using different meshes, sharing the same material, sharing the same shader.

    - I want to set _Color per game object, but shader property acts like a static class property.

    - GPU instancing focuses on setting custom material property, not custom shader property.

    What can I do?

    Should I try to pass custom property through uv2~uv4 (as they are not in used at the moment)?
     
  2. bgolus

    bgolus

    Joined:
    Dec 7, 2012
    Posts:
    12,352
    All a material is is a shader and a collection of property values for the shader to use. A shader by itself doesn't really have any inherent property values to render with, though Unity allows you to set defaults for materials in the shader file.

    If they're different meshes, then they can't be instanced. Instancing only works when the mesh and material (and thus shader) are the exact same. Instancing allows you to define specific shader properties as instanced and can thus change between multiple instances.

    What you're describing is batching, either static or dynamic, and for that you can use different meshes sharing the same material. Batching works by combining meshes into a single mesh on the CPU and then rendering that new mesh combined on the GPU. In this case if you want unique per object settings you would have to encode them into the vertex data, either the color or the UVs, though you could also use the normals or tangents if you wanted to.

    You can set this data by assigning it on the mesh in your modelling package of choice, but you're limited to a single color32 and a float2 per UV set, or you can set it in script and use up to a float4 per UV set, though the vertex color can still only be a color32. The best way to do that is not to modify the mesh directly, but instead use additional vertex streams to modify only a part of the meshes' vertex data rather than having to keep around multiple copies of the entire mesh.
    https://docs.unity3d.com/ScriptReference/MeshRenderer-additionalVertexStreams.html
     
    bitinn likes this.
  3. bitinn

    bitinn

    Joined:
    Aug 20, 2016
    Posts:
    961
    Thx for the detailed answer @bgolus ! My question might have unnecessarily complicated your answers.

    I am mainly looking for a solution to this problem: since my materials share the same shader, if I update default property for the shader, I change the shader for every material.

    Assuming:

    - I am using Properties block to expose default properties to Unity Editor.
    - I can have multiple materials.

    I am not sure which approach is better:

    - Have multiple materials? (but how to set custom properties)
    - Have multiple shaders with different default properties? (this works, but isn't DRY.)
    - Using script to bake custom properties on Mesh as UVs? (this works, but doesn't seem like the Unity solution)
    - Or whether there are better solutions in Unity?
     
  4. bitinn

    bitinn

    Joined:
    Aug 20, 2016
    Posts:
    961
    PS: yes, you are right, I am not able to use GPU instancing due to different meshes, but I wonder if SetPropertyBlock will help me have custom properties on each materials for my shader to use...
     
  5. bitinn

    bitinn

    Joined:
    Aug 20, 2016
    Posts:
    961
    Oh god, I am so sorry, I just need to create a few materials. I was using the same material, and that somehow trick me into believing somehow my shader shares properties across different materials (besides their default value).
     
  6. Pablomon

    Pablomon

    Joined:
    Mar 9, 2015
    Posts:
    47
    Thanks for sharing, I was falling into the same trick