{"id":1403,"date":"2024-05-27T23:17:52","date_gmt":"2024-05-27T14:17:52","guid":{"rendered":"https:\/\/xn--k10aa.com\/?p=1403"},"modified":"2024-10-20T21:16:27","modified_gmt":"2024-10-20T12:16:27","slug":"cs1","status":"publish","type":"post","link":"https:\/\/remoooo.com\/en\/cs1\/","title":{"rendered":"Compute Shader Learning Notes (I) Getting Started"},"content":{"rendered":"<p>Tags: Getting Started\/Shader\/Compute Shader\/GPU Optimization<\/p>\n\n\n\n<figure class=\"wp-block-image aligncenter\"><img decoding=\"async\" src=\"data:image\/gif;base64,R0lGODlhAQABAIAAAAAAAP\/\/\/yH5BAEAAAAALAAAAAABAAEAAAIBRAA7\" data-src=\"https:\/\/\u80a5\u80a5.com\/wp-content\/uploads\/image-272.png\" alt=\"img\" class=\"wp-image-1409 lazyload\"\/><noscript><img decoding=\"async\" width=\"1384\" height=\"992\" src=\"https:\/\/\u80a5\u80a5.com\/wp-content\/uploads\/image-272.png\" alt=\"img\" class=\"wp-image-1409 lazyload\" srcset=\"https:\/\/remoooo.com\/wp-content\/uploads\/image-272.png 1384w, https:\/\/remoooo.com\/wp-content\/uploads\/image-272-300x215.png 300w, https:\/\/remoooo.com\/wp-content\/uploads\/image-272-1024x734.png 1024w, https:\/\/remoooo.com\/wp-content\/uploads\/image-272-768x550.png 768w\" sizes=\"(max-width: 1384px) 100vw, 1384px\" \/><\/noscript><\/figure>\n\n\n\n<h2 class=\"wp-block-heading\">Preface<\/h2>\n\n\n\n<p>Compute Shader is relatively complex and requires certain programming knowledge, graphics knowledge, and GPU-related hardware knowledge to master it well. The study notes are divided into four parts:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Get to know Compute Shader and implement some simple effects<\/li>\n\n\n\n<li>Draw circles, planet orbits, noise maps, manipulate Meshes, and more<\/li>\n\n\n\n<li>Post-processing, particle system<\/li>\n\n\n\n<li>Physical simulation, drawing grass<\/li>\n\n\n\n<li>Fluid simulation<\/li>\n<\/ul>\n\n\n\n<p>The main references are as follows:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>https:\/\/www.udemy.com\/course\/compute-shaders\/?couponCode=LEADERSALE24A<\/li>\n\n\n\n<li>https:\/\/catlikecoding.com\/unity\/tutorials\/basics\/compute-shaders\/<\/li>\n\n\n\n<li>https:\/\/medium.com\/ericzhan-publication\/shader notes-a preliminary exploration of compute-shader-9efeebd579c1<\/li>\n\n\n\n<li>https:\/\/docs.unity3d.com\/Manual\/class-ComputeShader.html<\/li>\n\n\n\n<li>https:\/\/docs.unity3d.com\/ScriptReference\/ComputeShader.html<\/li>\n\n\n\n<li>https:\/\/learn.microsoft.com\/en-us\/windows\/win32\/api\/D3D11\/nf-d3d11-id3d11devicecontext-dispatch<\/li>\n\n\n\n<li><a href=\"https:\/\/zhuanlan.zhihu.com\/p\/102104374\">lygyue\uff1aCompute Shader<\/a>(Very interesting)<\/li>\n\n\n\n<li>https:\/\/medium.com\/@sengallery\/unity-compute-shader-basic-understanding-5a99df53cea1<\/li>\n\n\n\n<li>https:\/\/kylehalladay.com\/blog\/tutorial\/2014\/06\/27\/Compute-Shaders-Are-Nifty.html (too old and outdated)<\/li>\n\n\n\n<li>http:\/\/www.sunshine2k.de\/coding\/java\/Bresenham\/RasterisingLinesCircles.pdf<\/li>\n\n\n\n<li><a href=\"https:\/\/zhuanlan.zhihu.com\/p\/368307575\">Wang Jiangrong: [Unity] Basic Introduction and Usage of Compute Shader<\/a><\/li>\n\n\n\n<li>\u2026To be continued<\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">L1 Introduction to Compute Shader<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\">1. Introduction to Compute Shader<\/h3>\n\n\n\n<p>Simply put, you can use Compute Shader to calculate a material and then display it through Renderer. It should be noted that Compute Shader can do more than just this.<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"data:image\/gif;base64,R0lGODlhAQABAIAAAAAAAP\/\/\/yH5BAEAAAAALAAAAAABAAEAAAIBRAA7\" data-src=\"https:\/\/\u80a5\u80a5.com\/wp-content\/uploads\/image-267.png\" alt=\"img\" class=\"wp-image-1404 lazyload\"\/><noscript><img decoding=\"async\" width=\"1206\" height=\"574\" src=\"https:\/\/\u80a5\u80a5.com\/wp-content\/uploads\/image-267.png\" alt=\"img\" class=\"wp-image-1404 lazyload\" srcset=\"https:\/\/remoooo.com\/wp-content\/uploads\/image-267.png 1206w, https:\/\/remoooo.com\/wp-content\/uploads\/image-267-300x143.png 300w, https:\/\/remoooo.com\/wp-content\/uploads\/image-267-1024x487.png 1024w, https:\/\/remoooo.com\/wp-content\/uploads\/image-267-768x366.png 768w\" sizes=\"(max-width: 1206px) 100vw, 1206px\" \/><\/noscript><\/figure>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"data:image\/gif;base64,R0lGODlhAQABAIAAAAAAAP\/\/\/yH5BAEAAAAALAAAAAABAAEAAAIBRAA7\" data-src=\"https:\/\/\u80a5\u80a5.com\/wp-content\/uploads\/image-269.png\" alt=\"img\" class=\"wp-image-1406 lazyload\"\/><noscript><img decoding=\"async\" width=\"1046\" height=\"200\" src=\"https:\/\/\u80a5\u80a5.com\/wp-content\/uploads\/image-269.png\" alt=\"img\" class=\"wp-image-1406 lazyload\" srcset=\"https:\/\/remoooo.com\/wp-content\/uploads\/image-269.png 1046w, https:\/\/remoooo.com\/wp-content\/uploads\/image-269-300x57.png 300w, https:\/\/remoooo.com\/wp-content\/uploads\/image-269-1024x196.png 1024w, https:\/\/remoooo.com\/wp-content\/uploads\/image-269-768x147.png 768w\" sizes=\"(max-width: 1046px) 100vw, 1046px\" \/><\/noscript><\/figure>\n\n\n\n<p>You can copy the following two codes and test them.<\/p>\n\n\n\n<div class=\"wp-block-kevinbatdorf-code-block-pro\" data-code-block-pro-font-family=\"Code-Pro-JetBrains-Mono\" style=\"font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)\"><span style=\"display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"54\" height=\"14\" viewbox=\"0 0 54 14\"><g fill=\"none\" fill-rule=\"evenodd\" transform=\"translate(1 1)\"><circle cx=\"6\" cy=\"6\" r=\"6\" fill=\"#FF5F56\" stroke=\"#E0443E\" stroke-width=\".5\"><\/circle><circle cx=\"26\" cy=\"6\" r=\"6\" fill=\"#FFBD2E\" stroke=\"#DEA123\" stroke-width=\".5\"><\/circle><circle cx=\"46\" cy=\"6\" r=\"6\" fill=\"#27C93F\" stroke=\"#1AAB29\" stroke-width=\".5\"><\/circle><\/g><\/svg><\/span><span role=\"button\" tabindex=\"0\" data-code=\"using System.Collections;using System.Collections.Generic;using UnityEngine;public class AssignTexture : MonoBehaviour{    \/\/ ComputeShader \u7528\u4e8e\u5728 GPU \u4e0a\u6267\u884c\u8ba1\u7b97\u4efb\u52a1    public ComputeShader shader;    \/\/ \u7eb9\u7406\u5206\u8fa8\u7387    public int texResolution = 256;    \/\/ \u6e32\u67d3\u5668\u7ec4\u4ef6    private Renderer rend;    \/\/ \u6e32\u67d3\u7eb9\u7406    private RenderTexture outputTexture;    \/\/ \u8ba1\u7b97\u7740\u8272\u5668\u5185\u6838\u53e5\u67c4    private int kernelHandle;    \/\/ Start \u5728\u811a\u672c\u542f\u7528\u65f6\u88ab\u8c03\u7528\u4e00\u6b21    void Start()    {        \/\/ \u521b\u5efa\u4e00\u4e2a\u65b0\u7684\u6e32\u67d3\u7eb9\u7406\uff0c\u6307\u5b9a\u5bbd\u5ea6\u3001\u9ad8\u5ea6\u548c\u4f4d\u6df1\u5ea6\uff08\u6b64\u5904\u4f4d\u6df1\u5ea6\u4e3a0\uff09        outputTexture = new RenderTexture(texResolution, texResolution, 0);        \/\/ \u5141\u8bb8\u968f\u673a\u5199\u5165        outputTexture.enableRandomWrite = true;        \/\/ \u521b\u5efa\u6e32\u67d3\u7eb9\u7406\u5b9e\u4f8b        outputTexture.Create();        \/\/ \u83b7\u53d6\u5f53\u524d\u5bf9\u8c61\u7684\u6e32\u67d3\u5668\u7ec4\u4ef6        rend = GetComponent<Renderer&gt;();        \/\/ \u542f\u7528\u6e32\u67d3\u5668        rend.enabled = true;        InitShader();    }    private void InitShader()    {        \/\/ \u67e5\u627e\u8ba1\u7b97\u7740\u8272\u5668\u5185\u6838 &quot;CSMain&quot; \u7684\u53e5\u67c4        kernelHandle = shader.FindKernel(&quot;CSMain&quot;);        \/\/ \u8bbe\u7f6e\u8ba1\u7b97\u7740\u8272\u5668\u4e2d\u4f7f\u7528\u7684\u7eb9\u7406        shader.SetTexture(kernelHandle, &quot;Result&quot;, outputTexture);        \/\/ \u5c06\u6e32\u67d3\u7eb9\u7406\u8bbe\u7f6e\u4e3a\u6750\u8d28\u7684\u4e3b\u7eb9\u7406        rend.material.SetTexture(&quot;_MainTex&quot;, outputTexture);        \/\/ \u8c03\u5ea6\u8ba1\u7b97\u7740\u8272\u5668\u7684\u6267\u884c\uff0c\u4f20\u5165\u8ba1\u7b97\u7ec4\u7684\u5927\u5c0f        \/\/ \u8fd9\u91cc\u5047\u8bbe\u6bcf\u4e2a\u5de5\u4f5c\u7ec4\u662f 16x16        \/\/ \u7b80\u5355\u7684\u8bf4\u5c31\u662f\uff0c\u8981\u5206\u914d\u591a\u5c11\u4e2a\u7ec4\uff0c\u624d\u80fd\u5b8c\u6210\u8ba1\u7b97\uff0c\u76ee\u524d\u53ea\u5206\u4e86xy\u7684\u5404\u4e00\u534a\uff0c\u56e0\u6b64\u53ea\u6e32\u67d3\u4e861\/4\u7684\u753b\u9762\u3002        DispatchShader(texResolution \/ 16, texResolution \/ 16);    }    private void DispatchShader(int x, int y)    {        \/\/ \u8c03\u5ea6\u8ba1\u7b97\u7740\u8272\u5668\u7684\u6267\u884c        \/\/ x \u548c y \u8868\u793a\u8ba1\u7b97\u7ec4\u7684\u6570\u91cf\uff0c1 \u8868\u793a z \u65b9\u5411\u4e0a\u7684\u8ba1\u7b97\u7ec4\u6570\u91cf\uff08\u8fd9\u91cc\u53ea\u6709\u4e00\u4e2a\uff09        shader.Dispatch(kernelHandle, x, y, 1);    }    void Update()    {        \/\/ \u6bcf\u5e27\u68c0\u67e5\u662f\u5426\u6709\u952e\u76d8\u8f93\u5165\uff08\u6309\u952e U \u88ab\u677e\u5f00\uff09        if (Input.GetKeyUp(KeyCode.U))        {            \/\/ \u5982\u679c\u6309\u952e U \u88ab\u677e\u5f00\uff0c\u5219\u91cd\u65b0\u8c03\u5ea6\u8ba1\u7b97\u7740\u8272\u5668            DispatchShader(texResolution \/ 8, texResolution \/ 8);        }    }}\" style=\"color:#d8dee9ff;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewbox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki nord\" style=\"background-color: #2e3440ff\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color: #81A1C1\">using<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">System<\/span><span style=\"color: #D8DEE9FF\">.Collections<\/span><span style=\"color: #81A1C1\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #81A1C1\">using<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">System<\/span><span style=\"color: #D8DEE9FF\">.Collections.Generic<\/span><span style=\"color: #81A1C1\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #81A1C1\">using<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">UnityEngine<\/span><span style=\"color: #81A1C1\">;<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9\">public<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">class<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #8FBCBB\">AssignTexture<\/span><span style=\"color: #D8DEE9FF\"> : <\/span><span style=\"color: #8FBCBB\">MonoBehaviour<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ECEFF4\">{<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ECEFF4\">    <\/span><span style=\"color: #616E88\">\/\/ ComputeShader is used to perform computing tasks on the GPU<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #81A1C1\">public<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">ComputeShader<\/span><span style=\"color: #D8DEE9FF\"> shader<\/span><span style=\"color: #81A1C1\">;<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #ECEFF4\">    <\/span><span style=\"color: #616E88\">\/\/ Texture resolution<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #81A1C1\">public<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">int<\/span><span style=\"color: #D8DEE9FF\"> texResolution <\/span><span style=\"color: #81A1C1\">=<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #B48EAD\">256<\/span><span style=\"color: #81A1C1\">;<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #ECEFF4\">    <\/span><span style=\"color: #616E88\">\/\/ Renderer component<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #81A1C1\">private<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">Renderer<\/span><span style=\"color: #D8DEE9FF\"> rend<\/span><span style=\"color: #81A1C1\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ECEFF4\">    <\/span><span style=\"color: #616E88\">\/\/ Render texture<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #81A1C1\">private<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">RenderTexture<\/span><span style=\"color: #D8DEE9FF\"> outputTexture<\/span><span style=\"color: #81A1C1\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ECEFF4\">    <\/span><span style=\"color: #616E88\">\/\/ Compute shader kernel handle<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #81A1C1\">private<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">int<\/span><span style=\"color: #D8DEE9FF\"> kernelHandle<\/span><span style=\"color: #81A1C1\">;<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #ECEFF4\">    <\/span><span style=\"color: #616E88\">\/\/ Start is called once when the script is started<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #81A1C1\">void<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #88C0D0\">Start<\/span><span style=\"color: #ECEFF4\">()<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #ECEFF4\">{<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ECEFF4\">        <\/span><span style=\"color: #616E88\">\/\/ Create a new render texture, specifying width, height, and bit depth (here the bit depth is 0)<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">        <\/span><span style=\"color: #D8DEE9\">outputTexture<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">=<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">new<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #88C0D0\">RenderTexture<\/span><span style=\"color: #D8DEE9FF\">(<\/span><span style=\"color: #D8DEE9\">texResolution<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">texResolution<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #B48EAD\">0<\/span><span style=\"color: #D8DEE9FF\">)<\/span><span style=\"color: #81A1C1\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ECEFF4\">        <\/span><span style=\"color: #616E88\">\/\/ Allow random write<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">        <\/span><span style=\"color: #D8DEE9\">outputTexture<\/span><span style=\"color: #ECEFF4\">.<\/span><span style=\"color: #D8DEE9\">enableRandomWrite<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">=<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">true;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ECEFF4\">        <\/span><span style=\"color: #616E88\">\/\/ Create a render texture instance<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">        <\/span><span style=\"color: #D8DEE9\">outputTexture<\/span><span style=\"color: #ECEFF4\">.<\/span><span style=\"color: #88C0D0\">Create<\/span><span style=\"color: #D8DEE9FF\">()<\/span><span style=\"color: #81A1C1\">;<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #ECEFF4\">        <\/span><span style=\"color: #616E88\">\/\/ Get the renderer component of the current object<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">        <\/span><span style=\"color: #D8DEE9\">rend<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">=<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #88C0D0\">GetComponent<\/span><span style=\"color: #ECEFF4\">&lt;<\/span><span style=\"color: #D8DEE9FF\">Renderer<\/span><span style=\"color: #ECEFF4\">&gt;<\/span><span style=\"color: #D8DEE9FF\">()<\/span><span style=\"color: #81A1C1\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ECEFF4\">        <\/span><span style=\"color: #616E88\">\/\/ Enable the renderer<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">        <\/span><span style=\"color: #D8DEE9\">rend<\/span><span style=\"color: #ECEFF4\">.<\/span><span style=\"color: #D8DEE9\">enabled<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">=<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">true;<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">        <\/span><span style=\"color: #88C0D0\">InitShader<\/span><span style=\"color: #D8DEE9FF\">()<\/span><span style=\"color: #81A1C1\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #ECEFF4\">}<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #81A1C1\">private<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">void<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #88C0D0\">InitShader<\/span><span style=\"color: #ECEFF4\">()<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #ECEFF4\">{<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ECEFF4\">        <\/span><span style=\"color: #616E88\">\/\/ Find the handle of the compute shader kernel &quot;CSMain&quot;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">        <\/span><span style=\"color: #D8DEE9\">kernelHandle<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">=<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">shader<\/span><span style=\"color: #ECEFF4\">.<\/span><span style=\"color: #88C0D0\">FindKernel<\/span><span style=\"color: #D8DEE9FF\">(<\/span><span style=\"color: #ECEFF4\">&quot;<\/span><span style=\"color: #A3BE8C\">CSMain<\/span><span style=\"color: #ECEFF4\">&quot;<\/span><span style=\"color: #D8DEE9FF\">)<\/span><span style=\"color: #81A1C1\">;<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #ECEFF4\">        <\/span><span style=\"color: #616E88\">\/\/ Set up the texture used in the compute shader<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">        <\/span><span style=\"color: #D8DEE9\">shader<\/span><span style=\"color: #ECEFF4\">.<\/span><span style=\"color: #88C0D0\">SetTexture<\/span><span style=\"color: #D8DEE9FF\">(<\/span><span style=\"color: #D8DEE9\">kernelHandle<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #ECEFF4\">&quot;<\/span><span style=\"color: #A3BE8C\">Result<\/span><span style=\"color: #ECEFF4\">&quot;<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">outputTexture<\/span><span style=\"color: #D8DEE9FF\">)<\/span><span style=\"color: #81A1C1\">;<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #ECEFF4\">        <\/span><span style=\"color: #616E88\">\/\/ Set the render texture as the material&#039;s main texture<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">        <\/span><span style=\"color: #D8DEE9\">rend<\/span><span style=\"color: #ECEFF4\">.<\/span><span style=\"color: #D8DEE9\">Material<\/span><span style=\"color: #ECEFF4\">.<\/span><span style=\"color: #88C0D0\">SetTexture<\/span><span style=\"color: #D8DEE9FF\">(<\/span><span style=\"color: #ECEFF4\">&quot;<\/span><span style=\"color: #A3BE8C\">_MainTex<\/span><span style=\"color: #ECEFF4\">&quot;<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">outputTexture<\/span><span style=\"color: #D8DEE9FF\">)<\/span><span style=\"color: #81A1C1\">;<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #ECEFF4\">        <\/span><span style=\"color: #616E88\">\/\/ Schedule the execution of the compute shader, passing in the size of the compute group<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ECEFF4\">        <\/span><span style=\"color: #616E88\">\/\/ Here it is assumed that each working group is 16x16<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ECEFF4\">        <\/span><span style=\"color: #616E88\">\/\/ Simply put, how many groups should be allocated to complete the calculation. Currently, only half of x and y are divided, so only 1\/4 of the screen is rendered.<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">        <\/span><span style=\"color: #88C0D0\">DispatchShader<\/span><span style=\"color: #D8DEE9FF\">(<\/span><span style=\"color: #D8DEE9\">texResolution<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">\/<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #B48EAD\">16<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">texResolution<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">\/<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #B48EAD\">16<\/span><span style=\"color: #D8DEE9FF\">)<\/span><span style=\"color: #81A1C1\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #ECEFF4\">}<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #81A1C1\">private<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">void<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #88C0D0\">DispatchShader<\/span><span style=\"color: #ECEFF4\">(<\/span><span style=\"color: #D8DEE9\">int<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">x<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">int<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">y<\/span><span style=\"color: #ECEFF4\">)<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #ECEFF4\">{<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ECEFF4\">        <\/span><span style=\"color: #616E88\">\/\/ Schedule the execution of the compute shader<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ECEFF4\">        <\/span><span style=\"color: #616E88\">\/\/ x and y represent the number of calculation groups, 1 represents the number of calculation groups in the z direction (here there is only one)<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">        <\/span><span style=\"color: #D8DEE9\">shader<\/span><span style=\"color: #ECEFF4\">.<\/span><span style=\"color: #88C0D0\">Dispatch<\/span><span style=\"color: #D8DEE9FF\">(<\/span><span style=\"color: #D8DEE9\">kernelHandle<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">x<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">y<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #B48EAD\">1<\/span><span style=\"color: #D8DEE9FF\">)<\/span><span style=\"color: #81A1C1\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #ECEFF4\">}<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #81A1C1\">void<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #88C0D0\">Update<\/span><span style=\"color: #ECEFF4\">()<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #ECEFF4\">{<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ECEFF4\">        <\/span><span style=\"color: #616E88\">\/\/ Check every frame whether there is keyboard input (button U is released)<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">        <\/span><span style=\"color: #81A1C1\">if<\/span><span style=\"color: #D8DEE9FF\"> (<\/span><span style=\"color: #D8DEE9\">Input<\/span><span style=\"color: #ECEFF4\">.<\/span><span style=\"color: #88C0D0\">GetKeyUp<\/span><span style=\"color: #D8DEE9FF\">(<\/span><span style=\"color: #D8DEE9\">KeyCode<\/span><span style=\"color: #ECEFF4\">.<\/span><span style=\"color: #D8DEE9\">U<\/span><span style=\"color: #D8DEE9FF\">))<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">        <\/span><span style=\"color: #ECEFF4\">{<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ECEFF4\">            <\/span><span style=\"color: #616E88\">\/\/ If the U key is released, reschedule the compute shader<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">            <\/span><span style=\"color: #88C0D0\">DispatchShader<\/span><span style=\"color: #D8DEE9FF\">(<\/span><span style=\"color: #D8DEE9\">texResolution<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">\/<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #B48EAD\">8<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">texResolution<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">\/<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #B48EAD\">8<\/span><span style=\"color: #D8DEE9FF\">)<\/span><span style=\"color: #81A1C1\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">        <\/span><span style=\"color: #ECEFF4\">}<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #ECEFF4\">}<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ECEFF4\">}<\/span><\/span><\/code><\/pre><\/div>\n\n\n\n<p>Unity&#039;s default Compute Shader:<\/p>\n\n\n\n<div class=\"wp-block-kevinbatdorf-code-block-pro\" data-code-block-pro-font-family=\"Code-Pro-JetBrains-Mono\" style=\"font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)\"><span style=\"display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"54\" height=\"14\" viewbox=\"0 0 54 14\"><g fill=\"none\" fill-rule=\"evenodd\" transform=\"translate(1 1)\"><circle cx=\"6\" cy=\"6\" r=\"6\" fill=\"#FF5F56\" stroke=\"#E0443E\" stroke-width=\".5\"><\/circle><circle cx=\"26\" cy=\"6\" r=\"6\" fill=\"#FFBD2E\" stroke=\"#DEA123\" stroke-width=\".5\"><\/circle><circle cx=\"46\" cy=\"6\" r=\"6\" fill=\"#27C93F\" stroke=\"#1AAB29\" stroke-width=\".5\"><\/circle><\/g><\/svg><\/span><span role=\"button\" tabindex=\"0\" data-code=\"\/\/ Each #kernel tells which function to compile; you can have many kernels#pragma kernel CSMain\/\/ Create a RenderTexture with enableRandomWrite flag and set it\/\/ with cs.SetTextureRWTexture2D&lt;float4&gt; Result;[numthreads(8,8,1)]void CSMain (uint3 id : SV_DispatchThreadID) {   \/\/ TODO: insert actual code here! Result[id.xy] = float4(id.x &amp; id.y, (id.x &amp; 15)\/15.0, (id.y &amp; 15)\/15.0, 0.0); }\" style=\"color:#d8dee9ff;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewbox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki nord\" style=\"background-color: #2e3440ff\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color: #616E88\">\/\/ Each #kernel tells which function to compile; you can have many kernels<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">#<\/span><span style=\"color: #D8DEE9\">Pragmas<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">kernel<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">CSMain<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #616E88\">\/\/ Create a RenderTexture with enableRandomWrite flag and set it<\/span><\/span>\n<span class=\"line\"><span style=\"color: #616E88\">\/\/ with cs.SetTexture<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9\">RWTexture2D<\/span><span style=\"color: #81A1C1\">&lt;<\/span><span style=\"color: #D8DEE9\">float4<\/span><span style=\"color: #81A1C1\">&gt;<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">Result<\/span><span style=\"color: #81A1C1\">;<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">[<\/span><span style=\"color: #88C0D0\">numthreads<\/span><span style=\"color: #D8DEE9FF\">(<\/span><span style=\"color: #B48EAD\">8<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #B48EAD\">8<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #B48EAD\">1<\/span><span style=\"color: #D8DEE9FF\">)]<\/span><\/span>\n<span class=\"line\"><span style=\"color: #81A1C1\">void<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #88C0D0\">CSMain<\/span><span style=\"color: #D8DEE9FF\"> (<\/span><span style=\"color: #D8DEE9\">uint3<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">id<\/span><span style=\"color: #D8DEE9FF\"> : <\/span><span style=\"color: #D8DEE9\">SV_DispatchThreadID<\/span><span style=\"color: #D8DEE9FF\">) <\/span><span style=\"color: #ECEFF4\">{<\/span><span style=\"color: #D8DEE9FF\"> <\/span><\/span>\n<span class=\"line\"><span style=\"color: #ECEFF4\">  <\/span><span style=\"color: #616E88\">\/\/ TODO: insert actual code here! Result[id.xy] = float4(id.x &amp; id.y, (id.x &amp; 15)\/15.0, (id.y &amp; 15)\/15.0, 0.0); <\/span><\/span>\n<span class=\"line\"><span style=\"color: #ECEFF4\">}<\/span><\/span><\/code><\/pre><\/div>\n\n\n\n<p><\/p>\n\n\n\n<p>In this example, we can see that a fractal structure called Sierpinski net is drawn in the lower left quarter. This is not important. Unity officials think this graphic is very representative and use it as the default code.<\/p>\n\n\n\n<p>Let&#039;s talk about the Compute Shader code in detail. You can refer to the comments for the C# code.<\/p>\n\n\n\n<p>#pragma kernel CSMain This line of code indicates the entry of Compute Shader. You can change the name of CSMain at will.<\/p>\n\n\n\n<p>RWTexture2D Result This line of code is a readable and writable 2D texture. R stands for Read and W stands for Write.<\/p>\n\n\n\n<p>Focus on this line of code:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>[numthreads(8,8,1)]<\/code><\/pre>\n\n\n\n<p>In the Compute Shader file, this line of code specifies the size of a thread group. For example, in this 8 * 8 * 1 thread group, there are 64 threads in total. Each thread calculates a unit of pixels (RWTexture).<\/p>\n\n\n\n<p>In the C# file above, we use shader.Dispatch to specify the number of thread groups.<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"data:image\/gif;base64,R0lGODlhAQABAIAAAAAAAP\/\/\/yH5BAEAAAAALAAAAAABAAEAAAIBRAA7\" data-src=\"https:\/\/\u80a5\u80a5.com\/wp-content\/uploads\/image-270.png\" alt=\"img\" class=\"wp-image-1407 lazyload\"\/><noscript><img decoding=\"async\" width=\"1440\" height=\"864\" src=\"https:\/\/\u80a5\u80a5.com\/wp-content\/uploads\/image-270.png\" alt=\"img\" class=\"wp-image-1407 lazyload\" srcset=\"https:\/\/remoooo.com\/wp-content\/uploads\/image-270.png 1440w, https:\/\/remoooo.com\/wp-content\/uploads\/image-270-300x180.png 300w, https:\/\/remoooo.com\/wp-content\/uploads\/image-270-1024x614.png 1024w, https:\/\/remoooo.com\/wp-content\/uploads\/image-270-768x461.png 768w\" sizes=\"(max-width: 1440px) 100vw, 1440px\" \/><\/noscript><\/figure>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"data:image\/gif;base64,R0lGODlhAQABAIAAAAAAAP\/\/\/yH5BAEAAAAALAAAAAABAAEAAAIBRAA7\" data-src=\"https:\/\/\u80a5\u80a5.com\/wp-content\/uploads\/image-268.png\" alt=\"img\" class=\"wp-image-1405 lazyload\"\/><noscript><img decoding=\"async\" width=\"1440\" height=\"917\" src=\"https:\/\/\u80a5\u80a5.com\/wp-content\/uploads\/image-268.png\" alt=\"img\" class=\"wp-image-1405 lazyload\" srcset=\"https:\/\/remoooo.com\/wp-content\/uploads\/image-268.png 1440w, https:\/\/remoooo.com\/wp-content\/uploads\/image-268-300x191.png 300w, https:\/\/remoooo.com\/wp-content\/uploads\/image-268-1024x652.png 1024w, https:\/\/remoooo.com\/wp-content\/uploads\/image-268-768x489.png 768w\" sizes=\"(max-width: 1440px) 100vw, 1440px\" \/><\/noscript><\/figure>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"data:image\/gif;base64,R0lGODlhAQABAIAAAAAAAP\/\/\/yH5BAEAAAAALAAAAAABAAEAAAIBRAA7\" data-src=\"https:\/\/\u80a5\u80a5.com\/wp-content\/uploads\/image-271.png\" alt=\"img\" class=\"wp-image-1408 lazyload\"\/><noscript><img decoding=\"async\" width=\"1440\" height=\"835\" src=\"https:\/\/\u80a5\u80a5.com\/wp-content\/uploads\/image-271.png\" alt=\"img\" class=\"wp-image-1408 lazyload\" srcset=\"https:\/\/remoooo.com\/wp-content\/uploads\/image-271.png 1440w, https:\/\/remoooo.com\/wp-content\/uploads\/image-271-300x174.png 300w, https:\/\/remoooo.com\/wp-content\/uploads\/image-271-1024x594.png 1024w, https:\/\/remoooo.com\/wp-content\/uploads\/image-271-768x445.png 768w\" sizes=\"(max-width: 1440px) 100vw, 1440px\" \/><\/noscript><\/figure>\n\n\n\n<p>Next, let&#039;s ask a question. If the current thread group is specified as 8<em>8<\/em>1, so how many thread groups do we need to render a RWTexture of size res*res?<\/p>\n\n\n\n<p>The answer is: res\/8. However, our code currently only calls res\/16, so only the 1\/4 area in the lower left corner is rendered.<\/p>\n\n\n\n<p>In addition, the parameters passed into the entry function are also worth mentioning: uint3 id: SV_DispatchThreadID This id represents the unique identifier of the current thread.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">2. Quarter pattern<\/h3>\n\n\n\n<p>Before you learn to walk, you must first learn to crawl. First, specify the task (Kernel) to be performed in C#.<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"data:image\/gif;base64,R0lGODlhAQABAIAAAAAAAP\/\/\/yH5BAEAAAAALAAAAAABAAEAAAIBRAA7\" data-src=\"https:\/\/\u80a5\u80a5.com\/wp-content\/uploads\/image-273.png\" alt=\"img\" class=\"wp-image-1410 lazyload\"\/><noscript><img decoding=\"async\" width=\"928\" height=\"248\" src=\"https:\/\/\u80a5\u80a5.com\/wp-content\/uploads\/image-273.png\" alt=\"img\" class=\"wp-image-1410 lazyload\" srcset=\"https:\/\/remoooo.com\/wp-content\/uploads\/image-273.png 928w, https:\/\/remoooo.com\/wp-content\/uploads\/image-273-300x80.png 300w, https:\/\/remoooo.com\/wp-content\/uploads\/image-273-768x205.png 768w\" sizes=\"(max-width: 928px) 100vw, 928px\" \/><\/noscript><\/figure>\n\n\n\n<p>Currently we have written it in stone, now we expose a parameter that indicates that different rendering tasks can be performed.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>public string kernelName = &quot;CSMain&quot;; ... kernelHandle = shader.FindKernel(kernelName);<\/code><\/pre>\n\n\n\n<p>In this way, you can modify it at will in the Inspector.<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"data:image\/gif;base64,R0lGODlhAQABAIAAAAAAAP\/\/\/yH5BAEAAAAALAAAAAABAAEAAAIBRAA7\" data-src=\"https:\/\/\u80a5\u80a5.com\/wp-content\/uploads\/image-275.png\" alt=\"img\" class=\"wp-image-1412 lazyload\"\/><noscript><img decoding=\"async\" width=\"1042\" height=\"246\" src=\"https:\/\/\u80a5\u80a5.com\/wp-content\/uploads\/image-275.png\" alt=\"img\" class=\"wp-image-1412 lazyload\" srcset=\"https:\/\/remoooo.com\/wp-content\/uploads\/image-275.png 1042w, https:\/\/remoooo.com\/wp-content\/uploads\/image-275-300x71.png 300w, https:\/\/remoooo.com\/wp-content\/uploads\/image-275-1024x242.png 1024w, https:\/\/remoooo.com\/wp-content\/uploads\/image-275-768x181.png 768w\" sizes=\"(max-width: 1042px) 100vw, 1042px\" \/><\/noscript><\/figure>\n\n\n\n<p>However, it is not enough to just put the plate on the table, we need to serve the dish. We cook the dish in the Compute Shader.<\/p>\n\n\n\n<p>Let&#039;s set up a few menus first.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>#pragma kernel CSMain \/\/ We have just declared #pragma kernel SolidRed \/\/ Define a new dish and write it below... \/\/ You can write a lot [numthreads(8,8,1)] void CSMain (uint3 id : SV_DispatchThreadID){ ... } [numthreads(8,8,1)] void SolidRed (uint3 id : SV_DispatchThreadID){ Result[id.xy] = float4(1,0,0,0); }<\/code><\/pre>\n\n\n\n<p>You can enable different Kernels by modifying the corresponding names in the Inspector.<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"data:image\/gif;base64,R0lGODlhAQABAIAAAAAAAP\/\/\/yH5BAEAAAAALAAAAAABAAEAAAIBRAA7\" data-src=\"https:\/\/\u80a5\u80a5.com\/wp-content\/uploads\/image-274.png\" alt=\"img\" class=\"wp-image-1411 lazyload\"\/><noscript><img decoding=\"async\" width=\"1440\" height=\"858\" src=\"https:\/\/\u80a5\u80a5.com\/wp-content\/uploads\/image-274.png\" alt=\"img\" class=\"wp-image-1411 lazyload\" srcset=\"https:\/\/remoooo.com\/wp-content\/uploads\/image-274.png 1440w, https:\/\/remoooo.com\/wp-content\/uploads\/image-274-300x179.png 300w, https:\/\/remoooo.com\/wp-content\/uploads\/image-274-1024x610.png 1024w, https:\/\/remoooo.com\/wp-content\/uploads\/image-274-768x458.png 768w\" sizes=\"(max-width: 1440px) 100vw, 1440px\" \/><\/noscript><\/figure>\n\n\n\n<p>What if I want to pass data to the Compute Shader? For example, pass the resolution of a material to the Compute Shader.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>shader.SetInt(&quot;texResolution&quot;, texResolution);<\/code><\/pre>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"data:image\/gif;base64,R0lGODlhAQABAIAAAAAAAP\/\/\/yH5BAEAAAAALAAAAAABAAEAAAIBRAA7\" data-src=\"https:\/\/\u80a5\u80a5.com\/wp-content\/uploads\/image-276.png\" alt=\"img\" class=\"wp-image-1413 lazyload\"\/><noscript><img decoding=\"async\" width=\"1208\" height=\"434\" src=\"https:\/\/\u80a5\u80a5.com\/wp-content\/uploads\/image-276.png\" alt=\"img\" class=\"wp-image-1413 lazyload\" srcset=\"https:\/\/remoooo.com\/wp-content\/uploads\/image-276.png 1208w, https:\/\/remoooo.com\/wp-content\/uploads\/image-276-300x108.png 300w, https:\/\/remoooo.com\/wp-content\/uploads\/image-276-1024x368.png 1024w, https:\/\/remoooo.com\/wp-content\/uploads\/image-276-768x276.png 768w\" sizes=\"(max-width: 1208px) 100vw, 1208px\" \/><\/noscript><\/figure>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"data:image\/gif;base64,R0lGODlhAQABAIAAAAAAAP\/\/\/yH5BAEAAAAALAAAAAABAAEAAAIBRAA7\" data-src=\"https:\/\/\u80a5\u80a5.com\/wp-content\/uploads\/image-278.png\" alt=\"img\" class=\"wp-image-1415 lazyload\"\/><noscript><img decoding=\"async\" width=\"1326\" height=\"594\" src=\"https:\/\/\u80a5\u80a5.com\/wp-content\/uploads\/image-278.png\" alt=\"img\" class=\"wp-image-1415 lazyload\" srcset=\"https:\/\/remoooo.com\/wp-content\/uploads\/image-278.png 1326w, https:\/\/remoooo.com\/wp-content\/uploads\/image-278-300x134.png 300w, https:\/\/remoooo.com\/wp-content\/uploads\/image-278-1024x459.png 1024w, https:\/\/remoooo.com\/wp-content\/uploads\/image-278-768x344.png 768w\" sizes=\"(max-width: 1326px) 100vw, 1326px\" \/><\/noscript><\/figure>\n\n\n\n<p>And in the Compute Shader, it must also be declared.<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"data:image\/gif;base64,R0lGODlhAQABAIAAAAAAAP\/\/\/yH5BAEAAAAALAAAAAABAAEAAAIBRAA7\" data-src=\"https:\/\/\u80a5\u80a5.com\/wp-content\/uploads\/image-277.png\" alt=\"img\" class=\"wp-image-1414 lazyload\"\/><noscript><img decoding=\"async\" width=\"614\" height=\"168\" src=\"https:\/\/\u80a5\u80a5.com\/wp-content\/uploads\/image-277.png\" alt=\"img\" class=\"wp-image-1414 lazyload\" srcset=\"https:\/\/remoooo.com\/wp-content\/uploads\/image-277.png 614w, https:\/\/remoooo.com\/wp-content\/uploads\/image-277-300x82.png 300w\" sizes=\"(max-width: 614px) 100vw, 614px\" \/><\/noscript><\/figure>\n\n\n\n<p>Think about a question, how to achieve the following effect?<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"data:image\/gif;base64,R0lGODlhAQABAIAAAAAAAP\/\/\/yH5BAEAAAAALAAAAAABAAEAAAIBRAA7\" data-src=\"https:\/\/\u80a5\u80a5.com\/wp-content\/uploads\/image-280.png\" alt=\"img\" class=\"wp-image-1417 lazyload\"\/><noscript><img decoding=\"async\" width=\"914\" height=\"604\" src=\"https:\/\/\u80a5\u80a5.com\/wp-content\/uploads\/image-280.png\" alt=\"img\" class=\"wp-image-1417 lazyload\" srcset=\"https:\/\/remoooo.com\/wp-content\/uploads\/image-280.png 914w, https:\/\/remoooo.com\/wp-content\/uploads\/image-280-300x198.png 300w, https:\/\/remoooo.com\/wp-content\/uploads\/image-280-768x508.png 768w\" sizes=\"(max-width: 914px) 100vw, 914px\" \/><\/noscript><\/figure>\n\n\n\n<div class=\"wp-block-kevinbatdorf-code-block-pro\" data-code-block-pro-font-family=\"Code-Pro-JetBrains-Mono\" style=\"font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)\"><span style=\"display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"54\" height=\"14\" viewbox=\"0 0 54 14\"><g fill=\"none\" fill-rule=\"evenodd\" transform=\"translate(1 1)\"><circle cx=\"6\" cy=\"6\" r=\"6\" fill=\"#FF5F56\" stroke=\"#E0443E\" stroke-width=\".5\"><\/circle><circle cx=\"26\" cy=\"6\" r=\"6\" fill=\"#FFBD2E\" stroke=\"#DEA123\" stroke-width=\".5\"><\/circle><circle cx=\"46\" cy=\"6\" r=\"6\" fill=\"#27C93F\" stroke=\"#1AAB29\" stroke-width=\".5\"><\/circle><\/g><\/svg><\/span><span role=\"button\" tabindex=\"0\" data-code=\"[numthreads(8,8,1)]void SplitScreen (uint3 id : SV_DispatchThreadID){    int halfRes = texResolution &gt;&gt; 1;    Result[id.xy] = float4(step(halfRes, id.x),step(halfRes, id.y),0,1);}\" style=\"color:#d8dee9ff;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewbox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki nord\" style=\"background-color: #2e3440ff\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color: #D8DEE9FF\">[<\/span><span style=\"color: #88C0D0\">numthreads<\/span><span style=\"color: #D8DEE9FF\">(<\/span><span style=\"color: #B48EAD\">8<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #B48EAD\">8<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #B48EAD\">1<\/span><span style=\"color: #D8DEE9FF\">)]<\/span><\/span>\n<span class=\"line\"><span style=\"color: #81A1C1\">void<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #88C0D0\">SplitScreen<\/span><span style=\"color: #D8DEE9FF\"> (<\/span><span style=\"color: #D8DEE9\">uint3<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">id<\/span><span style=\"color: #D8DEE9FF\"> : <\/span><span style=\"color: #D8DEE9\">SV_DispatchThreadID<\/span><span style=\"color: #D8DEE9FF\">)<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ECEFF4\">{<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #D8DEE9\">int<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">halfRes<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">=<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">texResolution<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">&gt;&gt;<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #B48EAD\">1<\/span><span style=\"color: #81A1C1\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #D8DEE9\">Result<\/span><span style=\"color: #D8DEE9FF\">[<\/span><span style=\"color: #D8DEE9\">id<\/span><span style=\"color: #ECEFF4\">.<\/span><span style=\"color: #D8DEE9\">xy<\/span><span style=\"color: #D8DEE9FF\">] <\/span><span style=\"color: #81A1C1\">=<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #88C0D0\">float4<\/span><span style=\"color: #D8DEE9FF\">(<\/span><span style=\"color: #88C0D0\">step<\/span><span style=\"color: #D8DEE9FF\">(<\/span><span style=\"color: #D8DEE9\">halfRes<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">id<\/span><span style=\"color: #ECEFF4\">.<\/span><span style=\"color: #D8DEE9\">x<\/span><span style=\"color: #D8DEE9FF\">)<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #88C0D0\">step<\/span><span style=\"color: #D8DEE9FF\">(<\/span><span style=\"color: #D8DEE9\">halfRes<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">id<\/span><span style=\"color: #ECEFF4\">.<\/span><span style=\"color: #D8DEE9\">y<\/span><span style=\"color: #D8DEE9FF\">)<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #B48EAD\">0<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #B48EAD\">1<\/span><span style=\"color: #D8DEE9FF\">)<\/span><span style=\"color: #81A1C1\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ECEFF4\">}<\/span><\/span><\/code><\/pre><\/div>\n\n\n\n<p>To explain, the step function is actually:<\/p>\n\n\n\n<div class=\"wp-block-kevinbatdorf-code-block-pro\" data-code-block-pro-font-family=\"Code-Pro-JetBrains-Mono\" style=\"font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)\"><span style=\"display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"54\" height=\"14\" viewbox=\"0 0 54 14\"><g fill=\"none\" fill-rule=\"evenodd\" transform=\"translate(1 1)\"><circle cx=\"6\" cy=\"6\" r=\"6\" fill=\"#FF5F56\" stroke=\"#E0443E\" stroke-width=\".5\"><\/circle><circle cx=\"26\" cy=\"6\" r=\"6\" fill=\"#FFBD2E\" stroke=\"#DEA123\" stroke-width=\".5\"><\/circle><circle cx=\"46\" cy=\"6\" r=\"6\" fill=\"#27C93F\" stroke=\"#1AAB29\" stroke-width=\".5\"><\/circle><\/g><\/svg><\/span><span role=\"button\" tabindex=\"0\" data-code=\"step(edge, x){    return x&gt;=edge ? 1 : 0;}\" style=\"color:#d8dee9ff;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewbox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki nord\" style=\"background-color: #2e3440ff\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color: #88C0D0\">step<\/span><span style=\"color: #D8DEE9FF\">(<\/span><span style=\"color: #D8DEE9\">edge<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">x<\/span><span style=\"color: #D8DEE9FF\">)<\/span><span style=\"color: #ECEFF4\">{<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #81A1C1\">return<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">x<\/span><span style=\"color: #81A1C1\">&gt;=<\/span><span style=\"color: #D8DEE9\">edge<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">?<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #B48EAD\">1<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">:<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #B48EAD\">0<\/span><span style=\"color: #81A1C1\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ECEFF4\">}<\/span><\/span><\/code><\/pre><\/div>\n\n\n\n<p>(uint)res &gt;&gt; 1 means that the bits of res are shifted one position to the right. This is equivalent to dividing by 2 (binary content).<\/p>\n\n\n\n<p>This calculation method simply depends on the current thread id.<\/p>\n\n\n\n<p>The thread at the bottom left corner always outputs black because the step return is always 0.<\/p>\n\n\n\n<p>For the lower left thread, id.x &gt; halfRes , so 1 is returned in the red channel.<\/p>\n\n\n\n<p>If you are not convinced, you can do some calculations to help you understand the relationship between thread ID, thread group and thread group group.<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"data:image\/gif;base64,R0lGODlhAQABAIAAAAAAAP\/\/\/yH5BAEAAAAALAAAAAABAAEAAAIBRAA7\" data-src=\"https:\/\/\u80a5\u80a5.com\/wp-content\/uploads\/image-282.png\" alt=\"img\" class=\"wp-image-1419 lazyload\"\/><noscript><img decoding=\"async\" width=\"1176\" height=\"360\" src=\"https:\/\/\u80a5\u80a5.com\/wp-content\/uploads\/image-282.png\" alt=\"img\" class=\"wp-image-1419 lazyload\" srcset=\"https:\/\/remoooo.com\/wp-content\/uploads\/image-282.png 1176w, https:\/\/remoooo.com\/wp-content\/uploads\/image-282-300x92.png 300w, https:\/\/remoooo.com\/wp-content\/uploads\/image-282-1024x313.png 1024w, https:\/\/remoooo.com\/wp-content\/uploads\/image-282-768x235.png 768w\" sizes=\"(max-width: 1176px) 100vw, 1176px\" \/><\/noscript><\/figure>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"data:image\/gif;base64,R0lGODlhAQABAIAAAAAAAP\/\/\/yH5BAEAAAAALAAAAAABAAEAAAIBRAA7\" data-src=\"https:\/\/\u80a5\u80a5.com\/wp-content\/uploads\/image-279.png\" alt=\"img\" class=\"wp-image-1416 lazyload\"\/><noscript><img decoding=\"async\" width=\"1440\" height=\"1066\" src=\"https:\/\/\u80a5\u80a5.com\/wp-content\/uploads\/image-279.png\" alt=\"img\" class=\"wp-image-1416 lazyload\" srcset=\"https:\/\/remoooo.com\/wp-content\/uploads\/image-279.png 1440w, https:\/\/remoooo.com\/wp-content\/uploads\/image-279-300x222.png 300w, https:\/\/remoooo.com\/wp-content\/uploads\/image-279-1024x758.png 1024w, https:\/\/remoooo.com\/wp-content\/uploads\/image-279-768x569.png 768w\" sizes=\"(max-width: 1440px) 100vw, 1440px\" \/><\/noscript><\/figure>\n\n\n\n<h3 class=\"wp-block-heading\">3. Draw a circle<\/h3>\n\n\n\n<p>The principle sounds simple. It checks whether (id.x, id.y) is inside the circle. If yes, it outputs 1. Otherwise, it outputs 0. Let&#039;s try it.<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"data:image\/gif;base64,R0lGODlhAQABAIAAAAAAAP\/\/\/yH5BAEAAAAALAAAAAABAAEAAAIBRAA7\" data-src=\"https:\/\/\u80a5\u80a5.com\/wp-content\/uploads\/image-281.png\" alt=\"img\" class=\"wp-image-1418 lazyload\"\/><noscript><img decoding=\"async\" width=\"1318\" height=\"730\" src=\"https:\/\/\u80a5\u80a5.com\/wp-content\/uploads\/image-281.png\" alt=\"img\" class=\"wp-image-1418 lazyload\" srcset=\"https:\/\/remoooo.com\/wp-content\/uploads\/image-281.png 1318w, https:\/\/remoooo.com\/wp-content\/uploads\/image-281-300x166.png 300w, https:\/\/remoooo.com\/wp-content\/uploads\/image-281-1024x567.png 1024w, https:\/\/remoooo.com\/wp-content\/uploads\/image-281-768x425.png 768w\" sizes=\"(max-width: 1318px) 100vw, 1318px\" \/><\/noscript><\/figure>\n\n\n\n<div class=\"wp-block-kevinbatdorf-code-block-pro\" data-code-block-pro-font-family=\"Code-Pro-JetBrains-Mono\" style=\"font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)\"><span style=\"display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"54\" height=\"14\" viewbox=\"0 0 54 14\"><g fill=\"none\" fill-rule=\"evenodd\" transform=\"translate(1 1)\"><circle cx=\"6\" cy=\"6\" r=\"6\" fill=\"#FF5F56\" stroke=\"#E0443E\" stroke-width=\".5\"><\/circle><circle cx=\"26\" cy=\"6\" r=\"6\" fill=\"#FFBD2E\" stroke=\"#DEA123\" stroke-width=\".5\"><\/circle><circle cx=\"46\" cy=\"6\" r=\"6\" fill=\"#27C93F\" stroke=\"#1AAB29\" stroke-width=\".5\"><\/circle><\/g><\/svg><\/span><span role=\"button\" tabindex=\"0\" data-code=\"float inCircle( float2 pt, float radius ){    return ( length(pt)&lt;radius ) ? 1.0 : 0.0;}[numthreads(8,8,1)]void Circle (uint3 id : SV_DispatchThreadID){    int halfRes = texResolution &gt;&gt; 1;    int isInside = inCircle((float2)((int2)id.xy-halfRes), (float)(halfRes&gt;&gt;1));    Result[id.xy] = float4(0.0,isInside ,0,1);}\" style=\"color:#d8dee9ff;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewbox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki nord\" style=\"background-color: #2e3440ff\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color: #D8DEE9\">float<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #88C0D0\">inCircle<\/span><span style=\"color: #D8DEE9FF\">( <\/span><span style=\"color: #D8DEE9\">float2<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">pt<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">float<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">radius<\/span><span style=\"color: #D8DEE9FF\"> )<\/span><span style=\"color: #ECEFF4\">{<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #81A1C1\">return<\/span><span style=\"color: #D8DEE9FF\"> ( <\/span><span style=\"color: #88C0D0\">length<\/span><span style=\"color: #D8DEE9FF\">(<\/span><span style=\"color: #D8DEE9\">pt<\/span><span style=\"color: #D8DEE9FF\">)<\/span><span style=\"color: #81A1C1\">&lt;<\/span><span style=\"color: #D8DEE9\">radius<\/span><span style=\"color: #D8DEE9FF\"> ) <\/span><span style=\"color: #81A1C1\">?<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #B48EAD\">1.0<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">:<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #B48EAD\">0.0<\/span><span style=\"color: #81A1C1\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ECEFF4\">}<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">[<\/span><span style=\"color: #88C0D0\">numthreads<\/span><span style=\"color: #D8DEE9FF\">(<\/span><span style=\"color: #B48EAD\">8<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #B48EAD\">8<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #B48EAD\">1<\/span><span style=\"color: #D8DEE9FF\">)]<\/span><\/span>\n<span class=\"line\"><span style=\"color: #81A1C1\">void<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #88C0D0\">Circle<\/span><span style=\"color: #D8DEE9FF\"> (<\/span><span style=\"color: #D8DEE9\">uint3<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">id<\/span><span style=\"color: #D8DEE9FF\"> : <\/span><span style=\"color: #D8DEE9\">SV_DispatchThreadID<\/span><span style=\"color: #D8DEE9FF\">)<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ECEFF4\">{<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #D8DEE9\">int<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">halfRes<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">=<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">texResolution<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">&gt;&gt;<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #B48EAD\">1<\/span><span style=\"color: #81A1C1\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #D8DEE9\">int<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">isInside<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">=<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #88C0D0\">inCircle<\/span><span style=\"color: #D8DEE9FF\">((<\/span><span style=\"color: #D8DEE9\">float2<\/span><span style=\"color: #D8DEE9FF\">)((<\/span><span style=\"color: #D8DEE9\">int2<\/span><span style=\"color: #D8DEE9FF\">)<\/span><span style=\"color: #D8DEE9\">id<\/span><span style=\"color: #ECEFF4\">.<\/span><span style=\"color: #D8DEE9\">xy<\/span><span style=\"color: #81A1C1\">-<\/span><span style=\"color: #D8DEE9\">halfRes<\/span><span style=\"color: #D8DEE9FF\">)<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> (<\/span><span style=\"color: #D8DEE9\">float<\/span><span style=\"color: #D8DEE9FF\">)(<\/span><span style=\"color: #D8DEE9\">halfRes<\/span><span style=\"color: #81A1C1\">&gt;&gt;<\/span><span style=\"color: #B48EAD\">1<\/span><span style=\"color: #D8DEE9FF\">))<\/span><span style=\"color: #81A1C1\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #D8DEE9\">Result<\/span><span style=\"color: #D8DEE9FF\">[<\/span><span style=\"color: #D8DEE9\">id<\/span><span style=\"color: #ECEFF4\">.<\/span><span style=\"color: #D8DEE9\">xy<\/span><span style=\"color: #D8DEE9FF\">] <\/span><span style=\"color: #81A1C1\">=<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #88C0D0\">float4<\/span><span style=\"color: #D8DEE9FF\">(<\/span><span style=\"color: #B48EAD\">0.0<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9\">isInside<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #B48EAD\">0<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #B48EAD\">1<\/span><span style=\"color: #D8DEE9FF\">)<\/span><span style=\"color: #81A1C1\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ECEFF4\">}<\/span><\/span><\/code><\/pre><\/div>\n\n\n\n<p><\/p>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"data:image\/gif;base64,R0lGODlhAQABAIAAAAAAAP\/\/\/yH5BAEAAAAALAAAAAABAAEAAAIBRAA7\" data-src=\"https:\/\/\u80a5\u80a5.com\/wp-content\/uploads\/image-283.png\" alt=\"img\" class=\"wp-image-1420 lazyload\"\/><noscript><img decoding=\"async\" width=\"1390\" height=\"1078\" src=\"https:\/\/\u80a5\u80a5.com\/wp-content\/uploads\/image-283.png\" alt=\"img\" class=\"wp-image-1420 lazyload\" srcset=\"https:\/\/remoooo.com\/wp-content\/uploads\/image-283.png 1390w, https:\/\/remoooo.com\/wp-content\/uploads\/image-283-300x233.png 300w, https:\/\/remoooo.com\/wp-content\/uploads\/image-283-1024x794.png 1024w, https:\/\/remoooo.com\/wp-content\/uploads\/image-283-768x596.png 768w\" sizes=\"(max-width: 1390px) 100vw, 1390px\" \/><\/noscript><\/figure>\n\n\n\n<h3 class=\"wp-block-heading\">4. Summary\/Quiz<\/h3>\n\n\n\n<p>If the output is a RWTexture with a side length of 256, which answer will produce a completely red texture?<\/p>\n\n\n\n<div class=\"wp-block-kevinbatdorf-code-block-pro\" data-code-block-pro-font-family=\"Code-Pro-JetBrains-Mono\" style=\"font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)\"><span style=\"display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"54\" height=\"14\" viewbox=\"0 0 54 14\"><g fill=\"none\" fill-rule=\"evenodd\" transform=\"translate(1 1)\"><circle cx=\"6\" cy=\"6\" r=\"6\" fill=\"#FF5F56\" stroke=\"#E0443E\" stroke-width=\".5\"><\/circle><circle cx=\"26\" cy=\"6\" r=\"6\" fill=\"#FFBD2E\" stroke=\"#DEA123\" stroke-width=\".5\"><\/circle><circle cx=\"46\" cy=\"6\" r=\"6\" fill=\"#27C93F\" stroke=\"#1AAB29\" stroke-width=\".5\"><\/circle><\/g><\/svg><\/span><span role=\"button\" tabindex=\"0\" data-code=\"RWTexture2D&lt;float4&gt; output;[numthreads(16,16,1)]void CSMain (uint3 id : SV_DispatchThreadID){     output[id.xy] = float4(1.0, 0.0, 0.0, 1.0);}\" style=\"color:#d8dee9ff;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewbox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki nord\" style=\"background-color: #2e3440ff\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color: #D8DEE9\">RWTexture2D<\/span><span style=\"color: #81A1C1\">&lt;<\/span><span style=\"color: #D8DEE9\">float4<\/span><span style=\"color: #81A1C1\">&gt;<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">output<\/span><span style=\"color: #81A1C1\">;<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">[<\/span><span style=\"color: #88C0D0\">numthreads<\/span><span style=\"color: #D8DEE9FF\">(<\/span><span style=\"color: #B48EAD\">16<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #B48EAD\">16<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #B48EAD\">1<\/span><span style=\"color: #D8DEE9FF\">)]<\/span><\/span>\n<span class=\"line\"><span style=\"color: #81A1C1\">void<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #88C0D0\">CSMain<\/span><span style=\"color: #D8DEE9FF\"> (<\/span><span style=\"color: #D8DEE9\">uint3<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">id<\/span><span style=\"color: #D8DEE9FF\"> : <\/span><span style=\"color: #D8DEE9\">SV_DispatchThreadID<\/span><span style=\"color: #D8DEE9FF\">)<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ECEFF4\">{<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">     <\/span><span style=\"color: #D8DEE9\">output<\/span><span style=\"color: #D8DEE9FF\">[<\/span><span style=\"color: #D8DEE9\">id<\/span><span style=\"color: #ECEFF4\">.<\/span><span style=\"color: #D8DEE9\">xy<\/span><span style=\"color: #D8DEE9FF\">] <\/span><span style=\"color: #81A1C1\">=<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #88C0D0\">float4<\/span><span style=\"color: #D8DEE9FF\">(<\/span><span style=\"color: #B48EAD\">1.0<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #B48EAD\">0.0<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #B48EAD\">0.0<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #B48EAD\">1.0<\/span><span style=\"color: #D8DEE9FF\">)<\/span><span style=\"color: #81A1C1\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ECEFF4\">}<\/span><\/span><\/code><\/pre><\/div>\n\n\n\n<p><\/p>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"data:image\/gif;base64,R0lGODlhAQABAIAAAAAAAP\/\/\/yH5BAEAAAAALAAAAAABAAEAAAIBRAA7\" data-src=\"https:\/\/\u80a5\u80a5.com\/wp-content\/uploads\/image-284.png\" alt=\"img\" class=\"wp-image-1421 lazyload\"\/><noscript><img decoding=\"async\" width=\"1440\" height=\"376\" src=\"https:\/\/\u80a5\u80a5.com\/wp-content\/uploads\/image-284.png\" alt=\"img\" class=\"wp-image-1421 lazyload\" srcset=\"https:\/\/remoooo.com\/wp-content\/uploads\/image-284.png 1440w, https:\/\/remoooo.com\/wp-content\/uploads\/image-284-300x78.png 300w, https:\/\/remoooo.com\/wp-content\/uploads\/image-284-1024x267.png 1024w, https:\/\/remoooo.com\/wp-content\/uploads\/image-284-768x201.png 768w\" sizes=\"(max-width: 1440px) 100vw, 1440px\" \/><\/noscript><\/figure>\n\n\n\n<p>Which answer will give red on the left side of the texture output and yellow on the right side?<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"data:image\/gif;base64,R0lGODlhAQABAIAAAAAAAP\/\/\/yH5BAEAAAAALAAAAAABAAEAAAIBRAA7\" data-src=\"https:\/\/\u80a5\u80a5.com\/wp-content\/uploads\/image-285.png\" alt=\"img\" class=\"wp-image-1422 lazyload\"\/><noscript><img decoding=\"async\" width=\"1440\" height=\"601\" src=\"https:\/\/\u80a5\u80a5.com\/wp-content\/uploads\/image-285.png\" alt=\"img\" class=\"wp-image-1422 lazyload\" srcset=\"https:\/\/remoooo.com\/wp-content\/uploads\/image-285.png 1440w, https:\/\/remoooo.com\/wp-content\/uploads\/image-285-300x125.png 300w, https:\/\/remoooo.com\/wp-content\/uploads\/image-285-1024x427.png 1024w, https:\/\/remoooo.com\/wp-content\/uploads\/image-285-768x321.png 768w\" sizes=\"(max-width: 1440px) 100vw, 1440px\" \/><\/noscript><\/figure>\n\n\n\n<h2 class=\"wp-block-heading\">L2 has begun<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\">1. Passing values to the GPU<\/h3>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"data:image\/gif;base64,R0lGODlhAQABAIAAAAAAAP\/\/\/yH5BAEAAAAALAAAAAABAAEAAAIBRAA7\" data-src=\"https:\/\/\u80a5\u80a5.com\/wp-content\/uploads\/image-287.png\" alt=\"img\" class=\"wp-image-1424 lazyload\"\/><noscript><img decoding=\"async\" width=\"1220\" height=\"544\" src=\"https:\/\/\u80a5\u80a5.com\/wp-content\/uploads\/image-287.png\" alt=\"img\" class=\"wp-image-1424 lazyload\" srcset=\"https:\/\/remoooo.com\/wp-content\/uploads\/image-287.png 1220w, https:\/\/remoooo.com\/wp-content\/uploads\/image-287-300x134.png 300w, https:\/\/remoooo.com\/wp-content\/uploads\/image-287-1024x457.png 1024w, https:\/\/remoooo.com\/wp-content\/uploads\/image-287-768x342.png 768w\" sizes=\"(max-width: 1220px) 100vw, 1220px\" \/><\/noscript><\/figure>\n\n\n\n<p>Without further ado, let&#039;s draw a circle. Here are two initial codes.<\/p>\n\n\n\n<p>PassData.cs: https:\/\/pastebin.com\/PMf4SicK<\/p>\n\n\n\n<p>PassData.compute: https:\/\/pastebin.com\/WtfUmhk2<\/p>\n\n\n\n<p>The general structure is the same as above. You can see that a drawCircle function is called to draw a circle.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>[numthreads(1,1,1)] void Circles (uint3 id : SV_DispatchThreadID) { int2 center = (texResolution &gt;&gt; 1); int radius = 80; drawCircle( centre, radius ); }<\/code><\/pre>\n\n\n\n<p>The circle drawing method used here is a very classic rasterization drawing method. If you are interested in the mathematical principles, you can read http:\/\/www.sunshine2k.de\/coding\/java\/Bresenham\/RasterisingLinesCircles.pdf. The general idea is to use a symmetric idea to generate.<\/p>\n\n\n\n<p>The difference is that here we use (1,1,1) as the size of a thread group. Call CS on the CPU side:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>private void DispatchKernel(int count) { shader.Dispatch(circlesHandle, count, 1, 1); } void Update() { DispatchKernel(1); }<\/code><\/pre>\n\n\n\n<p>The question is, how many times does a thread execute?<\/p>\n\n\n\n<p>Answer: It is executed only once. Because a thread group has only 1<em>1<\/em>1 = 1 thread, and only 1 is called on the CPU side<em>1<\/em>1 = 1 thread group is used for calculation. Therefore, only one thread is used to draw a circle. In other words, one thread can draw an entire RWTexture at a time, instead of one thread drawing one pixel as before.<\/p>\n\n\n\n<p>This also shows that there is an essential difference between Compute Shader and Fragment Shader. Fragment Shader only calculates the color of a single pixel, while Compute Shader can perform more or less arbitrary operations!<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"data:image\/gif;base64,R0lGODlhAQABAIAAAAAAAP\/\/\/yH5BAEAAAAALAAAAAABAAEAAAIBRAA7\" data-src=\"https:\/\/\u80a5\u80a5.com\/wp-content\/uploads\/image-286.png\" alt=\"img\" class=\"wp-image-1423 lazyload\"\/><noscript><img decoding=\"async\" width=\"1238\" height=\"650\" src=\"https:\/\/\u80a5\u80a5.com\/wp-content\/uploads\/image-286.png\" alt=\"img\" class=\"wp-image-1423 lazyload\" srcset=\"https:\/\/remoooo.com\/wp-content\/uploads\/image-286.png 1238w, https:\/\/remoooo.com\/wp-content\/uploads\/image-286-300x158.png 300w, https:\/\/remoooo.com\/wp-content\/uploads\/image-286-1024x538.png 1024w, https:\/\/remoooo.com\/wp-content\/uploads\/image-286-768x403.png 768w\" sizes=\"(max-width: 1238px) 100vw, 1238px\" \/><\/noscript><\/figure>\n\n\n\n<p>Back to Unity, if you want to draw a good-looking circle, you need an outline color and a fill color. Pass these two parameters to CS.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>float4 clearColor; float4 circleColor;<\/code><\/pre>\n\n\n\n<p>And add color filling kernel, and modify the Circles kernel. If multiple kernels access a RWTexture at the same time, you can add the shared keyword.<\/p>\n\n\n\n<div class=\"wp-block-kevinbatdorf-code-block-pro\" data-code-block-pro-font-family=\"Code-Pro-JetBrains-Mono\" style=\"font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)\"><span style=\"display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"54\" height=\"14\" viewbox=\"0 0 54 14\"><g fill=\"none\" fill-rule=\"evenodd\" transform=\"translate(1 1)\"><circle cx=\"6\" cy=\"6\" r=\"6\" fill=\"#FF5F56\" stroke=\"#E0443E\" stroke-width=\".5\"><\/circle><circle cx=\"26\" cy=\"6\" r=\"6\" fill=\"#FFBD2E\" stroke=\"#DEA123\" stroke-width=\".5\"><\/circle><circle cx=\"46\" cy=\"6\" r=\"6\" fill=\"#27C93F\" stroke=\"#1AAB29\" stroke-width=\".5\"><\/circle><\/g><\/svg><\/span><span role=\"button\" tabindex=\"0\" data-code=\"#pragma kernel Circles#pragma kernel Clear    ...shared RWTexture2D&lt;float4&gt; Result;    ...[numthreads(32,1,1)]void Circles (uint3 id : SV_DispatchThreadID){    \/\/ int2 centre = (texResolution &gt;&gt; 1);    int2 centre = (int2)(random2((float)id.x) * (float)texResolution);    int radius = (int)(random((float)id.x) * 30);    drawCircle( centre, radius );}[numthreads(8,8,1)]void Clear (uint3 id : SV_DispatchThreadID){    Result[id.xy] = clearColor;}\" style=\"color:#d8dee9ff;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewbox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki nord\" style=\"background-color: #2e3440ff\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color: #D8DEE9FF\">#<\/span><span style=\"color: #D8DEE9\">Pragmas<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">kernel<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">Circles<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">#<\/span><span style=\"color: #D8DEE9\">Pragmas<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">kernel<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">Clear<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #81A1C1\">...<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9\">shared<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">RWTexture2D<\/span><span style=\"color: #81A1C1\">&lt;<\/span><span style=\"color: #D8DEE9\">float4<\/span><span style=\"color: #81A1C1\">&gt;<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">Result<\/span><span style=\"color: #81A1C1\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #81A1C1\">...<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">[<\/span><span style=\"color: #88C0D0\">numthreads<\/span><span style=\"color: #D8DEE9FF\">(<\/span><span style=\"color: #B48EAD\">32<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #B48EAD\">1<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #B48EAD\">1<\/span><span style=\"color: #D8DEE9FF\">)]<\/span><\/span>\n<span class=\"line\"><span style=\"color: #81A1C1\">void<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #88C0D0\">Circles<\/span><span style=\"color: #D8DEE9FF\"> (<\/span><span style=\"color: #D8DEE9\">uint3<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">id<\/span><span style=\"color: #D8DEE9FF\"> : <\/span><span style=\"color: #D8DEE9\">SV_DispatchThreadID<\/span><span style=\"color: #D8DEE9FF\">)<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ECEFF4\">{<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ECEFF4\">    <\/span><span style=\"color: #616E88\">\/\/ int2 center = (texResolution &gt;&gt; 1);<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #D8DEE9\">int2<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">centre<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">=<\/span><span style=\"color: #D8DEE9FF\"> (<\/span><span style=\"color: #D8DEE9\">int2<\/span><span style=\"color: #D8DEE9FF\">)(<\/span><span style=\"color: #88C0D0\">random2<\/span><span style=\"color: #D8DEE9FF\">((<\/span><span style=\"color: #D8DEE9\">float<\/span><span style=\"color: #D8DEE9FF\">)<\/span><span style=\"color: #D8DEE9\">id<\/span><span style=\"color: #ECEFF4\">.<\/span><span style=\"color: #D8DEE9\">x<\/span><span style=\"color: #D8DEE9FF\">) <\/span><span style=\"color: #81A1C1\">*<\/span><span style=\"color: #D8DEE9FF\"> (<\/span><span style=\"color: #D8DEE9\">float<\/span><span style=\"color: #D8DEE9FF\">)<\/span><span style=\"color: #D8DEE9\">texResolution<\/span><span style=\"color: #D8DEE9FF\">)<\/span><span style=\"color: #81A1C1\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #D8DEE9\">int<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">radius<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">=<\/span><span style=\"color: #D8DEE9FF\"> (<\/span><span style=\"color: #D8DEE9\">int<\/span><span style=\"color: #D8DEE9FF\">)(<\/span><span style=\"color: #88C0D0\">random<\/span><span style=\"color: #D8DEE9FF\">((<\/span><span style=\"color: #D8DEE9\">float<\/span><span style=\"color: #D8DEE9FF\">)<\/span><span style=\"color: #D8DEE9\">id<\/span><span style=\"color: #ECEFF4\">.<\/span><span style=\"color: #D8DEE9\">x<\/span><span style=\"color: #D8DEE9FF\">) <\/span><span style=\"color: #81A1C1\">*<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #B48EAD\">30<\/span><span style=\"color: #D8DEE9FF\">)<\/span><span style=\"color: #81A1C1\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #88C0D0\">drawCircle<\/span><span style=\"color: #D8DEE9FF\">( <\/span><span style=\"color: #D8DEE9\">centre<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">radius<\/span><span style=\"color: #D8DEE9FF\"> )<\/span><span style=\"color: #81A1C1\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ECEFF4\">}<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">[<\/span><span style=\"color: #88C0D0\">numthreads<\/span><span style=\"color: #D8DEE9FF\">(<\/span><span style=\"color: #B48EAD\">8<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #B48EAD\">8<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #B48EAD\">1<\/span><span style=\"color: #D8DEE9FF\">)]<\/span><\/span>\n<span class=\"line\"><span style=\"color: #81A1C1\">void<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #88C0D0\">Clear<\/span><span style=\"color: #D8DEE9FF\"> (<\/span><span style=\"color: #D8DEE9\">uint3<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">id<\/span><span style=\"color: #D8DEE9FF\"> : <\/span><span style=\"color: #D8DEE9\">SV_DispatchThreadID<\/span><span style=\"color: #D8DEE9FF\">)<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ECEFF4\">{<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #D8DEE9\">Result<\/span><span style=\"color: #D8DEE9FF\">[<\/span><span style=\"color: #D8DEE9\">id<\/span><span style=\"color: #ECEFF4\">.<\/span><span style=\"color: #D8DEE9\">xy<\/span><span style=\"color: #D8DEE9FF\">] <\/span><span style=\"color: #81A1C1\">=<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">clearColor<\/span><span style=\"color: #81A1C1\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ECEFF4\">}<\/span><\/span><\/code><\/pre><\/div>\n\n\n\n<p><\/p>\n\n\n\n<p>Get the Clear kernel on the CPU side and pass in the data.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>private int circlesHandle; private int clearHandle; ... shader.SetVector( &quot;clearColor&quot;, clearColor); shader.SetVector( &quot;circleColor&quot;, circleColor); ... private void DispatchKernels(int count) { shader.Dispatch(clearHandle, texResolution\/8, texResolution\/8, 1); shader.Dispatch(circlesHandle, count, 1, 1); } void Update() { DispatchKernels(1); \/\/ There are now 32 circles on the screen }<\/code><\/pre>\n\n\n\n<p>A question, if the code is changed to: DispatchKernels(10), how many circles will there be on the screen?<\/p>\n\n\n\n<p>Answer: 320. Initially, Dispatch is 1<em>1<\/em>1=1, a thread group has 32<em>1<\/em>1=32 threads, each thread draws a circle. Elementary school mathematics.<\/p>\n\n\n\n<p>Next, add the _Time variable to make the circle change with time. Since there seems to be no such variable as _time in the Compute Shader, it can only be passed in by the CPU.<\/p>\n\n\n\n<p>On the CPU side, note that variables updated in real time need to be updated before each Dispatch (outputTexture does not need to be updated because this outputTexture actually points to a reference to the GPU texture!):<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>private void DispatchKernels(int count) { shader.Dispatch(clearHandle, texResolution\/8, texResolution\/8, 1); shader.SetFloat( &quot;time&quot;, Time.time); shader.Dispatch(circlesHandle, count, 1, 1) ; }<\/code><\/pre>\n\n\n\n<p>Compute Shader:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>float time; ... void Circles (uint3 id : SV_DispatchThreadID){ ... int2 center = (int2)(random2((float)id.x + time) * (float)texResolution); ... }<\/code><\/pre>\n\n\n\n<p>Current version code:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Compute Shader: https:\/\/github.com\/Remyuu\/Unity-Compute-Shader-Learn\/blob\/L2_Circle_Time\/Assets\/Shaders\/PassData.compute<\/li>\n\n\n\n<li>CPU: https:\/\/github.com\/Remyuu\/Unity-Compute-Shader-Learn\/blob\/L2_Circle_Time\/Assets\/Scripts\/PassData.cs<\/li>\n<\/ul>\n\n\n\n<p>But now the circles are very messy. The next step is to use Buffer to make the circles look more regular.<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"data:image\/gif;base64,R0lGODlhAQABAIAAAAAAAP\/\/\/yH5BAEAAAAALAAAAAABAAEAAAIBRAA7\" data-src=\"https:\/\/\u80a5\u80a5.com\/wp-content\/uploads\/image-288.png\" alt=\"img\" class=\"wp-image-1425 lazyload\"\/><noscript><img decoding=\"async\" width=\"1224\" height=\"654\" src=\"https:\/\/\u80a5\u80a5.com\/wp-content\/uploads\/image-288.png\" alt=\"img\" class=\"wp-image-1425 lazyload\" srcset=\"https:\/\/remoooo.com\/wp-content\/uploads\/image-288.png 1224w, https:\/\/remoooo.com\/wp-content\/uploads\/image-288-300x160.png 300w, https:\/\/remoooo.com\/wp-content\/uploads\/image-288-1024x547.png 1024w, https:\/\/remoooo.com\/wp-content\/uploads\/image-288-768x410.png 768w\" sizes=\"(max-width: 1224px) 100vw, 1224px\" \/><\/noscript><\/figure>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p>At the same time, you don&#039;t need to worry about multiple threads trying to write to the same memory location (such as RWTexture) at the same time, which may cause race conditions. The current API will handle this problem well.<\/p>\n<\/blockquote>\n\n\n\n<h3 class=\"wp-block-heading\">2. Use Buffer to pass data to GPU<\/h3>\n\n\n\n<p>So far, we have learned how to transfer some simple data from the CPU to the GPU. How do we pass a custom structure?<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"data:image\/gif;base64,R0lGODlhAQABAIAAAAAAAP\/\/\/yH5BAEAAAAALAAAAAABAAEAAAIBRAA7\" data-src=\"https:\/\/\u80a5\u80a5.com\/wp-content\/uploads\/image-292.png\" alt=\"img\" class=\"wp-image-1429 lazyload\"\/><noscript><img decoding=\"async\" width=\"1324\" height=\"606\" src=\"https:\/\/\u80a5\u80a5.com\/wp-content\/uploads\/image-292.png\" alt=\"img\" class=\"wp-image-1429 lazyload\" srcset=\"https:\/\/remoooo.com\/wp-content\/uploads\/image-292.png 1324w, https:\/\/remoooo.com\/wp-content\/uploads\/image-292-300x137.png 300w, https:\/\/remoooo.com\/wp-content\/uploads\/image-292-1024x469.png 1024w, https:\/\/remoooo.com\/wp-content\/uploads\/image-292-768x352.png 768w\" sizes=\"(max-width: 1324px) 100vw, 1324px\" \/><\/noscript><\/figure>\n\n\n\n<p>We can use Buffer as a medium, where Buffer is of course stored in the GPU, and the CPU side (C#) only stores its reference. First, declare a structure on the CPU, and then declare the CPU-side reference and the GPU-side<strong>References<\/strong>.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>struct Circle { public Vector2 origin; public Vector2 velocity; public float radius; } Circle[] circleData; \/\/ on CPU ComputeBuffer buffer; \/\/ on GPU<\/code><\/pre>\n\n\n\n<p>To get the size information of a thread group, you can do this. The following code only gets the number of threads in the x direction of the circlesHandles thread group, ignoring y and z (because it is assumed that the y and z of the thread group are both 1). And multiply it by the number of allocated thread groups to get the total number of threads.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>uint threadGroupSizeX; shader.GetKernelThreadGroupSizes(circlesHandle, out threadGroupSizeX, out _, out _); int total = (int)threadGroupSizeX * count;<\/code><\/pre>\n\n\n\n<p>Now prepare the data to be passed to the GPU. Here we create circles with the number of threads, circleData[threadNums].<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>circleData = new Circle[total]; float speed = 100; float halfSpeed = speed * 0.5f; float minRadius = 10.0f; float maxRadius = 30.0f; float radiusRange = maxRadius - minRadius; for(int i=0; i<\/code><\/pre>\n\n\n\n<p>Then accept this Buffer in the Compute Shader. Declare an identical structure (Vector2 and Float2 are the same), and then create a reference to the Buffer.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>\/\/ Compute Shader struct circle { float2 origin; float2 velocity; float radius; }; StructuredBuffer circlesBuffer;<\/code><\/pre>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p>Note that the StructureBuffer used here is read-only, which is different from the RWStructureBuffer mentioned in the next section.<\/p>\n<\/blockquote>\n\n\n\n<p>Back to the CPU side, send the CPU data just prepared to the GPU through the Buffer. First, we need to make clear the size of the Buffer we applied for, that is, how big we want to pass to the GPU. Here, a circle data has two float2 variables and one float variable, a float is 4 bytes (may be different on different platforms, you can use sizeof(float) to determine), and there are circleData.Length pieces of circle data to be passed. circleData.Length indicates how many circle objects the buffer needs to store, and stride defines how many bytes each object&#039;s data occupies. After opening up such a large space, use SetData() to fill the data into the buffer, that is, in this step, pass the data to the GPU. Finally, bind the GPU reference where the data is located to the Kernel specified by the Compute Shader.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>int stride = (2 + 2 + 1) * 4; \/\/2 floats origin, 2 floats velocity, 1 float radius - 4 bytes per float buffer = new ComputeBuffer(circleData.Length, stride); buffer.SetData(circleData); shader.SetBuffer(circlesHandle, &quot;circlesBuffer&quot;, buffer);<\/code><\/pre>\n\n\n\n<p>So far, we have passed some data prepared by the CPU to the GPU through Buffer.<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"data:image\/gif;base64,R0lGODlhAQABAIAAAAAAAP\/\/\/yH5BAEAAAAALAAAAAABAAEAAAIBRAA7\" data-src=\"https:\/\/\u80a5\u80a5.com\/wp-content\/uploads\/image-290.png\" alt=\"img\" class=\"wp-image-1427 lazyload\"\/><noscript><img decoding=\"async\" width=\"1440\" height=\"753\" src=\"https:\/\/\u80a5\u80a5.com\/wp-content\/uploads\/image-290.png\" alt=\"img\" class=\"wp-image-1427 lazyload\" srcset=\"https:\/\/remoooo.com\/wp-content\/uploads\/image-290.png 1440w, https:\/\/remoooo.com\/wp-content\/uploads\/image-290-300x157.png 300w, https:\/\/remoooo.com\/wp-content\/uploads\/image-290-1024x535.png 1024w, https:\/\/remoooo.com\/wp-content\/uploads\/image-290-768x402.png 768w\" sizes=\"(max-width: 1440px) 100vw, 1440px\" \/><\/noscript><\/figure>\n\n\n\n<p>OK, now let\u2019s make use of the data that was transferred to the GPU with great difficulty.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>[numthreads(32,1,1)] void Circles (uint3 id : SV_DispatchThreadID) { int2 center = (int2)(circlesBuffer[id.x].origin + circlesBuffer[id.x].velocity * time); while (centre.x&gt;texResolution) centre.x -= texResolution; while (centre.x&lt;0) centre.x += texResolution; while (centre.y&gt;texResolution) centre.y -= texResolution; while (centre.y&lt;0) centre.y += texResolution; uint radius = (int)circlesBuffer[id.x].radius; drawCircle( centre, radius ); }<\/code><\/pre>\n\n\n\n<p>You can see that the circle is now moving continuously because our Buffer stores the position of the circle indexed by id.x in the previous frame and the movement status of the circle.<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"data:image\/gif;base64,R0lGODlhAQABAIAAAAAAAP\/\/\/yH5BAEAAAAALAAAAAABAAEAAAIBRAA7\" data-src=\"https:\/\/\u80a5\u80a5.com\/wp-content\/uploads\/image-289.png\" alt=\"img\" class=\"wp-image-1426 lazyload\"\/><noscript><img decoding=\"async\" width=\"1084\" height=\"848\" src=\"https:\/\/\u80a5\u80a5.com\/wp-content\/uploads\/image-289.png\" alt=\"img\" class=\"wp-image-1426 lazyload\" srcset=\"https:\/\/remoooo.com\/wp-content\/uploads\/image-289.png 1084w, https:\/\/remoooo.com\/wp-content\/uploads\/image-289-300x235.png 300w, https:\/\/remoooo.com\/wp-content\/uploads\/image-289-1024x801.png 1024w, https:\/\/remoooo.com\/wp-content\/uploads\/image-289-768x601.png 768w\" sizes=\"(max-width: 1084px) 100vw, 1084px\" \/><\/noscript><\/figure>\n\n\n\n<p>To sum up, in this section we learned how to customize a structure (data structure) on the CPU side, pass it to the GPU through a Buffer, and process the data on the GPU.<\/p>\n\n\n\n<p>In the next section, we will learn how to get data from the GPU back to the CPU.<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Current version code:<\/li>\n\n\n\n<li>Compute Shader: https:\/\/github.com\/Remyuu\/Unity-Compute-Shader-Learn\/blob\/L2_Using_Buffer\/Assets\/Shaders\/BufferJoy.compute<\/li>\n\n\n\n<li>CPU: https:\/\/github.com\/Remyuu\/Unity-Compute-Shader-Learn\/blob\/L2_Using_Buffer\/Assets\/Scripts\/BufferJoy.cs<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">3. Get data from GPU<\/h3>\n\n\n\n<p>As usual, create a Buffer to transfer data from the GPU to the CPU. Define an array on the CPU side to receive the data. Then create the buffer, bind it to the shader, and finally create variables on the CPU ready to receive GPU data.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>ComputeBuffer resultBuffer; \/\/ Buffer Vector3[] output; \/\/ CPU accepts... \/\/buffer on the gpu in the ram resultBuffer = new ComputeBuffer(starCount, sizeof(float) * 3); shader.SetBuffer(kernelHandle, &quot;Result &quot;, resultBuffer); output = new Vector3[starCount];<\/code><\/pre>\n\n\n\n<p>Compute Shader also accepts such a Buffer. The Buffer here is readable and writable, which means that the Buffer can be modified by Compute Shader. In the previous section, Compute Shader only needs to read the Buffer, so StructuredBuffer is enough. Here we need to use RW.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>RWStructuredBuffer Result;<\/code><\/pre>\n\n\n\n<p>Next, use GetData after Dispatch to receive the data.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>shader.Dispatch(kernelHandle, groupSizeX, 1, 1); resultBuffer.GetData(output);<\/code><\/pre>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"data:image\/gif;base64,R0lGODlhAQABAIAAAAAAAP\/\/\/yH5BAEAAAAALAAAAAABAAEAAAIBRAA7\" data-src=\"https:\/\/\u80a5\u80a5.com\/wp-content\/uploads\/image-291.png\" alt=\"img\" class=\"wp-image-1428 lazyload\"\/><noscript><img decoding=\"async\" width=\"1392\" height=\"572\" src=\"https:\/\/\u80a5\u80a5.com\/wp-content\/uploads\/image-291.png\" alt=\"img\" class=\"wp-image-1428 lazyload\" srcset=\"https:\/\/remoooo.com\/wp-content\/uploads\/image-291.png 1392w, https:\/\/remoooo.com\/wp-content\/uploads\/image-291-300x123.png 300w, https:\/\/remoooo.com\/wp-content\/uploads\/image-291-1024x421.png 1024w, https:\/\/remoooo.com\/wp-content\/uploads\/image-291-768x316.png 768w\" sizes=\"(max-width: 1392px) 100vw, 1392px\" \/><\/noscript><\/figure>\n\n\n\n<p>The idea is so simple. Now let&#039;s try to make a scene where a lot of stars move around the center of the sphere.<\/p>\n\n\n\n<p>The task of calculating the star coordinates is put on the GPU to complete, and finally the calculated position data of each star is obtained, and the object is instantiated in C#.<\/p>\n\n\n\n<p>In Compute Shader, each thread calculates the position of a star and outputs it to the Buffer.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>[numthreads(64,1,1)] void OrbitingStars (uint3 id : SV_DispatchThreadID) { float3 sinDir = normalize(random3(id.x) - 0.5); float3 vec = normalize(random3(id.x + 7.1393) - 0.5); float3 cosDir = normalize(cross(sinDir, vec)); float scaledTime = time * 0.5 + random(id.x) * 712.131234; float3 pos = sinDir * sin(scaledTime) + cosDir * cos(scaledTime); Result[id.x] = pos * 2; }<\/code><\/pre>\n\n\n\n<p>Get the calculation result through GetData on the CPU side, and modify the Pos of the corresponding previously instantiated GameObject at any time.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>void Update() { shader.SetFloat(&quot;time&quot;, Time.time); shader.Dispatch(kernelHandle, groupSizeX, 1, 1); resultBuffer.GetData(output); for (int i = 0; i &lt; stars.Length; i++) stars[i].localPosition = output[i]; }<\/code><\/pre>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"data:image\/gif;base64,R0lGODlhAQABAIAAAAAAAP\/\/\/yH5BAEAAAAALAAAAAABAAEAAAIBRAA7\" data-src=\"https:\/\/\u80a5\u80a5.com\/wp-content\/uploads\/image-296.png\" alt=\"img\" class=\"wp-image-1433 lazyload\"\/><noscript><img decoding=\"async\" width=\"1240\" height=\"664\" src=\"https:\/\/\u80a5\u80a5.com\/wp-content\/uploads\/image-296.png\" alt=\"img\" class=\"wp-image-1433 lazyload\" srcset=\"https:\/\/remoooo.com\/wp-content\/uploads\/image-296.png 1240w, https:\/\/remoooo.com\/wp-content\/uploads\/image-296-300x161.png 300w, https:\/\/remoooo.com\/wp-content\/uploads\/image-296-1024x548.png 1024w, https:\/\/remoooo.com\/wp-content\/uploads\/image-296-768x411.png 768w\" sizes=\"(max-width: 1240px) 100vw, 1240px\" \/><\/noscript><\/figure>\n\n\n\n<p>Current version code:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Compute Shader: https:\/\/github.com\/Remyuu\/Unity-Compute-Shader-Learn\/blob\/L2_GetData_From_Buffer\/Assets\/Shaders\/OrbitingStars.compute<\/li>\n\n\n\n<li>CPU: https:\/\/github.com\/Remyuu\/Unity-Compute-Shader-Learn\/blob\/L2_GetData_From_Buffer\/Assets\/Scripts\/OrbitingStars.cs<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">4. Use noise<\/h3>\n\n\n\n<p>Generating a noise map using Compute Shader is very simple and very efficient.<\/p>\n\n\n\n<div class=\"wp-block-kevinbatdorf-code-block-pro\" data-code-block-pro-font-family=\"Code-Pro-JetBrains-Mono\" style=\"font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)\"><span style=\"display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"54\" height=\"14\" viewbox=\"0 0 54 14\"><g fill=\"none\" fill-rule=\"evenodd\" transform=\"translate(1 1)\"><circle cx=\"6\" cy=\"6\" r=\"6\" fill=\"#FF5F56\" stroke=\"#E0443E\" stroke-width=\".5\"><\/circle><circle cx=\"26\" cy=\"6\" r=\"6\" fill=\"#FFBD2E\" stroke=\"#DEA123\" stroke-width=\".5\"><\/circle><circle cx=\"46\" cy=\"6\" r=\"6\" fill=\"#27C93F\" stroke=\"#1AAB29\" stroke-width=\".5\"><\/circle><\/g><\/svg><\/span><span role=\"button\" tabindex=\"0\" data-code=\"float random (float2 pt, float seed) {    const float a = 12.9898;    const float b = 78.233;    const float c = 43758.543123;    return frac(sin(seed + dot(pt, float2(a, b))) * c );}[numthreads(8,8,1)]void CSMain (uint3 id : SV_DispatchThreadID){    float4 white = 1;    Result[id.xy] = random(((float2)id.xy)\/(float)texResolution, time) * white;}\" style=\"color:#d8dee9ff;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewbox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki nord\" style=\"background-color: #2e3440ff\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color: #D8DEE9\">float<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #88C0D0\">random<\/span><span style=\"color: #D8DEE9FF\"> (<\/span><span style=\"color: #D8DEE9\">float2<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">pt<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">float<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">seed<\/span><span style=\"color: #D8DEE9FF\">) <\/span><span style=\"color: #ECEFF4\">{<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #81A1C1\">const<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">float<\/span><span style=\"color: #D8DEE9FF\"> a <\/span><span style=\"color: #81A1C1\">=<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #B48EAD\">12.9898<\/span><span style=\"color: #81A1C1\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #81A1C1\">const<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">float<\/span><span style=\"color: #D8DEE9FF\"> b <\/span><span style=\"color: #81A1C1\">=<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #B48EAD\">78.233<\/span><span style=\"color: #81A1C1\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #81A1C1\">const<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">float<\/span><span style=\"color: #D8DEE9FF\"> c <\/span><span style=\"color: #81A1C1\">=<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #B48EAD\">43758.543123<\/span><span style=\"color: #81A1C1\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #81A1C1\">return<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #88C0D0\">frac<\/span><span style=\"color: #D8DEE9FF\">(<\/span><span style=\"color: #88C0D0\">sin<\/span><span style=\"color: #D8DEE9FF\">(<\/span><span style=\"color: #D8DEE9\">seed<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">+<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #88C0D0\">dot<\/span><span style=\"color: #D8DEE9FF\">(<\/span><span style=\"color: #D8DEE9\">pt<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #88C0D0\">float2<\/span><span style=\"color: #D8DEE9FF\">(<\/span><span style=\"color: #D8DEE9\">a<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">b<\/span><span style=\"color: #D8DEE9FF\">))) <\/span><span style=\"color: #81A1C1\">*<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">c<\/span><span style=\"color: #D8DEE9FF\"> )<\/span><span style=\"color: #81A1C1\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ECEFF4\">}<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">[<\/span><span style=\"color: #88C0D0\">numthreads<\/span><span style=\"color: #D8DEE9FF\">(<\/span><span style=\"color: #B48EAD\">8<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #B48EAD\">8<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #B48EAD\">1<\/span><span style=\"color: #D8DEE9FF\">)]<\/span><\/span>\n<span class=\"line\"><span style=\"color: #81A1C1\">void<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #88C0D0\">CSMain<\/span><span style=\"color: #D8DEE9FF\"> (<\/span><span style=\"color: #D8DEE9\">uint3<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">id<\/span><span style=\"color: #D8DEE9FF\"> : <\/span><span style=\"color: #D8DEE9\">SV_DispatchThreadID<\/span><span style=\"color: #D8DEE9FF\">)<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ECEFF4\">{<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #D8DEE9\">float4<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">white<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">=<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #B48EAD\">1<\/span><span style=\"color: #81A1C1\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #D8DEE9\">Result<\/span><span style=\"color: #D8DEE9FF\">[<\/span><span style=\"color: #D8DEE9\">id<\/span><span style=\"color: #ECEFF4\">.<\/span><span style=\"color: #D8DEE9\">xy<\/span><span style=\"color: #D8DEE9FF\">] <\/span><span style=\"color: #81A1C1\">=<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #88C0D0\">random<\/span><span style=\"color: #D8DEE9FF\">(((<\/span><span style=\"color: #D8DEE9\">float2<\/span><span style=\"color: #D8DEE9FF\">)<\/span><span style=\"color: #D8DEE9\">id<\/span><span style=\"color: #ECEFF4\">.<\/span><span style=\"color: #D8DEE9\">xy<\/span><span style=\"color: #D8DEE9FF\">)<\/span><span style=\"color: #81A1C1\">\/<\/span><span style=\"color: #D8DEE9FF\">(<\/span><span style=\"color: #D8DEE9\">float<\/span><span style=\"color: #D8DEE9FF\">)<\/span><span style=\"color: #D8DEE9\">texResolution<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">time<\/span><span style=\"color: #D8DEE9FF\">) <\/span><span style=\"color: #81A1C1\">*<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">white<\/span><span style=\"color: #81A1C1\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ECEFF4\">}<\/span><\/span><\/code><\/pre><\/div>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"data:image\/gif;base64,R0lGODlhAQABAIAAAAAAAP\/\/\/yH5BAEAAAAALAAAAAABAAEAAAIBRAA7\" data-src=\"https:\/\/\u80a5\u80a5.com\/wp-content\/uploads\/image-302.png\" alt=\"img\" class=\"wp-image-1439 lazyload\"\/><noscript><img decoding=\"async\" width=\"1440\" height=\"607\" src=\"https:\/\/\u80a5\u80a5.com\/wp-content\/uploads\/image-302.png\" alt=\"img\" class=\"wp-image-1439 lazyload\" srcset=\"https:\/\/remoooo.com\/wp-content\/uploads\/image-302.png 1440w, https:\/\/remoooo.com\/wp-content\/uploads\/image-302-300x126.png 300w, https:\/\/remoooo.com\/wp-content\/uploads\/image-302-1024x432.png 1024w, https:\/\/remoooo.com\/wp-content\/uploads\/image-302-768x324.png 768w\" sizes=\"(max-width: 1440px) 100vw, 1440px\" \/><\/noscript><\/figure>\n\n\n\n<p>There is a library to get more various noises. https:\/\/pastebin.com\/uGhMLKeM<\/p>\n\n\n\n<div class=\"wp-block-kevinbatdorf-code-block-pro\" data-code-block-pro-font-family=\"Code-Pro-JetBrains-Mono\" style=\"font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)\"><span style=\"display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"54\" height=\"14\" viewbox=\"0 0 54 14\"><g fill=\"none\" fill-rule=\"evenodd\" transform=\"translate(1 1)\"><circle cx=\"6\" cy=\"6\" r=\"6\" fill=\"#FF5F56\" stroke=\"#E0443E\" stroke-width=\".5\"><\/circle><circle cx=\"26\" cy=\"6\" r=\"6\" fill=\"#FFBD2E\" stroke=\"#DEA123\" stroke-width=\".5\"><\/circle><circle cx=\"46\" cy=\"6\" r=\"6\" fill=\"#27C93F\" stroke=\"#1AAB29\" stroke-width=\".5\"><\/circle><\/g><\/svg><\/span><span role=\"button\" tabindex=\"0\" data-code=\"#include &quot;noiseSimplex.cginc&quot; \/\/ Paste the code above and named &quot;noiseSimplex.cginc&quot;...[numthreads(8,8,1)]void CSMain (uint3 id : SV_DispatchThreadID){    float3 pos = (((float3)id)\/(float)texResolution) * 2.0;    float n = snoise(pos);    float ring = frac(noiseScale * n);    float delta = pow(ring, ringScale) + n;    Result[id.xy] = lerp(darkColor, paleColor, delta);}\" style=\"color:#d8dee9ff;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewbox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki nord\" style=\"background-color: #2e3440ff\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color: #D8DEE9FF\">#<\/span><span style=\"color: #D8DEE9\">include<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #ECEFF4\">&quot;<\/span><span style=\"color: #A3BE8C\">noiseSimplex.cginc<\/span><span style=\"color: #ECEFF4\">&quot;<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #616E88\">\/\/ Paste the code above and named &quot;noiseSimplex.cginc&quot;<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #81A1C1\">...<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">[<\/span><span style=\"color: #88C0D0\">numthreads<\/span><span style=\"color: #D8DEE9FF\">(<\/span><span style=\"color: #B48EAD\">8<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #B48EAD\">8<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #B48EAD\">1<\/span><span style=\"color: #D8DEE9FF\">)]<\/span><\/span>\n<span class=\"line\"><span style=\"color: #81A1C1\">void<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #88C0D0\">CSMain<\/span><span style=\"color: #D8DEE9FF\"> (<\/span><span style=\"color: #D8DEE9\">uint3<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">id<\/span><span style=\"color: #D8DEE9FF\"> : <\/span><span style=\"color: #D8DEE9\">SV_DispatchThreadID<\/span><span style=\"color: #D8DEE9FF\">)<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ECEFF4\">{<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #D8DEE9\">float3<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">POS<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">=<\/span><span style=\"color: #D8DEE9FF\"> (((<\/span><span style=\"color: #D8DEE9\">float3<\/span><span style=\"color: #D8DEE9FF\">)<\/span><span style=\"color: #D8DEE9\">id<\/span><span style=\"color: #D8DEE9FF\">)<\/span><span style=\"color: #81A1C1\">\/<\/span><span style=\"color: #D8DEE9FF\">(<\/span><span style=\"color: #D8DEE9\">float<\/span><span style=\"color: #D8DEE9FF\">)<\/span><span style=\"color: #D8DEE9\">texResolution<\/span><span style=\"color: #D8DEE9FF\">) <\/span><span style=\"color: #81A1C1\">*<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #B48EAD\">2.0<\/span><span style=\"color: #81A1C1\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #D8DEE9\">float<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">n<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">=<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #88C0D0\">snoise<\/span><span style=\"color: #D8DEE9FF\">(<\/span><span style=\"color: #D8DEE9\">POS<\/span><span style=\"color: #D8DEE9FF\">)<\/span><span style=\"color: #81A1C1\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #D8DEE9\">float<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">ring<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">=<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #88C0D0\">frac<\/span><span style=\"color: #D8DEE9FF\">(<\/span><span style=\"color: #D8DEE9\">noiseScale<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">*<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">n<\/span><span style=\"color: #D8DEE9FF\">)<\/span><span style=\"color: #81A1C1\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #D8DEE9\">float<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">delta<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #81A1C1\">=<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #88C0D0\">pow<\/span><span style=\"color: #D8DEE9FF\">(<\/span><span style=\"color: #D8DEE9\">ring<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">ringScale<\/span><span style=\"color: #D8DEE9FF\">) <\/span><span style=\"color: #81A1C1\">+<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">n<\/span><span style=\"color: #81A1C1\">;<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #D8DEE9FF\">    <\/span><span style=\"color: #D8DEE9\">Result<\/span><span style=\"color: #D8DEE9FF\">[<\/span><span style=\"color: #D8DEE9\">id<\/span><span style=\"color: #ECEFF4\">.<\/span><span style=\"color: #D8DEE9\">xy<\/span><span style=\"color: #D8DEE9FF\">] <\/span><span style=\"color: #81A1C1\">=<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #88C0D0\">lerp<\/span><span style=\"color: #D8DEE9FF\">(<\/span><span style=\"color: #D8DEE9\">darkColor<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">paleColor<\/span><span style=\"color: #ECEFF4\">,<\/span><span style=\"color: #D8DEE9FF\"> <\/span><span style=\"color: #D8DEE9\">delta<\/span><span style=\"color: #D8DEE9FF\">)<\/span><span style=\"color: #81A1C1\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ECEFF4\">}<\/span><\/span><\/code><\/pre><\/div>\n\n\n\n<p><\/p>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"data:image\/gif;base64,R0lGODlhAQABAIAAAAAAAP\/\/\/yH5BAEAAAAALAAAAAABAAEAAAIBRAA7\" data-src=\"https:\/\/\u80a5\u80a5.com\/wp-content\/uploads\/image-297.png\" alt=\"img\" class=\"wp-image-1434 lazyload\"\/><noscript><img decoding=\"async\" width=\"1440\" height=\"649\" src=\"https:\/\/\u80a5\u80a5.com\/wp-content\/uploads\/image-297.png\" alt=\"img\" class=\"wp-image-1434 lazyload\" srcset=\"https:\/\/remoooo.com\/wp-content\/uploads\/image-297.png 1440w, https:\/\/remoooo.com\/wp-content\/uploads\/image-297-300x135.png 300w, https:\/\/remoooo.com\/wp-content\/uploads\/image-297-1024x462.png 1024w, https:\/\/remoooo.com\/wp-content\/uploads\/image-297-768x346.png 768w\" sizes=\"(max-width: 1440px) 100vw, 1440px\" \/><\/noscript><\/figure>\n\n\n\n<h3 class=\"wp-block-heading\">5. Deformed Mesh<\/h3>\n\n\n\n<p>In this section, we will transform a Cube into a Sphere through Compute Shader, and we will also need an animation process with gradual changes!<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"data:image\/gif;base64,R0lGODlhAQABAIAAAAAAAP\/\/\/yH5BAEAAAAALAAAAAABAAEAAAIBRAA7\" data-src=\"https:\/\/\u80a5\u80a5.com\/wp-content\/uploads\/image-293.png\" alt=\"img\" class=\"wp-image-1430 lazyload\"\/><noscript><img decoding=\"async\" width=\"1216\" height=\"710\" src=\"https:\/\/\u80a5\u80a5.com\/wp-content\/uploads\/image-293.png\" alt=\"img\" class=\"wp-image-1430 lazyload\" srcset=\"https:\/\/remoooo.com\/wp-content\/uploads\/image-293.png 1216w, https:\/\/remoooo.com\/wp-content\/uploads\/image-293-300x175.png 300w, https:\/\/remoooo.com\/wp-content\/uploads\/image-293-1024x598.png 1024w, https:\/\/remoooo.com\/wp-content\/uploads\/image-293-768x448.png 768w\" sizes=\"(max-width: 1216px) 100vw, 1216px\" \/><\/noscript><\/figure>\n\n\n\n<p>As usual, declare vertex parameters on the CPU side, then throw them into the GPU for calculation, and apply the calculated new coordinates newPos to the Mesh.<\/p>\n\n\n\n<p>Vertex structure declaration. We attach a constructor to the CPU declaration for convenience. The GPU declaration is similar. Here, we intend to pass two buffers to the GPU, one read-only and the other read-write. At first, the two buffers are the same. As time changes (gradually), the read-write buffer gradually changes, and the Mesh changes from a cube to a ball.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>\/\/ CPU public struct Vertex { public Vector3 position; public Vector3 normal; public Vertex( Vector3 p, Vector3 n ) { position.x = px; position.y = py; position.z = pz; normal.x = nx; normal.y = ny; normal.z = nz; } } ...Vertex[] vertexArray; Vertex { float3 position; float3 normal; }; ... RWStructuredBuffer vertexBuffer; StructuredBuffer initialBuffer;<\/code><\/pre>\n\n\n\n<p>The complete steps of initialization ( Start() function) are as follows:<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li>On the CPU side, initialize the kernel and obtain the Mesh reference<\/li>\n\n\n\n<li>Transfer Mesh data to CPU<\/li>\n\n\n\n<li>Declare the Buffer of Mesh data in GPU<\/li>\n\n\n\n<li>Passing Mesh data and other parameters to the GPU<\/li>\n<\/ol>\n\n\n\n<p>After completing these operations, every frame Update, we apply the new vertices obtained from the GPU to the mesh.<\/p>\n\n\n\n<p>So how do we implement GPU computing?<\/p>\n\n\n\n<p>It&#039;s quite simple, we just need to normalize each vertex in the model space! Imagine that when all vertex position vectors are normalized, the model becomes a sphere.<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"data:image\/gif;base64,R0lGODlhAQABAIAAAAAAAP\/\/\/yH5BAEAAAAALAAAAAABAAEAAAIBRAA7\" data-src=\"https:\/\/\u80a5\u80a5.com\/wp-content\/uploads\/image-294.png\" alt=\"img\" class=\"wp-image-1431 lazyload\"\/><noscript><img decoding=\"async\" width=\"1198\" height=\"514\" src=\"https:\/\/\u80a5\u80a5.com\/wp-content\/uploads\/image-294.png\" alt=\"img\" class=\"wp-image-1431 lazyload\" srcset=\"https:\/\/remoooo.com\/wp-content\/uploads\/image-294.png 1198w, https:\/\/remoooo.com\/wp-content\/uploads\/image-294-300x129.png 300w, https:\/\/remoooo.com\/wp-content\/uploads\/image-294-1024x439.png 1024w, https:\/\/remoooo.com\/wp-content\/uploads\/image-294-768x330.png 768w\" sizes=\"(max-width: 1198px) 100vw, 1198px\" \/><\/noscript><\/figure>\n\n\n\n<p>In the actual code, we also need to calculate the normal at the same time. If we don&#039;t change the normal, the lighting of the object will be very strange. So the question is, how to calculate the normal? It&#039;s very simple. The coordinates of the original vertices of the cube are the final normal vectors of the ball!<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"data:image\/gif;base64,R0lGODlhAQABAIAAAAAAAP\/\/\/yH5BAEAAAAALAAAAAABAAEAAAIBRAA7\" data-src=\"https:\/\/\u80a5\u80a5.com\/wp-content\/uploads\/image-295.png\" alt=\"img\" class=\"wp-image-1432 lazyload\"\/><noscript><img decoding=\"async\" width=\"924\" height=\"568\" src=\"https:\/\/\u80a5\u80a5.com\/wp-content\/uploads\/image-295.png\" alt=\"img\" class=\"wp-image-1432 lazyload\" srcset=\"https:\/\/remoooo.com\/wp-content\/uploads\/image-295.png 924w, https:\/\/remoooo.com\/wp-content\/uploads\/image-295-300x184.png 300w, https:\/\/remoooo.com\/wp-content\/uploads\/image-295-768x472.png 768w\" sizes=\"(max-width: 924px) 100vw, 924px\" \/><\/noscript><\/figure>\n\n\n\n<p>In order to achieve the &quot;breathing&quot; effect, a sine function is added to control the normalization coefficient.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>float delta = (Mathf.Sin(Time.time) + 1)\/ 2;<\/code><\/pre>\n\n\n\n<p>Since the code is a bit long, I&#039;ll put a link.<\/p>\n\n\n\n<p>Current version code:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Compute Shader: https:\/\/github.com\/Remyuu\/Unity-Compute-Shader-Learn\/blob\/L2_Mesh_Cube2Sphere\/Assets\/Shaders\/MeshDeform.compute<\/li>\n\n\n\n<li>CPU: https:\/\/github.com\/Remyuu\/Unity-Compute-Shader-Learn\/blob\/L2_Mesh_Cube2Sphere\/Assets\/Scripts\/MeshDeform.cs<\/li>\n<\/ul>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"data:image\/gif;base64,R0lGODlhAQABAIAAAAAAAP\/\/\/yH5BAEAAAAALAAAAAABAAEAAAIBRAA7\" data-src=\"https:\/\/\u80a5\u80a5.com\/wp-content\/uploads\/image-299.png\" alt=\"img\" class=\"wp-image-1436 lazyload\"\/><noscript><img decoding=\"async\" width=\"1188\" height=\"866\" src=\"https:\/\/\u80a5\u80a5.com\/wp-content\/uploads\/image-299.png\" alt=\"img\" class=\"wp-image-1436 lazyload\" srcset=\"https:\/\/remoooo.com\/wp-content\/uploads\/image-299.png 1188w, https:\/\/remoooo.com\/wp-content\/uploads\/image-299-300x219.png 300w, https:\/\/remoooo.com\/wp-content\/uploads\/image-299-1024x746.png 1024w, https:\/\/remoooo.com\/wp-content\/uploads\/image-299-768x560.png 768w\" sizes=\"(max-width: 1188px) 100vw, 1188px\" \/><\/noscript><\/figure>\n\n\n\n<h3 class=\"wp-block-heading\">6. Summary\/Quiz<\/h3>\n\n\n\n<p>How this structure should be defined on the GPU:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>struct Circle { public Vector2 origin; public Vector2 velocity; public float radius; }<\/code><\/pre>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"data:image\/gif;base64,R0lGODlhAQABAIAAAAAAAP\/\/\/yH5BAEAAAAALAAAAAABAAEAAAIBRAA7\" data-src=\"https:\/\/\u80a5\u80a5.com\/wp-content\/uploads\/image-298.png\" alt=\"img\" class=\"wp-image-1435 lazyload\"\/><noscript><img decoding=\"async\" width=\"1440\" height=\"649\" src=\"https:\/\/\u80a5\u80a5.com\/wp-content\/uploads\/image-298.png\" alt=\"img\" class=\"wp-image-1435 lazyload\" srcset=\"https:\/\/remoooo.com\/wp-content\/uploads\/image-298.png 1440w, https:\/\/remoooo.com\/wp-content\/uploads\/image-298-300x135.png 300w, https:\/\/remoooo.com\/wp-content\/uploads\/image-298-1024x462.png 1024w, https:\/\/remoooo.com\/wp-content\/uploads\/image-298-768x346.png 768w\" sizes=\"(max-width: 1440px) 100vw, 1440px\" \/><\/noscript><\/figure>\n\n\n\n<p>How should this structure set the size of ComputeBuffer?<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>struct Circle { public Vector2 origin; public Vector2 velocity; public float radius; }<\/code><\/pre>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"data:image\/gif;base64,R0lGODlhAQABAIAAAAAAAP\/\/\/yH5BAEAAAAALAAAAAABAAEAAAIBRAA7\" data-src=\"https:\/\/\u80a5\u80a5.com\/wp-content\/uploads\/image-301.png\" alt=\"img\" class=\"wp-image-1438 lazyload\"\/><noscript><img decoding=\"async\" width=\"1440\" height=\"392\" src=\"https:\/\/\u80a5\u80a5.com\/wp-content\/uploads\/image-301.png\" alt=\"img\" class=\"wp-image-1438 lazyload\" srcset=\"https:\/\/remoooo.com\/wp-content\/uploads\/image-301.png 1440w, https:\/\/remoooo.com\/wp-content\/uploads\/image-301-300x82.png 300w, https:\/\/remoooo.com\/wp-content\/uploads\/image-301-1024x279.png 1024w, https:\/\/remoooo.com\/wp-content\/uploads\/image-301-768x209.png 768w\" sizes=\"(max-width: 1440px) 100vw, 1440px\" \/><\/noscript><\/figure>\n\n\n\n<p>Why is the following code wrong?<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>StructuredBuffer positions; \/\/Inside a kernel ... positions[id.x] = fixed3(1,0,0);<\/code><\/pre>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"data:image\/gif;base64,R0lGODlhAQABAIAAAAAAAP\/\/\/yH5BAEAAAAALAAAAAABAAEAAAIBRAA7\" data-src=\"https:\/\/\u80a5\u80a5.com\/wp-content\/uploads\/image-300.png\" alt=\"img\" class=\"wp-image-1437 lazyload\"\/><noscript><img decoding=\"async\" width=\"1440\" height=\"372\" src=\"https:\/\/\u80a5\u80a5.com\/wp-content\/uploads\/image-300.png\" alt=\"img\" class=\"wp-image-1437 lazyload\" srcset=\"https:\/\/remoooo.com\/wp-content\/uploads\/image-300.png 1440w, https:\/\/remoooo.com\/wp-content\/uploads\/image-300-300x78.png 300w, https:\/\/remoooo.com\/wp-content\/uploads\/image-300-1024x265.png 1024w, https:\/\/remoooo.com\/wp-content\/uploads\/image-300-768x198.png 768w\" sizes=\"(max-width: 1440px) 100vw, 1440px\" \/><\/noscript><\/figure>\n\n\n\n<h2 class=\"wp-block-heading\">References<\/h2>\n\n\n\n<figure class=\"wp-block-embed is-type-wp-embed is-provider-ming-wai-chan wp-block-embed-ming-wai-chan\"><div class=\"wp-block-embed__wrapper\">\nhttps:\/\/cmwdexint.com\/2017\/10\/20\/indirect-compute-shader\n<\/div><\/figure>","protected":false},"excerpt":{"rendered":"<p>Tags: Getting Started \/ Shader \/ Compute Shader \/ GPU Optimization Introduction Compute Shader is relatively complex and requires certain [...]<\/p>","protected":false},"author":1,"featured_media":1409,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[53],"tags":[74,37],"class_list":["post-1403","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-tech","tag-compute-shader","tag-unity"],"_links":{"self":[{"href":"https:\/\/remoooo.com\/en\/wp-json\/wp\/v2\/posts\/1403","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/remoooo.com\/en\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/remoooo.com\/en\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/remoooo.com\/en\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/remoooo.com\/en\/wp-json\/wp\/v2\/comments?post=1403"}],"version-history":[{"count":2,"href":"https:\/\/remoooo.com\/en\/wp-json\/wp\/v2\/posts\/1403\/revisions"}],"predecessor-version":[{"id":1598,"href":"https:\/\/remoooo.com\/en\/wp-json\/wp\/v2\/posts\/1403\/revisions\/1598"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/remoooo.com\/en\/wp-json\/wp\/v2\/media\/1409"}],"wp:attachment":[{"href":"https:\/\/remoooo.com\/en\/wp-json\/wp\/v2\/media?parent=1403"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/remoooo.com\/en\/wp-json\/wp\/v2\/categories?post=1403"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/remoooo.com\/en\/wp-json\/wp\/v2\/tags?post=1403"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}