glNormal opengl - 方形示例

Ins*_*ath 1 opengl

我很难弄清楚如何计算正常,我想我有一些误解,所以我想举一个简单几何的例子,并找出正常情况,在这种情况下它应该更清楚如何做到这一点更难的几何.

    glBegin(GL_QUADS);
       glVertex3f(1,1,-1);
       glVertex3f(1,1,1);
       glVertex3f(-1,1,1);
       glVertex3f(-1,1,-1);
    glEnd();
Run Code Online (Sandbox Code Playgroud)

在每个顶点,我知道我需要放入一个正常的值(我想点亮它)所以这代表一个正面方形(2 x 2).那么在每个顶点之前我都会有(0,1.0,0)的法线?

Val*_*tin 13

当您需要计算四边形法线时,您需要计算四边形4个顶点的叉积.

A = (1, 1, -1)
B = (1, 1, 1)
C = (-1, 1, 1)
D = (-1, 1, -1)
Run Code Online (Sandbox Code Playgroud)

这就是你的四边形顶点的布局方式.我之所以添加这个,是因为你计算下面顶点的顺序很重要!

A----B
|    |
|    |
D----C
Run Code Online (Sandbox Code Playgroud)

所以现在当你想要计算法线时,你只需要做.

normal = (C - A) x (D - B)
Run Code Online (Sandbox Code Playgroud)

其中x表示交叉产品.

跨产品

如果您不知道跨产品是什么或如何计算它,那么我将在这里向您展示如何计算它.

V1 = (C - A)
V2 = (D - B)
Run Code Online (Sandbox Code Playgroud)

然后我们通过执行以下操作来计算交叉乘积.

normal.x = V1.y * V2.z - V1.z * V2.y
normal.y = V2.x * V1.z - V2.z * V1.x
normal.z = V1.x * V2.y - V1.y * V2.x
Run Code Online (Sandbox Code Playgroud)

上述3行相当于写作.

normal = V1 x V2
Run Code Online (Sandbox Code Playgroud)

现在我们计算了交叉积,在这种情况下是3D矢量.

额外

如果你不知道什么一个跨产品的,想了解更多关于它,那么你可以阅读更多关于它在这两个环节.

编辑

我做了十字架产品,它是正常=(0,8,0),如果我将它标准化我得到(0,1,0)

只是为了澄清一些事情,我们需要规范化法线的原因是因为我们正在计算它们x, y, z,之间的正态分布0 <-> 1

如果要标准化矢量,可以执行以下操作.

length = sqrt(x * x + y * y + z * z)

if (length > 0) {
    x /= length
    y /= length
    z /= length
}
Run Code Online (Sandbox Code Playgroud)

此外,如果要检查是否需要对矢量进行标准化,可以执行以下操作.

if ((x * x + y * y + z * z) != 1) {
    // NORMALIZE THE VECTOR
}
Run Code Online (Sandbox Code Playgroud)

现在这意味着我只需要在顶点上放置一次,或者我需要为四边形中的每个顶点提及它.

第一道路

glBegin(GL_QUADS);
    glNormal3f(0, 1, 0);
    glVertex3f(1, 1, -1);
    glVertex3f(1, 1, 1);
    glVertex3f(-1, 1, 1);
    glVertex3f(-1, 1, -1);
glEnd();
Run Code Online (Sandbox Code Playgroud)

第二种方式

glBegin(GL_QUADS);
    glNormal3f(0, 1, 0);
    glVertex3f(1, 1, -1);
    glNormal3f(0, 1, 0);
    glVertex3f(1, 1, 1);
    glNormal3f(0, 1, 0);
    glVertex3f(-1, 1, 1);
    glNormal3f(0, 1, 0);
    glVertex3f(-1, 1, -1);
glEnd();
Run Code Online (Sandbox Code Playgroud)

如果你以第一种或第二种方式做到这一点并不重要.只要你的四边形是平的,所以如果它是完全平坦的,你可以做第一种或第二种方式.

虽然如果你的四边形不是完全平坦的,那么你需要做第二种方式,因为四边形的每个顶点将/可能具有不同的法线.

许多资源表示你需要计算每个顶点的法线.

这是事实,虽然如上所述,如果你计算一个完全平坦的四边形的法线,那么每个顶点的法线将是相同的,因此你可以通过简单地仅计算法线一次来节省一些计算/时间/ CPU尽可能长时间地将它用于每个顶点.