Unity3D 布料系统 And Cloth Constraint 及 Mesh双面渲染

如何在Unity3D 实现布料旗帜的飘动效果呢?如下图:

在这里插入图片描述

一、布料系统的使用方法

1、添加Cloth组件
此处以plane作为例子。
在场景中生成plane平面后,添加组件Cloth,会出现Skinned Mesh Renderer和Cloth组件,如下图所示。

在这里插入图片描述
2、添加顶点,控制材质根据此点飘动

点击下图按钮打开编辑Cloth Constraint模式,

在这里插入图片描述
点击Select,选择其中一部分点作为顶点,可以直接点击黑点选择,按Shift可以多选,也可以用鼠标左键框选,如图:
(要想将当前有数值的顶点设置为Unconstrained(自由点), 只需要选中那些带有数值的顶点然后将对应复选框取消勾选即可)
在这里插入图片描述
选择部分黑点后,可以发现黑点变亮。勾选Max Distance前方的复选框。
在这里插入图片描述
运行,即可看到plane像布料一样在飘动,而选择的那些点是不动的。

二、Cloth布料系统的属性设置

在这里插入图片描述
翻译如下:

在这里插入图片描述
下面举几个最常使用的属性:

1、Use Gravity 重力

是否使用世界重力,勾选后,材质会随着重力下垂。

在这里插入图片描述

2、Damping 阻尼

阻尼会应用于每个布料顶点. 要想打造看上去抖动更小或更大的布料, 可以设置这个属性.在这里插入图片描述

3、布料的拉扯和弯曲程度

Stretching Stiffness: 拉扯硬度.
Bending Stiffness: 弯曲硬度.

4、Use Continuous Collision

使用Continuous Collision, 增加消耗, 减少直接穿透碰撞的几率,会增加系统开销。

5、添加碰撞体

Capsule Colliders: 要对布料产生交互的胶囊碰撞体。
Sphere Colliders: 要对布料产生交互的ClothSphereColliderPairs. 可以理解为他是按照一组来的, 一组中可以只有一个SphereCollider, 也可以有两个, 当有两个的时候, 那么这两个SphereCollider会在布料的碰撞系统中被”焊接”起来. 这样就允许通过两个大小不同的SphereCollider来组合成一个圆锥形状的碰撞体了。
至于碰撞体放在Cloth自生、子物体、外部都可以,根据需求来。

在这里插入图片描述

6、Cloth Unconstrained编辑面板

在这里插入图片描述

Max Distance可以设置每个顶点最大可移动距离. 最常用的用法是将不能动的顶点的Max Distance设置为0

Surface Penetration控制的是顶点最大可以嵌入到Mesh里面的程度. 在布料网格顶点比较稀疏的情况下可以明显对比出差别

Visualization这里能够选择当前在Scene视图中预览Max Distance还是Surface Penetration. (这两者二选一), 还能选择是否让操作影响视口背面的顶点

Select编辑模式要先通过框选, 或者Shift+点击来多选, 来选中顶点, 然后勾选Max Distance或者Surface Penetration前面的复选框, 代表我现在要改变选中的顶点的值了! 然后再在后面的数值里面输入想要的数值。

要想将当前有数值的顶点设置为Unconstrained, 只需要选中那些带有数值的顶点然后将对应复选框取消勾选即可。

三、使用布料系统的的注意事项

1、Cloth只能必须和Skinned Mesh Renderer搭配使用, 但是这不代表使用简单的物体时还必须在Max中导出一个带有蒙皮信息的FBX, 其实可以新建一个GameObject然后赋予Cloth组件, 这会自动添加Skinned Mesh Renderer组件, 然后在Skinned Mesh Renderer组件中赋予基本体的Mesh上去并且设置正确的材质也完全可以。布料可以接受外部影响,但完全不会将影响赋予外部刚体, 换句话说, 布料系统的物理模拟是单向的。

2、布不会对场景中的所有碰撞体做出反应,也不会将力施加到世界。 当它被添加时,布组件将不会反应或影响任何其他身体。 因此,布和世界不会相互识别或看到对方,直到你手动添加碰撞者从世界到布组件。 即使在那之后,模拟仍然是单向的:布料对这些物体做出反应,但不施加力。

3、您只能使用三种类型的碰撞器给Cloth:球体,胶囊和锥形胶囊碰撞,使用两个球碰撞器构造。 这些限制都有助于提高性能。

球体碰撞器数组可以包含单个有效的SphereCollider实例(第二个为空)或一对。在前一种情况下,ClothSphereColliderPair只代表一个单一的球体碰撞器,用于布料碰撞。在后一种情况下,它表示由两个球体限定的圆锥形胶囊形状,并且锥体连接两个球体。圆锥形胶囊形状对于模拟人物的肢体是有用的。

4、以后再补充 bulabulabula。。。

四、Shader双面材质渲染

由于Unity中要使用专用的双面显示的shader才能让模型单面片双面显示,所以需要修改Shader。

一、双面材质的模板分享

想直接下载双面材质模板可通过此链接:https://download.csdn.net/download/qq_43505432/13121760

导入unity后,直接拖动shader到指定的材质上,即可让单面材质变成双面。
在这里插入图片描述

二、制作双面材质的方法

1、简单双面相同材质

新建Shader文件或直接下载模板,用文本编辑器打开(Sublime Text、记事本等),复制以下代码,然后在unity中拖动此shader到指定的材质上,即可让单面材质变成双面。

此方法是在Shader代码中添加一个Cull off 语句,实现强制双面渲染。

