Unity:是否可以连续使用2次pass?
Unity: Is it possible to use 2 passes consecutively?
我有一个内部有多个通道的着色器,其中 2 个是轮廓通道和模糊通道。我正在尝试创建轮廓然后对其进行模糊处理。如何使模糊通道接受轮廓通道的输出以进行模糊处理?
大纲通过:
Pass{
Name "OUTLINE"
Cull Off
ZWrite Off
ZTest Always
Blend SrcAlpha OneMinusSrcAlpha
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#pragma target 2.0
#pragma multi_compile_fog
fixed4 frag(v2f IN) : SV_Target
{
fixed4 c = tex2D(_MainTex, IN.texcoord) * IN.color;
if (c.a > _Cutoff) {
float totalAlpha = 1.0;
[unroll(16)]
for (int i = 1; i < _OutlineSize + 1; i++) {
fixed4 pixelUp = tex2D(_MainTex, IN.texcoord + fixed2(0, i * _MainTex_TexelSize.y));
fixed4 pixelDown = tex2D(_MainTex, IN.texcoord - fixed2(0, i * _MainTex_TexelSize.y));
fixed4 pixelRight = tex2D(_MainTex, IN.texcoord + fixed2(i * _MainTex_TexelSize.x, 0));
fixed4 pixelLeft = tex2D(_MainTex, IN.texcoord - fixed2(i * _MainTex_TexelSize.x, 0));
totalAlpha = totalAlpha * pixelUp.a * pixelDown.a * pixelRight.a * pixelLeft.a;
}
if (totalAlpha == 0) {
c.rgba = fixed4(0.4, 1, 1, 1);
}
else
c.rgba = fixed4(0.5, 0.5, 0.5, .5);
}
c.rgb *= c.a;
return c;
}
ENDCG
}
模糊通道:
Pass{
Name "BLUR"
Cull Off
ZWrite Off
ZTest Always
Blend SrcAlpha OneMinusSrcAlpha
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#pragma target 2.0
#pragma multi_compile_fog
fixed4 frag(v2f IN) : SV_Target
{
fixed4 c = tex2D(_MainTex, IN.texcoord) * IN.color;
if (c.a > _Cutoff) {
fixed4 pixelUp = tex2D(_MainTex, IN.texcoord + fixed2(0, _MainTex_TexelSize.y));
fixed4 pixelDown = tex2D(_MainTex, IN.texcoord - fixed2(0, _MainTex_TexelSize.y));
fixed4 pixelRight = tex2D(_MainTex, IN.texcoord + fixed2(_MainTex_TexelSize.x, 0));
fixed4 pixelLeft = tex2D(_MainTex, IN.texcoord - fixed2(_MainTex_TexelSize.x, 0));
fixed4 pixelUp2 = tex2D(_MainTex, IN.texcoord + fixed2(0, 2 * _MainTex_TexelSize.y));
fixed4 pixelDown2 = tex2D(_MainTex, IN.texcoord - fixed2(0, 2 * _MainTex_TexelSize.y));
fixed4 pixelRight2 = tex2D(_MainTex, IN.texcoord + fixed2(2 * _MainTex_TexelSize.x, 0));
fixed4 pixelLeft2 = tex2D(_MainTex, IN.texcoord - fixed2(2 * _MainTex_TexelSize.x, 0));
fixed4 pixelUp3 = tex2D(_MainTex, IN.texcoord + fixed2(0, 3 * _MainTex_TexelSize.y));
fixed4 pixelDown3 = tex2D(_MainTex, IN.texcoord - fixed2(0, 3 * _MainTex_TexelSize.y));
fixed4 pixelRight3 = tex2D(_MainTex, IN.texcoord + fixed2(3 * _MainTex_TexelSize.x, 0));
fixed4 pixelLeft3 = tex2D(_MainTex, IN.texcoord - fixed2(3 * _MainTex_TexelSize.x, 0));
c = c * 0.18
+ 0.15 * (pixelUp + pixelDown + pixelRight + pixelLeft)
+ 0.12 * (pixelUp2 + pixelDown2 + pixelRight2 + pixelLeft2);
+ 0.09 * (pixelUp3 + pixelDown3 + pixelRight3 + pixelLeft3);
}
c.rgb *= c.a;
return c;
}
ENDCG
}
我是着色器的新手,所以如果有任何建议,我们将不胜感激。
使用 Grab pass,您可以获取到目前为止生成的屏幕并在另一遍中从中取样。
在你的情况下,将它放在轮廓通道之后,并从模糊通道中的结果纹理而不是原始纹理中采样。
Pass{
// ...
// no change
// ...
}
GrabPass { "_GrabTexture" }
Pass{
// Note the changes from calling tex2D with _MainTex to _GrabTexture,
// matching the string in the GrabPass directive above
// ...
// use a vertex shader to get the uvs of the screen grab
struct v2f {
float4 grabPos : TEXCOORD0;
float4 pos : SV_POSITION;
};
v2f vert(appdata_base v) {
v2f o;
// use UnityObjectToClipPos from UnityCG.cginc to calculate
// the clip-space of the vertex
o.pos = UnityObjectToClipPos(v.vertex);
// use ComputeGrabScreenPos function from UnityCG.cginc
// to get the correct texture coordinate
o.grabPos = ComputeGrabScreenPos(o.pos);
return o;
}
// Note the changes from calling tex2D with _MainTex to _GrabTexture,
// matching the string in the GrabPass directive above
// as well as IN.grabPos instead of IN.texcoord
// and tex2Dproj instead of tex2D
fixed4 frag(v2f IN) : SV_Target {
fixed4 c = tex2Dproj(_GrabTexture, IN.grabPos) * IN.color;
if (c.a > _Cutoff) {
fixed4 pixelUp = tex2Dproj(_GrabTexture, IN.grabPos+ fixed2(0, _MainTex_TexelSize.y));
fixed4 pixelDown = tex2Dproj(_GrabTexture, IN.grabPos - fixed2(0, _MainTex_TexelSize.y));
fixed4 pixelRight = tex2Dproj(_GrabTexture, IN.texcoord + fixed2(_MainTex_TexelSize.x, 0));
fixed4 pixelLeft = tex2Dproj(_GrabTexture, IN.texcoord - fixed2(_MainTex_TexelSize.x, 0));
fixed4 pixelUp2 = tex2Dproj(_GrabTexture, IN.texcoord + fixed2(0, 2 * _MainTex_TexelSize.y));
fixed4 pixelDown2 = tex2Dproj(_GrabTexture, IN.texcoord - fixed2(0, 2 * _MainTex_TexelSize.y));
fixed4 pixelRight2 = tex2Dproj(_GrabTexture, IN.texcoord + fixed2(2 * _MainTex_TexelSize.x, 0));
fixed4 pixelLeft2 = tex2Dproj(_GrabTexture, IN.texcoord - fixed2(2 * _MainTex_TexelSize.x, 0));
fixed4 pixelUp3 = tex2Dproj(_GrabTexture, IN.texcoord + fixed2(0, 3 * _MainTex_TexelSize.y));
fixed4 pixelDown3 = tex2Dproj(_GrabTexture, IN.texcoord - fixed2(0, 3 * _MainTex_TexelSize.y));
fixed4 pixelRight3 = tex2Dproj(_GrabTexture, IN.texcoord + fixed2(3 * _MainTex_TexelSize.x, 0));
fixed4 pixelLeft3 = tex2Dproj(_GrabTexture, IN.texcoord - fixed2(3 * _MainTex_TexelSize.x, 0));
c = c * 0.18
+ 0.15 * (pixelUp + pixelDown + pixelRight + pixelLeft)
+ 0.12 * (pixelUp2 + pixelDown2 + pixelRight2 + pixelLeft2);
+ 0.09 * (pixelUp3 + pixelDown3 + pixelRight3 + pixelLeft3);
}
c.rgb *= c.a;
return c;
}
ENDCG
}
我有一个内部有多个通道的着色器,其中 2 个是轮廓通道和模糊通道。我正在尝试创建轮廓然后对其进行模糊处理。如何使模糊通道接受轮廓通道的输出以进行模糊处理?
大纲通过:
Pass{
Name "OUTLINE"
Cull Off
ZWrite Off
ZTest Always
Blend SrcAlpha OneMinusSrcAlpha
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#pragma target 2.0
#pragma multi_compile_fog
fixed4 frag(v2f IN) : SV_Target
{
fixed4 c = tex2D(_MainTex, IN.texcoord) * IN.color;
if (c.a > _Cutoff) {
float totalAlpha = 1.0;
[unroll(16)]
for (int i = 1; i < _OutlineSize + 1; i++) {
fixed4 pixelUp = tex2D(_MainTex, IN.texcoord + fixed2(0, i * _MainTex_TexelSize.y));
fixed4 pixelDown = tex2D(_MainTex, IN.texcoord - fixed2(0, i * _MainTex_TexelSize.y));
fixed4 pixelRight = tex2D(_MainTex, IN.texcoord + fixed2(i * _MainTex_TexelSize.x, 0));
fixed4 pixelLeft = tex2D(_MainTex, IN.texcoord - fixed2(i * _MainTex_TexelSize.x, 0));
totalAlpha = totalAlpha * pixelUp.a * pixelDown.a * pixelRight.a * pixelLeft.a;
}
if (totalAlpha == 0) {
c.rgba = fixed4(0.4, 1, 1, 1);
}
else
c.rgba = fixed4(0.5, 0.5, 0.5, .5);
}
c.rgb *= c.a;
return c;
}
ENDCG
}
模糊通道:
Pass{
Name "BLUR"
Cull Off
ZWrite Off
ZTest Always
Blend SrcAlpha OneMinusSrcAlpha
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#pragma target 2.0
#pragma multi_compile_fog
fixed4 frag(v2f IN) : SV_Target
{
fixed4 c = tex2D(_MainTex, IN.texcoord) * IN.color;
if (c.a > _Cutoff) {
fixed4 pixelUp = tex2D(_MainTex, IN.texcoord + fixed2(0, _MainTex_TexelSize.y));
fixed4 pixelDown = tex2D(_MainTex, IN.texcoord - fixed2(0, _MainTex_TexelSize.y));
fixed4 pixelRight = tex2D(_MainTex, IN.texcoord + fixed2(_MainTex_TexelSize.x, 0));
fixed4 pixelLeft = tex2D(_MainTex, IN.texcoord - fixed2(_MainTex_TexelSize.x, 0));
fixed4 pixelUp2 = tex2D(_MainTex, IN.texcoord + fixed2(0, 2 * _MainTex_TexelSize.y));
fixed4 pixelDown2 = tex2D(_MainTex, IN.texcoord - fixed2(0, 2 * _MainTex_TexelSize.y));
fixed4 pixelRight2 = tex2D(_MainTex, IN.texcoord + fixed2(2 * _MainTex_TexelSize.x, 0));
fixed4 pixelLeft2 = tex2D(_MainTex, IN.texcoord - fixed2(2 * _MainTex_TexelSize.x, 0));
fixed4 pixelUp3 = tex2D(_MainTex, IN.texcoord + fixed2(0, 3 * _MainTex_TexelSize.y));
fixed4 pixelDown3 = tex2D(_MainTex, IN.texcoord - fixed2(0, 3 * _MainTex_TexelSize.y));
fixed4 pixelRight3 = tex2D(_MainTex, IN.texcoord + fixed2(3 * _MainTex_TexelSize.x, 0));
fixed4 pixelLeft3 = tex2D(_MainTex, IN.texcoord - fixed2(3 * _MainTex_TexelSize.x, 0));
c = c * 0.18
+ 0.15 * (pixelUp + pixelDown + pixelRight + pixelLeft)
+ 0.12 * (pixelUp2 + pixelDown2 + pixelRight2 + pixelLeft2);
+ 0.09 * (pixelUp3 + pixelDown3 + pixelRight3 + pixelLeft3);
}
c.rgb *= c.a;
return c;
}
ENDCG
}
我是着色器的新手,所以如果有任何建议,我们将不胜感激。
使用 Grab pass,您可以获取到目前为止生成的屏幕并在另一遍中从中取样。
在你的情况下,将它放在轮廓通道之后,并从模糊通道中的结果纹理而不是原始纹理中采样。
Pass{
// ...
// no change
// ...
}
GrabPass { "_GrabTexture" }
Pass{
// Note the changes from calling tex2D with _MainTex to _GrabTexture,
// matching the string in the GrabPass directive above
// ...
// use a vertex shader to get the uvs of the screen grab
struct v2f {
float4 grabPos : TEXCOORD0;
float4 pos : SV_POSITION;
};
v2f vert(appdata_base v) {
v2f o;
// use UnityObjectToClipPos from UnityCG.cginc to calculate
// the clip-space of the vertex
o.pos = UnityObjectToClipPos(v.vertex);
// use ComputeGrabScreenPos function from UnityCG.cginc
// to get the correct texture coordinate
o.grabPos = ComputeGrabScreenPos(o.pos);
return o;
}
// Note the changes from calling tex2D with _MainTex to _GrabTexture,
// matching the string in the GrabPass directive above
// as well as IN.grabPos instead of IN.texcoord
// and tex2Dproj instead of tex2D
fixed4 frag(v2f IN) : SV_Target {
fixed4 c = tex2Dproj(_GrabTexture, IN.grabPos) * IN.color;
if (c.a > _Cutoff) {
fixed4 pixelUp = tex2Dproj(_GrabTexture, IN.grabPos+ fixed2(0, _MainTex_TexelSize.y));
fixed4 pixelDown = tex2Dproj(_GrabTexture, IN.grabPos - fixed2(0, _MainTex_TexelSize.y));
fixed4 pixelRight = tex2Dproj(_GrabTexture, IN.texcoord + fixed2(_MainTex_TexelSize.x, 0));
fixed4 pixelLeft = tex2Dproj(_GrabTexture, IN.texcoord - fixed2(_MainTex_TexelSize.x, 0));
fixed4 pixelUp2 = tex2Dproj(_GrabTexture, IN.texcoord + fixed2(0, 2 * _MainTex_TexelSize.y));
fixed4 pixelDown2 = tex2Dproj(_GrabTexture, IN.texcoord - fixed2(0, 2 * _MainTex_TexelSize.y));
fixed4 pixelRight2 = tex2Dproj(_GrabTexture, IN.texcoord + fixed2(2 * _MainTex_TexelSize.x, 0));
fixed4 pixelLeft2 = tex2Dproj(_GrabTexture, IN.texcoord - fixed2(2 * _MainTex_TexelSize.x, 0));
fixed4 pixelUp3 = tex2Dproj(_GrabTexture, IN.texcoord + fixed2(0, 3 * _MainTex_TexelSize.y));
fixed4 pixelDown3 = tex2Dproj(_GrabTexture, IN.texcoord - fixed2(0, 3 * _MainTex_TexelSize.y));
fixed4 pixelRight3 = tex2Dproj(_GrabTexture, IN.texcoord + fixed2(3 * _MainTex_TexelSize.x, 0));
fixed4 pixelLeft3 = tex2Dproj(_GrabTexture, IN.texcoord - fixed2(3 * _MainTex_TexelSize.x, 0));
c = c * 0.18
+ 0.15 * (pixelUp + pixelDown + pixelRight + pixelLeft)
+ 0.12 * (pixelUp2 + pixelDown2 + pixelRight2 + pixelLeft2);
+ 0.09 * (pixelUp3 + pixelDown3 + pixelRight3 + pixelLeft3);
}
c.rgb *= c.a;
return c;
}
ENDCG
}