How to make shaders in this three.js minecraft script?:

Minecraft.js by HritikRC body { margin : 0; }
<script src = "three.js"></script>
<script src = "perlin.js"></script>
<script src = "PointerLockControls.js"></script>
<script src = "stats.js"></script>
<script type="text/javascript">
	var stats = new Stats();
	stats.showPanel(0); // 0:fps, 1:ms, 2:mb, 3+:custom
	document.body.appendChild(stats.dom);

	function animate(){
		stats.begin();

		// monitored code goes between this called functions

		stats.end();

		requestAnimationFrame(animate);
	}

	requestAnimationFrame(animate);

	noise.seed(0);

	var scene = new THREE.Scene();
	scene.background = new THREE.Color(0x00ffff);
	scene.fog = new THREE.Fog(0x00ffff, 10, 20000);
	var renderer = new THREE.WebGLRenderer();
	renderer.setSize(window.innerWidth, window.innerHeight);
	document.body.appendChild(renderer.domElement);
	var camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);

	/*
	var groundBox = new THREE.BoxBufferGeometry(25, 1, 50);
	var groundMesh = new THREE.MeshBasicMaterial({color : 0x00ff00});
	var ground = new THREE.Mesh(groundBox, groundMesh);
	scene.add(ground);
	ground.position.y = -5;

	// Creating the border lines for ground
	var edges = new THREE.EdgesGeometry(groundBox);
	var line = new THREE.LineSegments(edges, new THREE.LineBasicMaterial({color : 0x000000}));
	scene.add(line);
	line.position.y = -5;
	*/

	var faces = [
		{ // left
		    dir: [ -5,  0,  0, "left"],
		},
		{ // right
		    dir: [  5,  0,  0, "right"],
		},
		{ // bottom
		    dir: [  0, -5,  0, "bottom"],
		},
		{ // top
		    dir: [  0,  5,  0, "top"],
		},
		{ // back
		    dir: [  0,  0, -5, "back"],
		},
		{ // front
		    dir: [  0,  0,  5, "front"],
		},
	];

	function Block(x, y, z, placed){
		this.x = x;
		this.y = y;
		this.z = z;
		this.placed = placed;
	}

	// var axesHelper = new THREE.AxesHelper( 5 );
	// scene.add( axesHelper );

	/*
	var blocks = [];
	var xoff = 0;
	var zoff = 0;
	var inc = 0.05;
	var amplitude = 50;
	for(var x = 0; x < 20; x++){
		xoff = 0;
		for(var z = 0; z < 20; z++){
			var v = Math.round(noise.perlin2(xoff, zoff) * amplitude / 5) * 5;
			blocks.push(new Block(x * 5, v, z * 5));
			xoff = xoff + inc;
		}
		zoff = zoff + inc;
	}
	*/

	var chunks = [];
	var xoff = 0;
	var zoff = 0;
	var inc = 0.05;
	var amplitude = 50
	var renderDistance = 35;
	var chunkSize = 10;
	camera.position.x = 0;
	camera.position.z = 0;
	camera.position.y = 0;

	var loader = new THREE.TextureLoader();
	var materialArray = [
		new THREE.MeshBasicMaterial({map : loader.load("texture/side.jpg")}),
		new THREE.MeshBasicMaterial({map : loader.load("texture/side.jpg")}),
		new THREE.MeshBasicMaterial({map : loader.load("texture/top.jpg")}),
		new THREE.MeshBasicMaterial({map : loader.load("texture/bottom.jpg")}),
		new THREE.MeshBasicMaterial({map : loader.load("texture/side.jpg")}),
		new THREE.MeshBasicMaterial({map : loader.load("texture/side.jpg")}),
	];

	let leaves_box = new THREE.BoxGeometry(25, 25, 25)
	let leaves_front_material = new THREE.MeshBasicMaterial({map : loader.load("texture/leaves.png"),side:THREE.DoubleSide})
	let leaves2_box = new THREE.BoxGeometry(27, 27, 27)
	let leaves_front2_material = new THREE.MeshBasicMaterial({map : loader.load("texture/leaves.png"),transparent:true})
	let leaves3_box = new THREE.BoxGeometry(29, 29, 29)
	let leaves_front3_material = new THREE.MeshBasicMaterial({map : loader.load("texture/leaves.png"),transparent:true})
	let leaves_mesh = {}
	let trunk_box = new THREE.BoxGeometry(5, 40, 5)
	let trunk_material = new THREE.MeshBasicMaterial({map : loader.load("texture/trunk.png"),side:THREE.DoubleSide})
	let trunk_mesh={}

	var blockBox = new THREE.BoxGeometry(5, 15, 5)
	var instancedChunk = new THREE.InstancedMesh(blockBox, materialArray, renderDistance * renderDistance * chunkSize * chunkSize);
	var count = 0;
	for(var i = 0; i < renderDistance; i++){
		for(j = 0; j < renderDistance; j++){
			var chunk = [];
			for(var x = i * chunkSize; x < (i * chunkSize) + chunkSize; x++){
				for(var z = j * chunkSize; z < (j * chunkSize) + chunkSize; z++){
					xoff = inc * x;
					zoff = inc * z;
					var v = Math.round(noise.perlin2(xoff, zoff) * amplitude / 5
					 + noise.perlin2(xoff / 100, zoff / 100) * amplitude / 5 * 100
					 + noise.perlin2(xoff / 100000, zoff / 100000) * amplitude / 5 * 10000) * 5;
					chunk.push(new Block(x * 5, v, z * 5));
					if(Math.random()<0.0005){
						id=Math.random()
						trunk_mesh[id]={}
						trunk_mesh[id].c = new THREE.Mesh(trunk_box,trunk_material)
						trunk_mesh[id].c.position.set(x * 5, v + 20, z * 5)
						scene.add(trunk_mesh[id].c)
						id=Math.random()
						leaves_mesh[id]={}
						leaves_mesh[id].c = new THREE.Mesh(leaves_box,leaves_front_material)
						leaves_mesh[id].c.position.set(x * 5, v + 50, z * 5)
						scene.add(leaves_mesh[id].c)
						id=Math.random()
						leaves_mesh[id]={}
						leaves_mesh[id].c = new THREE.Mesh(leaves2_box,leaves_front2_material)
						leaves_mesh[id].c.position.set(x * 5, v + 50, z * 5)
						scene.add(leaves_mesh[id].c)
						id=Math.random()
						leaves_mesh[id]={}
						leaves_mesh[id].c = new THREE.Mesh(leaves3_box,leaves_front3_material)
						leaves_mesh[id].c.position.set(x * 5, v + 50, z * 5)
						scene.add(leaves_mesh[id].c)
					}
					let matrix = new THREE.Matrix4().makeTranslation(
						x * 5,
						v,
						z * 5
					);
					instancedChunk.setMatrixAt(count, matrix);
					count++;
				}
			}
			chunks.push(chunk);
		}
	}

	scene.add(instancedChunk);

	var keys = [];
	var canJump = true;
	var controlOptions = {
		forward : "w",
		backward : "s",
		right : "d",
		left : "a",
		jump : " ", // " " = space
		placeBlock : "q" 
	};

	var placedBlocks = [];
	var chunkMap = [];
	for(var x = 0; x < renderDistance; x++){
		for(var z = 0; z < renderDistance; z++){
			chunkMap.push({x : x, z : z});
		}
	}

	function identifyChunk(x, z){
		var lowestX = lowestXBlock();
		var lowestZ = lowestZBlock();
		var difX = x - lowestX;
		var difZ = z - lowestZ;
		var divX = Math.floor(difX / (chunkSize * 5));
		var divZ = Math.floor(difZ / (chunkSize * 5));
		var index = undefined;
		for(var i = 0; i < chunkMap.length; i++){
			if(chunkMap[i].x == divX && chunkMap[i].z == divZ){
				index = i;
				break;
			}
		}
		return index; // Identified the chunks!!!
	}

	document.addEventListener("keydown", function(e){
		keys.push(e.key);
		if(e.key == controlOptions.jump && canJump == true){
			ySpeed = -0.9;
			canJump = false;
		}
	});
	document.addEventListener("keyup", function(e){
		var newArr = [];
		for(var i = 0; i < keys.length; i++){
			if(keys[i] != e.key){
				newArr.push(keys[i]);
			}
		}
		keys = newArr;
	});

	var controls = new THREE.PointerLockControls(camera, document.body);
	var brokenBlocks = [];
	document.body.addEventListener("click", function(){
		controls.lock();
		// Breaking blocks
		if(controls.isLocked){
			// Shooting a ray
			const raycaster = new THREE.Raycaster();
			const pointer = new THREE.Vector2();
			pointer.x = (0.5) * 2 - 1;
			pointer.y = -1 * (0.5) * 2 + 1;
			raycaster.setFromCamera(pointer, camera);
			var intersection = raycaster.intersectObject(instancedChunk);
			if(intersection[0] != undefined && intersection[0].distance < 40){
				// finding x, y, z positions of that 
				console.log(intersection[0].point);
				var materialIndex = intersection[0].face.materialIndex;
				var position = intersection[0].point; // object with x, y and z coords
				var x = 0;
				var y = 0;
				var z = 0;
				const inc = 2.5; 
				switch(materialIndex){ // finding x, y, z positions of block
					case 0: // right
						x = position.x - inc;
						y = Math.round(position.y / 5) * 5;
						z = Math.round(position.z / 5) * 5;
						break;
					case 1: // left
						x = position.x + inc;
						y = Math.round(position.y / 5) * 5;
						z = Math.round(position.z / 5) * 5;
						break;
					case 2: // top
						x = Math.round(position.x / 5) * 5;
						y = position.y - inc;
						z = Math.round(position.z / 5) * 5;
						break;
					case 3: // bottom
						x = Math.round(position.x / 5) * 5;
						y = position.y + inc;
						z = Math.round(position.z / 5) * 5;
						break;
					case 4: // front
						x = Math.round(position.x / 5) * 5;
						y = Math.round(position.y / 5) * 5;
						z = position.z - inc;
						break;
					case 5: // back
						x = Math.round(position.x / 5) * 5;
						y = Math.round(position.y / 5) * 5;
						z = position.z + inc;
						break;
				}
				// Find block with those x, y, z positions
				// More efficient by finding it inside it's chunk
				var index1 = identifyChunk(x, z);
				var chunk = chunks[index1];
				for(var i = 0; i < chunk.length; i++){
					if(chunk[i].x == x && chunk[i].y == y && chunk[i].z == z){
						// Found the block!
						if(chunk[i].placed){
							// find the placedBlock and remove it
							for(var j = 0; j < placedBlocks.length; j++){
								if(placedBlocks[j].x == x && placedBlocks[j].y == y && placedBlocks[j].z == z){
									placedBlocks.splice(j, 1);
									break;
								}
							}
						} else { // if it is a normal block
							brokenBlocks.push({x : x, y : y, z : z});
						}
						chunks[index1].splice(i, 1); // block is removed from chunks variable
						break;
					}
				}
				// update chunks, array.splice(index, 1);
				scene.remove(instancedChunk);
				instancedChunk = new THREE.InstancedMesh(blockBox, materialArray, (renderDistance * renderDistance * chunkSize * chunkSize) + placedBlocks.length);
				var count = 0;
				for(var i = 0; i < chunks.length; i++){
					for(var j = 0; j < chunks[i].length; j++){
						let matrix = new THREE.Matrix4().makeTranslation(
							chunks[i][j].x,
							chunks[i][j].y,
							chunks[i][j].z
						);
						instancedChunk.setMatrixAt(count, matrix);
						count++;
					}
				}
				scene.add(instancedChunk);
			}
		}
	});
	controls.addEventListener("lock", function(){

	});
	controls.addEventListener("unlock", function(){

	});

	var movingSpeed = 0.5;
	var ySpeed = 0;
	var acc = 0.065;
	function update(){	
		if(keys.includes(controlOptions.forward)){
			controls.moveForward(movingSpeed);
			for(var i = 0; i < chunks.length; i++){
				for(var j = 0; j < chunks[i].length; j++){
					if(camera.position.x <= chunks[i][j].x + 2.5 && camera.position.x >= chunks[i][j].x - 2.5 && camera.position.z <= chunks[i][j].z + 2.5 && camera.position.z >= chunks[i][j].z - 2.5){
						if(camera.position.y == chunks[i][j].y - 2.5){
							controls.moveForward(-1 * movingSpeed);
						}
					}
				}
			}
		}
		if(keys.includes(controlOptions.left)){
			controls.moveRight(-1 * movingSpeed);
			for(var i = 0; i < chunks.length; i++){
				for(var j = 0; j < chunks[i].length; j++){
					if(camera.position.x <= chunks[i][j].x + 2.5 && camera.position.x >= chunks[i][j].x - 2.5 && camera.position.z <= chunks[i][j].z + 2.5 && camera.position.z >= chunks[i][j].z - 2.5){
						if(camera.position.y == chunks[i][j].y - 2.5){
							controls.moveRight(movingSpeed);
						}
					}
				}
			}
		}
		if(keys.includes(controlOptions.backward)){
			controls.moveForward(-1 * movingSpeed);
			for(var i = 0; i < chunks.length; i++){
				for(var j = 0; j < chunks[i].length; j++){
					if(camera.position.x <= chunks[i][j].x + 2.5 && camera.position.x >= chunks[i][j].x - 2.5 && camera.position.z <= chunks[i][j].z + 2.5 && camera.position.z >= chunks[i][j].z - 2.5){
						if(camera.position.y == chunks[i][j].y - 2.5){
							controls.moveForward(movingSpeed);
						}
					}
				}
			}
		}
		if(keys.includes(controlOptions.right)){
			controls.moveRight(movingSpeed);
			for(var i = 0; i < chunks.length; i++){
				for(var j = 0; j < chunks[i].length; j++){
					if(camera.position.x <= chunks[i][j].x + 2.5 && camera.position.x >= chunks[i][j].x - 2.5 && camera.position.z <= chunks[i][j].z + 2.5 && camera.position.z >= chunks[i][j].z - 2.5){
						if(camera.position.y == chunks[i][j].y - 2.5){
							controls.moveRight(-1 * movingSpeed);
						}
					}
				}
			}
		}
		
		camera.position.y = camera.position.y - ySpeed;
		ySpeed = ySpeed + acc;

		for(var i = 0; i < chunks.length; i++){
			for(var j = 0; j < chunks[i].length; j++){
				if(camera.position.x <= chunks[i][j].x + 2.5 && camera.position.x >= chunks[i][j].x - 2.5 && camera.position.z <= chunks[i][j].z + 2.5 && camera.position.z >= chunks[i][j].z - 2.5){
					if(camera.position.y <= chunks[i][j].y + 15 && camera.position.y >= chunks[i][j].y){
						camera.position.y = chunks[i][j].y + 15;
						ySpeed = 0;
						canJump = true;
						break;
					}
				}
			}
		}

		// INFINITE TERRAIN GENERATION PART!
		var worldSize = chunkSize * renderDistance * 5;
		var ratio = 0.4;
		if(camera.position.z < lowestZBlock() + (worldSize * ratio)){ // 20 is 4 blocks

			try{
				for(let i1 in trunk_mesh){
					if(trunk_mesh[i1].c.position.distanceTo(camera.position)>chunkSize*renderDistance){
						scene.remove(trunk_mesh.c)
						delete trunk_mesh[i1].c
					}
				}
				for(let i1 in leaves_mesh){
					if(leaves_mesh[i1].c.position.distanceTo(camera.position)>chunkSize*renderDistance){
						scene.remove(leaves_mesh.c)
						delete leaves_mesh[i1].c
					}
				}
			}catch(e){}

			/*
				
				[0], [3], [6],
				[1], [x], [7],
				[2], [5], [8],
			*/

			var newChunks = [];
			for(var i = 0; i < chunks.length; i++){
				if((i + 1) % renderDistance != 0){
					newChunks.push(chunks[i]);
				}
			}

			// add blocks
			var lowestX = lowestXBlock();
			var lowestZ = lowestZBlock();

			for(var i = 0; i < renderDistance; i++){
				var chunk = [];
				for(var x = lowestX + (i * chunkSize * 5); x < lowestX + (i * chunkSize * 5) + (chunkSize * 5); x = x + 5){
					for(var z = lowestZ - (chunkSize * 5); z < lowestZ; z = z + 5){
						xoff = inc * x / 5;
						zoff = inc * z / 5;
						var v = Math.round(noise.perlin2(xoff, zoff) * amplitude / 5
						 + noise.perlin2(xoff / 100, zoff / 100) * amplitude / 5 * 100
						 + noise.perlin2(xoff / 100000, zoff / 100000) * amplitude / 5 * 10000) * 5;
						// Try to find a broken block in that position
						var blockIsDestroyed = false;
						for(var d = 0; d < brokenBlocks.length; d++){
							if(brokenBlocks[d].x == x && brokenBlocks[d].y == v && brokenBlocks[d].z == z){
								blockIsDestroyed = true;
								break;
							}
						}
						if(!blockIsDestroyed){
							chunk.push(new Block(x, v, z));
							if(Math.random()<0.0005){
								id=Math.random()
								trunk_mesh[id]={}
								trunk_mesh[id].c = new THREE.Mesh(trunk_box,trunk_material)
								trunk_mesh[id].c.position.set(x, v + 16, z)
								scene.add(trunk_mesh[id].c)
								id=Math.random()
								leaves_mesh[id]={}
								leaves_mesh[id].c = new THREE.Mesh(leaves_box,leaves_front_material)
								leaves_mesh[id].c.position.set(x, v + 44, z)
								scene.add(leaves_mesh[id].c)
								id=Math.random()
								leaves_mesh[id]={}
								leaves_mesh[id].c = new THREE.Mesh(leaves2_box,leaves_front2_material)
								leaves_mesh[id].c.position.set(x, v + 44, z)
								scene.add(leaves_mesh[id].c)
								id=Math.random()
								leaves_mesh[id]={}
								leaves_mesh[id].c = new THREE.Mesh(leaves3_box,leaves_front3_material)
								leaves_mesh[id].c.position.set(x, v + 44, z)
								scene.add(leaves_mesh[id].c)
							}
						}
						// Check if there is also a placed block there
						for(var b = 0; b < placedBlocks.length; b++){
							if(placedBlocks[b].x == x && placedBlocks[b].z == z){
								chunk.push(new Block(placedBlocks[b].x, placedBlocks[b].y, placedBlocks[b].z, true));
							}
						}
					}
				}
				newChunks.splice(i * renderDistance, 0, chunk);
			}

			chunks = newChunks;

			scene.remove(instancedChunk);

			instancedChunk = new THREE.InstancedMesh(blockBox, materialArray, (renderDistance * renderDistance * chunkSize * chunkSize) + placedBlocks.length);
			var count = 0;
			for(var i = 0; i < chunks.length; i++){
				for(var j = 0; j < chunks[i].length; j++){
					let matrix = new THREE.Matrix4().makeTranslation(
						chunks[i][j].x,
						chunks[i][j].y,
						chunks[i][j].z
					);
					instancedChunk.setMatrixAt(count, matrix);
					count++;
				}
			}
			scene.add(instancedChunk);
		}

		if(camera.position.z > highestZBlock() - (worldSize * ratio)){ // 20 is 4 blocks
			/*
				
				[0], [3], [6],
				[1], [x], [7],
				[2], [5], [8],
			*/

			try{
				for(let i1 in trunk_mesh){
					if(trunk_mesh[i1].c.position.distanceTo(camera.position)>chunkSize*renderDistance){
						scene.remove(trunk_mesh.c)
						delete trunk_mesh[i1].c
					}
				}
				for(let i1 in leaves_mesh){
					if(leaves_mesh[i1].c.position.distanceTo(camera.position)>chunkSize*renderDistance){
						scene.remove(leaves_mesh.c)
						delete leaves_mesh[i1].c
					}
				}
			}catch(e){}

			var newChunks = [];
			for(var i = 0; i < chunks.length; i++){
				if(i % renderDistance != 0){
					newChunks.push(chunks[i]);
				}
			}

			// add blocks
			var lowestX = lowestXBlock();
			var highestZ = highestZBlock();
			for(var i = 0; i < renderDistance; i++){
				var chunk = [];
				for(var x = lowestX + (i * chunkSize * 5); x < lowestX + (i * chunkSize * 5) + (chunkSize * 5); x = x + 5){
					for(var z = highestZ + 5; z < (highestZ + 5) + (chunkSize * 5); z = z + 5){
						xoff = inc * x / 5;
						zoff = inc * z / 5;
						var v = Math.round(noise.perlin2(xoff, zoff) * amplitude / 5
						 + noise.perlin2(xoff / 100, zoff / 100) * amplitude / 5 * 100
						 + noise.perlin2(xoff / 100000, zoff / 100000) * amplitude / 5 * 10000) * 5;
						// Try to find a broken block in that position
						var blockIsDestroyed = false;
						for(var d = 0; d < brokenBlocks.length; d++){
							if(brokenBlocks[d].x == x && brokenBlocks[d].y == v && brokenBlocks[d].z == z){
								blockIsDestroyed = true;
								break;
							}
						}
						if(!blockIsDestroyed){
							chunk.push(new Block(x, v, z));
							if(Math.random()<0.0005){
								id=Math.random()
								trunk_mesh[id]={}
								trunk_mesh[id].c = new THREE.Mesh(trunk_box,trunk_material)
								trunk_mesh[id].c.position.set(x, v + 16, z)
								scene.add(trunk_mesh[id].c)
								id=Math.random()
								leaves_mesh[id]={}
								leaves_mesh[id].c = new THREE.Mesh(leaves_box,leaves_front_material)
								leaves_mesh[id].c.position.set(x, v + 44, z)
								scene.add(leaves_mesh[id].c)
								id=Math.random()
								leaves_mesh[id]={}
								leaves_mesh[id].c = new THREE.Mesh(leaves2_box,leaves_front2_material)
								leaves_mesh[id].c.position.set(x, v + 44, z)
								scene.add(leaves_mesh[id].c)
								id=Math.random()
								leaves_mesh[id]={}
								leaves_mesh[id].c = new THREE.Mesh(leaves3_box,leaves_front3_material)
								leaves_mesh[id].c.position.set(x, v + 44, z)
								scene.add(leaves_mesh[id].c)
							}
						}
						// Check if there is also a placed block there
						for(var b = 0; b < placedBlocks.length; b++){
							if(placedBlocks[b].x == x && placedBlocks[b].z == z){
								chunk.push(new Block(placedBlocks[b].x, placedBlocks[b].y, placedBlocks[b].z, true));
							}
						}
					}
				}
				newChunks.splice(((i + 1) * renderDistance) - 1, 0, chunk);
			}

			chunks = newChunks;

			scene.remove(instancedChunk);

			instancedChunk = new THREE.InstancedMesh(blockBox, materialArray, (renderDistance * renderDistance * chunkSize * chunkSize) + placedBlocks.length);
			var count = 0;
			for(var i = 0; i < chunks.length; i++){
				for(var j = 0; j < chunks[i].length; j++){
					let matrix = new THREE.Matrix4().makeTranslation(
						chunks[i][j].x,
						chunks[i][j].y,
						chunks[i][j].z
					);
					instancedChunk.setMatrixAt(count, matrix);
					count++;
				}
			}
			scene.add(instancedChunk);		
		}

		if(camera.position.x > highestXBlock() - (worldSize * ratio)){ // 20 is 4 blocks
			/*
				
				[0], [3], [6],
				[1], [x], [7],
				[2], [5], [8],
			*/

			try{
				for(let i1 in trunk_mesh){
					if(trunk_mesh[i1].c.position.distanceTo(camera.position)>chunkSize*renderDistance){
						scene.remove(trunk_mesh.c)
						delete trunk_mesh[i1].c
					}
				}
				for(let i1 in leaves_mesh){
					if(leaves_mesh[i1].c.position.distanceTo(camera.position)>chunkSize*renderDistance){
						scene.remove(leaves_mesh.c)
						delete leaves_mesh[i1].c
					}
				}
			}catch(e){}

			var newChunks = [];
			for(var i = renderDistance; i < chunks.length; i++){
				newChunks.push(chunks[i]);
			}

			// add blocks
			var highestX = highestXBlock();
			var lowestZ = lowestZBlock();

			for(var i = 0; i < renderDistance; i++){
				var chunk = [];
				for(var z = lowestZ + (i * chunkSize * 5); z < lowestZ + (i * chunkSize * 5) + (chunkSize * 5); z = z + 5){
					for(var x = highestX + 5; x < highestX + 5 + (chunkSize * 5); x = x + 5){
						xoff = inc * x / 5;
						zoff = inc * z / 5;
						var v = Math.round(noise.perlin2(xoff, zoff) * amplitude / 5
						 + noise.perlin2(xoff / 100, zoff / 100) * amplitude / 5 * 100
						 + noise.perlin2(xoff / 100000, zoff / 100000) * amplitude / 5 * 10000) * 5;
						// Try to find a broken block in that position
						var blockIsDestroyed = false;
						for(var d = 0; d < brokenBlocks.length; d++){
							if(brokenBlocks[d].x == x && brokenBlocks[d].y == v && brokenBlocks[d].z == z){
								blockIsDestroyed = true;
								break;
							}
						}
						if(!blockIsDestroyed){
							chunk.push(new Block(x, v, z));
							if(Math.random()<0.0005){
								id=Math.random()
								trunk_mesh[id]={}
								trunk_mesh[id].c = new THREE.Mesh(trunk_box,trunk_material)
								trunk_mesh[id].c.position.set(x, v + 16, z)
								scene.add(trunk_mesh[id].c)
								id=Math.random()
								leaves_mesh[id]={}
								leaves_mesh[id].c = new THREE.Mesh(leaves_box,leaves_front_material)
								leaves_mesh[id].c.position.set(x, v + 44, z)
								scene.add(leaves_mesh[id].c)
								id=Math.random()
								leaves_mesh[id]={}
								leaves_mesh[id].c = new THREE.Mesh(leaves2_box,leaves_front2_material)
								leaves_mesh[id].c.position.set(x, v + 44, z)
								scene.add(leaves_mesh[id].c)
								id=Math.random()
								leaves_mesh[id]={}
								leaves_mesh[id].c = new THREE.Mesh(leaves3_box,leaves_front3_material)
								leaves_mesh[id].c.position.set(x, v + 44, z)
								scene.add(leaves_mesh[id].c)
							}
						}
						// Check if there is also a placed block there
						for(var b = 0; b < placedBlocks.length; b++){
							if(placedBlocks[b].x == x && placedBlocks[b].z == z){
								chunk.push(new Block(placedBlocks[b].x, placedBlocks[b].y, placedBlocks[b].z, true));
							}
						}
					}
				}
				newChunks.splice(chunks.length - (renderDistance - i), 0, chunk);
			}

			chunks = newChunks;

			scene.remove(instancedChunk);

			instancedChunk = new THREE.InstancedMesh(blockBox, materialArray, (renderDistance * renderDistance * chunkSize * chunkSize) + placedBlocks.length);
			var count = 0;
			for(var i = 0; i < chunks.length; i++){
				for(var j = 0; j < chunks[i].length; j++){
					let matrix = new THREE.Matrix4().makeTranslation(
						chunks[i][j].x,
						chunks[i][j].y,
						chunks[i][j].z
					);
					instancedChunk.setMatrixAt(count, matrix);
					count++;
				}
			}
			scene.add(instancedChunk);				
		}

		if(camera.position.x < lowestXBlock() + (worldSize * ratio)){ // 20 is 4 blocks
			/*
				
				[0], [3], [6],
				[1], [x], [7],
				[2], [5], [8],
			*/

			try{
				for(let i1 in trunk_mesh){
					if(trunk_mesh[i1].c.position.distanceTo(camera.position)>chunkSize*renderDistance){
						scene.remove(trunk_mesh.c)
						delete trunk_mesh[i1].c
					}
				}
				for(let i1 in leaves_mesh){
					if(leaves_mesh[i1].c.position.distanceTo(camera.position)>chunkSize*renderDistance){
						scene.remove(leaves_mesh.c)
						delete leaves_mesh[i1].c
					}
				}
			}catch(e){}

			var newChunks = [];
			for(var i = 0; i < chunks.length - renderDistance; i++){
				newChunks.push(chunks[i]);
			}

			// add blocks
			var lowestX = lowestXBlock();
			var lowestZ = lowestZBlock();
			for(var i = 0; i < renderDistance; i++){
				var chunk = [];
				for(var z = lowestZ + (i * chunkSize * 5); z < lowestZ + (i * chunkSize * 5) + (chunkSize * 5); z = z + 5){
					for(var x = lowestX - (chunkSize * 5); x < lowestX; x = x + 5){
						xoff = inc * x / 5;
						zoff = inc * z / 5;
						var v = Math.round(noise.perlin2(xoff, zoff) * amplitude / 5
						 + noise.perlin2(xoff / 100, zoff / 100) * amplitude / 5 * 100
						 + noise.perlin2(xoff / 100000, zoff / 100000) * amplitude / 5 * 10000) * 5;
						// Try to find a broken block in that position
						var blockIsDestroyed = false;
						for(var d = 0; d < brokenBlocks.length; d++){
							if(brokenBlocks[d].x == x && brokenBlocks[d].y == v && brokenBlocks[d].z == z){
								blockIsDestroyed = true;
								break;
							}
						}
						if(!blockIsDestroyed){
							chunk.push(new Block(x, v, z));
							if(Math.random()<0.0005){
								id=Math.random()
								trunk_mesh[id]={}
								trunk_mesh[id].c = new THREE.Mesh(trunk_box,trunk_material)
								trunk_mesh[id].c.position.set(x, v + 16, z)
								scene.add(trunk_mesh[id].c)
								id=Math.random()
								leaves_mesh[id]={}
								leaves_mesh[id].c = new THREE.Mesh(leaves_box,leaves_front_material)
								leaves_mesh[id].c.position.set(x, v + 44, z)
								scene.add(leaves_mesh[id].c)
								id=Math.random()
								leaves_mesh[id]={}
								leaves_mesh[id].c = new THREE.Mesh(leaves2_box,leaves_front2_material)
								leaves_mesh[id].c.position.set(x, v + 44, z)
								scene.add(leaves_mesh[id].c)
								id=Math.random()
								leaves_mesh[id]={}
								leaves_mesh[id].c = new THREE.Mesh(leaves3_box,leaves_front3_material)
								leaves_mesh[id].c.position.set(x, v + 44, z)
								scene.add(leaves_mesh[id].c)
							}
						}
						// Check if there is also a placed block there
						for(var b = 0; b < placedBlocks.length; b++){
							if(placedBlocks[b].x == x && placedBlocks[b].z == z){
								chunk.push(new Block(placedBlocks[b].x, placedBlocks[b].y, placedBlocks[b].z, true));
							}
						}
					}
				}
				newChunks.splice(i, 0, chunk);
			}

			chunks = newChunks;

			scene.remove(instancedChunk);

			instancedChunk = new THREE.InstancedMesh(blockBox, materialArray, (renderDistance * renderDistance * chunkSize * chunkSize) + placedBlocks.length);
			var count = 0;
			for(var i = 0; i < chunks.length; i++){
				for(var j = 0; j < chunks[i].length; j++){
					let matrix = new THREE.Matrix4().makeTranslation(
						chunks[i][j].x,
						chunks[i][j].y,
						chunks[i][j].z
					);
					instancedChunk.setMatrixAt(count, matrix);
					count++;
				}
			}
			scene.add(instancedChunk);	
		}
	}

	function lowestXBlock(){
		var xPosArray = [];
		for(var i = 0; i < chunks.length; i++){
			for(var j = 0; j < chunks[i].length; j++){
				xPosArray.push(chunks[i][j].x);
			}
		}
		return Math.min.apply(null, xPosArray);
	}

	function highestXBlock(){
		var xPosArray = [];
		for(var i = 0; i < chunks.length; i++){
			for(var j = 0; j < chunks[i].length; j++){
				xPosArray.push(chunks[i][j].x);
			}
		}
		return Math.max.apply(null, xPosArray);
	}

	function lowestZBlock(){
		var zPosArray = [];
		for(var i = 0; i < chunks.length; i++){
			for(var j = 0; j < chunks[i].length; j++){
				zPosArray.push(chunks[i][j].z);
			}
		}
		return Math.min.apply(null, zPosArray);
	}

	function highestZBlock(){
		var zPosArray = [];
		for(var i = 0; i < chunks.length; i++){
			for(var j = 0; j < chunks[i].length; j++){
				zPosArray.push(chunks[i][j].z);
			}
		}
		return Math.max.apply(null, zPosArray);
	}

	// Resize Window
	window.addEventListener("resize", function(){
		renderer.setSize(window.innerWidth, window.innerHeight);
		camera.aspect = window.innerWidth / window.innerHeight;
		camera.updateProjectionMatrix();
	});

	const raycaster = new THREE.Raycaster();
	const pointer = new THREE.Vector2();
	pointer.x = (0.5) * 2 - 1;
	pointer.y = -1 * (0.5) * 2 + 1;

	var plane;
	function render(){
		raycaster.setFromCamera(pointer, camera);
		var intersection = raycaster.intersectObject(instancedChunk);
		if(intersection[0] != undefined && intersection[0].distance < 40){
			//console.log(intersection[0]);
			if(!scene.children.includes(plane)){
				var planeG = new THREE.PlaneGeometry(5, 5);
				var planeM = new THREE.MeshBasicMaterial({color : 0xffffff, side : THREE.DoubleSide});
				planeM.transparent = true;
				planeM.opacity = 0.5;
				plane = new THREE.Mesh(planeG, planeM);
				scene.add(plane);
			} else {
				plane.visible = true;
				var materialIndex = intersection[0].face.materialIndex;
				var position = intersection[0].point; // object with x, y and z coords
				var x = 0;
				var y = 0;
				var z = 0;
				const inc = 0.1; 
				switch(materialIndex){
					case 0: // right
						plane.rotation.x = 0;
						plane.rotation.y = (Math.PI / 2);
						plane.rotation.z = 0;
						x = position.x + inc;
						y = Math.round(position.y / 5) * 5;
						z = Math.round(position.z / 5) * 5;
						break;
					case 1: // left
						plane.rotation.x = 0;
						plane.rotation.y = (Math.PI / 2);
						plane.rotation.z = 0;
						x = position.x - inc;
						y = Math.round(position.y / 5) * 5;
						z = Math.round(position.z / 5) * 5;
						break;
					case 2: // top
						plane.rotation.x = (Math.PI / 2);
						plane.rotation.y = 0;
						plane.rotation.z = 0;
						x = Math.round(position.x / 5) * 5;
						y = position.y + inc;
						z = Math.round(position.z / 5) * 5;
						break;
					case 3: // bottom
						plane.rotation.x = (Math.PI / 2);
						plane.rotation.y = 0;
						plane.rotation.z = 0;
						x = Math.round(position.x / 5) * 5;
						y = position.y - inc;
						z = Math.round(position.z / 5) * 5;
						break;
					case 4: // front
						plane.rotation.x = 0;
						plane.rotation.y = 0;
						plane.rotation.z = 0;
						x = Math.round(position.x / 5) * 5;
						y = Math.round(position.y / 5) * 5;
						z = position.z + inc;
						break;
					case 5: // back
						plane.rotation.x = 0;
						plane.rotation.y = 0;
						plane.rotation.z = 0;
						x = Math.round(position.x / 5) * 5;
						y = Math.round(position.y / 5) * 5;
						z = position.z - inc;
						break;
				}
				plane.position.x = x;
				plane.position.y = y;
				plane.position.z = z;
			}
		} else {
			if(plane){
				plane.visible = false;
			}
		}

		renderer.render(scene, camera);
	}

	function GameLoop(){
		requestAnimationFrame(GameLoop);
		update();
		render();
	}

	GameLoop();
</script>

Depends on what you mean by “make shaders” - most of the time, you can use ShaderMaterial, RawShaderMaterial, CustomShaderMaterial, or just replacing parts of shader code of built-in materials in Material.onBeforeCompile.

1 Like