本文主要记录自己学习的简单总结:主要是绘制数字表面。

作者把这篇归类为Unity基础,看来我连Unity基础都不会!!!

效果图:作者代码不是彩色,我没有把ShaderGraph图里Z值设置0,所以是彩色的

下面代码作者已修改!!!如果三个轴向非统一缩放可以不改

中文学习链接
原文链接
链接中的这一节主要在上一节的基础上,利用ComputerShader把绘制Mesh的任务放到GPU上。
ComputerShader和传统说的VS和FS不一样,ComputerShader具有通用性,把在CPU端的耗时任务放到GPU处理。

源代码:

using UnityEngine;public class GPUGraph : MonoBehaviour
{const int maxResolution = 1000;static readonly intpositionsId = Shader.PropertyToID("_Positions"),resolutionId = Shader.PropertyToID("_Resolution"),scaleId = Shader.PropertyToID("_Scale"),stepId = Shader.PropertyToID("_Step"),timeId = Shader.PropertyToID("_Time"),transitionProgressId = Shader.PropertyToID("_TransitionProgress");[SerializeField]ComputeShader computeShader = default;[SerializeField]Material material = default;[SerializeField]Mesh mesh = default;[SerializeField, Range(1, maxResolution)]int resolution = 10;[SerializeField]FunctionLibrary.FunctionName function = default;public enum TransitionMode { Cycle, Random }[SerializeField]TransitionMode transitionMode = TransitionMode.Cycle;[SerializeField, Min(0f)]float functionDuration = 1f, transitionDuration = 1f;float duration;bool transitioning;FunctionLibrary.FunctionName transitionFunction;ComputeBuffer positionsBuffer;void OnEnable(){positionsBuffer = new ComputeBuffer(maxResolution * maxResolution, 3 * 4);}void OnDisable(){positionsBuffer.Release();positionsBuffer = null;}void Update(){duration += Time.deltaTime;if (transitioning){if (duration >= transitionDuration){duration -= transitionDuration;transitioning = false;}}else if (duration >= functionDuration){duration -= functionDuration;transitioning = true;transitionFunction = function;PickNextFunction();}UpdateFunctionOnGPU();}void PickNextFunction(){function = transitionMode == TransitionMode.Cycle ?FunctionLibrary.GetNextFunctionName(function) :FunctionLibrary.GetRandomFunctionNameOtherThan(function);}void UpdateFunctionOnGPU(){//ComputerShader:把需要的数据传进去float step = 2f / resolution;computeShader.SetInt(resolutionId, resolution);computeShader.SetFloat(stepId, step);computeShader.SetFloat(timeId, Time.time);if (transitioning){computeShader.SetFloat(transitionProgressId,Mathf.SmoothStep(0f, 1f, duration / transitionDuration));}//获取核心索引var kernelIndex = (int)function +(int)(transitioning ? transitionFunction : function) * FunctionLibrary.FunctionCount;computeShader.SetBuffer(kernelIndex, positionsId, positionsBuffer);int groups = Mathf.CeilToInt(resolution / 8f);//执行:获取位置computeShader.Dispatch(kernelIndex, groups, groups, 1);//把Shader需要的数据传进去material.SetBuffer(positionsId, positionsBuffer);material.SetVector(scaleId, new Vector4(step, 1f / step));//开始画var bounds = new Bounds(Vector3.zero, Vector3.one * (2f + 2f / resolution));Graphics.DrawMeshInstancedProcedural(mesh, 0, material, bounds, resolution * resolution);}
}

FunctionLibrary.computer:同一行代码后面加注释会报错:\\,需要在新的一行添加。
这里就是原来在C#端写的一些动画函数,这里核心排列使用规律的,方便在C#端计算索引

#pragma kernel WaveKernel
#pragma kernel WaveToMultiWaveKernel
#pragma kernel WaveToRippleKernel
#pragma kernel WaveToSphereKernel
#pragma kernel WaveToTorusKernel#pragma kernel MultiWaveToWaveKernel
#pragma kernel MultiWaveKernel
#pragma kernel MultiWaveToRippleKernel
#pragma kernel MultiWaveToSphereKernel
#pragma kernel MultiWaveToTorusKernel#pragma kernel RippleToWaveKernel
#pragma kernel RippleToMultiWaveKernel
#pragma kernel RippleKernel
#pragma kernel RippleToSphereKernel
#pragma kernel RippleToTorusKernel#pragma kernel SphereToWaveKernel
#pragma kernel SphereToMultiWaveKernel
#pragma kernel SphereToRippleKernel
#pragma kernel SphereKernel
#pragma kernel SphereToTorusKernel#pragma kernel TorusToWaveKernel
#pragma kernel TorusToMultiWaveKernel
#pragma kernel TorusToRippleKernel
#pragma kernel TorusToSphereKernel
#pragma kernel TorusKernelRWStructuredBuffer<float3> _Positions;uint _Resolution;float _Step, _Time, _TransitionProgress;float2 GetUV(uint3 id) {return (id.xy + 0.5) * _Step - 1.0;
}void SetPosition(uint3 id, float3 position) {if (id.x < _Resolution && id.y < _Resolution) {_Positions[id.x + id.y * _Resolution] = position;}
}#define PI 3.14159265358979323846float3 Wave(float u, float v, float t) {float3 p;p.x = u;p.y = sin(PI * (u + v + t));p.z = v;return p;
}float3 MultiWave(float u, float v, float t) {float3 p;p.x = u;p.y = sin(PI * (u + 0.5 * t));p.y += 0.5 * sin(2.0 * PI * (v + t));p.y += sin(PI * (u + v + 0.25 * t));p.y *= 1.0 / 2.5;p.z = v;return p;
}float3 Ripple(float u, float v, float t) {float d = sqrt(u * u + v * v);float3 p;p.x = u;p.y = sin(PI * (4.0 * d - t));p.y /= 1.0 + 10.0 * d;p.z = v;return p;
}float3 Sphere(float u, float v, float t) {float r = 0.9 + 0.1 * sin(PI * (12.0 * u + 8.0 * v + t));float s = r * cos(0.5 * PI * v);float3 p;p.x = s * sin(PI * u);p.y = r * sin(0.5 * PI * v);p.z = s * cos(PI * u);return p;
}float3 Torus(float u, float v, float t) {float r1 = 0.7 + 0.1 * sin(PI * (8.0 * u + 0.5 * t));float r2 = 0.15 + 0.05 * sin(PI * (16.0 * u + 8.0 * v + 3.0 * t));float s = r2 * cos(PI * v) + r1;float3 p;p.x = s * sin(PI * u);p.y = r2 * sin(PI * v);p.z = s * cos(PI * u);return p;
}#define KERNEL_FUNCTION(function) \[numthreads(8, 8, 1)] \void function##Kernel (uint3 id: SV_DispatchThreadID) { \float2 uv = GetUV(id); \SetPosition(id, function(uv.x, uv.y, _Time)); \}#define KERNEL_MOPH_FUNCTION(functionA, functionB) \[numthreads(8, 8, 1)] \void functionA##To##functionB##Kernel (uint3 id: SV_DispatchThreadID) { \float2 uv = GetUV(id); \float3 position = lerp( \functionA(uv.x, uv.y, _Time), functionB(uv.x, uv.y, _Time), \_TransitionProgress \); \SetPosition(id, position); \}KERNEL_FUNCTION(Wave)
KERNEL_FUNCTION(MultiWave)
KERNEL_FUNCTION(Ripple)
KERNEL_FUNCTION(Sphere)
KERNEL_FUNCTION(Torus)KERNEL_MOPH_FUNCTION(Wave, MultiWave);
KERNEL_MOPH_FUNCTION(Wave, Ripple);
KERNEL_MOPH_FUNCTION(Wave, Sphere);
KERNEL_MOPH_FUNCTION(Wave, Torus);KERNEL_MOPH_FUNCTION(MultiWave, Wave);
KERNEL_MOPH_FUNCTION(MultiWave, Ripple);
KERNEL_MOPH_FUNCTION(MultiWave, Sphere);
KERNEL_MOPH_FUNCTION(MultiWave, Torus);KERNEL_MOPH_FUNCTION(Ripple, Wave);
KERNEL_MOPH_FUNCTION(Ripple, MultiWave);
KERNEL_MOPH_FUNCTION(Ripple, Sphere);
KERNEL_MOPH_FUNCTION(Ripple, Torus);KERNEL_MOPH_FUNCTION(Sphere, Wave);
KERNEL_MOPH_FUNCTION(Sphere, MultiWave);
KERNEL_MOPH_FUNCTION(Sphere, Ripple);
KERNEL_MOPH_FUNCTION(Sphere, Torus);KERNEL_MOPH_FUNCTION(Torus, Wave);
KERNEL_MOPH_FUNCTION(Torus, MultiWave);
KERNEL_MOPH_FUNCTION(Torus, Ripple);
KERNEL_MOPH_FUNCTION(Torus, Sphere);

