Hi,
I need to use hardware instancing to draw a 3D representation of a path. I want each instance of a 3D arrow to be drawn with a given color.
I set up my shader with a gradient texture and each instance is adding a normalized value in a uniform array.
Because UNITY_VERTEX_INPUT_INSTANCE_ID is a macro:
// Used in vertex shader input / output struct. #define UNITY_VERTEX_INPUT_INSTANCE_ID uint instanceID : SV_InstanceID;
So line 47 is turning into: float grad = _colorId[uint instancedID : SV_InstanceID;];
And that won’t work at all for multiple reasons. It’s not even actually for the variable you actually want to use either, that’s unity_InstanceID.
Instead you’ll want something like this:
fixed4 frag(v2f i) : SV_Target
{
// if instancing, this sets up unity_InstanceID, otherwise it does nothing
UNITY_SETUP_INSTANCE_ID(i);
#if defined(UNITY_INSTANCING_ENABLED)
// if instancing, use the unity_InstanceID to look up into the color ID array
float grad = _colorId[unity_InstanceID];
#else
// if not instancing, just set the value to 0.0 to prevent compiler errors
float grad = 0.0;
#endif
...
edit: Some notes. As of the writing of this Unity’s documentation for 5.5 and 5.6 instancing is still showing 5.4’s information, and they changed a lot of this in 5.5. Also unless you’re drawing the instances manually using Graphics.DrawMeshInstanced() the order of the arrow instances might change on you. You might be better off using per-instanced material properties instead of trying to piggyback off of the instance id, and that part of the documentation is still correct and hasn’t changed for 5.5.
Hey!
Thanks for the answer. I’m using Graphics.DrawMeshInstanced() because I don’t want to have to setup multiple property blocks (and I knew I wanted to keep the order).
One thing that throw me off is the fact that unity is replacing the macro with UNITY_VERTEX_INPUT_INSTANCE_ID…
Because Unity changed some of their macro names between Unity 5.4 and 5.5 (and I think again in 5.6). Download the built in shader source for 5.4 and 5.5 and compare the UnityInstancing.cginc (I think that’s the file name).
Unity often tweaks naming conventions in the shaders and auto-upgrades users’ shader files on editor load. They also tend to be 2 or 3 versions late to actually update the documentation to reflect those changes. For example their 5.6 documentation still lists _Object2World as the object to world space matrix, but that changed to unity_ObjectToWorld in 5.4. The shader documentation is a good starting point, but it’s always useful to dig into the shader code itself to double check.