7. 高级技术与特效


文档摘要

高级技术与特效 Three.js 高级技术与特效 后期处理 (Post-processing) 后期处理是在场景渲染完成后,对渲染结果进行额外的处理,以添加各种视觉效果,例如景深、Bloom、颜色校正等。 原理: 后期处理通过渲染到纹理 (Render Targets) 实现。首先将场景渲染到纹理,然后将该纹理作为输入,应用各种后期处理特效,最后将处理后的纹理显示到屏幕上。 代码示例: 代码解释: 引入必要的模块: 、 、 。 创建 实例,传入渲染器。 添加 ,用于渲染原始场景。 添加 ,实现 Bloom 特效。可以调整 、 、 等参数来控制 Bloom 的效果。 在渲染循环中使用 代替 。 流程图: 阴影 (Shadows) 阴影可以增强场景的真实感和立体感。Three.

7. 高级技术与特效

Three.js 高级技术与特效

1. 后期处理 (Post-processing)

后期处理是在场景渲染完成后,对渲染结果进行额外的处理,以添加各种视觉效果,例如景深、Bloom、颜色校正等。

原理:

后期处理通过渲染到纹理 (Render Targets) 实现。首先将场景渲染到纹理,然后将该纹理作为输入,应用各种后期处理特效,最后将处理后的纹理显示到屏幕上。

代码示例:

import * as THREE from 'three'; import { EffectComposer } from 'three/examples/jsm/postprocessing/EffectComposer'; import { RenderPass } from 'three/examples/jsm/postprocessing/RenderPass'; import { UnrealBloomPass } from 'three/examples/jsm/postprocessing/UnrealBloomPass'; // 1. 创建场景、相机、渲染器 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 geometry = new THREE.SphereGeometry(1, 32, 32); const material = new THREE.MeshBasicMaterial({ color: 0xffff00 }); const sphere = new THREE.Mesh(geometry, material); scene.add(sphere); camera.position.z = 5; // 2. 创建 EffectComposer const composer = new EffectComposer(renderer); // 3. 添加 RenderPass const renderPass = new RenderPass(scene, camera); composer.addPass(renderPass); // 4. 添加 UnrealBloomPass (Bloom特效) const bloomPass = new UnrealBloomPass(new THREE.Vector2(window.innerWidth, window.innerHeight), 1.5, 0.4, 0.85); bloomPass.threshold = 0.1; bloomPass.strength = 0.8; bloomPass.radius = 0.2; composer.addPass(bloomPass); // 5. 渲染循环 function animate() { requestAnimationFrame(animate); sphere.rotation.x += 0.01; sphere.rotation.y += 0.01; composer.render(); // 使用 composer 渲染 //renderer.render(scene, camera); // 注释掉默认渲染 } animate();

代码解释:

  1. 引入必要的模块:EffectComposerRenderPassUnrealBloomPass

  2. 创建 EffectComposer 实例,传入渲染器。

  3. 添加 RenderPass,用于渲染原始场景。

  4. 添加 UnrealBloomPass,实现 Bloom 特效。可以调整 thresholdstrengthradius 等参数来控制 Bloom 的效果。

  5. 在渲染循环中使用 composer.render() 代替 renderer.render()

流程图:

2. 阴影 (Shadows)

阴影可以增强场景的真实感和立体感。Three.js 支持多种阴影类型。

代码示例:

import * as THREE from 'three'; // 1. 创建场景、相机、渲染器 const scene = new THREE.Scene(); const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000); const renderer = new THREE.WebGLRenderer({antialias: true}); renderer.setSize(window.innerWidth, window.innerHeight); document.body.appendChild(renderer.domElement); // 启用阴影支持 renderer.shadowMap.enabled = true; renderer.shadowMap.type = THREE.PCFSoftShadowMap; // 可选的阴影类型 // 2. 创建物体 const planeGeometry = new THREE.PlaneGeometry(10, 10); const planeMaterial = new THREE.MeshStandardMaterial({ color: 0x808080, side: THREE.DoubleSide }); const plane = new THREE.Mesh(planeGeometry, planeMaterial); plane.rotation.x = -Math.PI / 2; plane.receiveShadow = true; // 允许接收阴影 scene.add(plane); const sphereGeometry = new THREE.SphereGeometry(1, 32, 32); const sphereMaterial = new THREE.MeshStandardMaterial({ color: 0xff0000 }); const sphere = new THREE.Mesh(sphereGeometry, sphereMaterial); sphere.castShadow = true; // 允许投射阴影 sphere.position.y = 1; scene.add(sphere); // 3. 创建光源 const light = new THREE.DirectionalLight(0xffffff, 1); light.position.set(5, 5, 5); light.castShadow = true; // 允许投射阴影 light.shadow.mapSize.width = 1024; // 阴影贴图大小 light.shadow.mapSize.height = 1024; light.shadow.camera.near = 0.5; light.shadow.camera.far = 500; scene.add(light); // 添加环境光 const ambientLight = new THREE.AmbientLight(0x404040); scene.add(ambientLight); camera.position.z = 5; // 4. 渲染循环 function animate() { requestAnimationFrame(animate); sphere.rotation.x += 0.01; sphere.rotation.y += 0.01; renderer.render(scene, camera); } animate();

