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

GLSL着色器中如何在平面任意位置定位纹理且避免拉伸?

解决纹理偏移时的拉伸问题

我来帮你分析下问题所在,你遇到的拉伸现象其实不是纹理本身的拉伸,而是顶点着色器里错误的纹理采样逻辑导致平面形状变形,视觉上让你误以为是纹理拉伸了。咱们一步步来修正:

核心问题分析

  1. 错误的变量类型:你把offsetText1定义成了varying变量,但偏移量是全局统一的参数,不需要在顶点和片段间插值,应该用uniform类型。
  2. 顶点着色器采样纹理的副作用:你在顶点着色器里用偏移后的UV采样位移纹理,导致每个顶点的Z轴位移值基于偏移后的纹理位置计算,不同顶点的位移差异会让平面发生变形,最终看起来像是纹理被拉伸了。

解决方案

根据你的需求,分两种场景给出修正后的代码:

场景1:仅平移显示的纹理,位移效果保持不变

这种情况适合你只想移动纹理的显示位置,但不想改变平面的位移形态。

修正后的顶点着色器

varying vec2 vUv;
uniform sampler2D utexture1;
uniform sampler2D utexture2;
// 把偏移量改成uniform全局变量
uniform vec2 uOffsetText1;

void main() {
    vUv = uv;
    vec4 modelPosition = modelMatrix * vec4(position, 1.0);
    
    // 位移采样用原始UV,不添加偏移
    vec4 displacement = texture2D(utexture1, vUv);
    vec4 displacement2 = texture2D(utexture2, vUv);
    
    modelPosition.z += displacement.r * 1.0;
    modelPosition.z += displacement2.r * 40.0;
    
    gl_Position = projectionMatrix * viewMatrix * modelPosition;
}

修正后的片段着色器

#ifdef GL_ES
precision highp float;
#endif

uniform sampler2D utexture1;
uniform sampler2D utexture2;
varying vec2 vUv;
uniform vec2 uOffsetText1;

void main() {
    vec3 c;
    // 显示纹理用偏移后的UV实现平移
    vec4 Ca = texture2D(utexture1, vUv + uOffsetText1);
    vec4 Cb = texture2D(utexture2, vUv);
    
    // 保持你原来的混合逻辑
    c = Ca.rgb * Ca.a + Cb.rgb * Cb.a * (2.0 - Ca.a);
    gl_FragColor = vec4(c, 1.0);
}

场景2:平移显示纹理的同时,位移效果也跟随纹理移动

如果你希望位移形态也跟着纹理的移动而变化,只需要在顶点着色器的位移采样中也添加偏移即可,但要注意:如果你的位移纹理细节丰富,需要增加平面的顶点细分度,否则位移效果会因为顶点插值显得模糊。

修正后的顶点着色器

varying vec2 vUv;
uniform sampler2D utexture1;
uniform sampler2D utexture2;
uniform vec2 uOffsetText1;

void main() {
    vUv = uv;
    vec4 modelPosition = modelMatrix * vec4(position, 1.0);
    
    // 位移采样也使用偏移后的UV
    vec4 displacement = texture2D(utexture1, vUv + uOffsetText1);
    vec4 displacement2 = texture2D(utexture2, vUv);
    
    modelPosition.z += displacement.r * 1.0;
    modelPosition.z += displacement2.r * 40.0;
    
    gl_Position = projectionMatrix * viewMatrix * modelPosition;
}

片段着色器和场景1的完全一致。

额外优化建议

  • 纹理包裹模式:如果不希望偏移后的纹理重复显示,可以在加载纹理时设置包裹模式为CLAMP_TO_EDGE,比如在Three.js中:
    texture1.wrapS = THREE.ClampToEdgeWrapping;
    texture1.wrapT = THREE.ClampToEdgeWrapping;
    
  • UV适配:如果纹理尺寸和平面UV不匹配,可以对UV进行缩放(比如vUv * vec2(2.0, 2.0)),避免纹理因拉伸变形。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.28 21:12:29