Point GPU.hlsl:这里是把C#端传进来的数据设置好转换矩阵
会把这段代码插入到ShaderGraph里面用

#if defined(UNITY_PROCEDURAL_INSTANCING_ENABLED)
StructuredBuffer<float3> _Positions;
#endiffloat2 _Scale;void ConfigureProcedural() {#if defined(UNITY_PROCEDURAL_INSTANCING_ENABLED)float3 position = _Positions[unity_InstanceID];unity_ObjectToWorld = 0.0;unity_ObjectToWorld._m03_m13_m23_m33 = float4(position, 1.0);unity_ObjectToWorld._m00_m11_m22 = _Scale.x;//逆矩阵:法线要用unity_WorldToObject = 0.0;unity_WorldToObject._m03_m13_m23_m33 = float4(-position, 1.0);unity_WorldToObject._m00_m11_m22 = _Scale.y;
#endif
}//对输入未做修改,直接输出
void ShaderGraphFunction_float(float3 In, out float3 Out) {Out = In;
}//函数重载
void ShaderGraphFunction_half(half3 In, out half3 Out) {Out = In;
}

ShaderGraph图:

作者这里设置的是0

添加CustomFunction节点,设置右边的类型和源文件:就是上面的Point GPU.hlsl

下面这张图:再添加一个CustomFunction节点,编译指令#pragma…这些必须直接写入源文件,不能用上面的方式,从文件读取,所以节点右边的类型设置为string,Body里直接添加如下:

