Search Unity

Set per instance tiling and offset x,y properties on shader?

Discussion in 'Scripting' started by Unlimited_Energy, Oct 19, 2019.

  1. Unlimited_Energy

    Unlimited_Energy

    Joined:
    Jul 10, 2014
    Posts:
    469
    I have multiple game objects that are using 1 shader with a texture atlas. I created the texture atlas myself and the mesh is not combined, these are the same single mesh objects just different texture atlas samples to change up the appearance of this mesh. I want to Manually set the Tiling and offset x,y properties when a certain game object gets spawned. Im not sure how to do this, maybe a script per game object that sets the properties or do I specify this in the shader and have it set the tiling and offset based on the gameobjects name or something like that?
     
  2. Olmi

    Olmi

    Joined:
    Nov 29, 2012
    Posts:
    1,553
    @sunseeker1988 you can change the material properties (tiling, offset and any other parameter) in code, but then you create a new material instance as the settings aren't the same anymore.

    You can try this by using Material.SetTextureScale, for example. Create a simple script and set the material tiling by random in your script to lets say 30 spheres and see how the draw calls increase.

    So I wouldn't do that to 1000 objects (or whatever makes it too slow) if possible.

    One way to get around this might be to create the meshes so that their UVs look up different location on the texture page / atlas. Then they would batch fine as the material wouldn't change, only the meshes.

    But maybe you could create a pool of materials that you apply randomly to your meshes to give the appearance of randomness with a lower cost? In my experience you don't need that many different materials/textures to get a random look.
     
  3. Madgvox

    Madgvox

    Joined:
    Apr 13, 2014
    Posts:
    1,317
    Unlimited_Energy likes this.
  4. Unlimited_Energy

    Unlimited_Energy

    Joined:
    Jul 10, 2014
    Posts:
    469
    I think you mean for dynamic batching, but for GPU instancing you can change the material property blocks and not break instancing.
     
  5. Unlimited_Energy

    Unlimited_Energy

    Joined:
    Jul 10, 2014
    Posts:
    469
    how does this work tho. I have 24 game object prefabs that all use the same mesh. would I put a script on each prefab and set the offset x,y and tilling x,y on each script so that when the prefab is instantiated it will use the same material and have its own instance of tilling and offset for that prefab?
     
  6. Madgvox

    Madgvox

    Joined:
    Apr 13, 2014
    Posts:
    1,317
    That is one way to do it, yes.
     
  7. Unlimited_Energy

    Unlimited_Energy

    Joined:
    Jul 10, 2014
    Posts:
    469
    ok so I figured out I needed to create a surfgace shader. SO I did and unity pre generates a basic shader. I have spent 8 hours trying to figure out how to simply add a per instance tiling into this shader and theres NOTHING on all of the internet or unity that can tell me how to simply add a per instance property to this shader. ive tried a thousand variations of code and its compiler errors up the ass.

    Shader error in 'Custom/NewSurfaceShader': redefinition of '_TextureST' at line 44 (on d3d11)


    Code (CSharp):
    1. Properties {
    2.         _Color ("Color", Color) = (1,1,1,1)
    3.         _MainTex ("Albedo (RGB)", 2D) = "white" {}
    4.         _Glossiness ("Smoothness", Range(0,1)) = 0.5
    5.         _Metallic ("Metallic", Range(0,1)) = 0.0
    6.         _BumpMap("Normal Map", 2D) = "bump" {}
    7.        //_TextureST("Texture ST", Vector) = (1,1,0,0)
    8.     }
    9.     SubShader {
    10.         Tags { "RenderType" = "TransparentCutout" "Queue" = "Geometry+1" "IgnoreProjector" = "True" }
    11.         LOD 200
    12.  
    13.         CGPROGRAM
    14.         // Physically based Standard lighting model, and enable shadows on all light types
    15.         #pragma surface surf Standard fullforwardshadows
    16.         // Use shader model 3.0 target, to get nicer looking lighting
    17.         #pragma target 3.0
    18.             // Enable gpu instancing variants.
    19.         //    #pragma multi_compile_instancing
    20.             //#include "UnityCG.cginc"
    21.  
    22.         sampler2D _MainTex;
    23.         sampler2D _BumpMap;
    24.         float4 _TextureST;
    25.         fixed4 _Color;
    26.         //float4 _TextureST;
    27.         struct Input {
    28.             float2 uv_MainTex;
    29.             float2 uv_BumpMap;
    30.          
    31.         };
    32.  
    33.         half _Glossiness;
    34.         half _Metallic;
    35.  
    36.         // Add instancing support for this shader. You need to check 'Enable Instancing' on materials that use the shader.
    37.         // See https://docs.unity3d.com/Manual/GPUInstancing.html for more information about instancing.
    38.         // #pragma instancing_options assumeuniformscaling
    39.         UNITY_INSTANCING_BUFFER_START(Props)
    40.             // put more per-instance properties here
    41.             //_TextureST("_MainTex_ST", Vector) = (1, 1, 0, 0)
    42.             //UNITY_DEFINE_INSTANCED_PROP(fixed4, _Color)
    43.             UNITY_DEFINE_INSTANCED_PROP(float4, _TextureST)
    44.         UNITY_INSTANCING_BUFFER_END(Props)
    45.  
    46.         void surf (Input IN, inout SurfaceOutputStandard o) {
    47.             float4 texST = UNITY_ACCESS_INSTANCED_PROP(float4, _TextureST);
    48.             float2 uv = IN.uv_MainTex * UNITY_ACCESS_INSTANCED_PROP(float4, _TextureST);
    49.             //Normal Mapping
    50.             o.Albedo = tex2D(_MainTex, IN.uv_MainTex).rgb;
    51.             o.Normal = UnpackNormal(tex2D(_BumpMap, IN.uv_BumpMap));
    52.             // Albedo comes from a texture tinted by color
    53.             //fixed4 c = tex2D(_MainTex, IN.uv_MainTex) * UNITY_ACCESS_INSTANCED_PROP(fixed4, _Color);
    54.             fixed4 c = tex2D(_MainTex, IN.uv_MainTex) * _Color;
    55.             o.Albedo = c.rgb;
    56.             // Metallic and smoothness come from slider variables
    57.             o.Metallic = _Metallic;
    58.             o.Smoothness = _Glossiness;
    59.             o.Alpha = c.a;
    60.         }
    61.         ENDCG
    62.     }
    63.  
    64.     FallBack "Diffuse"
    65. }
    66.  
     
  8. Madgvox

    Madgvox

    Joined:
    Apr 13, 2014
    Posts:
    1,317
    MaterialPropertyBlocks don't require you to use a specific shader. It seems you are conflating MaterialPropertyBlocks and GPU Instancing. GPU Instancing is another option, but MaterialPropertyBlocks are far simpler to use.

    An example of using a MaterialPropertyBlock:

    Code (CSharp):
    1. var props = new MaterialPropertyBlock(); // create your mpb in Start or Awake
    2.  
    3. props.SetVector( "_MainTex_ST", new Vector4( 1, 1, 0, 0 ) );
    4.  
    5. renderer.SetPropertyBlock( props );


    Your shader is defining
    _TextureST
    both explicitly on line 24 and through a macro on line 43, which is why it's throwing an error (the macro is why the reported line number is "wrong").

    If you want to go the GPU instancing route, your surface shader looks good for the most part, but you'll want to swizzle your xy and zw coords for tiling and offset respectively:

    Code (CSharp):
    1. float4 texST = UNITY_ACCESS_INSTANCED_PROP(float4, _TextureST);
    2. float2 uv = IN.uv_MainTex * texST.xy + texST.zw;
     
    Unlimited_Energy likes this.
  9. Unlimited_Energy

    Unlimited_Energy

    Joined:
    Jul 10, 2014
    Posts:
    469
    Thank You!
     
  10. Unlimited_Energy

    Unlimited_Energy

    Joined:
    Jul 10, 2014
    Posts:
    469
    How would I set the tiling for the Normal map. not sure how to set its tiling from my _TextureST property.
     
  11. Unlimited_Energy

    Unlimited_Energy

    Joined:
    Jul 10, 2014
    Posts:
    469
    Figured it out, I needed to propertyBlock.SetVector("_BumpMap_ST", m_TextureTilingAndOffset); in my setAtlasTexture script on the gameobject prefabs.
     
    jjbish likes this.
  12. Unlimited_Energy

    Unlimited_Energy

    Joined:
    Jul 10, 2014
    Posts:
    469
    I cant get shadows to cast though...