Uniform arrays in shader program

I have a shader program that uses an array of a Light struct. It stores the light color and its position in world space. Problem is, i cannot use it in the scripts with go.set.:

struct Light {
    vec3 light_pos;
    vec3 light_color;

#define LIGHT_COUNT 1

uniform Light lights[LIGHT_COUNT];
function update(self, dt)
  local light_color = lights:get_color(lights.sources[1])
  go.set("#mBigCube", "lights[0].light_color", light_color)

  local light_pos = lights:get_position(lights.sources[1])
  go.set("#mBigCube", "lights[0].light_pos", light_pos)

how can i use uniform arrays?

Ah I see, no we don’t support uniform arrays like that, you have to split them into separate vec4 uniforms (or a single mat4 array) and use go.set with the index to set it to.

uniform vec4 light_pos[LIGHT_COUNT];
uniform vec4 light_color[LIGHT_COUNT];

go.set("...", "light_pos",  vmath.vector4(...), {index = 1}) -- note: lua index starts at 1

or you can use arrays in constant buffers in the render script (API reference (render)):

local b = render.constant_buffer()
-- either set entire array directly
b.light_pos = { vmath.vector4(), vmath.vector4(), ... }
-- or set them using t[k] = v
b.light_color = {}
b.light_color[1] = vmath.vector4()

im going with the vec4’s approach, much thanks. I might open a feature request to support arrays like that, would come in handy dealing with materials and alike.

I was looking for an example with a matrix as uniform constant - maybe you could add a very simple example of setting a mat4 as a constant to the API docs? :blush:

1 Like

What have you tried so far? You need to set the constant type to “User matrix4” in the material and then it shouldn’t be much more than doing a go.set() on the named constant.


Would also need to declare the constant and use it in the shader depending on what you want to do.

uniform lowp mat4 myMatrix4;

1 Like

We could definitely add an example if it’s missing, but it would be even more appreciated if someone from the community could add it :slight_smile:

1 Like

And how do we construct such matrix in Lua (in go.set)?

I suspect vmath.matrix4 could be used?

Yep! Off the top of my head it’s something like:

Go.set(url, vmath.matrix4(…), { index = xxx })

Or you can use a constant buffer in the render script

1 Like

Thank you guys! It works! :blush:


local mat = vmath.matrix4()
mat.m00 = 0.5
go.set("#sprite", "matrix_test", mat)


varying mediump vec2 var_texcoord0;

uniform lowp sampler2D texture_sampler;
uniform lowp vec4 tint;
uniform lowp mat4 matrix_test;

void main()
    // Pre-multiply alpha since all runtime textures already are
    lowp vec4 tint_pm = vec4(tint.xyz * matrix_test[0][0], matrix_test[0][0]);
    gl_FragColor = texture2D(texture_sampler, var_texcoord0.xy) * tint_pm;




Where such example should be documented? In API? Or an example?


For contant buffer usage - hmmm, the doc for constant buffer doesn’t take into account frustum, so I guess it should be something like:

local myconstants = render.constant_buffer()
myconstants["matrix_test"] = vmath.matrix4()
myconstants["matrix_test"].m00 = 0.25

render.draw(self.tile_pred, {frustum = frustum, constants = myconstants})

But it doesn’t works out of the box, with previous changes and using new render with the render script (default), with the above changes before drawing tiles :confused:



Changing tint works, but changing matrix, doesn’t affect sprite:

local myconstants = render.constant_buffer()
myconstants.tint = vmath.vector4(2, 0.0, 0.5, 1)
myconstants.matrix_test = vmath.matrix4()
myconstants.matrix_test.m00 = 0.2



But for tint = (1,1,1,1):


So, no visible effect from matrix value used to set tint

Test_Matrix_Constant.zip (84.6 KB)

I’ll take a look, thanks! We haven’t changed this code in a while so it should really work :face_with_monocle:


I never used it, so I might made a mistake :sweat_smile:

I’ve added a note about the matrix4 user type to the materials manual:

If it makes sense to also create an example then sure, please go ahead!