[outdated]CRT screen effect

● ARCHIVED · READ-ONLY
Started by utunnels 5 posts View original ↗

  1. Warning: This plugin takes an unconventional approach to adding filtering effects to the entire screen. It may cause lag on a slow device.


    Introduction
    This is not a "full" plugin. Just a simple plugin I wrote a while back for my game, but I ended up not using it because it doesn't fit the type of the game.
    Just in case somebody needs it, I decided to share it here.
    It adds a crt monitor effect to the WHOLE screen, including the video layer and loading text.

    Terms
    You can use it in any project, credit is not required but appreciated.

    How to Use
    Save the code as a js file and put it in plugins directory. There are no parameters for this plugin, just turn it on in the editor.
    It adds a Graphics. _crtFilter property. When it's true, the filter effect is on. The property is true by default. You can edit it or change it in game if you want.

    JavaScript:
    /*
    Create a filter canvas above upper canvas (the canvas
    that displays the loading screen), the filter canvas
    is used to copy contents from the game canvas, the video,
    and the upper canvas, so you can change the pixels later.
    */
    Graphics._createUpperCanvas = function () {
      this._upperCanvas = document.createElement('canvas');
      this._upperCanvas.id = 'UpperCanvas';
      this._filterCanvas = document.createElement('canvas');
      this._filterCanvas.id = 'FilterCanvas';
      this._updateUpperCanvas();
      document.body.appendChild(this._upperCanvas);
      document.body.appendChild(this._filterCanvas);
      this._crtFilter = true;
    };
    Graphics._updateUpperCanvas = function () {
      this._upperCanvas.width = this._filterCanvas.width = this._width;
      this._upperCanvas.height = this._filterCanvas.height = this._height;
      this._upperCanvas.style.zIndex = 3;
      this._filterCanvas.style.zIndex = 4;
      this._centerElement(this._upperCanvas);
      this._centerElement(this._filterCanvas);
    };
    /*
    crt monitor effect
    */
    var rgbData = null;
    function crt(gfx, ctx) {
      var shift = gfx.frameCount;
      var canvas = ctx.canvas;
      var imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
      var data = imageData.data;
      var lw = canvas.width * 4;
      var s = Math.round(shift / 20);
      var sl = false;
      if (!rgbData) {
        rgbData = new ImageData(canvas.width, canvas.height).data;
        for (let i = 0; i < rgbData.length; i += 4) {
          var y = Math.floor(i / lw);
          var x = Math.floor((i % lw) / 4);
          var r = 128;
          var g = 128;
          var b = 128;
          x = (x + Math.floor(y / 3)) % 3;
          if (x == 0) { r += 32; g -= 16; b -= 16; }
          else if (x == 1) { g += 32; r -= 16; b -= 16; }
          else if (x == 2) { b += 32; r -= 16; g -= 16; }
          rgbData[i] = r;
          rgbData[i + 1] = g;
          rgbData[i + 2] = b;
        }
      }
      var cw = canvas.width, ch = canvas.height, i = 0, dl = data.length;
      for (var y = 0; y < ch; y++) {
        var ds = 0;
        var ss = (y + shift) % 160;
        if (ss == 0) ds = lw * 2 + 4;
        else if (ss == 1) ds = lw + 4;
        var ys = ((y + s) % 4) ? 0 : 64;
        for (var x = 0; x < cw; x++, i += 4) {
          var is = (i + ds) % dl;
          data[i] = data[is] + rgbData[i] - 128 - ys;
          data[i + 1] = data[is + 1] + rgbData[i + 1] - 128 - ys;
          data[i + 2] = data[is + 2] + rgbData[i + 2] - 128 - ys;
        }
      }
      ctx.putImageData(imageData, 0, 0);
    }
    /*
    Draw everythign on this canvas and change pixels
    */
    Graphics.renderFilterCanvas = function () {
      this._filterCanvas.style.opacity = 1;
      var ctx = this._filterCanvas.getContext('2d');
      ctx.save();
      ctx.globalAlpha = 1;
      ctx.drawImage(this._canvas, 0, 0, this.width, this.height);
      if (this.isVideoPlaying()) {
        ctx.drawImage(this._video, 0, 0, this.width, this.height);
      }
      if (this._upperCanvas.style.opacity > 0) {
        ctx.drawImage(this._upperCanvas, 0, 0, this.width, this.height);
      }
      ctx.restore();
      crt(this, ctx);
    }
    const g_paintUpperCanvas = Graphics._paintUpperCanvas;
    Graphics._paintUpperCanvas = function () {
      g_paintUpperCanvas.call(this);
      //Just in case you need to display the loading text
      if (this._crtFilter) {
        this.renderFilterCanvas();
      } else {
        this._filterCanvas.style.opacity = 0;
      }
    };
    const g_render = Graphics.render;
    Graphics.render = function (stage) {
      g_render.call(this, stage);
      if (this._crtFilter) {
        if (this._rendered) {
          this.renderFilterCanvas();
        }
      } else {
        this._filterCanvas.style.opacity = 0;
      }
    };


    1719912611504.png
  2. I love this plugin but it's causing severe lag in my game. Probably a plugin conflict so I'll come back and update if I find out.
    ALSO I wish I could get the Tsukimi PIXI filters plugin to display over all the menus etc like yours does!

    EDIT: Ok, yeah even a fresh project runs at only 30fps.
  3. Okra said:
    I love this plugin but it's causing severe lag in my game. Probably a plugin conflict so I'll come back and update if I find out.
    ALSO I wish I could get the Tsukimi PIXI filters plugin to display over all the menus etc like yours does!
    Sorry it was my very early experiment.:hswt:
    I would like to improve it but there are already better plugins out there.
    I think PIXI filters can apply on the whole screen.

    The fastest way is using a small plugin after the PIXI filter controller plugin:

    JavaScript:
    (function(alias){
    Scene_Base.prototype.initialize = function() {
      alias.apply(this,arguments);
      var filters = this.filters||[];
      filters.push(new PIXI.filters.CRTFilter());
      this.filters = filters;
    };
    })(Scene_Base.prototype.initialize);
    SceneManager.snapForBackground = function() {
      var filters = this._scene.filters;
      this._scene.filters = null;
      this._backgroundBitmap = this.snap();
      this._backgroundBitmap.blur();
      this._scene.filters = filters;
    };

    But if you want to add options to turn it on/off, or adjust parameters of the filter, there will be more work to do.
  4. utunnels said:
    Sorry it was my very early experiment.:hswt:
    I would like to improve it but I think PIXI filters can apply on the whole screen.

    You the fastest way is using a small plugin after the PIXI filter controller plugin:

    JavaScript:
    (function(alias){
    Scene_Base.prototype.initialize = function() {
      alias.apply(this,arguments);
      var filters = this.filters||[];
      filters.push(new PIXI.filters.CRTFilter());
      this.filters = filters;
    };
    })(Scene_Base.prototype.initialize);
    SceneManager.snapForBackground = function() {
      var filters = this._scene.filters;
      this._scene.filters = null;
      this._backgroundBitmap = this.snap();
      this._backgroundBitmap.blur();
      this._scene.filters = filters;
    };

    But if you want to add options to turn it on/off, or adjust parameters of the filter, there will be more work to do.

    You're the best! I'll try it out and let you know.
    EDIT: It works! My goal was to be able to apply any of the Tsukimi filters to the whole screen and also be able to control them but that might be too complicated.
  5. Spoiler
    1739199946605.png

    Just did some optimization to make it faster. I think I've abandoned it.
    The only unusual feature of the plugin is it also adds the effect over the video and loading screen.
    Beucase the plugin adds another canvas above all others and draw everything on it.
    But the performance is not great, neither is the effect as cool as the PIXI's crt filter.