unity3d - Unity:可以连续使用2个pass吗?
问题描述
我有一个里面有多个通道的着色器,其中两个是轮廓通道和模糊通道。我正在尝试创建一个轮廓,然后将其模糊。如何使模糊通道接受轮廓通道的输出以进行模糊?
大纲通行证:
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 中从中采样。
在您的情况下,将其放在轮廓通道之后,并从模糊通道中的结果纹理而不是原始纹理中采样。
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
}
推荐阅读
- c# - 如何检查C#中嵌套的JSON解析对象中是否存在键
- shell - gcloud 使用时间戳过滤器登录 CLI
- xcode - 如何隐藏我认为来自版本控制的这些蓝色标记?
- reactjs - React Bundle 给出错误:“类型错误:无法读取未定义的属性 'ReactCurrentOwner'”
- arrays - 视觉基本<>问题
- haskell - Haskell 递归函数
- c# - 如何检查计算机是否可以连接到 Active Directory?
- javascript - 使用键盘选择 onchange - 在焦点消失之前不要触发 onchange 事件?
- r - 在 dplyr 中添加一个新的分组变量
- visual-studio-code - 将标题的默认语言永久更改为 C