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

第二部分-光照与阴影——12. 反射与折射

12. 反射与折射

1. 概述

反射和折射是创建逼真材质(如金属、玻璃、水面)的关键技术。Three.js 通过环境贴图(Environment Map)和 MeshPhysicalMaterial 的透射属性来实现这些效果。

┌─────────────────────────────────────────────────────────────┐ │ 反射与折射体系 │ ├─────────────────────────────────────────────────────────────┤ │ │ │ 环境贴图(Environment Map) │ │ ├── CubeTextureLoader:立方体贴图 │ │ ├── CubeCamera:实时环境贴图 │ │ └── Scene.background:场景背景 │ │ │ │ 反射效果 │ │ ├── MeshStandardMaterial.envMap │ │ ├── MeshPhysicalMaterial.envMap │ │ └── 金属材质自然反射 │ │ │ │ 折射效果 │ │ ├── transmission:透射率 │ │ ├── thickness:厚度 │ │ ├── ior:折射率 │ │ └── roughness:粗糙度 │ │ │ └─────────────────────────────────────────────────────────────┘

2. 环境贴图(Environment Map)

2.1 CubeTextureLoader(立方体贴图)

import*asTHREEfrom'three';constcubeTextureLoader=newTHREE.CubeTextureLoader();// 加载6个面的纹理(顺序:右、左、上、下、前、后)constenvMap=cubeTextureLoader.load(['px.jpg',// 右 (x正方向)'nx.jpg',// 左 (x负方向)'py.jpg',// 上 (y正方向)'ny.jpg',// 下 (y负方向)'pz.jpg',// 前 (z正方向)'nz.jpg'// 后 (z负方向)]);// 设置为场景背景scene.background=envMap;// 设置为环境反射贴图scene.environment=envMap;// 设置为材质的环境贴图constmaterial=newTHREE.MeshStandardMaterial({color:0xffffff,metalness:0.9,roughness:0.2,envMap:envMap});

2.2 从 HDR 文件加载

import{RGBELoader}from'three/examples/jsm/loaders/RGBELoader.js';constrgbeLoader=newRGBELoader();rgbeLoader.load('environment.hdr',(texture)=>{texture.mapping=THREE.EquirectangularMapping;scene.environment=texture;scene.background=texture;});

2.3 从 JSON 文件加载

import{EXRLoader}from'three/examples/jsm/loaders/EXRLoader.js';constexrLoader=newEXRLoader();exrLoader.load('environment.exr',(texture)=>{texture.mapping=THREE.EquirectangularMapping;scene.environment=texture;});

3. 实时反射(CubeCamera)

CubeCamera 用于实时生成周围环境的环境贴图。

3.1 CubeCamera 配置

// 创建 CubeCameraconstcubeRenderTarget=newTHREE.WebGLCubeRenderTarget(256,{format:THREE.RGBAFormat,generateMipmaps:true,minFilter:THREE.LinearMipmapLinearFilter});constcubeCamera=newTHREE.CubeCamera(0.1,1000,cubeRenderTarget);// 在需要反射的位置更新 CubeCameracubeCamera.update(renderer,scene);// 获取反射贴图constenvMap=cubeRenderTarget.texture;

3.2 实时反射示例

