当前位置: 首页 > news >正文

第二部分-光照与阴影——13. 光照模型与性能

13. 光照模型与性能

1. 概述

光照模型决定了材质如何与光线交互。Three.js 提供了多种内置光照模型,每种模型在视觉效果和性能之间有不同的权衡。了解这些模型的原理和性能特点,可以帮助你做出更好的选择。

┌─────────────────────────────────────────────────────────────┐ │ 光照模型体系 │ ├─────────────────────────────────────────────────────────────┤ │ │ │ 光照模型类型 │ │ ├── MeshBasicMaterial:无光照(性能最佳) │ │ ├── MeshLambertMaterial:兰伯特(漫反射) │ │ ├── MeshPhongMaterial:冯氏(漫反射+高光) │ │ ├── MeshStandardMaterial:标准 PBR │ │ ├── MeshPhysicalMaterial:物理 PBR(最真实) │ │ └── MeshToonMaterial:卡通(非真实感) │ │ │ │ 性能对比 │ │ ├── 计算复杂度 │ │ ├── 顶点/片元着色器负担 │ │ ├── 光源数量影响 │ │ └── 阴影性能 │ │ │ └─────────────────────────────────────────────────────────────┘

2. 光照模型详解

2.1 MeshBasicMaterial(无光照)

最简单的材质,不受光照影响,直接显示颜色或纹理。

constbasicMaterial=newTHREE.MeshBasicMaterial({color:0xff6600,map:texture});

特点:

  • 无需光照计算
  • 性能最佳
  • 无阴影
  • 适用于 UI、调试、2D 效果

2.2 MeshLambertMaterial(兰伯特)

兰伯特光照模型,只计算漫反射,适合粗糙表面。

constlambertMaterial=newTHREE.MeshLambertMaterial({color:0x44aa88});

特点:

  • 只有漫反射
  • 无高光
  • 性能较好
  • 适合粗糙材质

2.3 MeshPhongMaterial(冯氏)

冯氏光照模型,在兰伯特基础上增加了高光。

constphongMaterial=newTHREE.MeshPhongMaterial({color:0x44aa88,specular:0x444444,shininess:60});

特点:

  • 漫反射 + 高光
  • 性能中等
  • 适合光滑材质

2.4 MeshStandardMaterial(标准 PBR)

基于物理的渲染(PBR)模型,使用金属度和粗糙度。

conststandardMaterial=newTHREE.MeshStandardMaterial({color:0xccaa88,metalness:0.8,roughness:0.2});

特点:

  • 物理真实
  • 性能较高
  • 适合大多数场景

2.5 MeshPhysicalMaterial(物理 PBR)

标准 PBR 的扩展,增加清漆、透射等属性。

constphysicalMaterial=newTHREE.MeshPhysicalMaterial({color:0x88aaff,metalness:0.9,roughness:0.1,clearcoat:1.0,transmission:0.8});

特点:

  • 最真实
  • 性能消耗最大
  • 适合高端场景

2.6 MeshToonMaterial(卡通)

非真实感渲染,产生渐变着色效果。

consttoonMaterial=newTHREE.MeshToonMaterial({color:0x44aa88});

特点:

  • 卡通风格
  • 性能较好
  • 适合风格化渲染

3. 性能对比

3.1 性能对比表

材质类型顶点着色器片元着色器相对性能真实感
Basic简单简单⭐⭐⭐⭐⭐
Lambert中等简单⭐⭐⭐⭐⭐⭐
Phong中等中等⭐⭐⭐⭐⭐⭐
Standard复杂复杂⭐⭐⭐⭐⭐⭐
Physical复杂非常复杂⭐⭐⭐⭐⭐
Toon中等中等⭐⭐⭐⭐⭐⭐

3.2 性能测试代码

functionmeasureMaterialPerformance(material,iterations=1000){constgeometry=newTHREE.BoxGeometry(1,1,1);constmesh=newTHREE.Mesh(geometry,material);scene.add(mesh);conststart=performance.now();for(leti=0;i<iterations;i++){renderer.render(scene,camera);}constend=performance.now();scene.remove(mesh);returnend-start;}

