最近讨论在unity播放带alpha通道的视频,一开始一点效果也没有,然后搜索各种解决方案,总结出三种不太好的方案,有更好的方案的希望大家提出来。
方案重点两个方面:
1.能否播放带alpha通道的视频
2.播放的视频和三维场景的层级关系
1.剔除
使用一个剔除的shader,不渲染黑色部分
shader代码如下:
Shader "AlphaVideo/CullingVideo" { Properties { _MainTex("Base (RGB)", 2D) = "white" {} _AlphaOffsetX("alpha offset x", float) = 0.5 _AlphaOffsetY("alpha offset y", float) = 0 _Cutoff("Cutoff", Range(-1,0)) = -0.3 } SubShader { //Lighting Off AlphaTest Less[_Cutoff] Tags{ "Queue" = "Transparent-20" "IgnoreProjector" = "True" "RenderType" = "Transparent" } LOD 300 CGPROGRAM #pragma surface surf Lambert alphatest:_Cutoff sampler2D _MainTex; float _AlphaOffsetX; float _AlphaOffsetY; struct Input { float2 uv_MainTex; }; void surf(Input IN, inout SurfaceOutput o) { half4 c = tex2D(_MainTex, IN.uv_MainTex); IN.uv_MainTex.x += _AlphaOffsetX; IN.uv_MainTex.y += _AlphaOffsetY; half4 d = tex2D(_MainTex, IN.uv_MainTex); o.Albedo = c.rgb; o.Alpha = ((d.r*-1) + 1)*-1; } ENDCG } // FallBack "Diffuse" FallBack "Transparent/Diffuse" }
编写一个播放视频的C#脚本如下:
using UnityEngine; using System.Collections; public class MovieControl : MonoBehaviour { public MovieTexture movie; public AudioClip movieSound; void Start() { Play(); } public void Play() { if (movie != null) { MovieTexture temp = (MovieTexture)gameObject.GetComponent<MeshRenderer>().sharedMaterial.mainTexture; if (temp != null) { temp.Stop(); } gameObject.GetComponent<MeshRenderer>().sharedMaterial.mainTexture = movie; movie.Play(); if (movieSound != null) { GetComponent<AudioSource>().clip = movieSound; GetComponent<AudioSource>().Play(); } } } public void Stop() { movie.Stop(); } }
在场景的面板前后简历两个小方块,测试视频与3d的顺序问题:
效果如图:
第一种方案满足条件2,条件1的效果不好。
2.shader叠加遮罩
这种方案需要两个视频叠加,这里是重网上下载的测试视频,视频图和遮罩图如下:
使用的shader如下:
Shader "AlphaVideo/MaskVideo" { Properties { _MainTex("MainTex", 2D) = "white" {} _Mask("Mask", 2D) = "white" {} _Transparency("Transparency", Range(0, 1)) = 0 _Color("Color", Color) = (0.4485294,0.310013,0.310013,1) [HideInInspector]_Cutoff("Alpha cutoff", Range(0,1)) = 0.5 } SubShader { Tags { "IgnoreProjector" = "True" "Queue" = "Transparent" "RenderType" = "Transparent" } Pass { Name "FORWARD" Tags {"LightMode" = "ForwardBase"} Blend SrcAlpha OneMinusSrcAlpha ZWrite Off CGPROGRAM #pragma vertex vert #pragma fragment frag #define UNITY_PASS_FORWARDBASE #include "UnityCG.cginc" #include "UnityPBSLighting.cginc" #include "UnityStandardBRDF.cginc" #pragma multi_compile_fwdbase #pragma exclude_renderers gles3 metal d3d11_9x xbox360 xboxone ps3 ps4 psp2 #pragma target 3.0 uniform sampler2D _MainTex; uniform float4 _MainTex_ST; uniform sampler2D _Mask; uniform float4 _Mask_ST; uniform float _Transparency; uniform float4 _Color; struct VertexInput { float4 vertex : POSITION; float2 texcoord0 : TEXCOORD0; }; struct VertexOutput { float4 pos : SV_POSITION; float2 uv0 : TEXCOORD0; }; VertexOutput vert(VertexInput v) { VertexOutput o = (VertexOutput)0; o.uv0 = v.texcoord0; o.pos = mul(UNITY_MATRIX_MVP, v.vertex); return o; } float4 frag(VertexOutput i) : COLOR { float4 _MainTex_var = tex2D(_MainTex,TRANSFORM_TEX(i.uv0, _MainTex)); float3 emissive = (_Color.rgb*_MainTex_var.rgb); float3 finalColor = emissive; float4 _Mask_var = tex2D(_Mask,TRANSFORM_TEX(i.uv0, _Mask)); return fixed4(finalColor,((lerp(lerp(lerp(_Mask_var.b, _Mask_var.r, _Mask_var.rgb.r), _Mask_var.g, _Mask_var.rgb.g), _Mask_var.b, _Mask_var.rgb.b))*_Transparency)); } ENDCG } } FallBack "Diffuse" CustomEditor "ShaderForgeMaterialInspector" }
实现效果如图:
这种效果能同时满足条件1和2,但是要两个视频,比较麻烦,不知道有没有大神知道其他方案,遮罩换成图片也行。
3.unity自带的shader
首先用untiy的FX/Flare的shader,两种视频的播放效果如图:
发现能满足条件1,不能满足条件2,然后发现太亮了
然后unity自带的shader Particles/Addtive
效果如图:
亮度可以降下来,失去了视频原来的颜色,这也是醉了,所以,各位朋友们有其它更好的方案的欢迎交流。
时间: 2024-11-02 23:20:27