@takram/three-atmosphere
Version:
A Three.js and R3F implementation of Precomputed Atmospheric Scattering
93 lines (79 loc) • 2.32 kB
text/typescript
import {
DirectionalLight,
Matrix3,
Matrix4,
Vector3,
type Texture
} from 'three'
import { Ellipsoid } from '@takram/three-geospatial'
import { AtmosphereParameters } from './AtmosphereParameters'
import { getSunLightColor } from './getSunLightColor'
const vectorScratch = /*#__PURE__*/ new Vector3()
const rotationScratch = /*#__PURE__*/ new Matrix3()
export interface SunDirectionalLightParameters {
transmittanceTexture?: Texture | null
ellipsoid?: Ellipsoid
correctAltitude?: boolean
sunDirection?: Vector3
distance?: number
}
export const sunDirectionalLightParametersDefaults = {
ellipsoid: Ellipsoid.WGS84,
correctAltitude: true,
distance: 1
} satisfies SunDirectionalLightParameters
export class SunDirectionalLight extends DirectionalLight {
transmittanceTexture: Texture | null
ellipsoid: Ellipsoid
readonly worldToECEFMatrix = new Matrix4()
correctAltitude: boolean
readonly sunDirection: Vector3
distance: number
constructor(
params?: SunDirectionalLightParameters,
private readonly atmosphere = AtmosphereParameters.DEFAULT
) {
super()
const {
irradianceTexture = null,
ellipsoid,
correctAltitude,
sunDirection,
distance
} = { ...sunDirectionalLightParametersDefaults, ...params }
this.transmittanceTexture = irradianceTexture
this.ellipsoid = ellipsoid
this.correctAltitude = correctAltitude
this.sunDirection = sunDirection?.clone() ?? new Vector3()
this.distance = distance
}
update(): void {
const worldToECEFMatrix = this.worldToECEFMatrix
const ecefToWorldRotation = rotationScratch
.setFromMatrix4(worldToECEFMatrix)
.transpose()
this.position
.copy(this.sunDirection)
.applyMatrix3(ecefToWorldRotation)
.normalize()
.multiplyScalar(this.distance)
.add(this.target.position)
if (this.transmittanceTexture == null) {
return
}
const cameraPositionECEF = this.target
.getWorldPosition(vectorScratch)
.applyMatrix4(worldToECEFMatrix)
getSunLightColor(
this.transmittanceTexture,
cameraPositionECEF,
this.sunDirection,
this.color,
{
ellipsoid: this.ellipsoid,
correctAltitude: this.correctAltitude
},
this.atmosphere
)
}
}