As far as I see, Shader Graph has a texture array sampling node, but has no vector array node. I might be missing correct search terms, though.
If it’s actually missing - can we expect to get it anytime soon, and if not, can someone tell me if it’s possible to manually implement a vector array node?
Unity’s material system doesn’t have support for serializing arrays of data. You can set an array on a material, but it doesn’t have a way to add properties for them.
What I do a lot is store them in small lookup textures, though that won’t help you much without writing a custom shader editor…
Yeah, I don’t actually have any need for shader editors - I use vector arrays to pack values like smoothness and metalness in my tileset shader, allowing me to support rendering of each block in one draw call despite source assets using multi-materials. Kind of similar to MicroSplat. Those arrays are simply set from tileset data on game initialization, so I never edit them by hand and never need any in-material serialization.
Are you saying that lack of serialization support is the only reason why Shader Graph doesn’t support vector arrays?
Not necessarily, But I’d wager that having array support without being able to save the data or expose it like other properties would feel pretty broken.
Any update on this? It’s impossible to reimplement any of our level or character shaders in Shader Graph without vector array support, and those enable us to save literal thousands of draw calls, so we are effectively blocked from trying HDRP.
Encode your property values into a small lookup texture; I do this in most of my assets and for large numbers of properties it can actually be faster. If it’s texture array support you need you could wrap array access in a custom code node.
That’s a great idea for fixed properties, thanks! Can you recommend a good way to update such a lookup texture over time, though? One of the things I use arrays for per-bone damage in units, which is often updated over a dozen of units every frame - I suppose a per-unit R/W enabled texture of some sort could be feasibly used for that?
Yup; I do this in MicroSplat, though use a more elegant approach in one batch that doesn’t require a component. Basically I use a scriptable importer to make the scriptable object act as a texture to unity.
You can download MicroSplat in the Unity asset store (it’s free) and look at how the PropData class is used. The biggest issue is that Unity doesn’t serialize linear HDR textures correctly, and they recently decided they are not going to fix that bug, so you have two choices: one, construct the texture at runtime, or two, write a ScriptableAssetImporter to serialize and construct that data at import time (this is what I do in OneBatch)
I’m Trying to store a bunch of Gameobjects position and determine via shader the distance between those gameobjects without the need of making a vector3 property for each one, can’t seem to find a way of doing this via shader graph. Any tip that could guide me into this? Thank you for the previous answer btw.
Nope, you need to write code to convert the data into a texture; once there the shader needs to look that up via a texture and UV set, which the graph should be able to do fine though.
Does it work?
As far as I know you have to place all the used shader properties on the shader graph blackboard.
And you check these supposed to work locally on the material level as exposed, and leave unchecked these supposed to work globally.
Will the VectorArray work if you can’t put it there?
I created a vector array node with @Darkgaze hack!
Steps:
Create a Custom Function in ShaderGraph as follows
2) Create a file named CustomShader.cginc and paste this code inside
3) drage the file into the shader node to the Source box
#ifndef CUSTOM_INSTANCING
#define CUSTOM_INSTANCING
// This allows multiple Custom Function nodes to use the same file
// without trying to include the code multiple times (causing redefinition errors)
// Instancing Buffer
UNITY_INSTANCING_BUFFER_START(Props)
UNITY_DEFINE_INSTANCED_PROP(float4 myFloatArray[2], [2]) // creates array of size 2
UNITY_INSTANCING_BUFFER_END(Props)
// Custom Function "GetFirstElement", Outputs : float4
void GetFirstElement_float(out float4 FirstElement){
float4 array[] = UNITY_ACCESS_INSTANCED_PROP(Props, myFloatArray);
FirstElement = array[0];
}
#endif