three.js 7 材质
import * as THREE from 'three'; import { OrbitControls } from "three/examples/jsm/controls/OrbitControls"; import { RectAreaLightHelper } from "three/examples/jsm/helpers/RectAreaLightHelper"; /** * 3d Material 材质 * https://threejs.org/docs/index.html#api/zh/materials/LineBasicMaterial */ export class ThreeDoc7Material { constructor(canvasId) { this.work(canvasId); } work(canvasId) { // 创建 3d 场景 const scene = new THREE.Scene(); scene.background = new THREE.Color(0x9e9e9e); const renderer = new THREE.WebGLRenderer(); renderer.setSize(window.innerWidth, window.innerHeight); // 最后一步很重要,我们将renderer(渲染器)的dom元素(renderer.domElement)添加到我们的HTML文档中。这就是渲染器用来显示场景给我们看的<canvas>元素。 document.body.appendChild(renderer.domElement); // AxesHelper 3个坐标轴的对象. this.addAxesHelper(scene); // 添加几何体 const geometry = new THREE.BoxGeometry(1, 1, 1); let material; // 基础线条材质(LineBasicMaterial) - 不受光照影响? material = this.getLineBasicMaterial(); // 虚线材质(LineDashedMaterial) - 不受光照影响? material = this.getLineDashedMaterial(); // 基础网格材质(MeshBasicMaterial) - 这种材质不受光照的影响。 material = this.getMeshBasicMaterial(); // 深度网格材质(MeshDepthMaterial) material = this.getMeshDepthMaterial(); // MeshDistanceMaterial // material = this.getMeshDistanceMaterial(); // Lambert网格材质(MeshLambertMaterial) - 一种非光泽表面的材质,没有镜面高光。 material = this.getMeshLambertMaterial(); // MeshMatcapMaterial material = this.getMeshMatcapMaterial(); // 法线网格材质(MeshNormalMaterial) material = this.getMeshNormalMaterial(); // Phong网格材质(MeshPhongMaterial) material = this.getMeshPhongMaterial(); // 物理网格材质(MeshPhysicalMaterial) material = this.getMeshPhysicalMaterial(); // 标准网格材质(MeshStandardMaterial) material = this.getMeshStandardMaterial(); // MeshToonMaterial material = this.getMeshToonMaterial(); // 点材质(PointsMaterial) this.getPointsMaterial(scene); // 原始着色器材质(RawShaderMaterial) - 需要额外 script 内容,参考 three.js webgl_buffergeometry_rawshader.html // material = this.getRawShaderMaterial(scene); // 着色器材质(ShaderMaterial) - 类似上一个 // 阴影材质(ShadowMaterial) this.getShadowMaterial(scene); // 点精灵材质(SpriteMaterial) this.getSpriteMaterial(scene); // 创建物体 const dodecahedron = new THREE.Mesh(geometry, material); scene.add(dodecahedron); // 包围盒辅助线框对象 // const box = new THREE.BoxHelper(dodecahedron, 0xffff00); // scene.add(box); // 半球光(HemisphereLight) this.addHemisphereLight(scene); // 平面光光源(RectAreaLight) this.addRectAreaLight(scene); const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000); // 设置相机位置 camera.position.x = 10; camera.position.y = 10; camera.position.z = 10; // camera.lookAt(0, 0, 0); // 添加控制器 let orb = new OrbitControls(camera, document.body); orb.addEventListener('change', function () { renderer.render(scene, camera); }); renderer.render(scene, camera); } /** * AxesHelper * 用于简单模拟3个坐标轴的对象. * 红色代表 X 轴. 绿色代表 Y 轴. 蓝色代表 Z 轴. * AxesHelper( size : Number ) * size -- (可选的) 表示代表轴的线段长度. 默认为 1. */ addAxesHelper(scene) { const axesHelper = new THREE.AxesHelper(12); scene.add(axesHelper); } /** * 半球光(HemisphereLight) - 喜欢这个光 * 光源直接放置于场景之上,光照颜色从天空光线颜色渐变到地面光线颜色。 * 半球光不能投射阴影。 * * HemisphereLight( skyColor : Integer, groundColor : Integer, intensity : Float ) * skyColor - (可选参数) 天空中发出光线的颜色。 缺省值 0xffffff。 * groundColor - (可选参数) 地面发出光线的颜色。 缺省值 0xffffff。 * intensity - (可选参数) 光照强度。 缺省值 1。 */ addHemisphereLight(scene) { const light = new THREE.HemisphereLight(0xffffbb, 0x080820, 100); scene.add(light); light.position.set(0, -5, 0); const helper = new THREE.HemisphereLightHelper(light, 3); scene.add(helper); } /** * 平面光光源(RectAreaLight) - 这个光源也不错! * 平面光光源从一个矩形平面上均匀地发射光线。这种光源可以用来模拟像明亮的窗户或者条状灯光光源。 * 注意事项: * 不支持阴影。 * 只支持 MeshStandardMaterial 和 MeshPhysicalMaterial 两种材质。 * 你必须在你的场景中加入 RectAreaLightUniformsLib ,并调用init()。 * * RectAreaLight( color : Integer, intensity : Float, width : Float, height : Float ) * color - (可选参数) 十六进制数字表示的光照颜色。缺省值为 0xffffff (白色) * intensity - (可选参数) 光源强度/亮度 。缺省值为 1。 * width - (可选参数) 光源宽度。缺省值为 10。 * height - (可选参数) 光源高度。缺省值为 10。 */ addRectAreaLight(scene) { const width = 20; const height = 10; const intensity = 100; const rectLight = new THREE.RectAreaLight(0xffffff, intensity, width, height); rectLight.position.set(5, 5, 0); rectLight.lookAt(0, 0, 0); scene.add(rectLight); let rectLightHelper = new RectAreaLightHelper(rectLight); scene.add(rectLightHelper); } /** * 基础线条材质(LineBasicMaterial) - 不受光照影响? * LineBasicMaterial( parameters : Object ) * parameters - (可选)用于定义材质外观的对象,具有一个或多个属性。材质的任何属性都可以从此处传入(包括从Material继承的任何属性)。 * 属性color例外,其可以作为十六进制字符串传递,默认情况下为 0xffffff(白色),内部调用Color.set(color)。 * .color : Color * 材质的颜色(Color),默认值为白色 (0xffffff)。 * .fog : Boolean * 材质是否受雾影响。默认为true。 * .linewidth : Float * 控制线宽。默认值为 1。 * 由于OpenGL Core Profile与 大多数平台上WebGL渲染器的限制,无论如何设置该值,线宽始终为1。 * .linecap : String * 定义线两端的样式。可选值为 'butt', 'round' 和 'square'。默认值为 'round'。 * 该属性对应2D Canvas lineCap属性, 并且会被WebGL渲染器忽略。 * .linejoin : String * 定义线连接节点的样式。可选值为 'round', 'bevel' 和 'miter'。默认值为 'round'。 */ getLineBasicMaterial() { return new THREE.LineBasicMaterial({ color: 0x00ffff, linewidth: 1, linecap: 'round', //ignored by WebGLRenderer linejoin: 'round' //ignored by WebGLRenderer }); } /** * 虚线材质(LineDashedMaterial) - 不受光照影响? * LineDashedMaterial( parameters : Object ) * parameters - (可选)用于定义材质外观的对象,具有一个或多个属性。材质的任何属性都可以从此处传入 * (包括从LineBasicMaterial继承的任何属性)。 * .dashSize : number * 虚线的大小,是指破折号和间隙之和。默认值为 3。 * .gapSize : number * 间隙的大小,默认值为 1。 * .isLineDashedMaterial : Boolean * Read-only flag to check if a given object is of type LineDashedMaterial. * .scale : number * 线条中虚线部分的占比。默认值为 1。 */ getLineDashedMaterial() { return new THREE.LineDashedMaterial({ color: 0x00ffff, linewidth: 1, scale: 1, dashSize: 3, gapSize: 1, }); } /** * 基础网格材质(MeshBasicMaterial) * 一个以简单着色(平面或线框)方式来绘制几何体的材质。 * 这种材质不受光照的影响。 * MeshBasicMaterial( parameters : Object ) * parameters - (可选)用于定义材质外观的对象,具有一个或多个属性。材质的任何属性都可以从此处传入(包括从Material继承的任何属性)。 * 属性color例外,其可以作为十六进制字符串传递,默认情况下为 0xffffff(白色),内部调用Color.set(color)。 * .alphaMap : Texture * alpha贴图是一张灰度纹理,用于控制整个表面的不透明度。(黑色:完全透明;白色:完全不透明)。 默认值为null。 * 仅使用纹理的颜色,忽略alpha通道(如果存在)。 对于RGB和RGBA纹理,WebGL渲染器在采样此纹理时将使用绿色通道, 因为在DXT压缩和未压缩RGB 565格式中为绿色提供了额外的精度。 Luminance-only以及luminance/alpha纹理也仍然有效。 * .aoMap : Texture * 该纹理的红色通道用作环境遮挡贴图。默认值为null。aoMap需要第二组UV。 * .aoMapIntensity : Float * 环境遮挡效果的强度。默认值为1。零是不遮挡效果。 * .color : Color * 材质的颜色(Color),默认值为白色 (0xffffff)。 * .combine : Integer * 如何将表面颜色的结果与环境贴图(如果有)结合起来。 * 选项为THREE.MultiplyOperation(默认值),THREE.MixOperation, THREE.AddOperation。如果选择多个,则使用.reflectivity在两种颜色之间进行混合。 * .envMap : Texture * 环境贴图。默认值为null。 * .fog : Boolean * 材质是否受雾影响。默认为true。 * .lightMap : Texture * 光照贴图。默认值为null。lightMap需要第二组UV。 * .lightMapIntensity : Float * 烘焙光的强度。默认值为1。 * .map : Texture * 颜色贴图。默认为null。 * .reflectivity : Float * 环境贴图对表面的影响程度; 见.combine。默认值为1,有效范围介于0(无反射)和1(完全反射)之间。 * .refractionRatio : Float * 空气的折射率(IOR)(约为1)除以材质的折射率。它与环境映射模式THREE.CubeRefractionMapping 和THREE.EquirectangularRefractionMapping一起使用。 The index of refraction (IOR) of air (approximately 1) divided by the index of refraction of the material. It is used with environment mapping mode THREE.CubeRefractionMapping. 折射率不应超过1。默认值为0.98。 * .specularMap : Texture * 材质使用的高光贴图。默认值为null。 * .wireframe : Boolean * 将几何体渲染为线框。默认值为false(即渲染为平面多边形)。 * .wireframeLinecap : String * 定义线两端的外观。可选值为 'butt','round' 和 'square'。默认为'round'。 * 该属性对应2D Canvas lineJoin属性, 并且会被WebGL渲染器忽略。 * .wireframeLinejoin : String * 定义线连接节点的样式。可选值为 'round', 'bevel' 和 'miter'。默认值为 'round'。 * 该属性对应2D Canvas lineJoin属性, 并且会被WebGL渲染器忽略。 * .wireframeLinewidth : Float * 控制线框宽度。默认值为1。 */ getMeshBasicMaterial() { return new THREE.MeshBasicMaterial({ color: 0x00ffff, }); } /** * 深度网格材质(MeshDepthMaterial) * 一种按深度绘制几何体的材质。深度基于相机远近平面。白色最近,黑色最远。 * MeshDepthMaterial( parameters : Object ) * parameters - (可选)用于定义材质外观的对象,具有一个或多个属性。 材质的任何属性都可以从此处传入(包括从Material继承的任何属性)。 * .alphaMap : Texture * alpha贴图是一张灰度纹理,用于控制整个表面的不透明度。(黑色:完全透明;白色:完全不透明)。 默认值为null。 * 仅使用纹理的颜色,忽略alpha通道(如果存在)。 对于RGB和RGBA纹理,WebGL渲染器在采样此纹理时将使用绿色通道, 因为在DXT压缩和未压缩RGB 565格式中为绿色提供了额外的精度。 Luminance-only以及luminance/alpha纹理也仍然有效。 * .depthPacking : Constant * depth packing的编码。默认为BasicDepthPacking。 * .displacementMap : Texture * 位移贴图会影响网格顶点的位置,与仅影响材质的光照和阴影的其他贴图不同,移位的顶点可以投射阴影,阻挡其他对象,以及充当真实的几何体。 位移纹理是指:网格的所有顶点被映射为图像中每个像素的值(白色是最高的),并且被重定位。 * .displacementScale : Float * 位移贴图对网格的影响程度(黑色是无位移,白色是最大位移)。如果没有设置位移贴图,则不会应用此值。默认值为1。 * .displacementBias : Float * 位移贴图在网格顶点上的偏移量。如果没有设置位移贴图,则不会应用此值。默认值为0。 * .map : Texture * 颜色贴图。默认为null。 * .wireframe : Boolean * 将几何体渲染为线框。默认值为false(即渲染为平滑着色)。 * .wireframeLinewidth : Float * 控制线框宽度。默认值为1。 */ getMeshDepthMaterial() { return new THREE.MeshDepthMaterial({ color: 0xffffff, }); } /** * Lambert网格材质(MeshLambertMaterial) * 一种非光泽表面的材质,没有镜面高光。 * * 该材质使用基于非物理的Lambertian模型来计算反射率。 这可以很好地模拟一些表面(例如未经处理的木材或石材),但不能模拟具有镜面高光的光泽表面(例如涂漆木材)。 * MeshLambertMaterial( parameters : Object ) * parameters - (可选)用于定义材质外观的对象,具有一个或多个属性。 材质的任何属性都可以从此处传入(包括从Material继承的任何属性)。 * * 属性color例外,其可以作为十六进制字符串传递,默认情况下为 0xffffff(白色),内部调用Color.set(color)。 */ getMeshLambertMaterial() { return new THREE.MeshDepthMaterial({ color: 0x00ffff, }); } /** * MeshMatcapMaterial * MeshMatcapMaterial 由一个材质捕捉(MatCap,或光照球(Lit Sphere))纹理所定义,其编码了材质的颜色与明暗。 * MeshMatcapMaterial( parameters : Object ) * parameters - (可选)用于定义材质外观的对象,具有一个或多个属性。 材质的任何属性都可以从此处传入(包括从Material继承的任何属性)。 * * 属性color例外,其可以作为十六进制字符串传递,默认情况下为 0xffffff(白色),内部调用Color.set(color)。 */ getMeshMatcapMaterial() { return new THREE.MeshDepthMaterial({ color: 0x00ffff, }); } /** * 法线网格材质(MeshNormalMaterial) * 一种把法向量映射到RGB颜色的材质。 * MeshNormalMaterial( parameters : Object ) * parameters - (可选)用于定义材质外观的对象,具有一个或多个属性。材质的任何属性都可以从此处传入(包括从Material继承的任何属性)。 */ getMeshNormalMaterial() { return new THREE.MeshNormalMaterial({}); } /** * Phong网格材质(MeshPhongMaterial) * 一种用于具有镜面高光的光泽表面的材质。 * MeshPhongMaterial( parameters : Object ) * parameters - (可选)用于定义材质外观的对象,具有一个或多个属性。 材质的任何属性都可以从此处传入(包括从Material继承的任何属性)。 * * 属性color例外,其可以作为十六进制字符串传递,默认情况下为 0xffffff(白色),内部调用Color.set(color)。 */ getMeshPhongMaterial() { return new THREE.MeshPhongMaterial({ color: 0x00ffff, }); } /** * 物理网格材质(MeshPhysicalMaterial) * MeshStandardMaterial的扩展,提供了更高级的基于物理的渲染属性: * * Clearcoat: 有些类似于车漆,碳纤,被水打湿的表面的材质需要在面上再增加一个透明的,具有一定反光特性的面。而且这个面说不定有一定的起伏与粗糙度。Clearcoat可以在不需要重新创建一个透明的面的情况下做到类似的效果。 * 基于物理的透明度:.opacity属性有一些限制:在透明度比较高的时候,反射也随之减少。使用基于物理的透光性.transmission属性可以让一些很薄的透明表面,例如玻璃,变得更真实一些。 * 高级光线反射: 为非金属材质提供了更多更灵活的光线反射。 * MeshPhysicalMaterial( parameters : Object ) * parameters - (可选)用于定义材质外观的对象,具有一个或多个属性。 材质的任何属性都可以从此处传入(包括从Material和MeshStandardMaterial继承的任何属性) * * 属性color例外,其可以作为十六进制字符串传递,默认情况下为 0xffffff(白色),内部调用Color.set(color)。 */ getMeshPhysicalMaterial() { return new THREE.MeshPhysicalMaterial({ color: 0x00ffff, }); } /** * 标准网格材质(MeshStandardMaterial) * 一种基于物理的标准材质,使用Metallic-Roughness工作流程。 * * 基于物理的渲染(PBR)最近已成为许多3D应用程序的标准,例如Unity, Unreal和 3D Studio Max。 * MeshStandardMaterial( parameters : Object ) * parameters - (可选)用于定义材质外观的对象,具有一个或多个属性。 材质的任何属性都可以从此处传入(包括从Material继承的任何属性)。 * * 属性color例外,其可以作为十六进制字符串传递,默认情况下为 0xffffff(白色),内部调用Color.set(color)。 */ getMeshStandardMaterial() { return new THREE.MeshPhysicalMaterial({ color: 0x049EF4, }); } /** * MeshToonMaterial * A material implementing toon shading. * MeshToonMaterial( parameters : Object ) * parameters - (optional) an object with one or more properties defining the material's appearance. Any property * of the material (including any property inherited from Material) can be passed in here. */ getMeshToonMaterial() { return new THREE.MeshToonMaterial({ color: 0x00ffff, }); } /** * 点材质(PointsMaterial) * Points使用的默认材质。 * PointsMaterial( parameters : Object ) * parameters - (可选)用于定义材质外观的对象,具有一个或多个属性。 材质的任何属性都可以从此处传入(包括从Material继承的任何属性)。 * * 属性color例外,其可以作为十六进制字符串传递,默认情况下为 0xffffff(白色),内部调用Color.set(color)。 */ getPointsMaterial(scene) { const vertices = []; for (let i = 0; i < 10000; i++) { const x = THREE.MathUtils.randFloatSpread(2000); const y = THREE.MathUtils.randFloatSpread(2000); const z = THREE.MathUtils.randFloatSpread(2000); vertices.push(x, y, z); } const geometry = new THREE.BufferGeometry(); geometry.setAttribute('position', new THREE.Float32BufferAttribute(vertices, 3)); const material = new THREE.PointsMaterial({ color: 0x000000 }); const points = new THREE.Points(geometry, material); scene.add(points); } /** * 原始着色器材质(RawShaderMaterial) * 此类的工作方式与ShaderMaterial类似,不同之处在于内置的uniforms和attributes的定义不会自动添加到GLSL shader代码中。 * RawShaderMaterial( parameters : Object ) * parameters - (可选)用于定义材质外观的对象,具有一个或多个属性。 材质的任何属性都可以从此处传入(包括从Material 和 ShaderMaterial继承的任何属性)。 */ getRawShaderMaterial() { return new THREE.RawShaderMaterial({ uniforms: { time: { value: 1.0 } }, vertexShader: document.getElementById('vertexShader').textContent, fragmentShader: document.getElementById('fragmentShader').textContent, }); } /** * 阴影材质(ShadowMaterial) * 此材质可以接收阴影,但在其他方面完全透明。 * ShadowMaterial( parameters : Object ) * parameters - (可选)用于定义材质外观的对象,具有一个或多个属性。 材质的任何属性都可以从此处传入(包括从Material继承的任何属性)。 */ getShadowMaterial(scene) { const geometry = new THREE.PlaneGeometry( 2000, 2000 ); geometry.rotateX( - Math.PI / 2 ); const material = new THREE.ShadowMaterial(); material.opacity = 0.2; const plane = new THREE.Mesh( geometry, material ); plane.receiveShadow = true; scene.add( plane ); } /** * 点精灵材质(SpriteMaterial) * 一种使用Sprite的材质。 * SpriteMaterial( parameters : Object ) * parameters - (可选)用于定义材质外观的对象,具有一个或多个属性。 材质的任何属性都可以从此处传入(包括从Material 和 ShaderMaterial继承的任何属性)。 * * 属性color例外,其可以作为十六进制字符串传递,默认情况下为 0xffffff(白色), 内部调用Color.set(color)。 SpriteMaterials不会被Material.clippingPlanes裁剪。 */ getSpriteMaterial(scene) { const map = new THREE.TextureLoader().load( 'assets/111.png' ); const material = new THREE.SpriteMaterial( { map: map, color: 0xffffff } ); const sprite = new THREE.Sprite( material ); sprite.scale.set(200, 200, 0); scene.add( sprite ); } }