Understanding Three.js Core Concepts: Coordinate Systems and Lighting

3D Coordinate System Visualization

Visualizing Coordinate Axes

THREE.AxesHelper() accepts a parameter that determines the length of the coordinate axis lines. You can adjust this value based on your scene requirements.

// AxesHelper: Visual reference for 3D axes
const axisIndicator = new THREE.AxesHelper(200);
scene.add(axisIndicator);


Implementing Material Transparency

Configure material transparency to better observe the coordinate system's origin point.

const surfaceMaterial = new THREE.MeshBasicMaterial({
   color: 0x0080ff, // Set material color
   transparent: true, // Enable transparency
   opacity: 0.6, // Adjust transparency level
});


Understanding Axis Color Convention

In Three.js, the coordinate axes follow an RGB color scheme where Red represents the x-axis, Green represents the y-axis, and Blue represents the z-axis. The default Three.js coordinate system has the y-axis pointing upward.

Adjusting Camera Parameters

Positioning the camera on the negative x-axis while targeting the origin creates a view aligned with the positive x-direction, showing only one face of a rectangular object.

camera.position.set(-1000, 0, 0);
camera.lookAt(0, 0, 0);

// Camera视线沿着x轴负半轴,mesh位于相机后面,自然看不到
camera.position.set(-1000, 0, 0);
camera.lookAt(-2000, 0, 0);


When the camera's far clipping plane is too small, objects beyond this distance won't be rendered.

const perspectiveCamera = new THREE.PerspectiveCamera(30, width / height, 1, 300);

Impact of Light on Surface Rendering

In real-world scenarios, object surface brightness is affected by lighting conditions. In Three.js, where Mesh objects simulate physical items, lighting (Light) affects the surface appearance of these meshes, creating realistic visual effects.

Light-Reactive Materials

Three.js offers different mesh materials with varying responses to lighting.

Basic Mesh Material (MeshBasicMaterial) is unaffected by light sources.

// MeshBasicMaterial: Unaffected by lighting
const basicMaterial = new THREE.MeshBasicMaterial(); 


Lambert Mesh Material (MeshLambertMaterial) responds to lighting, creating natural shading effects. Different faces of a cube will show varying brightness based on their angle to the light source.

// MeshLambertMaterial: Light-reactive material
const lambertMaterial = new THREE.MeshLambertMaterial(); 


Light Source Types

Point Lights

A PointLight emits light uniformly in all directions from a single point, similar to an LED bulb in real life.

// PointLight with color and intensity parameters
// Parameter 1: 0xffffff represents pure white light
// Parameter 2: 1.0 sets the light intensity
const bulbLight = new THREE.PointLight(0xffffff, 1.0);

bulbLight.intensity = 1.5; // Adjust light intensity



Visualizing Point Lights

Use PointLightHelper to visualize the position and influence of point lights. Combine with OrbitControls for interactive scene exploration.

// Light visualization helper
const lightIndicator = new THREE.PointLightHelper(bulbLight, 10);
scene.add(lightIndicator);

bulbLight.position.set(100, 60, 50);
// Modify light position and observe with OrbitControls
bulbLight.position.set(-400, -200, -300);


Light Attenuation

Light naturally diminishes with distance. The .decay property controls this falloff, with a default value of 2.0. Set to 0.0 to disable distance-based attenuation.

bulbLight.decay = 0.0; // Disable distance-based light falloff


Light Positioning

Proper light placement is crucial for desired surface illumination. Position lights outside mesh objects to illuminate they exteriors effectively.

// Point light placement
bulbLight.position.set(0, 100, 0); // Position light along y-axis


Adding Lights to Scene

Like mesh objects, lights must be added to the scene to affect rendering.

scene.add(bulbLight); // Include point light in scene


Experiment with Light Position

Adjust light positions to observe different surface illumination patterns on mesh objects.

bulbLight.position.set(400, 200, 300); 


Ambient Lighting

AmbientLight provides uniform illlumination across the entire scene without directionality, subtly affecting overall brightness.

// Ambient light: Non-directional, affects overall scene brightness
const sceneAmbience = new THREE.AmbientLight(0xffffff, 0.4);
scene.add(sceneAmbience);


Directional Lights

