Unity中对物体进行轮廓线描绘的几种实现方案及原理

1.基于屏幕后处理

A.利用CommandBuffer

m_CommandBuffer.SetGlobalColor("_ID", col);//向pass 0中传颜色
m_CommandBuffer.DrawRenderer(r, m_OutlineMaterial, i, 0);
// Pass 0: Fill id
Pass
{
	Cull Off

	CGPROGRAM
	#pragma vertex vertex
	#pragma fragment fragment			
	#pragma enable_d3d11_debug_symbols
	#include "UnityCG.cginc"

	sampler2D _MainTex;
	sampler2D _Tex;
	fixed4 _ID;

	fixed4 fragment(v2f i) : SV_Target
	{
		fixed4 col = tex2D(_MainTex, i.uv);			
		if (col.a < 0.1) discard;
		return _ID;
	}
	ENDCG
}

col为每个模型(或mesh)对应的颜色,每个模型颜色都不同
DrawRenderer的顺序决定了渲染顺序,进而影响边的位置

B.在OnRenderImage执行CommandBuffer 绘会模型颜色区

在这里插入图片描述

C.pass 1中进行边缘检测,非边缘区全部置为白色

在这里插入图片描述

D.pass 2中进行模糊处理,包含横向和纵向

在这里插入图片描述

E.将C和D的RenderTexture传递给pass 3

C中黑色部分,且D中非黑色部分,设置为边的颜色
C中白色部分,为填充色

此方法对多个mesh组成的模型需要特殊处理,即将同模型的_ID值置为相同的值,否则会导致每个mesh都被描边,而不是仅轮廓线。

2.基于顶点着色器顶点修改

A.给模型添加新的材质球

B.pass 0进行模板测试,将模型像素区的模板缓存置为1

C.pass 1将模型顶点延法线法线外扩,且进行模板测试,不为1的像素模板测试通过,为1的过滤掉。

  • 此方法对互相遮蔽的模型,会导致轮廓线“看起来”融合到一起,主要是因为被遮蔽的模型的轮廓线会被前面的模型的模板测试留下的模板缓冲区的值给过滤掉
解决方案:

1.将各个模型排序,从近到远,分别向Shader中传入Stencil Ref的值,从大到小;越近的值越大,Stencil Buffer默认值是0。如图所示,这里需要将2个pass拆分为2个Shader。
在这里插入图片描述
2.第一个Shader(即原来的pass 0)的render queque使用大于2500的值,保证back-to-font的渲染顺序。
3.第二个Shader(即原来的pass 1)的模板测试Compare Func改为 Greater,即传入Ref的值>Stencilbuffer中的值,像素通过测试。
4.此方法当模型位置变动时,Stencil的值需要实时更新

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值