3D, particles and glow effect for DigDig.IO. Use num keys from 1 to 3 to toggle effects
当前为 
// ==UserScript==
// @name         DigDig.IO Effects
// @namespace    http://tampermonkey.net/
// @version      0.1.9
// @description  3D, particles and glow effect for DigDig.IO. Use num keys from 1 to 3 to toggle effects
// @author       Zertalious (Zert)
// @match        *://digdig.io/*
// @icon         https://www.google.com/s2/favicons?domain=digdig.io
// @grant        none
// @require      https://unpkg.com/three@latest/build/three.min.js
// @require      https://unpkg.com/three@latest/examples/js/postprocessing/EffectComposer.js
// @require      https://unpkg.com/three@latest/examples/js/postprocessing/RenderPass.js
// @require      https://unpkg.com/three@latest/examples/js/postprocessing/UnrealBloomPass.js
// @require      https://unpkg.com/three@latest/examples/js/postprocessing/ShaderPass.js
// @require      https://unpkg.com/three@latest/examples/js/shaders/LuminosityHighPassShader.js
// @require      https://unpkg.com/three@latest/examples/js/shaders/CopyShader.js
// ==/UserScript==
window.enable3d = true;
window.enableParticles = function ( bool ) {
	if ( bool === undefined ) {
		bool = ! particlesEnabled();
	}
	maskMaterial.uniforms.enableParticles.value = bool;
}
window.enableGlow = function ( bool ) {
	if ( bool === undefined ) {
		bool = ! glowEnabled();
	}
	maskMaterial.uniforms.enableGlow.value = bool;
}
window.addEventListener( 'keyup', function ( event ) {
	const key = String.fromCharCode( event.keyCode );
	switch ( key ) {
		case '1' : enable3d = ! enable3d; break;
		case '2' : enableGlow(); break;
		case '3' : enableParticles(); break;
	}
} );
const canvas = document.getElementById( 'canvas' );
canvas.style.opacity = '0';
const particleColor = '#0000ff';
CanvasRenderingContext2D.prototype.fillRect = new Proxy( CanvasRenderingContext2D.prototype.fillRect, {
	apply( target, ctx, args ) {
		if ( ctx.globalAlpha < 1 ) {
			if ( ctx.fillStyle === '#000000' ) {
				return;
			} if ( particlesEnabled() ) {
				if ( ctx.getTransform().d < 13 ) {
					ctx.fillStyle = '#00' + Math.floor( ctx.globalAlpha * 256 ).toString( 16 ).padStart( 2, '0' ) + 'ff';
					ctx.globalAlpha = 1;
				}
			}
		}
		return Reflect.apply( ...arguments );
	}
} );
const Canvas = window.OffscreenCanvas ? OffscreenCanvas.prototype : HTMLCanvasElement.prototype;
Canvas.getContext = new Proxy( Canvas.getContext, {
	apply( target, canvas, args ) {
		const ctx = Reflect.apply( ...arguments );
		ctx.fillRect = new Proxy( ctx.fillRect, {
			apply( target, thisArgs, args ) {
				if ( ctx.globalAlpha < 1 ) {
					if ( ctx.fillStyle === '#000000' ) {
						return;
					}
				}
				return Reflect.apply( ...arguments );
			}
		} );
		return ctx;
	}
} );
window.Image = new Proxy( window.Image, {
	construct( target, thisArgs, args ) {
		const image = Reflect.construct( ...arguments );
		image.crossOrigin = 'anonymous';
		return image;
	}
} );
const renderer = new THREE.WebGLRenderer( { antialias: true, preserveDrawingBuffer: true } );
renderer.domElement.style.position = 'absolute';
renderer.domElement.style.left = '0';
renderer.domElement.style.top = '0';
renderer.domElement.style.pointerEvents = 'none';
renderer.setPixelRatio( window.devicePixelRatio );
renderer.setSize( window.innerWidth, window.innerHeight );
document.body.insertBefore( renderer.domElement, canvas );
const scene = new THREE.Scene();
const camera = new THREE.PerspectiveCamera( 60, 1, 0.1, 1000 );
camera.position.z = Math.sin( Math.PI / 3 );
const texture = new THREE.CanvasTexture( canvas );
texture.minFilter = texture.magFilter = THREE.NearestFilter;
scene.background = new THREE.Color( '#522e00' );
const ground = toVec3( scene.background );
const diamond = toVec3( '#31a59e' );
const gold = toVec3( '#a59e15' );
const lava = toVec3( '#a61906' );
const uranium = toVec3( '#32a430' );
const particle = toVec3( particleColor );
const grid = toVec3( '#4e2c00' );
const material = new THREE.RawShaderMaterial( {
	vertexShader: `
	precision mediump float;
	attribute vec3 position;
	attribute vec2 uv;
	uniform mat4 projectionMatrix;
	uniform mat4 modelViewMatrix;
	uniform sampler2D texture;
	uniform float groundDepth;
	varying vec2 vUv;
	varying float vDepth;
	void main() {
		vec4 p = vec4( position, 1.0 );
		vec3 texColor = texture2D( texture, uv ).rgb;
		if ( length( ${ground} - texColor ) < 0.05 || length( ${grid} - texColor ) < 0.05 ) {
			p.z -= groundDepth;
		}
		vDepth = - p.z;
		gl_Position = projectionMatrix * modelViewMatrix * p;
		vUv = uv;
	}
	`,
	fragmentShader: `
	precision mediump float;
	uniform sampler2D texture;
	uniform float groundDepth;
	varying vec2 vUv;
	varying float vDepth;
	void main() {
		if ( vDepth > 0.0 && vDepth < groundDepth ) {
			gl_FragColor = vec4( ${ground} * 0.8, 1.0 );
		} else {
			gl_FragColor = texture2D( texture, vUv );
		}
	}
	`,
	uniforms: {
		texture: { value: texture },
		groundDepth: { value: 0.10 }
	}
} );
const tessellation = new THREE.Mesh( new THREE.PlaneGeometry( 1, 1, window.innerWidth, window.innerHeight ), material );
scene.add( tessellation );
const rtt = new THREE.WebGLRenderTarget( window.innerWidth * window.devicePixelRatio, window.innerHeight * window.devicePixelRatio );
const array = [ diamond, gold, lava, uranium ];
let text = '';
for ( let i = 0; i < array.length; i ++ ) {
	text += 'length( ' + array[ i ] + ' - gl_FragColor.rgb ) > 0.1';
	if ( i < array.length - 1 ) {
		text += ' && ';
	}
}
const maskMaterial = new THREE.RawShaderMaterial( {
	vertexShader: `
	precision mediump float;
	attribute vec3 position;
	attribute vec2 uv;
	uniform mat4 projectionMatrix;
	uniform mat4 modelViewMatrix;
	varying vec2 vUv;
	void main() {
		gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );
		vUv = uv;
	}
	`,
	fragmentShader: `
	precision mediump float;
	uniform sampler2D texture;
	uniform bool enableParticles;
	uniform bool enableGlow;
	varying vec2 vUv;
	void main() {
		gl_FragColor = texture2D( texture, vUv );
		float value = length( ${particle} - gl_FragColor.rgb ) / 0.2;
		if ( enableParticles && gl_FragColor.r == 0.0 && gl_FragColor.b == 1.0 ) {
			gl_FragColor = vec4( 1.0, 1.0 - gl_FragColor.g, gl_FragColor.g * 0.5 + 0.5, 1.0 );
		} else if ( ! enableGlow || ${text} ) {
			gl_FragColor = vec4( 0.0 );
		}
	}
	`,
	uniforms: {
		texture: { value: undefined },
		enableParticles: { value: true },
		enableGlow: { value: true }
	}
} );
function toVec3( color ) {
	if ( color.isColor ) {
		return 'vec3(' + color.r + ', ' + color.g + ', ' + color.b + ')';
	} else {
		const [ r, g, b ] = toRGB( color );
		return 'vec3(' + r + ', ' + g + ', ' + b + ')';
	}
}
function toRGB( hex ) {
	return [
		parseInt( hex.slice( 1, 3 ), 16 ) / 255, 
		parseInt( hex.slice( 3, 5 ), 16 ) / 255, 
		parseInt( hex.slice( 5, 7 ), 16 ) / 255
	]
}
const bloomScene = new THREE.Scene();
bloomScene.background = null;
const bloomCamera = new THREE.OrthographicCamera();
bloomCamera.position.z = 5;
const mask = new THREE.Mesh( new THREE.PlaneGeometry( 2, 2 ), maskMaterial );
bloomScene.add( mask );
const finalPass = new THREE.ShaderPass(
	new THREE.ShaderMaterial( {
		uniforms: {
			baseTexture: { value: null },
			originalTexture: { value: undefined }
		},
		vertexShader: `
		varying vec2 vUv;
		void main() {
			vUv = uv;
			gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );
		}
		`,
		fragmentShader: `
		uniform sampler2D baseTexture;
		uniform sampler2D originalTexture;
		varying vec2 vUv;
		void main() {
			gl_FragColor = texture2D( originalTexture, vUv ) + texture2D( baseTexture, vUv );
		}
		`,
		defines: {}
	} ), 'baseTexture'
);
const params = {
	exposure: 1,
	bloomStrength: 0.5,
	bloomThreshold: 0,
	bloomRadius: 0
};
const bloomPass = new THREE.UnrealBloomPass( new THREE.Vector2( window.innerWidth, window.innerHeight ), 1.5, 0.4, 0.85 );
bloomPass.threshold = params.bloomThreshold;
bloomPass.strength = params.bloomStrength;
bloomPass.radius = params.bloomRadius;
const renderPass = new THREE.RenderPass( bloomScene, bloomCamera );
const composer = new THREE.EffectComposer( renderer );
composer.addPass( renderPass );
composer.addPass( bloomPass );
composer.addPass( finalPass );
window.addEventListener( 'resize', function () {
	tessellation.geometry = new THREE.PlaneGeometry( 1, 1, window.innerWidth * window.devicePixelRatio, window.innerHeight * window.devicePixelRatio );
	composer.setSize( window.innerWidth, window.innerHeight );
	renderer.setSize( window.innerWidth, window.innerHeight );
	rtt.setSize( window.innerWidth, window.innerHeight );
	render();
} );
window.requestAnimationFrame = new Proxy( window.requestAnimationFrame, {
	apply( target, thisArgs, args ) {
		args[ 0 ] = new Proxy( args[ 0 ], {
			apply() {
				Reflect.apply( ...arguments );
				render();
			}
		} )
		Reflect.apply( ...arguments );
	}
} );
function particlesEnabled() {
	return maskMaterial.uniforms.enableParticles.value === true;
}
function glowEnabled() {
	return maskMaterial.uniforms.enableGlow.value === true;
}
function render() {
	if ( ! ( enable3d || glowEnabled() || particlesEnabled() ) ) {
		if ( canvas.style.opacity === '0' ) {
			canvas.style.opacity = '1';
			renderer.domElement.style.display = 'none';
		}
		return;
	} else {
		if ( canvas.style.opacity === '1' ) {
			canvas.style.opacity = '0';
			renderer.domElement.style.display = '';
		}
	}
	texture.needsUpdate = true;
	bloomPass.strength = ( Math.sin( Date.now() / 150 ) * 0.5 + 0.5 ) * 0.75 + 0.5;
	if ( enable3d ) {
		finalPass.material.uniforms.originalTexture.value = maskMaterial.uniforms.texture.value = rtt.texture;
		renderer.setRenderTarget( rtt );
		renderer.render( scene, camera );
		renderer.setRenderTarget( null );
	} else {
		finalPass.material.uniforms.originalTexture.value = maskMaterial.uniforms.texture.value = texture;
	}
	composer.render();
}