Rim边缘高光模型

Rim 模型,即边缘高光模型,其在游戏里的应用比较广泛。本节主要实现为其抽象出一个shader模型,并阐明原理,并附上简单应用案例。

一、Rim长啥样

先上几个图,了解一下这个Rim到底是什么样的。
火炬之光里骷髅怪被建筑物遮挡时呈现出的X光效果
火炬之光里骷髅怪被建筑物遮挡时呈现出的X光效果
boss进入某些特殊状态时的效果
boss进入某些特殊状态时的效果
某些场景为了凸显某些东西时的效果
某些场景为了凸显某些东西时的效果

以上这些都是Rim模型的功劳。那么下面先说说其实现的原理。

二、Rim原理及其模型公式

观察上面的图片,会发现他们都有些共同点就是模型的边缘呈现出了特殊的颜色。那么这是如何做到的??
在这里插入图片描述
其实上图就已经阐明了Rim的实现原理。

设我们的视线方向与法线方向的夹角 α(α ∈ [0°,90°]),当 α
的值越小,边缘光越弱。
换言之就是:
当我们的视线与法线垂直时(α = 90°),边缘光最强;
当视线与法线重合时(α = 0°),边缘最弱。

公式:

rim = 1 - max(0,dot( v → , n → \overrightarrow{v},\overrightarrow{n} v ,n ))

另外大家都喜欢再添加一个变量来控制一下这个rim的值,比如叫 rimPower,还是用的指数函数,所以最后 rim 其实是等于:

rim = pow( 1 - max(0,dot( v → , n → \overrightarrow{v},\overrightarrow{n} v ,n ),rimPower)

三、应用

以下代码仅仅是为了验证上诉理论,并不能真正用于项目中,看官们酌情取之!!

1、实现这种类型的

在这里插入图片描述

shader:

Shader "Unlit/SimpleRim"
{
	Properties
	{
		_MainTex ("Texture", 2D) = "white" {}
		_RimColor("RimColor",Color) = (0.0,0.0,0.0,0.0)
		_RimPow("RimPow",Range(0,5)) = 1.0
	}
	SubShader
	{
		Tags { "RenderType"="Opaque" }
		LOD 100

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

			struct appdata
			{
				float4 vertex : POSITION;
				float2 uv : TEXCOORD0;
				float3 normal : NORMAL;
			};

			struct v2f
			{
				float2 uv : TEXCOORD0;
				UNITY_FOG_COORDS(1)
				float4 vertex : SV_POSITION;
				fixed4 color : COLOR;
			};

			sampler2D _MainTex;
			float4 _MainTex_ST;
			fixed4 _RimColor;
			float _RimPow;
			
			v2f vert (appdata v)
			{
				v2f o;
				o.vertex = UnityObjectToClipPos(v.vertex);
				o.uv = TRANSFORM_TEX(v.uv, _MainTex);
				UNITY_TRANSFER_FOG(o,o.vertex);

				fixed3 worldNormal = UnityObjectToWorldNormal(v.normal);
				fixed3 worldViewDir = normalize(UnityWorldSpaceViewDir(v.vertex));
				fixed rim = (1 - saturate(dot(worldNormal,worldViewDir)));
				fixed4 rimColor = _RimColor * pow(rim,_RimPow);

				o.color = rimColor;
				return o;
			}
			
			fixed4 frag (v2f i) : SV_Target
			{
				fixed4 col = tex2D(_MainTex, i.uv);
				UNITY_APPLY_FOG(i.fogCoord, col);
				return col + i.color;
			}
			ENDCG
		}
	}
}

效果:
在这里插入图片描述

2、实现这种类型的

在这里插入图片描述

这种会稍微复杂些,其实懂得原理了,也简单,只是会多一个步骤。
先简单说下原理:
这个例子为了得到比较好的效果,一般都会开启混合(开启混合就意味着要关闭深度写入,如果这个看不太明白的童鞋需要去补补基础知识了,本文不解释。),所以性能也会低一些。
1、先用一个开了混合的pass单独渲染Rim的效果,为了保证在所有不透明物体之后渲染(场景的物体),改pass的QUEUE 应该在 Gemetry (2000) 和 Transparent(3000)之间。这样我们深度测试的操作自然就是选择 Greater。
2、再用一个pass去正常渲染(包括纹理采样,高光,等等效果)模型就行了。
代码:

Shader "Unlit/XRay"
{
	Properties
	{
		_MainTex ("Texture", 2D) = "white" {}
		_RimColor("Rim Color",Color) = (1.0,1.0,1.0,1.0)
		_RimPow("Rim Power",float) = 1.0
	}
	SubShader
	{
		Tags { "RenderType"="Opaque" }
		LOD 100
		Pass
		{
			Tags{"Queue" = "Gemetry + 500"}

			Blend SrcAlpha One
			ZWrite off
			ZTest Greater

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

			struct appdata
			{
				float4 vertex : POSITION;
				float3 normal : NORMAL;
			};

			struct v2f
			{
				float4 vertex : SV_POSITION;
				fixed4 color : COLOR;
			};

			fixed4 _RimColor;
			float _RimPow;
			
			v2f vert (appdata v)
			{
				v2f o;
				o.vertex = UnityObjectToClipPos(v.vertex);
				fixed3 worldNormal = UnityObjectToWorldNormal(v.normal);
				fixed3 worldViewDir = normalize(UnityWorldSpaceViewDir(v.vertex));
				fixed rim = (1 - saturate(dot(worldNormal,worldViewDir)));
				fixed4 rimColor = _RimColor * pow(rim,_RimPow);

				o.color = rimColor;

				return o;
			}
			
			fixed4 frag (v2f i) : SV_Target
			{
				return i.color;
			}
			ENDCG
		}
		Pass
		{
			CGPROGRAM
			#pragma vertex vert
			#pragma fragment frag
			
			#include "UnityCG.cginc"

			struct appdata
			{
				float4 vertex : POSITION;
				float2 uv : TEXCOORD0;
			};

			struct v2f
			{
				float2 uv : TEXCOORD0;
				float4 vertex : SV_POSITION;
			};

			sampler2D _MainTex;
			float4 _MainTex_ST;
			
			v2f vert (appdata v)
			{
				v2f o;
				o.vertex = UnityObjectToClipPos(v.vertex);
				o.uv = TRANSFORM_TEX(v.uv, _MainTex);
				UNITY_TRANSFER_FOG(o,o.vertex);
				return o;
			}
			
			fixed4 frag (v2f i) : SV_Target
			{
				// sample the texture
				fixed4 col = tex2D(_MainTex, i.uv);
				// apply fog
				UNITY_APPLY_FOG(i.fogCoord, col);
				return col;
			}
			ENDCG
		}
	}
}

效果:
在这里插入图片描述

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值