Earth (in THREE.js)

by PhilQ

HTML

<script type="x-shader/x-vertex" id="_vertexShader">
	uniform vec2 resolution;

	varying vec4 vPos;
	varying vec3 vNormal;
	varying vec2 vUv;
	varying mat4 matModel;
	varying mat4 matModelView;
	varying mat4 matProjection;
	varying mat3 matNormal;

	void main() {
		// Send to fragment shader
		vNormal = normal;
		vUv = uv;
		vPos = vec4(position, 1.0);
		matModel = modelMatrix;
		matModelView = modelViewMatrix;
		matProjection = projectionMatrix;
		matNormal = normalMatrix;

		// Local space (object)
		gl_Position = vPos;
		
		// to World space (scene)
		gl_Position = modelMatrix * vPos;
		
		// to View space (camera)
		gl_Position = viewMatrix * modelMatrix * vPos;
		
		// to Clip space
		gl_Position = projectionMatrix * viewMatrix * modelMatrix * vPos;

		// Note: Three.js will convert to NDC space and then to Screen/Viewport space
	}
</script>
<script type="x-shader/x-fragment" id="_fragmentShader">
	uniform vec2 resolution;

	varying vec4 vPos;
	varying vec3 vNormal;
	varying vec2 vUv;
	varying mat4 matModel;
	varying mat4 matModelView;
	varying mat4 matProjection;
	varying mat3 matNormal;

	void main() {
		vec4 localUv = vec4(vUv, 0.0, 1.0); // Local uv, bottom-left (0,0) to top-right (1,1)
		vec4 localPos = vPos;
		vec4 worldPos = matModel * vPos;
		vec4 viewPos = viewMatrix * matModel * vPos;
		vec4 clipPos = matProjection * viewMatrix * matModel * vPos;
		vec4 ndcPos = vec4(clipPos.xyz / clipPos.w, clipPos.w); // Added w to be able to back-calculate to clip space
		vec2 screenPos = (ndcPos.xy + 1.0) * 0.5; // Screen uv, bottom-left (0,0) to top-right (1,1)
		vec2 viewportPos = vec2(screenPos.x, -screenPos.y); // Top-left (0,0) to bottom-right (1,1)
		vec2 pixelPos = screenPos * resolution; // Actual pixel coordinates
		
		// gl_FragColor = vec4(screenPos.xy, 0.0, 1.0);
		
		// Basic color + lighting
		vec4 color = vec4(1.0, 0.0, 1.0, 1.0);
		vec3 light = normalize( vec3( 0.5, 0.2, 1.0 ) ); // Normalized direction (like sunlight)
		float...

CSS

body { margin: 0; }
canvas { width: 100%; height: 100% }
#toggle {
	position: fixed;
	top: 0;
	left: 0;
	z-index: 10;
}

JavaScript

import * as THREE from 'three';
import { OrbitControls } from 'OrbitControls';
import { ConvexGeometry } from 'ConvexGeometry';
import * as BufferGeometryUtils from 'BufferGeometryUtils';
import { VertexNormalsHelper } from 'VertexNormalsHelper';

// Author: Fyrestar https://mevedia.com (https://github.com/Fyrestar/THREE.BufferGeometry-toIndexed)
THREE.BufferGeometry.prototype.toIndexed = function () {

	let list = [], vertices = {};

	let _src, attributesKeys, morphKeys;

	let prec = 0, precHalf = 0, length = 0;


	function floor( array, offset ) {

		if ( array instanceof Float32Array ) {

			return Math.floor( array[ offset ] * prec );

		} else if ( array instanceof Float16Array ) {

			return Math.floor( array[ offset ] * precHalf );

		} else {

			return array[ offset ];

		}

	}

	function createAttribute( src_attribute ) {

		const dst_attribute = new THREE.BufferAttribute( new src_attribute.array.constructor( length * src_attribute.itemSize ), src_attribute.itemSize );

		const dst_array = dst_attribute.array;
		const src_array = src_attribute.array;

		switch ( src_attribute.itemSize ) {
			case 1:

				for ( let i = 0, l = list.length; i < l; i++ ) {

					dst_array[ i ] = src_array[ list[ i ] ];

				}

				break;
			case 2:

				for ( let i = 0, l = list.length; i < l; i++ ) {

					const index = list[ i ] * 2;

					const offset = i * 2;

					dst_array[ offset ] = src_array[ index ];
					dst_array[ offset + 1 ] = src_array[ index + 1 ];

				}

				break;
			case 3:

				for ( let i = 0, l = list.length; i < l; i++ ) {

					const index = list[ i ] * 3;

					const offset = i * 3;

					dst_array[ offset ] = src_array[ index ];
					dst_array[ offset + 1 ] = src_array[ index + 1 ];
					dst_array[ offset + 2 ] = src_array[ index + 2 ];


				}

				break;
			case 4:

				for ( let i = 0, l = list.length; i < l; i++ ) {

					const index = list[ i ] * 4;

					const offset = i * 4;

					dst_array[ offset ] = src_array[ index ];
					dst_array[...