Unity模型描边的几种方法.(Shader、GL、代码生成描绘边)

Unity模型描边的⼏种⽅法.(Shader、GL、代码⽣成描绘边)
前⾔
1、前段时间⼯作,需要给模型描边,由于对Shader不熟悉,就直接⽹上了描边Shader⽂件,⽆奈项⽬发布环境是WebGL,WebGL对Shader的需求⽐较特殊,故⽆法使⽤。
2、因为项⽬需要描边的物体并不多,所以萌⽣出,动态⽣成整个模型所有的边(线条),给各个边附上需要的材质球即可。(当然,也可以直接请美术在模型上描边,但这样不能实现泛光之类的效果)
3、现写下三种实现模型描边的⽅法,⽅便⽇后查看学习与使⽤。
实现
1、GL描边
原理⽐较简单,就是获取到模型的所有顶点,然后使⽤GL连线.
以下是GL描边代码,在项⽬的GLSingleWireFrameScene场景中有演⽰.
/// <summary>
/// 描绘单个模型线框.
/// </summary>
public class GLSingleWireFrame : MonoBehaviour
{
public Material lineMaterial;
private Mesh m_mesh;
private Vector3[] m_vertices;
private int[] m_triangles;
private Transform m_transform;
void Awake()
{
m_mesh = gameObject.GetComponent<MeshFilter>().mesh;
m_vertices = m_mesh.vertices;
m_triangles = iangles;
m_transform = transform;
}
public void OnRenderObject()
{
山药种植开沟机lineMaterial.SetPass(0);//GLSingleWireFrame材质球Shader是 Unlit/Color.
GL.PushMatrix();
GL.MultMatrix(m_transform.localToWorldMatrix);
GL.Begin(GL.LINES);
for(int cnt =0; cnt < m_triangles.Length; cnt +=3)
{
GL.Vertex(m_vertices[m_triangles[cnt]]);
GL.Vertex(m_vertices[m_triangles[cnt +1]]);
GL.Vertex(m_vertices[m_triangles[cnt +1]]);
GL.Vertex(m_vertices[m_triangles[cnt +2]]);
GL.Vertex(m_vertices[m_triangles[cnt +2]]);
GL.Vertex(m_vertices[m_triangles[cnt]]);
}
GL.End();
GL.PopMatrix();
}
}
2、Shader描边
人山
Shader描边实现的⽅法也有很多,上图的是法线外拓⽅法。使⽤两个pass,第⼀个pass让顶点沿着法线⽅向延伸出去,使得模型变⼤⼀圈。第⼆个pass正常渲染,让正常渲染的模型挡在第⼀个pass之上,这样就会露出去的部分就是描绘的边。
⽹上有很多描边的例⼦,这⾥不详细介绍. 例如,、、
以下是Shader代码,在项⽬的UtilizeShaderScene场景中有演⽰.
Shader "Shaders/ToonBound"
{
{
Properties
{
_Color ("Color Tint", Color)=(1,1,1,1)
_MainTex ("Main Tex",2D)="white"{}
_Ramp ("Ramp Texture",2D)="white"{}//控制漫反射⾊调的渐变纹理        _Outline ("Outline",Range(0,1))=0.1//控制轮廓线宽度
_OutlineColor ("Outline Color", Color)=(1,0,0,1)//轮廓线颜⾊
_Specular ("Specular", Color)=(1,1,1,1)//⾼光反⾊颜⾊
_SpecularScale ("Specular Scale",Range(0,0.1))=0.01//⾼光反射系数阈值
}
SubShader
{
超导限流器Tags {"RenderType"="Opaque""Queue"="Geometry"}
LOD 100
Pass
{
//命名Pass块,以便复⽤
NAME "OUTLINE"
//剔除正⾯
Cull Front
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
// make fog work
//#pragma multi_compile_fog
#include "inc"
float _Outline;
fixed4 _OutlineColor;
struct a2v {
float4 vertex : POSITION;
float3 normal : NORMAL;
};
struct v2f {
float4 pos : SV_POSITION;
};
v2f vert (a2v v){
v2f o;
//让描边在观察空间达到最好的效果
float4 pos =mul(UNITY_MATRIX_MV, v.vertex);
float3 normal =mul((float3x3)UNITY_MATRIX_IT_MV, v.normal);
normal.z =-0.5;
pos = pos +float4(normalize(normal),0)* _Outline;
/
/将顶点从视⾓空间变换到裁剪空间
o.pos =mul(UNITY_MATRIX_P, pos);
return o;
}
float4 frag(v2f i): SV_Target {
//轮廓线颜⾊渲染整个背⾯
return float4(_b,1);
}
ENDCG
}
Pass
夹网布
{
Tags {"LightMode"="ForwardBase"}
//渲染正⾯
Cull Back
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#pragma multi_compile_fwdbase
#include "inc"
#include "inc"
#include "inc"
#include "inc"
多功能锤子
fixed4 _Color;
sampler2D _MainTex;
float4 _MainTex_ST;
sampler2D _Ramp;
fixed4 _Specular;
fixed _SpecularScale;
电子台历struct a2v {
float4 vertex : POSITION;
float3 normal : NORMAL;
float4 texcoord : TEXCOORD0;
float4 tangent : TANGENT;
};
struct v2f {
float4 pos : POSITION;
float2 uv : TEXCOORD0;
float3 worldNormal : TEXCOORD1;
float3 worldPos : TEXCOORD2;
SHADOW_COORDS(3)
};
v2f vert (a2v v){
v2f o;
o.pos =UnityObjectToClipPos( v.vertex);
o.uv = TRANSFORM_TEX (v.texcoord, _MainTex);
o.worldNormal  =al);
o.worldPos =mul(unity_ObjectToWorld, v.vertex).xyz;
TRANSFER_SHADOW(o);
return o;
}
float4 frag(v2f i): SV_Target {
fixed3 worldNormal =normalize(i.worldNormal);
fixed3 worldLightDir =normalize(UnityWorldSpaceLightDir(i.worldPos));
fixed3 worldViewDir =normalize(UnityWorldSpaceViewDir(i.worldPos));
fixed3 worldHalfDir =normalize(worldLightDir + worldViewDir);
fixed4 c = tex2D (_MainTex, i.uv);
fixed3 albedo = c.rgb * _b;//计算材质反射率
fixed3 ambient = UNITY_ * albedo;//计算环境光UNITY_LIGHT_ATTENUATION(atten, i, i.worldPos);//计算当前世界坐标下的阴影值
fixed diff =dot(worldNormal, worldLightDir);
//计算半兰伯特漫反射系数
diff =(diff *0.5+0.5)* atten;
//对渐变纹理_Ramp进⾏采样
fixed3 diffuse = _b * albedo *tex2D(_Ramp,float2(diff, diff)).rgb;
fixed spec =dot(worldNormal, worldHalfDir);
fixed w =fwidth(spec)*2.0;//抗锯齿处理
fixed3 specular = _b *lerp(0,1,smoothstep(-w, w, spec + _SpecularScale -1))*step(0.0001, _SpecularScale);
return fixed4(ambient + diffuse + specular,1.0);
}
ENDCG
}
}
FallBack "Diffuse"
}
3、代码⽣成描边物体
①动态⽣成:
在项⽬DynamicDrawWireFrameScene场景中有演⽰.

本文发布于:2024-09-22 11:32:31,感谢您对本站的认可!

本文链接:https://www.17tex.com/tex/1/167908.html

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。

标签:模型   描边   空间   计算   实现
留言与评论(共有 0 条评论)
   
验证码:
Copyright ©2019-2024 Comsenz Inc.Powered by © 易纺专利技术学习网 豫ICP备2022007602号 豫公网安备41160202000603 站长QQ:729038198 关于我们 投诉建议