Three.js 无论网格大小如何,制作固定纹理
Three.js making fixed texture irrespective of mesh size
我正在制作一个简单的动画,我必须将平面的高度从 100% 设置为 0。平面上有纹理。我检查了多个示例,但找不到一种方法来制作固定尺寸的纹理,而不管网格的尺寸如何。
我创建了一个基本的动画示例here
不能使用这个,因为我可能有不同的背景纹理(不是黑色)。
在搜索了几个小时后,我找到了这个 (when I was about to post a question myself). Found the interesting setUv()
function. I modified this function to make another 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. 透明纹理),然后应用具有偏移量的第二个纹理(透明纹理)并将该纹理从底部向上移动。这样我们就不必每次都处理几何体。 (只是想知道这是否可能)
谢谢!
你知道你的几何参数,因此你可以用它来计算 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>
我正在制作一个简单的动画,我必须将平面的高度从 100% 设置为 0。平面上有纹理。我检查了多个示例,但找不到一种方法来制作固定尺寸的纹理,而不管网格的尺寸如何。
我创建了一个基本的动画示例here
不能使用这个,因为我可能有不同的背景纹理(不是黑色)。
在搜索了几个小时后,我找到了这个 setUv()
function. I modified this function to make another 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. 透明纹理),然后应用具有偏移量的第二个纹理(透明纹理)并将该纹理从底部向上移动。这样我们就不必每次都处理几何体。 (只是想知道这是否可能)
谢谢!
你知道你的几何参数,因此你可以用它来计算 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>