WebGL入门:Three.js高级材质与光照

WebGL入门:Three.js高级材质与光照

大家好,我是欧阳瑞(Rich Own)。今天想和大家聊聊WebGL和Three.js的高级特性。作为一个全栈开发者和极客玩家,我对3D可视化有着浓厚的兴趣。今天就来分享一下Three.js中的高级材质和光照技术。

为什么选择Three.js?

Three.js是一个强大的3D图形库,封装了复杂的WebGL API,让我们可以轻松创建3D场景。

基础设置

javascript 复制代码
import * as THREE from 'three';
import { OrbitControls } from 'three/addons/controls/OrbitControls.js';

const scene = new THREE.Scene();
const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
const renderer = new THREE.WebGLRenderer();

renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);

const controls = new OrbitControls(camera, renderer.domElement);
camera.position.z = 5;

function animate() {
  requestAnimationFrame(animate);
  controls.update();
  renderer.render(scene, camera);
}
animate();

高级材质

MeshStandardMaterial

javascript 复制代码
const geometry = new THREE.SphereGeometry(1, 32, 32);
const material = new THREE.MeshStandardMaterial({
  color: 0x00ffff,
  metalness: 0.8,
  roughness: 0.2,
  envMap: environmentMap,
  envMapIntensity: 1.0
});
const sphere = new THREE.Mesh(geometry, material);
scene.add(sphere);

MeshPhysicalMaterial

javascript 复制代码
const material = new THREE.MeshPhysicalMaterial({
  color: 0xff00ff,
  metalness: 0.5,
  roughness: 0.3,
  clearcoat: 1.0,
  clearcoatRoughness: 0.1,
  transmission: 0.9,
  ior: 1.5
});

ShaderMaterial

javascript 复制代码
const vertexShader = `
  varying vec2 vUv;
  void main() {
    vUv = uv;
    gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
  }
`;

const fragmentShader = `
  varying vec2 vUv;
  void main() {
    gl_FragColor = vec4(vUv.x, vUv.y, 0.5, 1.0);
  }
`;

const material = new THREE.ShaderMaterial({
  vertexShader,
  fragmentShader
});

光照系统

AmbientLight

javascript 复制代码
const ambientLight = new THREE.AmbientLight(0xffffff, 0.5);
scene.add(ambientLight);

DirectionalLight

javascript 复制代码
const directionalLight = new THREE.DirectionalLight(0xffffff, 1);
directionalLight.position.set(5, 5, 5);
directionalLight.castShadow = true;
directionalLight.shadow.mapSize.width = 2048;
directionalLight.shadow.mapSize.height = 2048;
scene.add(directionalLight);

PointLight

javascript 复制代码
const pointLight = new THREE.PointLight(0x00ffff, 1, 100);
pointLight.position.set(0, 5, 0);
pointLight.castShadow = true;
scene.add(pointLight);

SpotLight

javascript 复制代码
const spotLight = new THREE.SpotLight(0xff00ff, 1);
spotLight.position.set(0, 10, 0);
spotLight.angle = Math.PI / 4;
spotLight.penumbra = 0.1;
spotLight.castShadow = true;
scene.add(spotLight);

RectAreaLight

javascript 复制代码
const rectLight = new THREE.RectAreaLight(0x4e00ff, 10, 10, 10);
rectLight.position.set(0, 5, 0);
rectLight.lookAt(0, 0, 0);
scene.add(rectLight);

环境贴图

javascript 复制代码
const loader = new THREE.CubeTextureLoader();
const environmentMap = loader.load([
  'px.jpg', 'nx.jpg',
  'py.jpg', 'ny.jpg',
  'pz.jpg', 'nz.jpg'
]);
scene.background = environmentMap;

const material = new THREE.MeshStandardMaterial({
  envMap: environmentMap,
  metalness: 0.8,
  roughness: 0.2
});

实战案例:赛博朋克场景

javascript 复制代码
// 创建地面
const groundGeometry = new THREE.PlaneGeometry(50, 50);
const groundMaterial = new THREE.MeshStandardMaterial({
  color: 0x1a1a2e,
  roughness: 0.8,
  metalness: 0.2
});
const ground = new THREE.Mesh(groundGeometry, groundMaterial);
ground.rotation.x = -Math.PI / 2;
ground.receiveShadow = true;
scene.add(ground);

// 创建霓虹灯
function createNeonSign(text, position) {
  const canvas = document.createElement('canvas');
  const ctx = canvas.getContext('2d');
  canvas.width = 512;
  canvas.height = 128;
  
  ctx.fillStyle = '#000';
  ctx.fillRect(0, 0, canvas.width, canvas.height);
  
  ctx.font = 'bold 60px Arial';
  ctx.fillStyle = '#00ffff';
  ctx.shadowColor = '#00ffff';
  ctx.shadowBlur = 50;
  ctx.textAlign = 'center';
  ctx.fillText(text, canvas.width / 2, canvas.height / 2 + 20);
  
  const texture = new THREE.CanvasTexture(canvas);
  const material = new THREE.MeshBasicMaterial({
    map: texture,
    transparent: true,
    side: THREE.DoubleSide
  });
  
  const geometry = new THREE.PlaneGeometry(5, 1.2);
  const mesh = new THREE.Mesh(geometry, material);
  mesh.position.set(position.x, position.y, position.z);
  
  return mesh;
}

