Unity内置渲染管线:Shader场景视图正常游戏视图异常问题
Unity无光照Shader圆形显示异常问题
我制作了一个无光照Shader,想要在网格中心显示圆形,代码如下:
Shader "Unlit/UnlitBasicShader" { Properties { _Color("Tint", Color) = (1.0, 1.0, 1.0, 1.0) _ColorCenterOfMass("Color of the center of mass", Color) = (1.0, 1.0, 1.0, 1.0) _SizeCenterOfMass("Size of the center of mass", Float) = 1 } SubShader { Tags { "RenderType"="Opaque" } LOD 100 Pass { CGPROGRAM #pragma vertex vert #pragma fragment frag #include "UnityCG.cginc" struct appdata { float4 vertex : POSITION; float2 uv : TEXCOORD0; }; struct v2f { float4 worldPos : TEXCOORD1; float4 vertex : SV_POSITION; }; float4 _Color; float4 _ColorCenterOfMass; float _SizeCenterOfMass; v2f vert (appdata v) { v2f o; o.worldPos = mul(unity_ObjectToWorld, v.vertex); o.vertex = UnityObjectToClipPos(v.vertex); return o; } fixed4 frag(v2f i) : SV_Target { float3 localSpace = i.worldPos - mul(unity_ObjectToWorld,float4(0,0,0,1)).xyz; float distance = sqrt(localSpace.x * localSpace.x + localSpace.y * localSpace.y); float circleCenterOfMass = step(distance,_SizeCenterOfMass); fixed4 col = lerp(_Color, _ColorCenterOfMass, circleCenterOfMass); return col; } ENDCG } } }
该Shader在**Scene View(场景视图)中显示正常,但在Game View(游戏视图)**中,圆形锚定在世界空间中心,而非网格自身中心。
问题原因
你在计算相对位置时,错误地将顶点转成世界空间后再计算与物体世界中心的距离。这种写法在场景视图的相机渲染逻辑下偶然正常,但在游戏视图中,世界空间坐标的计算会受物体位置影响,导致圆形锚定到世界原点而非网格自身中心。本质上你需要的是模型空间内顶点到网格中心的距离,而非世界空间的距离。
修复方案
直接在模型空间计算顶点到中心的距离,避免世界空间转换带来的干扰:
修改后的Shader代码
Shader "Unlit/UnlitBasicShader" { Properties { _Color("Tint", Color) = (1.0, 1.0, 1.0, 1.0) _ColorCenterOfMass("Color of the center of mass", Color) = (1.0, 1.0, 1.0, 1.0) _SizeCenterOfMass("Size of the center of mass", Float) = 1 } SubShader { Tags { "RenderType"="Opaque" } LOD 100 Pass { CGPROGRAM #pragma vertex vert #pragma fragment frag #include "UnityCG.cginc" struct appdata { float4 vertex : POSITION; float2 uv : TEXCOORD0; }; struct v2f { float distanceToCenter : TEXCOORD1; float4 vertex : SV_POSITION; }; float4 _Color; float4 _ColorCenterOfMass; float _SizeCenterOfMass; v2f vert (appdata v) { v2f o; o.vertex = UnityObjectToClipPos(v.vertex); // 模型空间下网格中心就是(0,0,0),直接计算顶点到原点的距离 float3 localPos = v.vertex.xyz; o.distanceToCenter = sqrt(dot(localPos.xy, localPos.xy)); return o; } fixed4 frag(v2f i) : SV_Target { float circleCenterOfMass = step(i.distanceToCenter, _SizeCenterOfMass); fixed4 col = lerp(_Color, _ColorCenterOfMass, circleCenterOfMass); return col; } ENDCG } } }
额外优化
可以去掉开方运算提升性能,因为比较平方后的距离大小关系与原距离一致:
// 顶点着色器中传递平方距离 o.distanceSq = dot(localPos.xy, localPos.xy); // 片元着色器中比较平方后的大小 float circleCenterOfMass = step(i.distanceSq, _SizeCenterOfMass * _SizeCenterOfMass);
内容的提问来源于stack exchange,提问作者Louis
相关产品推荐
相关产品推荐

