GLSL着色器中如何在平面任意位置定位纹理且避免拉伸?
解决纹理偏移时的拉伸问题
我来帮你分析下问题所在,你遇到的拉伸现象其实不是纹理本身的拉伸,而是顶点着色器里错误的纹理采样逻辑导致平面形状变形,视觉上让你误以为是纹理拉伸了。咱们一步步来修正:
核心问题分析
- 错误的变量类型:你把
offsetText1定义成了varying变量,但偏移量是全局统一的参数,不需要在顶点和片段间插值,应该用uniform类型。 - 顶点着色器采样纹理的副作用:你在顶点着色器里用偏移后的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
相关产品推荐
相关产品推荐