4. 光源数量与性能

4.1 光源数量影响

光源数量BasicLambertPhongStandardPhysical
1100%120%140%160%180%
2100%140%180%220%260%
4100%180%260%340%420%
8100%260%420%580%740%

4.2 光源优化策略

// 限制光源数量constmaxLights=4;// 使用环境光减少光源需求constambientLight=newTHREE.AmbientLight(0x404040,0.5);// 使用光源辅助器调试constlightHelper=newTHREE.DirectionalLightHelper(directionalLight);

5. 性能优化技巧

5.1 材质优化

// 使用更简单的材质// 不需要高光时使用 Lambertconstmaterial=needsSpecular?newTHREE.MeshPhongMaterial({color:0x44aa88}):newTHREE.MeshLambertMaterial({color:0x44aa88});// 禁用不必要的特性material.transparent=false;material.depthTest=true;material.depthWrite=true;// 合并材质(相同材质的物体可以合并渲染)constmergedGeometry=BufferGeometryUtils.mergeBufferGeometries(geometries);constmergedMesh=newTHREE.Mesh(mergedGeometry,sharedMaterial);

5.2 纹理优化

// 降低纹理分辨率consttextureLoader=newTHREE.TextureLoader();consttexture=textureLoader.load('image.jpg');texture.minFilter=THREE.LinearFilter;texture.magFilter=THREE.LinearFilter;// 使用压缩纹理// 使用 BasisTexture 或 KTX2 格式

5.3 阴影优化

// 降低阴影质量renderer.shadowMap.type=THREE.BasicShadowMap;light.shadow.mapSize.width=512;light.shadow.mapSize.height=512;// 限制阴影范围light.shadow.camera.left=-5;light.shadow.camera.right=5;light.shadow.camera.top=5;light.shadow.camera.bottom=-5;// 禁用不必要的阴影backgroundMesh.castShadow=false;backgroundMesh.receiveShadow=false;

5.4 实例化渲染

// 大量相同物体使用 InstancedMeshconstcount=1000;constinstancedMesh=newTHREE.InstancedMesh(geometry,material,count);constdummy=newTHREE.Object3D();for(leti=0;i<count;i++){dummy.position.set(Math.random()*100-50,Math.random()*10,Math.random()*100-50);dummy.updateMatrix();instancedMesh.setMatrixAt(i,dummy.matrix);}instancedMesh.instanceMatrix.needsUpdate=true;scene.add(instancedMesh);

6. 光照模型选择指南

6.1 决策树

需要光照效果? │ ├─ 否 → MeshBasicMaterial │ └─ 是 → 需要高光效果? │ ├─ 否 → MeshLambertMaterial │ └─ 是 → 需要物理真实感? │ ├─ 否 → 性能优先? │ │ │ ├─ 是 → MeshPhongMaterial │ └─ 否 → MeshStandardMaterial │ └─ 是 → 需要透射/清漆? │ ├─ 是 → MeshPhysicalMaterial └─ 否 → MeshStandardMaterial

6.2 场景推荐

场景类型推荐材质理由
移动端 WebMeshBasicMaterial / MeshLambertMaterial性能优先
普通网页MeshStandardMaterial平衡性能与画质
产品展示MeshPhysicalMaterial最高画质
游戏MeshStandardMaterial适中性能
数据可视化MeshBasicMaterial无需光照
风格化MeshToonMaterial独特风格

7. 完整示例