代码解释:

  1. 启用阴影支持:renderer.shadowMap.enabled = true;,并选择阴影类型。

  2. 物体:设置 castShadow = true 允许物体投射阴影,receiveShadow = true 允许物体接收阴影。

  3. 光源:设置 light.castShadow = true 允许光源投射阴影,并配置阴影贴图的大小和相机参数,以获得更好的阴影效果。

  4. 材质:使用 MeshStandardMaterialMeshPhysicalMaterial 等支持阴影的材质。

注意事项:

  • 阴影的性能开销较大,应根据需要调整阴影贴图的大小。

  • 使用 DirectionalLightSpotLight 可以投射阴影。

  • AmbientLight 不会投射阴影,但可以照亮场景。

3. 自定义着色器 (Custom Shaders)

自定义着色器允许你完全控制物体的渲染方式,实现各种高级视觉效果。

原理:

Three.js 使用 WebGL 着色器语言 (GLSL) 编写着色器。你需要编写顶点着色器 (Vertex Shader) 和片元着色器 (Fragment Shader),分别控制顶点的位置和像素的颜色。

代码示例:

import * as THREE from 'three'; // 1. 创建场景、相机、渲染器 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); // 2. 定义着色器代码 const vertexShader = ` varying vec3 vNormal; void main() { vNormal = normal; gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0); } `; const fragmentShader = ` varying vec3 vNormal; void main() { vec3 normal = normalize(vNormal); float intensity = dot(normal, vec3(0.5, 0.7, 1.0)); vec3 color = vec3(0.8, 0.0, 0.0) * intensity; gl_FragColor = vec4(color, 1.0); } `; // 3. 创建材质 const material = new THREE.ShaderMaterial({ vertexShader: vertexShader, fragmentShader: fragmentShader }); // 4. 创建物体 const geometry = new THREE.SphereGeometry(1, 32, 32); const sphere = new THREE.Mesh(geometry, material); scene.add(sphere); camera.position.z = 5; // 5. 渲染循环 function animate() { requestAnimationFrame(animate); sphere.rotation.x += 0.01; sphere.rotation.y += 0.01; renderer.render(scene, camera); } animate();

代码解释:

  1. 定义顶点着色器和片元着色器的 GLSL 代码。

  2. 创建 THREE.ShaderMaterial 实例,传入着色器代码。

  3. 创建物体,并使用自定义材质。

GLSL 代码解释:

  • 顶点着色器:

    • varying vec3 vNormal;:声明一个 varying 变量,用于将法线传递给片元着色器。

    • gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);:计算顶点在裁剪空间中的位置。

  • 片元着色器:

    • varying vec3 vNormal;:接收从顶点着色器传递过来的法线。

    • vec3 normal = normalize(vNormal);:归一化法线。

    • float intensity = dot(normal, vec3(0.5, 0.7, 1.0));:计算光照强度,使用法线和光照方向的点积。

    • vec3 color = vec3(0.8, 0.0, 0.0) * intensity;:根据光照强度计算颜色。

    • gl_FragColor = vec4(color, 1.0);:设置像素的颜色。

用途:

自定义着色器可以用于实现各种特殊效果,例如:

  • 卡通渲染 (Toon Shading)

  • 水面效果

  • 火焰效果

  • 程序化纹理

4. 粒子系统 (Particle Systems)

粒子系统用于模拟大量的微小物体,例如烟雾、火焰、雪花等。

代码示例:

