Performance 具有多种纹理的three.js网格

Performance 具有多种纹理的three.js网格,performance,3d,three.js,textures,Performance,3d,Three.js,Textures,我目前正在尝试创建一个three.js网格,它有大量的面(数千个),并且正在使用纹理。但是,我的问题是,每个面都可以在运行时更改其纹理,因此每个面都可能具有不同的纹理 我尝试使用默认纹理预加载材质数组(对于MeshFaceMaterial),并为每个面指定不同的materialIndex,但这产生了很大的延迟 一点研究结果表明 如果数量大(例如每个人脸可能有不同的地方),考虑不同的解决方案,使用属性/纹理来驱动不同的每个脸部外观。 我对着色器的工作原理有点困惑,尤其是我甚至不确定如何将纹理与属性

我目前正在尝试创建一个three.js网格,它有大量的面(数千个),并且正在使用纹理。但是,我的问题是,每个面都可以在运行时更改其纹理,因此每个面都可能具有不同的纹理

我尝试使用默认纹理预加载材质数组(对于MeshFaceMaterial),并为每个面指定不同的materialIndex,但这产生了很大的延迟

一点研究结果表明

如果数量大(例如每个人脸可能有不同的地方),考虑不同的解决方案,使用属性/纹理来驱动不同的每个脸部外观。 我对着色器的工作原理有点困惑,尤其是我甚至不确定如何将纹理与属性结合使用。我在网上找不到任何这样的例子,因为我找到的大多数与纹理着色器相关的例子都使用了制服


所以我的问题是:有没有一种有效的方法来创建具有大量纹理的网格,并且在运行时可以更改?如果没有,是否有上述属性/纹理想法的示例?

事实上,这可能是一件很难实现的事情。现在我不能对GLSL说太多(我正在学习),但我知道制服是常量,在调用之间不会改变,所以您可能需要为您的案例添加属性,但我欢迎在这里出错。不过,我有一个简单得多的建议

你可以使用一个纹理,你可以“细分”成你需要的每个面的所有微小纹理。然后在运行时,可以从纹理中提取UV坐标,并将其分别应用于面。您仍然需要处理计算时间,但对于一千多张脸来说,这应该是可行的。我用一个25k的人脸模型进行了测试,它可以快速地改变每个刻度的所有人脸

现在的诀窍是导航faceVertexUvs三维阵列。但是,例如,一个有12个面的纹理立方体,您可以说将所有面重置为相等的一面,如下所示:

