<div class="main">
  <canvas id="bg"></canvas>
</div>
body {
  margin: 0;
}
#bg {
  position: fixed;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  background-color: #000;
}

.main {
  width: 100%;
}
window.addEventListener("load", init);
function random(num) {
  return Math.random() * num * 2 - num;
}

let scene = new THREE.Scene(),
  camera,
  renderer;

// グラデーションのためのvertex shader
const vertexShader = `
  uniform vec3 boundingBoxMin;
  uniform vec3 boundingBoxMax;
  varying vec2 vUv;
  void main() {
    vUv.y = (position.y - boundingBoxMin.y) / (boundingBoxMax.y - boundingBoxMin.y);
    gl_Position = projectionMatrix * modelViewMatrix * vec4(position,1.0);
  }
`;

// グラデーションのためのfragment shader
const fragmentShader = `
  uniform vec3 color1;
  uniform vec3 color2;
  varying vec2 vUv;
  void main() {
    gl_FragColor = vec4(mix(color1, color2, vUv.y), 1.0);
  }
`;

function init() {
  this.color1 = 0xffffff;
  this.color2 = 0xff0000;
  // GUI
  var controls = new (function () {
    this.color1 = 0xffffff;
    this.color2 = 0xff0000;

    this.redraw = function () {
      if (scene.getObjectByName("circle")) {
        scene.remove(scene.getObjectByName("circle"));
      }
      if (scene.getObjectByName("box")) {
        scene.remove(scene.getObjectByName("box"));
      }
      if (scene.getObjectByName("quadrangle")) {
        scene.remove(scene.getObjectByName("quadrangle"));
      }
      if (scene.getObjectByName("wireframe")) {
        scene.remove(scene.getObjectByName("wireframe"));
      }
      createObjects(controls.color1, controls.color2);
    };
  })();
  var gui = new dat.GUI();
  gui.addColor(controls, "color1").onChange(controls.redraw);
  gui.addColor(controls, "color2").onChange(controls.redraw);

  const element = document.getElementById("bg");
  scene = new THREE.Scene();

  camera = new THREE.PerspectiveCamera(
    75,
    element.width / element.height,
    0.1,
    1000
  );
  camera.position.set(20, 10, 30);
  camera.rotation.set(0, 0, 0);
  renderer = new THREE.WebGLRenderer({
    canvas: element,
    antialias: true,
    alpha: true,
    transparent: true
  });
  renderer.setSize(window.innerWidth, window.innerHeight);
  controls.redraw();

  function createObjects(color1, color2) {
    // 円
    const radius = 5;
    const segmentCount = 600;
    const segmentPoints = [];

    // 円周上に点を配置
    const SEG_RADS = (2 * Math.PI) / segmentCount;
    for (let c = 0; c < segmentCount; c++) {
      const x = radius * Math.cos(c * SEG_RADS);
      const y = radius * Math.sin(c * SEG_RADS);
      segmentPoints.push(new THREE.Vector3(x, y, 0));
    }
    // 円のgeometry作成
    const stemCurve = new THREE.CatmullRomCurve3(segmentPoints, true);
    const splinePoints = stemCurve.getPoints(segmentCount);
    const geometry = new THREE.BufferGeometry().setFromPoints(splinePoints);

    geometry.computeBoundingBox();

    // グラデーションがかかるように
    const material = new THREE.ShaderMaterial({
      uniforms: {
        color1: {
          value: new THREE.Color(color1)
        },
        color2: {
          value: new THREE.Color(color2)
        },
        boundingBoxMin: {
          value: geometry.boundingBox.min
        },
        boundingBoxMax: {
          value: geometry.boundingBox.max
        }
      },
      vertexShader,
      fragmentShader,
      opacity: 1
    });
    const circle = new THREE.Line(geometry, material);
    circle.name = "circle";
    circle.position.set(20, 20, 0);
    scene.add(circle);

    // box ---------------------
    const boxGeometry = new THREE.BoxBufferGeometry(5, 5, 5);
    boxGeometry.computeBoundingBox();
    // グラデーションがかかるように
    const boxMaterial = new THREE.ShaderMaterial({
      uniforms: {
        color1: {
          value: new THREE.Color(color1)
        },
        color2: {
          value: new THREE.Color(color2)
        },
        boundingBoxMin: {
          value: boxGeometry.boundingBox.min
        },
        boundingBoxMax: {
          value: boxGeometry.boundingBox.max
        }
      },
      vertexShader,
      fragmentShader,
      opacity: 1
    });
    const box = new THREE.Mesh(boxGeometry, boxMaterial);
    box.name = "box";
    box.position.set(20, 0, 0);
    box.rotation.set(0, 0, 0);

    scene.add(box);

    // 平面の四角形 -----------------
    const quadrangleGeometry = new THREE.BoxBufferGeometry(4, 4, 0.1);
    quadrangleGeometry.computeBoundingBox();

    // グラデーションがかかるように
    const quadrangleMaterial = new THREE.ShaderMaterial({
      uniforms: {
        color1: {
          value: new THREE.Color(color1)
        },
        color2: {
          value: new THREE.Color(color2)
        },
        boundingBoxMin: {
          value: quadrangleGeometry.boundingBox.min
        },
        boundingBoxMax: {
          value: quadrangleGeometry.boundingBox.max
        }
      },
      vertexShader,
      fragmentShader,
      opacity: 1
    });
    const quadrangle = new THREE.Mesh(quadrangleGeometry, quadrangleMaterial);
    quadrangle.name = "quadrangle";
    quadrangle.position.set(20, 10, 0);

    scene.add(quadrangle);

    // wireframe -----------------
    const wireframeGeometry = new THREE.CircleGeometry(4, 100);
    wireframeGeometry.computeBoundingBox();

    // グラデーションがかかるように
    const wireframeMaterial = new THREE.ShaderMaterial({
      uniforms: {
        color1: {
          value: new THREE.Color(color1)
        },
        color2: {
          value: new THREE.Color(color2)
        },
        boundingBoxMin: {
          value: wireframeGeometry.boundingBox.min
        },
        boundingBoxMax: {
          value: wireframeGeometry.boundingBox.max
        }
      },
      vertexShader,
      fragmentShader,
      opacity: 1,
      wireframe: true
    });
    const wireframe = new THREE.Mesh(wireframeGeometry, wireframeMaterial);
    wireframe.name = "wireframe";
    wireframe.position.set(30, 20, 0);

    scene.add(wireframe);
  }
  render();
}

function render() {
  renderer.render(scene, camera);
  window.requestAnimationFrame(render);
  scene.children.forEach((child) => {
    child.rotation.y += 0.01;
  });
}

External CSS

This Pen doesn't use any external CSS resources.

External JavaScript

  1. https://cdnjs.cloudflare.com/ajax/libs/three.js/r125/three.min.js
  2. https://cdnjs.cloudflare.com/ajax/libs/dat-gui/0.7.9/dat.gui.min.js