DEV Community

Daniel Chou Rainho
Daniel Chou Rainho

Posted on

1

[Unity] GameObject to Shader Communication: MaterialPropertyBlocks

Intro

Each GameObject in my scene is given a unique ID, and I want this ID value to be used inside the Shader that is part of the Material of every GameObject in my scene.

Specifically, I want this identifier to be able to be stored in a Color channel, i.e. it has to be a float between 0 and 1 that is unique to every GameObject in the scene.

Architecture

In the following 3 sections I outline the 3 main scripts I used for this post.

They interact as follows:

  1. My Identification script is attached to each GameObject in the scene that I want to attribute to an unique ID.
  2. This Identification script calls a function from the script IDManager (which I have attached to another GameObject in my scence) to get a unique ID.
  3. Then, the Identification script creates a MaterialPropertyBlock object to which it assigns the ID.
  4. Finally, in my Shader which I assign to the material associated with a custom Render Objects Render Feature, I can read this ID value from the MaterialPropertyBlock to then return it in the red color channel in the fragment shader.

IDManager

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

/**
* The first id starts at 0.0001.
* We don't use 0 because that's reserved for the background.
*/

public class IDManager : MonoBehaviour
{
    public static IDManager instance; // Singleton instance
    private int lastAssignedID = 0;  // Keep track of last assigned ID
    private int totalObjects = 10000; // Total number of objects you expect

    void Awake()
    {
        // Singleton setup
        if (instance == null)
        {
            instance = this;
            DontDestroyOnLoad(gameObject); // Ensure the manager persists between scenes
        }
        else
        {
            Destroy(gameObject);
        }
    }

    public float GetUniqueID()
    {
        lastAssignedID += 1;
        return (float)lastAssignedID / totalObjects; // Normalize the ID
    }
}
Enter fullscreen mode Exit fullscreen mode

Identification

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Identification : MonoBehaviour
{
    private float _id;
    private Renderer _renderer;
    private MaterialPropertyBlock _propBlock;

    void Awake()
    {
        _id = IDManager.instance.GetUniqueID();
        _propBlock = new MaterialPropertyBlock();
        _renderer = this.gameObject.GetComponent<Renderer>();

        // TEMP
        Debug.Log("ID: " + _id);

        _renderer.GetPropertyBlock(_propBlock);
        _propBlock.SetFloat("_ID", _id);
        _renderer.SetPropertyBlock(_propBlock);
    }
}
Enter fullscreen mode Exit fullscreen mode

URP Shader

Shader "Custom/UniqueColor2"
{
    Properties
    {
        _ID ("ID", Range(0, 1)) = 0.01
    }
    SubShader
    {
        Tags { "RenderType"="Opaque" }
        LOD 100

        HLSLINCLUDE

        #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"

        CBUFFER_START(UnityPerMaterial)
            float _ID;
        CBUFFER_END

        struct VertexInput
        {
            float4 position : POSITION;
        };

        struct VertexOutput
        {
            float4 position : SV_POSITION;
        };

        ENDHLSL

        Pass
        {
            HLSLPROGRAM
            #pragma vertex vert
            #pragma fragment frag

            VertexInput vert(VertexInput v)
            {
                VertexInput o;
                o.position = TransformObjectToHClip(v.position.xyz);
                return o;
            }

            float4 frag(VertexOutput i) : SV_Target
            {
                return float4(_ID, 0, 0, 1);
            }

            ENDHLSL
        }
    }
}
Enter fullscreen mode Exit fullscreen mode

AWS Security LIVE!

Join us for AWS Security LIVE!

Discover the future of cloud security. Tune in live for trends, tips, and solutions from AWS and AWS Partners.

Learn More

Top comments (0)

AWS Security LIVE!

Tune in for AWS Security LIVE!

Join AWS Security LIVE! for expert insights and actionable tips to protect your organization and keep security teams prepared.

Learn More

👋 Kindness is contagious

Please leave a ❤️ or a friendly comment on this post if you found it helpful!

Okay