cluttergjs

How to use Clutter.ShaderEffect.set_uniform_value() properly?


I am trying set a uniform float of a Clutter.ShaderEffect. This works well if floating point Numbers are passed to set_uniform_value(). However, when you pass an integer Number, an OpenGL error (1282, Invalid operation) is thrown. It seems that the implementation assumes in this case that the uniform is actually of type int. Here is a minimal example:

const {Clutter, GObject} = imports.gi;

Clutter.init(null);

let stage  = new Clutter.Stage({width: 200, height: 200});
let shader = new Clutter.ShaderEffect({shader_type: Clutter.ShaderType.FRAGMENT_SHADER});

shader.set_shader_source(`
  uniform float value;

  void main(void) {
    cogl_color_out = vec4(value, 0, 0, 1);
  }
`);

// This creates the OpenGL Error.
// shader.set_uniform_value('value', 1);

// This works however:
shader.set_uniform_value('value', 0.999);

stage.add_effect(shader);

stage.connect('destroy', () => Clutter.main_quit());
stage.show();

Clutter.main();

So how do I force set_uniform_value() to interpret the value as floating point number? Reading the documentation (https://gjs-docs.gnome.org/clutter6~6_api/clutter.shadereffect#method-set_uniform_value), I would assume that I could pass a GObject.Value - maybe like this:

let value = new GObject.Value();
value.init(GObject.TYPE_FLOAT);
value.set_float(1.0);
shader.set_uniform_value('value', value);

But this yields the error Invalid uniform of type 'GValue' for name 'value'. Maybe I now have a GObject.Value containing a GObject.Value containing a GObject.TYPE_FLOAT?


Solution

  • As of GJS 1.68.0 (GNOME 40), passing a GObject.Value works:

    let value = new GObject.Value();
    value.init(GObject.TYPE_FLOAT);
    value.set_float(1);
    shader.set_uniform_value('value', value);