const sign1 = createNeonSign('CYBERPUNK', { x: 0, y: 3, z: 0 });
scene.add(sign1);

// 创建全息投影效果
function createHologram(position) {
  const geometry = new THREE.BoxGeometry(2, 2, 2);
  const material = new THREE.MeshPhongMaterial({
    color: 0x00ffff,
    transparent: true,
    opacity: 0.3,
    wireframe: true
  });
  const cube = new THREE.Mesh(geometry, material);
  cube.position.set(position.x, position.y, position.z);
  
  return cube;
}

const hologram = createHologram({ x: 5, y: 2, z: 5 });
scene.add(hologram);

// 添加动态效果
function update() {
  sign1.rotation.y = Math.sin(Date.now() * 0.001) * 0.1;
  hologram.rotation.x += 0.01;
  hologram.rotation.y += 0.01;
}

后期处理

javascript 复制代码
import { EffectComposer } from 'three/addons/postprocessing/EffectComposer.js';
import { RenderPass } from 'three/addons/postprocessing/RenderPass.js';
import { UnrealBloomPass } from 'three/addons/postprocessing/UnrealBloomPass.js';

const composer = new EffectComposer(renderer);
const renderPass = new RenderPass(scene, camera);
composer.addPass(renderPass);

const bloomPass = new UnrealBloomPass(
  new THREE.Vector2(window.innerWidth, window.innerHeight),
  1.5, // strength
  0.4, // radius
  0.85 // threshold
);
composer.addPass(bloomPass);

function animate() {
  requestAnimationFrame(animate);
  controls.update();
  update();
  composer.render();
}
animate();

性能优化

使用InstancedMesh

javascript 复制代码
const geometry = new THREE.BoxGeometry(1, 1, 1);
const material = new THREE.MeshStandardMaterial({ color: 0x00ffff });

const instancedMesh = new THREE.InstancedMesh(geometry, material, 1000);

const dummy = new THREE.Object3D();
for (let i = 0; i < 1000; i++) {
  dummy.position.set(
    (Math.random() - 0.5) * 100,
    (Math.random() - 0.5) * 100,
    (Math.random() - 0.5) * 100
  );
  dummy.scale.set(
    Math.random(),
    Math.random(),
    Math.random()
  );
  dummy.rotation.set(
    Math.random() * Math.PI,
    Math.random() * Math.PI,
    Math.random() * Math.PI
  );
  dummy.updateMatrix();
  instancedMesh.setMatrixAt(i, dummy.matrix);
}

scene.add(instancedMesh);

使用LOD

javascript 复制代码
const lod = new THREE.LOD();

const highGeometry = new THREE.TorusKnotGeometry(10, 3, 100, 16);
const mediumGeometry = new THREE.TorusKnotGeometry(10, 3, 50, 8);
const lowGeometry = new THREE.TorusKnotGeometry(10, 3, 10, 4);

const material = new THREE.MeshStandardMaterial({ color: 0xff00ff });

lod.addLevel(new THREE.Mesh(highGeometry, material), 0);
lod.addLevel(new THREE.Mesh(mediumGeometry, material), 100);
lod.addLevel(new THREE.Mesh(lowGeometry, material), 200);

scene.add(lod);

总结

Three.js是一个功能强大的3D库,掌握高级材质和光照技术可以让你创建出令人惊叹的视觉效果。从简单的几何体到复杂的场景,Three.js都能胜任。

我的鬃狮蜥Hash对3D图形也有自己的理解------它总是能从不同角度观察蟋蟀,这也许就是自然界的"3D感知"吧!

如果你对WebGL或Three.js感兴趣,欢迎留言交流!我是欧阳瑞,极客之路,永无止境!


技术栈:Three.js · WebGL · 3D图形 · 着色器

相关推荐
大连好光景12 小时前
ClaudeCode有关Agent Loop知识点大全
react·max_turns·agentloop·checkpoint快照·流式输入
2601_9628857212 小时前
2026 Python 股票数据接口选型指南(横评 + 决策树)
开发语言·python·区块链
磐链科技13 小时前
智能合约系统:去中心化世界的可信执行基础设施
去中心化·区块链·智能合约
汤米粥14 小时前
2026年主流前端技术框架
vue·react·elementplus·tailwind css·angular‌·svelte‌·bootstrap‌
Leo.yuan18 小时前
集团司库系统之外还需要什么?2026年资金分析与司库决策平台建设指南
大数据·人工智能·区块链
2601_967987372 天前
Next.js 文档
react·开发·全栈·文档·next.js
前进的李工2 天前
Agent 学习笔记 01:从工具调用到 ReAct 循环
笔记·学习·llm·agent·react·工具调用
YFJ_mily2 天前
第二届区块链技术与基础模型国际学术会议(BTFM2027)
算法·区块链·能源·智能系统·rdlink研发家·机器人自动化
ss2732 天前
PostgreSQL表级锁、行级锁、轻量级锁
数据库·postgresql·区块链
Oiiouui3 天前
关于 Logto 登录系统的体验以及建议
javascript·安全·react