如何为不规则球体制作纹理?

8
我希望能给THREE.js球体的每个面都赋予独特的贴图。因此,我让一个SphereGeometry计算顶点,并使用面的顶点将每个面转换为PlaneGeometry。
THREE.SpherePlaneGeometry = function ( v1, v2, v3, v4 ) {

  THREE.Geometry.call( this );

  var normal = new THREE.Vector3( 0, 1, 0 );

  this.vertices.push( v1.clone() );
  this.vertices.push( v2.clone() );
  this.vertices.push( v3.clone() );
  this.vertices.push( v4.clone() );

  var face = new THREE.Face4( 0, 1, 2, 3 );

  face.normal.copy( normal );
  face.vertexNormals.push( normal.clone(), normal.clone(), normal.clone(), normal.clone() );

  this.faces.push( face );

  var uvs = [
    new THREE.UV( 1.0, 0.0 ),
    new THREE.UV( 0.0, 0.0 ),
    new THREE.UV( 0.0, 1.0 ),
    new THREE.UV( 1.0, 1.0 ),
  ];
  this.faceVertexUvs[ 0 ].push( uvs );

};

确保所有这些内容在返回的几何图形中运行:

geometry.computeCentroids();
geometry.computeFaceNormals();
geometry.verticesNeedUpdate = true;
geometry.uvsNeedUpdate = true;
geometry.normalsNeedUpdate = true;
geometry.tangentsNeedUpdate = true;
geometry.elementsNeedUpdate = true;
geometry.dynamic = true;

通过应用这个纹理:

texture

我得到了这个结果:

sphere

有什么方法可以消除红点和绿点之间的扭曲?对于极点,一个顶点被使用了两次,但是可能还有更好的方法,有什么想法吗?


1
看起来这是一个类似的问题:http://stackoverflow.com/questions/6046929/problem-gltexgen-in-open-gl-es-2-0,更一般的问题是:如何给一个投影四边形贴纹理?不过,是否有使用THREE.js的解决方案呢? - Torsten Becker
正如noiv所说,似乎顶部四边形的三角剖分有误。我建议为每个四边形创建一个中间点,并制作4个三角形,然后尝试使用纹理...甚至可以使用phi和delta的u,v来覆盖整个球体,并使用某种重复因子... - EliSherer
@EliSherer,过度细分可以解决这个问题,但多边形数量应该保持不变。另一种称为投影插值的方法被排除了,因为它将问题移动到四边形的边缘:http://www.reedbeta.com/blog/2012/05/26/quadrilateral-interpolation-part-1/ - Torsten Becker
2个回答

3

这是一个棘手的问题。我们的纹理贴图仍然是仿射的。

blah

在某个时候,我们需要尝试透视正确的纹理映射。我曾经在某个地方读到过一些关于插值 w 的内容...但我不确定这是否会解决你的问题。

为了简化问题...看看纹理映射图中的仿射映射四边形。想象一下,将左上角的顶点移动到右上角。通过这样做,你基本上将左三角形变成了从左下到右上的简单直线。这基本上意味着它不可见。由于右三角形的顶点没有移动,三角形仍然存在,可见,带有为每个顶点分配的UV。

所以我能想到的唯一解决方案是:

  1. 对这些多边形添加一级细分。
  2. 为这些可能情况准备特殊的预校正纹理(使用canvas或Photoshop)。

我不确定是否是同一个问题。也许会得出相同的解决方案,或者我需要解决这两个问题。但是我的矩形在投影时没有扭曲,而是变成了梯形。我发现这个描述很有用:http://www.xyzw.us/~cass/qcoord/。然而,我不知道从哪里开始实现这个方法:“这很好,因为我们可以将上部顶点的纹理坐标指定为(0,1)和(1,1)的(s,t)坐标,也可以将它们指定为(0,width,0,width)和(width,width,0,width)的(s,t,r,q)坐标!”听起来真的很简单。 - Torsten Becker

2
这里有几个问题。
首先,你不需要将几何体的每个面都转换成平面几何形状--除非出于某种原因你想这样做。你可以在下面的代码示例中看到如何处理这个问题。
其次,你的问题在于UV设置。
这是一个代码示例 (http://jsfiddle.net/PBjEE/),显示了类似于你的问题。我使用了一个更简单的几何体,但像你的一样,四边形面是梯形形状。在示例中,我按照你的方法设置了每个面的UV坐标为纹理的四个角落,(0,1),(0,0),(1,0)和(1,1)。结果是一个扭曲的圆形。
这是另一个代码示例 (http://jsfiddle.net/PBjEE/1/),通过改变UV坐标移除了扭曲。
UV坐标必须定义与面具有相同比例的梯形。

啊,现在我明白他所提到的梯形是什么了。我的眼睛完全忽略了那个畸变,只集中于上面的三角形 :P - mrdoob
公平地说,你的问题是“有什么办法可以消除失真?”这是解决该问题的方案。现在似乎你正在添加新的要求。也许你可以发一个新帖子? - WestLangley
保持纹理完整并不是一个隐藏的要求。但我会准备一个更好的小提琴并重新发布。顺便说一下:你的小提琴已经揭示了下一个问题:如何设置灯光? - Torsten Becker

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接