constmirrorMaterial=newTHREE.MeshStandardMaterial({metalness:1,roughness:0.1,envMap:cubeRenderTarget.texture});constmirrorSphere=newTHREE.Mesh(sphereGeometry,mirrorMaterial);scene.add(mirrorSphere);functionanimate(){// 每帧更新 CubeCameramirrorSphere.visible=false;cubeCamera.update(renderer,scene);mirrorSphere.visible=true;renderer.render(scene,camera);}

4. 材质反射属性

4.1 MeshStandardMaterial 反射

// 金属材质(高反射)constmetalMaterial=newTHREE.MeshStandardMaterial({color:0xccaa88,metalness:0.95,roughness:0.2,envMap:envMap,envMapIntensity:1.0});// 抛光金属constpolishedMetal=newTHREE.MeshStandardMaterial({color:0xffffff,metalness:0.98,roughness:0.05,envMapIntensity:1.2});// 拉丝金属constbrushedMetal=newTHREE.MeshStandardMaterial({color:0xaaaaaa,metalness:0.9,roughness:0.4,envMapIntensity:0.8});

4.2 MeshPhysicalMaterial 反射增强

// 清漆层增强反射constglossyMaterial=newTHREE.MeshPhysicalMaterial({color:0x88aaff,metalness:0.8,roughness:0.2,clearcoat:1.0,clearcoatRoughness:0.1,envMapIntensity:1.0});// 丝绸质感constsilkMaterial=newTHREE.MeshPhysicalMaterial({color:0xcc8866,metalness:0.3,roughness:0.5,sheen:0.8,sheenColor:0xffaa88,envMapIntensity:0.6});

5. 折射效果

5.1 玻璃材质(MeshPhysicalMaterial)

// 基础玻璃constglassMaterial=newTHREE.MeshPhysicalMaterial({color:0x88aaff,metalness:0.9,roughness:0.1,transparent:true,opacity:0.5,transmission:0.9,// 透射率thickness:0.5,// 厚度ior:1.5// 折射率});// 有色玻璃consttintedGlass=newTHREE.MeshPhysicalMaterial({color:0xff8866,metalness:0.9,roughness:0.05,transparent:true,opacity:0.7,transmission:0.8,thickness:0.3,ior:1.5});// 磨砂玻璃constfrostedGlass=newTHREE.MeshPhysicalMaterial({color:0xffffff,metalness:0,roughness:0.3,transparent:true,opacity:0.6,transmission:0.85,thickness:0.4,ior:1.5});

5.2 折射率(IOR)参考

材质IOR
真空1.0
空气1.0003
1.31
1.33
玻璃1.5
蓝宝石1.77
钻石2.42

6. 反射探针(Reflection Probe)

import{Reflector}from'three/examples/jsm/objects/Reflector.js';// 地面反射constreflector=newReflector(planeGeometry,{clipBias:0.003,textureWidth:1024,textureHeight:1024,color:0x8899aa});reflector.position.y=-0.5;reflector.rotateX(-Math.PI/2);scene.add(reflector);

7. 完整示例

import*asTHREEfrom'three';import{OrbitControls}from'three/examples/jsm/controls/OrbitControls.js';import{RGBELoader}from'three/examples/jsm/loaders/RGBELoader.js';constscene=newTHREE.Scene();scene.background=newTHREE.Color(0x111122);constcamera=newTHREE.PerspectiveCamera(45,window.innerWidth/window.innerHeight,0.1,1000);camera.position.set(5,4,8);camera.lookAt(0,0,0);constrenderer=newTHREE.WebGLRenderer({antialias:true});renderer.setSize(window.innerWidth,window.innerHeight);renderer.shadowMap.enabled=true;renderer.toneMapping=THREE.ACESFilmicToneMapping;renderer.toneMappingExposure=1.2;document.body.appendChild(renderer.domElement);constcontrols=newOrbitControls(camera,renderer.domElement);controls.enableDamping=true;// 加载环境贴图constcubeTextureLoader=newTHREE.CubeTextureLoader();// 使用在线资源或本地资源// const envMap = cubeTextureLoader.load([// 'px.jpg', 'nx.jpg', 'py.jpg', 'ny.jpg', 'pz.jpg', 'nz.jpg'// ]);// scene.environment = envMap;// 辅助对象constaxesHelper=newTHREE.AxesHelper(5);scene.add(axesHelper);constgridHelper=newTHREE.GridHelper(15,20);scene.add(gridHelper);// 光源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);// 金属球constsphereGeometry=newTHREE.SphereGeometry(0.8,128,128);// 金属材质constmetalMaterial=newTHREE.MeshStandardMaterial({color:0xccaa88,metalness:0.95,roughness:0.2});constmetalSphere=newTHREE.Mesh(sphereGeometry,metalMaterial);metalSphere.position.set(-2,0.8,0);metalSphere.castShadow=true;scene.add(metalSphere);// 玻璃球constglassMaterial=newTHREE.MeshPhysicalMaterial({color:0x88aaff,metalness:0.9,roughness:0.1,transparent:true,opacity:0.6,transmission:0.9,thickness:0.5,ior:1.5});constglassSphere=newTHREE.Mesh(sphereGeometry,glassMaterial);glassSphere.position.set(2,0.8,0);glassSphere.castShadow=true;scene.add(glassSphere);// 立方体constboxGeometry=newTHREE.BoxGeometry(1,1,1);// 抛光金属立方体constpolishedMaterial=newTHREE.MeshStandardMaterial({color:0xffffff,metalness:0.98,roughness:0.05});constpolishedCube=newTHREE.Mesh(boxGeometry,polishedMaterial);polishedCube.position.set(-2,0.5,2);polishedCube.castShadow=true;scene.add(polishedCube);// 彩色玻璃立方体constcoloredGlass=newTHREE.MeshPhysicalMaterial({color:0xff8866,metalness:0.9,roughness:0.05,transparent:true,opacity:0.7,transmission:0.85,thickness:0.4,ior:1.5});constglassCube=newTHREE.Mesh(boxGeometry,coloredGlass);glassCube.position.set(2,0.5,2);glassCube.castShadow=true;scene.add(glassCube);// 平面(地面)constplaneGeometry=newTHREE.PlaneGeometry(12,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);// GUI 控制importGUIfrom'lil-gui';constgui=newGUI();// 金属球控制constmetalFolder=gui.addFolder('金属球');metalFolder.add(metalMaterial,'metalness',0,1).name('金属度');metalFolder.add(metalMaterial,'roughness',0,1).name('粗糙度');metalFolder.add(metalMaterial,'envMapIntensity',0,2).name('环境强度');metalFolder.open();// 玻璃球控制constglassFolder=gui.addFolder('玻璃球');glassFolder.add(glassMaterial,'metalness',0,1).name('金属度');glassFolder.add(glassMaterial,'roughness',0,1).name('粗糙度');glassFolder.add(glassMaterial,'transparency',0,1).name('透明度').onChange(val=>{glassMaterial.transparent=val>0;glassMaterial.opacity=val;});glassFolder.add(glassMaterial,'transmission',0,1).name('透射率');glassFolder.add(glassMaterial,'thickness',0,1).name('厚度');glassFolder.add(glassMaterial,'ior',1,2.5).name('折射率');glassFolder.open();// 动画functionanimate(){requestAnimationFrame(animate);// 旋转物体metalSphere.rotation.y+=0.005;glassSphere.rotation.y+=0.005;polishedCube.rotation.x+=0.01;polishedCube.rotation.y+=0.01;glassCube.rotation.x+=0.01;glassCube.rotation.y+=0.01;controls.update();renderer.render(scene,camera);}animate();window.addEventListener('resize',onWindowResize,false);functiononWindowResize(){camera.aspect=window.innerWidth/window.innerHeight;camera.updateProjectionMatrix();renderer.setSize(window.innerWidth,window.innerHeight);}

8. 总结

技术类/方法用途
环境贴图CubeTextureLoader加载预制的环境贴图
HDR 环境RGBELoader加载 HDR 格式环境贴图
实时反射CubeCamera动态生成环境贴图
金属反射metalness控制金属反射强度
玻璃折射transmission控制透射率
厚度thickness影响折射强度
折射率ior影响光线弯曲程度
材质属性说明适用材质
metalness金属度 (0-1)Standard, Physical
roughness粗糙度 (0-1)Standard, Physical
envMap环境贴图Standard, Physical
envMapIntensity环境强度Standard, Physical
transparent透明开关所有
opacity透明度所有
transmission透射率Physical
thickness厚度Physical
ior折射率Physical
clearcoat清漆层Physical

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

相关文章:

  • 3步找回你的微信聊天记录:WechatDecrypt解密工具完全指南
  • 解决 SteamOS 无法上网问题:ToMoon DNS 复原完全指南
  • Rubberduck性能优化指南:如何在大项目中流畅使用
  • 2026年知网AI检测动真格!6个必看技巧助你论文轻松通过 - 降AI实验室
  • 基于Next.js构建AI食谱社区平台:ClawMarket全栈开发实战
  • 7个实战技巧掌握PyKAN持续学习:从数据流处理到智能模型更新全指南
  • E7Helper终极指南:第七史诗自动化助手完整使用教程
  • 本地化AI编程助手CoPaw:隐私、零延迟的代码补全实战指南
  • 第二部分-光照与阴影——13. 光照模型与性能
  • 番茄小说下载器终极指南:打造个人离线图书馆的完整解决方案
  • 实战指南:如何高效管理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的答案不太一样,有些疑惑