Unity中通常使用兩種方法來(lái)實(shí)現(xiàn)透明效果:第一種是試用透明度測(cè)試(Alpha Test),這種方法其實(shí)無(wú)法得到真正的半透明效果;另一種是透明度混合(Alpha Blending)。
由于深度緩沖的存在,可以讓不透明物體不考慮他們渲染順序也能得到正確的排序效果。但是實(shí)現(xiàn)透明效果需要關(guān)閉深度寫(xiě)入(ZWrite)。
透明度測(cè)試不需要關(guān)閉深度寫(xiě)入,它和其他不透明物體最大的不同就是他會(huì)根據(jù)透明度來(lái)舍棄一些片元。原理簡(jiǎn)單但是很極端,要么完全透明,看不到,要么完全不透明。
透明度混合需要關(guān)閉深度寫(xiě)入,不關(guān)閉深度測(cè)試。
對(duì)于透明度混合來(lái)說(shuō),深度緩沖是只讀的。
可以得到真正的半透明效果。
會(huì)使用當(dāng)前片元的透明度作為混合因子,與已經(jīng)存儲(chǔ)在顏色緩沖區(qū)中的顏色值進(jìn)行混合,得到新的顏色。
為什么渲染順序很重要
比如渲染距離較遠(yuǎn)的一個(gè)不透明物體和距離較近的一個(gè)半透明物體,如果先渲染半透明的物體,不透明物體會(huì)直接覆蓋顏色,出現(xiàn)視覺(jué)錯(cuò)誤。
兩個(gè)半透明物體也是需要順序的。如果兩個(gè)半透明物體A較近 B較遠(yuǎn),如果先渲染A在渲染B,混合結(jié)果也會(huì)反過(guò)來(lái),得到錯(cuò)誤的半透明結(jié)構(gòu)。
但總有一些情況很特殊 比如循環(huán)重疊 或者深度相同,為了減少錯(cuò)誤排序的情況,盡可能拆分子模型或者讓模型是凸面體。
擴(kuò)展博文:圖形學(xué)基礎(chǔ)|深度緩沖
Unity Shader的渲染順序
Unity內(nèi)部使用了一系列整數(shù)索引來(lái)表示每個(gè)渲染隊(duì)列,且索引號(hào)越小表示越早被渲染。
名稱(chēng) | 隊(duì)列索引號(hào) | 描述 |
---|---|---|
Background | 1000 | 這個(gè)渲染隊(duì)列會(huì)在任何其他隊(duì)列之前被渲染,我們通常使用該隊(duì)列來(lái)渲染那些需要繪制在背景上的物體 |
Geometry | 2000 | 默認(rèn)的渲染隊(duì)列,大多數(shù)物體都使用這個(gè)隊(duì)列。不透明物體使用這個(gè)隊(duì)列 |
AlphaTest | 2450 | 需要透明度測(cè)試的物體使用這個(gè)隊(duì)列。在Unity 5中它從Geometry隊(duì)列中被單獨(dú)分出來(lái),這是因?yàn)樵谒胁煌该魑矬w渲染之后再渲染他們會(huì)更加高效。 |
Transparent | 3000 | 這個(gè)隊(duì)列中的物體會(huì)在所有Geometry和AlphaTest物體渲染后,再按從后往前的順序進(jìn)行渲染。任何使用了透明度混合(例如關(guān)閉了深度寫(xiě)入的Shader)的物體都應(yīng)該使用該隊(duì)列 |
Overlay | 4000 | 該隊(duì)列用于實(shí)現(xiàn)一些疊加效果。任何需要在最后渲染的物體都應(yīng)該使用該隊(duì)列。 |
想通過(guò)透明度測(cè)試實(shí)現(xiàn)透明效果,應(yīng)包含類(lèi)似代碼:
SubShader {
Tags{ "Queue" = "AlphaTest"}
Pass{...}
}
想通過(guò)透明度混合實(shí)現(xiàn)透明效果,應(yīng)包含類(lèi)似代碼:
SubShader {
Tags{ "Queue" = "Transparent"}
Pass{
ZWrite Off//關(guān)閉深度寫(xiě)入
...}
}
透明度測(cè)試
通常會(huì)在片元著色器中進(jìn)行透明度測(cè)試
clip是Cg中的一個(gè)函數(shù)
函數(shù):void clip(float4 x) | void clip(float3 x) | void clip(float2 x) | void clip(float1 x) | void clip(float x)
參數(shù):裁剪時(shí)使用的標(biāo)量或矢量條件
描述:如果給定參數(shù)的任何一個(gè)分量是負(fù)數(shù),就會(huì)舍棄當(dāng)前像素的輸出顏色。
Shader "Custom/AlphaTestShader"
{
Properties
{
_Color ("Main Tint", Color) = (1,1,1,1)
_MainTex ("Main Tex", 2D) = "white" {}
_Cutoff ("Alpha Cutoff", Range(0, 1)) = 0.5//決定調(diào)用clip進(jìn)行透明度測(cè)試時(shí)使用的判斷條件 范圍0-1
}
SubShader
{
Pass
{
//通常使用了透明度測(cè)試的shader都應(yīng)該在subshader中設(shè)置這三個(gè)標(biāo)簽
//設(shè)置隊(duì)列為透明度測(cè)試 shader不會(huì)受到投影器的影響 rendertype標(biāo)簽可以讓Unity把這個(gè)shader歸入提前定義的組
Tags{"Queue" = "AlphaTest" "IgnoreProjector" = "True" "RenderType" = "TransparentCutout"}
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "Lighting.cginc"
fixed4 _Color;
sampler2D _MainTex;
float4 _MainTex_ST;
float _Cutoff;
struct a2v
{
float4 vertex : POSITION;
float3 normal : NORMAL;
float4 texcoord : TEXCOORD0;
};
struct v2f
{
float4 pos : SV_POSITION;
float3 worldNormal : TEXCOORD0;
float3 worldPos : TEXCOORD1;
float2 uv : TEXCOORD2;
};
v2f vert(a2v v)
{
v2f o;
o.pos = UnityObjectToClipPos(v.vertex);
o.worldNormal = UnityObjectToWorldNormal(v.normal);
o.worldPos = mul(unity_ObjectToWorld,v.vertex).xyz;
o.uv = TRANSFORM_TEX(v.texcoord,_MainTex);
return o;
}
fixed4 frag(v2f i) : SV_Target
{
fixed3 worldNormal = normalize(i.worldNormal);
fixed3 worldLightDir = normalize(UnityWorldSpaceLightDir(i.worldPos));
fixed4 texColor = tex2D(_MainTex,i.uv);
clip(texColor.a - _Cutoff);//相當(dāng)于↓
//if ((texColor.a - _Cutoff) < 0.0)
//{
// discard
//}
fixed3 albedo = texColor.rgb * _Color.rgb;
fixed3 ambient = UNITY_LIGHTMODEL_AMBIENT * albedo;
fixed3 diffuse = _LightColor0.rgb * albedo * max(0,dot(worldNormal,worldLightDir));
return fixed4(ambient + diffuse,1.0);
}
ENDCG
}
}
FallBack "Transparent/Cutout/VertexLit"
}
透明度混合
為了進(jìn)行混合,我們需要使用Unity提供的混合命令——Blend。Blend是Unity提供的設(shè)置混合模式的命令?;旌蠒r(shí)使用的函數(shù)就是由該指令決定的
語(yǔ)義 | 描述 |
---|---|
Blend Off | 關(guān)閉混合 |
Blend SrcFactor DstFactor | 開(kāi)啟混合,并設(shè)置混合因子。源顏色(該片元產(chǎn)生的顏色)會(huì)乘以SrcFactor,而目標(biāo)顏色(已經(jīng)存在于顏色緩存的顏色)會(huì)乘以DstFactor,然后把兩者相加后再存入顏色緩沖中。 |
Blend SrcFactor DstFactor, SrcFactorA DstFactorA | 和上面幾乎一樣,只是使用不同的因子來(lái)混合透明通道 |
BlendOp BlendOperation | 并非是吧源顏色和目標(biāo)顏色簡(jiǎn)單相加后混合,而是使用BlendOperation對(duì)它們進(jìn)行其他操作 |
只有開(kāi)啟混合模式之后,設(shè)置片元的透明通道才有意義,而Unity在我們使用Blend命令式會(huì)自動(dòng)幫我們打開(kāi)。
我們會(huì)把源顏色的混合因子SrcFactor設(shè)為SrcAlpha,而目標(biāo)顏色的混合因子DstFactor設(shè)為OneMinusSrcAlpha混合后新顏色 = ArcAlpha x SrcColor + (1 - SrcAlpha) x 混合前顏色
Shader "Custom/AlphaBlendShader"
{
Properties
{
_Color ("Main Tint", Color) = (1,1,1,1)
_MainTex ("Main Tex", 2D) = "white" {}
_AlphaScale("Alpha Scale", Range(0,1)) = 1
}
SubShader
{
Pass
{
Tags{"Queue" = "Transparent" "IgnoreProjector" = "True" "RenderType" = "Transparent"}
ZWrite Off//關(guān)閉深度寫(xiě)入
Blend SrcAlpha OneMinusSrcAlpha//將源顏色的混合因子設(shè)為SrcAlpha 目標(biāo)顏色的混合因子設(shè)為OneMinusSrcAlpha
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "Lighting.cginc"
fixed4 _Color;
sampler2D _MainTex;
float4 _MainTex_ST;
fixed _AlphaScale;
struct a2v
{
float4 vertex : POSITION;
float3 normal : NORMAL;
float4 texcoord : TEXCOORD0;
};
struct v2f
{
float4 pos : SV_POSITION;
float3 worldNormal : TEXCOORD0;
float3 worldPos : TEXCOORD1;
float2 uv : TEXCOORD2;
};
v2f vert(a2v v)
{
v2f o;
o.pos = UnityObjectToClipPos(v.vertex);
o.worldNormal = UnityObjectToWorldNormal(v.normal);
o.worldPos = mul(unity_ObjectToWorld,v.vertex).xyz;
o.uv = TRANSFORM_TEX(v.texcoord,_MainTex);
return o;
}
fixed4 frag(v2f i) : SV_Target
{
fixed3 worldNormal = normalize(i.worldNormal);
fixed3 worldLightDir = normalize(UnityWorldSpaceLightDir(i.worldPos));
fixed4 texColor = tex2D(_MainTex,i.uv);
fixed3 albedo = texColor.rgb * _Color.rgb;
fixed3 ambient = UNITY_LIGHTMODEL_AMBIENT * albedo;
fixed3 diffuse = _LightColor0.rgb * albedo * max(0,dot(worldNormal,worldLightDir));
return fixed4(ambient + diffuse,texColor.a * _AlphaScale);//設(shè)置透明通道
}
ENDCG
}
}
FallBack "Transparent/VertexLit"
}
開(kāi)啟深度寫(xiě)入的半透明效果
在面對(duì)復(fù)雜遮擋關(guān)系的模型師,會(huì)有各種因?yàn)榕判蝈e(cuò)誤而產(chǎn)生的透明效果。這都是因?yàn)殛P(guān)閉了深度寫(xiě)入而造成的。
一種解決方法是使用兩個(gè)Pass來(lái)渲染模型
第一個(gè)Pass開(kāi)啟深度寫(xiě)入,但不輸出顏色,目的僅僅是為了把該模型的深度值寫(xiě)入深度緩存中
第二個(gè)Pass進(jìn)行正常的透明度混合,由于上一個(gè)Pass已經(jīng)得到了逐像素的正確的深度信息,該P(yáng)ass就可以按照像素級(jí)別的深度排序結(jié)果進(jìn)行透明渲染。
但缺點(diǎn)是,多使用一個(gè)Pass會(huì)對(duì)性能造成一定的影響。
Pass { //新增 Pass
ZWrite On //開(kāi)啟深度寫(xiě)入
ColorMask 0 //Pass不寫(xiě)入任何顏色通道,即不輸出任何顏色。
}
這個(gè)新增Pass的目的僅為了把模型的深度信息寫(xiě)入深度緩沖中,從而剔除模型中被自身遮擋的片元。
ColorMask用于設(shè)置顏色通道的寫(xiě)掩碼(write mask)
ColorMask RGB | A | 0 | 任何其他的RGB的組合
ShaderLab 的混合命令
混合是如何實(shí)現(xiàn)的:
當(dāng)片元著色器產(chǎn)生一個(gè)顏色的時(shí)候,可以選擇與顏色緩存中的顏色進(jìn)行混合。這樣混合就和兩個(gè)操作數(shù)有關(guān):源顏色(source colo) 和 目標(biāo)顏色(destination color)。源顏色S,指的是由片元著色器產(chǎn)生的顏色;目標(biāo)顏色D,指的是從顏色緩沖中讀取到的顏色值。對(duì)它們進(jìn)行混合后得到的輸出顏色O,會(huì)重新寫(xiě)入到顏色緩沖中。需要注意的是源顏色目標(biāo)顏色和輸出顏色都包含了RGBA四個(gè)通道的值。
混合等式和參數(shù)
混合是一個(gè)逐片元操作,是不可編程但可高度配置的。
ShaderLab中設(shè)置混合因子的命令
命令 | 描述 |
---|---|
Blend SrcFactor DstFactor | 開(kāi)啟混合,并設(shè)置混合因子。源顏色(該片元產(chǎn)生的顏色)會(huì)乘以SrcFactor,而目標(biāo)顏色(已經(jīng)存在于顏色緩存的顏色)會(huì)乘以DstFactor,然后把兩者相加后在存入顏色緩沖中 |
Blend SrcFactor DstFactor, SrcFactorA DstFactorA | 和上面幾乎一樣,只是使用不同的因子來(lái)混合透明通道 |
加法混合公式O(rgb) = SrcFactor x S(rgb) + DstFactor x D(rgb)
O(a) = SrcFactor x S(a) + DstFactorA x D(a)
ShaderLab中的混合因子
參數(shù) | 描述 |
---|---|
One | 因子為1 |
Zero | 因子為0 |
SrcColor | 因子為源顏色值。當(dāng)用于混合RGB的混合等式時(shí),使用SrcColor的RGB分量作為混合因子;當(dāng)用于混合A的混合等式時(shí),使用SrcColor的A分量作為混合因子 |
SrcAlpha | 因子為源顏色的透明度值(A通道) |
DstColor | 因子為目標(biāo)顏色值。當(dāng)用于混合RGB的混合等式時(shí),使用DstColor的RGB分量作為混合因子;當(dāng)用于混合A的混合等式時(shí),使用DstColor的A分量作為混合因子 |
DestAlpha | 因子為目標(biāo)顏色的透明度值(A通道) |
OneMinusSrcColor | 因子為(1-源顏色)。當(dāng)用于混合RGB的混合等式時(shí),使用結(jié)果的RGB分量作為混合因子;當(dāng)用于混合A的混合等式時(shí),使用結(jié)果的A分量作為混合因子 |
OneMinusSrcAlpha | 因子為(1-源顏色的透明度值) |
OneMinusDstColor | 因子為(1-目標(biāo)顏色)。當(dāng)用于混合RGB的混合等式時(shí),使用結(jié)果的RGB分量作為混合因子;當(dāng)用于混合A的混合等式時(shí),使用結(jié)果的A分量作為混合因子 |
OneMinusDstAlpha | 因子為(1-目標(biāo)顏色的透明度值) |
例如:想要在混合后,輸出顏色的透明度值就是源顏色的透明度Blend SrcAlpha OneMinusSrcAlpha, One Zero
(代入公式前面x1后面x0 就是源顏色)
混合操作
BlendOp BlendOperation
ShaderLab中的混合操作
操作 | 描述 |
---|---|
Add | 將源和目標(biāo)相加。 |
Sub | 從源減去目標(biāo)。 |
RevSub | 從目標(biāo)減去源。 |
Min | 使用源和目標(biāo)中的較小者。 |
Max | 使用源和目標(biāo)中的較大者。 |
其他邏輯操作 | 僅在Direct11.1中支持 |
常見(jiàn)的混合類(lèi)型
//正常(Normal),即透明度混合
Blend SrcAlpha OneMinusSrcAlpha
//柔和相加(Soft Additive)
Blend OneMinusDstColor One
//正片疊底(Multiply),即相乘
Blend DstColor Zero
//兩倍相乘(2x Multiply)
Blend DstColor SrcColor
//變暗(Darken)
BlendOp Win
Blend One One
//變亮(Lighten)
BlendOp Max
Blend One One
//濾色(Screen)
Blend OneMinusDstColor One
//等同于
Blend One OneMinusSrcColor
//線性減淡(Linear Dodge)
Blend One One
雖然有些混合模式并沒(méi)有設(shè)置混合操作的種類(lèi),但是他們默認(rèn)就是使用加法操作,相當(dāng)于設(shè)置了BlendOp Add。
Shader "Unity Shaders Book/Chapter 8/Blend Operations 1" {
Properties {
_Color ("Color Tint", Color) = (1, 1, 1, 1)
_MainTex ("Main Tex", 2D) = "white" {}
_AlphaScale ("Alpha Scale", Range(0, 1)) = 1
}
SubShader {
Tags {"Queue"="Transparent" "IgnoreProjector"="True" "RenderType"="Transparent"}
Pass {
Tags { "LightMode"="ForwardBase" }
ZWrite Off
// // Normal
// Blend SrcAlpha OneMinusSrcAlpha
//
// // Soft Additive
// Blend OneMinusDstColor One
//
// // Multiply
Blend DstColor Zero
//
// // 2x Multiply
// Blend DstColor SrcColor
//
// // Darken
// BlendOp Min
// Blend One One // When using Min operation, these factors are ignored
//
// // Lighten
// BlendOp Max
// Blend One One // When using Max operation, these factors are ignored
//
// // Screen
// Blend OneMinusDstColor One
// Or
// Blend One OneMinusSrcColor
//
// // Linear Dodge
Blend One One
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "Lighting.cginc"
fixed4 _Color;
sampler2D _MainTex;
float4 _MainTex_ST;
fixed _AlphaScale;
struct a2v {
float4 vertex : POSITION;
float3 normal : NORMAL;
float4 texcoord : TEXCOORD0;
};
struct v2f {
float4 pos : SV_POSITION;
float2 uv : TEXCOORD0;
};
v2f vert(a2v v) {
v2f o;
o.pos = UnityObjectToClipPos(v.vertex);
o.uv = TRANSFORM_TEX(v.texcoord, _MainTex);
return o;
}
fixed4 frag(v2f i) : SV_Target {
fixed4 texColor = tex2D(_MainTex, i.uv);
return fixed4(texColor.rgb * _Color.rgb, texColor.a * _AlphaScale);
}
ENDCG
}
}
FallBack "Transparent/VertexLit"
}
雙面渲染的透明效果
使用 Cull 指令來(lái)控制需要剔除哪個(gè)面得渲染圖元
Untiy中Cull指令的語(yǔ)法:Cull Back | Front | Off
Back:是默認(rèn)狀態(tài)。背對(duì)著攝像機(jī)的圖元不會(huì)被渲染。
Front:朝向攝像機(jī)的渲染圖元不會(huì)被渲染。
Off:關(guān)閉剔除功能,渲染所有圖元,通常不關(guān)閉。
透明度測(cè)試的雙面渲染
只需在Pass中添加一句Cull Off
透明度混合的雙面渲染
因?yàn)殛P(guān)閉了深度寫(xiě)入,需要謹(jǐn)慎控制渲染順序。但如直接關(guān)閉剔除功能,那我們就無(wú)法保證同一個(gè)物體的正面和背面的渲染順序,就有可能得到錯(cuò)誤的半透明效果。
對(duì)此我們選擇把雙面渲染順序的工作分成兩個(gè)Pass——第一個(gè)Pass只渲染背面,第二個(gè)Pass只渲染正面。由于Unity會(huì)順序執(zhí)行SubShader中的各個(gè)Pass,因此可以保證背面總是在正面之前被渲染,借此用來(lái)保證正確的深度渲染關(guān)系。文章來(lái)源:http://www.zghlxwxcb.cn/news/detail-726527.html
Shader "Custom/AlphaTestBothSidedShader"
{
Properties
{
_Color ("Main Tint", Color) = (1,1,1,1)
_MainTex ("Main Tex", 2D) = "white" {}
_AlphaScale("Alpha Scale", Range(0,1)) = 1
}
SubShader
{
Tags{"Queue" = "Transparent" "IgnoreProjector" = "True" "RenderType" = "Transparent"}
Pass
{
Tags{ "LightMode" = "ForwardBase"}
Cull Front
ZWrite Off//關(guān)閉深度寫(xiě)入
Blend SrcAlpha OneMinusSrcAlpha//將源顏色的混合因子設(shè)為SrcAlpha 目標(biāo)顏色的混合因子設(shè)為OneMinusSrcAlpha
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "Lighting.cginc"
fixed4 _Color;
sampler2D _MainTex;
float4 _MainTex_ST;
fixed _AlphaScale;
struct a2v
{
float4 vertex : POSITION;
float3 normal : NORMAL;
float4 texcoord : TEXCOORD0;
};
struct v2f
{
float4 pos : SV_POSITION;
float3 worldNormal : TEXCOORD0;
float3 worldPos : TEXCOORD1;
float2 uv : TEXCOORD2;
};
v2f vert(a2v v)
{
v2f o;
o.pos = UnityObjectToClipPos(v.vertex);
o.worldNormal = UnityObjectToWorldNormal(v.normal);
o.worldPos = mul(unity_ObjectToWorld,v.vertex).xyz;
o.uv = TRANSFORM_TEX(v.texcoord,_MainTex);
return o;
}
fixed4 frag(v2f i) : SV_Target
{
fixed3 worldNormal = normalize(i.worldNormal);
fixed3 worldLightDir = normalize(UnityWorldSpaceLightDir(i.worldPos));
fixed4 texColor = tex2D(_MainTex,i.uv);
fixed3 albedo = texColor.rgb * _Color.rgb;
fixed3 ambient = UNITY_LIGHTMODEL_AMBIENT * albedo;
fixed3 diffuse = _LightColor0.rgb * albedo * max(0,dot(worldNormal,worldLightDir));
return fixed4(ambient + diffuse,texColor.a * _AlphaScale);//設(shè)置透明通道
}
ENDCG
}
Pass
{
Tags{ "LightMode" = "ForwardBase"}
Cull Back
ZWrite Off//關(guān)閉深度寫(xiě)入
Blend SrcAlpha OneMinusSrcAlpha//將源顏色的混合因子設(shè)為SrcAlpha 目標(biāo)顏色的混合因子設(shè)為OneMinusSrcAlpha
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "Lighting.cginc"
fixed4 _Color;
sampler2D _MainTex;
float4 _MainTex_ST;
fixed _AlphaScale;
struct a2v
{
float4 vertex : POSITION;
float3 normal : NORMAL;
float4 texcoord : TEXCOORD0;
};
struct v2f
{
float4 pos : SV_POSITION;
float3 worldNormal : TEXCOORD0;
float3 worldPos : TEXCOORD1;
float2 uv : TEXCOORD2;
};
v2f vert(a2v v)
{
v2f o;
o.pos = UnityObjectToClipPos(v.vertex);
o.worldNormal = UnityObjectToWorldNormal(v.normal);
o.worldPos = mul(unity_ObjectToWorld,v.vertex).xyz;
o.uv = TRANSFORM_TEX(v.texcoord,_MainTex);
return o;
}
fixed4 frag(v2f i) : SV_Target
{
fixed3 worldNormal = normalize(i.worldNormal);
fixed3 worldLightDir = normalize(UnityWorldSpaceLightDir(i.worldPos));
fixed4 texColor = tex2D(_MainTex,i.uv);
fixed3 albedo = texColor.rgb * _Color.rgb;
fixed3 ambient = UNITY_LIGHTMODEL_AMBIENT * albedo;
fixed3 diffuse = _LightColor0.rgb * albedo * max(0,dot(worldNormal,worldLightDir));
return fixed4(ambient + diffuse,texColor.a * _AlphaScale);//設(shè)置透明通道
}
ENDCG
}
}
FallBack "Transparent/VertexLit"
}
只是把Pass復(fù)制了兩份 然后第一個(gè)寫(xiě)的Cull Back 第二個(gè)是Cull Front文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-726527.html
到了這里,關(guān)于《Unity Shader 入門(mén)精要》筆記07的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!