无法在 Unity 中屏蔽 MovieTexture
Unable to mask a MovieTexture in Unity
我目前正在 Unity 中使用 MovieTexture 播放电影并应用自定义着色器以允许使用 alpha 通道。问题是我需要屏蔽视频的上半部分,但似乎没有任何效果。我相信这是阻止它的着色器(如果我错了请纠正我)。
我尝试了 3 种不同的遮蔽技术:
- 视频层(四边形)上的标准蒙版组件,使用黑色透明 PNG 图像作为蒙版。
- 应用于 3D 对象相交视频层的 DepthMask - 使用影响渲染队列或绘制调用(我忘记了)的特殊着色器以防止绘制 3D 对象后面或内部的任何内容。
- 将四边形放在 Canvas 和面板 UI 层中并调整它们,使 canvas 和面板是视频层大小的一半。 (不得不使用四边形,因为我不相信你可以向 UI 元素添加材料?)
不幸的是,None 阻止了任何视频。
(这是我正在使用的 alpha 着色器:https://github.com/keijiro/AotsMovieTexture)
这也是着色器的代码:
Shader "Custom/Aots Movie Texture" {
Properties
{
_MainTex("Base Texture", 2D) = "" {}
_ColorTint("Color Tint", Color) = (0.5, 0.5, 0.5, 1)
}
CGINCLUDE
#include "UnityCG.cginc"
sampler2D _MainTex;
half4 _ColorTint;
struct v2f
{
float4 position : SV_POSITION;
float2 texcoord : TEXCOORD0;
};
v2f vert(appdata_base v)
{
v2f o;
o.position = mul(UNITY_MATRIX_MVP, v.vertex);
o.texcoord = v.texcoord;
return o;
}
float4 frag(v2f i) : SV_Target
{
float2 uv1 = i.texcoord;
float2 uv2 = i.texcoord;
uv1.x *= 0.5f;
uv2.x *= 0.5f;
uv2.x += 0.5f;
half4 color = tex2D(_MainTex, uv1);
half4 mask = tex2D(_MainTex, uv2);
color.rgb *= _ColorTint.rgb * 2;
color.a = mask.r * _ColorTint.a;
return color;
}
ENDCG
SubShader
{
Tags { "RenderType"="Transparent" "Queue"="Transparent" }
Pass
{
ZTest Always Cull Off ZWrite Off
Fog { Mode off }
Blend SrcAlpha OneMinusSrcAlpha
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
ENDCG
}
}
}
编辑:
请更详细地解释我想要做什么,我们有一个 4K 视频被分成四部分。顶部的两个四边形将是独立视频,底部两个将用于 alpha 视频。我只需要隐藏顶部的两个四边形(4k 视频的上半部分),因此当视频像我链接到的着色器一样在顶部分层时,您只能看到 alpha 通道。
因此,着色器将如下所示:
Shader "Whosebug/splitVideo"{
Properties
{
_MainTex("Base Texture", 2D) = "" {}
_ColorTint("Color Tint", Color) = (0.5, 0.5, 0.5, 1)
[MaterialToggle]ShowLeft("Show Only Left", Float) = 0
[MaterialToggle]ShowRight("Show Only Right", Float) = 0
}
CGINCLUDE
#include "UnityCG.cginc"
#pragma multi_compile _ SHOWLEFT_ON
#pragma multi_compile _ SHOWRIGHT_ON
sampler2D _MainTex;
half4 _ColorTint;
struct v2f
{
float4 position : SV_POSITION;
float2 texcoord : TEXCOORD0;
};
v2f vert(appdata_base v)
{
v2f o;
o.position = UnityObjectToClipPos(v.vertex);
o.texcoord = v.texcoord;
return o;
}
float4 frag(v2f i) : SV_Target
{
float2 uv1 = i.texcoord;
float2 uv2 = i.texcoord;
#ifdef SHOWLEFT_ON
uv1.x *= 0.5;
uv2.x *= 0.5;
#else
#ifdef SHOWRIGHT_ON
uv1.x *= 0.5;
uv2.x *= 0.5;
uv2.x += 0.5;
uv1.x += 0.5;
#endif
#endif
uv1.y *= 0.5; // line 1
uv1.y += 0.5; // line 2
uv2.y *= 0.5;
half4 color = tex2D(_MainTex, uv1);
half4 mask = tex2D(_MainTex, uv2);
color.rgb *= _ColorTint.rgb * 2;
color.a = mask.b *_ColorTint.a;
return color;
}
ENDCG
SubShader
{
Tags{ "RenderType" = "Transparent" "Queue" = "Transparent" }
Pass
{
ZTest Always Cull Off ZWrite Off
Fog{ Mode off }
Blend SrcAlpha OneMinusSrcAlpha
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
ENDCG
}
}
}
关于顶点和片段着色器,您可以阅读 here。
让我们解释一下,这是怎么回事! (偏移量)
我们希望看到被 alpha 蒙版剪切的视频! (不是吗?)
我使用那个纹理(或视频。没关系):
默认情况下,您的 Fragment 将如下所示:
float4 frag(v2f i) : SV_Target
{
half4 color = tex2D(_MainTex, i.texcoord);
return color;
}
第一步,让我们尝试在没有遮罩的四边形上绘制两个视频!
为此,我们将默认纹理坐标保存在临时变量 float2 uv1 = i.texcoord;
中。并将 uv1.y
乘以 0.5
;我们会看到什么,为什么要这样做?
我们似乎将纹理垂直拉伸了两次,而着色器只绘制了纹理的下半部分。因为 uv.y
四边形之外的上半部分坐标。是的,这很好,但我们想要视频!因此,让我们将纹理垂直移动一半的纹理坐标 uv1.y +=0.5
。我们有什么?
是的!我们的视频是最好的! (仅绘制视频的示例)
float4 frag(v2f i) : SV_Target
{
float2 uv1 = i.texcoord;
uv1.y *= 0.5;
uv1.y += 0.5;
half4 color = tex2D(_MainTex, uv1);
return color;
}
第二步。
要使用掩码,我们需要两个变量来使用它!我们的纹理是单一的,但我们必须像使用两个不同的纹理一样使用它。 (视频和面具)!
声明一个新变量
float2 uv2 = i.texcoord;
并剪切上半部分视频 uv2.y *= 0.5;
。与 uv1
相同的故事,但没有移动纹理。第二个变量将是
half4 mask = tex2D(_MainTex, uv2);
动物是我们的朋友!我们看不见他们,他们却看见了我们!
由于我们使用黑色进行剪切,因此我们可以从蒙版的当前颜色分配视频的 Alpha 通道。
color.a = mask.r;
没有任何设置的简单着色器将如下所示:
float4 frag(v2f i) : SV_Target
{
float2 uv1 = i.texcoord;
float2 uv2 = i.texcoord;
uv1.y *= 0.5;
uv1.y += 0.5;
uv2.y *= 0.5;
half4 color = tex2D(_MainTex, uv1);
half4 mask = tex2D(_MainTex, uv2);
color.a = mask.r;
return color;
}
要控制视频的透明度和当前颜色,让我们添加 _ColorTint:
//...
half4 mask = tex2D(_MainTex, uv2);
color.rgb *= _ColorTint.rgb * 2;
color.a = mask.r *_ColorTint.a;
return color;
//...
所以,你可以问我,-"why you are using mask.r?", -"r 是红色的吗?", -"why not g or b?"
答案:黑色为(0,0,0),白色为(1,1,1)。如果我使用其他渠道(g 或 b),它不会改变任何东西。当你将 "color.a" 乘以 0 时,它将是透明的。
就这些了。
抱歉我的英语不好!
我目前正在 Unity 中使用 MovieTexture 播放电影并应用自定义着色器以允许使用 alpha 通道。问题是我需要屏蔽视频的上半部分,但似乎没有任何效果。我相信这是阻止它的着色器(如果我错了请纠正我)。
我尝试了 3 种不同的遮蔽技术:
- 视频层(四边形)上的标准蒙版组件,使用黑色透明 PNG 图像作为蒙版。
- 应用于 3D 对象相交视频层的 DepthMask - 使用影响渲染队列或绘制调用(我忘记了)的特殊着色器以防止绘制 3D 对象后面或内部的任何内容。
- 将四边形放在 Canvas 和面板 UI 层中并调整它们,使 canvas 和面板是视频层大小的一半。 (不得不使用四边形,因为我不相信你可以向 UI 元素添加材料?)
None 阻止了任何视频。
(这是我正在使用的 alpha 着色器:https://github.com/keijiro/AotsMovieTexture)
这也是着色器的代码:
Shader "Custom/Aots Movie Texture" {
Properties
{
_MainTex("Base Texture", 2D) = "" {}
_ColorTint("Color Tint", Color) = (0.5, 0.5, 0.5, 1)
}
CGINCLUDE
#include "UnityCG.cginc"
sampler2D _MainTex;
half4 _ColorTint;
struct v2f
{
float4 position : SV_POSITION;
float2 texcoord : TEXCOORD0;
};
v2f vert(appdata_base v)
{
v2f o;
o.position = mul(UNITY_MATRIX_MVP, v.vertex);
o.texcoord = v.texcoord;
return o;
}
float4 frag(v2f i) : SV_Target
{
float2 uv1 = i.texcoord;
float2 uv2 = i.texcoord;
uv1.x *= 0.5f;
uv2.x *= 0.5f;
uv2.x += 0.5f;
half4 color = tex2D(_MainTex, uv1);
half4 mask = tex2D(_MainTex, uv2);
color.rgb *= _ColorTint.rgb * 2;
color.a = mask.r * _ColorTint.a;
return color;
}
ENDCG
SubShader
{
Tags { "RenderType"="Transparent" "Queue"="Transparent" }
Pass
{
ZTest Always Cull Off ZWrite Off
Fog { Mode off }
Blend SrcAlpha OneMinusSrcAlpha
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
ENDCG
}
}
}
编辑:
请更详细地解释我想要做什么,我们有一个 4K 视频被分成四部分。顶部的两个四边形将是独立视频,底部两个将用于 alpha 视频。我只需要隐藏顶部的两个四边形(4k 视频的上半部分),因此当视频像我链接到的着色器一样在顶部分层时,您只能看到 alpha 通道。
因此,着色器将如下所示:
Shader "Whosebug/splitVideo"{
Properties
{
_MainTex("Base Texture", 2D) = "" {}
_ColorTint("Color Tint", Color) = (0.5, 0.5, 0.5, 1)
[MaterialToggle]ShowLeft("Show Only Left", Float) = 0
[MaterialToggle]ShowRight("Show Only Right", Float) = 0
}
CGINCLUDE
#include "UnityCG.cginc"
#pragma multi_compile _ SHOWLEFT_ON
#pragma multi_compile _ SHOWRIGHT_ON
sampler2D _MainTex;
half4 _ColorTint;
struct v2f
{
float4 position : SV_POSITION;
float2 texcoord : TEXCOORD0;
};
v2f vert(appdata_base v)
{
v2f o;
o.position = UnityObjectToClipPos(v.vertex);
o.texcoord = v.texcoord;
return o;
}
float4 frag(v2f i) : SV_Target
{
float2 uv1 = i.texcoord;
float2 uv2 = i.texcoord;
#ifdef SHOWLEFT_ON
uv1.x *= 0.5;
uv2.x *= 0.5;
#else
#ifdef SHOWRIGHT_ON
uv1.x *= 0.5;
uv2.x *= 0.5;
uv2.x += 0.5;
uv1.x += 0.5;
#endif
#endif
uv1.y *= 0.5; // line 1
uv1.y += 0.5; // line 2
uv2.y *= 0.5;
half4 color = tex2D(_MainTex, uv1);
half4 mask = tex2D(_MainTex, uv2);
color.rgb *= _ColorTint.rgb * 2;
color.a = mask.b *_ColorTint.a;
return color;
}
ENDCG
SubShader
{
Tags{ "RenderType" = "Transparent" "Queue" = "Transparent" }
Pass
{
ZTest Always Cull Off ZWrite Off
Fog{ Mode off }
Blend SrcAlpha OneMinusSrcAlpha
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
ENDCG
}
}
}
关于顶点和片段着色器,您可以阅读 here。
让我们解释一下,这是怎么回事! (偏移量)
我们希望看到被 alpha 蒙版剪切的视频! (不是吗?)
我使用那个纹理(或视频。没关系):
默认情况下,您的 Fragment 将如下所示:
float4 frag(v2f i) : SV_Target
{
half4 color = tex2D(_MainTex, i.texcoord);
return color;
}
第一步,让我们尝试在没有遮罩的四边形上绘制两个视频!
为此,我们将默认纹理坐标保存在临时变量 float2 uv1 = i.texcoord;
中。并将 uv1.y
乘以 0.5
;我们会看到什么,为什么要这样做?
我们似乎将纹理垂直拉伸了两次,而着色器只绘制了纹理的下半部分。因为 uv.y
四边形之外的上半部分坐标。是的,这很好,但我们想要视频!因此,让我们将纹理垂直移动一半的纹理坐标 uv1.y +=0.5
。我们有什么?
是的!我们的视频是最好的! (仅绘制视频的示例)
float4 frag(v2f i) : SV_Target
{
float2 uv1 = i.texcoord;
uv1.y *= 0.5;
uv1.y += 0.5;
half4 color = tex2D(_MainTex, uv1);
return color;
}
第二步。 要使用掩码,我们需要两个变量来使用它!我们的纹理是单一的,但我们必须像使用两个不同的纹理一样使用它。 (视频和面具)! 声明一个新变量
float2 uv2 = i.texcoord;
并剪切上半部分视频 uv2.y *= 0.5;
。与 uv1
相同的故事,但没有移动纹理。第二个变量将是
half4 mask = tex2D(_MainTex, uv2);
动物是我们的朋友!我们看不见他们,他们却看见了我们!
由于我们使用黑色进行剪切,因此我们可以从蒙版的当前颜色分配视频的 Alpha 通道。
color.a = mask.r;
没有任何设置的简单着色器将如下所示:
float4 frag(v2f i) : SV_Target
{
float2 uv1 = i.texcoord;
float2 uv2 = i.texcoord;
uv1.y *= 0.5;
uv1.y += 0.5;
uv2.y *= 0.5;
half4 color = tex2D(_MainTex, uv1);
half4 mask = tex2D(_MainTex, uv2);
color.a = mask.r;
return color;
}
要控制视频的透明度和当前颜色,让我们添加 _ColorTint:
//...
half4 mask = tex2D(_MainTex, uv2);
color.rgb *= _ColorTint.rgb * 2;
color.a = mask.r *_ColorTint.a;
return color;
//...
所以,你可以问我,-"why you are using mask.r?", -"r 是红色的吗?", -"why not g or b?"
答案:黑色为(0,0,0),白色为(1,1,1)。如果我使用其他渠道(g 或 b),它不会改变任何东西。当你将 "color.a" 乘以 0 时,它将是透明的。
就这些了。
抱歉我的英语不好!