You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在GLSL中为Three.js实现方形纹理到梯形的渐进式扭曲

问题解决:Three.js平面转梯形时的纹理扭曲校正

问题背景

使用Three.js开发项目时,尝试将带方形纹理的平面转换为顶部收窄的梯形。已通过PlaneBufferGeometry和ShaderMaterial实现了形状变形,但纹理虽覆盖梯形,却未呈现预期的透视扭曲效果(目标效果为纹理随梯形边缘自然拉伸,匹配梯形的透视形态)。

当前代码

顶点着色器

uniform sampler2D uTexture;
varying vec2 vUv;
void main(){

    float scaleTOP = 0.5;
    float scaleBOTTOM = 1.0;
    float scaleLEFT = 1.0;
    float scaleRIGHT = 1.0;

    float scaleX = mix(scaleBOTTOM, scaleTOP, uv.y);
    float posX = position.x*scaleX;

    float scaleY = mix(scaleLEFT, scaleRIGHT, uv.x);
    float posY = position.y*scaleY;

    vec3 finalPosition = vec3(posX, posY);

    gl_Position = projectionMatrix * modelViewMatrix * vec4( finalPosition, 1.0 );

    // Varyings:
    vUv = uv;
}

片元着色器

uniform sampler2D uTexture;
varying vec2 vUv;

void main() {
    vec4 tex = texture2D ( uTexture, vUv );
    gl_FragColor = vec4(tex.r, tex.g, tex.b, 1.0);
}

解决方案

问题核心在于UV坐标未跟随顶点的透视变形做对应调整,原始UV仍按方形平面映射,导致纹理无法匹配梯形的形态。需要修改顶点着色器,根据顶点X方向的缩放比例校正UV坐标:

修改后的顶点着色器

uniform sampler2D uTexture;
varying vec2 vUv;
void main(){

    float scaleTOP = 0.5;
    float scaleBOTTOM = 1.0;
    float scaleLEFT = 1.0;
    float scaleRIGHT = 1.0;

    float scaleX = mix(scaleBOTTOM, scaleTOP, uv.y);
    float posX = position.x*scaleX;

    float scaleY = mix(scaleLEFT, scaleRIGHT, uv.x);
    float posY = position.y*scaleY;

    vec3 finalPosition = vec3(posX, posY);

    gl_Position = projectionMatrix * modelViewMatrix * vec4( finalPosition, 1.0 );

    // 校正UV坐标,匹配X方向的缩放比例
    vUv.x = (uv.x - 0.5) / scaleX + 0.5;
    vUv.y = uv.y;
}

改动说明

  • 针对X方向的缩放(scaleX),对UV的x分量进行反向映射:将UV从以中心为原点的坐标空间缩放后,再还原回0-1范围。这样纹理会跟随梯形的宽度变化自然拉伸,顶部窄区域的纹理会相应收缩,匹配梯形的透视扭曲效果。
  • 片元着色器无需修改,直接使用校正后的vUv采样纹理即可。

内容的提问来源于stack exchange,提问作者Roberto Ferrero

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.14 19:05:15