three.js - 保持 Three.js 纹理的方面
问题描述
当纹理显示在不同大小的框中时,我试图保持纹理居中。
我看过这个答案
但它并不完全适合我。
this.texture = new THREE.Texture(this.image)
const vec = new THREE.Vector3()
new THREE.Box3().setFromObject( this.rounded ).getSize(vec)
const imageAspect = this.image.width/this.image.height
const boxAspect = vec.x/vec.y
this.texture.wrapT = THREE.RepeatWrapping;
this.texture.offset.y = 0.5 * ( 1 - boxAspect/imageAspect )
//texture.wrapT = THREE.RepeatWrapping; texture.repeat.x = geometryAspectRatio / imageAspectRatio; texture.offset.x = 0.5 * ( 1 - texture.repeat.x )
this.texture.needsUpdate = true
this.rounded.material = new THREE.MeshPhongMaterial( { map: this.texture, side: THREE.DoubleSide } )
在这方面,价值观是
Image: {width:399 height:275}
Texture: {width:1, height: 0.75}
在这方面,价值观是
Image: {width:399 height:275}
Texture: {width:2, height: 1}
如何修复它以使图形始终居中,保持外观并且不失真?
解决方案
我希望我得到了正确的答案,这是一个如何将其居中的选项:
var scene = new THREE.Scene();
var camera = new THREE.PerspectiveCamera(60, innerWidth / innerHeight, 1, 1000);
camera.position.set(0, 0, 10);
var renderer = new THREE.WebGLRenderer();
renderer.setSize(innerWidth, innerHeight);
document.body.appendChild(renderer.domElement);
var planeGeom = new THREE.PlaneBufferGeometry(16, 9);
var planeMat = new THREE.MeshBasicMaterial({
map: new THREE.TextureLoader().load("https://threejs.org/examples/textures/758px-Canestra_di_frutta_(Caravaggio).jpg", tex => {
//console.log(tex);
//console.log(tex.image.width, tex.image.height);
let imgRatio = tex.image.width / tex.image.height;
let planeRatio = planeGeom.parameters.width / planeGeom.parameters.height;
//console.log(imgRatio, planeRatio);
tex.wrapS = THREE.RepeatWrapping; // THREE.ClampToEdgeWrapping;
tex.repeat.x = planeRatio / imgRatio;
tex.offset.x = -0.5 * ((planeRatio / imgRatio) - 1);
})
});
var plane = new THREE.Mesh(planeGeom, planeMat);
scene.add(plane);
renderer.setAnimationLoop(() => {
renderer.render(scene, camera);
})
body {
overflow: hidden;
margin: 0;
}
<script src="https://threejs.org/build/three.min.js"></script>
补充:如何重新计算 ShapeBufferGeometry 的 UV
var box = new THREE.Box3().setFromObject(mesh); // mesh with ShapeBufferGeometry
var size = new THREE.Vector3();
box.getSize(size);
var vec3 = new THREE.Vector3(); // temp vector
var attPos = mesh.geometry.attributes.position;
var attUv = mesh.geometry.attributes.uv;
for (let i = 0; i < attPos.count; i++){
vec3.fromBufferAttribute(attPos, i);
attUv.setXY(i,
(vec3.x - box.min.x) / size.x,
(vec3.y - box.min.y) / size.y
);
}
attUv.needsUpdate = true; // just in case
推荐阅读
- jsf - JSF SelectOneMenu 在没有转换器的情况下无法工作?
- sql - 我想为每个现有的 ROW 插入一个 ID 值
- android - 当从 ViewPager 中删除页面时,PageTransformer 返回错误的位置
- android - 从另一个选项卡刷新选项卡
- oauth-2.0 - AWS 和 Cognito
- spring-boot - 如何优雅地关闭 Spring Batch 从站
- python - 在 Watson Studio Python“环境”中安装 rpy2 时出现问题
- php - apache 意外退出,chrome 浏览器失败,没有任何响应
- vb.net - 如何在 VB.NET BackgroundWorker 中使用百分比而不是 ProgressBar 控件
- ios - 在开发人员门户上创建配置文件时无法选择通配符 App ID