ARTICLE DETAIL

资讯详情

深耕网站建设、视觉设计与SEO优化的一线实战洞察。

three.js PointsMaterial 完全指南:点图元材质的属性配置、着色器原理与粒子实战

three.js PointsMaterial 完全指南:点图元材质的属性配置、着色器原理与粒子实战 three.js PointsMaterial 完全指南点图元材质的属性配置、着色器原理与粒子实战【免费下载链接】three.jsJavaScript 3D Library.项目地址: https://gitcode.com/GitHub_Trending/th/three.jsPointsMaterial点材质是 three.js 中负责渲染「点图元」的专用材质它不参与光照计算而是把几何体的每个顶点渲染为一个屏幕空间中的方形点是搭建星空、粒子、点云、散点图等场景最常用的基础材质。本文以官方 PointsMaterial 文档 为主体结合 源码 与着色器实现逐属性拆解其行为并给出可直接运行的实战示例帮助读者理解参数背后的渲染机制并正确落地到自己的项目中。PointsMaterial 是什么从继承链看PointsMaterial的完整关系为EventDispatcher → Material → PointsMaterial。它用于渲染点图元point primitives必须与Points对象而不是Mesh配合使用Points决定把几何体的每个顶点画成一个点而PointsMaterial决定这个点长什么样。与 Points 对象 配套使用时材质不参与光照、不产生面片因此渲染开销极低适合一次性绘制成千上万个对象这正是粒子系统与点云可视化的基础。基础用法把 10000 个随机顶点画成一片星空官方文档给出的 Code Example 完整演示了生成随机顶点 → 写入 BufferGeometry → 绑定材质 → 加入场景的最小链路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: 0x888888 } ); const points new THREE.Points( geometry, material ); scene.add( points );拆解这段代码的要点THREE.MathUtils.randFloatSpread( 2000 )在[-1000, 1000]范围内均匀随机取值使粒子散布在 2000 单位的立方体空间内顶点坐标以x, y, z平铺写入普通数组再封装为分量数3的Float32BufferAttribute未显式设置size将使用默认值1像素配合默认开启的sizeAttenuation近处粒子大、远处粒子小该示例省略了 renderer/camera 初始化与渲染循环把它放进标准场景后还需添加PerspectiveCamera否则感受不到大小随深度衰减的效果。可运行进阶版官方示例只负责造材质为了让读者直接看到点的大小衰减与颜色效果可补充相机与动画帧循环// 承上geometry / material / points 均沿用上文 const scene new THREE.Scene(); const camera new THREE.PerspectiveCamera( 60, innerWidth / innerHeight, 1, 5000 ); camera.position.z 1500; const renderer new THREE.WebGLRenderer(); renderer.setSize( innerWidth, innerHeight ); document.body.appendChild( renderer.domElement ); scene.add( points ); function animate() { requestAnimationFrame( animate ); points.rotation.y 0.0005; // 缓慢旋转观察近大远小 renderer.render( scene, camera ); } animate();旋转点云时可以看到由于sizeAttenuation默认为true朝向相机旋转过来的粒子在透视投影下会明显变大这正是点材质区别于Sprite的关键行为之一Sprite 始终以屏幕大小固定显示。构造函数与参数注入机制new PointsMaterial( parameters : Object )传入一个包含一个或多个属性的对象用于定义材质外观。值得强调的是parameters中可以传入该材质任意可写属性包括从基类Material继承下来的属性如transparent、opacity、alphaTest、blending、depthTest、side等。构造器内部通过this.setValues( parameters )批量赋值这一点可以从 PointsMaterial.js 末尾的调用得到确认setValues是基类Material提供的方法。颜色的传值方式极为灵活只要是被 Color#set 接受的类型即可例如十六进制数0x888888、CSS 字符串steelblue、THREE.Color实例或{ r, g, b }对象。材质还重写了copy( source )见 PointsMaterial.js依次复制color、map、alphaMap、size、sizeAttenuation、fog方便通过.clone()快速派生同款新材质。属性逐项详解下面对照文档中列出的全部属性并结合源码默认值逐一说明。.color : Color材质颜色所有顶点统一着该颜色每个点也支持后续所述的逐点颜色通道。类型Color源码默认值new Color( 0xffffff )即白色见 PointsMaterial.js文档默认值表述为(1, 1, 1)。当同时设置了map时纹理颜色会与color相乘调制modulated因此白色不会改变纹理观感而将color调成暖色调可让同一张贴图渲染出不同色彩的点。.map : Texture颜色贴图可选的 alpha 通道需配合继承自基类的Material.transparent或Material.alphaTest一起使用才能生效。贴图颜色由上述color调制。两点使用注意map属于颜色数据必须显式设置颜色空间绝大多数场景应令texture.colorSpace SRGBColorSpace默认值为null。map最常见的用途是把一张圆形渐变贴图赋予点材质把默认的方形点抠成圆形光晕粒子见后文实战一节。.alphaMap : Texture灰度贴图用明暗控制点整体的透明度黑色完全透明白色完全不透明。它与map的 alpha 通道相互独立提供另一种透明度来源。值得注意的采样细节文档明确说明仅使用纹理的颜色信息若纹理本身带 alpha 通道也会被忽略对 RGB / RGBA 纹理渲染器采样时使用绿色通道因为在 DXT 压缩与未压缩的 RGB 565 格式中绿色通道具有额外精度位Luminance-only仅亮度与 luminance/alpha 纹理仍可正常工作alphaMap属于非颜色数据所赋纹理必须保持texture.colorSpace NoColorSpace即默认值默认值为null。这一采绿色通道的细节与着色器实现完全吻合片段着色器 chunk 中执行的是diffuseColor.a * texture2D( alphaMap, uv ).g绿色分量见 alphamap_fragment.glsl.js 与点的 map_particle_fragment.glsl.js。.size : number点的绘制尺寸单位是像素在未缩放情况下。注意文档提醒当取值超过硬件相关的上限如 WebGL 的gl.ALIASED_POINT_SIZE_RANGE时大小可能会被 GPU 钳制capped。也就是说size设得过大并不能无限放大点WebGL 实现规范中ALIASED_POINT_SIZE_RANGE决定了单点能支持的最大尺寸范围。源码默认值为1见 PointsMaterial.js。.sizeAttenuation : boolean指定点的大小是否随相机深度衰减——注意文档限定为仅对透视相机perspective camera有效true距离越远点显示得越小符合近大远小的透视规律适合表现三维空间中的粒子false所有点始终以固定屏幕像素尺寸绘制适合 HUD、UI 点缀或散点图等不希望随景深变化的场景默认值为true。.fog : boolean该材质是否受场景雾效fog影响true点会参与雾的渐变褪色融入远处的雾色中false点完全不受雾影响默认值为true。注意它同样是从材质层面控制的独立开关与场景是否添加Fog/FogExp2无关——即使添加了雾也只有在材质fog为true时才生效。.isPointsMaterial : boolean只读类型测试标志用于快速判断一个材质是否是PointsMaterial源码在构造器中直接置为true见 PointsMaterial.js。默认值为true。源码级原理点究竟是如何画出来的把官方文档未展开的底层机制补全是深入理解上述参数的关键。PointsMaterial 在 WebGL 后端使用的是独立的点着色器程序位于 points.glsl.js。顶点着色器gl_PointSize 的由来// src/renderers/shaders/ShaderLib/points.glsl.js (vertex) gl_PointSize size; #ifdef USE_SIZEATTENUATION bool isPerspective isPerspectiveMatrix( projectionMatrix ); if ( isPerspective ) gl_PointSize * ( scale / - mvPosition.z ); #endif首先把 uniformsize即材质的.size直接赋给gl_PointSize当启用sizeAttenuation编译期写入宏USE_SIZEATTENUATION时再根据投影矩阵判断是否为透视投影isPerspectiveMatrix仅对透视相机执行gl_PointSize * scale / -mvPosition.z-mvPosition.z是顶点在相机空间的深度深度越大、点越小scale由渲染器根据画布像素比等计算。这也从底层印证了文档仅透视相机生效的表述正交相机下不做衰减点固定保持屏幕像素尺寸。宏是如何注入的sizeAttenuation不是一个在着色器里读取的 uniform而是通过编译期宏定义进入程序的WebGLProgram.js 根据参数决定是否注入#define USE_SIZEATTENUATIONWebGLPrograms.js 把material.sizeAttenuation true收集为程序参数用于程序的缓存复用与 key 判定同参数材质会命中同一编译结果避免重复编译。片段着色器方形点如何变成贴图粒子片段阶段与纹理/透明度相关的核心 chunk 是 map_particle_fragment.glsl.js// 无显式 POINTS_UV 时用内建 gl_PointCoord 换算 UV vec2 uv ( uvTransform * vec3( gl_PointCoord.x, 1.0 - gl_PointCoord.y, 1 ) ).xy; #ifdef USE_MAP diffuseColor * texture2D( map, uv ); #endif #ifdef USE_ALPHAMAP diffuseColor.a * texture2D( alphaMap, uv ).g; // 再次印证 alphaMap 取绿色通道 #endif这里的gl_PointCoord是 WebGL 为每个点提供的、取值范围[0,1]的片元局部坐标——点其实是一个始终面向相机的方形片元map/alphaMap就是在这个方形内采样的。若不做任何贴图每个点就是一个纯色小方块而只要把圆形的map贴上去并打开transparent方形点就抠成了圆形点。整套流程还依次接入了雾、色调映射与色彩空间处理fog_fragment、tonemapping_fragment、colorspace_fragment等与.fog属性一一对应。单元测试印证仓库的单元测试 test/unit/src/materials/PointsMaterial.tests.js 验证了三点核心事实实例是Material的子类、可以被正常实例化、type PointsMaterial且isPointsMaterial为true。这为类型判断和继承关系提供了自动化依据。实战组合让点成为粒子精灵官方文档中map常与transparent/alphaTest搭配的提示在仓库示例 examples/webgl_points_sprites.html 中得到了完整示范见该文件第 98 行const material new THREE.PointsMaterial( { size: size, map: sprite, // 圆形/径向渐变贴图 blending: THREE.AdditiveBlending, // 加法混合粒子叠加更亮 depthTest: false, // 不参与深度测试透明粒子互相透亮 transparent: true // 必须开启alpha 才参与合成 } );几个组合要点map配上圆形径向渐变纹理后点从硬边方块变为柔边光斑alphaTest可进一步裁掉边缘残影AdditiveBlending适合火焰、星云等发光粒子多个粒子重叠处会增亮而普通 alpha 混合在大量粒子重叠时会出现排序瑕疵成千上万个粒子无需逐个创建Mesh一个Points 一份BufferGeometry即可承载这正是该材质的核心价值场景。逐点着色与更多示例入口点材质同样支持按顶点着色点着色器包含color_pars_vertex/color_vertex/color_fragment等 chunk可从几何体的 color 属性读取逐点颜色。仓库中 XYZLoader.js 的文档注释便给出了new THREE.PointsMaterial( { size: 0.1, vertexColors: vertexColors } )的传参写法适合点云按高程或类别着色。更多可直接运行的真实用例分布在 examples/webgl_points_billboards.html、examples/webgl_buffergeometry_points.html、examples/webgl_points_dynamic.html 与 examples/webgl_interactive_raycasting_points.html覆盖公告板贴图、动态粒子与鼠标拾取等常见诉求。常用参数速查表属性类型默认值作用要点.colorColor(1,1,1)白色点的基础颜色与map相乘调制.mapTexturenull颜色贴图属颜色数据需设SRGBColorSpacealpha 需配transparent/alphaTest.alphaMapTexturenull灰度透明度贴图非颜色数据保持NoColorSpace采样绿色通道黑透白不透.sizenumber1点的大小像素可能受ALIASED_POINT_SIZE_RANGE硬件上限钳制.sizeAttenuationbooleantrue是否随深度衰减仅对透视相机生效.fogbooleantrue是否受场景雾效影响.isPointsMaterialboolean(只读)true类型测试标志小结PointsMaterial虽然属性极少却牵动了点图元渲染的完整链路size与sizeAttenuation决定顶点着色器中gl_PointSize的计算map/alphaMap决定片段着色器在gl_PointCoord方形点内的采样与透明度合成fog决定后处理阶段的雾化参与而继承自Material的transparent、alphaTest、blending等则进一步控制点的混合行为。结合 官方文档、材质源码 与其着色器实现读者可以在粒子系统、点云可视化与交互拾取等场景中准确预测材质表现避免尺寸不变点不够圆远处看不见等典型坑点。【免费下载链接】three.jsJavaScript 3D Library.项目地址: https://gitcode.com/GitHub_Trending/th/three.js创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表