import * as THREE from 'three'; // 1. 创建场景、相机、渲染器 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); // 2. 创建粒子几何体 const particleCount = 1000; const positions = new Float32Array(particleCount * 3); const colors = new Float32Array(particleCount * 3); for (let i = 0; i < particleCount; i++) { positions[i * 3] = (Math.random() - 0.5) * 10; positions[i * 3 + 1] = (Math.random() - 0.5) * 10; positions[i * 3 + 2] = (Math.random() - 0.5) * 10; colors[i * 3] = Math.random(); colors[i * 3 + 1] = Math.random(); colors[i * 3 + 2] = Math.random(); } const geometry = new THREE.BufferGeometry(); geometry.setAttribute('position', new THREE.BufferAttribute(positions, 3)); geometry.setAttribute('color', new THREE.BufferAttribute(colors, 3)); // 3. 创建粒子材质 const material = new THREE.PointsMaterial({ size: 0.1, vertexColors: true, transparent: true, opacity: 0.8 }); // 4. 创建粒子系统 const particles = new THREE.Points(geometry, material); scene.add(particles); camera.position.z = 5; // 5. 渲染循环 function animate() { requestAnimationFrame(animate); particles.rotation.x += 0.001; particles.rotation.y += 0.002; renderer.render(scene, camera); } animate();

代码解释:

  1. 创建 THREE.BufferGeometry,用于存储粒子的位置和颜色等属性。

  2. 创建 THREE.PointsMaterial,用于定义粒子的外观。

  3. 创建 THREE.Points 实例,表示粒子系统。

关键概念:

  • BufferGeometry: 高效地存储大量顶点数据。

  • PointsMaterial: 用于渲染粒子,可以设置粒子的大小、颜色、透明度等属性。

  • Points: 用于将几何体渲染为点。

高级用法:

  • 使用纹理作为粒子贴图。

  • 使用自定义着色器控制粒子的行为。

  • 使用力场 (Force Fields) 影响粒子的运动。

5. 模型加载与动画 (Model Loading and Animation)

Three.js 支持加载各种 3D 模型格式,例如 glTF, FBX, OBJ 等,并播放模型动画。

代码示例 (glTF):

import * as THREE from 'three'; import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader'; // 1. 创建场景、相机、渲染器 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); // 2. 创建 GLTFLoader const loader = new GLTFLoader(); // 3. 加载模型 loader.load( 'path/to/your/model.gltf', function (gltf) { scene.add(gltf.scene); // 获取动画剪辑 const animations = gltf.animations; // 创建动画混合器 (AnimationMixer) const mixer = new THREE.AnimationMixer(gltf.scene); // 创建动画动作 (AnimationAction) const clip = THREE.AnimationClip.findByName(animations, 'ArmatureAction'); // 替换为你的动画名称 const action = mixer.clipAction(clip); // 播放动画 action.play(); // 将 mixer 保存到全局变量,以便在渲染循环中使用 window.mixer = mixer; }, function (xhr) { console.log((xhr.loaded / xhr.total * 100) + '% loaded'); }, function (error) { console.log('An error happened'); } ); camera.position.z = 5; // 4. 渲染循环 function animate() { requestAnimationFrame(animate); // 更新动画混合器 if (window.mixer) { window.mixer.update(0.01); // delta time } renderer.render(scene, camera); } animate();

代码解释:

  1. 引入 GLTFLoader

  2. 创建 GLTFLoader 实例。

  3. 使用 loader.load() 加载模型,并在回调函数中将模型添加到场景中。

  4. 创建 THREE.AnimationMixer,用于控制动画的播放。

  5. 创建 THREE.AnimationAction,指定要播放的动画剪辑。

  6. 在渲染循环中使用 mixer.update() 更新动画。

其他模型格式:

可以使用 FBXLoaderOBJLoader 等加载其他模型格式。

总结

本文介绍了 Three.js 中的几种高级技术和特效,包括后期处理、阴影、自定义着色器、粒子系统和模型加载与动画。掌握这些技术可以让你创建更具吸引力和互动性的 3D 应用程序。通过实践这些代码示例,你将能够更深入地理解这些概念,并将其应用到你自己的项目中。


作者与出处
原作者: 灏天文库
来源:灏天文库
整理: 灏天文库整理
由灏天文库平台收录,内容或由平台用户上传,仅供学习交流
发布者: 作者: 灏天文库 转发
评论区 (0)
U