Atmosphere constructor

Atmosphere({
  1. AtmosphereParameters? atmosphereParams,
  2. Texture? cloudTexture,
  3. int renderOrder = 2,
})

Implementation

factory Atmosphere({AtmosphereParameters? atmosphereParams, Texture? cloudTexture, int renderOrder = 2}){
  atmosphereParams ??= AtmosphereParameters();

  final material = ShaderMaterial.fromMap({
    'uniforms': {
      'time': { 'value': 0.0 },
      'pointTexture': { 'value': cloudTexture },
      'radius': { 'value': atmosphereParams.radius },
      'thickness': { 'value': atmosphereParams.thickness },
      ...atmosphereParams.uniforms
    },
    'vertexShader': atosphereVertexShader,
    'fragmentShader': atmosphereFragmentShader.replaceAll(
      'void main() {',
      '''${noiseFunctions}
       void main() {'''
    ),
    'depthWrite': false,
    'transparent': true,
    'blending': AdditiveBlending,
  });
  material.polygonOffset = true;
  material.polygonOffsetFactor = -1.0;
  material.polygonOffsetUnits = -4.0;


  final int count = atmosphereParams.particles;
  final Float32List combinedData = Float32List(count * 6);
  final random = math.Random();
  for(int i = 0; i < count; i++) {
    double r = random.nextDouble() * atmosphereParams.thickness + atmosphereParams.radius;

    // Pick a random point within a cube of size [-1, 1]
    // This approach works better than parameterizing the spherical coordinates
    // since it doesn't have the issue of particles being bunched at the poles
    final p = Vector3(
      2 * random.nextDouble() - 1,
      2 * random.nextDouble() - 1,
      2 * random.nextDouble() - 1
    );

    // Project onto the surface of a sphere
    p.normalize();
    p.scale(r);

    final minSize = atmosphereParams.minParticleSize;
    final maxSize = atmosphereParams.maxParticleSize;
    final size = random.nextDouble() * (maxSize - minSize) + minSize;

    combinedData.setAll(i * 4, [p.x, p.y, p.z, size]);
  }

  final geometry = BufferGeometry();
  final interleavedBuffer = InterleavedBuffer(combinedData, 4);

  geometry.setAttributeFromString('position', InterleavedBufferAttribute(interleavedBuffer, 3, 0));
  geometry.setAttributeFromString('size', InterleavedBufferAttribute(interleavedBuffer, 1, 3));

  geometry.computeBoundingSphere();
  geometry.computeBoundingBox();

  return Atmosphere._(geometry, material, atmosphereParams, renderOrder);
}