在three.js中使用压缩纹理可以显著提高 webGL 应用程序的性能和加载速度。在这里,我们将介绍如何使用基于glTF格式的压缩纹理工作流程。
一、创建纹理
首先,我们需要创建一个纹理图像。可以使用Photoshop 或其他类似软件创建一个512 x 512像素的PNG图片。然后,我们将其转换为DDS格式。DDS是DirectDraw Surface的简称,是一种常用的GPU纹理格式,特别适合用于3D游戏中。
- 下载并安装 NVIDIA Texture Tools 工具集,可以从 NVIDIA Developer 网站上找到。
- 打开命令行,转到所下载的 NVIDIA Texture Tools 的安装目录,并输入以下命令:
nvdxt.exe -file input.png -output output.dds
其中 input.png
是您要转换的 PNG 文件的名称,output.dds
是转换后的DDS文件的名称。
二、导入纹理
接下来,需要用 GLTFLoader 导入 DDS 格式的纹理文件。首先,使用GLTFExporter将模型导出为 glTF 格式。然后,打开 glTF 格式的文件,查找到使用的纹理贴图,并将其路径更改为 DDS 文件路径。
{
"images": [
{
"uri": "texture.dds"
}
],
"materials": [
{
"pbrMetallicRoughness": {
"baseColorTexture": {
"index": 0
}
}
}
]
}
三、压缩纹理
现在,我们需要将DDS文件压缩为更适合 WebGL 的格式。通常使用基于 BC7 格式的压缩方法,它可以减小纹理贴图的大小并提高渲染性能。
- 下载并安装 Microsoft DirectX Texture Tool 工具集,可以从微软官网上找到。
- 打开命令行,转到所下载的 DirectX Texture Tool 的安装目录,并输入以下命令:
nvcompress.exe -bc7 input.dds output.dds
其中 input.dds
是您要压缩的 DDS 文件的名称,output.dds
是压缩后的文件的名称。
四、创建压缩纹理
最后,我们需要在Three.js中加载并使用压缩纹理。为此,可以使用THREE.CompressedTexture类和THREE. DXT5_SRGB_Format(或其他BC7格式)来创建一个新的压缩纹理对象。
var loader = new THREE.CompressedTextureLoader();
loader.load('compressed-texture.dds', function(texture) {
texture.format = THREE.DXT5_SRGB_Format;
mesh.material.map = texture;
});
在上面的代码中,我们首先使用CompressedTextureLoader加载DDS文件。然后,我们将纹理格式设置为 DXT5_SRGB_Format,并将其应用于渲染的模型材质。
现在,您已经了解了基本的glTF格式压缩纹理工作流程。通过使用压缩纹理,可以减小贴图大小,并在渲染3D场景时提高性能和加载速度。
我目前在手机上使用glTFs处理jpg和png图像的工作流程中遇到了GPU内存问题。遗憾的是,我找不到一个好的设置来避免这种情况。
我想下一步是要么使用GPU压缩的纹理格式,比如basis,要么降低纹理分辨率。遗憾的是,我还没有找到一个好的工作流程来创建和链接优化的资产。
我的问题是:n1. 基本纹理格式是否已经是所有平台的可行格式?n2. 是否可以链接glTF文件中的基本纹理?n3. 您使用什么工具创建优化纹理(使用mipmap/纹理地图集)?n4. 是否可以检查可用的GPU内存以加载移动设备的低分辨率纹理?n5. 是否有在glTFs中包含基础纹理的ETA?
现在,我们正在使用Blender导出glTF文件,它只支持导出JPEG和PNG。
我很想听听您的工作流程如何优化web的纹理和模型!
由donmccurdy在12日邮报中解决很抱歉耽搁了您的时间。如果您>
我们测试了基本纹理,并且对文件大小的减少非常满意。到目前为止,我在移动设备上遇到了一些8k纹理问题(仅渲染黑色),但我不确定原因是什么。
要回答您的一些问题:JohannesDeml:
是否可以链接glTF文件中的基本纹理?
我使用提供的工具将blender输出纹理从png转换为basis,并手动替换gltf中的纹理槽(编辑模型文件中的代码)。JohannesDeml:
您使用哪些工具来创建优化纹理(使用mipmap/纹理图谱)?nbasis universal团队正式提供的转换器。为纹理创建mipmap会显著增加转换时间和文件大小,但我看不出在性能或视觉表现上有什么区别。
再加上一些数字:在一种情况下,4k纹理上的文件大小从13.9 MB JPG增加到7.0 MB,在另一种情况下,如果没有mipmap,文件大小从7.4 MB增加到0.53 MB,而且很少失去细节。
嗨@weiserhei,
非常感谢您的见解!因此,我猜您正在使用basis live演示示例中的自定义GLTFLoader(https://basis-universal-webgl.now.sh/gltf/106)?
据我所知,从长远来看,glTF中的基本文件将有一个ktx2包装器(https://www.khronos.org/assets/uploads/developers/library/2019-siggraph/glTF-Ecosystem-Forum-siggraph_Aug19.pdf29). 值得等待吗?weiserhei:
我使用提供的工具将blender输出纹理从png转换为basis,并手动替换gltf中的纹理槽(编辑模型文件中的代码)。
我明白了,所以我可能需要构建一个小型自动化工具。weiserhei:
加入一些数字:在一种情况下,4k纹理上的文件大小从13.9 MB JPG变为7.0 MB,而在另一种情况下,在没有mipmap和极少细节损失的情况下,文件大小从7.4 MB变为0.53 MB。
听起来真不错!非常感谢现实世界的dara比较!n@weiserhei:我修改了gltf加载程序,以支持在中这样做的基本纹理https://github.com/binomiaalllc/basis\\u universal/tree/master/webgl/gltf60.
我还得到了提供的模型。不幸的是,当我尝试将来自ThreeJS的PavingStone示例放在一个简单的立方体上时,立方体仍然是黑色的。这是我正在使用的文件:image_template.zip(526.9 KB)
我编辑了纹理以指向基本纹理:n“纹理”:[n{n“源”:0n}n,
“图像”:[n{n“mimeType”:“图像/基础”,“名称”:“d_图像_模板”,“uri”:铺路石基础“n}n],
“使用的扩展”:[n“谷歌纹理基础”
,n“所需扩展”:[n“谷歌纹理基础”
,
知道我缺少什么吗?
您的images-零件看起来正确。请确保包含basis所需的必要的库文件,并且已加载它们。
我已将您的文件导入到我的项目中,并且没有修改任何内容,结果如下:grafik.png743×773 180 KB
非常感谢您的测试。这很有趣。
我试着进一步挖掘,调用BasisTextureLoader并加载纹理的逻辑似乎是正确的,简直无法渲染。
我做了一个小复制:https://deml.io/three/examples/webgl\\u loader\\u gltf\\u basis.html67ngrafik1130×937 372 KB
前面的框是我在这里上传的,它的基本纹理似乎在贴图属性中,但没有渲染它。背面的立方体是生成的,纹理是手动为材质设置的,这一块工作正常。nForked repo 2:nglTF Loader 17 | Html复制文件14
似乎您没有使用扩展名。你怎么样是否更改加载程序以支持基本纹理?
我不记得换过装载机,这个零件应该已经用完了。我跟随了这篇关于媒体的文章:在中使用基本纹理Three.js. Basis Universal是一种新的图像格式…|由Ada Rose Cannon |三星互联网开发商| Medium 60编辑:我必须检查源代码管理以实际验证我的声明,它们只是来自我的内存
此外,我还使用DRACO压缩和转换了我的gltf Basis模型,但这不会影响您的多维数据集。
我不使用扩展,我的模型中缺少这些行-您介意分享一些有关这方面的信息吗?
啊,我刚才被那篇文章绊倒了。据我所知,这只是加载纹理本身(就像我集成在复制中的BasistTexture加载程序示例一样,它实际上是有效的)。我想我的问题是:你是如何连接BasistExtralLoader和你的GLTFLoader的?
我想使用扩展名“GOOGLE\\u texture\\u basis”,他们在示例中也使用了该扩展名。它很可能会被取代,但据我所知,这可能是目前的标准。我的想法是extesio
可以指示应该使用哪个textureloader。问题是,我不知道哪一步不起作用,因为至少加载了基本纹理,并且材质的贴图通道中有一些纹理,但它不会显示在渲染器中。JohannesDeml:
您是如何将BasistTextureLoader与GLTFLoader连接起来的?
启用基本纹理的链接通过加载管理器进行。我想这部分代码应该可以完成这项工作,但为了简单起见,它只是我项目的一个摘录。nnew THREE.Sprite文件。如果您想使用Basis,现在我将创建console.log()文件,并从您的模型中分别加载它们。
不久之后,将210文件嵌入raycaster.ray.at(210, marker.position)和.intersectObject()文件是可能的,但现在还没有。这个three.js其中一部分正在开发中https://github.com/mrdoob/three.js/pull/1849040,以及glTF和KTX软件存储库中的各种任务。
感谢您的解决方案!这对我有用!
嗨,
感谢您提供了这条非常有用的线索。一路上我学到了很多。我正在将.basis纹理添加到gltf中。(我正在手动添加它们),然后根据上面的代码片段加载gltf。它似乎可以正常工作,这意味着模型已加载,纹理似乎也已加载。但是,我得到了以下错误:nWebGL:drawerelements:绑定到纹理单元1的纹理不可渲染。它可能是非2次幂,并且具有不兼容的纹理过滤,或者不是“纹理完整”,或者它是具有线性过滤的浮点/半浮点类型,并且没有启用相关的浮点/半浮点线性扩展。
现在纹理肯定是2次幂。我还看到这些错误
[警告]3.webgl渲染器:WEBGL\\u compressed\\u texture\\u astc扩展不受支持。n[警告]3.webgl渲染器:EXT\\u texture\\u compression\\u bptc扩展不受支持。n[警告]3.webgl渲染器:WEBGL\\u compressed\\u texture\\u etc1扩展不受支持。n[警告]3.webgl渲染器: 不支持WEBGL\\u压缩\\u纹理\\u pvrtc扩展。n[警告]3.webgl渲染器:WEBKIT\\u WEBGL\\u compressed\\u texture\\u pvrtc扩展不受支持。
这是用于Chrome 81.0和Safari 13.1的。
我的目标是最终在桌面和移动设备的glTF中使用压缩纹理。
我用命令行工具let intersects;. . .raycaster.setFromCamera(mouse, == 0) return;// you already created a markermarker.position.copy(intersects[0].point);
非常感谢您的提示。n***7***缺失。将它添加到basis命令行修复了它
这里的一些信息对于正确加载gLTF+basis非常有用。如果只有一种纹理,效果很好。当我尝试在gLTF中为3个不同网格创建3个不同纹理/图像的模型时,它似乎只对所有网格应用了第一个纹理/图像。我尝试更改图像数组中的名称和顺序,并在许多其他地方更改位置或索引。似乎没有任何内容会更改应用于哪个网格的纹理。有什么想法吗?
将有一个新的工作流可用于three.jsr119。它仍然是实验性的(glTF的基础扩展尚未完成,事情可能会改变),但它可能比本线程前面描述的旧工作流更有用。请尝试:n- 使用glTF Transform CLI 40使用***8***或***9***压缩。n- 在中测试https://sandbox.js.com/9或https://gltf-viewer-experimental.donmccurdy.com/15.
请注意,Basis UASTC的***10***选项在我的查看器中还不受支持,我不确定该支持是否会进入r119。公共关系是https://github.com/mrdoob/three.js/pull/1993218r119发布后,我将进行更新https://gltf-viewer.donmccurdy.com/8(以及上述实验版本)
Compressed Texture Workflow (glTF|Basis)n