text: ( function () {
  
  	/**
   * NVIDIA FXAA by Timothy Lottes
   * https://developer.download.nvidia.com/assets/gamedev/files/sdk/11/FXAA_WhitePaper.pdf
   * - WebGL port by @supereggbert
   * http://www.glge.org/demos/fxaa/
   * Further improved by Daniel Sturk
   */
  
  	const FXAAShader = {
  		uniforms: {
  			'tDiffuse': {
  				value: null
  			},
  			'resolution': {
  				value: new THREE.Vector2( 1 / 1024, 1 / 512 )
  			}
  		},
  		vertexShader:
    /* glsl */
    `
  
  		varying vec2 vUv;
  
  		void main() {
  
  			vUv = uv;
  			gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );
  
  		}`,
  		fragmentShader: `
  	precision highp float;
  
  	uniform sampler2D tDiffuse;
  
  	uniform vec2 resolution;
  
  	varying vec2 vUv;
  
  	// FXAA 3.11 implementation by NVIDIA, ported to WebGL by Agost Biro (biro@archilogic.com)
  
  	//----------------------------------------------------------------------------------
  	// File:        es3-kepler\FXAA\assets\shaders/FXAA_DefaultES.frag
  	// SDK Version: v3.00
  	// Email:       gameworks@nvidia.com
  	// Site:        http://developer.nvidia.com/
  	//
  	// Copyright (c) 2014-2015, NVIDIA CORPORATION. All rights reserved.
  	//
  	// Redistribution and use in source and binary forms, with or without
  	// modification, are permitted provided that the following conditions
  	// are met:
  	//  * Redistributions of source code must retain the above copyright
  	//    notice, this list of conditions and the following disclaimer.
  	//  * Redistributions in binary form must reproduce the above copyright
  	//    notice, this list of conditions and the following disclaimer in the
  	//    documentation and/or other materials provided with the distribution.
  	//  * Neither the name of NVIDIA CORPORATION nor the names of its
  	//    contributors may be used to endorse or promote products derived
  	//    from this software without specific prior written permission.
  	//
  	// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
  	// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  	// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
  	// PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
  	// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
  	// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
  	// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
  	// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
  	// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  	// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  	// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  	//
  	//----------------------------------------------------------------------------------
  
  	#ifndef FXAA_DISCARD
  			//
  			// Only valid for PC OpenGL currently.
  			// Probably will not work when FXAA_GREEN_AS_LUMA = 1.
  			//
  			// 1 = Use discard on pixels which don't need AA.
  			//     For APIs which enable concurrent TEX+ROP from same surface.
  			// 0 = Return unchanged color on pixels which don't need AA.
  			//
  			#define FXAA_DISCARD 0
  	#endif
  
  	/*--------------------------------------------------------------------------*/
  	#define FxaaTexTop(t, p) texture2D(t, p, -100.0)
  	#define FxaaTexOff(t, p, o, r) texture2D(t, p + (o * r), -100.0)
  	/*--------------------------------------------------------------------------*/
  
  	#define NUM_SAMPLES 5
  
  	// assumes colors have premultipliedAlpha, so that the calculated color contrast is scaled by alpha
  	float contrast( vec4 a, vec4 b ) {
  			vec4 diff = abs( a - b );
  			return max( max( max( diff.r, diff.g ), diff.b ), diff.a );
  	}
  
  	/*============================================================================
  
  									FXAA3 QUALITY - PC
  
  	============================================================================*/
  
  	/*--------------------------------------------------------------------------*/
  	vec4 FxaaPixelShader(
  			vec2 posM,
  			sampler2D tex,
  			vec2 fxaaQualityRcpFrame,
  			float fxaaQualityEdgeThreshold,
  			float fxaaQualityinvEdgeThreshold
  	) {
  			vec4 rgbaM = FxaaTexTop(tex, posM);
  			vec4 rgbaS = FxaaTexOff(tex, posM, vec2( 0.0, 1.0), fxaaQualityRcpFrame.xy);
  			vec4 rgbaE = FxaaTexOff(tex, posM, vec2( 1.0, 0.0), fxaaQualityRcpFrame.xy);
  			vec4 rgbaN = FxaaTexOff(tex, posM, vec2( 0.0,-1.0), fxaaQualityRcpFrame.xy);
  			vec4 rgbaW = FxaaTexOff(tex, posM, vec2(-1.0, 0.0), fxaaQualityRcpFrame.xy);
  			// . S .
  			// W M E
  			// . N .
  
  			bool earlyExit = max( max( max(
  					contrast( rgbaM, rgbaN ),
  					contrast( rgbaM, rgbaS ) ),
  					contrast( rgbaM, rgbaE ) ),
  					contrast( rgbaM, rgbaW ) )
  					< fxaaQualityEdgeThreshold;
  			// . 0 .
  			// 0 0 0
  			// . 0 .
  
  			#if (FXAA_DISCARD == 1)
  					if(earlyExit) FxaaDiscard;
  			#else
  					if(earlyExit) return rgbaM;
  			#endif
  
  			float contrastN = contrast( rgbaM, rgbaN );
  			float contrastS = contrast( rgbaM, rgbaS );
  			float contrastE = contrast( rgbaM, rgbaE );
  			float contrastW = contrast( rgbaM, rgbaW );
  
  			float relativeVContrast = ( contrastN + contrastS ) - ( contrastE + contrastW );
  			relativeVContrast *= fxaaQualityinvEdgeThreshold;
  
  			bool horzSpan = relativeVContrast > 0.;
  			// . 1 .
  			// 0 0 0
  			// . 1 .
  
  			// 45 deg edge detection and corners of objects, aka V/H contrast is too similar
  			if( abs( relativeVContrast ) < .3 ) {
  					// locate the edge
  					vec2 dirToEdge;
  					dirToEdge.x = contrastE > contrastW ? 1. : -1.;
  					dirToEdge.y = contrastS > contrastN ? 1. : -1.;
  					// . 2 .      . 1 .
  					// 1 0 2  ~=  0 0 1
  					// . 1 .      . 0 .
  
  					// tap 2 pixels and see which ones are "outside" the edge, to
  					// determine if the edge is vertical or horizontal
  
  					vec4 rgbaAlongH = FxaaTexOff(tex, posM, vec2( dirToEdge.x, -dirToEdge.y ), fxaaQualityRcpFrame.xy);
  					float matchAlongH = contrast( rgbaM, rgbaAlongH );
  					// . 1 .
  					// 0 0 1
  					// . 0 H
  
  					vec4 rgbaAlongV = FxaaTexOff(tex, posM, vec2( -dirToEdge.x, dirToEdge.y ), fxaaQualityRcpFrame.xy);
  					float matchAlongV = contrast( rgbaM, rgbaAlongV );
  					// V 1 .
  					// 0 0 1
  					// . 0 .
  
  					relativeVContrast = matchAlongV - matchAlongH;
  					relativeVContrast *= fxaaQualityinvEdgeThreshold;
  
  					if( abs( relativeVContrast ) < .3 ) { // 45 deg edge
  							// 1 1 .
  							// 0 0 1
  							// . 0 1
  
  							// do a simple blur
  							return mix(
  									rgbaM,
  									(rgbaN + rgbaS + rgbaE + rgbaW) * .25,
  									.4
  							);
  					}
  
  					horzSpan = relativeVContrast > 0.;
  			}
  
  			if(!horzSpan) rgbaN = rgbaW;
  			if(!horzSpan) rgbaS = rgbaE;
  			// . 0 .      1
  			// 1 0 1  ->  0
  			// . 0 .      1
  
  			bool pairN = contrast( rgbaM, rgbaN ) > contrast( rgbaM, rgbaS );
  			if(!pairN) rgbaN = rgbaS;
  
  			vec2 offNP;
  			offNP.x = (!horzSpan) ? 0.0 : fxaaQualityRcpFrame.x;
  			offNP.y = ( horzSpan) ? 0.0 : fxaaQualityRcpFrame.y;
  
  			bool doneN = false;
  			bool doneP = false;
  
  			float nDist = 0.;
  			float pDist = 0.;
  
  			vec2 posN = posM;
  			vec2 posP = posM;
  
  			int iterationsUsed = 0;
  			int iterationsUsedN = 0;
  			int iterationsUsedP = 0;
  			for( int i = 0; i < NUM_SAMPLES; i++ ) {
  					iterationsUsed = i;
  
  					float increment = float(i + 1);
  
  					if(!doneN) {
  							nDist += increment;
  							posN = posM + offNP * nDist;
  							vec4 rgbaEndN = FxaaTexTop(tex, posN.xy);
  							doneN = contrast( rgbaEndN, rgbaM ) > contrast( rgbaEndN, rgbaN );
  							iterationsUsedN = i;
  					}
  
  					if(!doneP) {
  							pDist += increment;
  							posP = posM - offNP * pDist;
  							vec4 rgbaEndP = FxaaTexTop(tex, posP.xy);
  							doneP = contrast( rgbaEndP, rgbaM ) > contrast( rgbaEndP, rgbaN );
  							iterationsUsedP = i;
  					}
  
  					if(doneN || doneP) break;
  			}
  
  
  			if ( !doneP && !doneN ) return rgbaM; // failed to find end of edge
  
  			float dist = min(
  					doneN ? float( iterationsUsedN ) / float( NUM_SAMPLES - 1 ) : 1.,
  					doneP ? float( iterationsUsedP ) / float( NUM_SAMPLES - 1 ) : 1.
  			);
  
  			// hacky way of reduces blurriness of mostly diagonal edges
  			// but reduces AA quality
  			dist = pow(dist, .5);
  
  			dist = 1. - dist;
  
  			return mix(
  					rgbaM,
  					rgbaN,
  					dist * .5
  			);
  	}
  
  	void main() {
  			const float edgeDetectionQuality = .2;
  			const float invEdgeDetectionQuality = 1. / edgeDetectionQuality;
  
  			gl_FragColor = FxaaPixelShader(
  					vUv,
  					tDiffuse,
  					resolution,
  					edgeDetectionQuality, // [0,1] contrast needed, otherwise early discard
  					invEdgeDetectionQuality
  			);
  
  	}
  	`
  	};
  
  	THREE.FXAAShader = FXAAShader;
  
  } )();
  