Unity 3D : RAW 10 bit 轉 RGB ( GPU 版 ) [ 舊版本 ]

前言 :

也許你想先看 CPU 版,任意門 :

https://blog.csdn.net/weixin_38884324/article/details/80458545

另外這篇的新版本在這

https://blog.csdn.net/weixin_38884324/article/details/80673220

這裡是記錄我之前多蠢的樣子,請不要參考也不要亂學,不過是可以當負面教材就是哈。

C # :

using System.IO;
using UnityEngine;
using UnityEngine.UI;

public class GPU_RAW_To_RGB : MonoBehaviour {

    public RawImage outputImage;
    public RawImage outputImage2;
    public ComputeShader shader;

    int[] a;

    void Start()
    {
        print("是否支持 GPU 運算 ? "+SystemInfo.supportsComputeShaders);


        System.Diagnostics.Stopwatch time = new System.Diagnostics.Stopwatch();
        time.Start();

        a = ByteArray_To_IntArray(File.ReadAllBytes("C:/FFMPEG/Hello.raw"));

        time.Stop();
        print("檔案讀取 " + time.Elapsed.TotalSeconds + " 秒");

        Run();
    }

    // 之後這裡寫成多線程 (多執行序) 速度也許會快點
    int[] ByteArray_To_IntArray(byte [] b) {
        int[] i = new int[b.Length];

        for (int x = 0; x < b.Length; x++)
        {
            i[x] = b[x];
        }
        return i;
    }

    public void Run()
    {
        System.Diagnostics.Stopwatch time = new System.Diagnostics.Stopwatch();
        time.Start();

        // 預先必須要先知道圖片寬高,因為 RAW 檔案沒有寬高的資訊
        int width = 4208;
        int height = 3120;

        // ------------------------------------------------
        //初始化 RAW 圖片

        RenderTexture t = new RenderTexture(width, height, 24);
        t.enableRandomWrite = true;
        t.Create();
        outputImage.texture = t;

        // ------------------------------------------------
        //初始化 RGB 圖片

        RenderTexture t2 = new RenderTexture(width, height, 24);
        t2.enableRandomWrite = true;
        t2.Create();
        outputImage2.texture = t2;

        // ------------------------------------------------
        // CSMain

        int k = shader.FindKernel("CSMain");

        ComputeBuffer buffer = new ComputeBuffer(a.Length, 4);
        buffer.SetData(a);
        shader.SetBuffer(k, "a", buffer);

        shader.SetInt("width", width);
        shader.SetInt("height", height);

        shader.SetTexture(k, "outputTexture", t);

        shader.Dispatch(k, width, height, 1);

        // ------------------------------------------------
        // ToRGB

        int k2 = shader.FindKernel("ToRGB");
        shader.SetInt("width", width);
        shader.SetInt("height", height);
        shader.SetTexture(k2, "outputTexture", t);
        shader.SetTexture(k2, "outputTexture2", t2);
        shader.Dispatch(k2, width, height, 1);

        // 釋放
        buffer.Dispose();

        time.Stop();
        print("GPU 執行 " + time.Elapsed.TotalSeconds + " 秒");
    }
}

ComputeShader :

#pragma kernel CSMain

int width;
int height;

// ( CPU -> GPU )
StructuredBuffer<int> a;

// ( GPU -> CPU )
RWTexture2D <float4> outputTexture;
RWTexture2D <float4> outputTexture2;

[numthreads(1, 1, 1)]
void CSMain(uint3 id : SV_DispatchThreadID, uint3 _group_thread_id : SV_GroupThreadID)
{
    int i = ((width * id.y) + id.x) * 2; // 因為 RAW 10bit 佔用 2 個 byte 所以要乘二

    int L = a[i];
    int H = a[i + 1];
    int D = (H << 8) + L;

    float C = D / 1024.0f;

    float4 color;

    if (id.y % 2 == 0)
    {
        if (id.x % 2 == 0)
        {
            color = float4(0, C, 0, 1);
        }
        else
        {
            color = float4(C, 0, 0, 1);
        }
    }
    else
    {
        if (id.x % 2 == 0)
        {
            color = float4(0, 0, C, 1);
        }
        else
        {
            color = float4(0, C, 0, 1);
        }
    }

    int y_mirror = height - 1 - id.y; // 上下反轉

    outputTexture[float2(id.x, y_mirror)] = color; // 丟回 CPU    
}

#pragma kernel ToRGB

[numthreads(1, 1, 1)]
void ToRGB(uint3 id : SV_DispatchThreadID, uint3 _group_thread_id : SV_GroupThreadID) {

    // 注意這是左下角
    if (id.y % 2 == 0) {
        if (id.x % 2 == 0) {

            int X = id.x;
            int Y = id.y;

            // 不採用 Y 軸反轉了,Debug 累了,就直接從左下角算吧

            float4 _B = outputTexture[float2(X, Y)];
            float4 _Gr = outputTexture[float2(X, Y + 1)];
            float4 _Gb = outputTexture[float2(X + 1, Y)];
            float4 _R = outputTexture[float2(X + 1, Y + 1)];

            float Gr = _Gr[1];
            float B = _B[2];
            float R = _R[0];
            float Gb = _Gb[1];

            float G = (Gr + Gb) / 2;

            float4 color = float4(R, G, B, 1);

            // 丟回 CPU :
            //
            // 理論上 RAW 轉 RGB 解析度會是原來的四分之一
            // 但是這裡我的 RAW 與 RGB 是一樣大小,所以要補足另外三個空缺顏色
            outputTexture2[float2(X, Y)] = color;
            outputTexture2[float2(X, Y + 1)] = color;
            outputTexture2[float2(X + 1, Y)] = color;
            outputTexture2[float2(X + 1, Y + 1)] = color;
        }
    }
}

这里写图片描述

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值