import { SphereGeometry, Texture, Mesh, Object3D, TextureLoader, Color, DirectionalLight, ShaderMaterial, MeshPhongMaterial, } from 'three'; import { plainText as vertexShader } from './shaders/earth.vert'; import { plainText as fragmentShader } from './shaders/earth.frag'; import { Atmosphere } from './atmosphere'; export class Globe extends Object3D { private sphere?: SphereGeometry; private clouds = new SphereGeometry(1.02, 64, 64); public atmosphere = new Atmosphere(1, 1.05); public earthMaterial?: ShaderMaterial; public earthMesh?: Mesh; private loader = new TextureLoader(); constructor(private planetRadius: number) { super(); } set radius(radius: number) { this.planetRadius = radius; this.atmosphere.planetRadius = radius; this.earthMaterial && this.atmosphere.setUniforms(this.earthMaterial); this.createMesh(); } get radius() { return this.planetRadius; } public async loadTexture(name: string) { return new Promise((resolve, reject) => { this.loader.load(`./${name}`, resolve, undefined, reject); }); } public async loadArray(names: string[]) { return Promise.all(names.map((name) => this.loadTexture(name))); } public async initialize(light: DirectionalLight) { const textures = await this.loadArray([ 'earth/2k_earth_daymap.jpg', 'earth/2k_earth_nightmap.jpg', 'earth/2k_earth_clouds.jpg', 'earth/2k_earth_normal_map.jpg', 'earth/2k_earth_specular_map.jpg', ]); this.earthMaterial = new ShaderMaterial({ fragmentShader, vertexShader, uniforms: { light: { value: light.position }, texture0: { value: textures[0] }, texture1: { value: textures[1] }, normalmap: { value: textures[3] }, specularMap: { value: textures[4] }, shininess: { value: 1.0 }, specular: { value: new Color('gray') }, }, }); this.atmosphere.setUniforms(this.earthMaterial); this.atmosphere.setLight(light); this.createMesh(); this.add(this.atmosphere); } public tick() {} private createMesh() { if (this.sphere) { this.sphere.dispose(); this.earthMesh && this.remove(this.earthMesh); } this.sphere = new SphereGeometry(this.planetRadius, 128, 128); this.earthMesh = new Mesh(this.sphere, this.earthMaterial); this.add(this.earthMesh); } }