Unity Shader问题:无法使侧面朝向正确方向并旋转UV
解决Shader的两个核心问题:侧面UV顺时针旋转90度 + 固定纹理缩放比例
问题分析
- 纹理缩放随物体尺寸变化:你当前使用
worldPos计算UV,物体缩放时世界坐标会同步缩放,导致纹理跟着被拉伸/压缩。需要改用本地坐标(Object Space),它不受物体缩放影响,能保持纹理原始比例。 - 侧面UV旋转失效:顺时针旋转90度的UV变换公式是
float2(uv.y, 1 - uv.x),需要针对所有侧面(x/z方向法线的面)应用这个变换。
修改后的完整Shader代码
Shader "Custom/Tiling" { Properties { _Color ("Main Color", Color) = (1,1,1,1) _MainTex ("Base (RGB)", 2D) = "white" {} _Scale("Texture Scale", Float) = 1.0 } SubShader { Tags { "RenderType"="Opaque" } LOD 200 CGPROGRAM #pragma surface surf Lambert sampler2D _MainTex; fixed4 _Color; float _Scale; struct Input { float3 worldNormal; float3 worldPos; }; void surf (Input IN, inout SurfaceOutput o) { float2 UV; fixed4 c; // 将世界坐标转换为本地坐标,消除物体缩放对UV的影响 float3 objPos = mul(unity_WorldToObject, float4(IN.worldPos, 1)).xyz; if (abs(IN.worldNormal.x) > 0.5) { // X轴方向的侧面:取本地坐标的yz分量,然后顺时针旋转90度 UV = objPos.yz; UV = float2(UV.y, 1 - UV.x); // 顺时针旋转90度 c = tex2D(_MainTex, UV * _Scale); } else if (abs(IN.worldNormal.z) > 0.5) { // Z轴方向的侧面:取本地坐标的xy分量,然后顺时针旋转90度 UV = objPos.xy; UV = float2(UV.y, 1 - UV.x); // 顺时针旋转90度 c = tex2D(_MainTex, UV * _Scale); } else { // 顶面/底面:取本地坐标的xz分量,保持原UV方向 UV = objPos.xz; c = tex2D(_MainTex, UV * _Scale); } o.Albedo = c.rgb * _Color; } ENDCG } Fallback "Legacy Shaders/VertexLit" }
关键改动说明
- 替换为本地坐标:通过
mul(unity_WorldToObject, float4(IN.worldPos, 1)).xyz将世界坐标转换为物体本地坐标,这样无论物体怎么缩放,UV计算都基于模型原始尺寸,纹理比例保持不变。 - UV旋转实现:顺时针旋转90度的核心是
UV = float2(UV.y, 1 - UV.x)——因为纹理的原点在左下角,旋转后需要将y轴反转才能保证图像正确朝上。 - 移除无用参数:原Input结构中的
uv_MainTex未被使用,直接删除简化代码。
额外提示
如果旋转后纹理方向不符合预期,可以尝试调整旋转公式:
- 逆时针旋转90度:
float2(1 - UV.y, UV.x) - 顺时针旋转后镜像:
float2(UV.y, UV.x)(根据实际需求调整)
内容的提问来源于stack exchange,提问作者LinkVader
相关产品推荐
相关产品推荐

