Javascript THREEjs-裁剪纹理,而不是拉伸以适应
我正在尝试使用three.js构建一个基于图像的艺术制作应用程序 我使用的是React.js,但希望下面的内容对那些没有React经验的人来说也很清楚。组件呈现一个,并从父组件传递一个本地托管的图像URL 当前代码设置为只创建一个完整的窗口画布,创建一个横跨整个画布的2D形状,并将提供的图像设置为纹理:Javascript THREEjs-裁剪纹理,而不是拉伸以适应,javascript,three.js,Javascript,Three.js,我正在尝试使用three.js构建一个基于图像的艺术制作应用程序 我使用的是React.js,但希望下面的内容对那些没有React经验的人来说也很清楚。组件呈现一个,并从父组件传递一个本地托管的图像URL 当前代码设置为只创建一个完整的窗口画布,创建一个横跨整个画布的2D形状,并将提供的图像设置为纹理: import React, { PureComponent } from 'react'; import * as THREE from 'three'; const textureLoade
import React, { PureComponent } from 'react';
import * as THREE from 'three';
const textureLoader = new THREE.TextureLoader();
const vertexShader = `
varying vec2 vUv;
void main() {
vUv = uv;
gl_Position = vec4(uv * 2. - vec2(1, 1), 0., 1.);
}
`;
const fragmentShader = `
precision highp float;
varying vec2 vUv;
uniform sampler2D texture1;
void main() {
gl_FragColor = texture2D(texture1, vUv.xy);
}
`;
class Canvas extends PureComponent {
state = {
width: window.innerWidth,
height: window.innerHeight
}
componentDidMount() {
// TODO: resize handlers for width/height
const {width, height} = this.state;
this.canvas.width = width;
this.canvas.height = height;
const rendererParams = {
canvas: this.canvas,
};
const cameraParams = [
-width / 2,
width / 2,
-height / 2,
height / 2,
];
this.renderer = new THREE.WebGLRenderer(rendererParams);
this.renderer.setClearColor(0xFFFFFF, 1.0)
this.renderer.setSize(width, height);
this.camera = new THREE.OrthographicCamera(...cameraParams);
this.camera.position.set(0, 0, 200);
this.scene = new THREE.Scene();
this.scene.add(this.camera);
// Our initial texture will be the specified default image.
const imageSrc = this.props.defaultImageSrc;
textureLoader.load(imageSrc, texture => {
this.texture = texture;
// TODO: Do I need this?
this.material = new THREE.ShaderMaterial({
vertexShader,
fragmentShader,
uniforms: {
texture1: {
type: "t",
value: this.texture
}
}
});
this.mesh = new THREE.Mesh(new THREE.PlaneGeometry(1), this.material);
this.scene.add(this.mesh);
this.animate();
})
}
animate = () => {
requestAnimationFrame(this.animate);
this.renderer.render(this.scene, this.camera);
}
render() {
return (
<canvas innerRef={elem => this.canvas = elem} />
);
}
}
export default Canvas;
我遇到的问题是,纹理将被拉伸以适合。这意味着,如果图像为1600x1600正方形,但浏览器窗口为1000x500,则图像将被挤压和扭曲,因为它将图像映射为完全适合可用空间:
我想要的是一个相当于背景大小的:封面。在我的例子中,我希望它缩小到最大的窗口尺寸1000x1000,然后从中心裁剪,只显示中间500px的高度。您需要显示您的相机,您使用的是透视相机、正交相机还是占位符相机。而且,如果你正在使用一个自定义着色器,你需要展示你是如何计算你的顶点位置的,他们是否使用projectionMatrix等等。。。。没有这些知识,没有人能回答这个问题 下面是如何使用一个正交摄影机来实现这一点,该摄影机刚刚设置为单位矩阵和2个单位的平面几何体 如果我们不做任何更改,这将显示一个填充画布的平面。之后,我们根据画布的侧面和图像的侧面对其进行缩放
const canvas = renderer.domElement;
const image = material.map.image;
const canvasAspect = canvas.clientWidth / canvas.clientHeight;
const imageAspect = image.width / image.height;
// this assumes we want to fill vertically
let horizontalDrawAspect = imageAspect / canvasAspect;
let verticalDrawAspect = 1;
// does it fill horizontally?
if (horizontalDrawAspect < 1) {
// no it does not so scale so we fill horizontally and
// adjust vertical to match
verticalDrawAspect /= horizontalDrawAspect;
horizontalDrawAspect = 1;
}
mesh.scale.x = horizontalDrawAspect;
mesh.scale.y = verticalDrawAspect;
您需要展示您的相机,您使用的是透视相机、正交相机还是占位符相机。而且,如果您使用的是自定义着色器,则需要显示如何计算顶点位置,以及它们是否使用projectionMatrix。没有这些知识,没有人能回答这个问题嘿@gman,谢谢你的帮助!我的缺点是假设摄影机和着色器没有必要更新我的代码片段-我确实在使用正交摄影机。我之所以使用自定义顶点着色器,仅仅是因为我无法在没有它的情况下渲染图像,但我将给MeshBasicMaterial另一个镜头。非常感谢你的投入,我真的很感激。