详细信息:
我正处于程序性行星生成的过程中;到目前为止,我已经完成了动态LOD工作,但我目前的软件算法非常慢。我决定使用DX11的新镶嵌功能代替它。 目前,我的球体是一个细分的二十面体。 (所有等边三角形的20边)
当我使用我的软件算法细分时,会出现一个三角形 在父母的中点分成四个孩子,每次形成Hyrule符号......像这样:http://puu.sh/1xFIx
如您所见,每个细分的三角形创建了越来越多的等边三角形,即每个三角形的形状完全相同。
但是现在我正在使用GPU在HLSL中进行细分,结果肯定不是 我在寻找什么:http://puu.sh/1xFx7
问题:
我可以在Hull和Domain着色器中做些什么来改变曲面细分 以便它像第一张图像一样细分为等边三角形组?
我应该使用几何着色器这样的东西吗?如果是的话,会不会 比曲面细分更慢?
答案 0 :(得分:0)
我尝试使用Tessellation Shader,但我遇到了一个问题:当着色点的域位置为0.3,0.3,0.3(中心顶点)时,域着色器仅传递uv坐标(SV_DomainLocation)和用于定位顶点的输入补丁)不可能知道正确的位置,因为您需要有关其他顶点的信息或域着色器阶段未提供的迭代索引(x,y)。
因为这个问题我在几何着色器中编写代码,这个着色器对于镶嵌细分非常有限,因为输出流的大小不能超过1024字节(在着色器模型5.0中)。我使用uv(比如SV_DomainLocation)实现了顶点位置的计算,但是这个只镶嵌三角形,你必须使用部分代码来计算三角形中心的添加位置,以创建精确的最终结果。
这是等边三角形曲面细分的代码:
// required for array
#define MAX_ITERATIONS 5
void DrawTriangle(float4 p0, float4 p1, float4 p2, inout TriangleStream<VS_OUT> stream)
{
VS_OUT v0;
v0.pos = p0;
stream.Append(v0);
VS_OUT v1;
v1.pos = p1;
stream.Append(v1);
VS_OUT v2;
v2.pos = p2;
stream.Append(v2);
stream.RestartStrip();
}
[maxvertexcount(128)] // directx rule: maxvertexcount * sizeof(VS_OUT) <= 1024
void gs(triangle VS_OUT input[3], inout TriangleStream<VS_OUT> stream)
{
int itc = min(tess, MAX_ITERATIONS);
float fitc = itc;
float4 past_pos[MAX_ITERATIONS];
float4 array_pass[MAX_ITERATIONS];
for (int pi = 0; pi < MAX_ITERATIONS; pi++)
{
past_pos[pi] = float4(0, 0, 0, 0);
array_pass[pi] = float4(0, 0, 0, 0);
}
// -------------------------------------
// Tessellation kernel for the control points
for (int x = 0; x <= itc; x++)
{
float4 last;
for (int y = 0; y <= x; y++)
{
float2 seg = float2(x / fitc, y / fitc);
float3 uv;
uv.x = 1 - seg.x;
uv.z = seg.y;
uv.y = 1 - (uv.x + uv.z);
// ---------------------------------------
// Domain Stage
// uv Domain Location
// x,y IterationIndex
float4 fpos = input[0].pos * uv.x;
fpos += input[1].pos * uv.y;
fpos += input[2].pos * uv.z;
if (x > 0 && y > 0)
{
DrawTriangle(past_pos[y - 1], last, fpos, stream);
if (y < x)
{
// add adjacent triangle
DrawTriangle(past_pos[y - 1], fpos, past_pos[y], stream);
}
}
array_pass[y] = fpos;
last = fpos;
}
for (int i = 0; i < MAX_ITERATIONS; i++)
{
past_pos[i] = array_pass[i];
}
}
}