RecursiveFrog 发表于 2022-3-2 15:19

Unity Compute Shader入门笔记

教程:https://www.youtube.com/watch?v=BrZ4pWwkpto
官方手册:https://docs.unity3d.com/Manual/class-ComputeShader.html
简单理解


compute shader(cs)使用HLSL语言,将一些原本由cpu执行的计算过程分摊到gpu单元高效完成。用于生成噪声等程序化的东西。
compute buffer:是CPU与GPU之间传输数据的通道
官方提示:用好cs需要对GPU架构的深入理解等
基础使用


新建一个cs:
#pragma kernel CSMain //指定要编译的函数为kernel 可以指定多个RWTexture2D<float4> Result; //可读写的2D纹理作为输出 //?指定GPU用于此计算的线程(暂不理解,沿用此默认设置)void CSMain(uint3 id : SV_DispatchThreadID){   Result = float4(id.x & id.y, (id.x & 15)/15.0, (id.y & 15)/15.0, 0.0);}
由于cs不像普通shader一样与材质或mesh关联(从而自动被执行),我们需要在代码中显示调用该cs。


Snipaste_2022-03-01_16-04-08.png

运行后该RT被生成,Ctrl+单击看到纹理预览。

image.png


image.png

将代码挂到相机上,并将这段代码移到OnRenderImage函数中,使得该RT被显示出来。

    private void OnRenderImage(RenderTexture source, RenderTexture destination)    {      if (renderTexture == null)      {            renderTexture = new RenderTexture(256, 256, 24);            renderTexture.enableRandomWrite = true;            renderTexture.Create();      }      computeShader.SetTexture(0, "Result", renderTexture);      computeShader.Dispatch(0, renderTexture.width / 8, renderTexture.height / 8, 1);      Graphics.Blit(renderTexture, destination);    }}
在cs中增加表示分辨率的变量,传入分辨率参数,使输出颜色与归一化坐标相关。


image.png


image.png

加速案例


使用compute buffer
为若干个Mesh指定随机颜色,重复次数越高生成的越慢


image.png


image.png

原来的c#代码:
using System.Collections;using System.Collections.Generic;using UnityEngine;using UnityEngine.UI;public class RandomColor : MonoBehaviour{    public int repetitions = 1;    public int childrenCount = 10;    public GameObject sample;    private float time;    public Text timeLabel;    private List<GameObject> objects;    // Start is called before the first frame update    void Start()    {      objects = new List<GameObject>();      for(int i = 0; i < childrenCount; i++)      {            for (int j = 0; j < childrenCount; j++)            {                GameObject go = Instantiate(sample,transform);                objects.Add(go);                go.transform.position = new Vector3(-childrenCount/2 + i , -childrenCount/2 + j, go.transform.position.z);            }      }    }    public void OnRandomize()    {      time = Time.realtimeSinceStartup;      for (int i = 0; i <repetitions; i++)      {            for (int c = 0; c <objects.Count; c++)            {                GameObject obj = objects;                obj.GetComponent<MeshRenderer>().material.SetColor("_Color", Random.ColorHSV());            }      }      time = Time.realtimeSinceStartup - time;      timeLabel.text = "Process Time = "+ time.ToString();    }}


image.png


image.png

重复次数提高后有明显延迟(用Time.realtimeSinceStartup获得帧内延迟,Time.time为当前帧开始时的时间)

修改为使用cs来完成计算任务:


image.png


image.png


image.png

将cs代码改为生成随机颜色:


image.png

效果get:


image.png

第二次及其以后运行都变快了?

image.png

快到离谱:


image.png


image.png

原来CPU版的速度:

image.png

用来生成3D噪声也会非常不错
后续:可以用GPU加速实现unity中的路径追踪
http://three-eyed-games.com/2018/05/03/gpu-ray-tracing-in-unity-part-1/
页: [1]
查看完整版本: Unity Compute Shader入门笔记