如何在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
相关产品推荐
相关产品推荐

