<script type="importmap">
	{
		"imports": {
			"three": "https://unpkg.com/three@0.147/build/three.module.js",
      "three/addons/": "https://unpkg.com/three@0.147/examples/jsm/"
		}
	}
</script>

<div class="container">
body {
	margin: 0px;
  overflow: hidden;
}
.container{
  position:fixed;
  top:0;
  left:0;
  width:100%;
  height:100%;
  background-color:#030303;
}
import * as THREE from 'three';
import { OrbitControls } from 'three/addons/controls/OrbitControls.js';
import { TransformControls } from 'three/addons/controls/TransformControls.js' 

let mesh, renderer, scene, camera, controls, transformControl, sp, bo;
let container = document.querySelector('.container')
let anim = true

const vsShader = `
			varying vec4 pos;

			void main() {
				pos = modelMatrix * vec4(position, 1.0);
				gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
			}
			`;

const fragmentShader = `

      uniform vec3 boxMin;
			uniform vec3 boxMax;
			uniform vec3 boxColor;
			varying vec4 pos;


			void main() {
      
        vec3 color1 = vec3(1.0, 0.0, 0.0); // red
        vec3 color2 = vec3(1.0, 0.5, 0.0); // orange
        vec3 color3 = vec3(1.0, 1.0, 0.0); // yellow
        vec3 color4 = vec3(0.0, 1.0, 0.0); // green
        vec3 color5 = vec3(0.0, 0.0, 1.0); // blue

        float gradientOffset = (pos.y / (boxMax.y * 2.0)) - 0.1;

        vec3 startColor;
        vec3 endColor;

        if (gradientOffset < -0.4) {
          startColor = color5;
          endColor = color4;
        } else if (gradientOffset < -0.2) {
          startColor = color4;
          endColor = color3;
        } else if (gradientOffset < 0.0) {
          startColor = color3;
          endColor = color2;
        } else if (gradientOffset < 0.2) {
          startColor = color2;
          endColor = color1;
        }else if (gradientOffset < 0.4) {
          startColor = color1;
          endColor = color1;
        }; 

        vec3 gradientColor = mix(startColor, endColor, fract(gradientOffset * 5.0));

				// Check if the model vertex is outside the box range
        
				if (pos.x < boxMin.x || pos.x > boxMax.x ||
					pos.y < boxMin.y || pos.y > boxMax.y ||
					pos.z < boxMin.z || pos.z > boxMax.z) {
          
            // If it is outside the range, use the mesh colour

            gl_FragColor = vec4(1.0, 1.0, 1.0, 1.0);
				
				} else {
        
            // If it is within the range, use gradient color
        
            gl_FragColor = vec4(gradientColor, 1.0);

				}
			}
			`;

init();


function init() {

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

  // scene
  scene = new THREE.Scene();

  // camera
  camera = new THREE.PerspectiveCamera(40, window.innerWidth / window.innerHeight, 0.1, 10000);
  camera.position.set(300, 300, 300);

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

  // ambient
  scene.add(new THREE.AmbientLight(0x222222));

  // light
  const light = new THREE.DirectionalLight(0xffffff, 1);
  light.position.set(20, 20, 0);
  scene.add(light);

  const box = new THREE.BoxGeometry(
    192,
    124,
    220
  );

  const lineMaterial = setLineMaterial();
  const lineSegments = new THREE.LineSegments(box, lineMaterial);
  const boxMesh = new THREE.Mesh(box, new THREE.MeshBasicMaterial({
    transparent: true,
    opacity: 0.1
  }));

  const box3 = new THREE.Box3();
  box3.setFromObject(boxMesh);
  console.log(box3);

  scene.add(lineSegments);
  scene.add(boxMesh);

  // geometry
  const geometry = new THREE.ConeGeometry(
    40,
    200,
    32
  );
  
  const sGeometry = new THREE.SphereGeometry(
    40,
    200,
    32
  );
  
  const bGeometry = new THREE.BoxGeometry(
    40,
    200,
    40
  );

  // material
  const material = new THREE.ShaderMaterial({

    uniforms: {

      boxMin: {
        value: new THREE.Vector3(box3.min.x, box3.min.y, box3.min.z)
      },
      boxMax: {
        value: new THREE.Vector3(box3.max.x, box3.max.y, box3.max.z)
      },
      boxColor: {
        value: new THREE.Vector3(1.0, 0.0, 0.0)
      },
      res: {
        value: new THREE.Vector2(1,1)
      }

    },

    vertexShader: vsShader,

    fragmentShader: fragmentShader

  });

  // mesh
  mesh = new THREE.Mesh(geometry, material);
  scene.add(mesh);
  
  sp = new THREE.Mesh(sGeometry, material.clone());
  bo = new THREE.Mesh(bGeometry, material.clone());
  
  sp.position.z = 70
  bo.position.z = -80
  scene.add(sp, bo);

  // TransformControls
  transformControl = new TransformControls(camera, renderer.domElement);

  transformControl.addEventListener('dragging-changed', function(event) {

    controls.enabled = !event.value;
    anim = !event.value;
  });

  transformControl.attach(mesh);
  scene.add(transformControl);
  
  console.log(transformControl.object)
  
  animate();

}

function animate(t) {
  
  if(anim){
    transformControl.object.position.y = (Math.sin(t / 1000) * 60) - 100;
  }

  sp.position.y = (Math.sin((t / 1000) + 10) * 60) - 50;
  bo.position.y = (Math.sin((t / 1000) + 5) * 60) - 100;
  renderer.render(scene, camera);
  requestAnimationFrame(animate);

}

function setLineMaterial() {

  return new THREE.LineBasicMaterial({
    color: 0xffffff,
    linewidth: 1,
    transparent: true,
    opacity: 0.5
  });

}
Run Pen

External CSS

This Pen doesn't use any external CSS resources.

External JavaScript

This Pen doesn't use any external JavaScript resources.