教程: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纹理作为输出[numthreads(8,8,1)] //?指定GPU用于此计算的线程(暂不理解,沿用此默认设置)void CSMain(uint3 id : SV_DispatchThreadID){ Result[id.xy] = 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[c]; 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/ |