Unity-支持 DX11/OpenGL Core 曲面細(xì)分的表面著色器
表面著色器在一定程度上支持 DirectX 11/OpenGL Core GPU 曲面細(xì)分。具體情況為:
曲面細(xì)分由?
tessellate:FunctionName
?修改器聲明。該函數(shù)計(jì)算三角形的邊和內(nèi)部曲面細(xì)分因子。使用曲面細(xì)分時(shí),對于域著色器中的每個(gè)生成的頂點(diǎn),將在曲面細(xì)分_之后_調(diào)用“頂點(diǎn)修改器”(
vertex:FunctionName
)。這里通常要進(jìn)行置換貼圖。即使沒有任何位移貼圖,表面著色器也可以選擇計(jì)算?Phong 曲面細(xì)分來平滑模型表面。
對于曲面細(xì)分的支持目前存在以下局限性:
僅限于三角形域 - 不支持四邊形和等值線曲面細(xì)分。
使用曲面細(xì)分時(shí),著色器會(huì)自動(dòng)編譯到 Shader Model?4.6 target,即表示它僅在支持 DX11/12 OpenGL Core 和 PS4/XB1 的設(shè)備上正常工作。
在頂點(diǎn)修改器中不支持 GPU 曲面細(xì)分和位移
接下來這個(gè)示例中的表面著色器在_不_使用曲面細(xì)分的情況下執(zhí)行某種位移貼圖。它僅根據(jù)來自位移貼圖的數(shù)量沿著法線移動(dòng)頂點(diǎn):
? ?
Shader "Tessellation Sample" { ? ? ? ? ? ?
?Properties { ? ? ? ? ? ? ? ?
? ?_MainTex ("Base (RGB)", 2D) = "white" {} ? ? ? ? ? ? ? ?
? ?_DispTex ("Disp Texture", 2D) = "gray" {} ? ? ? ? ? ? ? ?
? ?_NormalMap ("Normalmap", 2D) = "bump" {} ? ? ? ? ? ? ? ?
? ?_Displacement ("Displacement", Range(0, 1.0)) = 0.3 ? ? ? ? ? ? ? ?
? ?_Color ("Color", color) = (1,1,1,0) ? ? ? ? ? ? ? ?
? ?_SpecColor ("Spec color", color) = (0.5,0.5,0.5,0.5) ? ? ? ? ? ?
?} ? ? ? ? ? ?
?SubShader { ? ? ? ? ? ? ? ?
? ?Tags { "RenderType"="Opaque" } ? ? ? ? ? ? ? ?
? ?LOD 300 ? ? ? ? ? ? ? ? ? ? ? ? ? ?
? ?CGPROGRAM ? ? ? ? ? ? ? ?
? ?#pragma surface surf BlinnPhong addshadow fullforwardshadows vertex:disp
? ?nolightmap ? ? ? ? ? ? ? ?
? ?#pragma target 4.6 ? ? ? ? ? ? ? ?
? ?struct appdata { ? ? ? ? ? ? ? ? ? ?
? ? ?float4 vertex : POSITION; ? ? ? ? ? ? ? ? ? ?
? ? ?float4 tangent : TANGENT; ? ? ? ? ? ? ? ? ? ?
? ? ?float3 normal : NORMAL; ? ? ? ? ? ? ? ? ? ?
? ? ?float2 texcoord : TEXCOORD0; ? ? ? ? ? ? ? ?
? ?}; ? ? ? ? ? ? ? ?
? ?sampler2D _DispTex; ? ? ? ? ? ? ? ?
? ?float _Displacement; ? ? ? ? ? ? ? ?
? ?void disp (inout appdata v){ ? ? ? ? ? ? ? ? ? ?
? ? ?float d = tex2Dlod(_DispTex, float4(v.texcoord.xy,0,0)).r * _Displacement;
? ? ?v.vertex.xyz += v.normal * d; ? ? ? ? ? ? ? ?
? ?} ? ? ? ? ? ? ? ?
? ?struct Input { ? ? ? ? ? ? ? ? ? ?
? ? ?float2 uv_MainTex; ? ? ? ? ? ? ? ?
? ?}; ? ? ? ? ? ? ? ?
? ?sampler2D _MainTex; ? ? ? ? ? ? ? ?
? ?sampler2D _NormalMap; ? ? ? ? ? ? ? ?
? ?fixed4 _Color; ? ? ? ? ? ? ? ?
? ?void surf (Input IN, inout SurfaceOutput o){ ? ? ? ? ? ? ? ? ? ?
? ? ?half4 c = tex2D (_MainTex, IN.uv_MainTex) * _Color
? ? ?o.Albedo = c.rgb; ? ? ? ? ? ? ? ? ? ?
? ? ?o.Specular = 0.2; ? ? ? ? ? ? ? ? ? ?
? ? ?o.Gloss = 1.0; ? ? ? ? ? ? ? ? ? ?
? ? ?o.Normal = UnpackNormal(tex2D(_NormalMap, IN.uv_MainTex));
? ?} ? ? ? ? ? ? ? ?
? ?ENDCG ? ? ? ? ? ?
?} ? ? ? ? ? ?
?FallBack "Diffuse" ? ? ? ?
}
以上著色器相當(dāng)標(biāo)準(zhǔn):
頂點(diǎn)修改器?
disp
?對位移貼圖進(jìn)行采樣并沿法線移動(dòng)頂點(diǎn)。它使用自定義的“頂點(diǎn)數(shù)據(jù)輸入”結(jié)構(gòu) (
appdata
),而不是默認(rèn)的?appdata_full
。目前這還不是必需的,但是使用盡可能小的結(jié)構(gòu)進(jìn)行曲面細(xì)分會(huì)更高效。由于我們的頂點(diǎn)數(shù)據(jù)沒有第二個(gè) UV 坐標(biāo),所以我們添加?
nolightmap
?指令來排除光照貼圖。
下圖顯示了應(yīng)用此著色器的一些簡單游戲?qū)ο蟆?/p>
固定量的曲面細(xì)分
如果模型的面在屏幕上的大小大致相同,則向網(wǎng)格添加固定量的曲面細(xì)分(整個(gè)網(wǎng)格上的曲面細(xì)分級(jí)別相同)。
以下示例腳本應(yīng)用了固定量的曲面細(xì)分。
? ?
Shader "Tessellation Sample" { ? ? ? ? ? ?
?Properties { ? ? ? ? ? ? ? ?
? ?_Tess ("Tessellation", Range(1,32)) = 4 ? ? ? ? ? ? ? ?
? ?_MainTex ("Base (RGB)", 2D) = "white" {} ? ? ? ? ? ? ? ?
? ?_DispTex ("Disp Texture", 2D) = "gray" {} ? ? ? ? ? ? ? ?
? ?_NormalMap ("Normalmap", 2D) = "bump" {} ? ? ? ? ? ? ? ?
? ?_Displacement ("Displacement", Range(0, 1.0)) = 0.3 ? ? ? ? ? ? ? ?
? ?_Color ("Color", color) = (1,1,1,0) ? ? ? ? ? ? ? ?
? ?_SpecColor ("Spec color", color) = (0.5,0.5,0.5,0.5) ? ? ? ? ? ?
?} ? ? ? ? ? ?
?SubShader { ? ? ? ? ? ? ? ?
? ?Tags { "RenderType"="Opaque" } ? ? ? ? ? ? ? ?
? ?LOD 300 ? ? ? ? ? ? ? ? ? ? ? ? ? ?
? ?CGPROGRAM ? ? ? ? ? ? ? ?
? ?#pragma surface surf BlinnPhong addshadow fullforwardshadows vertex:disp tessellate:tessFixed nolightmap ? ? ? ? ? ? ? ?
? ?#pragma target 4.6 ? ? ? ? ? ? ? ?
? ?struct appdata { ? ? ? ? ? ? ? ? ? ?
? ? ?float4 vertex : POSITION; ? ? ? ? ? ? ? ? ? ?
? ? ?float4 tangent : TANGENT; ? ? ? ? ? ? ? ? ? ?
? ? ?float3 normal : NORMAL; ? ? ? ? ? ? ? ? ? ?
? ? ?float2 texcoord : TEXCOORD0; ? ? ? ? ? ? ? ?
? ?}; ? ? ? ? ? ? ? ?
? ?float _Tess; ? ? ? ? ? ? ? ?
? ?float4 tessFixed() ? ? ? ? ? ? ? ?
? ?{ ? ? ? ? ? ? ? ? ? ?
? ? ?return _Tess; ? ? ? ? ? ? ? ?
? ?} ? ? ? ? ? ? ? ?
? ?sampler2D _DispTex; ? ? ? ? ? ? ? ?
? ?float _Displacement; ? ? ? ? ? ? ? ?
? ?void disp (inout appdata v) ? ? ? ? ? ? ? ?
? ?{ ? ? ? ? ? ? ? ? ? ?
? ? ?float d = tex2Dlod(_DispTex, float4(v.texcoord.xy,0,0)).r * _Displacement;
? ? ?v.vertex.xyz += v.normal * d; ? ? ? ? ? ? ? ?
? ?} ? ? ? ? ? ? ? ?
? ?struct Input { ? ? ? ? ? ? ? ? ? ?
? ? ?float2 uv_MainTex; ? ? ? ? ? ? ? ?
? ?}; ? ? ? ? ? ? ? ?
? ?sampler2D _MainTex; ? ? ? ? ? ? ? ?
? ?sampler2D _NormalMap; ? ? ? ? ? ? ? ?
? ?fixed4 _Color; ? ? ? ? ? ? ? ? ?
? ?void surf (Input IN, inout SurfaceOutput o) { ? ? ? ? ? ? ? ? ? ?
? ? ?half4 c = tex2D (_MainTex, IN.uv_MainTex) * _Color;
? ? ?o.Albedo = c.rgb; ? ? ? ? ? ? ? ? ? ?
? ? ?o.Specular = 0.2; ? ? ? ? ? ? ? ? ? ?
? ? ?o.Gloss = 1.0; ? ? ? ? ? ? ? ? ? ?
? ? ?o.Normal = UnpackNormal(tex2D(_NormalMap, IN.uv_MainTex));
? ?} ? ? ? ? ? ? ? ?
? ?ENDCG ? ? ? ? ? ?
?} ? ? ? ? ? ?
?FallBack "Diffuse" ? ? ? ?
}
在上面的例子中,tessFixed
?曲面細(xì)分函數(shù)以單個(gè) float4 值的形式返回四個(gè)曲面細(xì)分因子:三角形的每個(gè)邊一共三個(gè)因子,還有三角形內(nèi)部的一個(gè)因子。
該示例返回材質(zhì)屬性中設(shè)置的常量值。

