import { BackSide, DirectionalLight, Mesh, Object3D, ShaderMaterial, SphereGeometry, } from 'three'; import { plainText as vertexShader } from './shaders/atmosphere.vert'; import { plainText as fragmentShader } from './shaders/atmosphere.frag'; export class Atmosphere extends Object3D { public Rayleigh = 0.0025; public Mie = 0.0005; public Exposure = 15.0; public Scale = 1; public ScaleDepth = 0.25; public G = -0.95; public Wavelength = [0.65, 0.57, 0.475]; public geom?: SphereGeometry; public mesh?: Mesh; public shader = new ShaderMaterial({ vertexShader, fragmentShader, side: BackSide, transparent: true, }); constructor(public innerRadius: number, public outerRadius: number) { super(); this.Scale = 1 / (this.outerRadius - this.innerRadius); this.setUniforms(this.shader); this.initialize(); } setUniforms(shader: ShaderMaterial) { shader.uniforms.invWavelength = { value: [ 1 / Math.pow(this.Wavelength[0], 4), 1 / Math.pow(this.Wavelength[1], 4), 1 / Math.pow(this.Wavelength[2], 4), ], }; shader.uniforms.outerRadius = { value: this.outerRadius }; shader.uniforms.innerRadius = { value: this.innerRadius }; shader.uniforms.Kr = { value: this.Rayleigh }; shader.uniforms.Km = { value: this.Mie }; shader.uniforms.ESun = { value: this.Exposure }; shader.uniforms.scale = { value: this.Scale }; shader.uniforms.scaleDepth = { value: this.ScaleDepth }; shader.uniforms.g = { value: this.G }; } setLight(light: DirectionalLight) { this.shader.uniforms.lightDirection = { value: light.position.clone().normalize(), }; } initialize() { this.geom = new SphereGeometry(this.outerRadius, 128, 128); this.mesh = new Mesh(this.geom, this.shader); this.add(this.mesh); } }