繁体   English   中英

自动计算GLKit / OpenGL-ES中的法线

[英]Automatically calculate normals in GLKit/OpenGL-ES

我基于Apple的示例代码在OpenGL-ES中制作了一些相当基本的形状。 他们使用了一个点数组,在第一个数组中有一个索引数组,每组三个索引创建一个多边形。 这一切都很棒,我可以制作出我想要的形状。 为了正确地遮蔽形状,我相信我需要计算每个多边形上每个顶点的法线。 起初形状是立方形的,所以很容易,但现在我正在制作(略微)更高级的形状,我想自动创建这些法线。 如果我得到一个多边形的两条边的向量(这里所有多边形都是三角形)并且对它上面的每个顶点使用它们的叉积,这似乎很容易。 之后,我使用如下代码绘制形状。

glEnableVertexAttribArray(GLKVertexAttribPosition);
glVertexAttribPointer(GLKVertexAttribPosition, 3, GL_FLOAT, GL_FALSE, 0, triangleVertices);

glEnableVertexAttribArray(GLKVertexAttribColor);
glVertexAttribPointer(GLKVertexAttribColor, 4, GL_FLOAT, GL_FALSE, 0, triangleColours);

glEnableVertexAttribArray(GLKVertexAttribNormal);
glVertexAttribPointer(GLKVertexAttribNormal, 3, GL_FLOAT, GL_FALSE, 0, triangleNormals);

glDrawArrays(GL_TRIANGLES, 0, 48);

glDisableVertexAttribArray(GLKVertexAttribPosition);
glDisableVertexAttribArray(GLKVertexAttribColor);
glDisableVertexAttribArray(GLKVertexAttribNormal);

我无法理解的是为什么我必须手动执行此操作。 我确信有些情况下你需要的东西不仅仅是垂直于表面的矢量,但我也确定这是迄今为止最流行的用例,所以不应该有更简单的方法吗? 我错过了明显的东西吗? glCalculateNormals()会很棒。

//这里是一个答案传递GLKVector3 [],你希望用法线填充,另一个用顶点(每三个被分组成多边形),然后是顶点的计数。

- (void) calculateSurfaceNormals: (GLKVector3 *) normals forVertices: (GLKVector3 *)incomingVertices count:(int) numOfVertices
{

    for(int i = 0; i < numOfVertices; i+=3)
    {
        GLKVector3 vector1 = GLKVector3Subtract(incomingVertices[i+1],incomingVertices[i]);
        GLKVector3 vector2 = GLKVector3Subtract(incomingVertices[i+2],incomingVertices[i]);        
        GLKVector3 normal = GLKVector3Normalize(GLKVector3CrossProduct(vector1, vector2));
        normals[i] = normal;
        normals[i+1] = normal;
        normals[i+2] = normal;
    }
}

答案是: OpenGL既不是场景管理库也不是几何库,而只是一个绘制API ,可以将漂亮的图片绘制到屏幕上。 对于照明,它需要法线,你给它正常。 就这样。 如果这可以由用户完成并且与实际绘图无关,为什么还要计算法线?

通常,您不会在运行时计算它们,而是从文件中加载它们。 并且有许多方法可以计算法线。 你想要每面法线还是每顶点法线? 您是否需要任何特定的硬边或任何特定的光滑补丁? 如果你想平均面法线以获得顶点法线,你想如何平均这些?

随着着色器的出现以及在较新的OpenGL版本中删除内置的普通属性和光照计算,无论如何,整个问题都变得过时,因为您可以按照您想要的任何方式进行照明,并且不再需要传统法线。

顺便说一句,听起来就像你正在使用每面法线一样,这意味着面部的每个顶点都具有相同的法线。 这会创建一个具有硬边的非常刻面的模型,并且与索引一起工作也不能很好。 如果你想要一个平滑的模型(我不知道,也许你真的想要一个刻面的外观),你应该平均每个顶点的相邻面的面法线来计算每顶点法线。 这实际上是更常见的用例,而不是每个正常情况。

所以你可以做这样的伪代码:

for each vertex normal:
    intialize to zero vector

for each face:
    compute face normal using cross product
    add face normal to each vertex normal of this face

for each vertex normal:
    normalize

生成平滑的每顶点法线。 即使在实际代码中,这也会产生10到20行代码,这并不是很复杂。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM