赞
踩
根据前面的学习,我们了解到除了可以对点的颜色进行处理,还可以对点本身进行操作,例如我们可以改变点的位置,这样就可以实现对模型渲染的操控。物体边缘效果是我们常用的一种效果,要实现物体边缘,原理也很简单。
首先我们要了解到,模型在渲染时,有正面和背面之分,背面一般是不渲染,进行剔除,我们看到的模型往往是正常渲染正面,如下图所示:
了解到这,因此我们可以控制是否显示正面或者背面。进一步了解物体轮廓,物体轮廓其实就是物体在显示的屏幕上最外侧的边缘部分,因此要对模型最外部的边缘部分进行处理,如上图的边缘部分就是立方体的几条边,如下图所示,红色所在范围即为边缘部分。为了获取到边缘部分,需要将点转换到裁切空间进行处理。
关于裁剪空间,参考裁剪空间这篇文章
说明白点,裁剪空间就是摄像机视野范围内的一个矩阵转换空间,在该空间内可以进行点处理。首先,我们把边缘处理的流程分为两个pass,一个处理剔除正面的渲染,一个处理正面的正常渲染。
第一个pass:
Pass
{
//剔除正面 只看背面
Cull Front
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
float _Outline;
float4 _OutlineColor;
struct appdata
{
float4 vertex : POSITION;
float3 normal : NORMAL;
};
struct v2f
{
float4 pos : SV_POSITION;
};
v2f vert (appdata v)
{
v2f o;
o.pos = UnityObjectToClipPos(v.vertex + normalize(v.vertex) * _Outline);
return o;
}
fixed4 frag (v2f i) : SV_Target
{
return _OutlineColor;
}
ENDCG
}
使用UnityObjectToClipPos函数,可以将模型空间的点转换到裁剪空间,下面这行在原来点的基础上,乘以法线点和轮廓值,向外延伸,如下图所示。
o.pos = UnityObjectToClipPos(v.vertex + normalize(v.vertex) * _Outline);
完成背面处理的pass后,进行正常的pass处理,不需要添加cull,默认渲染只正面,代码如下:
Pass
{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
sampler2D _MainTex;
struct appdata
{
float4 vertex : POSITION;
float2 uv : TEXCOORD0;
};
struct v2f
{
float2 uv : TEXCOORD0;
float4 vertex : SV_POSITION;
};
v2f vert (appdata v)
{
v2f o;
o.vertex = UnityObjectToClipPos(v.vertex);
o.uv = v.uv;
return o;
}
fixed4 frag (v2f i) : SV_Target
{
return tex2D(_MainTex, i.uv);
}
ENDCG
}
整体的效果如下:
完整code:
Shader "Custom/Study/Simple Outline"
{
Properties
{
_MainTex ("Texture", 2D) = "white" {}
_Outline ("Outline", Range(0, 1)) = 0.1
_OutlineColor ("Outline Color", Color) = (1,1,1,1)
}
SubShader
{
Tags { "RenderType"="Opaque" }
LOD 100
Pass
{
//剔除正面 只看背面
Cull Front
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
float _Outline;
float4 _OutlineColor;
struct appdata
{
float4 vertex : POSITION;
float3 normal : NORMAL;
};
struct v2f
{
float4 pos : SV_POSITION;
};
v2f vert (appdata v)
{
v2f o;
o.pos = UnityObjectToClipPos(v.vertex + normalize(v.vertex) * _Outline);
return o;
}
fixed4 frag (v2f i) : SV_Target
{
return _OutlineColor;
}
ENDCG
}
Pass
{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
sampler2D _MainTex;
struct appdata
{
float4 vertex : POSITION;
float2 uv : TEXCOORD0;
};
struct v2f
{
float2 uv : TEXCOORD0;
float4 vertex : SV_POSITION;
};
v2f vert (appdata v)
{
v2f o;
o.vertex = UnityObjectToClipPos(v.vertex);
o.uv = v.uv;
return o;
}
fixed4 frag (v2f i) : SV_Target
{
return tex2D(_MainTex, i.uv);
}
ENDCG
}
}
}
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。