无法屏蔽Unity中的MovieTexture

时间:2017-07-25 00:07:50

标签: unity3d shader mask

我目前正在使用MovieTexture在Unity中播放电影并应用自定义着色器以允许Alpha通道。问题是我需要屏蔽视频的上半部分,似乎没有任何效果。我相信它是防止它的着色器(如果我错了,请纠正我)。

我尝试了3种不同的掩蔽技术:

  • 视频图层(四边形)上的标准蒙版组件,黑色透明PNG图像作为蒙版。
  • DepthMask应用于与视频图层交叉的3D对象 - 使用影响渲染队列的特殊着色器或绘制调用(我忘记)以防止在3D对象后面或内部绘制任何内容。
  • 将四边形置于Canvas和Panel UI图层中并调整它们,使画布和面板的大小只是视频图层的一半。 (不得不使用四核,因为我不相信你可以为UI元素添加材料?)

不幸的是,这些都没有阻止任何视频。

(这是我正在使用的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通道。 enter image description here

1 个答案:

答案 0 :(得分:1)

所以,着色器看起来像那样:

Shader "StackOverFlow/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蒙版切割! (不是吗?)

我使用的是纹理(或视频。它并不重要):

image and coordinates

默认情况下,您的片段会是这样的:

 float4 frag(v2f i) : SV_Target
 {
     half4 color = tex2D(_MainTex, i.texcoord);
     return color;
 }

第一步,让我们尝试在没有面具的情况下在四边形上绘制两个视频!

为此,让我们在临时变量float2 uv1 = i.texcoord;中保存默认纹理坐标。并将uv1.y乘以0.5;我们将看到什么,为什么我们这样做?

mouse & kitty masks

我们似乎已经将纹理垂直拉伸两次,并且着色器仅绘制纹理的下半部分。因为uv.y上半部分的坐标在四边形之外。是的它很好,但我们想要视频!因此,让我们将纹理垂直移动一半纹理坐标uv1.y +=0.5。我们有什么?

video 1 & 2

是的!我们的视频最棒! (仅绘制视频的示例)

 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;

mouse kitty final

没有任何设置的简单着色器将如下所示:

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;
}

要控制视频的Alpha和当前颜色,请添加 _ColorTint

//...
half4 mask = tex2D(_MainTex, uv2);
color.rgb *= _ColorTint.rgb * 2;
color.a = mask.r *_ColorTint.a;
return color;
//...

所以,你可以问我, - "为什么你使用 mask.r ?", - " r 是RED ?", - "为什么不 g b ?"

答案:黑色是(0,0,0),白色是(1,1,1)。如果我使用其他渠道( g b ),则不会更改任何内容。当你乘以" color.a"到0,它将是Tranparent。

这就是全部。

抱歉我的英语不好而且很差!