3JS #02 – Rabbit Hole in the Old Net

I might have just went overboard with research. So, it started with the next lesson in threejs implementing GUI controls for debugging objects in the 3D space. Since I had a GLTF object, I was curious to know if the process in adding the GUI would be smooth. And it was smooth, I added controls for the colors in directional light, position for camera, and the position of the GLTF object. You can try it out in the above sandbox.

Being able to change directional lighting colors on the fly is really time-saving

With more confidence, I thought about creating a fun little hero section scene, strongly inspired by vaporware style and 90s internet, which led me to a never-ending rabbit hole.

vaporwave, 90s, moodboard

At first, I drew in inspiration from several renderings, illustrations, and image styles made by other artists and designers. The purplish vibe, VHS tape recording, funky abstract 3D with chrome materials and the occasional windows95 and browser references. I wanted to focus on the windows95 and browser vibes, which led me into thinking about 90s websites. So I sketched out as best as I can a 90s-like website that might use the 3D text model.

Sketched in Figma

But then as a 90s kid myself, I felt something was missing. So I started exploring actual internet pages back in the 90s. And I found myself opening countless tabs exploring websites from the 90s. I not only caught myself in nostalgia, but wanted to understand the design mind and dreams about websites back during the dotcom boom and it was fascinating to see how far we’ve evolved since then. I just felt there was so much to learn and understand where all this came from.

One site in particular was so much fun. We all know the web archives, but do you know The Old Net?

This is Nintendo.com in 1996, we have really cool portals (not buttons) in the hallway.

Mother 3 article from nintendo.com itself!

The Old Internet Again is an attempt to restore vintage web browsing on vintage computers. It uses the Archive.org Way Back Machine API and a proxy that strips out any incompatible javascript and stitches together as many links as it can.
— The Old Net

Lived in Chile so Spanish sites like these about Pokemon cards and combos, brings back memories.

Haha my name is on here, I really loved visiting my friends sites.

The Old Net was giving me vibes back then of myself when I was excited to find random websites of people. It felt more like a pen pal type social platform, seeing all the information and fan pages of things people liked and wanted to share, but in my own little private space.

The anti-aliased render of the browser fonts was a bit too modern for my taste, but still fun. I was able to visit a few pages I ventured back in the days. I even found old web address of my friend’s pages and it was amazing to see it again. I was even able to find my name on it haha. Makes me feel like I was a part of internet history.

Now, I’ve not forgotten the task at hand. I inspected the coding behind, and most websites are just made in simple HTML. Tables, Images as Buttons, a lot of these tags: <center>,<p>,<b>,<i>,<br>,<hr> and .gif files. So I’ll have to somehow control my urge to click on more links and reading what people wrote back in the 90s.

Anyway, it was fun learning about my own origins for my interest in web development. I just hope to break out of the explore phase to create more draft ideas.

import * as THREE from "three";
import { GLTFLoader } from "three/examples/jsm/loaders/GLTFLoader.js";
import * as dat from "lil-gui";

const gui = new dat.GUI();
/**
 * Cursor // Pure Javascript
 */

const cursor = {
  x: 0,
  y: 0
};

window.addEventListener("mousemove", (event) => {
  cursor.x = event.clientX / sizes.width - 0.5;
  cursor.y = -(event.clientY / sizes.height - 0.5);
});

/**
 * Base
 */
// Canvas
const canvas = document.querySelector("canvas.webgl");

// Sizes
const sizes = {
  width: window.innerWidth,
  height: window.innerHeight
};

window.addEventListener("resize", () => {
  //Update sizes
  sizes.width = window.innerWidth;
  sizes.height = window.innerHeight;

  //Update camera
  camera.aspect = sizes.width / sizes.height;
  camera.updateProjectionMatrix();

  //Update renderer
  renderer.setSize(sizes.width, sizes.height);
  //Set PixelRatio
  renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2));
});

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

const ambientLight = new THREE.AmbientLight("0x333333", 1);
scene.add(ambientLight);
gui.addColor(ambientLight, "color").name("ambientLightColor");
gui.add(ambientLight, "intensity");

const directionalLight = new THREE.DirectionalLight(0xffffff, 10);
directionalLight.position.set(1, 3, 4);
scene.add(directionalLight);
gui.addColor(directionalLight, "color").name("directionalLightColor");

// Loader
let text = null;
const gltfLoader = new GLTFLoader();

gltfLoader.load(
  "models/sample-3d.glb",
  (gltf) => {
    console.log("success");
    console.log(gltf);
    text = gltf.scene.children[0];
    text.position.x = 0.66;
    text.position.z = 1;
    text.rotation.z = 6.56;
    gui.add(text.rotation, "x", 0, 100, 0.01).name("rotateX");
    gui.add(text.rotation, "y", 0, 100, 0.01).name("rotateY");
    gui.add(text.rotation, "z", 0, 100, 0.01).name("rotateZ");

    // Material
    text.material = Object.assign(
      new THREE.MeshStandardMaterial({
        color: 0x9fcae0,
        roughness: 0.1,
        metalness: 0.95,
        emissive: 0x1a1919
      }),
      {}
    );

    scene.add(text);
  },
  (progress) => {
    console.log("progress");
    console.log(progress);
  },
  (error) => {
    console.log("error");
    console.log(error);
  }
);

// Camera
let fov = 105;
const camera = new THREE.PerspectiveCamera(
  fov,
  sizes.width / sizes.height,
  0.1,
  100
);

camera.position.x = 3;
camera.position.y = -0.32;
camera.position.z = 4.59;

scene.add(camera);

// Debug
gui.add(camera.position, "y", -10, 10, 0.01);
gui.add(camera.position, "x", 0, 10, 0.01);
gui.add(camera.position, "z", -10, 10, 0.01);

//Fullscreen Mode
window.addEventListener("dblclick", () => {
  if (!document.fullscreenElement) {
    canvas.requestFullscreen();
  } else {
    document.exitFullscreen();
  }
});

// Renderer
const renderer = new THREE.WebGLRenderer({
  canvas: canvas,
  alpha: true
});
renderer.setSize(sizes.width, sizes.height);

// Animate
const clock = new THREE.Clock();

const tick = () => {
  const elapsedTime = clock.getElapsedTime();

  // Update gltf
  if (!!text) {
    text.position.y = Math.sin(elapsedTime * 0.5) * 0.1 - 0.1;
  }

  // Render
  renderer.render(scene, camera);

  // Call tick again on the next frame
  window.requestAnimationFrame(tick);
};

tick();
 
Next
Next

3JS #01 – Loading GLTF in three.js and mouse interaction