碼字不易,轉載請注明出處喔
https://blog.csdn.net/newchenxf/article/details/119575690
分兩件事來說,一個是Unity怎么播放視頻,二是播放了,怎么把綠色的摳掉!
1 Unity播放視頻
1.1 把綠幕視頻放到Assets中
這個太簡單了,直接視頻拖到Assets下的某個目錄,例如video目錄
1.2 創建播放視頻的物件RawImage
Hierarchy面板,UI -> Raw Image,

1.3 創建RawImage輸入源即紋理Render Texture
這個將為視頻播放的輸出,也是RawImage的輸入,
在Project面板,你要的目錄下,右鍵,創建Render Texture

建立好了,在Inspector面板,改一下紋理size,最好和視頻源一樣的寬高,

1.4 Raw Image的紋理設定
把它的Texture設定為第三步新建的texture,(直接把Project面板的texture檔案,拖到箭頭區域即可),Texture可以認為是Raw Image的輸入源,

1.5 給RawImage加視頻組件
即選中Raw Image,在Inspector面板中,給他添加VideoPlayer組件,
即Add Component,選擇VideoPlayer,

1.6 配置Video Player
視頻來源,即Video Clip,選擇為前面匯入的綠幕視頻

Render Mode選擇為Render Texture,然后,目標Target Texture選擇為前面第三步新建的texture,
流程搭建完成了,
視頻的輸出到一個texture,這個texture又是Raw Image的輸入, Raw Image最終被顯示到螢屏上,
完成到6,已經可以播放視頻了,只不過,出來的是原始資料,帶綠幕的!
1.7 補充:調整輸出寬高
如果你想除錯的時候,顯示視窗是1080P,然后畫面也鋪滿,怎么辦?
一方面,調整顯示視窗寬高:
即Game視窗做如下修改:

當然了,如果你默認Game視窗沒出來,則手動打開一下:

別問我這個視窗干嘛的,這個是除錯視窗,模擬真實輸出的畫面,點擊這個:

就會自己出來了,這夠基礎了,跑偏了,,囧
好了,輸出視窗改好了,接下來,就是把Raw Image的寬高,也設定為1080P,即Inspector做如下修改,然后挪一下Raw Image位置,螢屏居中顯示,就妥了,

2 視頻處理,即摳圖
再次回到Raw Image的Inspector面板,

