shader編-透明効果
shader編-透明効果
ラベル(スペース区切り):shader
透明効果の実現方法の概要
Unityでは2つの方法で透明効果を実現します.1つは透明度テスト、2つは透明度混合です.透明度テスト:深さ書き込みを閉じる必要がなく、透明度が基準に達しないと削除されるので、物体は不透明か完全に透明になります.透明度ブレンド(Transparency Blend):実際の半透明効果を得ることができます.透明度とカラーバッファのカラーをブレンドして新しいカラーを得るのが原理です.ただし、これは深さ書き込みを閉じる必要があります.半透明の物体が不透明な物体や半透明の後ろの半透明の物体のレンダリングに影響しないことを保証します.
レンダリング順序の重要性
深度書き込みをオフにすると、オブジェクトのレンダリング順序に注意する必要があります.オフにする前のオブジェクトのレンダリングは深度z-bufferによって決定されるため、半透明なオブジェクトの後の非透明なオブジェクト(ここでは前後が仮想カメラからの距離を指す)をレンダリングし、透明なオブジェクトをレンダリングする必要があります.そうしないと、オフにしていない深度テストは透明度ブレンド後のカラーバッファを直接上書きし、ある半透明な効果を失うことになります.しかし、レンダリング順序が設定されていても、2本のロープで2つの物体の前後を区別することができず、合理的なレンダリング順序を制定できないなどの問題が発生することがあります.この問題を解決するには、グリッドを分割する必要があります.
Unity shaderのレンダリング順序
レンダリング順序を解決するためにunityはレンダリングキューを提供します.Queueラベルは、モデルがどのキューを使用するかを決定します.
名前
キューインデックス
説明
Background
1000
バックグラウンドをレンダリングする最も古いレンダリングキュー
Geometry
2000
既定のレンダリングキュー、不透明な物体はこれを使用します
AlphaTest
2450
透明度テスト
Transparent
3000
透明度を使用して深さ書き込みのshaderをブレンドまたは閉じる
Overlay
4000
いくつかのオーバーラップ効果を使用して、最後にレンダリングされたオブジェクトがキューを使用します.
インスタンスを使用して透明度テストを使用する場合は、次のtagを追加する必要があります.
SubShader {
Tags {"Queue"="AlphaTest"
同様に、透明度ブレンドには、以下のtagを使用する必要があります.
SubShader {
Tags {"Queue"="Transparent"
透明度テスト
unityメタシェーダはclip関数を使用して透明度テストを行います
void clip(float4 x)
{
if(any(x<0))
discard;
}
コンフィギュレーションではtagsがかなり重要ですが、Queueラベルは前に述べましたが、RenderTypeはレンダリングのキューを作成するために使用されています.「IgnoreProjector」=「True」は、shaderがプロジェクタの影響を受けないことを保証します.
Properties {
_Color ("Color Tint", Color) = (1, 1, 1, 1)
_MainTex ("Main Tex", 2D) = "white" {}
_Cutoff ("Alpha Cutoff", Range(0, 1)) = 0.5
}
SubShader {
Tags {"Queue"="AlphaTest" "IgnoreProjector"="True" "RenderType"="TransparentCutout"}
Pass {
Tags { "LightMode"="ForwardBase" }
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "Lighting.cginc"
fixed4 _Color;
sampler2D _MainTex;
float4 _MainTex_ST;
//_Cutoff [0,1], fix
fixed _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;
};
頂点シェーダ(Vertex Shader)
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);
// Alpha test
clip (texColor.a - _Cutoff);
// Equal to
// if ((texColor.a - _Cutoff) < 0.0) {
// discard;
// }
fixed3 albedo = texColor.rgb * _Color.rgb;
fixed3 ambient = UNITY_LIGHTMODEL_AMBIENT.xyz * albedo;
fixed3 diffuse = _LightColor0.rgb * albedo * max(0, dot(worldNormal, worldLightDir));
return fixed4(ambient + diffuse, 1.0);
}
Fallbackは内蔵Transparent/Outout/VertexLitをfallbackとして使用し、shaderが現在のグラフィックスカードで動作している間に交換可能なshaderが存在しないことを保証します.
FallBack "Transparent/Cutout/VertexLit"
透明度のブレンド(Transparency Blend)
同様に、透明度ブレンドに対応し、unityは内蔵コマンドBlendを提供します.
意味
説明
Blend Off
ブレンドを閉じる
Blend SrcFactor DstFactor
ブレンドをオンにする
コード実装はまず構成です
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
//
Blend SrcAlpha 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;
};
シェーダ(Shader)
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.xyz * albedo;
fixed3 diffuse = _LightColor0.rgb * albedo * max(0, dot(worldNormal, worldLightDir));
// , Blend ,
return fixed4(ambient + diffuse, texColor.a * _AlphaScale);
}
深度ライトの半透明効果をオンにする
深さ書き込みをオンにしても半透明になりますが、passを2つ使うと一定の性能損失が発生します
Pass {
ZWrite On
ColorMask 0
}
Pass {
この最初のpassは、モデルの深さ情報を深さキャッシュに入力するために設定され、ColorMaskを0に設定してpassがマスクを出力しないようにします.
両面レンダリング
これは、すべてのオブジェクトをレンダリングするために除去機能をキャンセルし、より多くのパフォーマンスを消費することを実現します.
Cull Off//
透明度ブレンドの両面レンダリング両面レンダリング両面レンダリングは、両面レンダリングがオンになっているため、レンダリング順序を保証するためにコードを再設定する必要があります.
Pass {
// First pass renders only back faces
Cull Front
ZWrite Off
Blend SrcAlpha OneMinusSrcAlpha
。。。。
}
Pass {
Tags { "LightMode"="ForwardBase" }
// Second pass renders only front faces
Cull Back
。。。。
2つのpassを使用してcullコマンドを使用してレンダリング順序を設定し、異なる方向のレンダリングエンティティを除去します.
これは私個人の学習ノートと個人の総括にすぎません.もし不適切なところがあれば、指摘してください.