globe/src/globe.ts

91 lines
2.4 KiB
TypeScript

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<Texture>((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);
}
}