使用Unity直接渲染YUV420格式

最近好久没来写些字了。

工作中发现YUV420格式转为RGB格式,最后也还是要渲染的,
所以考虑直接渲染,节约了CPU工作量,GPU做这种粗活非常擅长的。

话不多说,开始编码。
先说一下开发环境,使用的是,Windows10 + Unity5.3.6
其实用什么版本的Unity没关系,(最新的Unity2018.2最好,这个版本非常强大)
我写的是普通顶点/片段shader.

1、了解YUV420格式

这个可以看我的《YUV格式初探》嘿嘿。
主要分为I420 , YV12, NV12, NV21.
这4种都是12bits表达8个像素,比起rgb888格式,24bits表达8像素,节约了一半空间
具体布局如下:
I420: YYYYYYYY UU VV =>YUV420P

YV12: YYYYYYYY VV UU =>YUV420P

NV12: YYYYYYYY UVUV =>YUV420SP

NV21: YYYYYYYY VUVU =>YUV420SP

2、创建Shader

首先创建一个空白shader,再创建一个材质球Material,把shader赋给它,
然后把这个材质球Material挂到需要渲染的UI组件上去,比如Image/RawImage。

3、创建贴图Texture

根据上述的格式,可以看出:
YUV420P里Y,U,V分量数据明显的分为3块,I420,YV12两种的区别只是U和V分量数据顺序不同罢了,并不影响我们使用。那我们可以创建 3 个贴图Texture,分别存放Y,U,V分量数据,然后再片段着色器里做 3 次采样Sampler,然后重新计算为RGB颜色。
3 张贴图都使用8bits的格式,例如Alpha8。要注意U,V贴图的尺寸只有Y的1/4哦。
YUV420SP里Y,U,V分量数据明显的分为2块,Y分量单独一块,UV分量混杂在一起作为一块。NV12,NV21两种的区别只是U和V分量数据顺序不同罢了。那我们就要创建 2 个贴图Texture,分别存放Y分量和UV分量数据,然后再片段着色器里做2次采样Sampler,然后重新计算为RGB颜色。
Y分量贴图要使用8bits格式,例如Alpha8,UV分量贴图要使用16bits格式,例如我就用的RGBA4444,RGBA各占4bits,然后把RG通道重组为U, BA通道重组为V。要注意UV贴图的尺寸只有Y的1/4哦。

float u = (uv4.r * 15 * 16 + uv4.g * 15) / 255 - 0.5; 
float v = (uv4.b * 15 * 16 + uv4.a * 15) / 255 - 0.5;

当然你也可以用其他格式比如RGB888,但你只用R,G通道等等。
Do whatever you want.

4、Show me the code

话不多说,直接上代码了。
我就以NV12格式举例:
创建贴图

m_YImageTex = new Texture2D(ImageXSize, ImageYSize, TextureFormat.Alpha8, false);
m_UVImageTex = new Texture2D(ImageXSize / 2, ImageYSize / 2, TextureFormat.RGBA4444, false);

给shader设置数据

YUVTex.material.SetTexture("_MainTex" , YData);
YUVTex.material.SetTexture("_UVTex", UVData); 

shader本体

Shader "Custom/UI/YUVRender"
{
    Properties
    {
        _MainTex ("Texture", 2D) = "white" {}
        _UVTex ("Texture", 2D) = "white" {}
    }
    SubShader
    {
        // No culling or depth
        Cull Off ZWrite Off ZTest Always

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

            v2f vert (appdata v)
            {
                v2f o;
                o.vertex = mul(UNITY_MATRIX_MVP, v.vertex);
                o.uv = v.uv;
                return o;
            }
            
            sampler2D _MainTex;
            sampler2D _UVTex;

            fixed4 frag (v2f i) : SV_Target
            {
                fixed4 col = tex2D(_MainTex, i.uv);
                fixed4 uv4 = tex2D(_UVTex, i.uv);
                float y = 1.1643 * (col.a - 0.0625);
                float u = (uv4.r * 15 * 16 + uv4.g * 15) / 255 - 0.5; 
                float v = (uv4.b * 15 * 16 + uv4.a * 15) / 255 - 0.5;

                //float r = y + 1.596 * v;
                //float g = y - 0.391  * u - 0.813 * v;
                //float b = y + 2.018  * u;
                float r = y + 1.403 * v;
                float g = y - 0.344  * u - 0.714 * v;
                float b = y + 1.770  * u;
                col.rgba = float4(r, g, b, 1.f);
                return col;
            }
            ENDCG
        }
    }
}

然后就是每帧更新YData和UVData数据,就可以正常渲染了


就酱。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 220,137评论 6 511
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,824评论 3 396
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 166,465评论 0 357
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 59,131评论 1 295
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 68,140评论 6 397
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,895评论 1 308
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,535评论 3 420
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,435评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,952评论 1 319
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 38,081评论 3 340
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,210评论 1 352
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,896评论 5 347
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,552评论 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 32,089评论 0 23
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,198评论 1 272
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,531评论 3 375
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 45,209评论 2 357

推荐阅读更多精彩内容