Initialize Texture2D[ ]

7 篇文章 0 订阅


    在Unity中播放YUV视频时,采用每帧播放时再将YUV转化成RGB然后传入着色器的方式不仅会造成大量的内存开销,而且会造成播放卡顿的现象。
    为了解决这个问题笔者尝试将视频源在Start()中先全部转化成RGB存放在Texture2D[ ]数组中,然后在每帧渲染时直接从数组中索引对应的纹理即可,播放速度提升了50倍以上。

初始化数组长度

public Texture2D[] ts;
ts = new Texture2D[Length];

详细可参考:数组的初始化 array initializer is not allowed here

初始化元素

for (i = 0; i < frameCount; i++)
    ts[i] = new Texture2D(width, height, TextureFormat.RGB24, false); 

参考Texture2D初始化即可

参考代码

该例程实现了YUV420视频播放器的功能:

using System.Collections;
using System.Collections.Generic;
using System.IO;
using UnityEngine;
using UnityEngine.UI;
using System;

public class RGBPlayer : MonoBehaviour
{

    public int frameCount;
    private int frameNow = 0;
    private int frameOffset = 0;

    byte[] file;//最大值255

    //public Renderer target;

    private int w = 2048;
    private int h = 2048;

    //原始纹理t
    public Texture2D t = null;
    public Texture2D[] ts;
    public Renderer target;

    private byte Y00, Y01, Y10, Y11;//Y分量     
    private float R00, G00, B00;
    private float R01, G01, B01;
    private float R10, G10, B10;
    private float R11, G11, B11;
    int i, k;
    int mY;//颠倒y值

    private int Ysize;
    private int UorVsize;
    private byte U, V;
    private int offset;


    // Plana 連續儲存,Packed 交錯儲存
    // 使用 Plana YUV420 格式
    void Start()
    {

        //一次读取所有比特
        file = File.ReadAllBytes("D:/FFMPEG/bin/2048_2048_420_8b.yuv");

        frameCount = GetFrameCount(file, w, h); // 影像寬高
                                                //输出总帧数
        frameCount = 150;
        print("Frame Count : " + frameCount);

        
        ConvertRGB(file, w, h);
        
    }

    void Update()
    {

        if (frameNow > frameCount - 1) return;

        ts[frameNow].Apply();

        target.sharedMaterial.SetTexture("_MainTex", ts[frameNow]);

        frameNow++;

        print("Frame : " + (frameNow) + " (" + (int)(frameNow / (float)(frameCount) * 100) + "%)");
    }

    int GetFrameCount(byte[] file, int width, int height)
    {
        return file.Length / ((width * height) * 3 / 2);
    }