for (var uvCnt = 0; uvCnt < mesh.geometry.faceVertexUvs[0].length; uvCnt+=2 ) {
    mesh.geometry.faceVertexUvs[0][uvCnt][0] = mesh.geometry.faceVertexUvs[0][2][0];
    mesh.geometry.faceVertexUvs[0][uvCnt][1] = mesh.geometry.faceVertexUvs[0][2][1];
    mesh.geometry.faceVertexUvs[0][uvCnt][2] = mesh.geometry.faceVertexUvs[0][2][2];

    mesh.geometry.faceVertexUvs[0][uvCnt+1][0] = mesh.geometry.faceVertexUvs[0][3][0];
    mesh.geometry.faceVertexUvs[0][uvCnt+1][1] = mesh.geometry.faceVertexUvs[0][3][1];
    mesh.geometry.faceVertexUvs[0][uvCnt+1][2] = mesh.geometry.faceVertexUvs[0][3][2];
}
(var uvCnt=0;uvCnt{ mesh.geometry.faceVertexUvs[0][uvCnt][0]=mesh.geometry.faceVertexUvs[0][2][0]; mesh.geometry.faceVertexUvs[0][uvCnt][1]=mesh.geometry.faceVertexUvs[0][2][1]; mesh.geometry.faceVertexUvs[0][uvCnt][2]=mesh.geometry.faceVertexUvs[0][2][2]; mesh.geometry.faceVertexUvs[0][uvCnt+1][0]=mesh.geometry.faceVertexUvs[0][3][0]; mesh.geometry.faceVertexUvs[0][uvCnt+1][1]=mesh.geometry.faceVertexUvs[0][3][1]; mesh.geometry.faceVertexUvs[0][uvCnt+1][2]=mesh.geometry.faceVertexUvs[0][3][2]; }
在这里,我有一个立方体,有6种颜色(每边1种),我在每个面顶点上循环(两个三角形组成一个平面时步进2个),然后将所有UV重置为我的第二个面,即蓝色。当然,您会希望将坐标映射到一个排序对象中,这样您就可以轻松地查询该对象以返回和重置坐标,但我不知道您的用例。为了实现完整性,您需要运行
mesh.geometry.uvsNeedUpdate=true在运行时查看更新。我希望这会有所帮助。

事实上,这可能是一件很难实现的事情。现在我不能对GLSL说太多(我正在学习),但我知道制服是常量,在调用之间不会改变,所以您可能需要为您的案例添加属性,但我欢迎在这里出错。不过,我有一个简单得多的建议

你可以使用一个纹理,你可以“细分”成你需要的每个面的所有微小纹理。然后在运行时,可以从纹理中提取UV坐标,并将其分别应用于面。您仍然需要处理计算时间,但对于一千多张脸来说,这应该是可行的。我用一个25k的人脸模型进行了测试,它可以快速地改变每个刻度的所有人脸

现在的诀窍是导航faceVertexUvs三维阵列。但是,例如,一个有12个面的纹理立方体,您可以说将所有面重置为相等的一面,如下所示:

for (var uvCnt = 0; uvCnt < mesh.geometry.faceVertexUvs[0].length; uvCnt+=2 ) {
    mesh.geometry.faceVertexUvs[0][uvCnt][0] = mesh.geometry.faceVertexUvs[0][2][0];
    mesh.geometry.faceVertexUvs[0][uvCnt][1] = mesh.geometry.faceVertexUvs[0][2][1];
    mesh.geometry.faceVertexUvs[0][uvCnt][2] = mesh.geometry.faceVertexUvs[0][2][2];

    mesh.geometry.faceVertexUvs[0][uvCnt+1][0] = mesh.geometry.faceVertexUvs[0][3][0];
    mesh.geometry.faceVertexUvs[0][uvCnt+1][1] = mesh.geometry.faceVertexUvs[0][3][1];
    mesh.geometry.faceVertexUvs[0][uvCnt+1][2] = mesh.geometry.faceVertexUvs[0][3][2];
}
(var uvCnt=0;uvCnt{ mesh.geometry.faceVertexUvs[0][uvCnt][0]=mesh.geometry.faceVertexUvs[0][2][0]; mesh.geometry.faceVertexUvs[0][uvCnt][1]=mesh.geometry.faceVertexUvs[0][2][1]; mesh.geometry.faceVertexUvs[0][uvCnt][2]=mesh.geometry.faceVertexUvs[0][2][2]; mesh.geometry.faceVertexUvs[0][uvCnt+1][0]=mesh.geometry.faceVertexUvs[0][3][0]; mesh.geometry.faceVertexUvs[0][uvCnt+1][1]=mesh.geometry.faceVertexUvs[0][3][1]; mesh.geometry.faceVertexUvs[0][uvCnt+1][2]=mesh.geometry.faceVertexUvs[0][3][2]; }

在这里,我有一个立方体,有6种颜色(每边1种),我在每个面顶点上循环(两个三角形组成一个平面时步进2个),然后将所有UV重置为我的第二个面,即蓝色。当然,您会希望将坐标映射到一个排序对象中,这样您就可以轻松地查询该对象以返回和重置坐标,但我不知道您的用例。为了实现完整性,您需要运行
mesh.geometry.uvsNeedUpdate=true在运行时查看更新。我希望这会有所帮助。

使用单一纹理和更改uv坐标似乎是一个更容易的解决方案,效果非常好。谢谢很高兴能为您提供帮助,将来如果我知道了一种使用着色器的方法,我也会添加它。使用单个纹理和更改uv坐标似乎是一种更简单的解决方案,效果非常好。谢谢很高兴能帮上忙,将来如果我学会了一种使用着色器的方法,我也会加上它。