【问题标题】:Unable to mask a MovieTexture in Unity无法在 Unity 中屏蔽 MovieTexture
【发布时间】:2017-07-25 00:07:50
【问题描述】:

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

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

  • 视频层(四边形)上的标准蒙版组件,以黑色透明 PNG 图像作为蒙版。
  • DepthMask 应用于与视频层相交的 3D 对象 - 使用影响渲染队列或绘制调用(我忘记了)的特殊着色器来防止在 3D 对象后面或内部绘制任何内容。
  • 将四边形放入 Canvas 和 Panel UI 层并调整它们,使 Canvas 和面板的大小是视频层的一半。 (必须使用四边形,因为我不相信您可以将材料添加到 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 通道。

【问题讨论】:

  • 您好,此时您不应该使用 MoveTexture,请查看 this 帖子了解在 Unity 中播放视频的新方法。
  • 嗨!我可以重写这个着色器,只剪掉视频的顶部,但也许你想要更多的东西,idk。请详细描述问题并添加截图。
  • 那太棒了。我很想进入着色器,但它看起来很复杂。我将编辑主要帖子以添加我们想要完成的内容。
  • 我很想知道着色器的哪一部分还可以让您操纵视频的哪一部分显示,因为我们将来可能需要对其进行一些更改。
  • 程序员:感谢您的提醒。直到 2017 年正式发布之前我还在使用 5.4,但我注意到它现在已经发布了。

标签: unity3d shader mask


【解决方案1】:

所以,shader 应该是这样的:

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 蒙版剪切! (不是吗?)

我使用那个纹理(或视频。没关系):

默认情况下,您的 Fragment 将如下所示:

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

第一步,让我们尝试在不使用蒙版的quad上绘制两个视频!

为此,让我们将默认纹理坐标保存在临时变量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;
}

为了控制视频的 alpha 和当前颜色,让我们添加 _ColorTint

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

所以,你可以问我,-“为什么你使用 ma​​sk.r?”,-“r 是红色的?”,-“为什么不使用 g 还是 b?”

答案:黑色是(0,0,0),白色是(1,1,1)。如果我使用其他频道(gb),它不会改变任何东西。当您将“color.a”乘以 0 时,它将是透明的。

就是这样。

对不起我的英语不好!

【讨论】:

  • 这种作品。我觉得有了你给我的好信息,我可能会弄清楚。它没有显示顶部四边形,但现在它使用 Alpha 四边形(右下角)来掩盖左下角和右上角的四边形。真的很奇怪。从侧面看,它似乎被压扁了。
  • 实际上使用您的“仅显示左/右”代码似乎可以解决它。通过改变四边形的比例很容易修复被压扁的部分(愚蠢的我)。但是颜色都是颠倒的和奇怪的。还不确定是什么原因造成的。如果我知道如何解决,我会尝试一些事情并报告。
  • @KeepCool 如果你解决了问题,请通知我。)
  • 嘿尼珀科普。除了颜色,一切都有效。我尝试使用 x 和 y 的所有 uv 数字,但我不知道它们中的任何一个是什么意思。唯一似乎可以做任何事情的是“uv1.y += 0.5f”。如果我将其更改为 0.0f,它会显示为红色。但没有忧郁。
  • @KeepCool, 在float2 uv1 = i.texcoord; 我将纹理坐标保存到临时值(默认为 0 到 1),uv1.y *= 0.5; 这意味着我想绘制纹理/视频的下半部分(纹理将在quad 仅按坐标从 0 到 0.5),并且,uv1.y +=0.5; 这意味着我们设置偏移量以绘制上半部分(将在四边形上从 0.5 渲染到 1)。工作结束后会告诉你更多=\
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-05-15
  • 2015-12-01
  • 2014-02-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多