如何才能将 Tessellation Evaluation Shader 中的新顶点定位到球体中?

What can I do to position the new vertices from my Tessellation Evaluation Shader into a sphere?

提问人:ModernEraCaveman 提问时间:12/19/2022 最后编辑:SpektreModernEraCaveman 更新时间:12/20/2022 访问量:105

问:

我离解决方案还有大约四分之一半的路程;我能够使用曲面细分评估着色器生成球体的八个八分之一,但我无法以正确的方式定向它们。

这是我第一次尝试的代码。我发现归一化曲面细分坐标对于沿球体圆周重新定位新顶点很重要,但我一辈子都无法弄清楚如何正确定位和定向这些四分之一球体。

#version 460 core

// Triangles
layout (triangles, equal_spacing , ccw) in;
layout(location = 0) uniform mat4 modelMatrix;
layout(location = 1) uniform mat4 camMatrix;

void main()
{
    vec3 pos = normalize(gl_TessCoord);

    gl_Position = camMatrix * modelMatrix * vec4(pos, 1.f);
}

生成的四分之一球体(一个“单个”四分之一球体,但它实际上是所有相互堆叠的四分之一球体):

Image

这是我第二次尝试的代码。我越来越接近解决方案,因为宿舍被调整到正确的位置,但它们仍然没有正确定位以形成一个球体。

#version 460 core

// Triangles
layout (triangles, equal_spacing , ccw) in;
layout(location = 0) uniform mat4 modelMatrix;
layout(location = 1) uniform mat4 camMatrix;


void main()
{
    vec4 pos0 = gl_in[0].gl_Position;
    vec4 pos1 = gl_in[1].gl_Position;
    vec4 pos2 = gl_in[2].gl_Position;

    vec3 pos = normalize(gl_TessCoord) + pos0.xyz + pos1.xyz +pos2.xyz;

    gl_Position = camMatrix * modelMatrix * vec4(pos, 1.f);
}

生成的四分之一球体现在位于各自的位置,但它们的方向不正确。球体宿舍现在位于正确的位置,但方向不正确:

image

我希望缺乏色彩对比度不会使图像太难看清。我还没有在场景中添加光源,因为我想先让球体正确生成。

C++ OpenGL GLSL 着色器 曲面细分

评论

0赞 ModernEraCaveman 12/19/2022
@NicolBolas八个八分之一哈哈,我的坏

答:

1赞 Spektre 12/19/2022 #1

什么是着色器的输入,你渲染的单个三角形是什么?相对于球体放置在哪里?到底是什么?我假设从镶嵌着色器输出,但是您只共享顶点着色器......gl_TessCoord

看起来您正在抵消八进制而不是镜像!你应该做的就是否定坐标(所有 7 种组合,所以要得到一个八进制,你只需将位置乘以......另一个八进制乘以依此类推,直到最后一个八进制乘以完全没有偏移,如果您有整数的八进制,那么它的最低 3 位表示要否定的轴......把所有放在一起:(-1,+1,+1)(+1,-1,+1)(-1,-1,-1)i

#version 460 core

// Triangles
layout (triangles, equal_spacing , ccw) in;
layout(location = 0) uniform mat4 modelMatrix;
layout(location = 1) uniform mat4 camMatrix;
layout(location = 2) uniform int octant;

void main()
{
    vec3 pos = normalize(gl_TessCoord);
    if ((octant&1)!=0) pos.x=-pos.x;
    if ((octant&2)!=0) pos.y=-pos.y;
    if ((octant&4)!=0) pos.z=-pos.z;

    gl_Position = camMatrix * modelMatrix * vec4(pos, 1.f);
}

请注意,没有对此进行测试,也不确定 GLSL 中是否允许这样的位操作,但是要无分支地执行此操作,您可以简单地将乘法作为统一传递,并保留原始八进制及其 7 个镜像的这些值:vec3

octant0:(+1.0,+1.0,+1.0)
octant1:(-1.0,+1.0,+1.0)
octant2:(+1.0,-1.0,+1.0)
octant3:(-1.0,-1.0,+1.0)
octant4:(+1.0,+1.0,-1.0)
octant5:(-1.0,+1.0,-1.0)
octant6:(+1.0,-1.0,-1.0)
octant7:(-1.0,-1.0,-1.0)

然后用它乘以而不是那 3 个表达式......posif

0赞 ModernEraCaveman 12/20/2022 #2

我想我昨天完全没有找到解决方案是一整天编码和一大堆笨拙的结果。

所以,在睡了个好觉之后,我用新的眼光重新审视了这个问题。这一次,我使用了归一化函数,并将其应用于每个可能的向量,我发现解决方案是将三角形顶点向量乘以镶嵌的三角形顶点坐标(将新基元放在各自的八分位数中),然后归一化总和(使向量位于球体上)。

曲面细分评估着色器代码如下所示:

#version 460 core

// Triangles
layout (triangles, equal_spacing , ccw) in;
layout(location = 0) uniform mat4 modelMatrix;
layout(location = 1) uniform mat4 camMatrix;

void main()
{
    vec3 TC  = gl_TessCoord;
    vec4 pos0 = gl_in[0].gl_Position;
    vec4 pos1 = gl_in[1].gl_Position;
    vec4 pos2 = gl_in[2].gl_Position;

    vec3 pos = normalize( TC.x * pos0.xyz + TC.y * pos1.xyz + TC.z * pos2.xyz);

    gl_Position = camMatrix * modelMatrix * vec4(pos, 1.f);
}

对于那些关注的人来说,camMatrix 是视图和投影矩阵的乘积,因此镶嵌的球体具有动态的细节水平。

动态LOD如下所示:Minimum tessellation at long distance

Moderate tessellation at medium distance

Maximum tessellation at close distance

总的来说,我对结果非常满意。可以在曲面细分控件着色器中编辑曲面细分量,以及曲面细分的最小和最大距离。

有时,解决方案就在明天的门后等待!