Unity渲染 YUV420P 数据

使用 h264 解码 得到的 一般是 yuv420 格式的数据 

我解码 1920*1080分辨率 的 h264 得到的数据格式如下

Y[0,1,2,...,1920*1080-1] UV[0,1,1920*1080/2-1]

使用 unity 的shader 进行渲染 定义了 两个 TEX  

一个用来 保存 Y 变量 一个 用来 保存 uv 变量

Shader "Custom/YUV420ToRGB"
{
   Properties
	{
		_MainTex ("Texture", 2D) = "white" {}
        //_UTex ("U", 2D) = "white" {}
        //_VTex ("V", 2D) = "white" {}
		_UVTex("U", 2D) = "white" {}
  
	}
	SubShader
	{
		Tags { "RenderType"="Opaque" }
		LOD 100

		Pass
		{
			CGPROGRAM
			#pragma vertex vert
			#pragma fragment frag
		
			
			#include "UnityCG.cginc"

			struct appdata
			{
				float4 vertex : POSITION;
				float2 uv : TEXCOORD0;
			};

			struct v2f
			{
				float2 uv : TEXCOORD0;
				UNITY_FOG_COORDS(1)
				float4 vertex : SV_POSITION;
			};

            sampler2D _MainTex;
            //sampler2D _UTex;
            //sampler2D _VTex;
			sampler2D _UVTex;
			float4 _MainTex_ST;
			
			v2f vert (appdata v)
			{
				v2f o;
				o.vertex = UnityObjectToClipPos(v.vertex);
				o.uv = TRANSFORM_TEX(v.uv, _MainTex);
				UNITY_TRANSFER_FOG(o,o.vertex);
				return o;
			}
			
			fixed4 frag (v2f i) : SV_Target
			{
                //如果需要翻转画面,把下面的 进行对应的 1- 即可,例如(翻转左右则 1- i.uv.x)
                fixed2 uv = fixed2(i.uv.x, i.uv.y);
                fixed4 ycol = tex2D(_MainTex, uv);
                //fixed4 ucol = tex2D(_UTex, uv);
				//fixed4 vcol = tex2D(_VTex, uv);
				fixed4 uvcol = tex2D(_UVTex, uv);
               
                
                //如果是使用 Alpha8 的纹理格式写入各分量的值,各分量的值就可以直接取a通道的值
                //float r = ycol.a + 1.4022 * vcol.a - 0.7011;
                //float g = ycol.a - 0.3456 * ucol.a - 0.7145 * vcol.a + 0.53005;
                //float b = ycol.a + 1.771 * ucol.a - 0.8855;         

				float r = ycol.a + 1.4022 * uvcol.g - 0.7011;
				float g = ycol.a - 0.3456 * uvcol.r - 0.7145 * uvcol.g + 0.53005;
				float b = ycol.a + 1.771 * uvcol.r - 0.8855;

				return fixed4(r,g,b,1);
			}
			ENDCG
		}
	}
	FallBack "diffuse"
}

添加更新 tex 数据的函数 在 update 定时调用 YUV420ToRGB 代码如下 如下

using UnityEngine;

/// <summary>
/// 把 YUV byte[] 转为 RGB 格式的封装类
/// </summary>
public static class YUV420ToRGBWrapper
{

    static Texture2D texY = new Texture2D(1920, 1080, TextureFormat.Alpha8, false);
    static Texture2D texUV = new Texture2D(1920 >> 1, 1080 >> 1, TextureFormat.RG16, false);

    /// <summary>
    /// YUV 转为 RGB 的对外接口
    /// </summary>
    /// <param name="dataY">数据流</param>
    /// <param name="dataUV">数据流</param>
    /// <param name="width">yuv 宽</param>
    /// <param name="height">yuv 高</param>
    /// <param name="renderer">要渲染的 Renderer</param>
    public static void YUV420ToRGB(byte[] dataY, byte[] dataUV, Renderer renderer)
    {
        // 把数据下载到对应 YUV 贴图中
        texY.LoadRawTextureData(dataY);
        texUV.LoadRawTextureData(dataUV);
        texY.Apply();
        texUV.Apply();
        // 把 YUV 贴图中 数据传给 shader 进行 RGB 解析显示
        renderer.sharedMaterial.SetTexture("_MainTex", texY);
        renderer.sharedMaterial.SetTexture("_UVTex", texUV);
    }
}

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值