教程: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。
运行后该RT被生成,Ctrl+单击看到纹理预览。
将代码挂到相机上,并将这段代码移到
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中增加表示分辨率的变量,传入分辨率参数,使输出颜色与归一化坐标相关。
加速案例
使用compute buffer
为若干个Mesh指定随机颜色,重复次数越高生成的越慢
原来的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();
}
}
重复次数提高后有明显延迟(用
Time.realtimeSinceStartup
获得帧内延迟,Time.time
为当前帧开始时的时间)
修改为使用cs来完成计算任务:
将cs代码改为生成随机颜色:
效果get:
第二次及其以后运行都变快了?
快到离谱:
原来CPU版的速度:
用来生成3D噪声也会非常不错
后续:可以用GPU加速实现unity中的路径追踪
http://three-eyed-games.com/2018/05/03/gpu-ray-tracing-in-unity-part-1/