0
\$\begingroup\$

I am building this scene in 3D using Unity 2019.3.13's Universal Render Pipeline. I have a block prefab that I want to instance, but I want to choose which are yellow and which are blue (you can see the materials are basically the same). How can I write a shader that will allow me to pick either yellow or blue in the editor for each one? Is this possible? What is the most optimal way to make dozens of identical blocks where the color is different for specific instances?

enter image description here

(I would prefer a script to a graph, something with a simple switch/boolean input and hex values: yellow: e4c658 blue: 32676a

\$\endgroup\$
1
  • \$\begingroup\$ Presumably you considered using MaterialPropertyBlocks for this? \$\endgroup\$ – DMGregory May 15 '20 at 0:04
1
\$\begingroup\$

If you just want chequerboard alternation, we can do this with a single material, and save you making/positioning/rendering individual cubes.

Chequerboard alternating material

You can see from the selection wireframe in this screenshot, we're drawing far fewer triangles this way than if every cube was a separate mesh with a distinct material from its neighbours. That also means less overdraw from interior faces that we never see.

Here I assume that each of your cubes is 1 unit wide, and they're placed at integer coordinates in world space. We can scale/shift the effect if you need a different grid alignment though.

Shader "Custom/Chequer Volume"
{
    Properties
    {
        _Color ("Color", Color) = (0.8941,0.7764,0.3450,1)
        _OtherColor("Other Color", Color) = (0.1960,0.4039,0.4156,1)
        _MainTex ("Albedo (RGB)", 2D) = "white" {}
        _Glossiness ("Smoothness", Range(0,1)) = 0.7
        _Metallic ("Metallic", Range(0,1)) = 0.0
    }
    SubShader
    {
        Tags { "RenderType"="Opaque" }
        LOD 200

        CGPROGRAM
        // Physically based Standard lighting model, and enable shadows on all light types
        #pragma surface surf Standard fullforwardshadows

        // Use shader model 3.0 target, to get nicer looking lighting
        #pragma target 3.0

        sampler2D _MainTex;

        struct Input
        {
            float2 uv_MainTex;
            float3 worldPos;
            float3 worldNormal;
        };

        half _Glossiness;
        half _Metallic;
        fixed4 _Color;
        fixed4 _OtherColor;

        // Add instancing support for this shader. You need to check 'Enable Instancing' on materials that use the shader.
        // See https://docs.unity3d.com/Manual/GPUInstancing.html for more information about instancing.
        // #pragma instancing_options assumeuniformscaling
        UNITY_INSTANCING_BUFFER_START(Props)
            // put more per-instance properties here
        UNITY_INSTANCING_BUFFER_END(Props)

        void surf (Input IN, inout SurfaceOutputStandard o)
        {
            float3 inside = round(IN.worldPos - 0.1f * IN.worldNormal);
            float parity = abs(fmod(inside.x + inside.y + inside.z, 2.0f));

            fixed4 color = lerp(_Color, _OtherColor, parity);

            // Albedo comes from a texture tinted by color
            fixed4 c = tex2D (_MainTex, IN.uv_MainTex) * color;
            o.Albedo = c.rgb;
            // Metallic and smoothness come from slider variables
            o.Metallic = _Metallic;
            o.Smoothness = _Glossiness;
            o.Alpha = c.a;
        }
        ENDCG
    }
    FallBack "Diffuse"
}
\$\endgroup\$
2
  • \$\begingroup\$ Hey, Gregory, how are you? This is awesome, but my blocks have bevels and the topology is slightly more complicated than I led on. I simplified the problem for brevity. I decided to create "prefab variants" where the only difference is the material. I don't like having two materials where the only difference is color though... ... yes, I will see if this looks good. I will use Blender to bake Normal and AO maps from a hi-res version. \$\endgroup\$ – hatinacat2000 May 17 '20 at 8:00
  • 1
    \$\begingroup\$ I've also tested this with a bevelled cube and it worked in that case too. That said, two separate materials is likely to also be fairly efficient, since all the blues can be drawn together in one batch, followed by all the yellows in a second batch. \$\endgroup\$ – DMGregory May 17 '20 at 8:21

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.