DirectionalLight emits parallel light rays in a specific direction, simulating distant light sources like the sun.

// Directional light configuration
const sunLight = new THREE.DirectionalLight(0xffffff, 1);
// Set light direction via position and target
sunLight.position.set(80, 100, 50);
// Target can be any object in the scene
sunLight.target = mesh;
scene.add(sunLight);


Visualizing Directional Lights

Use DirectionalLightHelper to display the direction and position of directional lights.

// DirectionalLightHelper: Visualize directional light
const sunLightHelper = new THREE.DirectionalLightHelper(sunLight, 5, 0xff0000);
scene.add(sunLightHelper);


Light Reflection on Surfaces

Directional light interacts with mesh surfaces based on the angle of incidence. Different angles produce varying reflection intensities on Lambert materials.

// Compare different incident angles
sunLight.position.set(100, 0, 0);
sunLight.position.set(0, 100, 0);
sunLight.position.set(100, 100, 100);
sunLight.position.set(100, 60, 50);
// Default target is the scene origin


OrbitControls Camera Manipulation

Basic OrbitControls Usage

  • Rotation: Left mouse button drag
  • Zoom: Middle mouse wheel
  • Pan: Right mouse button drag

Import OrbitControls Extension

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

// Import OrbitControls extension
import { OrbitControls } from 'three/addons/controls/OrbitControls.js';


Implementing OrbitControls

// Configure orbit controls for camera manipulation
const sceneControls = new OrbitControls(camera, renderer.domElement);
// Update render when controls change camera parameters
sceneControls.addEventListener('change', function () {
   renderer.render(scene, camera);
});


OrbitControls Fundamentals

OrbitControls modify camera properties like position to acheive different viewing angles. This enables 360-degree object inspection and distance-based zoom effects.

sceneControls.addEventListener('change', function () {
   // Monitor camera position changes
   console.log('Camera position updated:', camera.position);
});


Animation Rendering Loop

Request Animation Frame Pattern

// Periodic execution using requestAnimationFrame
// Attempts 60 calls per second, actual rate depends on performance
let frameCount = 0;
function animateFrame() {
   frameCount++;
   console.log('Frame:', frameCount);
   requestAnimationFrame(animateFrame);
}
animateFrame();


Implementing Object Rotation

Animation creates the illusion of motion by rendering successive frames. At sufficient frame rates, the human eye perceives smooth, continuous motion.

const webglRenderer = new THREE.WebGLRenderer();
webglRenderer.setSize(width, height);
document.body.appendChild(webglRenderer.domElement);

// Animation loop
function animateScene() {
   webglRenderer.render(scene, camera);
   mesh.rotation.y += 0.01; // Incremental rotation
   requestAnimationFrame(animateScene);
}
animateScene();


Measuring Frame Rate and Performance

// Performance monitoring in render loop
const performanceClock = new THREE.Clock();
function renderLoop() {
   const frameTime = performanceClock.getDelta() * 1000; // Convert to milliseconds
   console.log('Frame time (ms):', frameTime.toFixed(2));
   console.log('FPS:', (1000 / frameTime).toFixed(0));
   webglRenderer.render(scene, camera);
   mesh.rotation.y += 0.01;
   requestAnimationFrame(renderLoop);
}
renderLoop();


Combining Animation Loop with Controls

When using a render loop, you don't need to trigger renderer.render() through OrbitControls' change event, as the loop continuously handles rendering.

Full-Screen Rendering

// Set canvas dimensions to window size
const canvasWidth = window.innerWidth;
const canvasHeight = window.innerHeight;
const webglRenderer = new THREE.WebGLRenderer();
webglRenderer.setSize(canvasWidth, canvasHeight);
document.body.appendChild(webglRenderer.domElement);


Responsive Canvas Resizing

// Handle window resize events
window.addEventListener('resize', function () {
   // Update renderer dimensions
   webglRenderer.setSize(window.innerWidth, window.innerHeight);
   // Update camera aspect ratio
   camera.aspect = window.innerWidth / window.innerHeight;
   // Recalculate projection matrix
   camera.updateProjectionMatrix();
   webglRenderer.render(scene, camera);
});


Tags: Three.js WebGL 3D Graphics Lighting animation

Posted on Wed, 13 May 2026 20:13:09 +0000 by VanHagar