Passing an uniform texture to a shader effect in GJS

I’m trying to apply a shader effect on the entire screen, and I need to pass an uniform texture to this shader, but I don’t know if it is possible at all.

I’m trying to use a Clutter.ShaderEffect for this, but on the documentation for set_uniform_value I don’t see a way to set textures.

This is a snippet I tried to get to work, with a simple shader that should lower the red component of the frame. But it’s not working properly.
I have also tried to use a Clutter.Timeline like shown here but it seems to change nothing, and peg one core at 100%.

import { Extension } from 'resource:///org/gnome/shell/extensions/extension.js';
import Clutter from 'gi://Clutter';

export default class Test extends Extension {

  enable() {
    this._actor = global.stage;

    console.debug("test: enabling");

    var effect = new Clutter.ShaderEffect({ shader_type: 1 });
    effect.set_shader_source('\
void main() {\
  cogl_color_out.r = cogl_color_out.r / 2;\
}\
   ');
    console.debug("test: shader set");

    this._actor.add_effect_with_name("effect", effect);
    console.debug("test: effect set");
  }

  disable() {
    console.debug("test: disabling")
    this._actor.remove_effect_by_name("effect");
    console.debug("test: effect removed")
  }
}
1 Like

Do you have a standalone snippet that can reproduce the problem without needing to be loaded as a shell extension?

Unfortunately no.

You can run these two lines in LookingGlass to create the shader effect:

effect = new Clutter.ShaderEffect({ shader_type: 1 })
effect.set_shader_source('void main() { cogl_color_out.r = cogl_color_out.r / 2; }')

Then you should be able to use global.stage.add_effect_with_name("effect", effect) and global.stage.remove_effect_by_name("effect") to enable and disable the effect. Which is what the extension does. But instead, adding the effect just freezes the screen, and removing it unfreezes it.

Doing the exact same commands, but in a shell extension, applies the shader, but it’s broken. This is weird because simpler effects like Clutter.DesaturateEffect({factor: 0.5}) work the same in LookingGlass or an extension.

when using the extension, the observed behaviours are:

  1. the effect gets progressively “stronger”, like the shader is run multiple times per frame
  2. after “reaching a certain strength” some artifacts appears
  3. disabling the effect brings everything back to normal.

Again, none of this happens for other effects like Clutter.DesaturateEffect({factor: 0.5}), which just works as expected.

Instead, for the “passing a texture” part of the question i have no snippet. I don’t even know where to start.

1 Like

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.