發現我們的Material是沒有做任何設定的,
Material是干嘛的?下文做個介紹
2.1 Material材質簡介
材質,又稱物體質地,表示一個物體的色彩、紋理、光滑度、透明度、反射率、折射率、發光度等屬性,
在Unity層面來說,材質的本質是一個Shader實體,
Shader又是什么?它是渲染管線中的GPU影像演算法程式,可以理解為,一個物件 渲染的方式,
所以,我們如果添加一個材質,就代表要怎么渲染這個物件,
2.2 添加shader
這是一個大神貢獻的shader演算法(原始碼見附錄),專業摳綠幕!把這個檔案,放到Assets下的Material目錄中:
// Created by Oliver Davies. Enjoy.
// oliver@psyfer.io
Shader "Unlit/ChromaKey"
{
Properties
{
_MainTex ("Texture", 2D) = "white" {}
_KeyColor("KeyColor", Color) = (0,1,0,0)
_TintColor("TintColor", Color) = (1,1,1,1)
_ColorCutoff("Cutoff", Range(0, 1)) = 0.2
_ColorFeathering("ColorFeathering", Range(0, 1)) = 0.33
_MaskFeathering("MaskFeathering", Range(0, 1)) = 1
_Sharpening("Sharpening", Range(0, 1)) = 0.5
_Despill("DespillStrength", Range(0, 1)) = 1
_DespillLuminanceAdd("DespillLuminanceAdd", Range(0, 1)) = 0.2
}
SubShader
{
Tags
{
"RenderPipeline"="HDRenderPipeline"
"RenderType"="HDUnlitShader"
"Queue" = "Transparent+1"
}
Blend SrcAlpha OneMinusSrcAlpha
ZWrite Off
cull off
Pass
{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
struct appdata
{
float4 vertex : POSITION;
float2 uv : TEXCOORD0;
};
struct v2f
{
float2 uv : TEXCOORD0;
float4 vertex : SV_POSITION;
//float4 uvgrab : TEXCOORD1;
};
sampler2D _MainTex;
float4 _MainTex_TexelSize;
float4 _MainTex_ST;
float4 _KeyColor;
float4 _TintColor;
float _ColorCutoff;
float _ColorFeathering;
float _MaskFeathering;
float _Sharpening;
float _Despill;
float _DespillLuminanceAdd;
//sampler2D _GrabTexture;
//float4 _GrabTexture_TexelSize;
#define GRABXYPIXEL(kernelx, kernely) tex2Dproj( _GrabTexture, UNITY_PROJ_COORD(float4(i.uvgrab.x + _GrabTexture_TexelSize.x * kernelx, i.uvgrab.y + _GrabTexture_TexelSize.y * kernely, i.uvgrab.z, i.uvgrab.w)))
// Utility functions -----------
float rgb2y(float3 c)
{
return (0.299*c.r + 0.587*c.g + 0.114*c.b);
}
float rgb2cb(float3 c)
{
return (0.5 + -0.168736*c.r - 0.331264*c.g + 0.5*c.b);
}
float rgb2cr(float3 c)
{
return (0.5 + 0.5*c.r - 0.418688*c.g - 0.081312*c.b);
}
float colorclose(float Cb_p, float Cr_p, float Cb_key, float Cr_key, float tola, float tolb)
{
float temp = (Cb_key-Cb_p)*(Cb_key-Cb_p)+(Cr_key-Cr_p)*(Cr_key-Cr_p);
float tola2 = tola*tola;
float tolb2 = tolb*tolb;
if (temp < tola2) return (0);
if (temp < tolb2) return (temp-tola2)/(tolb2-tola2);
return (1);
}
float maskedTex2D(sampler2D tex, float2 uv)
{
float4 color = tex2D(tex, uv);
// Chroma key to CYK conversion
float key_cb = rgb2cb(_KeyColor.rgb);
float key_cr = rgb2cr(_KeyColor.rgb);
float pix_cb = rgb2cb(color.rgb);
float pix_cr = rgb2cr(color.rgb);
return colorclose(pix_cb, pix_cr, key_cb, key_cr, _ColorCutoff, _ColorFeathering);
}
//-------------------------
v2f vert (appdata v)
{
v2f o;
o.vertex = UnityObjectToClipPos(v.vertex);
//o.uvgrab.xy = (float2(o.vertex.x, o.vertex.y) + o.vertex.w) * 0.5;
//o.uvgrab.zw = o.vertex.zw;
o.uv = TRANSFORM_TEX(v.uv, _MainTex);
return o;
}
float4 frag (v2f i) : SV_Target
{
// Get pixel width
float2 pixelWidth = float2(1.0 / _MainTex_TexelSize.z, 0);
float2 pixelHeight = float2(0, 1.0 / _MainTex_TexelSize.w);
//float2 uv = i.uv.xy;
//half4 grab = GRABXYPIXEL(0,0);
// Unmodified MainTex
float4 color = tex2D(_MainTex, i.uv);
// Unfeathered mask
float mask = maskedTex2D(_MainTex, i.uv);
// Feathering & smoothing
float c = mask;
float r = maskedTex2D(_MainTex, i.uv + pixelWidth);
float l = maskedTex2D(_MainTex, i.uv - pixelWidth);
float d = maskedTex2D(_MainTex, i.uv + pixelHeight);
float u = maskedTex2D(_MainTex, i.uv - pixelHeight);
float rd = maskedTex2D(_MainTex, i.uv + pixelWidth + pixelHeight) * .707;
float dl = maskedTex2D(_MainTex, i.uv - pixelWidth + pixelHeight) * .707;
float lu = maskedTex2D(_MainTex, i.uv - pixelHeight - pixelWidth) * .707;
float ur = maskedTex2D(_MainTex, i.uv + pixelWidth - pixelHeight) * .707;
float blurContribution = (r + l + d + u + rd + dl + lu + ur + c) * 0.12774655;
float smoothedMask = smoothstep(_Sharpening, 1, lerp(c, blurContribution, _MaskFeathering));
float4 result = color * smoothedMask;
// Despill
float v = (2*result.b+result.r)/4;
if(result.g > v) result.g = lerp(result.g, v, _Despill);
float4 dif = (color - result);
float desaturatedDif = rgb2y(dif.xyz);
result += lerp(0, desaturatedDif, _DespillLuminanceAdd);
return float4(result.xyz, smoothedMask);
}
ENDCG
}
}
}
接著,還是Assets/Materail目錄下,自定義一個Material:

然后,改個名字,然后,選中這個Material,Inspector面板顯示其具體引數,它的Shader默認配置了Standard,咱們改成Unlit -> ChromaKey,

這個Unlit-> ChromaKey哪里來的?
就是在上面的shader腳本,第一句話定義的:
Shader "Unlit/ChromaKey"
當你匯入這個shader,則選單上就會顯示這個選項了!
選好以后,面板的各種可選項,和代碼是息息相關的:

你可以就著代碼仔細研究一下哈,
2.3 RawImage的Material定制
上面自己加了Material,現在就可以拖到Raw Image的Materail選項了,

2.4 播放效果

這是我這里的播放效果,你需要調整箭頭的一些引數,才能保證摳圖效果完美,默認引數可能不會摳對,可能又蒙層啥的,
附錄
Unity 工程原始碼
https://github.com/newchenxf/UnityCutGreenVideo
其他參考資料
- https://blog.csdn.net/qq_42672770/article/details/108068718
- https://blog.csdn.net/cs874300/article/details/89294433
- shader演算法原始碼
- https://www.reddit.com/r/vfx/comments/ikfcrv/created_a_free_chromakey_green_screen_shader_for/
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/293437.html
標籤:其他
