<script type="importmap">
  {
    "imports": {
      "three": "https://cdn.jsdelivr.net/npm/three@v0.170.0/build/three.webgpu.js",
      "three/tsl": "https://cdn.jsdelivr.net/npm/three@v0.170.0/build/three.webgpu.js",
      "three/addons/": "https://cdn.jsdelivr.net/npm/three@v0.170.0/examples/jsm/"
    }
  }
</script>

<div id="courses"><a href="https://niklever.com/courses" target="_blank">niklever.com/courses</a></div>
body {
  padding: 0;
  margin: 0;
}

#courses {
  font: bold 30px "Arial";
  position: fixed;
  left: 20px;
  top: 20px;
  color: #ffffff;
  text-decoration: none;
}

a:link {
  color: white;
  text-decoration: none;
}

a:hover {
  color: #dddd33;
  text-decoration: underline;
}

a:visited {
  color: white;
  text-decoration: none;
}
import * as THREE from "three";
import { positionLocal } from "three/tsl";
import { OrbitControls } from "three/addons/controls/OrbitControls.js";
import { GUI } from "three/addons/libs/lil-gui.module.min.js";

let container;

let camera, scene, renderer, options, material, assetPath;

init();

function init() {
  container = document.createElement("div");
  document.body.appendChild(container);

  camera = new THREE.PerspectiveCamera(
    40,
    window.innerWidth / window.innerHeight,
    1,
    2500
  );
  camera.position.set(0.0, 1, 4);

  //

  scene = new THREE.Scene();
  scene.background = new THREE.Color(0x444488);

  //

  renderer = new THREE.WebGPURenderer({ antialias: true });
  renderer.setPixelRatio(window.devicePixelRatio);
  renderer.setSize(window.innerWidth, window.innerHeight);
  renderer.setAnimationLoop(render);
  container.appendChild(renderer.domElement);

  //

  //content

  const ambient = new THREE.HemisphereLight(0xaaaaaa, 0x333333);
  const light = new THREE.DirectionalLight(0xffffff, 3);
  light.position.set(3, 3, 1);
  scene.add(ambient);
  scene.add(light);

  const controls = new OrbitControls(camera, renderer.domElement);

  assetPath = "https://niksfiles.s3.eu-west-2.amazonaws.com";

  tsl();

  window.addEventListener("resize", onWindowResize);
}

function tsl() {
  const geometry = new THREE.SphereGeometry();
  material = new THREE.MeshStandardNodeMaterial({ color: 0xff0000 });

  material.colorNode = positionLocal;

  const mesh = new THREE.Mesh(geometry, material);
  scene.add(mesh);

  options = {
    operation: "add",
    value: 0
  };

  const gui = new GUI();
  gui
    .add(options, "operation", ["add", "sub", "mul", "div"])
    .onChange((value) => {
      updateTSL(value, options.value);
      material.needsUpdate = true;
    });
  gui.add(options, "value", 0, 2).onChange((value) => {
    updateTSL(options.operation, value);
    material.needsUpdate = true;
  });
}

function updateTSL(operation, value) {
  switch (operation) {
    case "add":
      material.colorNode = positionLocal.add(value);
      break;
    case "sub":
      material.colorNode = positionLocal.sub(value);
      break;
    case "mul":
      material.colorNode = positionLocal.mul(value);
      break;
    case "div":
      material.colorNode = positionLocal.div(value);
      break;
  }
}

function onWindowResize() {
  camera.aspect = window.innerWidth / window.innerHeight;
  camera.updateProjectionMatrix();

  renderer.setSize(window.innerWidth, window.innerHeight);
}

//

function render() {
  renderer.render(scene, camera);
}

External CSS

This Pen doesn't use any external CSS resources.

External JavaScript

This Pen doesn't use any external JavaScript resources.