Unity3d 统一:在GPU上重新计算网格

Unity3d 统一:在GPU上重新计算网格,unity3d,unity5,Unity3d,Unity5,我在网上搜索了一段时间,但对于我目前的问题找不到一个好的答案:在unity中,一个可见的对象由一个网格组成。在OpenGL术语中,网格是顶点缓冲区,理想情况下传输一次到GPU,然后馈送到顶点着色器 现在,在某个给定点,我想在GPU上重新计算给定的网格。例如,如果我的VertexBuffer有空间容纳作为立方体一部分的200个Vector3,我想调用ComputeShader更新每个Vector3,使网格现在成为一个球体 我知道我可以使用CPU重新分配网格,但在我的场景中,这太慢了 所以问题是,如

我在网上搜索了一段时间,但对于我目前的问题找不到一个好的答案:在unity中,一个可见的对象由一个网格组成。在OpenGL术语中,网格是顶点缓冲区,理想情况下传输一次到GPU,然后馈送到顶点着色器

现在,在某个给定点,我想在GPU上重新计算给定的网格。例如,如果我的VertexBuffer有空间容纳作为立方体一部分的200个Vector3,我想调用ComputeShader更新每个Vector3,使网格现在成为一个球体

我知道我可以使用CPU重新分配网格,但在我的场景中,这太慢了

所以问题是,如何将顶点缓冲区或网格传递到unity中的ComputeShader中?我想直接修改VertexBuffer


感谢您的想法、资源和提示

计算着色器的设置非常简单

编写一个这样的计算着色器

#pragma kernel CSMain

#define thread_group_size_x 4
#define thread_group_size_y 4

//A struct that simple holds a position
struct PositionStruct
{
    float3 pos;
};

RWStructuredBuffer<PositionStruct> output;

[numthreads(thread_group_size_x,thread_group_size_y,1)]

void CSMain (uint3 id : SV_DispatchThreadID)
{
   int idx = id.x + id.y * thread_group_size_x * 32;
   float spacing = 1.0;

   float3 pos = float3(id.x*spacing, id.y*spacing, id.z*spacing);

   pos = UpdateVertex(pos,idx);

   output[idx].pos = pos;
}

float3 UpdateVertex(float3 p, int idx)
{
    //Do your stuff here
    return p;
}

这个步骤是vector3数据=新vector3[200];outputbuffer.GetDatadata;必需的它读起来像是将数据复制回cpu。但是outputbuffer是我的openGL VertexBuffer,可以这么说吗?因此,如果我知道缓冲区的长度,我可以直接将其交给网格,而无需复制回cpu?为了获取数据,必须让缓冲区将结果数据从自身复制到cpu RAM中的新位置。这是在调用dispatch之后使用GetData方法完成的。好的,最后一个问题。其中是buf_点的来源,在对SetBuffer的调用中。您可以跳过该部分metrial.SetBufferstring名称,ComputeBuffer值,其中name是属性名称。buf_Points是在着色器中定义的属性名称。也就是说,如果你已经编写了着色器来绘制它,那么它就可以工作了。很不错的。我提出了最后一个问题,我找不到任何关于它的信息:为什么它是int idx=id.x+id.y*thread\u group\u size\u x*32;为什么是*32。它是从哪里来的。
public class ComputeShaderScript: MonoBehaviour
{
public Shader shader;
public ComputeShader computeShader;

private ComputeBuffer outputBuffer;
private int _kernel;
private Material material;

void Start()
{
 RunShader();
}

void RunShader()
{
  _Kernal = computeShader.FindKernal("CSMain");

  vector3 Array = new vector3[200];
  outputBuffer = new ComputeBuffer(Array.Length, 12); //Output buffer  contains      vertices (float3 = Vector3 -> 12 bytes)
  outputbuffer.SetData(Array);

  computeShader.SetBuffer(_Kernal,"output",outputBuffer);

  computeShader.Dispatch(_Kernal,array.Length,1,1);

  vector3 data= new vector3[200];
  outputbuffer.GetData(data);

  buffer.Dispose();

  material.SetPass(0);
  material.SetBuffer("buf_Points", outputBuffer);
  Graphics.DrawProcedural(MeshTopology.Points, data.Length);
}