body {
margin: 0;
}
const scene = new THREE.Scene();
const fov = 75;
const aspect = window.innerWidth / window.innerHeight;
const near = 0.1;
const far = 1000;
const camera = new THREE.PerspectiveCamera(fov, aspect, near, far);
const renderer = new THREE.WebGLRenderer();
const loader = new THREE.TextureLoader();
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
const light = createLight();
scene.add(light);
const flyingWindow = createFlyingWindow();
scene.add(flyingWindow);
camera.position.z = 1;
let rotationDirection = 1;
function animate() {
requestAnimationFrame(animate);
if (flyingWindow.rotation.y < -2 || flyingWindow.rotation.y > 2) {
rotationDirection *= -1;
}
flyingWindow.rotation.y += 0.01 * rotationDirection;
renderer.render(scene, camera);
}
animate();
window.addEventListener('resize', onWindowResize, false);
function createLight() {
const color = 0xFFFFFF;
const intensity = 1;
const light = new THREE.DirectionalLight(color, intensity);
light.position.set(-1, 2, 4);
return light;
}
function createFlyingWindow() {
// width and height are based on the aspect of the Windows logo image
const width = 1.235;
const height = 1;
// arbitrary depth to make it appear flat enough
const depth = 0.01;
const geometry = new THREE.BoxGeometry(width, height, depth);
const windowImageMaterial = new THREE.MeshBasicMaterial({
map: loader.load('https://i.imgur.com/mSoYNK0.png'),
transparent: true,
side: THREE.FrontSide
});
const blackMaterial = new THREE.MeshBasicMaterial({
color: 0x000000,
side: THREE.DoubleSide,
});
// put color on both sides so transparent front can show color from inside box
const colorMaterial = new THREE.MeshBasicMaterial({
color: 0xff0000,
side: THREE.BackSide,
});
const materials = [
blackMaterial,
blackMaterial,
blackMaterial,
blackMaterial,
windowImageMaterial, // front side facing camera
colorMaterial, // back side facing camera from the inside
];
const flyingWindow = new THREE.Mesh(geometry, materials);
flyingWindow.position.z = -1;
return flyingWindow;
}
function onWindowResize() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
}
This Pen doesn't use any external CSS resources.