Buckets:
| import { | |
| Vector2 | |
| } from 'three'; | |
| /** | |
| * @module FXAAShader | |
| * @three_import import { FXAAShader } from 'three/addons/shaders/FXAAShader.js'; | |
| */ | |
| /** | |
| * FXAA algorithm from NVIDIA, C# implementation by Jasper Flick, GLSL port by Dave Hoskins. | |
| * | |
| * References: | |
| * - {@link http://developer.download.nvidia.com/assets/gamedev/files/sdk/11/FXAA_WhitePaper.pdf}. | |
| * - {@link https://catlikecoding.com/unity/tutorials/advanced-rendering/fxaa/}. | |
| * | |
| * @constant | |
| * @type {ShaderMaterial~Shader} | |
| */ | |
| 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 */` | |
| uniform sampler2D tDiffuse; | |
| uniform vec2 resolution; | |
| varying vec2 vUv; | |
| #define EDGE_STEP_COUNT 6 | |
| #define EDGE_GUESS 8.0 | |
| #define EDGE_STEPS 1.0, 1.5, 2.0, 2.0, 2.0, 4.0 | |
| const float edgeSteps[EDGE_STEP_COUNT] = float[EDGE_STEP_COUNT]( EDGE_STEPS ); | |
| float _ContrastThreshold = 0.0312; | |
| float _RelativeThreshold = 0.063; | |
| float _SubpixelBlending = 1.0; | |
| vec4 Sample( sampler2D tex2D, vec2 uv ) { | |
| return texture( tex2D, uv ); | |
| } | |
| float SampleLuminance( sampler2D tex2D, vec2 uv ) { | |
| return dot( Sample( tex2D, uv ).rgb, vec3( 0.3, 0.59, 0.11 ) ); | |
| } | |
| float SampleLuminance( sampler2D tex2D, vec2 texSize, vec2 uv, float uOffset, float vOffset ) { | |
| uv += texSize * vec2(uOffset, vOffset); | |
| return SampleLuminance(tex2D, uv); | |
| } | |
| struct LuminanceData { | |
| float m, n, e, s, w; | |
| float ne, nw, se, sw; | |
| float highest, lowest, contrast; | |
| }; | |
| LuminanceData SampleLuminanceNeighborhood( sampler2D tex2D, vec2 texSize, vec2 uv ) { | |
| LuminanceData l; | |
| l.m = SampleLuminance( tex2D, uv ); | |
| l.n = SampleLuminance( tex2D, texSize, uv, 0.0, 1.0 ); | |
| l.e = SampleLuminance( tex2D, texSize, uv, 1.0, 0.0 ); | |
| l.s = SampleLuminance( tex2D, texSize, uv, 0.0, -1.0 ); | |
| l.w = SampleLuminance( tex2D, texSize, uv, -1.0, 0.0 ); | |
| l.ne = SampleLuminance( tex2D, texSize, uv, 1.0, 1.0 ); | |
| l.nw = SampleLuminance( tex2D, texSize, uv, -1.0, 1.0 ); | |
| l.se = SampleLuminance( tex2D, texSize, uv, 1.0, -1.0 ); | |
| l.sw = SampleLuminance( tex2D, texSize, uv, -1.0, -1.0 ); | |
| l.highest = max( max( max( max( l.n, l.e ), l.s ), l.w ), l.m ); | |
| l.lowest = min( min( min( min( l.n, l.e ), l.s ), l.w ), l.m ); | |
| l.contrast = l.highest - l.lowest; | |
| return l; | |
| } | |
| bool ShouldSkipPixel( LuminanceData l ) { | |
| float threshold = max( _ContrastThreshold, _RelativeThreshold * l.highest ); | |
| return l.contrast < threshold; | |
| } | |
| float DeterminePixelBlendFactor( LuminanceData l ) { | |
| float f = 2.0 * ( l.n + l.e + l.s + l.w ); | |
| f += l.ne + l.nw + l.se + l.sw; | |
| f *= 1.0 / 12.0; | |
| f = abs( f - l.m ); | |
| f = clamp( f / l.contrast, 0.0, 1.0 ); | |
| float blendFactor = smoothstep( 0.0, 1.0, f ); | |
| return blendFactor * blendFactor * _SubpixelBlending; | |
| } | |
| struct EdgeData { | |
| bool isHorizontal; | |
| float pixelStep; | |
| float oppositeLuminance, gradient; | |
| }; | |
| EdgeData DetermineEdge( vec2 texSize, LuminanceData l ) { | |
| EdgeData e; | |
| float horizontal = | |
| abs( l.n + l.s - 2.0 * l.m ) * 2.0 + | |
| abs( l.ne + l.se - 2.0 * l.e ) + | |
| abs( l.nw + l.sw - 2.0 * l.w ); | |
| float vertical = | |
| abs( l.e + l.w - 2.0 * l.m ) * 2.0 + | |
| abs( l.ne + l.nw - 2.0 * l.n ) + | |
| abs( l.se + l.sw - 2.0 * l.s ); | |
| e.isHorizontal = horizontal >= vertical; | |
| float pLuminance = e.isHorizontal ? l.n : l.e; | |
| float nLuminance = e.isHorizontal ? l.s : l.w; | |
| float pGradient = abs( pLuminance - l.m ); | |
| float nGradient = abs( nLuminance - l.m ); | |
| e.pixelStep = e.isHorizontal ? texSize.y : texSize.x; | |
| if (pGradient < nGradient) { | |
| e.pixelStep = -e.pixelStep; | |
| e.oppositeLuminance = nLuminance; | |
| e.gradient = nGradient; | |
| } else { | |
| e.oppositeLuminance = pLuminance; | |
| e.gradient = pGradient; | |
| } | |
| return e; | |
| } | |
| float DetermineEdgeBlendFactor( sampler2D tex2D, vec2 texSize, LuminanceData l, EdgeData e, vec2 uv ) { | |
| vec2 uvEdge = uv; | |
| vec2 edgeStep; | |
| if (e.isHorizontal) { | |
| uvEdge.y += e.pixelStep * 0.5; | |
| edgeStep = vec2( texSize.x, 0.0 ); | |
| } else { | |
| uvEdge.x += e.pixelStep * 0.5; | |
| edgeStep = vec2( 0.0, texSize.y ); | |
| } | |
| float edgeLuminance = ( l.m + e.oppositeLuminance ) * 0.5; | |
| float gradientThreshold = e.gradient * 0.25; | |
| vec2 puv = uvEdge + edgeStep * edgeSteps[0]; | |
| float pLuminanceDelta = SampleLuminance( tex2D, puv ) - edgeLuminance; | |
| bool pAtEnd = abs( pLuminanceDelta ) >= gradientThreshold; | |
| for ( int i = 1; i < EDGE_STEP_COUNT && !pAtEnd; i++ ) { | |
| puv += edgeStep * edgeSteps[i]; | |
| pLuminanceDelta = SampleLuminance( tex2D, puv ) - edgeLuminance; | |
| pAtEnd = abs( pLuminanceDelta ) >= gradientThreshold; | |
| } | |
| if ( !pAtEnd ) { | |
| puv += edgeStep * EDGE_GUESS; | |
| } | |
| vec2 nuv = uvEdge - edgeStep * edgeSteps[0]; | |
| float nLuminanceDelta = SampleLuminance( tex2D, nuv ) - edgeLuminance; | |
| bool nAtEnd = abs( nLuminanceDelta ) >= gradientThreshold; | |
| for ( int i = 1; i < EDGE_STEP_COUNT && !nAtEnd; i++ ) { | |
| nuv -= edgeStep * edgeSteps[i]; | |
| nLuminanceDelta = SampleLuminance( tex2D, nuv ) - edgeLuminance; | |
| nAtEnd = abs( nLuminanceDelta ) >= gradientThreshold; | |
| } | |
| if ( !nAtEnd ) { | |
| nuv -= edgeStep * EDGE_GUESS; | |
| } | |
| float pDistance, nDistance; | |
| if ( e.isHorizontal ) { | |
| pDistance = puv.x - uv.x; | |
| nDistance = uv.x - nuv.x; | |
| } else { | |
| pDistance = puv.y - uv.y; | |
| nDistance = uv.y - nuv.y; | |
| } | |
| float shortestDistance; | |
| bool deltaSign; | |
| if ( pDistance <= nDistance ) { | |
| shortestDistance = pDistance; | |
| deltaSign = pLuminanceDelta >= 0.0; | |
| } else { | |
| shortestDistance = nDistance; | |
| deltaSign = nLuminanceDelta >= 0.0; | |
| } | |
| if ( deltaSign == ( l.m - edgeLuminance >= 0.0 ) ) { | |
| return 0.0; | |
| } | |
| return 0.5 - shortestDistance / ( pDistance + nDistance ); | |
| } | |
| vec4 ApplyFXAA( sampler2D tex2D, vec2 texSize, vec2 uv ) { | |
| LuminanceData luminance = SampleLuminanceNeighborhood( tex2D, texSize, uv ); | |
| if ( ShouldSkipPixel( luminance ) ) { | |
| return Sample( tex2D, uv ); | |
| } | |
| float pixelBlend = DeterminePixelBlendFactor( luminance ); | |
| EdgeData edge = DetermineEdge( texSize, luminance ); | |
| float edgeBlend = DetermineEdgeBlendFactor( tex2D, texSize, luminance, edge, uv ); | |
| float finalBlend = max( pixelBlend, edgeBlend ); | |
| if (edge.isHorizontal) { | |
| uv.y += edge.pixelStep * finalBlend; | |
| } else { | |
| uv.x += edge.pixelStep * finalBlend; | |
| } | |
| return Sample( tex2D, uv ); | |
| } | |
| void main() { | |
| gl_FragColor = ApplyFXAA( tDiffuse, resolution.xy, vUv ); | |
| }` | |
| }; | |
| export { FXAAShader }; | |
Xet Storage Details
- Size:
- 6.82 kB
- Xet hash:
- a60756a4339da7773b523efe7ad120ede59d1ce6dee09fc246fd6e181d763e54
·
Xet efficiently stores files, intelligently splitting them into unique chunks and accelerating uploads and downloads. More info.