Unity ComputeShader 基础语法与使用教程

Unity ComputeShader 基础语法与使用教程

一、基础概念

ComputeShader 是 Unity 中利用 GPU 并行计算能力的工具,适用于大规模数据处理(如粒子模拟、图像处理、物理计算等)。其核心特点:

  • 独立于渲染管线:不依赖顶点/片元着色器,直接操作内存数据。
  • 并行计算:通过线程组(Thread Groups)实现多线程并行处理。
  • 数据驱动 :通过 ComputeBufferRWTexture2D 在 CPU/GPU 间传递数据。
二、基础语法
1. 创建 ComputeShader 文件

在 Unity 项目中右键点击 AssetsCreate → Shader → Compute Shader ,生成 .compute 文件。

2. 核函数(Kernel)定义
  • 使用 #pragma kernel 声明核函数入口(可定义多个)。

  • 示例:

    复制代码
    `#pragma kernel ProcessData // 声明核函数名
    
    // 定义可读写纹理(输出目标)
    RWTexture2D<float4> Result;
    
    // 线程组配置:每个线程组包含 8x8x1 个线程
    [numthreads(8, 8, 1)]
    void ProcessData (uint3 id : SV_DispatchThreadID) {
        // id.xy 表示当前线程处理的纹理坐标
        Result[id.xy] = float4(1.0, 0.0, 0.0, 1.0); // 填充红色
    }`
    • [numthreads(x,y,z)]:定义线程组大小(通常为 8x8x1256x1x1)。
    • SV_DispatchThreadID:全局线程索引,用于定位数据。
3. 数据类型与缓冲区
  • RWTexture2D<float4>:可读写纹理,用于图像处理。

  • RWStructuredBuffer<T> :结构化缓冲区,存储任意类型数据(如粒子位置、速度)。

    复制代码
    `struct Particle {
        float3 position;
        float3 velocity;
    };
    RWStructuredBuffer<Particle> Particles;`
三、C# 脚本调用流程
1. 初始化资源
  • 创建 RenderTexture(纹理输出)

    复制代码
    `RenderTexture outputTexture = new RenderTexture(256, 256, 24);
    outputTexture.enableRandomWrite = true; // 允许 GPU 写入
    outputTexture.Create();`
  • 创建 ComputeBuffer(结构化数据)

    复制代码
    `int particleCount = 100000;
    ComputeBuffer particleBuffer = new ComputeBuffer(particleCount, sizeof(float) * 6); // 3位置+3速度`
2. 调用 ComputeShader
  • 获取核函数索引

    复制代码
    `int kernelHandle = computeShader.FindKernel("ProcessData");`
  • 设置参数

    复制代码
    `computeShader.SetTexture(kernelHandle, "Result", outputTexture); // 传递纹理
    computeShader.SetBuffer(kernelHandle, "Particles", particleBuffer); // 传递缓冲区`
  • 计算线程组数量

    复制代码
    `uint threadGroupsX = Mathf.CeilToInt(256 / 8f); // 纹理宽度 / 线程组x维度
    uint threadGroupsY = Mathf.CeilToInt(256 / 8f); // 纹理高度 / 线程组y维度`
  • 启动计算

    复制代码
    `computeShader.Dispatch(kernelHandle, threadGroupsX, threadGroupsY, 1);`
3. 释放资源
复制代码
`void OnDestroy() {
    particleBuffer?.Release(); // 释放 ComputeBuffer
    outputTexture?.Release();  // 释放 RenderTexture
}`
四、完整示例:图像灰度化
1. ComputeShader 代码
复制代码
`#pragma kernel Grayscale
RWTexture2D<float4> InputOutput; // 输入输出共用同一纹理

[numthreads(8, 8, 1)]
void Grayscale (uint3 id : SV_DispatchThreadID) {
    float4 color = InputOutput[id.xy];
    float gray = dot(color.rgb, float3(0.299, 0.587, 0.114)); // 加权平均
    InputOutput[id.xy] = float4(gray, gray, gray, color.a);
}`
2. C# 脚本
复制代码
`using UnityEngine;

public class GrayscaleProcessor : MonoBehaviour {
    public ComputeShader computeShader;
    public RenderTexture inputTexture;

    void Start() {
        // 确保输入纹理可写
        inputTexture.enableRandomWrite = true;

        // 获取核函数
        int kernelHandle = computeShader.FindKernel("Grayscale");

        // 设置参数
        computeShader.SetTexture(kernelHandle, "InputOutput", inputTexture);

        // 计算线程组
        uint threadGroupsX = Mathf.CeilToInt(inputTexture.width / 8f);
        uint threadGroupsY = Mathf.CeilToInt(inputTexture.height / 8f);

        // 启动计算
        computeShader.Dispatch(kernelHandle, threadGroupsX, threadGroupsY, 1);
    }
}`
五、关键注意事项
  1. 线程组大小优化
    • 根据硬件调整 numthreads(如 NVIDIA GPU 擅长 32x1x1,AMD 擅长 16x16x1)。
    • 总线程数 = numthreads.x * numthreads.y * numthreads.z * Dispatch(x,y,z)
  2. 数据传递性能
    • 避免每帧频繁调用 SetData/GetData,尽量在 GPU 端完成所有计算。
    • 使用 ComputeBuffer.SetCounterValue 实现动态数据扩容(如粒子系统)。
  3. 同步问题
    • GPU 计算是异步的,若需同步等待,使用 ComputeShader.WaitForCompletion()(慎用,可能卡顿)。
  4. 平台兼容性
    • 移动端需检查 SystemInfo.supportsComputeShader,部分低端设备不支持。
相关推荐
小清兔4 小时前
一个unity中URP的环境下旋转天空盒的脚本(RotationSky)
开发语言·数据库·学习·程序人生·unity·c#·游戏引擎
EQ-雪梨蛋花汤4 小时前
【Unity笔记】 WorldStreamer2指南——针对大世界的流式加载与优化
笔记·unity·游戏引擎
迪普阳光开朗很健康4 小时前
适用Unity的AndroidStudio项目自动修改打包文件名称的方案
unity·游戏引擎
米芝鱼5 小时前
Unity自定义按钮
算法·ui·unity·游戏引擎·编辑器扩展
米芝鱼5 小时前
Unity自定义TextImage,鼠标悬浮显示信息
算法·ui·unity·编辑器·游戏引擎·图形渲染
阿Q说代码6 小时前
开篇:从理论到实践,体验openEuler嵌入式开发全流程
unity·游戏引擎
qq_2052790520 小时前
Unity log工具 Unity Logviewer插件
unity·游戏引擎
tealcwu1 天前
【Unity实战】如何使用VS Code在真实iOS设备上调试 Unity应用
unity·游戏引擎·iphone
冰凌糕1 天前
Unity3D Shader 顶点和片段着色器
unity