DigDig.IO Effects

3D, particles and glow effect for DigDig.IO. Use num keys from 1 to 3 to toggle effects

当前为 2021-07-17 提交的版本,查看 最新版本

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Greasemonkey 油猴子Violentmonkey 暴力猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Violentmonkey 暴力猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Userscripts ,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展后才能安装此脚本。

(我已经安装了用户脚本管理器,让我安装!)

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

(我已经安装了用户样式管理器,让我安装!)

// ==UserScript==
// @name         DigDig.IO Effects
// @namespace    http://tampermonkey.net/
// @version      0.1.4
// @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
// @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==

( function () {

	unsafeWindow.enable3d = true;

	unsafeWindow.enableParticles = function ( bool ) {

		if ( bool === undefined ) {

			bool = ! particlesEnabled();

		}

		maskMaterial.uniforms.enableParticles.value = bool;

	}

	unsafeWindow.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 ) {

				const height = ctx.getTransform().d;

				if ( height > window.innerHeight * 0.75 ) {

					return;

				} else if ( height < 10 && particlesEnabled() ) {

					ctx.globalAlpha = 1;

					ctx.fillStyle = particleColor;

				}

			}

			return Reflect.apply( ...arguments );

		}
	} );

	const renderer = new THREE.WebGLRenderer( { alpha: 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 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 ) 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, 500, 500 ), material );
	scene.add( tessellation );

	const rtt = new THREE.WebGLRenderTarget( window.innerWidth, window.innerHeight );

	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 += ' && ';

		}

	}

	console.log( { 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 && value <= 1.0 ) {

				gl_FragColor = vec4( 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 = parseInt( color.slice( 1, 3 ), 16 ) / 255;
			const g = parseInt( color.slice( 3, 5 ), 16 ) / 255;
			const b = parseInt( color.slice( 5, 7 ), 16 ) / 255;

			return 'vec3(' + r + ', ' + g + ', ' + b + ')';

		}

	}

	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 () {

		composer.setSize( window.innerWidth, window.innerHeight );

		renderer.setSize( window.innerWidth, window.innerHeight );

		rtt.setSize( window.innerWidth, window.innerHeight );

		render();

	} );

	unsafeWindow.requestAnimationFrame = new Proxy( unsafeWindow.requestAnimationFrame, {
		apply( target, thisArgs, args ) {

			Reflect.apply( ...arguments );

			render()

		}
	} );

	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();

	}

} )();