UnityShader之OutLine

这篇博客介绍了如何在Unity中使用Shader实现观察空间下的均匀描边效果。关键在于将顶点坐标转换到观察空间并根据法线进行偏移,确保线条在不同视角下宽度一致。Shader包含两个Pass,一个用于绘制线条,一个用于填充。最终实现了在物体边缘描绘出固定宽度的轮廓线。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

算法很简单,主要需要不同观察角度看上去线的宽度一样,需要转换到观察空间进行操作,空间变换请看我上一篇博客。
需要两个pass,一个画线,一个填充

Shader "Custom/Outline"
{
	Properties
	{
	
	_OutlineVal("Outline value", Range(0., 2.)) = 1.                //描线的宽度
		_OutlineCol("Outline color", color) = (1., 1., 1., 1.)
	}
		SubShader
	{
		Tags{ "Queue" = "Geometry" "RenderType" = "Opaque" }

		Pass
	{
		Cull Front

		CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"

		struct v2f {
		float4 pos : SV_POSITION;
	};

	float _OutlineVal;

	v2f vert(appdata_base v) {
		v2f o;
		o.pos = mul(UNITY_MATRIX_MV, v.vertex);       //注意这里只换算到观察空间,还没有到裁剪空间
		float3 normal = mul((float3x3) UNITY_MATRIX_IT_MV, v.normal); //上一篇博客说过,法线的变换需要用到UNITY_MATRIX_IT_MV
		o.pos.xy += _OutlineVal*normal.xy;   //观察空间里xy方向始终和最终屏幕方向相同,这保证了描线始终面向我们,边缘朝外偏移一点点
		o.pos = mul(UNITY_MATRIX_P, o.pos); //最终需要把坐标从观察空间变换到裁剪空间
		return o;
	}

	fixed4 _OutlineCol;

	fixed4 frag(v2f i) : SV_Ta
### Unity Shader 实现透明描边效果的方法 为了在Unity中实现带有透明度的描边效果,可以采用多Pass的方式处理。具体来说: #### 深度写入 Pass 创建一个用于仅写入深度信息的第一Pass,这有助于后续Pass判断哪些像素应该被遮挡或剔除。 ```cg Pass { Name "DepthOnly" Tags { "LightMode"="ShadowCaster" } CGPROGRAM #pragma vertex vert #pragma fragment frag struct appdata_t { float4 vertex : POSITION; }; void vert(appdata_t v, out float4 oPos : SV_POSITION) { oPos = UnityObjectToClipPos(v.vertex); } half4 frag() : COLOR { return 0; // 不输出颜色只写入深度 } ENDCG } ``` #### 正常渲染 Pass 第二个Pass按照常规方式绘制对象本身的颜色和材质属性,这里假设使用的是`StandardSpecular`光照模型并启用了全部阴影投射功能[^1]。 ```cg Pass { Name "ForwardBase" Tags {"LightMode"="ForwardBase"} CGPROGRAM #pragma surface surf StandardSpecular fullforwardshadows addshadow sampler2D _MainTex; struct Input { float2 uv_MainTex; }; void surf (Input IN, inout SurfaceOutputStandardSpecular o) { fixed4 col = tex2D(_MainTex, IN.uv_MainTex); o.Albedo = col.rgb; o.Specular = col.a; // 假设高光强度存储于alpha通道 o.Smoothness = col.a; // Smoothness也来自同一张贴图的alpha通道 } ENDCG } ``` #### 法线延伸描边 Pass 最后一个Pass用来计算边缘位置并通过扩展法线方向来形成描边视觉效果。通过读取场景中的深度缓冲区数据,能够有效地检测到物体轮廓,并应用指定宽度和平滑过渡的半透明描边。 ```cg Pass { Name "Outline" Cull Front // 反向裁剪以捕捉背面作为外框 ZWrite Off // 关闭Z测试防止干扰其他渲染 Blend SrcAlpha OneMinusSrcAlpha // 启用混合模式支持半透明白边 CGPROGRAM #include "UnityCG.cginc" struct appdata_t { float4 vertex : POSITION; float3 normal : NORMAL; }; struct v2f { float4 pos : SV_POSITION; float4 color : COLOR; }; uniform float _OutlineWidth; uniform float4 _OutlineColor; v2f vert(appdata_t v) { v2f OUT; // 将顶点沿其法线向外移动一定距离模拟描边厚度 v.vertex.xyz += normalize(v.normal) * _OutlineWidth; OUT.pos = UnityObjectToClipPos(v.vertex); // 设置描边颜色(带透明度) OUT.color = _OutlineColor; return OUT; } half4 frag(v2f i) : COLOR { clip(i.color.a - 0.01); // 移除完全不透明的部分 return i.color; } ENDCG } ``` 上述代码片段展示了如何构建一个多阶段Shader程序,在Unity环境中实现了具有透明特性的描边效果。注意调整参数如`_OutlineWidth` 和 `_OutlineColor` 来获得理想的艺术风格表现[^2]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值