body{
  overflow: hidden;
  margin: 0;
}
import * as THREE from "three";
import { OrbitControls } from "three/addons/controls/OrbitControls.js";


console.clear();

let scene = new THREE.Scene();
scene.background = new THREE.Color("gray");
let camera = new THREE.PerspectiveCamera(60, innerWidth / innerHeight, 1, 100);
camera.position.set(0, 0, 10);
let renderer = new THREE.WebGLRenderer({antialias: true});
renderer.setSize(innerWidth, innerHeight);
document.body.appendChild(renderer.domElement);

window.addEventListener("resize", (event) => {
  camera.aspect = innerWidth / innerHeight;
  camera.updateProjectionMatrix();
  renderer.setSize(innerWidth, innerHeight);
});

// environment map

const path = 'https://threejs.org/examples/textures/cube/SwedishRoyalCastle/';
const format = '.jpg';
const urls = [
  path + 'px' + format, path + 'nx' + format,
  path + 'py' + format, path + 'ny' + format,
  path + 'pz' + format, path + 'nz' + format
];

const cubeTextureLoader = new THREE.CubeTextureLoader();

const reflectionCube = cubeTextureLoader.load( urls );
scene.environment = reflectionCube;

let controls = new OrbitControls(camera, renderer.domElement);
controls.enableDamping = true;

let light = new THREE.DirectionalLight(0xffffff, Math.PI * 2);
light.position.setScalar(1);
scene.add(light, new THREE.AmbientLight(0xffffff, Math.PI * 0.5));

let g = new THREE.LatheGeometry(
  new THREE.CatmullRomCurve3(
      [
        [3, 0],
        [3, -1],
        [3.25, -1],
        [3.5, 0],
        [3.25, 1],
        [3, 1]
      ].map(p => {return new THREE.Vector3(p[0], p[1], 0)}),
      true
    ).getSpacedPoints(100),
  72
)
let ru = {
  color1: {value: new THREE.Color("silver")},
  color2: {value: new THREE.Color("gold")},
  plane: {value: new THREE.Vector4(0, 1, 1).normalize()}
}
let m = new THREE.MeshStandardMaterial({
  metalness: 0.99,
  roughness: 0.2,
  envMapIntensity: 2,
  onBeforeCompile: shader => {
    shader.uniforms.color1 = ru.color1;
    shader.uniforms.color2 = ru.color2;
    shader.uniforms.plane = ru.plane;
    shader.vertexShader = `
      varying vec3 vPos;
      ${shader.vertexShader}
    `.replace(
      `#include <begin_vertex>`,
      `#include <begin_vertex>
        vPos = position;
      `
    );
    console.log(shader.vertexShader);
    shader.fragmentShader = `
      uniform vec3 color1;
      uniform vec3 color2;
      uniform vec3 plane;
      varying vec3 vPos;
      ${shader.fragmentShader}
    `.replace(
      `vec4 diffuseColor = vec4( diffuse, opacity );`,
      `
      vec3 color = vec3(0);
      float d = dot(vPos, plane);
      vec3 fw = fwidth(vPos);
      float mfw = min(min(fw.x, fw.y), fw.z) * 0.5;
      float f = smoothstep(-mfw, mfw, d);
      color = mix(color1, color2, f);
      vec4 diffuseColor = vec4( color, opacity );`
    );
    console.log(shader.fragmentShader);
    
  }
});
let o = new THREE.Mesh(g, m)
scene.add(o);

let clock = new THREE.Clock();
let t = 0;

renderer.setAnimationLoop(() => {
  let dt = clock.getDelta();
  t += dt;
  controls.update();
  renderer.render(scene, camera);
});
Run Pen

External CSS

This Pen doesn't use any external CSS resources.

External JavaScript

This Pen doesn't use any external JavaScript resources.