Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  2. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

Resolved Adding per-instance normal maps to shader

Discussion in 'Shaders' started by DevDunk, Apr 21, 2021.

  1. DevDunk

    DevDunk

    Joined:
    Feb 13, 2020
    Posts:
    4,969
    I am looking for a way to add per instance normal maps to a shader.
    Currently only the colors are per instance as in the shader below

    Does anyone know if this is possible and how I would implement this?
    I am lost since most guides only cover colors being changed.

    Code (CSharp):
    1. Shader "Custom/PerInstanceColor"
    2. {
    3.     Properties {
    4.         _Color ("Color", Color) = (1,1,1,1)
    5.         _MainTex ("Albedo (RGB)", 2D) = "white" {}
    6.         _Glossiness ("Smoothness", Range(0,1)) = 0.5
    7.         _Metallic ("Metallic", Range(0,1)) = 0.0
    8.     }
    9.  
    10.     SubShader {
    11.         Tags { "RenderType"="Opaque" }
    12.         LOD 200
    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
    17.         #pragma target 3.0
    18.         sampler2D _MainTex;
    19.         struct Input {
    20.             float2 uv_MainTex;
    21.         };
    22.         half _Glossiness;
    23.         half _Metallic;
    24.         UNITY_INSTANCING_BUFFER_START(Props)
    25.            UNITY_DEFINE_INSTANCED_PROP(fixed4, _Color)
    26.         UNITY_INSTANCING_BUFFER_END(Props)
    27.         void surf (Input IN, inout SurfaceOutputStandard o) {
    28.             fixed4 c = tex2D (_MainTex, IN.uv_MainTex) * UNITY_ACCESS_INSTANCED_PROP(Props, _Color);
    29.             o.Albedo = c.rgb;
    30.             o.Metallic = _Metallic;
    31.             o.Smoothness = _Glossiness;
    32.             o.Alpha = c.a;
    33.         }
    34.         ENDCG
    35.     }
    36.     FallBack "Diffuse"
    37. }
    38.  
     
  2. bgolus

    bgolus

    Joined:
    Dec 7, 2012
    Posts:
    12,329
    Because colors, or more specifically numerical values, are the only thing you can change between instances. You cannot change the texture.* The "trick" is you don't change the texture, you use a Texture2DArray, which is a "single texture" with multiple layers and you use an instanced value to select the layer index. If you're using Unity 2020.2 or newer you don't even need to do anything custom with code to support them as you can import a texture atlas (a single source texture with all of the separate layers in a grid or long strip side by side) as a texture array. Older versions of Unity you'd have to construct the texture array manually with a custom c# script.

    Here's a simple example of what the shader (and c# if needed) looks like.
    https://gist.github.com/smkplus/cee0f5147ee27e1793f9b0e3f0400497