Arrays in shader (.fx) not working for OpenGL

I have an OpenGL project and am currently working on the lighting system.

I am trying to add support for multiple lights by supporting passing an of array of light parameters to my shader.

However, when passing any array, my shader seems to get messed up and everything renders as red. It doesn’t matter which attribute I try setting as an array (light color, light position etc). The end result is always a red scene.

Here’s an example of how I am declaring the array in the shader:

        float  LightRange[10];

And this is how I am setting it in my c# code:

        float[] LightRange = new float[10];
        LightRange[0] = 50.0f;
        _effect.Parameters["LightRange"].SetValue(LightRange);

Referencing the indexed value in the shader is pretty standard:

         x = LightRange[index] * y;

Any ideas as to what the issue might be?

FYI, I am using build 3.7.0.1441.

Thanks.

Could it be the same problem as https://github.com/MonoGame/MonoGame/issues/6250 ?

@Alkher yes… Looks like it could be related to that issue.

Could you add your debug information etc. to the issue please ?

Another related topic - using ‘Elements’ don’t work either.
Hope this will get fixed one day

Necro’ing, did this ever get fixed? I’m having same issue.

Static arrays will work in OpenGL and DirectX. If you mark an array static it will be a real constant, that doesn’t need to be initialized from C#, you initialize it directly in HLSL.

If you have a regular non-static array you always have to initialize it from C#. In OpenGL default values don’t work at all. In DirectX default values work in general, but are broken for arrays, see my comment here for more details:

In general arrays should work. I’ve seen MojoShader optimize away unused elements of an array, which can cause problems.

OK, I was not using static but was having issues doing this in shader:

#define MAX_LIGHTS 6
float3 LightDirections[MAX_LIGHTS];
float LightRadiuses[MAX_LIGHTS];
VS_OUTPUT VS_MultiLight(VS_INPUT IN)
{
  ...
  float3 lightDir = (LightPosition[0] - WorldPos) / LightRadiuses[0];
  ...

Even when fully initializing the arrays in C# like so, filling them out and setting the arrays on the shader params:

Vector3[] LightDirections = new Vector3[MaxLights];
float[] LightRadiuses = new float[MaxLights];

I had problems even when using an array of 1 or 2 elements. The tex sampling wouldn’t work anymore, like if I literally just wrote a one-line pixel shader to return just the sample from the pixel via return tex2D(Texture, TexCoord); the results were extremely strange. As in the sampling was just not correct, things would draw but they were not the right things, it was just a mess of colors all over the screen. I figured something squirrely was going on with the arrays causing some kind of memory offsetting issue in the binary.

I rewrote it all to use numbered lights such as float3 LightDirection0 etc., which is fugly to look at it in the code but it does work. If it’s useful, I can pull the old version from my repo and experiment some more.

This is what I meant by MojoShader optimizing the array. If you are only accessing the first element, MojoShader throws away the rest of the array. I’m assuming this could mess up the offsets for parameters.

I’m wondering if things start working when you actually use all the elements.

It doesn’t. Arrays just simply do not work at the moment. Even when fully initialised and all elements used, they somehow break the shader.

I struggled with this yesterday until I also figured out that indexing variable names is probably the only way around this… I hope we get a better solution to this in the future.

Hold up. Is the shader optimization a MojoShader specific thing?

Because if ShaderConductor doesn’t, it might be worth it for me to switch to the Compute fork purely on the basis of being able to debug my shaders without getting spammed with null references every time I comment something out.

ShaderConductor will also optimize things out, if they are not needed. There’s this disableOptimizations setting here, perhaps this could change things, but it’s not used at the moment.

Arrays in general should work with SC. Whatever problem MojoShader is having here, I doubt SC has it too.

The null references sound familiar in the context of commenting out texture related stuff. What I do here is to check for null in the app by appending a question mark to the EffectParameter when setting the texture shader variable. So then the variable will only be set if the EffectParameter for the texture is not null. This makes it slower so removing this extra check later for the final check is recommended but for debugging this helps because it avoids the exceptions when the texture is not used while debugging.