// ==UserScript==
// @name DigDig.IO Effects
// @namespace http://tampermonkey.net/
// @version 0.1.2
// @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 ) {
if ( args[ 3 ] > window.innerHeight * 0.75 ) {
return;
} else if ( args[ 2 ] === 16 && args[ 3 ] === 16 && particlesEnabled() ) {
ctx.globalAlpha = 1;
ctx.strokeStyle = particleColor;
ctx.lineWidth = 4;
ctx.strokeRect( ...args );
return;
}
}
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 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 ];
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 () {
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();
}
} )();