私は計算シェーダーと、それを使用して y 軸上の頂点の配列を変更するために使用される C# スクリプトを持っています。
しかし、正常に動作するという事実にもかかわらず、シェーダーは私の形状の最初の頂点を忘れているようです (その形状が閉じたボリュームの場合を除く?)
C# クラスは次のとおりです。
Mesh m;
//public bool stopProcess = false; //Useless in this version of exemple
MeshCollider coll;
public ComputeShader csFile; //the compute shader file added the Unity way
Vector3[] arrayToProcess; //An array of vectors i'll use to store data
ComputeBuffer cbf; //the buffer CPU->GPU (An early version with exactly
//the same result had only this one)
ComputeBuffer cbfOut; //the Buffer GPU->CPU
int vertexLength;
void Awake() { //Assigning my stuff
coll = gameObject.GetComponent<MeshCollider>();
m = GetComponent<MeshFilter>().sharedMesh;
vertexLength = m.vertices.Length;
arrayToProcess = m.vertices; //setting the first version of the vertex array (copy of mesh)
}
void Start () {
cbf = new ComputeBuffer(vertexLength,32); //Buffer in
cbfOut = new ComputeBuffer(vertexLength,32); //Buffer out
csFile.SetBuffer(0,"Board",cbf);
csFile.SetBuffer(0,"BoardOut",cbfOut);
}
void Update () {
csFile.SetFloat("time",Time.time);
cbf.SetData(m.vertices);
csFile.Dispatch(0,vertexLength,vertexLength,1); //Dispatching (i think there is my mistake)
cbfOut.GetData(arrayToProcess); //getting back my processed vertices
m.vertices = arrayToProcess; //assigning them to the mesh
//coll.sharedMesh = m; //collider stuff useless in this demo
}
そして私の計算シェーダースクリプト:
#pragma kernel CSMain
RWStructuredBuffer<float3> Board : register(s[0]);
RWStructuredBuffer<float3> BoardOut : register(s[1]);
float time;
[numthreads(1,1,1)]
void CSMain (uint3 id : SV_DispatchThreadID)
{
float valx = (sin((time*4)+Board[id.x].x));
float valz = (cos((time*2)+Board[id.x].z));
Board[id.x].y = (valx + valz)/5;
BoardOut[id.x] = Board[id.x];
}
最初は同じバッファから読み書きしていましたが、問題が発生したため、別のバッファを使用しようとしましたが、成功しませんでした。私はまだ同じ問題を抱えています。
計算シェーダーの使用方法を誤解している可能性があります (頂点シェーダーを使用できることはわかっていますが、計算シェーダーをさらに改善するために試してみたいだけです)。
私が言ったことを完了するために、Mesh.vertices Array で頂点にインデックスを付ける方法に関連していると思います。
さまざまなブロック/スレッド構成をたくさん試しましたが、試した問題の組み合わせを解決するものは何もないようです:
Block Thread
60,60,1 1,1,1
1,1,1 60,60,3
10,10,3 3,1,1
私が覚えていない他のいくつか。以下のようなバランスの良い構成がベストだと思います。
Block : VertexCount,1,1 Thread : 3,1,1
閉じたボリュームについて: Cube {8 Vertices} ではすべてがそれに応じて移動するように見えるため、それについてはわかりませんが、頂点の数が奇数の形状では、最初の (または最後はまだチェックしていません) ようです処理されません
さまざまな形状で試してみましたが、分割された平面が最も明白で、1 つの角が常に動かないことがわかりました。
編集 :
さらに調査した結果、メッシュの最後の (最初にチェックした頂点ではなく) 頂点を計算しないのは単に計算シェーダーであることがわかりました。これはバッファーの種類に関連しているようです。なぜ RWStructuredBuffer が問題になるのか、まだわかりません。ストリーム用に予約されていますか? これに関するMSDNドキュメントを理解できません。
編集:解決後
C# スクリプト:
using UnityEngine;
using System.Collections;
public class TreeObject : MonoBehaviour {
Mesh m;
public bool stopProcess = false;
MeshCollider coll;
public ComputeShader csFile;
Vector3[] arrayToProcess;
ComputeBuffer cbf;
ComputeBuffer cbfOut;
int vertexLength;
// Use this for initialization
void Awake() {
coll = gameObject.GetComponent<MeshCollider>();
m = GetComponent<MeshFilter>().mesh;
vertexLength = m.vertices.Length+3; //I add 3 because apparently
//vertexnumber is odd
//arrayToProcess = new Vector3[vertexLength];
arrayToProcess = m.vertices;
}
void Start () {
cbf = new ComputeBuffer(vertexLength,12);
cbfOut = new ComputeBuffer(vertexLength,12);
csFile.SetBuffer(0,"Board",cbf);
csFile.SetBuffer(0,"BoardOut",cbfOut);
}
// Update is called once per frame
void Update () {
csFile.SetFloat("time",Time.time);
cbf.SetData(m.vertices);
csFile.Dispatch(0,vertexLength,1,1);
cbfOut.GetData(arrayToProcess);
m.vertices = arrayToProcess;
coll.sharedMesh = m;
}
}
VCount*VCount を使用していたので、頂点を必要以上に "2 乗" 回処理していたのはロジックだったので、回答の前に既に Blocks VCount,1,1 にロールバックしていました。
完了するには、ストライドが明らかに問題を引き起こしていることは間違いありませんでした。ストライド パラメータに関するドキュメントへのリンクを使用して回答を完成させていただけますか? (Unity ドキュメントは VOID であり、MSDN は 32 ではなく 12 であるべき理由を理解するのに役立たなかったため、どこからでも (32 は float3 のサイズだと思っていたので)
Docが必要です
それまでの間、これをより強力にするために十分に柔軟な (ジェネリック?) バージョンを提供し、シェーダーにいくつかの優れた配列処理関数を追加することを試みます...