如果将圆柱体分割为8面棱镜,并根据其位置(“平滑阴影”)计算顶点法线,则效果会很好。

如果将圆锥分割为8边的金字塔,并根据其位置计算法线,则会卡在圆锥的尖端(严格来说是圆锥的顶点,但我们称其为尖端以避免与网格顶点混淆) 。

对于每个三角形面,您都希望沿两个边缘匹配法线。但是,由于只能在三角形的每个顶点上指定一个法线,因此可以匹配一个边或另一个边,但不能同时匹配两个边。您可以通过选择两个边缘的平均值的尖端法线来妥协,但是现在没有一个边缘看起来不错。这是为每个尖端顶点选择平均法线的外观的详细信息。

在理想的情况下,GPU可以栅格化一个真正的四边形,而不仅仅是三角形。然后,我们可以为每个面指定一个退化的四边形,从而可以为每个三角形的两个相邻边指定不同的法线。但是我们要做的只是三角形...我们可以将圆锥切成多个“堆栈”,这样边缘的不连续性仅在圆锥的顶端可见,而不是在整个事物上可见,但是仍然会有一个小费!

有人对平滑低聚圆锥体有任何窍门吗?

最佳答案

我在用三角形组成的现代OpenGL(即着色器)中正在为锥度而苦苦挣扎,但后来我找到了一个出乎意料的简单解决方案!我想说,它比当前接受的答案所建议的要好得多,也更简单。

我有一个三角形阵列(显然每个三角形都有3个顶点),这些三角形构成了圆锥面。我不在乎底面(圆形底面),因为这确实很简单。在我的所有工作中,我使用以下简单的顶点结构:

  • position: vec3(通过在着色器中添加1.0f作为最后一个元素,自动将其转换为着色器中的vec4)
  • normal_vector: vec3(在着色器中以vec3的形式保存,因为它用于计算光方向的点积)
  • color: vec3(我未使用透明度)

  • 在我的顶点着色器中,我只变换顶点位置(乘以投影和模型 View 矩阵),还变换法线向量(乘以变换的模型 View 矩阵逆矩阵)。然后将变换后的位置,法线向量和未变换的颜色传递到片段着色器,在其中计算光方向和法线向量的点积,然后将此数字乘以颜色。

    让我从所做的事情开始并发现不满意的地方:

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

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

    但是后来我找到了解决方案:

    尝试#3 :我做了所有与尝试#2相同的操作,除了我在锥顶顶点分配了等于零向量vec3(0.0f,0.0f,0.0f)的法线向量。这是诀窍的关键! 然后将此零法线向量传递到片段着色器(即,在顶点着色器和片段着色器之间,它会自动与其他两个顶点的法线向量进行插值)。当然,然后需要对片段着色器(!)着色器中的向量进行归一化,因为它的大小不恒定为1(我需要点积)。因此,我对其进行了归一化-当然,对于法线矢量的大小为零的圆锥体的顶端,这是不可能的。但这适用于所有其他方面。就是这样。

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

    这会在除圆锥形尖端的所有点之外的所有点上使圆锥形产生平滑的阴影。但这一点并不重要(谁在乎一个像素...),也可以用一种特殊的方式来处理。另一个优点是,您甚至可以使用非常简单的着色器。唯一的变化是在片段着色器中而不是在顶点着色器中甚至之前对法线向量进行归一化。

    opengl - 低多边形圆锥体-尖端的平滑阴影-LMLPHP

    09-11 18:55