From 654666d272edac91b79ef2d600392f3037419f29 Mon Sep 17 00:00:00 2001 From: Garrett Johnson Date: Tue, 24 Dec 2024 14:44:00 +0900 Subject: [PATCH] Wrap the material with batched mesh uniforms --- src/plugins/three/fade/FadeMaterialManager.js | 73 +---------- src/plugins/three/fade/wrapFadeMaterial.js | 122 ++++++++++++++++++ 2 files changed, 125 insertions(+), 70 deletions(-) create mode 100644 src/plugins/three/fade/wrapFadeMaterial.js diff --git a/src/plugins/three/fade/FadeMaterialManager.js b/src/plugins/three/fade/FadeMaterialManager.js index 5eea03d4f..f6e432753 100644 --- a/src/plugins/three/fade/FadeMaterialManager.js +++ b/src/plugins/three/fade/FadeMaterialManager.js @@ -1,3 +1,5 @@ +import { wrapFadeMaterial } from './wrapFadeMaterial.js'; + export class FadeMaterialManager { constructor() { @@ -93,76 +95,7 @@ export class FadeMaterialManager { } - const params = { - fadeIn: { value: 0 }, - fadeOut: { value: 0 }, - }; - - material.defines = { - FEATURE_FADE: 0, - }; - - material.onBeforeCompile = shader => { - - shader.uniforms = { - ...shader.uniforms, - ...params, - }; - - shader.fragmentShader = shader.fragmentShader - .replace( /void main\(/, value => /* glsl */` - #if FEATURE_FADE - - // adapted from https://www.shadertoy.com/view/Mlt3z8 - float bayerDither2x2( vec2 v ) { - - return mod( 3.0 * v.y + 2.0 * v.x, 4.0 ); - - } - - float bayerDither4x4( vec2 v ) { - - vec2 P1 = mod( v, 2.0 ); - vec2 P2 = floor( 0.5 * mod( v, 4.0 ) ); - return 4.0 * bayerDither2x2( P1 ) + bayerDither2x2( P2 ); - - } - - uniform float fadeIn; - uniform float fadeOut; - #endif - - ${ value } - ` ) - .replace( /#include /, value => /* glsl */` - - ${ value } - - #if FEATURE_FADE - - float bayerValue = bayerDither4x4( floor( mod( gl_FragCoord.xy, 4.0 ) ) ); - float bayerBins = 16.0; - float dither = ( 0.5 + bayerValue ) / bayerBins; - if ( dither >= fadeIn ) { - - discard; - - } - - if ( dither < fadeOut ) { - - discard; - - } - - #endif - - ` ); - - - }; - - fadeParams.set( material, params ); + fadeParams.set( material, wrapFadeMaterial( material ) ); } diff --git a/src/plugins/three/fade/wrapFadeMaterial.js b/src/plugins/three/fade/wrapFadeMaterial.js new file mode 100644 index 000000000..f40f68c64 --- /dev/null +++ b/src/plugins/three/fade/wrapFadeMaterial.js @@ -0,0 +1,122 @@ +export function wrapFadeMaterial( material ) { + + const params = { + fadeIn: { value: 0 }, + fadeOut: { value: 0 }, + fadeTexture: { value: null }, + }; + + material.defines = { + FEATURE_FADE: 0, + }; + + material.onBeforeCompile = shader => { + + shader.uniforms = { + ...shader.uniforms, + ...params, + }; + + shader.vertexShader = shader.vertexShader + .replace( + /void\s+main()\s+{/, + value => /* glsl */` + #ifdef USE_BATCHING + + varying float vBatchId; + + #endif + + ${ value } + + #ifdef USE_BATCHING + + // add 0.5 to the value to avoid floating error that may cause flickering + vBatchId = batchId + 0.5; + + #endif + ` + ); + + shader.fragmentShader = shader.fragmentShader + .replace( /void main\(/, value => /* glsl */` + #if FEATURE_FADE + + // adapted from https://www.shadertoy.com/view/Mlt3z8 + float bayerDither2x2( vec2 v ) { + + return mod( 3.0 * v.y + 2.0 * v.x, 4.0 ); + + } + + float bayerDither4x4( vec2 v ) { + + vec2 P1 = mod( v, 2.0 ); + vec2 P2 = floor( 0.5 * mod( v, 4.0 ) ); + return 4.0 * bayerDither2x2( P1 ) + bayerDither2x2( P2 ); + + } + + #ifdef USE_BATCHING + + uniform sampler2D fadeTexture; + varying float vBatchId; + vec2 getFadeValues( const in float i ) { + + int size = textureSize( fadeTexture, 0 ).x; + int j = int( i ); + int x = j % size; + int y = j / size; + return texelFetch( fadeTexture, ivec2( x, y ), 0 ).rg; + + } + + #else + + uniform float fadeIn; + uniform float fadeOut; + + #endif + + #endif + + ${ value } + ` ) + .replace( /#include /, value => /* glsl */` + + ${ value } + + #if FEATURE_FADE + + #ifdef USE_BATCHING + + vec2 fadeValues = getFadeValues( vBatchId ); + float fadeIn = fadeValues.r; + float fadeOut = fadeValues.g; + + #endif + + float bayerValue = bayerDither4x4( floor( mod( gl_FragCoord.xy, 4.0 ) ) ); + float bayerBins = 16.0; + float dither = ( 0.5 + bayerValue ) / bayerBins; + if ( dither >= fadeIn ) { + + discard; + + } + + if ( dither < fadeOut ) { + + discard; + + } + + #endif + + ` ); + + }; + + return params; + +}