import { WebGLRenderer, WebGLRenderTarget, Scene, OrthographicCamera, Mesh, PlaneBufferGeometry, RGBAFormat, LinearFilter, DepthTexture, UnsignedShortType } from "three";

import THREEShader from "dlib/three/THREEShader.js";
import AntialiasGLSL from "dlib/shaders/AntialiasGLSL.js";

export default class THREERenderer extends WebGLRenderer {
  constructor(options) {
    super(options);

    this.filters = [];

    this.renderTargetIn = new WebGLRenderTarget(this.domElement.width, this.domElement.height, {
      format: RGBAFormat,
      minFilter: LinearFilter,
      magFilter: LinearFilter,
      stencilBuffer: false
    });
    this.renderTargetIn.texture.generateMipmaps = false;

    this.renderTargetOut = this.renderTargetIn.clone();
    this.renderTargetOut.texture.generateMipmaps = false;

    if(this.context.getExtension("WEBGL_depth_texture")) {
      this.renderTargetIn.depthTexture = new DepthTexture();
      this.renderTargetIn.depthTexture.type = UnsignedShortType;
      this.renderTargetOut.depthTexture = new DepthTexture();
      this.renderTargetOut.depthTexture.type = UnsignedShortType;
    }

    this.scene = new Scene();
    this.scene.camera = new OrthographicCamera(-1, 1, 1, -1, 0, 1);
    this._quad = new Mesh(new PlaneBufferGeometry(2, 2));
    this._quad.frustumCulled = false;
    this.scene.add(this._quad);

    // Fix to make WebGLRenderer.render extendable
    this._render = this.render;
    delete this.render;
  }

  applyFilter(filter, renderTarget) {
    this._quad.material = filter;
    if (filter.texture) {
      filter.texture = this.renderTargetIn.texture;
    }
    if (filter.depthTexture && this.renderTargetIn.depthTexture) {
      filter.depthTexture = this.renderTargetIn.depthTexture;
    }
    this._render(this.scene, this.scene.camera, renderTarget);
    [this.renderTargetIn, this.renderTargetOut] = [this.renderTargetOut, this.renderTargetIn];
  }

  resize(width, height) {
    this.setSize(width, height, false);
    this.renderTargetIn.setSize(width, height);
    this.renderTargetOut.setSize(width, height);
  }

  render(scene, renderTarget) {
    if(!renderTarget && this.filters.length) {
      this._render(scene, scene.camera, this.renderTargetIn);
      for (let [i, filter] of this.filters.entries()) {
        this.applyFilter(filter, i < this.filters.length - 1 ? this.renderTargetOut : undefined);
      }
      this._render(this.scene, this.scene.camera);
    } else {
      this._render(scene, scene.camera, renderTarget);
      if(renderTarget === this.renderTargetOut) {
        [this.renderTargetIn, this.renderTargetOut] = [this.renderTargetOut, this.renderTargetIn];
      }
    }
  }
}

@@ -169,121 +169,8 @@
 %22;%0A%0A
-import THREEShader from %22dlib/three/THREEShader.js%22;%0Aimport AntialiasGLSL from %22dlib/shaders/AntialiasGLSL.js%22;%0A%0A
 expo
@@ -1429,25 +1429,37 @@
  if (filter.
-t
+renderTargetT
 exture) %7B%0A  
@@ -1469,17 +1469,29 @@
  filter.
-t
+renderTargetT
 exture =
@@ -1537,25 +1537,37 @@
  if (filter.
-d
+renderTargetD
 epthTexture 
@@ -1618,17 +1618,29 @@
  filter.
-d
+renderTargetD
 epthText
@@ -2029,78 +2029,145 @@
 der(
+%7B
 scene, 
-renderTarget) %7B%0A    if(!renderTarget && this.filters.length
+filters = this.filters, renderTarget, viewport, scissor = viewport%7D = %7B%7D) %7B%0A    if(viewport %7C%7C scissor) %7B%0A      if(viewport
 ) %7B%0A
+  
     
@@ -2177,324 +2177,634 @@
 his.
-_render(scene, scene.camera, this.renderTargetIn);%0A      for (let %5Bi, filter%5D of this.filters.entries()) %7B%0A        this.applyFilter(filter, i %3C this.filters.length - 1 ? this.renderTargetOut : undefined);%0A      %7D%0A      this._render(this.scene, this.scene.camera);%0A    %7D else %7B%0A      this._render(scene, scene.camera,
+setViewport(viewport%5B0%5D, viewport%5B1%5D, viewport%5B2%5D, viewport%5B3%5D);%0A      %7D%0A      this.setScissor(scissor%5B0%5D, scissor%5B1%5D, scissor%5B2%5D, scissor%5B3%5D);%0A      this.setScissorTest(true);%0A    %7D else %7B%0A      this.setScissor(0, 0, this.domElement.width, this.domElement.height);%0A      this.setViewport(0, 0, this.domElement.width, this.domElement.height);%0A      this.setScissorTest(false);%0A    %7D%0A    if(scene) %7B%0A      this._render(scene, scene.camera, filters.length ? this.renderTargetIn : renderTarget);%0A    %7D%0A    for (let %5Bi, filter%5D of filters.entries()) %7B%0A      this.applyFilter(filter, i %3C filters.length - 1 ? this.renderTargetOut :
  ren
@@ -2813,24 +2813,28 @@
 rTarget);%0A  
+  %7D%0A
     if(rende
@@ -2865,26 +2865,24 @@
 argetOut) %7B%0A
-  
       %5Bthis.
@@ -2966,24 +2966,16 @@
 getIn%5D;%0A
-      %7D%0A
     %7D%0A  

add viewport/scissors to THREERenderer, scene is now optional