恒美微站 Logo 恒美微站
  • 首页
  • 关于我们
  • 建站服务
  • 主题模板
  • 案例展示
  • 资讯中心
  • 联系我们

three.js 纹理数据源详解:TextureSource(Source)类的设计动机、上传机制与序列化

  • 首页
  • 资讯中心
  • /
  • three.js 纹理数据源详解:TextureSource(Source)类的设计动机、上传机制与序列化

相关资讯

Remotion 视觉效果实战指南:掌握 `effects` 数组与 `createEffect()` 自定义特效开发 2026/9/8 22:57:51
RuView ADR-152 实战解析:WiFi 姿态估计 SOTA 情报入档——几何条件化校准、外部基准复现与基础编码器训练配方 2026/9/8 22:57:51
深度学习开源教材:4 本书、18 个动态演示的完整学习资源站 2026/9/8 22:57:51

最新资讯

Linux设备驱动开发入门:从内核模块到设备树的硬核学习路线
STM32F103C8T6入门到实战:性价比之王完整开发指南
数据结构C语言版速成:补考期末考研复试冲刺指南
ARM底层优化库optimized-routines源码审计与架构拆解
扫地机器人自动上下水版安装指南:从半自动到全自动的工程化升级
PHP转Java实战指南:从架构设计到性能调优的迁移方法论

今日推荐

基于MongoDB的图书管理系统:数据建模与Spring Boot+Vue实战
Claude Code安装配置全攻略:从零开始用上终端AI编程助手
tmux 会话管理与终端复用:AI 编程工作流的调度中枢实战

本周热门

超人会飞不算本事:系统稳定依赖清晰规则与边界设计
超人VS蜘蛛侠:拆解超级IP的影响力与传播方法论
基于CNN的调制信号识别:MATLAB实现时频图分类实战

本月精选

自研推理加速器Redwood:两周内实现PyTorch模型高效部署的实战教程
V4L2摄像头采集实战:从camera_client.rar到出图全流程解析
从“谁发明了钢琴键”到知识问答智能体:RAG与记忆工程实践

three.js 纹理数据源详解:TextureSource(Source)类的设计动机、上传机制与序列化

