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

151 Views Asked by At

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?

2

There are 2 best solutions below

0
ptomato On BEST ANSWER

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);
1
Danil S On

if someone looks for this question, I have the answer:

https://gjs-docs.gnome.org/clutter7~7_api/clutter.shadereffect#method-set_uniform_value value - a GObject.Value GObject.TYPE_FLOAT for float

and in gjs GTK Javascript they have https://gjs-docs.gnome.org/clutter7~7_api/clutter.value_set_shader_float

value_set_shader_float(value,[float]) method - Value must have been initialized using %CLUTTER_TYPE_SHADER_FLOAT.

and in Javascript version of GTK they dont have any way to initialize that CLUTTER_TYPE_SHADER_FLOAT or GObject.TYPE_FLOAT

The solution is:

function make_float(val) {
    return Math.floor(val)==val?val+0.000001:val;
}