基于距離的曲面細(xì)分
您還可以根據(jù)與攝像機(jī)之間的距離來更改曲面細(xì)分級(jí)別。 例如,可定義兩個(gè)距離值:
曲面細(xì)分處于最大值時(shí)的距離(例如,10 米)。
曲面細(xì)分級(jí)別遞減時(shí)的距離(例如,20 米)。
? ?
Shader "Tessellation Sample" { ? ? ? ? ? ?
?Properties { ? ? ? ? ? ? ? ?
? ?_Tess ("Tessellation", Range(1,32)) = 4 ? ? ? ? ? ? ? ?
? ?_MainTex ("Base (RGB)", 2D) = "white" {} ? ? ? ? ? ? ? ?
? ?_DispTex ("Disp Texture", 2D) = "gray" {} ? ? ? ? ? ? ? ?
? ?_NormalMap ("Normalmap", 2D) = "bump" {} ? ? ? ? ? ? ? ?
? ?_Displacement ("Displacement", Range(0, 1.0)) = 0.3 ? ? ? ? ? ? ? ?
? ?_Color ("Color", color) = (1,1,1,0) ? ? ? ? ? ? ? ?
? ?_SpecColor ("Spec color", color) = (0.5,0.5,0.5,0.5) ? ? ? ? ? ?
?} ? ? ? ? ? ?
?SubShader { ? ? ? ? ? ? ? ?
? ?Tags { "RenderType"="Opaque" } ? ? ? ? ? ? ? ?
? ?LOD 300 ? ? ? ? ? ? ? ? ? ? ? ? ? ?
? ?CGPROGRAM ? ? ? ? ? ? ? ?
? ?#pragma surface surf BlinnPhong addshadow fullforwardshadows vertex:disp tessellate:tessDistance nolightmap ? ? ? ? ? ? ? ?
? ?#pragma target 4.6 ? ? ? ? ? ? ? ?
? ?#include "Tessellation.cginc" ? ? ? ? ? ? ? ?
? ?struct appdata { ? ? ? ? ? ? ? ? ? ?
? ? ?float4 vertex : POSITION; ? ? ? ? ? ? ? ? ? ?
? ? ?float4 tangent : TANGENT; ? ? ? ? ? ? ? ? ? ?
? ? ?float3 normal : NORMAL; ? ? ? ? ? ? ? ? ? ?
? ? ?float2 texcoord : TEXCOORD0; ? ? ? ? ? ? ? ?
? ?}; ? ? ? ? ? ? ? ?
? ?float _Tess; ? ? ? ? ? ? ? ?
? ?float4 tessDistance (appdata v0, appdata v1, appdata v2) {
? ? ?float minDist = 10.0; ? ? ? ? ? ? ? ? ? ?
? ? ?float maxDist = 25.0; ? ? ? ? ? ? ? ? ? ?
? ? ?return UnityDistanceBasedTess(v0.vertex, v1.vertex, v2.vertex, minDist, maxDist, _Tess); ? ? ? ? ? ? ? ?
? ?} ? ? ? ? ? ? ? ?
? ?sampler2D _DispTex; ? ? ? ? ? ? ? ?
? ?float _Displacement; ? ? ? ? ? ? ? ?
? ?void disp (inout appdata v) ? ? ? ? ? ? ? ?
? ?{ ? ? ? ? ? ? ? ? ? ?
? ? ?float d = tex2Dlod(_DispTex, float4(v.texcoord.xy,0,0)).r * _Displacement; ? ?
? ? ?v.vertex.xyz += v.normal * d; ? ? ? ? ? ? ? ?
? ?} ? ? ? ? ? ? ? ?
? ?struct Input { ? ? ? ? ? ? ? ? ? ?
? ? ?float2 uv_MainTex; ? ? ? ? ? ? ? ?
? ?}; ? ? ? ? ? ? ? ?
? ?sampler2D _MainTex; ? ? ? ? ? ? ? ?
? ?sampler2D _NormalMap; ? ? ? ? ? ? ? ?
? ?fixed4 _Color; ? ? ? ? ? ? ? ?
? ?void surf (Input IN, inout SurfaceOutput o) { ? ? ? ? ? ? ? ? ? ?
? ? ?half4 c = tex2D (_MainTex, IN.uv_MainTex) * _Color;
? ? ?o.Albedo = c.rgb; ? ? ? ? ? ? ? ? ? ?
? ? ?o.Specular = 0.2; ? ? ? ? ? ? ? ? ? ?
? ? ?o.Gloss = 1.0; ? ? ? ? ? ? ? ? ? ?
? ? ?o.Normal = UnpackNormal(tex2D(_NormalMap, IN.uv_MainTex));
? ?} ? ? ? ? ? ? ? ?
? ?ENDCG ? ? ? ? ? ?
?} ? ? ? ? ? ?
?FallBack "Diffuse" ? ? ?
}
這里,曲面細(xì)分函數(shù)在曲面細(xì)分之前將三角形三個(gè)角的頂點(diǎn)數(shù)據(jù)作為其三個(gè)參數(shù)。
Unity 需要此數(shù)據(jù)來計(jì)算曲面細(xì)分級(jí)別,而這取決于頂點(diǎn)位置。
該示例包含一個(gè)內(nèi)置的 helper 文件 Tessellation.cginc,并從該文件中調(diào)用?UnityDistanceBasedTess
?函數(shù)來完成所有工作。此函數(shù)計(jì)算每個(gè)頂點(diǎn)到攝像機(jī)的距離,并推導(dǎo)出最終的曲面細(xì)分因子。

