使用计算着色器生成共享顶点的平面网格
Generating a flat mesh that shares vertices using compute shaders
我遇到了一个看起来很简单的问题,但现在却因为我沮丧的尖叫声而引起了邻居的噪音投诉。
长话短说;博士
程序网格通常使用四边形条带制作。相反,我试图将一个网格作为一个整体,重复使用边缘顶点,而不是像一个网格一样排列四边形条带。
我正在测试一些东西,所以这可能是一种奇怪的方法,但它应该有效。
着色器 1:
RWStructuredBuffer<float3> vertexBuffer;
uniform uint yColumnHeight;
[numthreads(8,8,1)]
void calcVerts (uint3 id : SV_DispatchThreadID)
{
//convert x and y to 1 dimensional counter
int idx = (id.y + (yColumnHeight * id.x));
//create a flat array of vertices
float3 vA = float3(id.x, 1, id.y);
vertexBuffer[idx] = vA;
}
着色器 2:
RWStructuredBuffer<float3> vertexBuffer;
RWStructuredBuffer<float3> triangleBuffer;
uniform uint yColumnHeight;
[numthreads(8,8,1)]
void createMeshFromVerts (uint3 id : SV_DispatchThreadID)
{
int idx = (id.y + (yColumnHeight * id.x));
if (id.x > 0 && id.y > 0){
//convert idx to index for tri/quad vertices, skipping first row and column
int subtractFirstYColumn = idx - yColumnHeight;
int subtractFirstXRow = id.y - 1;
int trID = (subtractFirstYColumn - subtractFirstXRow) * 6;
//find the vertices of the quad using verts from first row and column
int tri_a = idx - yColumnHeight - 1;
int tri_b = idx - 1;
int tri_c = idx;
int tri_d = idx - yColumnHeight;
triangleBuffer[trID] = vertexBuffer[tri_a];
triangleBuffer[trID + 1] = vertexBuffer[tri_b];
triangleBuffer[trID + 2] = vertexBuffer[tri_c];
triangleBuffer[trID + 3] = vertexBuffer[tri_d];
triangleBuffer[trID + 4] = vertexBuffer[tri_a];
triangleBuffer[trID + 5] = vertexBuffer[tri_c];
}
}
第二个着色器最初可能看起来很迟钝,但它非常简单。我得到了一组顶点:
. . . .
. . . .
. . . .
. . . .
在上面,这是一个 3x3 的四边形网格,由 4x4 的顶点组成。
我首先让 vert 1 穿过和 1 向下,然后用左上角的顶点制作一个四边形。
每个四边形都以 vert _ 开头并使用前面的 verts 。像这样:
. .
. _
并在主 C# 中捆绑在一起:
//buffers for vertices and map of vertices to make triangles
vertexBuffer = new ComputeBuffer(triVertCount, stride, ComputeBufferType.Default);
triangleBuffer = new ComputeBuffer(tris, stride, ComputeBufferType.Default);
//create initial vertices grid
calcVerts.SetBuffer(verts, "vertexBuffer", vertexBuffer);
calcVerts.Dispatch(verts, Mathf.Max(1, (widthInVertices) / (int)threadsx), Mathf.Max(1, (heightInVertices) / (int)threadsy), (int)z);
//use vertices grid to make mesh
createMeshFromVerts.SetBuffer(meshFromVerts, "vertexBuffer", vertexBuffer);
createMeshFromVerts.SetBuffer(meshFromVerts, "triangleBuffer", triangleBuffer);
createMeshFromVerts.Dispatch(meshFromVerts, Mathf.Max(1, (widthInVertices) / (int)threadsx), Mathf.Max(1, (heightInVertices) / (int)threadsy), (int)z);
我跳过了法线的代码,并在其中传递给 material 进行渲染。当它运行时,我得到了混乱的三角形。你能看到我哪里搞砸了吗?
trId
的计算导致某些索引重叠,并跳过其他值。
具有 4x2 顶点网格(显示 idx)和 yColumnHeight
4:
0 4
x <- (desired trID 0)
1 5
x <- (desired trID 6)
2 6
x <- (desired trID 12)
3 7
当前为id
= 1,1 (idx 5)计算的trId
结果为6,但它可能应该为0,以便[=19中的前6项=] 设置为有用的东西。事实上,使用当前计算,没有 trId
等于 0。此外,当前计算的 trId
for id
= 1,2 (idx 6) 也为 6! id
=1,3 (idx 7) 也是如此。
遗憾的是,这种重叠发生在每一列中,因此大多数 triangleBuffer
都未设置。
答案是改变 trId
的计算方式。
一个简单的方法是重复使用从二维数组映射到一维数组的方法,只将 x 和 y 坐标减 1,同时将高度减 1:
顶点映射(当前):
int idx = (id.y + (yColumnHeight * id.x));
三角形映射(提议):
int trId = ((id.y-1) + ((yColumnHeight-1) * (id.x-1));
trId *= 6;
或更简单地说:
int trId = 6 * (id.y - 1 + (yColumnHeight-1) * (id.x-1));
或者,扩展和替换 idx
。我发现这不太清楚发生了什么,但它更简洁:
// = 6 * (id.y - 1 + yColumnHeight * id.x - yColumnHeight - id.x + 1)
// = 6 * (id.y + yColumnHeight * id.x - yColumnHeight - id.x)
int trId = 6 * (idx - yColumnHeight - id.x);
我遇到了一个看起来很简单的问题,但现在却因为我沮丧的尖叫声而引起了邻居的噪音投诉。
长话短说;博士 程序网格通常使用四边形条带制作。相反,我试图将一个网格作为一个整体,重复使用边缘顶点,而不是像一个网格一样排列四边形条带。
我正在测试一些东西,所以这可能是一种奇怪的方法,但它应该有效。
着色器 1:
RWStructuredBuffer<float3> vertexBuffer;
uniform uint yColumnHeight;
[numthreads(8,8,1)]
void calcVerts (uint3 id : SV_DispatchThreadID)
{
//convert x and y to 1 dimensional counter
int idx = (id.y + (yColumnHeight * id.x));
//create a flat array of vertices
float3 vA = float3(id.x, 1, id.y);
vertexBuffer[idx] = vA;
}
着色器 2:
RWStructuredBuffer<float3> vertexBuffer;
RWStructuredBuffer<float3> triangleBuffer;
uniform uint yColumnHeight;
[numthreads(8,8,1)]
void createMeshFromVerts (uint3 id : SV_DispatchThreadID)
{
int idx = (id.y + (yColumnHeight * id.x));
if (id.x > 0 && id.y > 0){
//convert idx to index for tri/quad vertices, skipping first row and column
int subtractFirstYColumn = idx - yColumnHeight;
int subtractFirstXRow = id.y - 1;
int trID = (subtractFirstYColumn - subtractFirstXRow) * 6;
//find the vertices of the quad using verts from first row and column
int tri_a = idx - yColumnHeight - 1;
int tri_b = idx - 1;
int tri_c = idx;
int tri_d = idx - yColumnHeight;
triangleBuffer[trID] = vertexBuffer[tri_a];
triangleBuffer[trID + 1] = vertexBuffer[tri_b];
triangleBuffer[trID + 2] = vertexBuffer[tri_c];
triangleBuffer[trID + 3] = vertexBuffer[tri_d];
triangleBuffer[trID + 4] = vertexBuffer[tri_a];
triangleBuffer[trID + 5] = vertexBuffer[tri_c];
}
}
第二个着色器最初可能看起来很迟钝,但它非常简单。我得到了一组顶点:
. . . .
. . . .
. . . .
. . . .
在上面,这是一个 3x3 的四边形网格,由 4x4 的顶点组成。 我首先让 vert 1 穿过和 1 向下,然后用左上角的顶点制作一个四边形。 每个四边形都以 vert _ 开头并使用前面的 verts 。像这样:
. .
. _
并在主 C# 中捆绑在一起:
//buffers for vertices and map of vertices to make triangles
vertexBuffer = new ComputeBuffer(triVertCount, stride, ComputeBufferType.Default);
triangleBuffer = new ComputeBuffer(tris, stride, ComputeBufferType.Default);
//create initial vertices grid
calcVerts.SetBuffer(verts, "vertexBuffer", vertexBuffer);
calcVerts.Dispatch(verts, Mathf.Max(1, (widthInVertices) / (int)threadsx), Mathf.Max(1, (heightInVertices) / (int)threadsy), (int)z);
//use vertices grid to make mesh
createMeshFromVerts.SetBuffer(meshFromVerts, "vertexBuffer", vertexBuffer);
createMeshFromVerts.SetBuffer(meshFromVerts, "triangleBuffer", triangleBuffer);
createMeshFromVerts.Dispatch(meshFromVerts, Mathf.Max(1, (widthInVertices) / (int)threadsx), Mathf.Max(1, (heightInVertices) / (int)threadsy), (int)z);
我跳过了法线的代码,并在其中传递给 material 进行渲染。当它运行时,我得到了混乱的三角形。你能看到我哪里搞砸了吗?
trId
的计算导致某些索引重叠,并跳过其他值。
具有 4x2 顶点网格(显示 idx)和 yColumnHeight
4:
0 4
x <- (desired trID 0)
1 5
x <- (desired trID 6)
2 6
x <- (desired trID 12)
3 7
当前为id
= 1,1 (idx 5)计算的trId
结果为6,但它可能应该为0,以便[=19中的前6项=] 设置为有用的东西。事实上,使用当前计算,没有 trId
等于 0。此外,当前计算的 trId
for id
= 1,2 (idx 6) 也为 6! id
=1,3 (idx 7) 也是如此。
遗憾的是,这种重叠发生在每一列中,因此大多数 triangleBuffer
都未设置。
答案是改变 trId
的计算方式。
一个简单的方法是重复使用从二维数组映射到一维数组的方法,只将 x 和 y 坐标减 1,同时将高度减 1:
顶点映射(当前):
int idx = (id.y + (yColumnHeight * id.x));
三角形映射(提议):
int trId = ((id.y-1) + ((yColumnHeight-1) * (id.x-1));
trId *= 6;
或更简单地说:
int trId = 6 * (id.y - 1 + (yColumnHeight-1) * (id.x-1));
或者,扩展和替换 idx
。我发现这不太清楚发生了什么,但它更简洁:
// = 6 * (id.y - 1 + yColumnHeight * id.x - yColumnHeight - id.x + 1)
// = 6 * (id.y + yColumnHeight * id.x - yColumnHeight - id.x)
int trId = 6 * (idx - yColumnHeight - id.x);