<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/104/three.min.js"></script>
html, body {
  height: 100%;
  margin: 0;
  overflow: hidden;
}
canvas {
  width: 100%;
  height: 100%;
  display; block;
}
var materialShader;
var scene = new THREE.Scene();
var camera = new THREE.PerspectiveCamera(60, 1, 1, 1000);
camera.position.set(0, 0, 20);
var renderer = new THREE.WebGLRenderer({
  antialias: true
});
renderer.setClearColor(0x000000);
var canvas = renderer.domElement;
document.body.appendChild(canvas);

var light = new THREE.DirectionalLight(0xffffff, 1);
light.position.setScalar(10);
scene.add(light);
scene.add(new THREE.AmbientLight(0xffffff, 0.75));

let starship = new THREE.Group();

let shipMat = new THREE.MeshLambertMaterial({
  color: 0x444444,
  flatShading: true
});
let hullGeom = new THREE.ConeBufferGeometry(5, 10, 4);
hullGeom.rotateX(-Math.PI * 0.5);
hullGeom.scale(1, 0.25, 1);
let hull = new THREE.Mesh(hullGeom, shipMat);
starship.add(hull);

// ENGINES
///////////////////////////////////////////////////////////////////////////////
let shipEnginesGeom = new THREE.BufferGeometry().setFromPoints([
  new THREE.Vector3(-2, 0, 5.25),
  new THREE.Vector3(0.0, 0, 5.25),
  new THREE.Vector3(2, 0, 5.25)
]);
let sprite = "https://threejs.org/examples/textures/sprites/circle.png";
let shipEnginesMat = new THREE.PointsMaterial({
  size: 2,
  color: "aqua",
  map: new THREE.TextureLoader().load(sprite),
  transparent: true
});
let shipEngines = new THREE.Points(shipEnginesGeom, shipEnginesMat);
starship.add(shipEngines);
///////////////////////////////////////////////////////////////////////////////

scene.add(starship);

// stars
let starsPos = [];
for (let i = 0; i < 50; i++) {
  starsPos.push(
    new THREE.Vector3(
      THREE.Math.randFloatSpread(20),
      THREE.Math.randFloatSpread(20),
      THREE.Math.randFloatSpread(20)
    )
  );
}
let starsGeom = new THREE.BufferGeometry().setFromPoints(starsPos);
let starsMat = new THREE.PointsMaterial({size: 0.25, color: "white"});
starsMat.onBeforeCompile = shader => {
  shader.uniforms.time = {value: 0};
  shader.uniforms.speed = {value: 40};
  shader.vertexShader = `
  uniform float time;
  uniform float speed;
  ` + shader.vertexShader;
  shader.vertexShader = shader.vertexShader.replace(
    `#include <begin_vertex>`,
    `
    vec3 transformed = vec3( position );
    transformed.z = mod(10.0 + position.z + (speed * time), 20.) - 10.;
    `
  );
  materialShader = shader;
};
let stars = new THREE.Points(starsGeom, starsMat);
scene.add(stars);

var time = 0;

render();

function render() {
  if (resize(renderer)) {
    camera.aspect = canvas.clientWidth / canvas.clientHeight;
    camera.updateProjectionMatrix();
  }
  
  time = performance.now() / 1000;
  starship.position.set(
    Math.sin(time * 0.1) * 7,
    Math.cos(time * 0.314) * 4,
    0
  );
  
  shipEnginesMat.opacity = 0.9 + Math.sin(time * Math.PI * 5) * 0.1;
  if (materialShader) materialShader.uniforms.time.value = time;

  renderer.render(scene, camera);
  requestAnimationFrame(render);
}

function resize(renderer) {
  const canvas = renderer.domElement;
  const width = canvas.clientWidth;
  const height = canvas.clientHeight;
  const needResize = canvas.width !== width || canvas.height !== height;
  if (needResize) {
    renderer.setSize(width, height, false);
  }
  return needResize;
}
Run Pen

External CSS

This Pen doesn't use any external CSS resources.

External JavaScript

This Pen doesn't use any external JavaScript resources.