Three.js制作固定纹理,而与网格大小无关

时间:2018-12-07 14:25:48

标签: three.js texture-mapping

我正在制作一个简单的动画,其中我必须使平面的高度从100%变为0进行动画处理。平面上具有纹理。我检查了多个示例,无论网格的尺寸如何,都找不到一种使尺寸固定的纹理的方法。

我创建了动画here

的基本示例

不能使用它,因为我的背景纹理可能不同(不是黑色)。

经过几个小时的搜索,我发现了这个question(当我自己要发布问题时)。找到了有趣的setUv()函数。我修改了此函数以制作另一个example。 基本上,我会在每次迭代中放置几何体,并为新的几何体分配新的纹理(比上一个小)。

var group, mesh, geometry, meterial;
var planeHeight, planeWidth;
var UVwr, UVhr;
planeHeight = planeWidth = 3;
UVwr = UVhr = 1.5;
function drawElements(){
  group = new THREE.Group();
  geometry = new THREE.PlaneGeometry( planeWidth, planeHeight );
  var texture = new THREE.Texture( generateTexture() );
  texture.needsUpdate = true;
  texture.wrapS = texture.wrapT = THREE.RepeatWrapping;
  texture.repeat.set(1,1);
  material = new THREE.MeshBasicMaterial( { map: texture, transparent: true } );
  plane = new THREE.Mesh( geometry, material );
  var v = plane.geometry.faceVertexUvs[0];
  setUv( v, 0, UVwr, UVhr );
  group.add( plane );
    scene.add( group );
}

/* Plane Geometry */
function setUv( v, index, wr, hr ) {
    for (var i=index*2; i<(index+1)*2; i++) {
        for (var j=0; j<3; j++) {
            v[i][j].x = v[i][j].x * wr;
            v[i][j].y = v[i][j].y * hr;         
        }
    }
}
function animate(){
  planeHeight -= 0.01;
  UVhr -= 0.005;
  planeHeight = planeHeight < 0.01 ? 3 : planeHeight;
  UVhr = UVhr < 0.005 ? 1.5 : UVhr;
  group.children[0].geometry.dispose();
  group.children[0].geometry = new THREE.PlaneGeometry( planeWidth, planeHeight );

  var v = plane.geometry.faceVertexUvs[0];
  setUv( v, 0, UVwr, UVhr );
}

我想知道是否还有其他更好的方法来制作此动画。

也许我们可以使用2个纹理(1.图像纹理和2.透明纹理),然后应用具有偏移量的第二个纹理(透明纹理),然后从底部向上移动该纹理。这样,我们就不必每次都布置几何体。 (只是想知道那是否可能)

谢谢!

1 个答案:

答案 0 :(得分:2)

您知道几何的参数,因此可以将其用于计算uv坐标:

var scene = new THREE.Scene();
var camera = new THREE.PerspectiveCamera(60, window.innerWidth / window.innerHeight, 1, 1000);
camera.position.set(0, 0, 10);
var renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);

var planeGeom = new THREE.PlaneBufferGeometry(10, 10);
console.log(planeGeom);
var planeMat = new THREE.MeshBasicMaterial({
  map: new THREE.TextureLoader().load("https://threejs.org/examples/textures/UV_Grid_Sm.jpg")
});
var plane = new THREE.Mesh(planeGeom, planeMat);
scene.add(plane);

var clock = new THREE.Clock();
var y = 0,
  yUv = 0,
  h = planeGeom.parameters.height;

renderer.setAnimationLoop(() => {

  y = Math.sin(clock.getElapsedTime()) * 2.5 + 2.5;
  
  plane.position.y = y;

  planeGeom.attributes.position.setY(0, h * 0.5 - y * 2);
  planeGeom.attributes.position.setY(1, h * 0.5 - y * 2);
  planeGeom.attributes.position.needsUpdate = true;

  yUv = (Math.sin(clock.getElapsedTime()) * h * 0.5 + h * 0.5) / h;

  planeGeom.attributes.uv.setY(0, 1 - yUv);
  planeGeom.attributes.uv.setY(1, 1 - yUv);
  planeGeom.attributes.uv.needsUpdate = true;

  renderer.render(scene, camera);
});
body {
  overflow: hidden;
  margin: 0;
}
<script src="https://threejs.org/build/three.min.js"></script>