这段主要是添加两个编译指令,对输入未做修改直接输出

//实例化时配置选项:procedural:设置自己的程序片段,会在VS,FS开始时调用
#pragma instancing_options procedural:ConfigureProcedural
//禁用编辑器异步编译着色器:采用同步方式
#pragma editor_sync_compilationOut = In;


CustomFunction用法:查看ShaderGraph文档:链接

总结:
1.C#端设置ComputerShader需要的数据。
2.ComputerShader计算好保存在CommandBuffer里。
3.把CommandBuffer的数据设置到要用的Shader里。
4.最后开始画。

学习笔记:ComputerShader相关推荐

  1. PyTorch 学习笔记(六):PyTorch hook 和关于 PyTorch backward 过程的理解 call

    您的位置 首页 PyTorch 学习笔记系列 PyTorch 学习笔记(六):PyTorch hook 和关于 PyTorch backward 过程的理解 发布: 2017年8月4日 7,195阅读 ...

  2. 容器云原生DevOps学习笔记——第三期:从零搭建CI/CD系统标准化交付流程

    暑期实习期间,所在的技术中台-效能研发团队规划设计并结合公司开源协同实现符合DevOps理念的研发工具平台,实现研发过程自动化.标准化: 实习期间对DevOps的理解一直懵懵懂懂,最近观看了阿里专家带 ...

  3. 容器云原生DevOps学习笔记——第二期:如何快速高质量的应用容器化迁移

    暑期实习期间,所在的技术中台-效能研发团队规划设计并结合公司开源协同实现符合DevOps理念的研发工具平台,实现研发过程自动化.标准化: 实习期间对DevOps的理解一直懵懵懂懂,最近观看了阿里专家带 ...

  4. 2020年Yann Lecun深度学习笔记(下)

    2020年Yann Lecun深度学习笔记(下)

  5. 2020年Yann Lecun深度学习笔记(上)

    2020年Yann Lecun深度学习笔记(上)

  6. 知识图谱学习笔记(1)

    知识图谱学习笔记第一部分,包含RDF介绍,以及Jena RDF API使用 知识图谱的基石:RDF RDF(Resource Description Framework),即资源描述框架,其本质是一个 ...

  7. 计算机基础知识第十讲,计算机文化基础(第十讲)学习笔记

    计算机文化基础(第十讲)学习笔记 采样和量化PictureElement Pixel(像素)(链接: 采样的实质就是要用多少点(这个点我们叫像素)来描述一张图像,比如,一幅420x570的图像,就表示 ...

  8. Go 学习推荐 —(Go by example 中文版、Go 构建 Web 应用、Go 学习笔记、Golang常见错误、Go 语言四十二章经、Go 语言高级编程)

    Go by example 中文版 Go 构建 Web 应用 Go 学习笔记:无痕 Go 标准库中文文档 Golang开发新手常犯的50个错误 50 Shades of Go: Traps, Gotc ...

  9. MongoDB学习笔记(入门)

    MongoDB学习笔记(入门) 一.文档的注意事项: 1.  键值对是有序的,如:{ "name" : "stephen", "genda" ...

  10. NuGet学习笔记(3) 搭建属于自己的NuGet服务器

    文章导读 创建NuGetServer Web站点 发布站点到IIS 添加本地站点到包包数据源 在上一篇NuGet学习笔记(2) 使用图形化界面打包自己的类库 中讲解了如何打包自己的类库,接下来进行最重 ...

最新文章

  1. 美多商城之验证码(图形验证码)
  2. ZIL (ZFS intent log) zil.c
  3. 解析烧录固件失败_化虚为实,示人本相!FLIR热像仪双型号双版本上手解析
  4. 块分割,维特比算法小结
  5. 【LeetCode】3月25日打卡-Day10
  6. 螺旋方阵问题【数组】
  7. Fibonacci思想的灵活应用(洛谷P1011题题解,Java语言描述)
  8. 类似 Observer Pattern 的 NSNotificationCenter (实例)
  9. mysql查询语句块_mysql查询语句
  10. Timus 1531. Zones on a plane
  11. NoSQL、memcached介绍、安装memcached、查看memcached状态
  12. 2019计算机二级vb考试大纲,2019年全国计算机二级VB试题
  13. 局域网中毒2003server、Workstation服务自动停止!
  14. PS2游戏手柄——基于STC15W4K32S4
  15. 福建阳光学院计算机学费,福建省物价局关于调整福州大学阳光学院部分专业学费标准的复函...
  16. 使用BS4爬取智联招聘
  17. 直接在文件夹打开cmd
  18. 【云原生】还不会使用linux?快看这里,在window快速安装centos系统
  19. Photoshop脚本 锁定图层组所有图层
  20. MCNP5 粒子输运 常见问题汇总与踩坑记录(导火索:死循环)

热门文章

  1. 中新金盾信息安全管理系统存在默认密码
  2. 英雄远征Erlang源码分析(1)-源码结构解析
  3. 绩效管理软件哪个好?企业如何建立绩效考核体系?
  4. 使用PlantUml插件画类图
  5. winform开发心得
  6. [转载]普通运动控制卡在LabVIEW平台上的应用
  7. 大学计算机课程报告论坛 贵州,会议首页 - 第十三届大学计算机课程报告论坛” - 搜会网...
  8. 终于,狂神说SSM及SpringBoot系列文章完更!!!
  9. 中国的县级以上行政区划地名中,哪些字是最常见的?
  10. Kafka 批量消费