Three.js:在自定义 ShaderMaterial 中修改我的纹理的 UV

Three.js : Modify the UV of my texture inside a custom ShaderMaterial

我有一个平面几何体,我正在创建一个与其相关的 CustomShader material。它将接收一些纹理作为制服。我希望纹理能够完美地覆盖我的平面(例如 background-size:cover css 属性)

当我将我的纹理与 MeshBasicMaterial 一起使用时,我设法通过一个实用函数来做到这一点:

cover( texture, aspect ) {

    var imageAspect = texture.image.width / texture.image.height;

    if ( aspect < imageAspect ) {
        texture.matrix.setUvTransform( 0, 0, aspect / imageAspect, 1, 0, 0.5, 0.5 );

    } else {
        texture.matrix.setUvTransform( 0, 0, 1, imageAspect / aspect, 0, 0.5, 0.5 );

    }

}

但不幸的是,由于我使用的是 ShaderMaterial,我的“封面”功能不再适用。我是否强制在片段着色器中执行此操作?如果是这样,我如何设法重现此行为?

这是我的代码:

const vertexShader = `
    precision highp float;
    uniform mat3 uUvTransform;
    varying vec2 vUv;
    void main() {
        vUv = ( uUvTransform * vec3( uv, 1 ) ).xy;
        gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );
}`;

const fragmentShader = `
    precision highp float;
    uniform sampler2D uText1;
    varying vec2 vUv;


    void main() {
        vec2 xy = vUv;

        vec4 color = texture2D(uText1,xy);
        gl_FragColor = color;
}`;

这是我目前的结果:

非常感谢

Three.js 处理像 .offset, .repeat, .rotation, .center 这样的纹理变换的方式是通过 Matrix3 作为 uniform 传递到顶点着色器中。顶点着色器执行矩阵乘法,然后将修改后的 UV 作为变量传递给片段着色器。

您可以将这些 GLSL 代码行复制到您的 ShaderMaterial 的顶点着色器中,我认为纹理属性会自动出现在 Matrix3 中。但是,如果由于某种原因它没有,您可以重新创建 Matrix3 by copying it from the source 并手动将其作为统一传递。我不知道你的效用函数是什么样的,所以很难说你是如​​何实现所需的缩放的。

您可以简单地使用自定义制服,例如:

uniform sampler2D uText1;
uniform vec2 uUvScale;
varying vec2 vUv;
void main() {
    vec2 uv = (vUv - 0.5) * uUvScale + 0.5;
    gl_FragColor = texture2D(uText1, uv);
}

并且:

var imageAspect = texture.image.width / texture.image.height;
if ( aspect < imageAspect ) {
    material.uniforms.uUvScale.value.set(aspect / imageAspect, 1)
} else {
    material.uniforms.uUvScale.value.set(1, imageAspect / aspect)
}