How to define an array of floats in Shader properties?
Asked Answered
S

3

12

I'd like to define an array of floats in my shader, something like this:

Properties
{
    _TilesX ("Tiles X", Int) = 10
    _TilesY ("Tiles Y", Int) = 10

    _TileData1 ("Tile data", Float[]) = {} // THIS!!!

    _Texture1 ("Texture odd", 2D) = "white" {}
    _Texture2 ("Texture even", 2D) = "white" {}
}

I'm trying to create a single plane that I'll use as a grid and I want to modify the _TileData1 at run-time to change the Y offset of a tile. I'm using _TilesX and _TilesY to get a 2d position of the tile from a 1d array.

Just to be clear, I just want to find out how to define a property type of float[] since I couldn't find how to do so on Unity's manual pages or forums.

Skvorak answered 14/7, 2017 at 8:51 Comment(0)
S
8

Apparently not.

I didn't think so, as I'd never seen it, but I thought I'd take a search around and I ran across this thread where the person answering the question says this (emphasis mine):

You can set arrays from script using SetFloatArray, SetVectorArray, and SetColorArray as of 5.4, but you can't define an array in the properties. Basically this means you can still set the value and have it defined in the CGPROGRAM block to be used, but it won't be serialized / saved by the material asset or show up in the material editor. It's an odd omission, especially since texture arrays are supported as properties (though texture arrays are a specific type of texture sampler rather than an array of texture properties like color arrays).

So you would be able to use it in the calculation, but you would only be able to modify the value via MonoBehaviour script (and would need to).

Sleekit answered 14/7, 2017 at 14:17 Comment(1)
for some reason SetVectorArray is not working properly in ios builds, using metal apiFlint
M
20

You can't use properties for float[]. But you can use them as variables in your shader and set them from script:

In your shader:

CGPROGRAM
int _SegmentsCount = 0;
float _Segments[1000];

void surf (Input IN, inout SurfaceOutput o) {
    for (int i = 0; i < _SegmentsCount; i++) {
        // This is obsviously just an example,
        // avoid loops in shaders if you can help it.
    }
}

ENDCG

Then in your script:

float [] array = new float[] { 0.25f, 0.75f };
material.SetFloatArray("_Segments", array);
material.SetInt("_SegmentsCount", 2);

renderer.material = material;
Medellin answered 21/11, 2017 at 14:16 Comment(4)
So _Segments must have a defined length ? Can't it be changed at run time by c#?Chibouk
It can be changed in your C# code. But not in the shader (hence oversizing it to 1000 and requiring passing the length in _SegmentsCount)Medellin
A absolute gem of an answer! Thank youPhotoconductivity
Be aware that setting a float array like this means the array will NOT be serialized. So if you set it, and then call AssetDatabase.SaveAssets(), it won't make a difference and when you go to use the material later the values you had previously set will be erased.Celestyn
S
8

Apparently not.

I didn't think so, as I'd never seen it, but I thought I'd take a search around and I ran across this thread where the person answering the question says this (emphasis mine):

You can set arrays from script using SetFloatArray, SetVectorArray, and SetColorArray as of 5.4, but you can't define an array in the properties. Basically this means you can still set the value and have it defined in the CGPROGRAM block to be used, but it won't be serialized / saved by the material asset or show up in the material editor. It's an odd omission, especially since texture arrays are supported as properties (though texture arrays are a specific type of texture sampler rather than an array of texture properties like color arrays).

So you would be able to use it in the calculation, but you would only be able to modify the value via MonoBehaviour script (and would need to).

Sleekit answered 14/7, 2017 at 14:17 Comment(1)
for some reason SetVectorArray is not working properly in ios builds, using metal apiFlint
C
0

You can use a ComputeBuffer to set the float array from C#.

ComputeShader programs often need arbitrary data to be read & written into memory buffers. ComputeBuffer class is exactly for that - you can create & fill them from script code, and use them in compute shaders or regular shaders.

Example can be found on GitHub, e.g., in this audio wave form shader.

Chil answered 4/8 at 19:30 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.