发布时间:2026/9/8 22:57:51
three.js 纹理数据源详解:TextureSource(Source)类的设计动机、上传机制与序列化 three.js 纹理数据源详解TextureSourceSource类的设计动机、上传机制与序列化【免费下载链接】three.jsJavaScript 3D Library.项目地址: https://gitcode.com/GitHub_Trending/th/three.js本文基于 three.js 仓库中的 Source API 文档 及其源码实现系统讲解纹理数据源类自 r186 起更名为TextureSource的核心设计它如何将纹理数据定义与纹理定义解耦data、dataReady、needsUpdate、version各属性如何驱动 WebGL 纹理上传流程以及getSize与toJSON两种方法的具体行为。读完本文你将能够独立使用TextureSource让多个Texture实例共享同一份图像数据并理解Texture#needsUpdate触发 GPU 上传的完整调用链。1. 什么是纹理数据源数据与纹理解耦Source现名TextureSource表示一张纹理的数据源data source。其核心目的用 API 文档 的原话说The main purpose of this class is to decouple the data definition from the texture definition so the same data can be used with multiple texture instances.即把数据定义与纹理定义解耦使同一份数据可以被多个纹理实例复用。这在实践中非常常见同一张法线图可能被两个材质以不同wrapS、repeat、magFilter使用若各自持有独立数据副本不仅浪费内存数据更新时还需同步多次。通过共享一个TextureSourceGPU 端只需维护一份纹理对象多个Texture实例只是挂在同一数据源上的不同视图配置。从源码结构看Texture与TextureSource的关系在 src/textures/Texture.js 中直接体现this.source new TextureSource( image );new Texture( image )时构造函数会把传入的图像封装成一个TextureSource作为texture.source。Texture的image属性实际上是一个代理属性读写都转发到 source// src/textures/Texture.js get image() { return this.source.data; } set image( value ) { this.source.data value; }因此texture.image newImage与texture.source.data newImage等价而texture.image只是读取source.data。2. 命名沿革Source 更名为 TextureSource当前版本中实际使用的类是TextureSource。原Source类自 r186 起被标记为弃用deprecated保留为TextureSource的子类用于向后兼容。在 src/textures/TextureSource.js 中可以看到这一设计/** * deprecated since r186. Use {link TextureSource} instead. Source has been renamed to TextureSource. */ class Source extends TextureSource { constructor( data null ) { warnOnce( Source: Source has been renamed to TextureSource. Please update your code to use THREE.TextureSource instead. ); // deprecated, r186 super( data ); this.isSource true; } }两点迁移要点新代码应使用TextureSource使用Source会触发一次warnOnce控制台警告仅首次实例上仍保留isSource标志供旧代码做类型测试类型测试标志从isSource更名为isTextureSource新代码应检查source.isTextureSource true。3. 构造函数new TextureSource( data : any )构造一个新的纹理数据源。参数data纹理的数据定义可以是HTMLImageElement、HTMLCanvasElement、HTMLVideoElement、ImageBitmap、VideoFrame、带width/height的普通对象或立方体贴图所需的图像数组。默认为null。构造函数实现位于 src/textures/TextureSource.js逐字段初始化如下与 API 文档的属性清单一一对应constructor( data null ) { // 类型测试标志 this.isTextureSource true; // 自增 ID模块级计数器 _sourceId Object.defineProperty( this, id, { value: _sourceId } ); // 全局唯一 UUID this.uuid generateUUID(); // 纹理数据定义 this.data data; // 数据是否已就绪默认 true this.dataReady true; // 版本号默认 0 this.version 0; }注意id是通过Object.defineProperty以只读方式挂载的模块级自增计数_sourceId从 0 开始主要用于内部对象属性映射与调试标识。4. 属性详解.data : any纹理的数据定义。渲染器最终上传到 GPU 的内容就是source.data。在 src/renderers/webgl/WebGLTextures.js 的uploadTexture流程中上传前会先对texture.image即source.data执行resizeImage与verifyColorSpace预处理。.dataReady : boolean默认true。该属性仅在needsUpdate被设为true时才有意义用于精细控制纹理数据的处理方式当dataReady为false时引擎执行内存分配如必要但不把数据实际传输到 GPU 内存。源码级证据在 src/renderers/webgl/WebGLTextures.jsconst allocateMemory ( sourceProperties.__version undefined ) || ( forceUpload true ); const dataReady source.dataReady;随后在各级 mipmap 上传分支中例如 src/renderers/webgl/WebGLTextures.jsif ( useTexStorage ) { if ( dataReady ) { state.texSubImage2D( _gl.TEXTURE_2D, i, 0, 0, mipmap.width, mipmap.height, glFormat, glType, mipmap.data ); } } else { state.texImage2D( _gl.TEXTURE_2D, i, glInternalFormat, mipmap.width, mipmap.height, 0, glFormat, glType, mipmap.data ); }典型场景是流式纹理或渐进加载先置dataReady false让引擎按数据尺寸分配 GPU 显存texStorage2D待真实像素数据如网络加载的 mipmap 层就位后再置回true并触发上传避免渲染出空白纹理。.id : number (readonly)数据源 ID模块级自增计数器只读。.isSource : boolean (readonly)/.isTextureSource : boolean (readonly)类型测试标志均为true。当前版本的主标志是isTextureSourceisSource仅由弃用的Source子类设置见第 2 节。.needsUpdate : boolean这是一个只写 settersrc/textures/TextureSource.jsset needsUpdate( value ) { if ( value true ) this.version ; }设为true时引擎为纹理分配内存如必要并在该 source 下次被使用时触发实际的 GPU 上传设为false不会递减version。它本身不存储布尔值而是通过递增version传递需要更新的信号。.uuid : string (readonly)数据源的 UUID由generateUUID()生成。序列化第 7 节与ObjectLoader反序列化都以此为图像缓存的键。.version : number (readonly)从0开始记录needsUpdate被设为true的次数。渲染器正是靠比较version与上次记录的版本来决定是否重新上传见 src/renderers/webgl/WebGLTextures.jsif ( source.version ! sourceProperties.__version || forceUpload true ) { // 执行纹理上传流程 }上传完成后src/renderers/webgl/WebGLTextures.jssourceProperties.__version source.version;由此形成设置 → 检测差异 → 上传 → 记录版本的幂等更新闭环。5. 与 Texture 的联动Texture#needsUpdate的传播Texture自己也有一个needsUpdatesettersrc/textures/Texture.jsset needsUpdate( value ) { if ( value true ) { this.version ; this.source.needsUpdate true; } }即texture.needsUpdate true同时做两件事递增texture.version并级联触发source.needsUpdate true进而递增source.version。由于多个Texture可以共享同一个source任一纹理声明更新所有共享该数据源的纹理在下一帧渲染时都会看到更新后的 GPU 内容——这正是数据解耦带来的复用收益。Texture的width/height/depth访问器同样直接委托给source.getSizesrc/textures/Texture.js。6. 方法getSize( target ).getSize( target : Vector2 | Vector3 ) : Vector2 | Vector3将数据源尺寸写入并返回给定的目标向量。实现位于 src/textures/TextureSource.js按数据类型分支getSize( target ) { const data this.data; if ( ( typeof HTMLVideoElement ! undefined ) ( data instanceof HTMLVideoElement ) ) { target.set( data.videoWidth, data.videoHeight, 0 ); } else if ( ( typeof VideoFrame ! undefined ) ( data instanceof VideoFrame ) ) { target.set( data.displayWidth, data.displayHeight, 0 ); } else if ( data ! null ) { target.set( data.width, data.height, data.depth || 0 ); } else { target.set( 0, 0, 0 ); } return target; }要点视频帧源HTMLVideoElement/VideoFrame使用videoWidth/videoHeight或displayWidth/displayHeight深度恒为 0普通数据源直接读取width/height/depth无depth时取 0data为null时返回(0, 0, 0)结果写入调用方提供的target复用向量避免频繁分配并返回同一对象支持链式调用。7. 方法toJSON( meta )序列化.toJSON( meta : Object | string ) : Object将数据源序列化为 JSON。meta是可选的序列化元信息对象由Object3D.toJSON在序列化场景时传递当meta为undefined或字符串时视为序列化根对象root object。实现位于 src/textures/TextureSource.js行为可归纳为三步去重非根对象时若meta.images[ this.uuid ]已存在则直接返回缓存项——同一TextureSource被多个纹理引用时images表中只会出现一份记录输出结构{ uuid, url }其中url由serializeImage填充data为数组立方体贴图时url是逐项序列化后的数组否则url为单个序列化结果data为null时url保持空字符串缓存登记非根对象时把输出登记进meta.images[ this.uuid ]供后续纹理的toJSON引用Texture#toJSON输出中即包含image: this.source.toJSON( meta ).uuid见 src/textures/Texture.js。serializeImage函数src/textures/TextureSource.js区分三类输入数据形式序列化结果HTMLImageElement/HTMLCanvasElement/ImageBitmapImageUtils.getDataURL( image )即 data URL 字符串DataTexture的图像对象带.data{ data: Array.from( image.data ), width, height, type: image.data.constructor.name }其他不可识别数据输出警告Texture: Unable to serialize Texture.并返回空对象{}反序列化端在 src/loaders/ObjectLoader.js 中消费这些记录立方体贴图分支执行images[ image.uuid ] new TextureSource( imageArray )普通图像分支执行images[ image.uuid ] new TextureSource( deserializedImage )纹理对象随后通过 uuid 找回对应 source。API 文档中toJSON的 See: ObjectLoader#parse 即指这一对序列化/反序列化闭环。8. 实战示例多纹理共享同一数据源import * as THREE from three; const loader new THREE.TextureLoader(); loader.load( textures/brick-wall.jpg, ( image ) { // 手动构造数据源供多个纹理共享 const source new THREE.TextureSource( image ); const diffuseMap new THREE.Texture( source ); diffuseMap.colorSpace THREE.SRGBColorSpace; diffuseMap.wrapS diffuseMap.wrapT THREE.RepeatWrapping; diffuseMap.repeat.set( 4, 2 ); // 同一份 GPU 数据不同采样参数 const normalMap new THREE.Texture( source ); normalMap.wrapS normalMap.wrapT THREE.RepeatWrapping; normalMap.repeat.set( 4, 2 ); normalMap.magFilter THREE.NearestFilter; material.map diffuseMap; material.normalMap normalMap; // 数据更新后只需触发一次共享 source 的所有纹理同步生效 // Texture#needsUpdate 会级联到 source.needsUpdate diffuseMap.needsUpdate true; } );注意两个 API 细节new THREE.Texture( source )传入的 source 若是已有实例Texture构造函数会直接复用this.source source.source见 src/textures/Texture.js 附近逻辑不会二次封装使用旧类名new THREE.Source( image )虽仍可用但会打印一次弃用警告新代码请一律使用TextureSource。9. 关键文件索引内容路径TextureSource/ 弃用Source实现src/textures/TextureSource.jsTexture与 source 的绑定、needsUpdate传播src/textures/Texture.jsGPU 上传主流程version对比、dataReady控制src/renderers/webgl/WebGLTextures.js反序列化重建TextureSourcesrc/loaders/ObjectLoader.js原始 API 文档docs/pages/Source.html.md10. 小结TextureSource是纹理数据与纹理定义的解耦层一个 source 可被多个Texture共享GPU 只上传一次needsUpdate不存值只通过递增version向渲染器发信号渲染器以source.version ! sourceProperties.__version判断是否需要重新上传dataReady false允许只分配显存、不传数据是流式/渐进纹理加载的关键开关toJSON/ObjectLoader以uuid为键完成 source 的去重序列化与重建保证场景序列化时共享关系不丢失r186 起请使用TextureSource与isTextureSource旧名Source/isSource仅为兼容保留。【免费下载链接】three.jsJavaScript 3D Library.项目地址: https://gitcode.com/GitHub_Trending/th/three.js创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

关于恒美微站

恒美微站专注于为个体商户、工作室提供极简自助建站服务,让每个人都能轻松拥有专业网站。

快速链接

  • 关于我们
  • 建站服务
  • 主题模板
  • 案例展示
  • 资讯中心

服务项目

  • 可视化建站
  • 拖拽编辑
  • 主题定制
  • SEO 优化
  • 网站托管

联系方式

  • 📍 地址:北京市朝阳区建国路 88 号
  • 📞 电话:400-888-8888
  • ✉️ 邮箱:info@hmyw.cn
  • 🕐 时间:周一至周日 9:00-18:00

© 2024 恒美微站 hmyw.cn 版权所有 | 京 ICP 备 12345678 号