import*asTHREEfrom'three';import{OrbitControls}from'three/examples/jsm/controls/OrbitControls.js';importStatsfrom'stats.js';constscene=newTHREE.Scene();scene.background=newTHREE.Color(0x111122);constcamera=newTHREE.PerspectiveCamera(45,window.innerWidth/window.innerHeight,0.1,1000);camera.position.set(8,6,12);camera.lookAt(0,0,0);constrenderer=newTHREE.WebGLRenderer({antialias:true});renderer.setSize(window.innerWidth,window.innerHeight);renderer.shadowMap.enabled=true;document.body.appendChild(renderer.domElement);constcontrols=newOrbitControls(camera,renderer.domElement);controls.enableDamping=true;// 性能监控conststats=newStats();stats.showPanel(0);document.body.appendChild(stats.dom);// 光源constambientLight=newTHREE.AmbientLight(0x404040,0.4);scene.add(ambientLight);constdirectionalLight=newTHREE.DirectionalLight(0xffffff,1);directionalLight.position.set(5,10,7);directionalLight.castShadow=true;scene.add(directionalLight);constfillLight=newTHREE.PointLight(0x88aaff,0.3);fillLight.position.set(-3,2,4);scene.add(fillLight);// 辅助对象constaxesHelper=newTHREE.AxesHelper(5);scene.add(axesHelper);constgridHelper=newTHREE.GridHelper(15,20);scene.add(gridHelper);constgeometry=newTHREE.SphereGeometry(0.8,64,64);// 不同材质对比constmaterials=[{name:'Basic',material:newTHREE.MeshBasicMaterial({color:0xff6600}),pos:[-3,1,-2]},{name:'Lambert',material:newTHREE.MeshLambertMaterial({color:0x44aa88}),pos:[0,1,-2]},{name:'Phong',material:newTHREE.MeshPhongMaterial({color:0x44aa88,shininess:60}),pos:[3,1,-2]},{name:'Standard',material:newTHREE.MeshStandardMaterial({color:0x44aa88,metalness:0.5,roughness:0.3}),pos:[-3,1,2]},{name:'Physical',material:newTHREE.MeshPhysicalMaterial({color:0x44aa88,metalness:0.5,roughness:0.3,clearcoat:0.5}),pos:[0,1,2]},{name:'Toon',material:newTHREE.MeshToonMaterial({color:0x44aa88}),pos:[3,1,2]}];materials.forEach((item)=>{constmesh=newTHREE.Mesh(geometry,item.material);mesh.position.set(item.pos[0],item.pos[1],item.pos[2]);mesh.castShadow=true;scene.add(mesh);});// 平面constplaneGeometry=newTHREE.PlaneGeometry(14,12);constplaneMaterial=newTHREE.MeshStandardMaterial({color:0x336699,side:THREE.DoubleSide});constplane=newTHREE.Mesh(planeGeometry,planeMaterial);plane.rotation.x=-Math.PI/2;plane.position.y=-0.5;plane.receiveShadow=true;scene.add(plane);// 标签import{CSS2DRenderer,CSS2DObject}from'three/examples/jsm/renderers/CSS2DRenderer.js';constlabelRenderer=newCSS2DRenderer();labelRenderer.setSize(window.innerWidth,window.innerHeight);labelRenderer.domElement.style.position='absolute';labelRenderer.domElement.style.top='0px';labelRenderer.domElement.style.left='0px';labelRenderer.domElement.style.pointerEvents='none';document.body.appendChild(labelRenderer.domElement);materials.forEach((item)=>{constdiv=document.createElement('div');div.textContent=item.name;div.style.color='white';div.style.background='rgba(0,0,0,0.6)';div.style.padding='4px 8px';div.style.borderRadius='4px';div.style.fontSize='14px';constlabel=newCSS2DObject(div);label.position.set(item.pos[0],item.pos[1]+1.2,item.pos[2]);scene.add(label);});// GUI 控制importGUIfrom'lil-gui';constgui=newGUI();// 光源强度控制gui.add(directionalLight,'intensity',0,2).name('主光强度');gui.add(fillLight,'intensity',0,1).name('补光强度');gui.add(ambientLight,'intensity',0,1).name('环境光强度');// 性能信息显示constperfFolder=gui.addFolder('性能信息');perfFolder.add({fps:0},'fps').name('FPS').listen();perfFolder.open();letframeCount=0;letlastTime=performance.now();functionanimate(){constnow=performance.now();frameCount++;if(now-lastTime>=1000){stats.update();perfFolder.controllers[0].setValue(frameCount);frameCount=0;lastTime=now;}stats.begin();controls.update();renderer.render(scene,camera);labelRenderer.render(scene,camera);stats.end();requestAnimationFrame(animate);}animate();window.addEventListener('resize',onWindowResize,false);functiononWindowResize(){camera.aspect=window.innerWidth/window.innerHeight;camera.updateProjectionMatrix();renderer.setSize(window.innerWidth,window.innerHeight);labelRenderer.setSize(window.innerWidth,window.innerHeight);}

