Greasy Fork is available in English.

DigDig.IO/DigWorm.IO Effects

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

  1. // ==UserScript==
  2. // @name DigDig.IO/DigWorm.IO Effects
  3. // @namespace http://tampermonkey.net/
  4. // @version 0.2.5
  5. // @description 3D, particles and glow effect for DigDig.IO and DigWorm.IO. Use num keys from 1 to 3 to toggle effects
  6. // @author Zertalious (Zert)
  7. // @match *://digdig.io/*
  8. // @match *://digworm.io/*
  9. // @icon https://www.google.com/s2/favicons?domain=digdig.io
  10. // @grant none
  11. // @require https://unpkg.com/three@0.120.0/build/three.min.js
  12. // @require https://unpkg.com/three@0.120.0/examples/js/postprocessing/EffectComposer.js
  13. // @require https://unpkg.com/three@0.120.0/examples/js/postprocessing/RenderPass.js
  14. // @require https://unpkg.com/three@0.120.0/examples/js/postprocessing/UnrealBloomPass.js
  15. // @require https://unpkg.com/three@0.120.0/examples/js/postprocessing/ShaderPass.js
  16. // @require https://unpkg.com/three@0.120.0/examples/js/shaders/LuminosityHighPassShader.js
  17. // @require https://unpkg.com/three@0.120.0/examples/js/shaders/CopyShader.js
  18. // ==/UserScript==
  19.  
  20. window.enable3d = true;
  21.  
  22. window.enableParticles = function ( bool ) {
  23.  
  24. if ( bool === undefined ) {
  25.  
  26. bool = ! particlesEnabled();
  27.  
  28. }
  29.  
  30. maskMaterial.uniforms.enableParticles.value = bool;
  31.  
  32. }
  33.  
  34. window.enableGlow = function ( bool ) {
  35.  
  36. if ( bool === undefined ) {
  37.  
  38. bool = ! glowEnabled();
  39.  
  40. }
  41.  
  42. maskMaterial.uniforms.enableGlow.value = bool;
  43.  
  44. }
  45.  
  46. window.addEventListener( 'keyup', function ( event ) {
  47.  
  48. const key = String.fromCharCode( event.keyCode );
  49.  
  50. switch ( key ) {
  51.  
  52. case '1' : enable3d = ! enable3d; break;
  53. case '2' : enableGlow(); break;
  54. case '3' : enableParticles(); break;
  55.  
  56. }
  57.  
  58. } );
  59.  
  60. const canvas = document.getElementById( 'canvas' );
  61. canvas.style.opacity = '0';
  62.  
  63. const particleColor = '#0000ff';
  64.  
  65. CanvasRenderingContext2D.prototype.fillRect = new Proxy( CanvasRenderingContext2D.prototype.fillRect, {
  66. apply( target, ctx, args ) {
  67.  
  68. if ( ctx.globalAlpha <= 1 ) {
  69.  
  70. if ( ctx.fillStyle === '#000000' ) {
  71.  
  72. return;
  73.  
  74. } if ( particlesEnabled() ) {
  75.  
  76. if ( ctx.getTransform().d < 20 ) {
  77.  
  78. ctx.fillStyle = '#00' + Math.floor( ctx.globalAlpha * 256 ).toString( 16 ).padStart( 2, '0' ) + 'ff';
  79. ctx.globalAlpha = 1;
  80.  
  81. }
  82.  
  83. }
  84.  
  85. }
  86.  
  87. return Reflect.apply( ...arguments );
  88.  
  89. }
  90. } );
  91.  
  92. const Canvas = window.OffscreenCanvas ? OffscreenCanvas.prototype : HTMLCanvasElement.prototype;
  93.  
  94. Canvas.getContext = new Proxy( Canvas.getContext, {
  95. apply( target, canvas, args ) {
  96.  
  97. const ctx = Reflect.apply( ...arguments );
  98.  
  99. ctx.fillRect = new Proxy( ctx.fillRect, {
  100. apply( target, thisArgs, args ) {
  101.  
  102. if ( ctx.globalAlpha < 1 ) {
  103.  
  104. if ( ctx.fillStyle === '#000000' ) {
  105.  
  106. return;
  107.  
  108. }
  109.  
  110. }
  111.  
  112. return Reflect.apply( ...arguments );
  113.  
  114. }
  115. } );
  116.  
  117. return ctx;
  118.  
  119. }
  120. } );
  121.  
  122. window.Image = new Proxy( window.Image, {
  123. construct( target, thisArgs, args ) {
  124.  
  125. const image = Reflect.construct( ...arguments );
  126.  
  127. image.crossOrigin = 'anonymous';
  128.  
  129. return image;
  130.  
  131. }
  132. } );
  133.  
  134. const renderer = new THREE.WebGLRenderer( { antialias: true, preserveDrawingBuffer: true } );
  135.  
  136. renderer.domElement.style.position = 'absolute';
  137. renderer.domElement.style.left = '0';
  138. renderer.domElement.style.top = '0';
  139. renderer.domElement.style.pointerEvents = 'none';
  140.  
  141. renderer.setPixelRatio( window.devicePixelRatio );
  142. renderer.setSize( window.innerWidth, window.innerHeight );
  143.  
  144. canvas.parentNode.insertBefore( renderer.domElement, canvas );
  145.  
  146. const scene = new THREE.Scene();
  147. const camera = new THREE.PerspectiveCamera( 60, 1, 0.1, 1000 );
  148.  
  149. camera.position.z = Math.sin( camera.fov * Math.PI / 180 ) * 2;
  150.  
  151. const texture = new THREE.CanvasTexture( canvas );
  152. texture.minFilter = texture.magFilter = THREE.NearestFilter;
  153.  
  154. scene.background = new THREE.Color( '#522e00' );
  155.  
  156. const ground = toVec3( scene.background );
  157. const diamond = toVec3( '#31a59e' );
  158. const gold = toVec3( '#a59e15' );
  159. const lava = toVec3( '#a61906' );
  160. const uranium = toVec3( '#32a430' );
  161. const particle = toVec3( particleColor );
  162. const grid = toVec3( '#4e2c00' );
  163. const amethyst = toVec3( '#b332b5' );
  164.  
  165. const material = new THREE.RawShaderMaterial( {
  166. vertexShader: `
  167.  
  168. attribute vec3 position;
  169.  
  170. varying vec3 vPosition;
  171.  
  172. void main() {
  173.  
  174. vPosition = position;
  175.  
  176. gl_Position = vec4( position, 1.0 );
  177.  
  178. }
  179.  
  180. `,
  181. fragmentShader: `
  182.  
  183. precision mediump float;
  184.  
  185. uniform sampler2D map;
  186. uniform float depth;
  187.  
  188. uniform mat4 modelViewMatrix;
  189. uniform mat4 projectionMatrix;
  190.  
  191. varying vec3 vPosition;
  192.  
  193. void main() {
  194.  
  195. vec4 a;
  196.  
  197. const int count = 20;
  198.  
  199. for ( int i = 0; i <= count; i ++ ) {
  200.  
  201. vec4 p = projectionMatrix * modelViewMatrix * vec4( vec3( vPosition.xy, float( i ) / float( count ) * depth ), 1.0 );
  202.  
  203. vec4 b = texture2D( map, p.xy / p.w * 0.5 + 0.5 );
  204.  
  205. if ( length( b.rgb - ${ground} ) < 0.1 || length( b.rgb - ${grid} ) < 0.1 ) {
  206.  
  207. if ( i != count ) {
  208.  
  209. b.a = 0.0;
  210.  
  211. }
  212.  
  213. } else if ( i != 0 ) {
  214.  
  215. b.rgb = ${ground} * 0.8;
  216.  
  217. }
  218.  
  219. a.rgb = a.rgb * a.a + b.rgb * b.a * ( 1.0 - a.a );
  220. a.a = a.a + b.a * ( 1.0 - a.a );
  221.  
  222. }
  223.  
  224. gl_FragColor = a;
  225.  
  226. }
  227.  
  228. `,
  229. uniforms: {
  230. map: {
  231. value: texture
  232. },
  233. depth: {
  234. value: 0.20
  235. }
  236. }
  237. } );
  238.  
  239. const tessellation = new THREE.Mesh( new THREE.PlaneGeometry( 2, 2 ), material );
  240. scene.add( tessellation );
  241.  
  242. const rtt = new THREE.WebGLRenderTarget( window.innerWidth * window.devicePixelRatio, window.innerHeight * window.devicePixelRatio );
  243.  
  244. const array = [ diamond, gold, lava, uranium, amethyst ];
  245.  
  246. let text = '';
  247.  
  248. for ( let i = 0; i < array.length; i ++ ) {
  249.  
  250. text += 'length( ' + array[ i ] + ' - gl_FragColor.rgb ) > 0.1';
  251.  
  252. if ( i < array.length - 1 ) {
  253.  
  254. text += ' && ';
  255.  
  256. }
  257.  
  258. }
  259.  
  260. const maskMaterial = new THREE.RawShaderMaterial( {
  261. vertexShader: `
  262.  
  263. precision mediump float;
  264.  
  265. attribute vec3 position;
  266. attribute vec2 uv;
  267.  
  268. uniform mat4 projectionMatrix;
  269. uniform mat4 modelViewMatrix;
  270.  
  271. varying vec2 vUv;
  272.  
  273. void main() {
  274.  
  275. gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );
  276. vUv = uv;
  277.  
  278. }
  279.  
  280. `,
  281. fragmentShader: `
  282.  
  283. precision mediump float;
  284.  
  285. uniform sampler2D texture;
  286. uniform bool enableParticles;
  287. uniform bool enableGlow;
  288.  
  289. varying vec2 vUv;
  290.  
  291. void main() {
  292.  
  293. gl_FragColor = texture2D( texture, vUv );
  294.  
  295. float value = length( ${particle} - gl_FragColor.rgb ) / 0.2;
  296.  
  297. if ( enableParticles && gl_FragColor.r == 0.0 && gl_FragColor.b == 1.0 ) {
  298.  
  299. gl_FragColor = vec4( 1.0, 1.0 - gl_FragColor.g, gl_FragColor.g * 0.5 + 0.5, 1.0 );
  300.  
  301. } else if ( ! enableGlow || ${text} ) {
  302.  
  303. gl_FragColor = vec4( 0.0 );
  304.  
  305. }
  306.  
  307. }
  308.  
  309. `,
  310. uniforms: {
  311. texture: { value: undefined },
  312. enableParticles: { value: true },
  313. enableGlow: { value: true }
  314. }
  315. } );
  316.  
  317. function toVec3( color ) {
  318.  
  319. if ( color.isColor ) {
  320.  
  321. return 'vec3(' + color.r + ', ' + color.g + ', ' + color.b + ')';
  322.  
  323. } else {
  324.  
  325. const [ r, g, b ] = toRGB( color );
  326.  
  327. return 'vec3(' + r + ', ' + g + ', ' + b + ')';
  328.  
  329. }
  330.  
  331. }
  332.  
  333. function toRGB( hex ) {
  334.  
  335. return [
  336. parseInt( hex.slice( 1, 3 ), 16 ) / 255,
  337. parseInt( hex.slice( 3, 5 ), 16 ) / 255,
  338. parseInt( hex.slice( 5, 7 ), 16 ) / 255
  339. ]
  340.  
  341. }
  342.  
  343. const bloomScene = new THREE.Scene();
  344. bloomScene.background = null;
  345.  
  346. const bloomCamera = new THREE.OrthographicCamera();
  347.  
  348. bloomCamera.position.z = 5;
  349.  
  350. const mask = new THREE.Mesh( new THREE.PlaneGeometry( 2, 2 ), maskMaterial );
  351. bloomScene.add( mask );
  352.  
  353. const finalPass = new THREE.ShaderPass(
  354. new THREE.ShaderMaterial( {
  355. uniforms: {
  356. baseTexture: { value: null },
  357. originalTexture: { value: undefined }
  358. },
  359. vertexShader: `
  360.  
  361. varying vec2 vUv;
  362.  
  363. void main() {
  364.  
  365. vUv = uv;
  366.  
  367. gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );
  368.  
  369. }
  370.  
  371. `,
  372. fragmentShader: `
  373.  
  374. uniform sampler2D baseTexture;
  375. uniform sampler2D originalTexture;
  376.  
  377. varying vec2 vUv;
  378.  
  379. void main() {
  380.  
  381. gl_FragColor = texture2D( originalTexture, vUv ) + texture2D( baseTexture, vUv );
  382.  
  383. }
  384.  
  385. `,
  386. defines: {}
  387. } ), 'baseTexture'
  388. );
  389.  
  390. const params = {
  391. exposure: 1,
  392. bloomStrength: 0.5,
  393. bloomThreshold: 0,
  394. bloomRadius: 0
  395. };
  396.  
  397. const bloomPass = new THREE.UnrealBloomPass( new THREE.Vector2( window.innerWidth, window.innerHeight ), 1.5, 0.4, 0.85 );
  398. bloomPass.threshold = params.bloomThreshold;
  399. bloomPass.strength = params.bloomStrength;
  400. bloomPass.radius = params.bloomRadius;
  401.  
  402. const renderPass = new THREE.RenderPass( bloomScene, bloomCamera );
  403.  
  404. const composer = new THREE.EffectComposer( renderer );
  405. composer.addPass( renderPass );
  406. composer.addPass( bloomPass );
  407. composer.addPass( finalPass );
  408.  
  409. window.addEventListener( 'resize', function () {
  410.  
  411. composer.setSize( window.innerWidth, window.innerHeight );
  412.  
  413. renderer.setSize( window.innerWidth, window.innerHeight );
  414.  
  415. rtt.setSize( window.innerWidth, window.innerHeight );
  416.  
  417. render();
  418.  
  419. } );
  420.  
  421. window.requestAnimationFrame = new Proxy( window.requestAnimationFrame, {
  422. apply( target, thisArgs, args ) {
  423.  
  424. args[ 0 ] = new Proxy( args[ 0 ], {
  425. apply() {
  426.  
  427. Reflect.apply( ...arguments );
  428.  
  429. render();
  430.  
  431. }
  432. } )
  433.  
  434. Reflect.apply( ...arguments );
  435.  
  436. }
  437. } );
  438.  
  439. function particlesEnabled() {
  440.  
  441. return maskMaterial.uniforms.enableParticles.value === true;
  442.  
  443. }
  444.  
  445. function glowEnabled() {
  446.  
  447. return maskMaterial.uniforms.enableGlow.value === true;
  448.  
  449. }
  450.  
  451. function render() {
  452.  
  453. if ( ! ( enable3d || glowEnabled() || particlesEnabled() ) ) {
  454.  
  455. if ( canvas.style.opacity === '0' ) {
  456.  
  457. canvas.style.opacity = '1';
  458. renderer.domElement.style.display = 'none';
  459.  
  460. }
  461.  
  462. return;
  463.  
  464. } else {
  465.  
  466. if ( canvas.style.opacity === '1' ) {
  467.  
  468. canvas.style.opacity = '0';
  469. renderer.domElement.style.display = '';
  470.  
  471. }
  472.  
  473. }
  474.  
  475. texture.needsUpdate = true;
  476.  
  477. bloomPass.strength = ( Math.sin( Date.now() / 150 ) * 0.5 + 0.5 ) * 0.75 + 0.5;
  478.  
  479. if ( enable3d ) {
  480.  
  481. finalPass.material.uniforms.originalTexture.value = maskMaterial.uniforms.texture.value = rtt.texture;
  482.  
  483. renderer.setRenderTarget( rtt );
  484. renderer.render( scene, camera );
  485.  
  486. renderer.setRenderTarget( null );
  487.  
  488. } else {
  489.  
  490. finalPass.material.uniforms.originalTexture.value = maskMaterial.uniforms.texture.value = texture;
  491.  
  492. }
  493.  
  494. composer.render();
  495.  
  496. }