Shader "Double Face/Bumped Specular" {
    
    
Properties {
    
    
	_Color ("Main Color", Color) = (1,1,1,1)
	_SpecColor ("Specular Color", Color) = (0.5, 0.5, 0.5, 1)
	_Shininess ("Shininess", Range (0.03, 1)) = 0.078125
	_MainTex ("Base (RGB) Gloss (A)", 2D) = "white" {
    
    }
	_BumpMap ("Normalmap", 2D) = "bump" {
    
    }
}
SubShader {
    
     
	Tags {
    
     "RenderType"="Opaque" }
	LOD 400
Cull Off	
CGPROGRAM
#pragma surface surf BlinnPhong

sampler2D _MainTex;
sampler2D _BumpMap;
float4 _Color;
float _Shininess;

struct Input {
    
    
	float2 uv_MainTex;
	float2 uv_BumpMap;
};

void surf (Input IN, inout SurfaceOutput o) {
    
    
	half4 tex = tex2D(_MainTex, IN.uv_MainTex);
	o.Albedo = tex.rgb * _Color.rgb;
	o.Gloss = tex.a;
	o.Alpha = tex.a * _Color.a;
	o.Specular = _Shininess;
	o.Normal = UnpackNormal(tex2D(_BumpMap, IN.uv_BumpMap));
}
ENDCG
}

FallBack "Specular"
}

2、双面不同效果材质

直接用Cull off的方式 有个重大的缺陷,这材质从两面看无论贴图、颜色、反光、照明情况,都是一模一样的,这并不符合大多数实际情况的常识。

如何做到双面不同效果呢?
前面说了Surface shader是不能写两个pass渲染不同面的,但其实surface方式可以写多个渲染过程,根本不需要pass的概念,Surface Shader可以这样写:

Call back 渲染正面的代码
Call front 渲染反面的代码

就可以实现双面不同的控制了。

根据这个原理,其实我们只要把系统内建shader的源代码复制一份,就能实现另一面不同效果了。

Shader "Hog's shaders/BumpSpec_Twoside" {
    
    
Properties {
    
    
//正面5个参数
     _Color ("Main Color", Color) = (1,1,1,1)
     _SpecColor ("Specular Color", Color) = (0.5, 0.5, 0.5, 1)
     _Shininess ("Shininess", Range (0.03, 1)) = 0.078125
     _MainTex ("Base (RGB) Gloss (A)", 2D) = "white" {
    
    }
     _BumpMap ("Normalmap", 2D) = "bump" {
    
    }
//反面拷贝 改名 也是5个
     _BackColor ("Back Main Color", Color) = (1,1,1,1)
     _BackSpecColor ("Back Specular Color", Color) = (0.5, 0.5, 0.5, 1)
     _BackShininess ("Back Shininess", Range (0.03, 1)) = 0.078125
     _BackMainTex ("Back Base (RGB) Gloss (A)", 2D) = "white" {
    
    }
     _BackBumpMap ("Back Normalmap", 2D) = "bump" {
    
    }
}
SubShader {
    
    
Tags {
    
     "RenderType"="Opaque" }
     LOD 400
     Cull back
//开始渲染正面   
CGPROGRAM
//表明是surface渲染方式 主渲染程序是surf 光照模型是BLinnPhong
#pragma surface surf BlinnPhong 
 
 
sampler2D _MainTex;
sampler2D _BumpMap;
fixed4 _Color;
half _Shininess;
 
struct Input {
    
    
     float2 uv_MainTex;
     float2 uv_BumpMap;
};
 
void surf (Input IN, inout SurfaceOutput o) {
    
    
     fixed4 tex = tex2D(_MainTex, IN.uv_MainTex);
     o.Albedo = tex.rgb * _Color.rgb;
     o.Gloss = tex.a;
     o.Alpha = tex.a * _Color.a;
     o.Specular = _Shininess;
     o.Normal = UnpackNormal(tex2D(_BumpMap, IN.uv_BumpMap));}
ENDCG
 
 
     Cull front
//开始渲染反面 其实和就是拷贝了一份正面渲染的代码 除了变量名要改   
CGPROGRAM
#pragma surface surf BlinnPhong
 
sampler2D _BackMainTex;
sampler2D _BackBumpMap;
fixed4 _BackColor;
half _BackShininess;
 
struct Input {
    
    
     float2 uv_BackMainTex;
     float2 uv_BackBumpMap;
};
 
void surf (Input IN, inout SurfaceOutput o) {
    
    
     fixed4 tex = tex2D(_BackMainTex, IN.uv_BackMainTex);
     o.Albedo = tex.rgb * _BackColor.rgb;
     o.Gloss = tex.a;
     o.Alpha = tex.a * _BackColor.a;
     o.Specular = _BackShininess;
     o.Normal = UnpackNormal(tex2D(_BackBumpMap, IN.uv_BackBumpMap));}
ENDCG
}
FallBack "Specular"
}

这是个双面可以分别指定的高光-凹凸材质,注意几个要点:

1、properties部分只能出现一次,所以这是不能直接拷贝的。因为要为双面指定不同的参数,双面的参数变量名肯定不能一样,这个论坛里都是程序猿,没必要多解释了。我简单的把用于正面的5个参数前面都加上了一个Back用于反面。

2、在CG代码内部也要对应的应用相应的参数,反面的渲染代码就用刚才全部加了Back的那5个参数。

3、正面代码段用Cull back 开始 反面的代码用Cull front开始。

4、一般不要动不动就使用双面材质,因为会增加系统负荷,应该只用在需要的地方。

猜你喜欢

转载自blog.csdn.net/qq_43505432/article/details/109735723