289 lines
		
	
	
		
			8.3 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
		
		
			
		
	
	
			289 lines
		
	
	
		
			8.3 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
| 
								 | 
							
								import {
							 | 
						||
| 
								 | 
							
									Vector2
							 | 
						||
| 
								 | 
							
								} from 'three';
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/**
							 | 
						||
| 
								 | 
							
								 * 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 = {
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									name: 'FXAAShader',
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									uniforms: {
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										'tDiffuse': { value: null },
							 | 
						||
| 
								 | 
							
										'resolution': { value: new Vector2( 1 / 1024, 1 / 512 ) }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									},
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									vertexShader: /* glsl */`
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										varying vec2 vUv;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										void main() {
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											vUv = uv;
							 | 
						||
| 
								 | 
							
											gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										}`,
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									fragmentShader: /* glsl */`
							 | 
						||
| 
								 | 
							
										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
							 | 
						||
| 
								 | 
							
											);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
									`
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								};
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								export { FXAAShader };
							 |