0
votes

I'm diving again into learning shaders and trying to get a better understanding about the way they work and I'm having trouble modifying the values of a an uniform array in the vertex program of my shader, and then passing and using those values in the fragment program.


I'm using this shader to do some calculations on "Object A", which holds the shader, based on the local matrix of a bunch of objects "Objects B".

I use those matrices in the vertex program to multiply them with the local position of the vertices of "Object A", which I then want to store those results in an array and pass into the fragment program.

I can get it working if I put the array I want to modify in a struct used by the vertex and fragment programs with the semantic TEXCOORD but this limits the size of that array to 32, which restricts the functionality even if I used all the TEXCOORD1 <--> to TEXCOORD15.

This also sets more limitations for me since I would like to use multiple arrays to store the maximum items allowed (which I believe is 1024) per array.


So I'm having a hard time understanding why I cannot modify those array values in the vertex program if I use an uniform array.

My guess is this way of passing data between vertex and fragment programs doesn't work...


Posting basic version of the shader, excluding all the non-relevant code for better readability

CGPROGRAM
            uniform float4x4 _MyMatrixArray [100];
            uniform float4 _WorldPositions [100];

            struct vertexInput{
                float4 vertex : POSITION;
                float2 uv : TEXCOORD0;
            };
            struct vertexOutput{
                float4 pos : SV_POSITION;
                float2 uv: TEXCOORD0;
                //float4 _WorldPositions [32] : TEXCOORD1;
            };


            vertexOutput vert(vertexInput input)
            {
                for(int i = 0; i < 100; i++)
                {
                    //output._WorldPositions[i] = mul(_MyMatrixArray[i], worldPos);
                    _WorldPositions[i] = mul(_MyMatrixArray[i], worldPos);
                }
            }

            float4 frag(vertexOutput input) : COLOR
            {
                for(int i = 0; i < 100; i++)
                {
                    //if (length(input._WorldPositions[i].xyz) > 0.5)
                    if (length(_WorldPositions[i].xyz) > 0.5)
                    {
                        //Do stuff
                    }
                }
            }
ENDCG

Using the commented lines works but that greatly limits the functionality of my shader.

Why can't I modify the values of the array in the vertex program if I declare it outside of a struct? Is there any way to do this?

Are there any other approaches that I should be taking when it comes to using large arrays in the way I intend to (chaning and using their values on vertex/fragment programs?

I'm kinda lost on this one, any info on this is greatly appreciated.Thanks in advance!

1
You declared the array as uniform - modifying it would mean it is no longer uniform across the shaders executionUnholySheep
@UnholySheep I see, so then I could use that uniform array on the vertex/fragment program as long as I don't change the values inside the shader itself? Like I'm doing with the other array "_MyMatrixArray[i]" which has all data predefined in an external C# script?MadLed
Yes, you can read uniform variables anywhere inside the shader. Mutable global variables are a bad idea in general, so passing values you need around as parameters is always a better ideaUnholySheep
@UnholySheep thanks a lot! I understand how uniforms are treated now in a shader. I guess I will have to do my matrix multiplications on an external way and then supply them into the uniform shader array :)MadLed

1 Answers

0
votes

I used a better approach for this that doesn't involve the need to modify uniform variables inside the shader or to declare them inside a struct.

Providing all the values for the uniform arrays from an external source and then doing distance calculations + doing a pixel discard gives me the results I wanted.