    void ConvertRGB(byte[] file, int width, int height)
    {
        ts = new Texture2D[frameCount];
        for (; frameOffset < frameCount; frameOffset++)
        {
            ts[frameOffset] = new Texture2D(width, height, TextureFormat.RGB24, false); 

            Ysize = width * height;
            UorVsize = width * height / 4;

            U = 0;
            V = 0;

            k = 0;
            //offset偏移量
            int offset = frameOffset * ((width * height) * 3 / 2);

            for (int y = 0; y < height; y += 2)
            {
                for (int x = 0; x < width; x += 2)
                {
                    U = file[offset + Ysize - 1 + k++]; //注意要减一
                    V = file[offset + Ysize - 1 + k + UorVsize];  //注意要减一

                    i = y * width + x;
                    mY = height - 1 - y;

                    Y00 = file[offset + i];
                    Y01 = file[offset + i + width];
                    Y10 = file[offset + i + 1];
                    Y11 = file[offset + i + width + 1];


                    R00 = (Y00 + 1.4075f * (V - 128)) / 255f;
                    G00 = (Y00 - 0.3455f * (U - 128) - 0.7169f * (V - 128)) / 255f;
                    B00 = (Y00 + 1.779f * (U - 128)) / 255f;

                    R01 = (Y01 + 1.4075f * (V - 128)) / 255f;
                    G01 = (Y01 - 0.3455f * (U - 128) - 0.7169f * (V - 128)) / 255f;
                    B01 = (Y01 + 1.779f * (U - 128)) / 255f;

                    R10 = (Y10 + 1.4075f * (V - 128)) / 255f;
                    G10 = (Y10 - 0.3455f * (U - 128) - 0.7169f * (V - 128)) / 255f;
                    B10 = (Y10 + 1.779f * (U - 128)) / 255f;

                    R11 = (Y11 + 1.4075f * (V - 128)) / 255f;
                    G11 = (Y11 - 0.3455f * (U - 128) - 0.7169f * (V - 128)) / 255f;
                    B11 = (Y11 + 1.779f * (U - 128)) / 255f;

                    ts[frameOffset].SetPixel(x, h * frameOffset + mY, new Color(R00, G00, B00, 1)) ; //注意y存储顺序,第一帧在最下面
                    ts[frameOffset].SetPixel(x, h * frameOffset + mY - 1, new Color(R01, G01, B01, 1));
                    ts[frameOffset].SetPixel(x + 1, h * frameOffset + mY, new Color(R10, G10, B10, 1));
                    ts[frameOffset].SetPixel(x + 1, h * frameOffset + mY - 1, new Color(R11, G11, B11, 1));
                }
            }                      
        }
    }
}

参考链接

Unity3D-Documentation-Texture2DArray
Unity中Texture2DArray使用小结
Texture2DArray 功能测试

这个报错的意思是这个着色器脚本中必须同时包含顶点着色器和片元着色器,但是它只找到了其中一个,所以编译失败。 为了解决这个问题,你需要在着色器脚本中同时包含顶点着色器和片元着色器的代码。你可以检查一下你的着色器脚本是否有缺失顶点着色器或片元着色器的部分。如果有,你需要将其添加到脚本中。 在这个着色器脚本中,你需要在Pass块中添加顶点着色器和片元着色器的代码。其中,顶点着色器的函数名为"vert",片元着色器的函数名为"frag"。你需要将这两个函数添加到Pass块中,并且在顶点着色器中对输入的顶点数据进行处理,并将处理后的数据传递给片元着色器进行渲染。 以下是修改后的代码: ``` Shader "Custom/URP Blinking" { Properties { _MainTex ("Texture", 2D) = "white" {} _Color ("Color", Color) = (1,1,1,1) _BlinkSpeed ("Blink Speed", Range(0.1, 10)) = 1 } SubShader { Tags {"Queue"="Transparent" "RenderType"="Opaque"} Pass { HLSLPROGRAM #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl" #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Lighting.hlsl" CBUFFER_START(UnityPerMaterial) UNITY_DEFINE_PER_MATERIAL_MAIN_LIGHT_SHADOW(UnityPerMaterialShadow) float4 _Color; float _BlinkSpeed; float _Time; float4 _MainTex_ST; TEXTURE2D(_MainTex); SAMPLER(sampler_MainTex); CBUFFER_END 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 = UnityObjectToClipPos(v.vertex); o.uv = TRANSFORM_TEX(v.uv, _MainTex); return o; } fixed4 frag (v2f i) : SV_Target { float4 tex = UnitySampleTexture(sampler_MainTex, _MainTex, i.uv * _MainTex_ST.xy + _MainTex_ST.zw); float t = _Time * _BlinkSpeed; float blink = sin(t) * 0.5 + 0.5; fixed4 col = lerp(_Color, float4(1,1,1,1), blink); return tex * col; } ENDHLSL CGPROGRAM #pragma vertex vert #pragma fragment frag ENDCG } } FallBack "Diffuse" } ``` 请注意,在这里,我们将顶点着色器和片元着色器的代码分别放置在了HLSLPROGRAM和CGPROGRAM标签中,并使用#pragma vertex和#pragma fragment指令来告诉Unity哪一个是顶点着色器,哪一个是片元着色器。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值