Search Unity

Question How to GPU Instance the scale tiling & offset properties of a _MainTex

Discussion in 'Shaders' started by fiveampsoftware, Jul 7, 2020.

  1. fiveampsoftware

    fiveampsoftware

    Joined:
    Feb 9, 2015
    Posts:
    33
    I've been able to GPU instance shader properties like Color or Saturation using the Unity docs on GPU Instancing: https://docs.unity3d.com/Manual/GPUInstancing.html

    However I am looking for help on how to GPU Instance the _MainTex's Tiling & Offset parameters, in a material I see them as serialized as:
    _MainTex:
    m_Scale: {x: 1, y: 1}
    m_Offset: {x: 0, y: 0}


    Can anyone advise on how I can setup a super simple shader where I am able to GPU Instance these properties or add new ones to replicate them so when I apply a MaterialPropertyBlock to override tiling or offset I do not break batching?
     
  2. bgolus

    bgolus

    Joined:
    Dec 7, 2012
    Posts:
    12,352
    The
    m_Scale
    and
    m_Offset
    serialized properties are converted at runtime into the
    float4 _TexName_ST;
    and applied with a
    TRANSFORM_TEX(uv, _TexName)
    macro in the shader. That macro looks like this:
    #define TRANSFORM_TEX(tex,name) (tex.xy * name##_ST.xy + name##_ST.zw)


    If you want to include the same functionality, you need to not use the built in tiling / offset options the material exposes (I'd recommend putting a
    [NoScaleOffset]
    in front of the texture property in your shader to hide those options) and use your own Vector/float4 value to do the same thing.

    Code (csharp):
    1. [NoScaleOffset] _MainTex ("Texture", 2D) = "white" {}
    2. _MainTex_ScaleOffset ("Scale (XY) Offset (ZW)", Vector) = (1,1,0,0)
    3.  
    4. // .. .
    5.  
    6. UNITY_INSTANCING_BUFFER_START(Props)
    7.   UNITY_DEFINE_INSTANCED_PROP(float4, _MainTex_ScaleOffset)
    8. UNITY_INSTANCING_BUFFER_END(Props)
    9.  
    10. // ...
    11.  
    12. float4 scaleOffset = UNITY_ACCESS_INSTANCED_PROP(Props, _MainTex_ScaleOffset);
    13. uv.xy = uv.xy * scaleOffset.xy + scaleOffset.zw;
     
  3. fiveampsoftware

    fiveampsoftware

    Joined:
    Feb 9, 2015
    Posts:
    33
    Awesome, thanks so much! This is exactly what I needed.
     
  4. ArtemAppside

    ArtemAppside

    Joined:
    Oct 21, 2020
    Posts:
    3
    Hey. Could you provide a full shade code, please? I'll very appreciate this
     
  5. fiveampsoftware

    fiveampsoftware

    Joined:
    Feb 9, 2015
    Posts:
    33
    Here is a barebones shader that accomplishes GPU instancing for scale / offset (note: untested):
    Code (CSharp):
    1.  
    2. Shader "Test/TestShader"
    3. {
    4.     Properties
    5.     {
    6.         _MainTex ("MainTexture", 2D) = "white" {}
    7.         _MainScaleOffset ("Main Scale (XY) Offset (ZW)", Vector) = (1,1,0,0)
    8.     }
    9.     SubShader
    10.     {
    11.         Tags
    12.         {
    13.             "RenderType"="Opaque"
    14.         }
    15.         LOD 200
    16.  
    17.         CGPROGRAM
    18.         #pragma surface surf Lambert
    19.         sampler2D _MainTex;
    20.  
    21.         UNITY_INSTANCING_BUFFER_START(Props)
    22.         UNITY_DEFINE_INSTANCED_PROP(float4, _MainScaleOffset)
    23.         UNITY_INSTANCING_BUFFER_END(Props)
    24.  
    25.         struct Input
    26.         {
    27.             float2 uv_MainTex;
    28.         };
    29.  
    30.         void surf(Input IN, inout SurfaceOutput o)
    31.         {
    32.             float4 scaleOffset = UNITY_ACCESS_INSTANCED_PROP(Props, _MainScaleOffset);
    33.             float2 uv = IN.uv_MainTex * scaleOffset.xy + scaleOffset.zw;
    34.             o.Albedo = tex2D(_MainTex, uv).rgb;
    35.         }
    36.         ENDCG
    37.     }
    38.     FallBack "Mobile/Diffuse"
    39. }
    40.  
     
  6. ArtemAppside

    ArtemAppside

    Joined:
    Oct 21, 2020
    Posts:
    3
    Thanks a lot! It's working perfect