javascriptgnomecluttergnome-shellgnome-shell-extensions

ClutterShaderEffect with gnome extension


The purpose of my project is to implement a shader and attach it on stage. I want a whole screen deformation using JS gnome extension system. (I did it in C and recompile gnome but I would like to use a technology without any compilation needed).

Then, I'm looking for implement and attach a custom ShaderEffect to stage. I tried to do it with the following code, but the whole screen freeze :

fx = new Clutter.ShaderEffect({
        shader_type: Clutter.ShaderType.FRAGMENT_SHADER });
fx.set_shader_source(shader);
fx.set_uniform_value('height', this._actor.get_height());
fx.set_uniform_value('width', this._actor.get_width());
this._actor.add_effect_with_name('shader', fx);

this._actor = global.stage. This is working but the screen freeze. So I read the documentation and found this Doc link:

Implementing a ClutterOffscreenEffect Creating a sub-class of ClutterOffscreenEffect requires, in case of overriding the ClutterEffect virtual functions, to chain up to the ClutterOffscreenEffect's implementation. On top of the ClutterEffect's virtual functions, ClutterOffscreenEffect also provides a ClutterOffscreenEffectClass.paint_target() function, which encapsulates the effective painting of the texture that contains the result of the offscreen redirection.

But how am I suppose to do it in JS ?

const ClutterShaderEffectCustom = new Lang.Class({
  Name : 'ClutterShaderEffectCustom',
  Extends : Clutter.ShaderEffect,

  _init : function(shader_type, actor, shaderSource) {
      // some stuff 
  },

  paint_target : function() {
     // TODO but how ? :/
  }
});

Because I had some C files doing it, but I don't have any clue how to implement it in JS. The non official JS documentation is not helping.

I also tried something else with Clutter.Shader :

fx = new Clutter.Shader();
fx.set_fragment_source(shader, shader.lenght);
fx.set_uniform('height', this._actor.get_height());
fx.set_uniform('width', this._actor.get_width());
this._actor.set_shader(fx);

But the shader was applied only on childs, not on stage. this._actor = global.stage. Here is an overview of the result of the use of the second method. My shader is duplicating the textures, just for the test.But why only on icons and not on the whole screens since I attach it on stage ?

Overview of the second method using Clutter.Shader


Solution

  • I fixed my non refresh problem by using the following source code :

    myFunction : function() {
        fx = new Clutter.ShaderEffect({
            shader_type: Clutter.ShaderType.FRAGMENT_SHADER });
        fx.set_shader_source(shader);
        fx.set_uniform_value('height', this._actor.get_height());
        fx.set_uniform_value('width', this._actor.get_width());
        this._actor.add_effect_with_name('shader', fx); 
        this._timeline = new Clutter.Timeline({ duration: 1, repeat_count: -1 });
        this._timeline.connect('new-frame', Lang.bind(this, this._newFrame));
        this._timeline.start();
    }
    
    _newFrame: function() {
        this._actor.scale_y = 1.0;
    }