Opengl 低多边形圆锥体-尖端平滑着色

Opengl 低多边形圆锥体-尖端平滑着色,opengl,3d,geometry,directx,mesh,Opengl,3d,Geometry,Directx,Mesh,如果将圆柱体细分为8面棱柱体,根据顶点法线的位置(“平滑着色”)计算顶点法线,效果会非常好 如果将圆锥体细分为8边棱锥体,根据法线的位置计算法线,则会卡在圆锥体的尖端上(从技术上讲是圆锥体的顶点,但我们称其为尖端以避免与网格顶点混淆) 对于每个三角形面,您希望沿两条边匹配法线。但由于只能在三角形的每个顶点指定一条法线,因此可以匹配一条边或另一条边,但不能同时匹配两条边。可以通过选择两条边的平均值作为“尖端法线”进行折衷,但现在没有一条边看起来很好。下面是为每个顶点选择平均法线的详细信息 在一

如果将圆柱体细分为8面棱柱体,根据顶点法线的位置(“平滑着色”)计算顶点法线,效果会非常好

如果将圆锥体细分为8边棱锥体,根据法线的位置计算法线,则会卡在圆锥体的尖端上(从技术上讲是圆锥体的顶点,但我们称其为尖端以避免与网格顶点混淆)

对于每个三角形面,您希望沿两条边匹配法线。但由于只能在三角形的每个顶点指定一条法线,因此可以匹配一条边或另一条边,但不能同时匹配两条边。可以通过选择两条边的平均值作为“尖端法线”进行折衷,但现在没有一条边看起来很好。下面是为每个顶点选择平均法线的详细信息

在一个完美的世界里,GPU可以光栅化一个真正的四边形,而不仅仅是三角形。然后,我们可以使用退化四边形指定每个面,允许我们为每个三角形的两个相邻边指定不同的法线。但我们要做的只是三角形。。。我们可以将圆锥体切割成多个“堆叠”,这样边缘不连续性只在圆锥体的顶端可见,而不是沿着整个圆锥体可见,但仍然会有一个尖端


有人对平滑着色的低多边形圆锥体有什么窍门吗?

是的,这当然是三角形的限制。我认为,当你从圆柱体接近圆锥体时,显示问题会让问题变得非常清楚:

这里有一些你可以尝试的东西

  • 使用四边形(如@WhitAngl所说)。让新的OpenGL见鬼去吧,毕竟四边形是有用的

  • 细分得更均匀一点。将尖端的法线设置为公共上方向向量将删除任何粗糙的边,尽管在未照亮的一侧看起来有点奇怪。不幸的是,这与您的问题标题“低多边形圆锥体”背道而驰

  • 确保圆锥体围绕对象空间原点居中(或在顶点着色器中按程序生成圆锥体),使用碎片位置生成法线

    in vec2 coneSlope; //normal x/z magnitude and y
    in vec3 objectSpaceFragPos;
    
    uniform mat3 normalMatrix;
    
    void main()
    {
        vec3 osNormal = vec3(normalize(objectSpaceFragPos.xz) * coneSlope.x, coneSlope.y);
        vec3 esNormal = normalMatrix * osNormal;
        ...
    }
    
    也许你也可以用一些花哨的技巧来减少碎片着色器的操作。 然后是细分更多着色器与更昂贵着色器之间的整体平衡


  • 圆锥体是一个相当简单的物体,虽然我喜欢这个挑战,但在实践中,我不认为这是一个问题,除非你想要很多圆锥体。在这种情况下,您可能会进入几何体着色器或实例化。更好的是,可以在片段着色器中使用四边形和光线投射隐式圆锥体绘制圆锥体。如果圆锥体都在一个平面上,你可以尝试法线贴图,甚至视差贴图。

    我在现代OpenGL(即着色器)中努力使用由三角形组成的圆锥体,但后来我发现了一个非常简单的解决方案!我想说,这比目前被接受的答案中的建议要好得多,也简单得多

    我有一个三角形阵列(显然每个三角形有3个顶点),它们形成了锥形曲面。我不关心底面(圆形底座),因为这非常简单。在我的所有工作中,我使用以下简单的顶点结构:

    • 位置:vec3
      (通过添加1.0f作为最后一个元素,在着色器中自动转换为vec4)

    • 法线_向量:vec3
      (在着色器中保持为vec3,因为它用于计算与灯光方向的点积)

    • color:vec3
      (我没有使用透明度)

    在我的顶点着色器中,我只变换顶点位置(乘以投影和模型视图矩阵),还变换法向量(乘以模型视图矩阵的变换逆)。然后,变换的位置、法向量和未变换的颜色被传递到片段着色器,在那里我计算了光方向和法向量的点积,并将这个数字与颜色相乘

    让我从我所做的事情开始,我觉得不满意:

    尝试#1:每个锥面(三角形)使用一个恒定的法向量,即一个三角形的所有顶点具有相同的法向量。 这很简单,但没有实现平滑照明,每个面都有一个恒定的颜色,因为三角形的所有片段都有相同的法向量。错

    尝试#2:我分别计算了每个顶点的法向量。这对于圆锥体圆底上的顶点来说很容易,但是圆锥体尖端应该使用什么呢?我使用了整个三角形的法向量(即与尝试#中的值相同)。这更好,因为我在靠近圆锥体底部的部分有平滑的照明,但在靠近尖端的部分不平滑。错

    但后来我找到了解决办法:

    尝试#3:我做了与尝试#2相同的一切,除了我将锥尖顶点中的法向量指定为等于零向量vec3(0.0f,0.0f,0.0f)。这是诀窍的关键然后将该零法向量传递给片段着色器(即,在顶点和片段着色器之间,它将自动与其他两个顶点的法向量插值)。当然然后您需要规范化片段(!)着色器中的向量,因为它没有恒定的大小1(我需要点积)。所以我规范化了它-当然,对于法向量大小为零的圆锥尖端,这是不可能的。但它适用于所有其他方面。就这样

    有一件重要的事情要记住,要么只能在片段着色器中规格化法线向量。当然,如果你试图在C++中对零大小的向量进行标准化,你会得到错误。因此,如果出于某种原因在进入片段着色器之前需要进行规范化,请确保排除大小为零的法向量(即圆锥体的尖端),否则会出现错误

    这就产生了