8. 总结

材质类型特点性能适用场景
Basic无光照⭐⭐⭐⭐⭐调试、UI
Lambert漫反射⭐⭐⭐⭐粗糙表面
Phong漫反射+高光⭐⭐⭐光滑表面
StandardPBR⭐⭐大多数场景
Physical高级 PBR高端场景
Toon卡通⭐⭐⭐⭐风格化
优化策略说明
选择合适的材质不需要高光时用 Lambert
限制光源数量每增加一个光源性能下降
降低阴影质量使用 BasicShadowMap
纹理压缩使用压缩格式
实例化渲染大量相同物体
禁用阴影不需要阴影时关闭

9. 第二部分总结

恭喜你完成了第二部分:光照与阴影

你已掌握:

  1. ✅ 光源类型(环境光、平行光、点光源、聚光灯、半球光)
  2. ✅ 光照属性与配置(颜色、强度、位置、衰减)
  3. ✅ 阴影系统(启用、配置、优化)
  4. ✅ 反射与折射(环境贴图、玻璃材质)
  5. ✅ 光照模型与性能(材质选择、性能优化)

http://www.jsqmd.com/news/730809/

相关文章:

  • 番茄小说下载器终极指南:打造个人离线图书馆的完整解决方案
  • 实战指南:如何高效管理Steam游戏成就与进度
  • 终极指南:使用React-PDF与Auth0集成生成安全PDF文档
  • 视线交互革命:如何用开源技术实现精准眼动追踪
  • 终极指南:tview鼠标事件 - 实现终端中的点击交互功能
  • 7天掌握PyQt6:从零到一的Python桌面应用开发实战指南
  • Dify插件Webhook安全加固实战:从CSRF到SSRF,如何用200行TypeScript代码实现零信任回调验证?
  • 第三部分-纹理与贴图——14. 纹理基础
  • ts-prune vs knip:哪个更适合你的TypeScript项目?
  • 技术变革:Sunshine如何重新定义自托管游戏串流体验
  • Llama-3.2V-11B-cot实操手册:推理过程JSON日志结构与字段说明
  • Linux线程栈内存优化详解 机制风险调优与排障实践
  • CPPM和CPSM同时备考可行吗 - 众智商学院官方
  • 革命性视线交互解决方案:eyetracker如何实现无鼠标电脑控制?
  • 3步掌握OBS多平台直播:obs-multi-rtmp插件完全指南
  • 苹果新款iPhone或推“液态玻璃”全曲面屏,是旧方案轮回还是创新突破?
  • Seraphine:英雄联盟玩家的终极自动化助手使用指南
  • 3种快速解决TranslucentTB启动失败的终极指南:让Windows任务栏透明化工具完美运行
  • Linux服务器安全加固终极指南:10个关键步骤全面保护你的系统
  • 第二部分-光照与阴影——09. 光源类型
  • 存储字长是一个存储单元的位数还是一次读写从主存中提取的位数 刚学计组, 我看王道书和我问ai的答案不太一样,有些疑惑
  • TI LMR14030电源芯片选型避坑:开关频率设到2MHz,为什么我的板子一上36V就炸?
  • 从预测到干预:基于因果推断的决策引擎架构与实战
  • BBDown深度解析:高效下载B站视频的完整实战指南
  • 3分钟快速查询:如何通过手机号找到对应的QQ号码
  • LinkSwift网盘直链下载助手:八大主流网盘一站式解决方案终极指南
  • AMD Ryzen处理器深度调校终极指南:免费开源工具SMUDebugTool完整教程
  • 适合新人财经记者采访准备用的,市场营销会议干货指南
  • AudioSeal Pixel Studio部署案例:在线教育平台录播课防录屏盗用系统
  • 2026年3月食品输送带工厂推荐,食品输送带/输送带/pvc输送带/工业皮带,食品输送带公司有哪些 - 品牌推荐师