您的位置:首页 > 移动开发 > Unity3D

3.顶点外扩方法实现的描边shader

2016-07-01 22:40 1201 查看
描边shader的实现有很多种,顶点外扩是其中之一。顶点外扩的原理是用2个Pass 渲染物体2次
第一遍:描边,顶点沿法线方向外拓后用黑色渲染。外扩这一步的实现是在投影空间,也就是2D的,根绝法线的x和y值进行外扩,因为是沿着法线方向外扩,所以法线越和摄像机方向相同,也就是越接近面向摄像机的顶点,顶点的位置变化的越小,当法线和摄像机方向相同时,不会有任何变化。

第一遍渲染后,实际的图像如下:





第二遍:正常渲染物体,与第一遍渲染的混合在一起





优点:

(1)效果最好。

(2)适用范围广。

缺点:

(1)对效率有一定影响。因为有2个Pass,所以DrawCall为正常的2倍
(2)对于法线过度不均匀的模型,比如立方体,轮廓会有缝隙。

上边的立方体例子我是特意把描边的外扩值调到很大,便于理解。由第一遍渲染后的图和第二遍渲染后的图的对比,很容易理解这个方法的原理。其实就是通过法线来把边缘进行位移,如果不是边缘,则不位移,比如立方体的正面。在第二次渲染后,会覆盖同位置的像素,因为边缘已经外扩,像素的位置已经不是原来的位置,因此不会被覆盖,而像位于立方体正面的像素,则会被第二次渲染时覆盖,最后就混合成了带黑边的效果图。

Shader "Study/3_OutLine"
{
Properties
{
_MainTex("Texture", 2D) = "white"{}
_LineSize("OutlineSize", range(0, 0.1)) = 0.02
_LineColor("LineColor", Color) = (0,0,0,1)
}
SubShader
{
Pass
{
Tags{ "LightMode" = "Always" }
// 先绘制这个纯色的顶点,然后在下一个pass绘制对象
//这里不存在前后面,关闭裁剪前后面,也不需要深度缓存
Cull Off // 关闭剔除,模型前后都会显示
ZWrite Off // 系统默认是开的,要关闭。关闭深度缓存,后渲染的物体会根据ZTest的结果将自己渲染输出写入
ZTest Always // 深度测试[一直显示],被其他物体挡住后,此pass绘制的颜色会显示出来
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
float _LineSize;
float4 _LineColor;
struct v2f
{
float4 pos:SV_POSITION;
float4 color : COLOR;
};
v2f vert(appdata_full v)
{
v2f o;
// 获取模型的最终的投影坐标
o.pos = mul(UNITY_MATRIX_MVP, v.vertex);
// UNITY_MATRIX_IT_MV为【模型坐标-世界坐标-摄像机坐标】【专门针对法线的变换】
// 法线乘以MV,将模型空间 转换 视图空间
float3 norm = mul((float3x3)UNITY_MATRIX_IT_MV, v.normal);
// 转换 视图空间 到 投影空间 【3D转2D】
float2 offset = TransformViewToProjection(norm.xy);
// 得到的offset,模型被挤的非常大,然后乘以倍率
o.pos.xy += offset * _LineSize;
o.color = _LineColor;
return o;
}
float4 frag(v2f i) : COLOR
{
return i.color;
}
ENDCG
}
Pass
{
// 直接使用顶点和片段shader显示物体
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
sampler2D _MainTex;
float4 _MainTex_ST;

struct v2f
{
float4 pos:SV_POSITION;
float2 uv : TEXCOORD0;// 纹理,相对自身的坐标轴,float2是一个平面
};
v2f vert(appdata_full v)
{
v2f o;
o.pos = mul(UNITY_MATRIX_MVP, v.vertex);
o.uv = TRANSFORM_TEX(v.texcoord, _MainTex);
return o;
}
float4 frag(v2f i) : COLOR
{
float4 texCol = tex2D(_MainTex, i.uv);
return texCol;
}
ENDCG
}
}
}

附上工程连接:http://download.csdn.net/detail/yinfourever/9565336
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  Unity Shader 描边