Customising the RGB Matrix Effect transitions

Customising the RGB Matrix Effect transitions


3 min read

After setting up my layer indicators, I wanted an easy way to turn on/off and cycle through two RGB matrix effects. The idea was to use plain solid light (RGB_MATRIX_SOLID_COLOR) as a kind of keyboard backlighting and an RGB effect (RGB_MATRIX_CYCLE_LEFT_RIGHT) for showing off, preferably using just one key to cycle through them. Here are two ways I tried.

Method 1: Use RGB_MOD or RGB_RMOD and disable unused effects

The RGB_MOD and RGB_RMOD keycodes to cycle between the animation effects. The only problem was that it cycles through all the enabled effects and they were all enabled by default. Fortunately, it's possible to control which effects are enabled.

Initially, all effects were enabled for my keyboard in keyboards/keebio/iris/rev6b/config.h. There was a # define ENABLE_RGB_MATRIX_<effect name> for each effect. So I commented out all effects except ENABLE_RGB_MATRIX_SOLID_COLOR and ENABLE_RGB_MATRIX_CYCLE_LEFT_RIGHT. However, RGB_MOD would just cycle between the two effects. I needed a way to "turn off" the effect. I would create a custom effect for this1.

The "no animation" effect is similar to the RGB_MATRIX_SOLID_COLOR effect. The only difference is the led are set to RGB_OFF (or 0, 0, 0). I added RGB_MATRIX_CUSTOM_USER=yes to my and created the file with the following content to set up this effect:


static bool no_light(effect_params_t* params) {
    RGB_MATRIX_USE_LIMITS(led_min, led_max);
    for (uint8_t i = led_min; i < led_max; i++) {
        rgb_matrix_set_color(i, RGB_OFF);
    return rgb_matrix_check_finished_leds(led_max);

The first method required me to edit the keyboard's config.h to disable the unwanted effects. This didn't seem ideal to me as the file may change as QMK evolves (and, thus, I would need to merge the new changes with mine). On my second try, I use a custom keycode to cycle between just the three effects.

Method 2: Write code to cycle to the next animation in my keymap.c

In this method, a custom keycode is added to cycle between the three effects. I started by adding a function to my keycode.c to transition to the next effect:

// Transition to the next RGB matrix mode.
void next_light_mode(void) {
   switch(rgb_matrix_get_mode()) {
      case RGB_MATRIX_NONE:

Notice the RGB_MATRIX_CUSTOM_no_light animation. This is the same as the one from the above method2.

The next step is to assign a key. I used a custom keycode for this in keymap.c (called LIGHT):

enum custom_keycodes {

After then assigning the keycode to a key, update process_record_user to call next_light_mode when the key is pressed:

bool process_record_user(uint16_t keycode, keyrecord_t *record) {
   switch (keycode) {
       // ... (removed for brevity)
       case LIGHT:
           if (record->event.pressed) {
           return false;
       // ... 

The switch implementation in this method isn't perfect. If the keyboard happens to be at one of the other effects (possible if you have RGB_MOD somewhere), then the keyboard will go to the custom "no effect" next. But this is still good enough for my purposes.


After trying both methods, I am using the second method. The second method produces a larger firmware because of the additional effects (23,416 bytes vs 27,622 bytes) but still fits. There have also been times where still being able to use RGB_MOD to access other effects has been handy. If you're curious, here's a video of this transition in action:


  1. There is also the RBG_TOG keycode which toggles the RBG lighting on and off. Unfortunately, this wasn't going to work for me because I was using lights for layer indicators - the key was also toggling them!
  2. I first tried using RGB_MATRIX_NONE but this didn't work. The keyboard cycled between only the RGB_MATRIX_SOLID_COLOR and RGB_MATRIX_CYCLE_LEFT_RIGHT. It never turned off! Turns out RGB_MATRIX_NONE doesn't mean "no animation". See this issue.