找回密码
 立即注册
查看: 404|回复: 0

Unity Compute Shader入门笔记

[复制链接]
发表于 2022-3-2 15:19 | 显示全部楼层 |阅读模式
教程: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/

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

×
懒得打字嘛,点击右侧快捷回复 【右侧内容,后台自定义】
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Unity开发者联盟 ( 粤ICP备20003399号 )

GMT+8, 2024-11-17 00:30 , Processed in 0.116479 second(s), 35 queries .

Powered by Discuz! X3.5 Licensed

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表