three.js - 以编程方式为模型生成简单的UV贴图

标签 three.js uv-mapping

来自this问题,我正在尝试使用Three.js通过编程方式为某些模型生成UV贴图,我需要这样做是因为我的模型也是通过编程方式生成的,因此我需要对其应用简单的纹理。我已阅读here并成功为一些简单的3D文本生成了UV贴图,但是当将相同的贴图应用于更复杂的模型时,它根本无法正常工作。

我尝试应用的纹理是这样的:

enter image description here

黑色背景在PNG图片中只是透明的。我需要将其应用到我的模型中,这只是一个闪光效果,所以我不在乎模型中的确切位置,有什么方法可以针对这种情况以编程方式创建一个简单的UV贴图吗?

我正在使用链接问题中的以下代码,该代码对平面模型非常有效,但不适用于非平面模型:

assignUVs = function( geometry ){

    geometry.computeBoundingBox();

    var max     = geometry.boundingBox.max;
    var min     = geometry.boundingBox.min;

    var offset  = new THREE.Vector2(0 - min.x, 0 - min.y);
    var range   = new THREE.Vector2(max.x - min.x, max.y - min.y);

    geometry.faceVertexUvs[0] = [];
    var faces = geometry.faces;

    for (i = 0; i < geometry.faces.length ; i++) {

      var v1 = geometry.vertices[faces[i].a];
      var v2 = geometry.vertices[faces[i].b];
      var v3 = geometry.vertices[faces[i].c];

      geometry.faceVertexUvs[0].push([
        new THREE.Vector2( ( v1.x + offset.x ) / range.x , ( v1.y + offset.y ) / range.y ),
        new THREE.Vector2( ( v2.x + offset.x ) / range.x , ( v2.y + offset.y ) / range.y ),
        new THREE.Vector2( ( v3.x + offset.x ) / range.x , ( v3.y + offset.y ) / range.y )
      ]);

    }

    geometry.uvsNeedUpdate = true;
}

最佳答案

你需要更具体。在这里,我将以编程方式应用UV贴图

for (i = 0; i < geometry.faces.length ; i++) {
   geometry.faceVertexUvs[0].push([
     new THREE.Vector2( 0, 0 ),
     new THREE.Vector2( 0, 0 ),
     new THREE.Vector2( 0, 0 ),
   ]);
}

快乐的?

有无数种应用UV坐标的方法。这个怎么样
for (i = 0; i < geometry.faces.length ; i++) {
   geometry.faceVertexUvs[0].push([
     new THREE.Vector2( Math.random(), Math.random() ),
     new THREE.Vector2( Math.random(), Math.random() ),
     new THREE.Vector2( Math.random(), Math.random() ),
   ]);
}

没有正确的答案。您想做什么就取决于您。这有点像问我如何在纸上涂铅笔。

抱歉,如此狡猾,仅指出问题在某种意义上是荒谬的。

无论如何,有几种常见的应用纹理的方法。
  • 球形映射

    想象一下,您的模型是半透明的,里面有一个用薄膜制成的球体,并且该球体内部是一个点光源,因此它从球体的各个方向转换(就像电影放映机一样)。因此,您可以进行数学运算以针对该情况计算正确的UV

    要在球上获得一个点,请将您的点乘以该球的世界矩阵的倒数,然后对结果进行归一化。在那之后,尽管仍然存在纹理本身如何映射到虚球的问题,但对于虚球还是有无数种方法。

    我猜最简单的方法叫做mercator projection,它是世界上大多数2d map 的工作方式。他们有一个问题,就是北极和南极都浪费了很多空间。假设x,y,z是上一段中提到的归一化坐标,则
    U = Math.atan2(z, x) / Math.PI * 0.5 - 0.5;
    V = 0.5 - Math.asin(y) / Math.PI;
    
  • 投影映射

    这就像一部电影。您正在从一个点投影2d图像。假设您将电影放映机(或投影电视)对准椅子。计算这些点

    计算这些点就像几乎所有WebGL应用程序都从3D数据计算2D图像一样。通常他们在顶点着色器中有一条线,像这样
    gl_Position = matrix * position;
    

    其中matrix = worldViewProjection。然后你可以做
    clipSpace = gl_Position.xy / gl_Position.w
    

    您现在具有从-1到+1的x,y值。然后,您将它们转换
    UV坐标为0到1
    uv = clipSpace * 0.5 + 0.5;
    

    当然,通常您会在JavaScript初始化时计算UV坐标,但是概念是相同的。
  • 平面贴图

    这与投影贴图几乎相同,只是可以想象投影仪不是您要投影的点,而是要投影的大小相同。换句话说,当您将模型移近投影仪时,使用投影映射时,被投影的图片会变小,而在平面上则不会。

    在投影映射示例之后,唯一的区别是使用正射投影而不是透视投影。
  • 多维数据集映射?

    这实际上是从6个方向进行的平面映射。由你决定
    以确定哪个UV坐标获取6个平面中的哪个。我猜
    大多数时候,您会采用三角形的法线来查看哪个
    将其最面都平面化,然后从该平面进行平面映射。

    实际上,我可能会混淆我的条款。你也可以
    真实的多维数据集映射,其中具有多维数据集纹理,但这需要
    U,V,W而不只是U,V。为此,它与球体相同
    示例,只是您只将归一化的坐标直接用作
    U,V,W
  • 圆柱映射

    就像球面贴图一样,只是假设模型上有小圆柱体投影。与球体不同,圆柱体具有方向,但是基本上可以将模型的点移动到圆柱体的方向,然后假设x,y,z现在相对于圆柱体(换句话说,将它们乘以矩阵的逆矩阵)代表圆柱体的方向),然后。
    U = Math.atan2(x, z) / Math.PI * 0.5 + 0.5
    V = y
    

  • 另外2个解决方案
  • 也许您想要环境映射?

    Here's 1 exampleHere's another
  • 也许您应该考虑使用内置了UV editors和UV投影仪的建模包,例如Maya或Blender。

  • 关于three.js - 以编程方式为模型生成简单的UV贴图,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34958072/

    相关文章:

    3d - 将3D位置转换为2d屏幕位置[r69!]

    javascript - Three.js 动态片段着色器 GUI

    c++ - 将 2-Dim 循环拆分为多个线程

    opengl - 如何使用 VAO/VBO 为相同顶点指定多个 UV 坐标?

    libgdx - UV映射不适用于导入的obj文件

    graphics - 自动生成UV坐标算法

    javascript - 如何在 Three.js 中相对于相机位置移动聚光灯?

    javascript - three.js: "TypeError: v is undefined"在定义我自制的几何图形时

    javascript - 从 THREE.Mesh 或 THREE.Geometry 创建 CANNON.RigidBody

    c++ - D3D11/C++ 像素着色器中的 uv 插值不准确。如何避免?