1

为什么下面的tessellation control shader会让大部分三角形消失?

#version 410

layout(vertices = 3) out;

void main(void) {
    gl_TessLevelInner[0]=1;
    gl_TessLevelOuter[gl_InvocationID]=gl_InvocationID+1;
    gl_TessLevelOuter[gl_InvocationID]=gl_InvocationID+1;
    gl_TessLevelOuter[gl_InvocationID]=gl_InvocationID+1;
}

我输入三角形。当我用 0,1 和 2 索引 gl_TessLevelOuter 时,一切正常。在我看来,这个构造为我节省了 if 语句,我相信这有助于并行执行着色器。当然,我省略了片段中的顶点计算。

4

3 回答 3

4

三角形消失了,因为你招致了“未定义”的行为,就是这样。内部曲面细分级别应至少为 2。

gl_TessLevelInner[0] = 2;

您获得的奇怪结果是因为当内部级别为 1 时如何计算重心坐标。假设您提供了至少 2 作为值,您可以为 Outerlevels 使用您想要的任何值。

以下是三角形的边关联

out0 => edge 1-2
out1 => edge 2-3
out2 => edge 3-1

镶嵌三角形

Out[0] = 4
Out[1] = 1
Out[2] = 2

如您所见,Inner2 中的 2 沿着三角形的平分线切割了三角形两次,而 3 个不同的Outer水平线沿着边缘切割了三角形(没有切割1,两次切割,2当值为 4 时4

提示:

还有一些小建议,tessellation control 中的数据是共享的,也就是说它被多次调用,你只需要设置 tessellation control 一次:

if(gl_InvocationID==0){
    gl_TessLevelInner[0] = 2; //take a triangle

    gl_TessLevelOuter[0] = 1; //and subdivde it in 3 triangles
    gl_TessLevelOuter[1] = 1;
    gl_TessLevelOuter[2] = 1;
}
gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;

那么为什么仍然可以为每次调用设置不同的值呢?那是根据屏幕错误添加细分(至少是合理的使用)。

if(gl_InvocationID==0){
    gl_TessLevelInner[0] = 2; //take a triangle
    gl_TessLevelOuter[0] = lenghtOnScreen<5? 3: 4;
}

if(gl_InvocationID==1)
    gl_TessLevelOuter[1] = lenghtOnScreen<5? 3: 4;

if(gl_InvocationID==2)
    gl_TessLevelOuter[2] = lenghtOnScreen<5? 3: 4;

gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;

到底:

Inner=3和的另一个例子Outer=2

镶嵌三角形

注意沿等分线的 3 个切口和沿边缘的 2 个切口,所有其他切口仅用于“无缝过渡”

于 2015-01-17T10:10:10.350 回答
3

接受的答案不正确。您可以指定内部层级为 1。如果所有外部层级也为 1,则不会有细分(三角形将保持不变)。如果内部为 1 并且至少一个外部大于 1,则内部将有效地为 2 或 3(取决于间距),确保内部区域中至少有 1 个点。

OP 代码的实际问题是它设置了1 个外部级别 3 次,而不是设置所有 3 个外部级别。其他 2 个默认为 0,导致补丁被丢弃。 就是三角形消失的原因。

参考:https ://www.opengl.org/wiki/Tessellation

于 2016-10-05T19:02:56.207 回答
-2

因为您正在使用三角形,所以可以给外部的最小值是 3,因此,在您的情况下,您将索引 0 设置为 1,将 1 设置为 2,将 2 设置为 3,但是当您通过 0、1、2 对它们进行寻址时它的工作原理是他们将获得的最终价值gl_InvocationID = 2 + 1 = 3,因此您可以节省一天的时间,如果您这样做,它应该可以工作:

void main(void) {
    gl_TessLevelOuter[gl_InvocationID] = 3;
    gl_TessLevelInner[0] = max(gl_TessLevelInner[0], gl_TessLevelOuter[gl_InvocationID]); // that is a bonus =D
}
于 2014-10-13T22:08:02.743 回答