docs: function NormalMapFilter(texture)
  {
      core.AbstractFilter.call(this,
          // vertex shader
          null,
          // fragment shader
          fs.readFileSync(__dirname + '/normalMap.frag', 'utf8'),
          // custom uniforms
          {
              displacementMap:  { type: 'sampler2D', value: texture },
              scale:            { type: '2f', value: { x: 15, y: 15 } },
              offset:           { type: '2f', value: { x: 0,  y: 0 } },
              mapDimensions:    { type: '2f', value: { x: 1,  y: 1 } },
              dimensions:       { type: '4f', value: [0, 0, 0, 0] },
              // LightDir:         { type: 'f3', value: [0, 1, 0] },
              LightPos:         { type: '3f', value: [0, 1, 0] }
          }
      );
  
      texture.baseTexture._powerOf2 = true;
  
      if (texture.baseTexture.hasLoaded)
      {
          this.onTextureLoaded();
      }
      else
      {
          texture.baseTexture.once('loaded', this.onTextureLoaded, this);
      }
  }