Home > Software design >  Understanding Buffer and SetBuffer method in Unity
Understanding Buffer and SetBuffer method in Unity

Time:09-28

I don't understand why the _Positions property of ComputeShader was given as a parameter of material.SetBuffer.

I thought SetSomething(property, value) method give value to property.

But in this case, _Positions property is a ComputeShader's variable then what is the mean of giving it to material?

And experience has shown that the code actually stores the positions of the material. How and Why it does?

I think I'm missing something fundamental about Buffers.

And Is it relative with where does ShaderGraph's Position Node input come from?

C# Code:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class GPUGraph : MonoBehaviour
{
    [SerializeField]
    ComputeShader computeShader;
    static int positionID = Shader.PropertyToID("_Positions");
 // _Positions poperty in computeShader
 // RWStructuredBuffer<float3> _Positions;
 // Some position data saved in _Positions property

    [SerializeField]
    Material material;

    [SerializeField]
    Mesh mesh;

    ComputeBuffer positionBuffer;
    const int MaxResolution = 10;

    void OnEnable() {
        positionBuffer = new ComputeBuffer(MaxResolution * MaxResolution, 3 * 4);

    }
    
    void OnDisable() {
        positionBuffer.Release();
        positionBuffer = null;
    }
    void Update() {
        UpdateFunctionOnGPU();
    }

    void UpdateFunctionOnGPU() {        
        computeShader.SetBuffer(0, positionID, positionBuffer);

        int groups = Mathf.CeilToInt(MaxResolution / 8f);

        computeShader.Dispatch(0, groups, groups, 1);

        material.SetBuffer(positionID, positionBuffer);

        var bounds = new Bounds(Vector3.zero, Vector3.one * (2f   2f / resolution));
        Graphics.DrawMeshInstancedProcedural(mesh, 0, material, bounds, resolution * resolution);
    }
}

ShaderGraph applied to material

CodePudding user response:

To make it clear for yourself, you should understand what shaders and materials are.

Shader - is a kind of program, that is executed on GPU. It differs from regular programs for CPU written in C#, Java or something. Mostly shaders are written in C-like languages (HLSL in Unity). There are also codeless tools, like Shader Graph in Unity for shaders creating. And shaders are used to draw something on your screen.

Material - is an abstract concept, that represents a... I think it can be called shader instance. In other words, it is a structure, that contains data about which shader should be executed and with which parameters, and maybe some other data about shader execution.

And speaking about buffers. As I said, shaders deffer from regular CPU program. And, to execute it, you should make three general steps.

  1. Load this program on GPU
  2. Load data, that should be handled by this program (parameters of this program).
  3. Say GPU to execute this program.

And if you have experience with low level network development, or different kind of hardware components interactions, you could know, that buffers are the main way to pass any data from component to component, or from computer to computer. So, to pass any data to the GPU, you should place it in the concrete buffer. It can be a buffer for executable code, or for parameters, or for some control instructions. And sometimes there is one buffer for several goals, and you should know which byte positions in the buffer are needed for you.

Unity encapsulate all this staff from you. And you can work only with materials, actually. In your code, you have positionID = Shader.PropertyToID("_Positions"). For Unity, it is an indicator of buffer, that should be loaded to the GPU to make it understand, that this data should be handled as "_Positions" variable. And after this you execute material.SetBuffer(positionID, positionBuffer); And, generally, link your created buffer for this indicator. And after you do it (not instantly, but probably in render step of Unity execution pipeline), this positionBuffer will be loaded to the GPU and will be handled as _Position variable.

  • Related