基于邊長的曲面細(xì)分
純粹基于距離的曲面細(xì)分僅在三角形大小非常相似時(shí)才能起到有效的作用。在上圖中,具有小三角形的游戲?qū)ο蟊贿^度曲面細(xì)分,而具有大三角形的游戲?qū)ο髣t曲面細(xì)分不足。
一種改善方法是根據(jù)屏幕上的三角形邊長來計(jì)算曲面細(xì)分級(jí)別。Unity 應(yīng)該將更大的細(xì)分因子應(yīng)用于更長的邊。
? ?
Shader "Tessellation Sample" { ? ? ? ? ? ?
?Properties { ? ? ? ? ? ? ? ?
? ?_EdgeLength ("Edge length", Range(2,50)) = 15 ? ? ? ? ? ? ? ?
? ?_MainTex ("Base (RGB)", 2D) = "white" {} ? ? ? ? ? ? ? ?
? ?_DispTex ("Disp Texture", 2D) = "gray" {} ? ? ? ? ? ? ? ?
? ?_NormalMap ("Normalmap", 2D) = "bump" {} ? ? ? ? ? ? ? ?
? ?_Displacement ("Displacement", Range(0, 1.0)) = 0.3 ? ? ? ? ? ? ? ?
? ?_Color ("Color", color) = (1,1,1,0) ? ? ? ? ? ? ? ?
? ?_SpecColor ("Spec color", color) = (0.5,0.5,0.5,0.5) ? ? ? ? ? ?
?} ? ? ? ? ? ?
?SubShader { ? ? ? ? ? ? ? ?
? ?Tags { "RenderType"="Opaque" } ? ? ? ? ? ? ? ?
? ?LOD 300 ? ? ? ? ? ? ? ? ? ? ? ? ? ?
? ?CGPROGRAM ? ? ? ? ? ? ? ?
? ?#pragma surface surf BlinnPhong addshadow fullforwardshadows vertex:disp tessellate:tessEdge nolightmap ? ? ? ? ? ? ? ?
? ?#pragma target 4.6 ? ? ? ? ? ? ? ?
? ?#include "Tessellation.cginc" ? ? ? ? ? ? ? ?
? ?struct appdata { ? ? ? ? ? ? ? ? ? ?
? ? ?float4 vertex : POSITION; ? ? ? ? ? ? ? ? ? ?
? ? ?float4 tangent : TANGENT; ? ? ? ? ? ? ? ? ? ?
? ? ?float3 normal : NORMAL; ? ? ? ? ? ? ? ? ? ?
? ? ?float2 texcoord : TEXCOORD0; ? ? ? ? ? ? ? ?
? ?}; ? ? ? ? ? ? ? ?
? ?float _EdgeLength; ? ? ? ? ? ? ? ?
? ?float4 tessEdge (appdata v0, appdata v1, appdata v2) ? ? ? ? ? ? ? ?
? ?{ ? ? ? ? ? ? ? ? ? ?
? ? ?return UnityEdgeLengthBasedTess (v0.vertex, v1.vertex, v2.vertex, _EdgeLength); ? ? ? ? ? ? ? ?
? ?} ? ? ? ? ? ? ? ?
? ?sampler2D _DispTex; ? ? ? ? ? ? ? ?
? ?float _Displacement; ? ? ? ? ? ? ? ?
? ?void disp (inout appdata v) ? ? ? ? ? ? ? ?
? ?{ ? ? ? ? ? ? ? ? ? ?
? ? ?float d = tex2Dlod(_DispTex, float4(v.texcoord.xy,0,0)).r * _Displacement; ? ?
? ? ?v.vertex.xyz += v.normal * d; ? ? ? ? ? ? ? ?
? ?} ? ? ? ? ? ? ? ?
? ?struct Input { ? ? ? ? ? ? ? ? ? ?
? ? ?float2 uv_MainTex; ? ? ? ? ? ? ? ?
? ?}; ? ? ? ? ? ? ? ?
? ?sampler2D _MainTex; ? ? ? ? ? ? ? ?
? ?sampler2D _NormalMap; ? ? ? ? ? ? ? ?
? ?fixed4 _Color; ? ? ? ? ? ? ? ?
? ?void surf (Input IN, inout SurfaceOutput o) { ? ? ? ? ? ? ? ? ? ?
? ? ?half4 c = tex2D (_MainTex, IN.uv_MainTex) * _Color; ? ? ? ? ? ? ? ? ? ?
? ? ?o.Albedo = c.rgb; ? ? ? ? ? ? ? ? ? ?
? ? ?o.Specular = 0.2; ? ? ? ? ? ? ? ? ? ?
? ? ?o.Gloss = 1.0; ? ? ? ? ? ? ? ? ? ?
? ? ?o.Normal = UnpackNormal(tex2D(_NormalMap, IN.uv_MainTex));
? ?} ? ? ? ? ? ? ? ?
? ?ENDCG ? ? ? ? ? ?
?} ? ? ? ? ? ?
?FallBack "Diffuse" ? ? ? ?
}
在此示例中,從?Tessellation.cginc?調(diào)用?UnityEdgeLengthBasedTess
?函數(shù)來完成所有工作。
出于性能原因,請改為調(diào)用 UnityEdgeLengthBasedTessCull 函數(shù),該函數(shù)將執(zhí)行樣條曲線視錐體剔除。這會(huì)使著色器的成本略微提高,但為攝像機(jī)視圖之外的網(wǎng)格部分節(jié)省了大量 GPU 工作。
Phong 曲面細(xì)分
Phong 曲面細(xì)分將修改細(xì)分面的位置,使得生成的表面稍微跟隨網(wǎng)格法線。這是使簡單多邊形網(wǎng)格變得更加平滑的一種非常有效的方法。
Unity 的表面著色器可以使用?tessphong:VariableName
?編譯指令自動(dòng)計(jì)算 Phong 曲面細(xì)分。下面是著色器示例:
? ?
Shader "Phong Tessellation" { ? ? ? ? ? ?
?Properties { ? ? ? ? ? ? ? ?
? ?_EdgeLength ("Edge length", Range(2,50)) = 5 ? ? ? ? ? ? ? ?
? ?_Phong ("Phong Strengh", Range(0,1)) = 0.5 ? ? ? ? ? ? ? ?
? ?_MainTex ("Base (RGB)", 2D) = "white" {} ? ? ? ? ? ? ? ?
? ?_Color ("Color", color) = (1,1,1,0) ? ? ? ? ? ?
?} ? ? ? ? ? ?
?SubShader { ? ? ? ? ? ? ? ?
? ?Tags { "RenderType"="Opaque" } ? ? ? ? ? ? ? ?
? ?LOD 300 ? ? ? ? ? ? ? ? ? ? ? ? ? ?
? ?CGPROGRAM ? ? ? ? ? ? ? ?
? ?#pragma surface surf Lambert vertex:dispNone tessellate:tessEdge tessphong:_Phong nolightmap ? ? ? ? ? ? ? ?
? ?#include "Tessellation.cginc" ? ? ? ? ? ? ? ?
? ?struct appdata { ? ? ? ? ? ? ? ? ? ?
? ? ?float4 vertex : POSITION; ? ? ? ? ? ? ? ? ? ?
? ? ?float3 normal : NORMAL; ? ? ? ? ? ? ? ? ? ?
? ? ?float2 texcoord : TEXCOORD0; ? ? ? ? ? ? ? ?
? ?}; ? ? ? ? ? ? ? ?
? ?void dispNone (inout appdata v) { } ? ? ? ? ? ? ? ?
? ?float _Phong; ? ? ? ? ? ? ? ?
? ?float _EdgeLength; ? ? ? ? ? ? ? ?
? ?float4 tessEdge (appdata v0, appdata v1, appdata v2) ? ? ? ? ? ? ? ?
? ?{ ? ? ? ? ? ? ? ? ? ?
? ? ?return UnityEdgeLengthBasedTess (v0.vertex, v1.vertex, v2.vertex, _EdgeLength);
? ?} ? ? ? ? ? ? ? ?
? ?struct Input { ? ? ? ? ? ? ? ? ? ?
? ? ?float2 uv_MainTex; ? ? ? ? ? ? ? ?
? ?}; ? ? ? ? ? ? ? ?
? ?fixed4 _Color; ? ? ? ? ? ? ? ?
? ?sampler2D _MainTex; ? ? ? ? ? ? ? ?
? ?void surf (Input IN, inout SurfaceOutput o) { ? ? ? ? ? ? ? ? ? ?
? ? ?half4 c = tex2D (_MainTex, IN.uv_MainTex) * _Color;
? ? ?o.Albedo = c.rgb; ? ? ? ? ? ? ? ? ? ?
? ? ?o.Alpha = c.a; ? ? ? ? ? ? ? ?
? ?} ? ? ? ? ? ? ? ?
? ?ENDCG ? ? ? ? ? ?
?} ? ? ? ? ? ?
?FallBack "Diffuse" ? ? ? ?
}
以下是常規(guī)著色器(上排)和使用 Phong 曲面細(xì)分的著色器(下排)之間的比較??梢钥闯?,即使沒有任何位移貼圖,表面也會(huì)變得更圓。
